From d8b37fe189d5cacf9bac8162d25c58c1a6890a6c Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Wed, 26 Jan 2022 22:02:24 +0100 Subject: [PATCH] Wrap libusb_device Introduce a structure to wrap a libusb_device and expose its descriptor data read during discovery. PR #2974 --- app/src/scrcpy.c | 13 +++++++++---- app/src/usb/usb.c | 47 +++++++++++++++++++++++++++++++++++------------ app/src/usb/usb.h | 17 +++++++++++++++-- 3 files changed, 59 insertions(+), 18 deletions(-) diff --git a/app/src/scrcpy.c b/app/src/scrcpy.c index 9039eede..7d58b0f1 100644 --- a/app/src/scrcpy.c +++ b/app/src/scrcpy.c @@ -432,16 +432,21 @@ scrcpy(struct scrcpy_options *options) { } assert(serial); - libusb_device *device = sc_usb_find_device(&s->usb, serial); - if (!device) { + struct sc_usb_device usb_device; + ok = sc_usb_find_device(&s->usb, serial, &usb_device); + if (!ok) { LOGE("Could not find USB device %s", serial); sc_usb_destroy(&s->usb); sc_acksync_destroy(&s->acksync); goto aoa_hid_end; } - ok = sc_usb_connect(&s->usb, device); - libusb_unref_device(device); + LOGI("USB device: %s (%04" PRIx16 ":%04" PRIx16 ") %s %s", + usb_device.serial, usb_device.vid, usb_device.pid, + usb_device.manufacturer, usb_device.product); + + ok = sc_usb_connect(&s->usb, usb_device.device); + sc_usb_device_destroy(&usb_device); if (!ok) { LOGE("Failed to connect to USB device %s", serial); sc_usb_destroy(&s->usb); diff --git a/app/src/usb/usb.c b/app/src/usb/usb.c index 459aefc0..9d5f35be 100644 --- a/app/src/usb/usb.c +++ b/app/src/usb/usb.c @@ -30,7 +30,8 @@ read_string(libusb_device_handle *handle, uint8_t desc_index) { } static bool -accept_device(libusb_device *device, const char *serial) { +accept_device(libusb_device *device, const char *serial, + struct sc_usb_device *out) { // Do not log any USB error in this function, it is expected that many USB // devices available on the computer have permission restrictions @@ -47,39 +48,61 @@ accept_device(libusb_device *device, const char *serial) { } char *device_serial = read_string(handle, desc.iSerialNumber); - libusb_close(handle); if (!device_serial) { + libusb_close(handle); return false; } bool matches = !strcmp(serial, device_serial); - free(device_serial); - return matches; + if (!matches) { + free(device_serial); + libusb_close(handle); + return false; + } + + out->device = libusb_ref_device(device); + out->serial = device_serial; + out->vid = desc.idVendor; + out->pid = desc.idProduct; + out->manufacturer = read_string(handle, desc.iManufacturer); + out->product = read_string(handle, desc.iProduct); + + libusb_close(handle); + + return true; } -libusb_device * -sc_usb_find_device(struct sc_usb *usb, const char *serial) { +void +sc_usb_device_destroy(struct sc_usb_device *usb_device) { + libusb_unref_device(usb_device->device); + free(usb_device->serial); + free(usb_device->manufacturer); + free(usb_device->product); +} + +bool +sc_usb_find_device(struct sc_usb *usb, const char *serial, + struct sc_usb_device *out) { assert(serial); libusb_device **list; - libusb_device *result = NULL; ssize_t count = libusb_get_device_list(usb->context, &list); if (count < 0) { log_libusb_error((enum libusb_error) count); - return NULL; + return false; } for (size_t i = 0; i < (size_t) count; ++i) { libusb_device *device = list[i]; - if (accept_device(device, serial)) { - result = libusb_ref_device(device); - break; + if (accept_device(device, serial, out)) { + libusb_free_device_list(list, 1); + return true; } } libusb_free_device_list(list, 1); - return result; + return false; } static libusb_device_handle * diff --git a/app/src/usb/usb.h b/app/src/usb/usb.h index 0ab7ce90..ea6e5514 100644 --- a/app/src/usb/usb.h +++ b/app/src/usb/usb.h @@ -11,14 +11,27 @@ struct sc_usb { libusb_device_handle *handle; }; +struct sc_usb_device { + libusb_device *device; + char *serial; + char *manufacturer; + char *product; + uint16_t vid; + uint16_t pid; +}; + +void +sc_usb_device_destroy(struct sc_usb_device *usb_device); + bool sc_usb_init(struct sc_usb *usb); void sc_usb_destroy(struct sc_usb *usb); -libusb_device * -sc_usb_find_device(struct sc_usb *usb, const char *serial); +bool +sc_usb_find_device(struct sc_usb *usb, const char *serial, + struct sc_usb_device *out); bool sc_usb_connect(struct sc_usb *usb, libusb_device *device);