Introduce adb device selector
Currently, a device is selected either from a specific serial, or if it is the only one connected. In order to support selecting the only device connected via USB or via TCP/IP separately, introduce a new selection structure. PR #3005 <https://github.com/Genymobile/scrcpy/pull/3005>
This commit is contained in:
parent
5ed13ef477
commit
146f65d7b2
3 changed files with 85 additions and 38 deletions
|
@ -424,39 +424,49 @@ sc_adb_list_devices(struct sc_intr *intr, unsigned flags,
|
|||
}
|
||||
|
||||
static bool
|
||||
sc_adb_accept_device(const struct sc_adb_device *device, const char *serial) {
|
||||
if (!serial) {
|
||||
return true;
|
||||
}
|
||||
|
||||
char *device_serial_colon = strchr(device->serial, ':');
|
||||
if (device_serial_colon) {
|
||||
// The device serial is an IP:port...
|
||||
char *serial_colon = strchr(serial, ':');
|
||||
if (!serial_colon) {
|
||||
// But the requested serial has no ':', so only consider the IP part
|
||||
// of the device serial. This allows to use "192.168.1.1" to match
|
||||
// any "192.168.1.1:port".
|
||||
size_t serial_len = strlen(serial);
|
||||
size_t device_ip_len = device_serial_colon - device->serial;
|
||||
if (serial_len != device_ip_len) {
|
||||
// They are not equal, they don't even have the same length
|
||||
return false;
|
||||
sc_adb_accept_device(const struct sc_adb_device *device,
|
||||
const struct sc_adb_device_selector *selector) {
|
||||
switch (selector->type) {
|
||||
case SC_ADB_DEVICE_SELECT_ALL:
|
||||
return true;
|
||||
case SC_ADB_DEVICE_SELECT_SERIAL:
|
||||
assert(selector->serial);
|
||||
char *device_serial_colon = strchr(device->serial, ':');
|
||||
if (device_serial_colon) {
|
||||
// The device serial is an IP:port...
|
||||
char *serial_colon = strchr(selector->serial, ':');
|
||||
if (!serial_colon) {
|
||||
// But the requested serial has no ':', so only consider
|
||||
// the IP part of the device serial. This allows to use
|
||||
// "192.168.1.1" to match any "192.168.1.1:port".
|
||||
size_t serial_len = strlen(selector->serial);
|
||||
size_t device_ip_len = device_serial_colon - device->serial;
|
||||
if (serial_len != device_ip_len) {
|
||||
// They are not equal, they don't even have the same
|
||||
// length
|
||||
return false;
|
||||
}
|
||||
return !strncmp(selector->serial, device->serial,
|
||||
device_ip_len);
|
||||
}
|
||||
}
|
||||
return !strncmp(serial, device->serial, device_ip_len);
|
||||
}
|
||||
return !strcmp(selector->serial, device->serial);
|
||||
default:
|
||||
assert(!"Missing SC_ADB_DEVICE_SELECT_* handling");
|
||||
break;
|
||||
}
|
||||
|
||||
return !strcmp(serial, device->serial);
|
||||
return false;
|
||||
}
|
||||
|
||||
static size_t
|
||||
sc_adb_devices_select(struct sc_adb_device *devices, size_t len,
|
||||
const char *serial, size_t *idx_out) {
|
||||
const struct sc_adb_device_selector *selector,
|
||||
size_t *idx_out) {
|
||||
size_t count = 0;
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
struct sc_adb_device *device = &devices[i];
|
||||
device->selected = sc_adb_accept_device(device, serial);
|
||||
device->selected = sc_adb_accept_device(device, selector);
|
||||
if (device->selected) {
|
||||
if (idx_out && !count) {
|
||||
*idx_out = i;
|
||||
|
@ -502,8 +512,9 @@ sc_adb_device_check_state(struct sc_adb_device *device,
|
|||
}
|
||||
|
||||
bool
|
||||
sc_adb_select_device(struct sc_intr *intr, const char *serial, unsigned flags,
|
||||
struct sc_adb_device *out_device) {
|
||||
sc_adb_select_device(struct sc_intr *intr,
|
||||
const struct sc_adb_device_selector *selector,
|
||||
unsigned flags, struct sc_adb_device *out_device) {
|
||||
struct sc_adb_device devices[16];
|
||||
ssize_t count =
|
||||
sc_adb_list_devices(intr, flags, devices, ARRAY_LEN(devices));
|
||||
|
@ -518,23 +529,42 @@ sc_adb_select_device(struct sc_intr *intr, const char *serial, unsigned flags,
|
|||
}
|
||||
|
||||
size_t sel_idx; // index of the single matching device if sel_count == 1
|
||||
size_t sel_count = sc_adb_devices_select(devices, count, serial, &sel_idx);
|
||||
size_t sel_count =
|
||||
sc_adb_devices_select(devices, count, selector, &sel_idx);
|
||||
|
||||
if (sel_count == 0) {
|
||||
// if count > 0 && sel_count == 0, then necessarily a serial is provided
|
||||
assert(serial);
|
||||
LOGE("Could not find ADB device %s", serial);
|
||||
// if count > 0 && sel_count == 0, then necessarily a selection is
|
||||
// requested
|
||||
assert(selector->type != SC_ADB_DEVICE_SELECT_ALL);
|
||||
|
||||
switch (selector->type) {
|
||||
case SC_ADB_DEVICE_SELECT_SERIAL:
|
||||
assert(selector->serial);
|
||||
LOGE("Could not find ADB device %s:", selector->serial);
|
||||
break;
|
||||
default:
|
||||
assert(!"Unexpected selector type");
|
||||
break;
|
||||
}
|
||||
|
||||
sc_adb_devices_log(SC_LOG_LEVEL_ERROR, devices, count);
|
||||
sc_adb_devices_destroy_all(devices, count);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sel_count > 1) {
|
||||
if (serial) {
|
||||
LOGE("Multiple (%" SC_PRIsizet ") ADB devices with serial %s:",
|
||||
sel_count, serial);
|
||||
} else {
|
||||
LOGE("Multiple (%" SC_PRIsizet ") ADB devices:", sel_count);
|
||||
switch (selector->type) {
|
||||
case SC_ADB_DEVICE_SELECT_ALL:
|
||||
LOGE("Multiple (%" SC_PRIsizet ") ADB devices:", sel_count);
|
||||
break;
|
||||
case SC_ADB_DEVICE_SELECT_SERIAL:
|
||||
assert(selector->serial);
|
||||
LOGE("Multiple (%" SC_PRIsizet ") ADB devices with serial %s:",
|
||||
sel_count, selector->serial);
|
||||
break;
|
||||
default:
|
||||
assert(!"Unexpected selector type");
|
||||
break;
|
||||
}
|
||||
sc_adb_devices_log(SC_LOG_LEVEL_ERROR, devices, count);
|
||||
LOGE("Select a device via -s (--serial)");
|
||||
|
|
|
@ -18,6 +18,16 @@
|
|||
const char *
|
||||
sc_adb_get_executable(void);
|
||||
|
||||
enum sc_adb_device_selector_type {
|
||||
SC_ADB_DEVICE_SELECT_ALL,
|
||||
SC_ADB_DEVICE_SELECT_SERIAL,
|
||||
};
|
||||
|
||||
struct sc_adb_device_selector {
|
||||
enum sc_adb_device_selector_type type;
|
||||
const char *serial;
|
||||
};
|
||||
|
||||
sc_pid
|
||||
sc_adb_execute(const char *const argv[], unsigned flags);
|
||||
|
||||
|
@ -79,8 +89,9 @@ sc_adb_disconnect(struct sc_intr *intr, const char *ip_port, unsigned flags);
|
|||
* Return true if a single matching device is found, and write it to out_device.
|
||||
*/
|
||||
bool
|
||||
sc_adb_select_device(struct sc_intr *intr, const char *serial, unsigned flags,
|
||||
struct sc_adb_device *out_device);
|
||||
sc_adb_select_device(struct sc_intr *intr,
|
||||
const struct sc_adb_device_selector *selector,
|
||||
unsigned flags, struct sc_adb_device *out_device);
|
||||
|
||||
/**
|
||||
* Execute `adb getprop <prop>`
|
||||
|
|
|
@ -687,9 +687,15 @@ run_server(void *data) {
|
|||
bool need_initial_serial = !params->tcpip_dst;
|
||||
|
||||
if (need_initial_serial) {
|
||||
struct sc_adb_device_selector selector;
|
||||
if (params->req_serial) {
|
||||
selector.type = SC_ADB_DEVICE_SELECT_SERIAL;
|
||||
selector.serial = params->req_serial;
|
||||
} else {
|
||||
selector.type = SC_ADB_DEVICE_SELECT_ALL;
|
||||
}
|
||||
struct sc_adb_device device;
|
||||
ok = sc_adb_select_device(&server->intr, params->req_serial, 0,
|
||||
&device);
|
||||
ok = sc_adb_select_device(&server->intr, &selector, 0, &device);
|
||||
if (!ok) {
|
||||
goto error_connection_failed;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue