Wrap libusb_device

Introduce a structure to wrap a libusb_device and expose its descriptor
data read during discovery.

PR #2974 <https://github.com/Genymobile/scrcpy/pull/2974>
This commit is contained in:
Romain Vimont 2022-01-26 22:02:24 +01:00
parent 0ee9e2ff51
commit d8b37fe189
3 changed files with 59 additions and 18 deletions

View file

@ -432,16 +432,21 @@ scrcpy(struct scrcpy_options *options) {
} }
assert(serial); assert(serial);
libusb_device *device = sc_usb_find_device(&s->usb, serial); struct sc_usb_device usb_device;
if (!device) { ok = sc_usb_find_device(&s->usb, serial, &usb_device);
if (!ok) {
LOGE("Could not find USB device %s", serial); LOGE("Could not find USB device %s", serial);
sc_usb_destroy(&s->usb); sc_usb_destroy(&s->usb);
sc_acksync_destroy(&s->acksync); sc_acksync_destroy(&s->acksync);
goto aoa_hid_end; goto aoa_hid_end;
} }
ok = sc_usb_connect(&s->usb, device); LOGI("USB device: %s (%04" PRIx16 ":%04" PRIx16 ") %s %s",
libusb_unref_device(device); 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) { if (!ok) {
LOGE("Failed to connect to USB device %s", serial); LOGE("Failed to connect to USB device %s", serial);
sc_usb_destroy(&s->usb); sc_usb_destroy(&s->usb);

View file

@ -30,7 +30,8 @@ read_string(libusb_device_handle *handle, uint8_t desc_index) {
} }
static bool 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 // Do not log any USB error in this function, it is expected that many USB
// devices available on the computer have permission restrictions // 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); char *device_serial = read_string(handle, desc.iSerialNumber);
libusb_close(handle);
if (!device_serial) { if (!device_serial) {
libusb_close(handle);
return false; return false;
} }
bool matches = !strcmp(serial, device_serial); bool matches = !strcmp(serial, device_serial);
if (!matches) {
free(device_serial); free(device_serial);
return matches; libusb_close(handle);
return false;
} }
libusb_device * out->device = libusb_ref_device(device);
sc_usb_find_device(struct sc_usb *usb, const char *serial) { 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;
}
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); assert(serial);
libusb_device **list; libusb_device **list;
libusb_device *result = NULL;
ssize_t count = libusb_get_device_list(usb->context, &list); ssize_t count = libusb_get_device_list(usb->context, &list);
if (count < 0) { if (count < 0) {
log_libusb_error((enum libusb_error) count); log_libusb_error((enum libusb_error) count);
return NULL; return false;
} }
for (size_t i = 0; i < (size_t) count; ++i) { for (size_t i = 0; i < (size_t) count; ++i) {
libusb_device *device = list[i]; libusb_device *device = list[i];
if (accept_device(device, serial)) { if (accept_device(device, serial, out)) {
result = libusb_ref_device(device); libusb_free_device_list(list, 1);
break; return true;
} }
} }
libusb_free_device_list(list, 1); libusb_free_device_list(list, 1);
return result; return false;
} }
static libusb_device_handle * static libusb_device_handle *

View file

@ -11,14 +11,27 @@ struct sc_usb {
libusb_device_handle *handle; 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 bool
sc_usb_init(struct sc_usb *usb); sc_usb_init(struct sc_usb *usb);
void void
sc_usb_destroy(struct sc_usb *usb); sc_usb_destroy(struct sc_usb *usb);
libusb_device * bool
sc_usb_find_device(struct sc_usb *usb, const char *serial); sc_usb_find_device(struct sc_usb *usb, const char *serial,
struct sc_usb_device *out);
bool bool
sc_usb_connect(struct sc_usb *usb, libusb_device *device); sc_usb_connect(struct sc_usb *usb, libusb_device *device);