From be1936bb85de6a19a805ed320dcabe217e52d656 Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Thu, 10 Feb 2022 07:57:18 +0100 Subject: [PATCH 01/10] Report USB device disconnection when detected USB device disconnection is detected via a hotplug callback when it is supported. In addition, report disconnection on libusb calls returning LIBUSB_ERROR_NO_DEVICE or LIBUSB_ERROR_NOT_FOUND. This allows to detect disconnection after a libusb call when hotplug is not available. PR #3011 --- app/src/usb/aoa_hid.c | 4 ++++ app/src/usb/usb.c | 22 ++++++++++++++++++++-- app/src/usb/usb.h | 6 ++++++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/app/src/usb/aoa_hid.c b/app/src/usb/aoa_hid.c index 57296bfcc1..0007169d86 100644 --- a/app/src/usb/aoa_hid.c +++ b/app/src/usb/aoa_hid.c @@ -95,6 +95,7 @@ sc_aoa_register_hid(struct sc_aoa *aoa, uint16_t accessory_id, DEFAULT_TIMEOUT); if (result < 0) { LOGE("REGISTER_HID: libusb error: %s", libusb_strerror(result)); + sc_usb_check_disconnected(aoa->usb, result); return false; } @@ -131,6 +132,7 @@ sc_aoa_set_hid_report_desc(struct sc_aoa *aoa, uint16_t accessory_id, DEFAULT_TIMEOUT); if (result < 0) { LOGE("SET_HID_REPORT_DESC: libusb error: %s", libusb_strerror(result)); + sc_usb_check_disconnected(aoa->usb, result); return false; } @@ -173,6 +175,7 @@ sc_aoa_send_hid_event(struct sc_aoa *aoa, const struct sc_hid_event *event) { DEFAULT_TIMEOUT); if (result < 0) { LOGE("SEND_HID_EVENT: libusb error: %s", libusb_strerror(result)); + sc_usb_check_disconnected(aoa->usb, result); return false; } @@ -195,6 +198,7 @@ sc_aoa_unregister_hid(struct sc_aoa *aoa, const uint16_t accessory_id) { DEFAULT_TIMEOUT); if (result < 0) { LOGE("UNREGISTER_HID: libusb error: %s", libusb_strerror(result)); + sc_usb_check_disconnected(aoa->usb, result); return false; } diff --git a/app/src/usb/usb.c b/app/src/usb/usb.c index 07fb961918..7a0e4cfd1e 100644 --- a/app/src/usb/usb.c +++ b/app/src/usb/usb.c @@ -216,6 +216,24 @@ sc_usb_destroy(struct sc_usb *usb) { libusb_exit(usb->context); } +static void +sc_usb_report_disconnected(struct sc_usb *usb) { + if (usb->cbs && !atomic_flag_test_and_set(&usb->disconnection_notified)) { + assert(usb->cbs && usb->cbs->on_disconnected); + usb->cbs->on_disconnected(usb, usb->cbs_userdata); + } +} + +bool +sc_usb_check_disconnected(struct sc_usb *usb, int result) { + if (result == LIBUSB_ERROR_NO_DEVICE || result == LIBUSB_ERROR_NOT_FOUND) { + sc_usb_report_disconnected(usb); + return false; + } + + return true; +} + static int sc_usb_libusb_callback(libusb_context *ctx, libusb_device *device, libusb_hotplug_event event, void *userdata) { @@ -232,8 +250,7 @@ sc_usb_libusb_callback(libusb_context *ctx, libusb_device *device, return 0; } - assert(usb->cbs && usb->cbs->on_disconnected); - usb->cbs->on_disconnected(usb, usb->cbs_userdata); + sc_usb_report_disconnected(usb); // Do not automatically deregister the callback by returning 1. Instead, // manually deregister to interrupt libusb_handle_events() from the libusb @@ -307,6 +324,7 @@ sc_usb_connect(struct sc_usb *usb, libusb_device *device, if (cbs) { atomic_init(&usb->stopped, false); + usb->disconnection_notified = (atomic_flag) ATOMIC_FLAG_INIT; if (sc_usb_register_callback(usb)) { // Create a thread to process libusb events, so that device // disconnection could be detected immediately diff --git a/app/src/usb/usb.h b/app/src/usb/usb.h index d264a536d3..f0ebbd96b6 100644 --- a/app/src/usb/usb.h +++ b/app/src/usb/usb.h @@ -22,6 +22,7 @@ struct sc_usb { sc_thread libusb_event_thread; atomic_bool stopped; // only used if cbs != NULL + atomic_flag disconnection_notified; }; struct sc_usb_callbacks { @@ -73,6 +74,11 @@ sc_usb_connect(struct sc_usb *usb, libusb_device *device, void sc_usb_disconnect(struct sc_usb *usb); +// A client should call this function with the return value of a libusb call +// to detect disconnection immediately +bool +sc_usb_check_disconnected(struct sc_usb *usb, int result); + void sc_usb_stop(struct sc_usb *usb); From b9b28797893c9449b89b44e1c0ac209a5358cca5 Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Thu, 10 Feb 2022 09:29:07 +0100 Subject: [PATCH 02/10] Remove USB hotplug callback error log If it fails, the error is already logged by sc_usb_register_callback(). PR #3011 --- app/src/usb/usb.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/src/usb/usb.c b/app/src/usb/usb.c index 7a0e4cfd1e..799ada9416 100644 --- a/app/src/usb/usb.c +++ b/app/src/usb/usb.c @@ -335,8 +335,6 @@ sc_usb_connect(struct sc_usb *usb, libusb_device *device, LOGW("Libusb event thread handler could not be created, USB " "device disconnection might not be detected immediately"); } - } else { - LOGW("Could not register USB device disconnection callback"); } } From 06243e7c3cd313e2d4d4b34fe0d2c3f35d9aee6d Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Mon, 7 Feb 2022 08:57:42 +0100 Subject: [PATCH 03/10] Avoid PRIx16 printf format on Windows Convert uint16_t to unsigned to avoid using PRIx16, which may not exist on Windows. PR #3011 --- app/src/usb/scrcpy_otg.c | 4 ++-- app/src/usb/usb.c | 11 +++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/app/src/usb/scrcpy_otg.c b/app/src/usb/scrcpy_otg.c index d3a4567921..1eaa2537bd 100644 --- a/app/src/usb/scrcpy_otg.c +++ b/app/src/usb/scrcpy_otg.c @@ -91,8 +91,8 @@ scrcpy_otg(struct scrcpy_options *options) { usb_device_initialized = true; - LOGI("USB device: %s (%04" PRIx16 ":%04" PRIx16 ") %s %s", - usb_device.serial, usb_device.vid, usb_device.pid, + LOGI("USB device: %s (%04x:%04x) %s %s", usb_device.serial, + (unsigned) usb_device.vid, (unsigned) usb_device.pid, usb_device.manufacturer, usb_device.product); ok = sc_usb_connect(&s->usb, usb_device.device, &cbs, NULL); diff --git a/app/src/usb/usb.c b/app/src/usb/usb.c index 799ada9416..2d3fc3a643 100644 --- a/app/src/usb/usb.c +++ b/app/src/usb/usb.c @@ -40,8 +40,9 @@ sc_usb_read_device(libusb_device *device, struct sc_usb_device *out) { if (result < 0) { // Log at debug level because it is expected that some non-Android USB // devices present on the computer require special permissions - LOGD("Open USB device %04" PRIx16 ":%04" PRIx16 ": libusb error: %s", - desc.idVendor, desc.idProduct, libusb_strerror(result)); + LOGD("Open USB device %04x:%04x: libusb error: %s", + (unsigned) desc.idVendor, (unsigned) desc.idProduct, + libusb_strerror(result)); return false; } @@ -146,8 +147,10 @@ sc_usb_devices_log(enum sc_log_level level, struct sc_usb_device *devices, 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); + // Convert uint16_t to unsigned because PRIx16 may not exist on Windows + LOG(level, " %s %-18s (%04x:%04x) %s %s", + selection, d->serial, (unsigned) d->vid, (unsigned) d->pid, + d->manufacturer, d->product); } } From ff3cb31cb4a5d58354e6a7b59c6e2486091ff691 Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Mon, 7 Feb 2022 09:08:21 +0100 Subject: [PATCH 04/10] Fix libusb callback for Windows Add LIBUSB_CALL so that the callback has the correct signature on Windows (including __attribute__((stdcall))). PR #3011 --- app/src/usb/usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/usb/usb.c b/app/src/usb/usb.c index 2d3fc3a643..276b0067e2 100644 --- a/app/src/usb/usb.c +++ b/app/src/usb/usb.c @@ -237,7 +237,7 @@ sc_usb_check_disconnected(struct sc_usb *usb, int result) { return true; } -static int +static LIBUSB_CALL int sc_usb_libusb_callback(libusb_context *ctx, libusb_device *device, libusb_hotplug_event event, void *userdata) { (void) ctx; From 6b65cd405a56d09b00a609ef43f2846c2cc349f7 Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Mon, 7 Feb 2022 08:52:17 +0100 Subject: [PATCH 05/10] Build for Windows with libusb support Fixes #2773 PR #3011 --- BUILD.md | 6 ++++-- app/meson.build | 15 ++++++++++++++- app/prebuilt-deps/prepare-libusb.sh | 28 ++++++++++++++++++++++++++++ cross_win32.txt | 2 ++ cross_win64.txt | 2 ++ release.mk | 4 ++++ 6 files changed, 54 insertions(+), 3 deletions(-) create mode 100755 app/prebuilt-deps/prepare-libusb.sh diff --git a/BUILD.md b/BUILD.md index e32ab6848c..60be752d26 100644 --- a/BUILD.md +++ b/BUILD.md @@ -161,7 +161,8 @@ install the required packages: ```bash # runtime dependencies pacman -S mingw-w64-x86_64-SDL2 \ - mingw-w64-x86_64-ffmpeg + mingw-w64-x86_64-ffmpeg \ + mingw-w64-x86_64-libusb # client build dependencies pacman -S mingw-w64-x86_64-make \ @@ -175,7 +176,8 @@ For a 32 bits version, replace `x86_64` by `i686`: ```bash # runtime dependencies pacman -S mingw-w64-i686-SDL2 \ - mingw-w64-i686-ffmpeg + mingw-w64-i686-ffmpeg \ + mingw-w64-i686-libusb # client build dependencies pacman -S mingw-w64-i686-make \ diff --git a/app/meson.build b/app/meson.build index 9cd009fefc..a008661933 100644 --- a/app/meson.build +++ b/app/meson.build @@ -74,7 +74,7 @@ if v4l2_support src += [ 'src/v4l2_sink.c' ] endif -usb_support = get_option('usb') and host_machine.system() != 'windows' +usb_support = get_option('usb') if usb_support src += [ 'src/usb/aoa_hid.c', @@ -141,9 +141,22 @@ else include_directories: include_directories(ffmpeg_include_dir) ) + prebuilt_libusb = meson.get_cross_property('prebuilt_libusb') + prebuilt_libusb_root = meson.get_cross_property('prebuilt_libusb_root') + libusb_bin_dir = meson.current_source_dir() + '/prebuilt-deps/data/' + prebuilt_libusb + '/dll' + libusb_include_dir = 'prebuilt-deps/data/' + prebuilt_libusb_root + '/include' + + libusb = declare_dependency( + dependencies: [ + cc.find_library('libusb-1.0', dirs: libusb_bin_dir), + ], + include_directories: include_directories(libusb_include_dir) + ) + dependencies = [ ffmpeg, sdl2, + libusb, cc.find_library('mingw32') ] diff --git a/app/prebuilt-deps/prepare-libusb.sh b/app/prebuilt-deps/prepare-libusb.sh new file mode 100755 index 0000000000..54ead536ef --- /dev/null +++ b/app/prebuilt-deps/prepare-libusb.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +set -e +DIR=$(dirname ${BASH_SOURCE[0]}) +cd "$DIR" +. common +mkdir -p "$PREBUILT_DATA_DIR" +cd "$PREBUILT_DATA_DIR" + +DEP_DIR=libusb-1.0.25 + +FILENAME=libusb-1.0.25.7z +SHA256SUM=3d1c98416f454026034b2b5d67f8a294053898cb70a8b489874e75b136c6674d + +if [[ -d "$DEP_DIR" ]] +then + echo "$DEP_DIR" found + exit 0 +fi + +get_file "https://github.com/libusb/libusb/releases/download/v1.0.25/$FILENAME" "$FILENAME" "$SHA256SUM" + +mkdir "$DEP_DIR" +cd "$DEP_DIR" + +7z x "../$FILENAME" \ + MinGW32/dll/libusb-1.0.dll \ + MinGW64/dll/libusb-1.0.dll \ + include / diff --git a/cross_win32.txt b/cross_win32.txt index db448a0018..750dbd78c7 100644 --- a/cross_win32.txt +++ b/cross_win32.txt @@ -21,3 +21,5 @@ ffmpeg_avformat = 'avformat-58' ffmpeg_avutil = 'avutil-56' prebuilt_ffmpeg = 'ffmpeg-win32-4.3.1' prebuilt_sdl2 = 'SDL2-2.0.20/i686-w64-mingw32' +prebuilt_libusb_root = 'libusb-1.0.25' +prebuilt_libusb = prebuilt_libusb_root + '/MinGW32' diff --git a/cross_win64.txt b/cross_win64.txt index 9d169a71cf..114b0c2217 100644 --- a/cross_win64.txt +++ b/cross_win64.txt @@ -21,3 +21,5 @@ ffmpeg_avformat = 'avformat-59' ffmpeg_avutil = 'avutil-57' prebuilt_ffmpeg = 'ffmpeg-win64-5.0' prebuilt_sdl2 = 'SDL2-2.0.20/x86_64-w64-mingw32' +prebuilt_libusb_root = 'libusb-1.0.25' +prebuilt_libusb = prebuilt_libusb_root + '/MinGW64' diff --git a/release.mk b/release.mk index aff9bd8959..00d2389ff7 100644 --- a/release.mk +++ b/release.mk @@ -66,11 +66,13 @@ prepare-deps-win32: @app/prebuilt-deps/prepare-adb.sh @app/prebuilt-deps/prepare-sdl.sh @app/prebuilt-deps/prepare-ffmpeg-win32.sh + @app/prebuilt-deps/prepare-libusb.sh prepare-deps-win64: @app/prebuilt-deps/prepare-adb.sh @app/prebuilt-deps/prepare-sdl.sh @app/prebuilt-deps/prepare-ffmpeg-win64.sh + @app/prebuilt-deps/prepare-libusb.sh build-win32: prepare-deps-win32 [ -d "$(WIN32_BUILD_DIR)" ] || ( mkdir "$(WIN32_BUILD_DIR)" && \ @@ -107,6 +109,7 @@ dist-win32: build-server build-win32 cp app/prebuilt-deps/data/platform-tools-31.0.3/AdbWinApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/" cp app/prebuilt-deps/data/platform-tools-31.0.3/AdbWinUsbApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/" cp app/prebuilt-deps/data/SDL2-2.0.20/i686-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN32_TARGET_DIR)/" + cp app/prebuilt-deps/data/libusb-1.0.25/MinGW32/dll/libusb-1.0.dll "$(DIST)/$(WIN32_TARGET_DIR)/" dist-win64: build-server build-win64 mkdir -p "$(DIST)/$(WIN64_TARGET_DIR)" @@ -125,6 +128,7 @@ dist-win64: build-server build-win64 cp app/prebuilt-deps/data/platform-tools-31.0.3/AdbWinApi.dll "$(DIST)/$(WIN64_TARGET_DIR)/" cp app/prebuilt-deps/data/platform-tools-31.0.3/AdbWinUsbApi.dll "$(DIST)/$(WIN64_TARGET_DIR)/" cp app/prebuilt-deps/data/SDL2-2.0.20/x86_64-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN64_TARGET_DIR)/" + cp app/prebuilt-deps/data/libusb-1.0.25/MinGW64/dll/libusb-1.0.dll "$(DIST)/$(WIN64_TARGET_DIR)/" zip-win32: dist-win32 cd "$(DIST)/$(WIN32_TARGET_DIR)"; \ From 6ee75c0cff3eb995486901757e682f960516b6b0 Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Sun, 20 Feb 2022 17:19:11 +0100 Subject: [PATCH 06/10] Remove obsolete text in error message The HID/OTG features are now available on all platforms. PR #3011 --- app/src/cli.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/app/src/cli.c b/app/src/cli.c index f930142ef4..d8ae4f5385 100644 --- a/app/src/cli.c +++ b/app/src/cli.c @@ -1370,8 +1370,7 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[], opts->keyboard_input_mode = SC_KEYBOARD_INPUT_MODE_HID; break; #else - LOGE("HID over AOA (-K/--hid-keyboard) is disabled (or " - "unsupported on this platform)."); + LOGE("HID over AOA (-K/--hid-keyboard) is disabled."); return false; #endif case OPT_MAX_FPS: @@ -1389,8 +1388,7 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[], opts->mouse_input_mode = SC_MOUSE_INPUT_MODE_HID; break; #else - LOGE("HID over AOA (-M/--hid-mouse) is disabled (or " - "unsupported on this platform)."); + LOGE("HID over AOA (-M/--hid-mouse) is disabled."); return false; #endif case OPT_LOCK_VIDEO_ORIENTATION: @@ -1559,8 +1557,7 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[], opts->otg = true; break; #else - LOGE("OTG mode (--otg) is disabled (or unsupported on this " - "platform)."); + LOGE("OTG mode (--otg) is disabled."); return false; #endif case OPT_V4L2_SINK: From 3bb24b3926a2db0fa38393c829b4e703471c0fcc Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Thu, 10 Feb 2022 08:05:54 +0100 Subject: [PATCH 07/10] Make intr optional for adb commands All adb commands are executed with an "interruptor", so that they can be interrupted on Ctrl+C. Make this interruptor optional, so that we could call "adb kill-server" in OTG mode. This command always returns almost immediately anyway. Ideally, we should make all blocking calls interruptible (including libusb calls, by using the asynchronous API), but it's a lot of work, and in practice it works well enough. PR #3011 --- app/src/adb/adb.c | 6 ++++-- app/src/util/process_intr.c | 14 ++++++++++---- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/app/src/adb/adb.c b/app/src/adb/adb.c index 8ce9cc6fbd..8742c4d02e 100644 --- a/app/src/adb/adb.c +++ b/app/src/adb/adb.c @@ -150,7 +150,7 @@ process_check_success_internal(sc_pid pid, const char *name, bool close, static bool process_check_success_intr(struct sc_intr *intr, sc_pid pid, const char *name, unsigned flags) { - if (!sc_intr_set_process(intr, pid)) { + if (intr && !sc_intr_set_process(intr, pid)) { // Already interrupted return false; } @@ -158,7 +158,9 @@ process_check_success_intr(struct sc_intr *intr, sc_pid pid, const char *name, // Always pass close=false, interrupting would be racy otherwise bool ret = process_check_success_internal(pid, name, false, flags); - sc_intr_set_process(intr, SC_PROCESS_NONE); + if (intr) { + sc_intr_set_process(intr, SC_PROCESS_NONE); + } // Close separately sc_process_close(pid); diff --git a/app/src/util/process_intr.c b/app/src/util/process_intr.c index 940fe89f9f..d37bd5a54a 100644 --- a/app/src/util/process_intr.c +++ b/app/src/util/process_intr.c @@ -3,27 +3,33 @@ ssize_t sc_pipe_read_intr(struct sc_intr *intr, sc_pid pid, sc_pipe pipe, char *data, size_t len) { - if (!sc_intr_set_process(intr, pid)) { + if (intr && !sc_intr_set_process(intr, pid)) { // Already interrupted return false; } ssize_t ret = sc_pipe_read(pipe, data, len); - sc_intr_set_process(intr, SC_PROCESS_NONE); + if (intr) { + sc_intr_set_process(intr, SC_PROCESS_NONE); + } + return ret; } ssize_t sc_pipe_read_all_intr(struct sc_intr *intr, sc_pid pid, sc_pipe pipe, char *data, size_t len) { - if (!sc_intr_set_process(intr, pid)) { + if (intr && !sc_intr_set_process(intr, pid)) { // Already interrupted return false; } ssize_t ret = sc_pipe_read_all(pipe, data, len); - sc_intr_set_process(intr, SC_PROCESS_NONE); + if (intr) { + sc_intr_set_process(intr, SC_PROCESS_NONE); + } + return ret; } From 25296ae16710c0c7bf69e60f4e1aa952e0443075 Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Thu, 10 Feb 2022 08:42:15 +0100 Subject: [PATCH 08/10] Kill adb daemon in OTG mode on Windows On Windows, it is not possible to open a USB device from several process, so HID events may only work if no adb daemon is running. PR #3011 --- app/src/adb/adb.c | 8 ++++++++ app/src/adb/adb.h | 3 +++ app/src/usb/scrcpy_otg.c | 10 ++++++++++ 3 files changed, 21 insertions(+) diff --git a/app/src/adb/adb.c b/app/src/adb/adb.c index 8742c4d02e..4ddb93f374 100644 --- a/app/src/adb/adb.c +++ b/app/src/adb/adb.c @@ -204,6 +204,14 @@ sc_adb_start_server(struct sc_intr *intr, unsigned flags) { return process_check_success_intr(intr, pid, "adb start-server", flags); } +bool +sc_adb_kill_server(struct sc_intr *intr, unsigned flags) { + const char *const argv[] = SC_ADB_COMMAND("kill-server"); + + sc_pid pid = sc_adb_execute(argv, flags); + return process_check_success_intr(intr, pid, "adb kill-server", flags); +} + bool sc_adb_forward(struct sc_intr *intr, const char *serial, uint16_t local_port, const char *device_socket_name, unsigned flags) { diff --git a/app/src/adb/adb.h b/app/src/adb/adb.h index 6ea6e897bf..10e8f293b1 100644 --- a/app/src/adb/adb.h +++ b/app/src/adb/adb.h @@ -36,6 +36,9 @@ sc_adb_execute(const char *const argv[], unsigned flags); bool sc_adb_start_server(struct sc_intr *intr, unsigned flags); +bool +sc_adb_kill_server(struct sc_intr *intr, unsigned flags); + bool sc_adb_forward(struct sc_intr *intr, const char *serial, uint16_t local_port, const char *device_socket_name, unsigned flags); diff --git a/app/src/usb/scrcpy_otg.c b/app/src/usb/scrcpy_otg.c index 1eaa2537bd..1c53410eeb 100644 --- a/app/src/usb/scrcpy_otg.c +++ b/app/src/usb/scrcpy_otg.c @@ -2,6 +2,7 @@ #include +#include "adb/adb.h" #include "events.h" #include "screen_otg.h" #include "util/log.h" @@ -75,6 +76,15 @@ scrcpy_otg(struct scrcpy_options *options) { bool aoa_started = false; bool aoa_initialized = false; +#ifdef _WIN32 + // On Windows, only one process could open a USB device + // + LOGI("Killing adb daemon (if any)..."); + unsigned flags = SC_ADB_NO_STDOUT | SC_ADB_NO_STDERR | SC_ADB_NO_LOGERR; + // uninterruptible (intr == NULL), but in practice it's very quick + sc_adb_kill_server(NULL, flags); +#endif + static const struct sc_usb_callbacks cbs = { .on_disconnected = sc_usb_on_disconnected, }; From 73a5311ac6c6570f1c9d23cd943c8d9aa0b281fe Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Thu, 10 Feb 2022 09:01:31 +0100 Subject: [PATCH 09/10] Forbid HID input without OTG on Windows On Windows, if the adb daemon is running, opening the USB device will necessarily fail, so HID input is not possible. Refs #2773 PR #3011 --- app/src/cli.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/app/src/cli.c b/app/src/cli.c index d8ae4f5385..482896781c 100644 --- a/app/src/cli.c +++ b/app/src/cli.c @@ -1680,6 +1680,18 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[], } #ifdef HAVE_USB + +# ifdef _WIN32 + if (!opts->otg && (opts->keyboard_input_mode == SC_KEYBOARD_INPUT_MODE_HID + || opts->mouse_input_mode == SC_MOUSE_INPUT_MODE_HID)) { + LOGE("On Windows, it is not possible to open a USB device already open " + "by another process (like adb)."); + LOGE("Therefore, -K/--hid-keyboard and -M/--hid-mouse may only work in " + "OTG mode (--otg)."); + return false; + } +# endif + if (opts->otg) { // OTG mode is compatible with only very few options. // Only report obvious errors. From d9bc5082ab24d214928be499f70c2aaed107b0df Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Sun, 20 Feb 2022 17:11:07 +0100 Subject: [PATCH 10/10] Disable USB features for win32 Currently, there is an issue with the libusb prebuilt dll. Refs libusb/#1049 PR #3011 --- release.mk | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/release.mk b/release.mk index 00d2389ff7..98b84a8e65 100644 --- a/release.mk +++ b/release.mk @@ -75,10 +75,12 @@ prepare-deps-win64: @app/prebuilt-deps/prepare-libusb.sh build-win32: prepare-deps-win32 + # -Dusb=false because of libusb-win32 build issue, cf #3011 [ -d "$(WIN32_BUILD_DIR)" ] || ( mkdir "$(WIN32_BUILD_DIR)" && \ meson "$(WIN32_BUILD_DIR)" \ --cross-file cross_win32.txt \ --buildtype release --strip -Db_lto=true \ + -Dusb=false \ -Dcompile_server=false \ -Dportable=true ) ninja -C "$(WIN32_BUILD_DIR)" @@ -109,7 +111,7 @@ dist-win32: build-server build-win32 cp app/prebuilt-deps/data/platform-tools-31.0.3/AdbWinApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/" cp app/prebuilt-deps/data/platform-tools-31.0.3/AdbWinUsbApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/" cp app/prebuilt-deps/data/SDL2-2.0.20/i686-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN32_TARGET_DIR)/" - cp app/prebuilt-deps/data/libusb-1.0.25/MinGW32/dll/libusb-1.0.dll "$(DIST)/$(WIN32_TARGET_DIR)/" + #cp app/prebuilt-deps/data/libusb-1.0.25/MinGW32/dll/libusb-1.0.dll "$(DIST)/$(WIN32_TARGET_DIR)/" dist-win64: build-server build-win64 mkdir -p "$(DIST)/$(WIN64_TARGET_DIR)"