From 146f65d7b2b046c2d9a218116b4483f1633b0322 Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Sun, 6 Feb 2022 16:06:46 +0100 Subject: [PATCH] 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 --- app/src/adb/adb.c | 98 +++++++++++++++++++++++++++++++---------------- app/src/adb/adb.h | 15 +++++++- app/src/server.c | 10 ++++- 3 files changed, 85 insertions(+), 38 deletions(-) diff --git a/app/src/adb/adb.c b/app/src/adb/adb.c index 5b61788a..2bfa9f1e 100644 --- a/app/src/adb/adb.c +++ b/app/src/adb/adb.c @@ -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)"); diff --git a/app/src/adb/adb.h b/app/src/adb/adb.h index 1381031f..dc302a85 100644 --- a/app/src/adb/adb.h +++ b/app/src/adb/adb.h @@ -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 ` diff --git a/app/src/server.c b/app/src/server.c index f6e8b6df..c0c33a2c 100644 --- a/app/src/server.c +++ b/app/src/server.c @@ -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; }