Use vector for listing USB devices

This avoids the hardcoded maximum number of USB devices detected (16).

Refs #3029 <https://github.com/Genymobile/scrcpy/pull/3029>
PR #3035 <https://github.com/Genymobile/scrcpy/pull/3035>
This commit is contained in:
Romain Vimont 2022-02-18 19:40:05 +01:00
parent c070723bc8
commit 1790e88278

View file

@ -3,6 +3,9 @@
#include <assert.h> #include <assert.h>
#include "util/log.h" #include "util/log.h"
#include "util/vector.h"
struct sc_vec_usb_devices SC_VECTOR(struct sc_usb_device);
static char * static char *
read_string(libusb_device_handle *handle, uint8_t desc_index) { read_string(libusb_device_handle *handle, uint8_t desc_index) {
@ -85,33 +88,39 @@ sc_usb_device_move(struct sc_usb_device *dst, struct sc_usb_device *src) {
} }
void void
sc_usb_devices_destroy_all(struct sc_usb_device *usb_devices, size_t count) { sc_usb_devices_destroy(struct sc_vec_usb_devices *usb_devices) {
for (size_t i = 0; i < count; ++i) { for (size_t i = 0; i < usb_devices->size; ++i) {
sc_usb_device_destroy(&usb_devices[i]); sc_usb_device_destroy(&usb_devices->data[i]);
} }
sc_vector_destroy(usb_devices);
} }
static ssize_t static bool
sc_usb_list_devices(struct sc_usb *usb, struct sc_usb_device *devices, sc_usb_list_devices(struct sc_usb *usb, struct sc_vec_usb_devices *out_vec) {
size_t len) {
libusb_device **list; libusb_device **list;
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) {
LOGE("List USB devices: libusb error: %s", libusb_strerror(count)); LOGE("List USB devices: libusb error: %s", libusb_strerror(count));
return -1; return false;
} }
size_t idx = 0; for (size_t i = 0; i < (size_t) count; ++i) {
for (size_t i = 0; i < (size_t) count && idx < len; ++i) {
libusb_device *device = list[i]; libusb_device *device = list[i];
if (sc_usb_read_device(device, &devices[idx])) { struct sc_usb_device usb_device;
++idx; if (sc_usb_read_device(device, &usb_device)) {
bool ok = sc_vector_push(out_vec, usb_device);
if (!ok) {
LOG_OOM();
LOGE("Could not push usb_device to vector");
sc_usb_device_destroy(&usb_device);
// continue anyway
}
} }
} }
libusb_free_device_list(list, 1); libusb_free_device_list(list, 1);
return idx; return true;
} }
static bool static bool
@ -157,29 +166,28 @@ sc_usb_devices_log(enum sc_log_level level, struct sc_usb_device *devices,
bool bool
sc_usb_select_device(struct sc_usb *usb, const char *serial, sc_usb_select_device(struct sc_usb *usb, const char *serial,
struct sc_usb_device *out_device) { struct sc_usb_device *out_device) {
struct sc_usb_device usb_devices[16]; struct sc_vec_usb_devices vec = SC_VECTOR_INITIALIZER;
ssize_t count = bool ok = sc_usb_list_devices(usb, &vec);
sc_usb_list_devices(usb, usb_devices, ARRAY_LEN(usb_devices)); if (!ok) {
if (count == -1) {
LOGE("Could not list USB devices"); LOGE("Could not list USB devices");
return false; return false;
} }
if (count == 0) { if (vec.size == 0) {
LOGE("Could not find any USB device"); LOGE("Could not find any USB device");
return false; return false;
} }
size_t sel_idx; // index of the single matching device if sel_count == 1 size_t sel_idx; // index of the single matching device if sel_count == 1
size_t sel_count = size_t sel_count =
sc_usb_devices_select(usb_devices, count, serial, &sel_idx); sc_usb_devices_select(vec.data, vec.size, serial, &sel_idx);
if (sel_count == 0) { if (sel_count == 0) {
// if count > 0 && sel_count == 0, then necessarily a serial is provided // if count > 0 && sel_count == 0, then necessarily a serial is provided
assert(serial); assert(serial);
LOGE("Could not find USB device %s", serial); LOGE("Could not find USB device %s", serial);
sc_usb_devices_log(SC_LOG_LEVEL_ERROR, usb_devices, count); sc_usb_devices_log(SC_LOG_LEVEL_ERROR, vec.data, vec.size);
sc_usb_devices_destroy_all(usb_devices, count); sc_usb_devices_destroy(&vec);
return false; return false;
} }
@ -190,21 +198,21 @@ sc_usb_select_device(struct sc_usb *usb, const char *serial,
} else { } else {
LOGE("Multiple (%" SC_PRIsizet ") USB devices:", sel_count); LOGE("Multiple (%" SC_PRIsizet ") USB devices:", sel_count);
} }
sc_usb_devices_log(SC_LOG_LEVEL_ERROR, usb_devices, count); sc_usb_devices_log(SC_LOG_LEVEL_ERROR, vec.data, vec.size);
LOGE("Select a device via -s (--serial)"); LOGE("Select a device via -s (--serial)");
sc_usb_devices_destroy_all(usb_devices, count); sc_usb_devices_destroy(&vec);
return false; return false;
} }
assert(sel_count == 1); // sel_idx is valid only if sel_count == 1 assert(sel_count == 1); // sel_idx is valid only if sel_count == 1
struct sc_usb_device *device = &usb_devices[sel_idx]; struct sc_usb_device *device = &vec.data[sel_idx];
LOGD("USB device found:"); LOGD("USB device found:");
sc_usb_devices_log(SC_LOG_LEVEL_DEBUG, usb_devices, count); sc_usb_devices_log(SC_LOG_LEVEL_DEBUG, vec.data, vec.size);
// Move device into out_device (do not destroy device) // Move device into out_device (do not destroy device)
sc_usb_device_move(out_device, device); sc_usb_device_move(out_device, device);
sc_usb_devices_destroy_all(usb_devices, count); sc_usb_devices_destroy(&vec);
return true; return true;
} }