diff --git a/app/scrcpy.1 b/app/scrcpy.1 index 0f618cb4..b659cd35 100644 --- a/app/scrcpy.1 +++ b/app/scrcpy.1 @@ -273,6 +273,14 @@ Set the TCP port of the adb tunnel to reach the scrcpy server. This option autom Default is 0 (not forced): the local port used for establishing the tunnel will be used. +.TP +.B \-T, \-\-select\-tcpip +Use TCP/IP device (if there is exactly one). + +.TP +.B \-U, \-\-select\-usb +Use USB device (if there is exactly one). + .TP .BI "\-\-v4l2-sink " /dev/videoN Output to v4l2loopback device. diff --git a/app/src/adb/adb.c b/app/src/adb/adb.c index 4794f062..a25b5a5c 100644 --- a/app/src/adb/adb.c +++ b/app/src/adb/adb.c @@ -451,6 +451,10 @@ sc_adb_accept_device(const struct sc_adb_device *device, } } return !strcmp(selector->serial, device->serial); + case SC_ADB_DEVICE_SELECT_USB: + return !sc_adb_is_serial_tcpip(device->serial); + case SC_ADB_DEVICE_SELECT_TCPIP: + return sc_adb_is_serial_tcpip(device->serial); default: assert(!"Missing SC_ADB_DEVICE_SELECT_* handling"); break; @@ -542,6 +546,12 @@ sc_adb_select_device(struct sc_intr *intr, assert(selector->serial); LOGE("Could not find ADB device %s:", selector->serial); break; + case SC_ADB_DEVICE_SELECT_USB: + LOGE("Could not find any ADB device over USB:"); + break; + case SC_ADB_DEVICE_SELECT_TCPIP: + LOGE("Could not find any ADB device over TCP/IP:"); + break; default: assert(!"Unexpected selector type"); break; @@ -562,6 +572,14 @@ sc_adb_select_device(struct sc_intr *intr, LOGE("Multiple (%" SC_PRIsizet ") ADB devices with serial %s:", sel_count, selector->serial); break; + case SC_ADB_DEVICE_SELECT_USB: + LOGE("Multiple (%" SC_PRIsizet ") ADB devices over USB:", + sel_count); + break; + case SC_ADB_DEVICE_SELECT_TCPIP: + LOGE("Multiple (%" SC_PRIsizet ") ADB devices over TCP/IP:", + sel_count); + break; default: assert(!"Unexpected selector type"); break; diff --git a/app/src/adb/adb.h b/app/src/adb/adb.h index dc302a85..6ea6e897 100644 --- a/app/src/adb/adb.h +++ b/app/src/adb/adb.h @@ -21,6 +21,8 @@ sc_adb_get_executable(void); enum sc_adb_device_selector_type { SC_ADB_DEVICE_SELECT_ALL, SC_ADB_DEVICE_SELECT_SERIAL, + SC_ADB_DEVICE_SELECT_USB, + SC_ADB_DEVICE_SELECT_TCPIP, }; struct sc_adb_device_selector { diff --git a/app/src/cli.c b/app/src/cli.c index 7567a10b..5ab46fec 100644 --- a/app/src/cli.c +++ b/app/src/cli.c @@ -416,6 +416,16 @@ static const struct sc_option options[] = { "Default is 0 (not forced): the local port used for " "establishing the tunnel will be used.", }, + { + .shortopt = 'T', + .longopt = "select-tcpip", + .text = "Use TCP/IP device (if there is exactly one).", + }, + { + .shortopt = 'U', + .longopt = "select-usb", + .text = "Use USB device (if there is exactly one).", + }, { .longopt_id = OPT_V4L2_SINK, .longopt = "v4l2-sink", @@ -1401,6 +1411,12 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[], case 't': opts->show_touches = true; break; + case 'T': + opts->select_tcpip = true; + break; + case 'U': + opts->select_usb = true; + break; case OPT_ALWAYS_ON_TOP: opts->always_on_top = true; break; @@ -1559,8 +1575,16 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[], // If a TCP/IP address is provided, then tcpip must be enabled assert(opts->tcpip || !opts->tcpip_dst); - if (opts->serial && opts->tcpip_dst) { - LOGE("Incompatible options: -s/--serial and --tcpip with an argument"); + unsigned selectors = !!opts->serial + + !!opts->tcpip_dst + + opts->select_tcpip + + opts->select_usb; + if (selectors > 1) { + LOGE("At most one device selector option may be passed, among:\n" + " --serial (-s)\n" + " --select-usb (-U)\n" + " --select-tcpip (-T)\n" + " --tcpip= (with an argument)"); return false; } diff --git a/app/src/options.c b/app/src/options.c index c94f798d..377c5590 100644 --- a/app/src/options.c +++ b/app/src/options.c @@ -60,4 +60,6 @@ const struct scrcpy_options scrcpy_options_default = { .downsize_on_error = true, .tcpip = false, .tcpip_dst = NULL, + .select_tcpip = false, + .select_usb = false, }; diff --git a/app/src/options.h b/app/src/options.h index 1591a065..44104734 100644 --- a/app/src/options.h +++ b/app/src/options.h @@ -135,6 +135,8 @@ struct scrcpy_options { bool downsize_on_error; bool tcpip; const char *tcpip_dst; + bool select_usb; + bool select_tcpip; }; extern const struct scrcpy_options scrcpy_options_default; diff --git a/app/src/scrcpy.c b/app/src/scrcpy.c index d0aa2627..c3a481d0 100644 --- a/app/src/scrcpy.c +++ b/app/src/scrcpy.c @@ -297,6 +297,8 @@ scrcpy(struct scrcpy_options *options) { struct sc_server_params params = { .req_serial = options->serial, + .select_usb = options->select_usb, + .select_tcpip = options->select_tcpip, .log_level = options->log_level, .crop = options->crop, .port_range = options->port_range, diff --git a/app/src/server.c b/app/src/server.c index c0c33a2c..0de51c7e 100644 --- a/app/src/server.c +++ b/app/src/server.c @@ -687,10 +687,19 @@ run_server(void *data) { bool need_initial_serial = !params->tcpip_dst; if (need_initial_serial) { + // At most one of the 3 following parameters may be set + assert(!!params->req_serial + + params->select_usb + + params->select_tcpip <= 1); + struct sc_adb_device_selector selector; if (params->req_serial) { selector.type = SC_ADB_DEVICE_SELECT_SERIAL; selector.serial = params->req_serial; + } else if (params->select_usb) { + selector.type = SC_ADB_DEVICE_SELECT_USB; + } else if (params->select_tcpip) { + selector.type = SC_ADB_DEVICE_SELECT_TCPIP; } else { selector.type = SC_ADB_DEVICE_SELECT_ALL; } diff --git a/app/src/server.h b/app/src/server.h index c2293118..5818b43c 100644 --- a/app/src/server.h +++ b/app/src/server.h @@ -44,6 +44,8 @@ struct sc_server_params { bool downsize_on_error; bool tcpip; const char *tcpip_dst; + bool select_usb; + bool select_tcpip; }; struct sc_server {