diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index f3f34834..bd11cd4c 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -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 @@ -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. diff --git a/src/usbasp.c b/src/usbasp.c index d9bca89e..f5c301c8 100644 --- a/src/usbasp.c +++ b/src/usbasp.c @@ -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); @@ -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 @@ -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; @@ -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); @@ -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; @@ -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); @@ -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; @@ -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;