diff --git a/README.md b/README.md index 20ad0f9c46..8709169614 100644 --- a/README.md +++ b/README.md @@ -395,8 +395,8 @@ address), connect the device over USB, then run: scrcpy --tcpip # without arguments ``` -It will automatically find the device IP address, enable TCP/IP mode, then -connect to the device before starting. +It will automatically find the device IP address and adb port, enable TCP/IP +mode if necessary, then connect to the device before starting. ##### Manual diff --git a/app/scrcpy.1 b/app/scrcpy.1 index 7cb893b7f0..852d9d03ff 100644 --- a/app/scrcpy.1 +++ b/app/scrcpy.1 @@ -275,7 +275,7 @@ Configure and reconnect the device over TCP/IP. If a destination address is provided, then scrcpy connects to this address before starting. The device must listen on the given TCP port (default is 5555). -If no destination address is provided, then scrcpy attempts to find the IP address of the current device (typically connected over USB), enables TCP/IP mode, then connects to this address before starting. +If no destination address is provided, then scrcpy attempts to find the IP address and adb port of the current device (typically connected over USB), enables TCP/IP mode if necessary, then connects to this address before starting. .TP .B \-S, \-\-turn\-screen\-off diff --git a/app/src/server.c b/app/src/server.c index 663ef18bb4..e597048753 100644 --- a/app/src/server.c +++ b/app/src/server.c @@ -19,6 +19,8 @@ #define SC_SERVER_PATH_DEFAULT PREFIX "/share/scrcpy/" SC_SERVER_FILENAME #define SC_DEVICE_SERVER_PATH "/data/local/tmp/scrcpy-server.jar" +#define SC_ADB_PORT_DEFAULT 5555 + static char * get_server_path(void) { #ifdef __WINDOWS__ @@ -513,27 +515,36 @@ sc_server_on_terminated(void *userdata) { LOGD("Server terminated"); } -static bool -is_tcpip_mode_enabled(struct sc_server *server, const char *serial) { +static uint16_t +get_adb_tcp_port(struct sc_server *server, const char *serial) { struct sc_intr *intr = &server->intr; char *current_port = sc_adb_getprop(intr, serial, "service.adb.tcp.port", SC_ADB_SILENT); if (!current_port) { - return false; + return 0; } - // Is the device is listening on TCP on port 5555? - bool enabled = !strcmp("5555", current_port); + long value; + bool ok = sc_str_parse_integer(current_port, &value); free(current_port); - return enabled; + if (!ok) { + return 0; + } + + if (value < 0 || value > 0xFFFF) { + return 0; + } + + return value; } static bool wait_tcpip_mode_enabled(struct sc_server *server, const char *serial, - unsigned attempts, sc_tick delay) { - if (is_tcpip_mode_enabled(server, serial)) { - LOGI("TCP/IP mode enabled"); + uint16_t expected_port, unsigned attempts, + sc_tick delay) { + uint16_t adb_port = get_adb_tcp_port(server, serial); + if (adb_port == expected_port) { return true; } @@ -547,28 +558,23 @@ wait_tcpip_mode_enabled(struct sc_server *server, const char *serial, return false; } - if (is_tcpip_mode_enabled(server, serial)) { - LOGI("TCP/IP mode enabled"); + adb_port = get_adb_tcp_port(server, serial); + if (adb_port == expected_port) { return true; } } while (--attempts); return false; } -char * -append_port_5555(const char *ip) { - size_t len = strlen(ip); - - // sizeof counts the final '\0' - char *ip_port = malloc(len + sizeof(":5555")); - if (!ip_port) { +static char * +append_port(const char *ip, uint16_t port) { + char *ip_port; + int ret = asprintf(&ip_port, "%s:%" PRIu16, ip, port); + if (ret == -1) { LOG_OOM(); return NULL; } - memcpy(ip_port, ip, len); - memcpy(ip_port + len, ":5555", sizeof(":5555")); - return ip_port; } @@ -586,34 +592,36 @@ sc_server_switch_to_tcpip(struct sc_server *server, const char *serial) { return NULL; } - char *ip_port = append_port_5555(ip); - free(ip); - if (!ip_port) { - return NULL; - } - - bool tcp_mode = is_tcpip_mode_enabled(server, serial); + uint16_t adb_port = get_adb_tcp_port(server, serial); + if (adb_port) { + LOGI("TCP/IP mode already enabled on port %" PRIu16, adb_port); + } else { + LOGI("Enabling TCP/IP mode on port " SC_STR(SC_ADB_PORT_DEFAULT) "..."); - if (!tcp_mode) { - bool ok = sc_adb_tcpip(intr, serial, 5555, SC_ADB_NO_STDOUT); + bool ok = sc_adb_tcpip(intr, serial, SC_ADB_PORT_DEFAULT, + SC_ADB_NO_STDOUT); if (!ok) { LOGE("Could not restart adbd in TCP/IP mode"); - goto error; + free(ip); + return NULL; } unsigned attempts = 40; sc_tick delay = SC_TICK_FROM_MS(250); - ok = wait_tcpip_mode_enabled(server, serial, attempts, delay); + ok = wait_tcpip_mode_enabled(server, serial, SC_ADB_PORT_DEFAULT, + attempts, delay); if (!ok) { - goto error; + free(ip); + return NULL; } + + adb_port = SC_ADB_PORT_DEFAULT; + LOGI("TCP/IP mode enabled on port " SC_STR(SC_ADB_PORT_DEFAULT)); } + char *ip_port = append_port(ip, adb_port); + free(ip); return ip_port; - -error: - free(ip_port); - return NULL; } static bool @@ -640,7 +648,8 @@ sc_server_configure_tcpip_known_address(struct sc_server *server, const char *addr) { // Append ":5555" if no port is present bool contains_port = strchr(addr, ':'); - char *ip_port = contains_port ? strdup(addr) : append_port_5555(addr); + char *ip_port = contains_port ? strdup(addr) + : append_port(addr, SC_ADB_PORT_DEFAULT); if (!ip_port) { LOG_OOM(); return false; diff --git a/app/src/util/str.h b/app/src/util/str.h index 1736bd951f..4f7eeeda5a 100644 --- a/app/src/util/str.h +++ b/app/src/util/str.h @@ -6,6 +6,10 @@ #include #include +/* Stringify a numeric value */ +#define SC_STR(s) SC_XSTR(s) +#define SC_XSTR(s) #s + /** * Like strncpy(), except: * - it copies at most n-1 chars