summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorMary Ruthven <mruthven@chromium.org>2019-05-07 15:43:39 -0700
committerchrome-bot <chrome-bot@chromium.org>2019-05-12 19:27:40 -0700
commitd68548eebbe93a6c3009cf20ddf0da7b27fe2012 (patch)
tree9a6effed3c59ea43462322fa705f95b990b6480a /util
parente02b08ceca36300a602c50b2b3cc81f3a5385978 (diff)
downloadchrome-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.c2
-rw-r--r--util/usb_if.c73
-rw-r--r--util/usb_if.h12
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