diff options
author | Mary Ruthven <mruthven@chromium.org> | 2019-05-07 15:43:39 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2019-05-12 19:27:40 -0700 |
commit | d68548eebbe93a6c3009cf20ddf0da7b27fe2012 (patch) | |
tree | 9a6effed3c59ea43462322fa705f95b990b6480a /util | |
parent | e02b08ceca36300a602c50b2b3cc81f3a5385978 (diff) | |
download | chrome-ec-d68548eebbe93a6c3009cf20ddf0da7b27fe2012.tar.gz |
usb_if: use the device with the matching serial number
There might be multiple devices with the same VID:PID connected to the
host. Use the serial number to find the correct device if it is given.
BUG=none
BRANCH=none
TEST=none
Change-Id: I96f31e8e7ceb0dd2c3c643771b38752da88a2a9e
Signed-off-by: Mary Ruthven <mruthven@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1600500
Reviewed-by: Matthew Blecker <matthewb@chromium.org>
Diffstat (limited to 'util')
-rw-r--r-- | util/iteflash.c | 2 | ||||
-rw-r--r-- | util/usb_if.c | 73 | ||||
-rw-r--r-- | util/usb_if.h | 12 |
3 files changed, 74 insertions, 13 deletions
diff --git a/util/iteflash.c b/util/iteflash.c index 480756e71e..f0d110f19e 100644 --- a/util/iteflash.c +++ b/util/iteflash.c @@ -809,7 +809,7 @@ static int connect_to_ccd_i2c_bridge(struct common_hnd *chnd) { int rv; - rv = usb_findit(chnd->conf.usb_vid, chnd->conf.usb_pid, + rv = usb_findit(NULL, chnd->conf.usb_vid, chnd->conf.usb_pid, CR50_I2C_SUBCLASS, CR50_I2C_PROTOCOL, &chnd->uep); if (rv) { diff --git a/util/usb_if.c b/util/usb_if.c index 1f0adfecda..f8aa6bfd7e 100644 --- a/util/usb_if.c +++ b/util/usb_if.c @@ -66,26 +66,85 @@ out: return iface_num; } -int usb_findit(uint16_t vid, uint16_t pid, uint16_t subclass, - uint16_t protocol, struct usb_endpoint *uep) +static libusb_device_handle *check_device(libusb_device *dev, + uint16_t vid, uint16_t pid, const char *serial) { - int iface_num, r; + struct libusb_device_descriptor desc; + libusb_device_handle *handle = NULL; + char sn[256]; + size_t sn_size = 0; + + if (libusb_get_device_descriptor(dev, &desc) < 0) + return NULL; + + if (libusb_open(dev, &handle) != LIBUSB_SUCCESS) + return NULL; + + if (desc.iSerialNumber && serial) { + sn_size = libusb_get_string_descriptor_ascii(handle, + desc.iSerialNumber, (unsigned char *)sn, + sizeof(sn)); + } + /* + * If the VID, PID, and serial number don't match, then it's not the + * correct device. Close the handle and return NULL. + */ + if ((vid && vid != desc.idVendor) || + (pid && pid != desc.idProduct) || + (serial && ((sn_size != strlen(serial)) || + memcmp(sn, serial, sn_size)))) { + libusb_close(handle); + return NULL; + } + return handle; +} + +int usb_findit(const char *serial, uint16_t vid, uint16_t pid, + uint16_t subclass, uint16_t protocol, struct usb_endpoint *uep) +{ + int iface_num, r, i; + libusb_device **devs; + libusb_device_handle *devh = NULL; + ssize_t count; memset(uep, 0, sizeof(*uep)); + /* Must supply either serial or vendor and product ids. */ + if (!serial && !(vid && pid)) + goto terminate_usb_findit; + r = libusb_init(NULL); if (r < 0) { USB_ERROR("libusb_init", r); goto terminate_usb_findit; } - printf("open_device %04x:%04x\n", vid, pid); - /* NOTE: This doesn't handle multiple matches! */ - uep->devh = libusb_open_device_with_vid_pid(NULL, vid, pid); - if (!uep->devh) { + printf("finding_device "); + if (vid) + printf("%04x:%04x ", vid, pid); + if (serial) + printf("%s", serial); + printf("\n"); + + count = libusb_get_device_list(NULL, &devs); + if (count < 0) + goto terminate_usb_findit; + + for (i = 0; i < count; i++) { + devh = check_device(devs[i], vid, pid, serial); + if (devh) { + printf("Found device.\n"); + break; + } + } + + libusb_free_device_list(devs, 1); + + if (!devh) { fprintf(stderr, "Can't find device\n"); goto terminate_usb_findit; } + uep->devh = devh; iface_num = find_interface(subclass, protocol, uep); if (iface_num < 0) { diff --git a/util/usb_if.h b/util/usb_if.h index 220564d2a3..8cc1088c6e 100644 --- a/util/usb_if.h +++ b/util/usb_if.h @@ -17,14 +17,16 @@ struct usb_endpoint { }; /* - * Find the requested USB endpoint, as determined by vid, pid, subclass and - * protocol parameters. If found, fill up the uep structure. If succeeded, - * usb_shut_down() must be invoked before program exits. + * Find the requested USB endpoint. This finds the device using the device + * serial number, vendor id, and product id. The subclass and protocol are used + * to find the correct endpoint. If a matching endpoint is found, fill up the + * uep structure. If succeeded, usb_shut_down() must be invoked before program + * exits. * * Return 0 on success, -1 on failure. */ -int usb_findit(uint16_t vid, uint16_t pid, uint16_t subclass, - uint16_t protocol, struct usb_endpoint *uep); +int usb_findit(const char *serialno, uint16_t vid, uint16_t pid, + uint16_t subclass, uint16_t protocol, struct usb_endpoint *uep); /* * Actual USB transfer function, the 'allow_less' flag indicates that the |