mirror of
https://github.com/Genymobile/scrcpy
synced 2024-11-11 01:10:32 +00:00
List and select USB devices separately
List all USB devices in a first step, then select the matching one(s). This allows to report a user-friendly log message containing the list of devices, with the matching one(s) highlighted. PR #3005 <https://github.com/Genymobile/scrcpy/pull/3005>
This commit is contained in:
parent
61969aeb80
commit
700503df6c
@ -25,8 +25,7 @@ read_string(libusb_device_handle *handle, uint8_t desc_index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
accept_device(libusb_device *device, const char *serial,
|
sc_usb_read_device(libusb_device *device, struct sc_usb_device *out) {
|
||||||
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
|
||||||
|
|
||||||
@ -48,22 +47,13 @@ accept_device(libusb_device *device, const char *serial,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serial) {
|
|
||||||
// Filter by serial
|
|
||||||
bool matches = !strcmp(serial, device_serial);
|
|
||||||
if (!matches) {
|
|
||||||
free(device_serial);
|
|
||||||
libusb_close(handle);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out->device = libusb_ref_device(device);
|
out->device = libusb_ref_device(device);
|
||||||
out->serial = device_serial;
|
out->serial = device_serial;
|
||||||
out->vid = desc.idVendor;
|
out->vid = desc.idVendor;
|
||||||
out->pid = desc.idProduct;
|
out->pid = desc.idProduct;
|
||||||
out->manufacturer = read_string(handle, desc.iManufacturer);
|
out->manufacturer = read_string(handle, desc.iManufacturer);
|
||||||
out->product = read_string(handle, desc.iProduct);
|
out->product = read_string(handle, desc.iProduct);
|
||||||
|
out->selected = false;
|
||||||
|
|
||||||
libusb_close(handle);
|
libusb_close(handle);
|
||||||
|
|
||||||
@ -97,8 +87,8 @@ sc_usb_devices_destroy_all(struct sc_usb_device *usb_devices, size_t count) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t
|
static ssize_t
|
||||||
sc_usb_find_devices(struct sc_usb *usb, const char *serial,
|
sc_usb_list_devices(struct sc_usb *usb, struct sc_usb_device *devices,
|
||||||
struct sc_usb_device *devices, size_t len) {
|
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) {
|
||||||
@ -110,7 +100,7 @@ sc_usb_find_devices(struct sc_usb *usb, const char *serial,
|
|||||||
for (size_t i = 0; i < (size_t) count && idx < len; ++i) {
|
for (size_t i = 0; i < (size_t) count && idx < len; ++i) {
|
||||||
libusb_device *device = list[i];
|
libusb_device *device = list[i];
|
||||||
|
|
||||||
if (accept_device(device, serial, &devices[idx])) {
|
if (sc_usb_read_device(device, &devices[idx])) {
|
||||||
++idx;
|
++idx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -119,46 +109,94 @@ sc_usb_find_devices(struct sc_usb *usb, const char *serial,
|
|||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
sc_usb_accept_device(const struct sc_usb_device *device, const char *serial) {
|
||||||
|
if (!serial) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !strcmp(serial, device->serial);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t
|
||||||
|
sc_usb_devices_select(struct sc_usb_device *devices, size_t len,
|
||||||
|
const char *serial, size_t *idx_out) {
|
||||||
|
size_t count = 0;
|
||||||
|
for (size_t i = 0; i < len; ++i) {
|
||||||
|
struct sc_usb_device *device = &devices[i];
|
||||||
|
device->selected = sc_usb_accept_device(device, serial);
|
||||||
|
if (device->selected) {
|
||||||
|
if (idx_out && !count) {
|
||||||
|
*idx_out = i;
|
||||||
|
}
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sc_usb_devices_log(enum sc_log_level level, struct sc_usb_device *devices,
|
||||||
|
size_t count) {
|
||||||
|
for (size_t i = 0; i < count; ++i) {
|
||||||
|
struct sc_usb_device *d = &devices[i];
|
||||||
|
const char *selection = d->selected ? "-->" : " ";
|
||||||
|
LOG(level, " %s %-18s (%04" PRIx16 ":%04" PRIx16 ") %s %s",
|
||||||
|
selection, d->serial, d->vid, d->pid, d->manufacturer, d->product);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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_usb_device usb_devices[16];
|
||||||
ssize_t count = sc_usb_find_devices(usb, serial, usb_devices,
|
ssize_t count =
|
||||||
ARRAY_LEN(usb_devices));
|
sc_usb_list_devices(usb, usb_devices, ARRAY_LEN(usb_devices));
|
||||||
if (count == -1) {
|
if (count == -1) {
|
||||||
LOGE("Could not list USB devices");
|
LOGE("Could not list USB devices");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
if (serial) {
|
LOGE("Could not find any USB device");
|
||||||
LOGE("Could not find USB device %s", serial);
|
|
||||||
} else {
|
|
||||||
LOGE("Could not find any USB device");
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count > 1) {
|
size_t sel_idx; // index of the single matching device if sel_count == 1
|
||||||
|
size_t sel_count =
|
||||||
|
sc_usb_devices_select(usb_devices, count, serial, &sel_idx);
|
||||||
|
|
||||||
|
if (sel_count == 0) {
|
||||||
|
// if count > 0 && sel_count == 0, then necessarily a serial is provided
|
||||||
|
assert(serial);
|
||||||
|
LOGE("Could not find USB device %s", serial);
|
||||||
|
sc_usb_devices_log(SC_LOG_LEVEL_ERROR, usb_devices, count);
|
||||||
|
sc_usb_devices_destroy_all(usb_devices, count);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sel_count > 1) {
|
||||||
if (serial) {
|
if (serial) {
|
||||||
LOGE("Multiple (%" SC_PRIsizet ") USB devices with serial %s:",
|
LOGE("Multiple (%" SC_PRIsizet ") USB devices with serial %s:",
|
||||||
count, serial);
|
sel_count, serial);
|
||||||
} else {
|
} else {
|
||||||
LOGE("Multiple (%" SC_PRIsizet ") USB devices:", count);
|
LOGE("Multiple (%" SC_PRIsizet ") USB devices:", sel_count);
|
||||||
}
|
|
||||||
for (size_t i = 0; i < (size_t) count; ++i) {
|
|
||||||
struct sc_usb_device *d = &usb_devices[i];
|
|
||||||
LOGE(" %-18s (%04" PRIx16 ":%04" PRIx16 ") %s %s",
|
|
||||||
d->serial, d->vid, d->pid, d->manufacturer, d->product);
|
|
||||||
}
|
}
|
||||||
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_all(usb_devices, count);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(count == 1);
|
assert(sel_count == 1); // sel_idx is valid only if sel_count == 1
|
||||||
// Move usb_devices[0] into out_device (do not destroy usb_devices[0])
|
struct sc_usb_device *device = &usb_devices[sel_idx];
|
||||||
*out_device = usb_devices[0];
|
|
||||||
|
LOGD("USB device found:");
|
||||||
|
sc_usb_devices_log(SC_LOG_LEVEL_DEBUG, usb_devices, count);
|
||||||
|
|
||||||
|
// Move device into out_device (do not destroy device)
|
||||||
|
sc_usb_device_move(out_device, device);
|
||||||
|
sc_usb_devices_destroy_all(usb_devices, count);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@ struct sc_usb_device {
|
|||||||
char *product;
|
char *product;
|
||||||
uint16_t vid;
|
uint16_t vid;
|
||||||
uint16_t pid;
|
uint16_t pid;
|
||||||
|
bool selected;
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
|
Loading…
Reference in New Issue
Block a user