Skip to content

Commit

Permalink
Merge pull request #1588 from MikeRaffa/main
Browse files Browse the repository at this point in the history
Issue #973: Differentiate multiple USB programmers of the same VID/PI…
  • Loading branch information
stefanrueger authored Dec 18, 2023
2 parents 2bd6b56 + 5dbbb4e commit 79f7035
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 11 deletions.
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) {

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

0 comments on commit 79f7035

Please sign in to comment.