Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #973: Differentiate multiple USB programmers of the same VID/PI… #1588

Merged
merged 4 commits into from
Dec 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions src/doc/avrdude.texi
Original file line number Diff line number Diff line change
Expand Up @@ -739,8 +739,11 @@ and Mac OS but not on Windows. For more information about AVR-Doper see
For the USBtinyISP, which is a simplistic device not implementing
serial numbers, multiple devices can be distinguished by their
location in the USB hierarchy.
See the respective
@xref{Troubleshooting} entry for examples.
See the respective @ref{Troubleshooting} entry for examples.

For USBasp, multiple devices can be distinguished by either USB connection
or serial number.
See the respective @ref{Troubleshooting} entry for examples.

For the XBee programmer the target MCU is to be programmed wirelessly
over a ZigBee mesh using the XBeeBoot bootloader. The ZigBee 64-bit
Expand Down Expand Up @@ -4233,6 +4236,14 @@ avrdude -c usbtiny -p atmega8 \
-P usb:bus-0:\\.\libusb0-0001--0x1781-0x0c9f (Windows)
@end example

For USBasp, the same format for @var{-P usb} can be used to match usb bus/device. Alternatively,
device serial number can be specified as follows (for serial number '1234').

@example
avrdude -c USBasp -p atmega8 -P usb:1234
@end example


@item
Problem: I cannot do @dots{} when the target is in debugWire mode.

Expand Down
59 changes: 50 additions & 9 deletions src/usbasp.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,9 @@ static int usbasp_transmit(const PROGRAMMER *pgm, unsigned char receive,
unsigned char functionid, const unsigned char *send,
unsigned char *buffer, int buffersize);
#ifdef USE_LIBUSB_1_0
static int usbOpenDevice(libusb_device_handle **device, int vendor, const char *vendorName, int product, const char *productName);
static int usbOpenDevice(libusb_device_handle **device, int vendor, const char *vendorName, int product, const char *productName, const char *port);
#else
static int usbOpenDevice(usb_dev_handle **device, int vendor, const char *vendorName, int product, const char *productName);
static int usbOpenDevice(usb_dev_handle **device, int vendor, const char *vendorName, int product, const char *productName, const char *port);
#endif
// interface - prog.
static int usbasp_open(PROGRAMMER *pgm, const char *port);
Expand Down Expand Up @@ -399,6 +399,26 @@ static int usbasp_transmit(const PROGRAMMER *pgm,
return nbytes;
}

static int check_for_port_argument_match(const char *port, char *bus, char *device, char *serial_num) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function returns a 1 if the port arguments are not matched and 0 if they do. So I suggest renaming the function to port_argument_not_matched().


pmsg_notice("usbOpenDevice(): found USBasp, bus:device: %s:%s, serial_number: %s\n", bus, device, serial_num);
const size_t usb_len = strlen("usb");
if(str_starts(port, "usb") && ':' == port[usb_len]) {
port += usb_len + 1;
char *colon_pointer = strchr(port, ':');
if (colon_pointer) {
// Value contains ':' character. Compare with bus/device.
if (strncmp(port, bus, colon_pointer - port))
return 0;
port = colon_pointer + 1;
return str_eq(port, device);
}
// serial number case
return *port && str_ends(serial_num, port);
}
// Invalid -P option.
return 0;
}

/*
* Try to open USB device with given VID, PID, vendor and product name
Expand All @@ -407,8 +427,8 @@ static int usbasp_transmit(const PROGRAMMER *pgm,
* shared VID/PID
*/
#ifdef USE_LIBUSB_1_0
static int usbOpenDevice(libusb_device_handle **device, int vendor,
const char *vendorName, int product, const char *productName)
static int usbOpenDevice(libusb_device_handle **device, int vendor, const char *vendorName,
int product, const char *productName, const char *port)
{
libusb_device_handle *handle = NULL;
int errorCode = USB_ERROR_NOTFOUND;
Expand Down Expand Up @@ -463,6 +483,18 @@ static int usbOpenDevice(libusb_device_handle **device, int vendor,
if((productName != NULL) && (productName[0] != 0) && !str_eq(string, productName))
errorCode = USB_ERROR_NOTFOUND;
}
if (errorCode == 0) {
if(!str_eq(port, "usb")) {
// -P option given
libusb_get_string_descriptor_ascii(handle, descriptor.iSerialNumber, (unsigned char*)string, sizeof(string));
char bus_num[21];
sprintf(bus_num, "%d", libusb_get_bus_number(dev));
char dev_addr[21];
sprintf(dev_addr, "%d", libusb_get_device_address(dev));
if (!check_for_port_argument_match(port, bus_num, dev_addr, string))
errorCode = USB_ERROR_NOTFOUND;
}
}
if (errorCode == 0)
break;
libusb_close(handle);
Expand All @@ -477,8 +509,8 @@ static int usbOpenDevice(libusb_device_handle **device, int vendor,
return errorCode;
}
#else
static int usbOpenDevice(usb_dev_handle **device, int vendor,
const char *vendorName, int product, const char *productName)
static int usbOpenDevice(usb_dev_handle **device, int vendor, const char *vendorName,
int product, const char *productName, const char *port)
{
struct usb_bus *bus;
struct usb_device *dev;
Expand Down Expand Up @@ -533,6 +565,15 @@ static int didUsbInit = 0;
if((productName != NULL) && (productName[0] != 0) && !str_eq(string, productName))
errorCode = USB_ERROR_NOTFOUND;
}
if (errorCode == 0) {
if(!str_eq(port, "usb")) {
// -P option given
usb_get_string_simple(handle, dev->descriptor.iSerialNumber,
string, sizeof(string));
if (!check_for_port_argument_match(port, bus->dirname, dev->filename, string))
errorCode = USB_ERROR_NOTFOUND;
}
}
if (errorCode == 0)
break;
usb_close(handle);
Expand Down Expand Up @@ -566,14 +607,14 @@ static int usbasp_open(PROGRAMMER *pgm, const char *port) {
pid = USBASP_SHARED_PID;
}
vid = pgm->usbvid? pgm->usbvid: USBASP_SHARED_VID;
if (usbOpenDevice(&PDATA(pgm)->usbhandle, vid, pgm->usbvendor, pid, pgm->usbproduct) != 0) {
if (usbOpenDevice(&PDATA(pgm)->usbhandle, vid, pgm->usbvendor, pid, pgm->usbproduct, port) != 0) {
/* try alternatives */
if(str_eq(pgmid, "usbasp")) {
/* for id usbasp autodetect some variants */
if(str_caseeq(port, "nibobee")) {
pmsg_error("using -C usbasp -P nibobee is deprecated, use -C nibobee instead\n");
if (usbOpenDevice(&PDATA(pgm)->usbhandle, USBASP_NIBOBEE_VID, "www.nicai-systems.com",
USBASP_NIBOBEE_PID, "NIBObee") != 0) {
USBASP_NIBOBEE_PID, "NIBObee", port) != 0) {
pmsg_error("cannot find USB device NIBObee with vid=0x%x pid=0x%x\n",
USBASP_NIBOBEE_VID, USBASP_NIBOBEE_PID);
return -1;
Expand All @@ -582,7 +623,7 @@ static int usbasp_open(PROGRAMMER *pgm, const char *port) {
}
/* check if device with old VID/PID is available */
if (usbOpenDevice(&PDATA(pgm)->usbhandle, USBASP_OLD_VID, "www.fischl.de",
USBASP_OLD_PID, "USBasp") == 0) {
USBASP_OLD_PID, "USBasp", port) == 0) {
/* found USBasp with old IDs */
pmsg_error("found USB device USBasp with old VID/PID; please update firmware of USBasp\n");
return 0;
Expand Down