diff --git a/device.h b/device.h index 2b11be2..0baea83 100644 --- a/device.h +++ b/device.h @@ -66,6 +66,7 @@ struct device_args { int vcc_mv; const char *path; const char *forced_chip_id; + const char *requested_serial; }; struct device_class { diff --git a/fet.c b/fet.c index 8845d39..730b2bb 100644 --- a/fet.c +++ b/fet.c @@ -1053,7 +1053,7 @@ static device_t fet_open_rf2500(const struct device_args *args) return NULL; } - trans = rf2500_open(args->path); + trans = rf2500_open(args->path, args->requested_serial); if (!trans) return NULL; @@ -1082,7 +1082,7 @@ static device_t fet_open_olimex(const struct device_args *args) if (args->flags & DEVICE_FLAG_TTY) trans = uif_open(args->path, UIF_TYPE_OLIMEX); else - trans = olimex_open(args->path); + trans = olimex_open(args->path, args->requested_serial); if (!trans) return NULL; diff --git a/main.c b/main.c index 2d259c3..7c05d1d 100644 --- a/main.c +++ b/main.c @@ -88,6 +88,8 @@ static void usage(const char *progname) " Connect via the given tty device, rather than USB.\n" " -U bus:dev\n" " Specify a particular USB device to connect to.\n" +" -s serial\n" +" Specify a particular device serial number to connect to.\n" " -j\n" " Use JTAG, rather than Spy-Bi-Wire (UIF devices only).\n" " -v voltage\n" @@ -178,7 +180,7 @@ static int parse_cmdline_args(int argc, char **argv, }; int want_usb = 0; - while ((opt = getopt_long(argc, argv, "d:jv:nU:q", + while ((opt = getopt_long(argc, argv, "d:jv:nU:s:q", longopts, NULL)) >= 0) switch (opt) { case 'q': @@ -208,6 +210,10 @@ static int parse_cmdline_args(int argc, char **argv, want_usb = 1; break; + case 's': + args->devarg.requested_serial = optarg; + break; + case 'L': exit(list_devices()); @@ -300,6 +306,7 @@ int main(int argc, char **argv) opdb_reset(); args.devarg.vcc_mv = 3000; + args.devarg.requested_serial = NULL; if (parse_cmdline_args(argc, argv, &args) < 0) return -1; diff --git a/mspdebug.man b/mspdebug.man index 8c01181..23e0e1b 100644 --- a/mspdebug.man +++ b/mspdebug.man @@ -46,6 +46,9 @@ section \fBDRIVERS\fR below for details. .IP "\-U \fIbus\fR:\fIdevice\fR" Specify a particular USB device to connect to. Without this option, the first device of the appropriate type is opened. +.IP "\-s \fIserial\fR" +Specify a particular USB device serial number to connect to. Use this +option to distinguish between multiple devices of the same type. .IP "\-n" Do not process the startup file (~/.mspdebug). .IP "\--long-password" diff --git a/olimex.c b/olimex.c index 4c61478..722ca67 100644 --- a/olimex.c +++ b/olimex.c @@ -221,7 +221,7 @@ static void usbtr_destroy(transport_t tr_base) free(tr); } -transport_t olimex_open(const char *devpath) +transport_t olimex_open(const char *devpath, const char *requested_serial) { struct olimex_transport *tr = malloc(sizeof(*tr)); struct usb_device *dev; @@ -243,9 +243,11 @@ transport_t olimex_open(const char *devpath) if (devpath) { dev = usbutil_find_by_loc(devpath); } else { - dev = usbutil_find_by_id(USB_FET_VENDOR, V1_PRODUCT); + dev = usbutil_find_by_id(USB_FET_VENDOR, V1_PRODUCT, + requested_serial); if (!dev) - dev = usbutil_find_by_id(USB_FET_VENDOR, V2_PRODUCT); + dev = usbutil_find_by_id(USB_FET_VENDOR, V2_PRODUCT, + requested_serial); } if (!dev) { diff --git a/olimex.h b/olimex.h index 38f883f..fe4060c 100644 --- a/olimex.h +++ b/olimex.h @@ -28,6 +28,6 @@ * * A particular USB device may be specified in bus:dev form. */ -transport_t olimex_open(const char *usb_device); +transport_t olimex_open(const char *usb_device, const char *requested_serial); #endif diff --git a/rf2500.c b/rf2500.c index 50762f0..21bd2f1 100644 --- a/rf2500.c +++ b/rf2500.c @@ -179,7 +179,7 @@ static void usbtr_destroy(transport_t tr_base) free(tr); } -transport_t rf2500_open(const char *devpath) +transport_t rf2500_open(const char *devpath, const char *requested_serial) { struct rf2500_transport *tr = malloc(sizeof(*tr)); struct usb_device *dev; @@ -201,7 +201,8 @@ transport_t rf2500_open(const char *devpath) if (devpath) dev = usbutil_find_by_loc(devpath); else - dev = usbutil_find_by_id(USB_FET_VENDOR, USB_FET_PRODUCT); + dev = usbutil_find_by_id(USB_FET_VENDOR, USB_FET_PRODUCT, + requested_serial); if (!dev) { free(tr); diff --git a/rf2500.h b/rf2500.h index e766624..a702102 100644 --- a/rf2500.h +++ b/rf2500.h @@ -27,6 +27,6 @@ * * A particular device may be specified in bus:dev form. */ -transport_t rf2500_open(const char *dev_path); +transport_t rf2500_open(const char *dev_path, const char *requested_serial); #endif diff --git a/usbutil.c b/usbutil.c index a0a514a..d03d72b 100644 --- a/usbutil.c +++ b/usbutil.c @@ -43,43 +43,78 @@ static const char *device_help(const struct usb_device *dev) return ""; } +static int read_serial(struct usb_device *dev, char *buf, int max_len) +{ + struct usb_dev_handle *dh = usb_open(dev); + + if (!dh) + return -1; + + if (usb_get_string_simple(dh, dev->descriptor.iSerialNumber, + buf, max_len) < 0) { + usb_close(dh); + return -1; + } + + usb_close(dh); + return 0; +} + void usbutil_list(void) { const struct usb_bus *bus; for (bus = usb_get_busses(); bus; bus = bus->next) { - const struct usb_device *dev; + struct usb_device *dev; int busnum = atoi(bus->dirname); printc("Devices on bus %03d:\n", busnum); for (dev = bus->devices; dev; dev = dev->next) { int devnum = atoi(dev->filename); + char serial[128]; - printc(" %03d:%03d %04x:%04x %s\n", + printc(" %03d:%03d %04x:%04x %s", busnum, devnum, dev->descriptor.idVendor, dev->descriptor.idProduct, device_help(dev)); + + if (!read_serial(dev, serial, sizeof(serial))) + printc(" [serial: %s]\n", serial); + else + printc("\n"); } } } -struct usb_device *usbutil_find_by_id(int vendor, int product) +struct usb_device *usbutil_find_by_id(int vendor, int product, const char *requested_serial) { struct usb_bus *bus; for (bus = usb_get_busses(); bus; bus = bus->next) { struct usb_device *dev; - for (dev = bus->devices; dev; dev = dev->next) + for (dev = bus->devices; dev; dev = dev->next) { if (dev->descriptor.idVendor == vendor && - dev->descriptor.idProduct == product) - return dev; + dev->descriptor.idProduct == product) { + char buf[128]; + + if (!requested_serial || + (!read_serial(dev, buf, sizeof(buf)) && + !strcasecmp(requested_serial, buf))) + return dev; + } + } } - printc_err("usbutil: unable to find a device matching " - "%04x:%04x\n", vendor, product); + if(requested_serial) + printc_err("usbutil: unable to find device matching " + "%04x:%04x with serial %s\n", vendor, product, + requested_serial); + else + printc_err("usbutil: unable to find a device matching " + "%04x:%04x\n", vendor, product); return NULL; } diff --git a/usbutil.h b/usbutil.h index 49960c1..3573ffc 100644 --- a/usbutil.h +++ b/usbutil.h @@ -25,7 +25,8 @@ void usbutil_list(void); /* Search for the first device matching the given Vendor:Product */ -struct usb_device *usbutil_find_by_id(int vendor, int product); +struct usb_device *usbutil_find_by_id(int vendor, int product, + const char *requested_serial); /* Search for a device using a bus:dev location string */ struct usb_device *usbutil_find_by_loc(const char *loc);