Skip to content

Commit

Permalink
Use existing --serial to replace --usb
Browse files Browse the repository at this point in the history
  • Loading branch information
AlynxZhou committed Sep 11, 2021
1 parent 1290712 commit 60fd7a5
Show file tree
Hide file tree
Showing 9 changed files with 63 additions and 77 deletions.
13 changes: 0 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,19 +207,6 @@ scrcpy --crop 1224:1440:0:0 # 1224x1440 at offset (0,0)

If `--max-size` is also specified, resizing is applied after cropping.

#### USB HID over AoAv2

Scrcpy can simulate a USB physical keyboard on Android to provide better input
experience, to use this feature you need to find your Android device's USB ID.
Then run it with `--usb` argument.

```bash
scrcpy --usb 04e8:6861
```

USB ID can be found via lsusb. It will fallback to inject mode if HID over AoAv2
failed to set up.

#### Lock video orientation


Expand Down
6 changes: 0 additions & 6 deletions app/scrcpy.1
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,6 @@ Limit both the width and height of the video to \fIvalue\fR. The other dimension

Default is 0 (unlimited).

.TP
.BI "\-u, \-\-usb " vid:pid
Specify the USB ID of Android device to simulate a physical keyboard via HID over AoAv2, provide better input experience than inject mode.

The USB ID of Android device can be found via lsusb.

.TP
.B \-n, \-\-no\-control
Disable device control (mirror the device in read\-only).
Expand Down
7 changes: 7 additions & 0 deletions app/src/adb.c
Original file line number Diff line number Diff line change
Expand Up @@ -224,3 +224,10 @@ adb_install(const char *serial, const char *local) {

return proc;
}

process_t
adb_get_serialno(const char *serial) {
const char *const adb_cmd[] = {"get-serialno"};
process_t proc = adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd));
return proc;
}
3 changes: 3 additions & 0 deletions app/src/adb.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,7 @@ adb_push(const char *serial, const char *local, const char *remote);
process_t
adb_install(const char *serial, const char *local);

process_t
adb_get_serialno(const char *serial);

#endif
57 changes: 46 additions & 11 deletions app/src/aoa_hid.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,58 @@

#define DEFAULT_TIMEOUT 1000

inline static void print_libusb_error(enum libusb_error errcode) {
// 128 seems to be enough for serial.
#define SERIAL_BUFFER_SIZE 128

inline static void log_libusb_error(enum libusb_error errcode) {
LOGW("libusb error: %s", libusb_strerror(errcode));
}

libusb_device *aoa_find_usb_device(uint16_t vid, uint16_t pid) {
inline static int
get_usb_serial(libusb_device *device, char *buffer, int size) {
libusb_device_handle *handle;
int result = libusb_open(device, &handle);
if (result < 0) {
log_libusb_error((enum libusb_error)result);
return result;
}

struct libusb_device_descriptor desc;
libusb_get_device_descriptor(device, &desc);
if (!desc.iSerialNumber) {
libusb_close(handle);
LOGW("USB device %04x:%04x has no serial number",
desc.idVendor, desc.idProduct);
return 1;
}

result = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber,
(unsigned char *)buffer, size);
if (result < 0) {
log_libusb_error((enum libusb_error)result);
libusb_close(handle);
return result;
}

libusb_close(handle);
buffer[SERIAL_BUFFER_SIZE - 1] = '\0';
return 0;
}

libusb_device *aoa_find_usb_device(const char *serial) {
libusb_device **list;
libusb_device *result = NULL;
ssize_t count = libusb_get_device_list(NULL, &list);
if (count < 0) {
print_libusb_error((enum libusb_error)count);
log_libusb_error((enum libusb_error)count);
return NULL;
}

char buffer[SERIAL_BUFFER_SIZE];
for (ssize_t i = 0; i < count; ++i) {
libusb_device *device = list[i];
struct libusb_device_descriptor desc;
libusb_get_device_descriptor(device, &desc);
if (vid == desc.idVendor && pid == desc.idProduct) {
int error = get_usb_serial(device, buffer, SERIAL_BUFFER_SIZE);
if (!error && !strcmp(buffer, serial)) {
result = libusb_ref_device(device);
break;
}
Expand All @@ -37,7 +72,7 @@ libusb_device *aoa_find_usb_device(uint16_t vid, uint16_t pid) {
int aoa_open_usb_handle(libusb_device *device, libusb_device_handle **handle) {
int result = libusb_open(device, handle);
if (result < 0) {
print_libusb_error((enum libusb_error)result);
log_libusb_error((enum libusb_error)result);
return result;
}
return 0;
Expand All @@ -56,7 +91,7 @@ int aoa_register_hid(libusb_device_handle *handle, uint16_t report_desc_size) {
int result = libusb_control_transfer(handle, request_type, request, value,
index, buffer, length, DEFAULT_TIMEOUT);
if (result < 0) {
print_libusb_error((enum libusb_error)result);
log_libusb_error((enum libusb_error)result);
return result;
}
return 0;
Expand All @@ -75,7 +110,7 @@ int aoa_unregister_hid(libusb_device_handle *handle) {
int result = libusb_control_transfer(handle, request_type, request, value,
index, buffer, length, DEFAULT_TIMEOUT);
if (result < 0) {
print_libusb_error((enum libusb_error)result);
log_libusb_error((enum libusb_error)result);
return result;
}
return 0;
Expand Down Expand Up @@ -111,7 +146,7 @@ aoa_set_hid_report_desc(libusb_device_handle *handle,
value, offset, buffer + offset, packet_length, DEFAULT_TIMEOUT);
offset += packet_length;
if (result < 0) {
print_libusb_error((enum libusb_error)result);
log_libusb_error((enum libusb_error)result);
return result;
}
}
Expand All @@ -134,7 +169,7 @@ aoa_send_hid_event(libusb_device_handle *handle,
int result = libusb_control_transfer(handle, request_type, request, value,
index, buffer, length, DEFAULT_TIMEOUT);
if (result < 0) {
print_libusb_error((enum libusb_error)result);
log_libusb_error((enum libusb_error)result);
return result;
}
return 0;
Expand Down
2 changes: 1 addition & 1 deletion app/src/aoa_hid.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ struct hid_event {
uint16_t size;
};

libusb_device *aoa_find_usb_device(uint16_t vid, uint16_t pid);
libusb_device *aoa_find_usb_device(const char *serial);
int aoa_open_usb_handle(libusb_device *device, libusb_device_handle **handle);
int aoa_register_hid(libusb_device_handle *handle, uint16_t report_desc_size);
int aoa_unregister_hid(libusb_device_handle *handle);
Expand Down
38 changes: 1 addition & 37 deletions app/src/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,6 @@ scrcpy_print_usage(const char *arg0) {
" is preserved.\n"
" Default is 0 (unlimited).\n"
"\n"
" -u, --usb vid:pid\n"
" Specify the USB ID of Android device to simulate a physical\n"
" keyboard via HID over AoAv2, provide better input experience\n"
" than inject mode.\n"
" The USB ID of Android device can be found via lsusb.\n"
"\n"
" -n, --no-control\n"
" Disable device control (mirror the device in read-only).\n"
"\n"
Expand Down Expand Up @@ -537,29 +531,6 @@ parse_display_id(const char *s, uint32_t *display_id) {
return true;
}

static bool
parse_usb_id(char *s, uint16_t *vid, uint16_t *pid) {
if (strlen(s) == 0) {
LOGE("USB ID parameter is empty");
return false;
}
uint32_t v;
uint32_t p;
int result = sscanf(s, "%x:%x", &v, &p);
if (result != 2) {
LOGE("Invalid USB ID: %s", s);
return false;
}
if ((v & ~0xffff) || (p & ~0xffff)) {
LOGE("USB ID out of range: %s", s);
return false;
}

*vid = (uint16_t)v;
*pid = (uint16_t)p;
return true;
}

static bool
parse_log_level(const char *s, enum sc_log_level *log_level) {
if (!strcmp(s, "verbose")) {
Expand Down Expand Up @@ -772,7 +743,6 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
OPT_LOCK_VIDEO_ORIENTATION},
{"max-fps", required_argument, NULL, OPT_MAX_FPS},
{"max-size", required_argument, NULL, 'm'},
{"usb", required_argument, NULL, 'u'},
{"no-control", no_argument, NULL, 'n'},
{"no-display", no_argument, NULL, 'N'},
{"no-key-repeat", no_argument, NULL, OPT_NO_KEY_REPEAT},
Expand Down Expand Up @@ -814,7 +784,7 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
optind = 0; // reset to start from the first argument in tests

int c;
while ((c = getopt_long(argc, argv, "b:c:fF:hm:u:nNp:r:s:StTvV:w",
while ((c = getopt_long(argc, argv, "b:c:fF:hm:nNp:r:s:StTvV:w",
long_options, NULL)) != -1) {
switch (c) {
case 'b':
Expand Down Expand Up @@ -857,12 +827,6 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
return false;
}
break;
case 'u':
if (!parse_usb_id(optarg, &opts->usb_vid, &opts->usb_pid)) {
return false;
}
opts->use_hid_over_aoa = true;
break;
case OPT_LOCK_VIDEO_ORIENTATION:
if (!parse_lock_video_orientation(optarg,
&opts->lock_video_orientation)) {
Expand Down
10 changes: 5 additions & 5 deletions app/src/scrcpy.c
Original file line number Diff line number Diff line change
Expand Up @@ -419,14 +419,13 @@ scrcpy(const struct scrcpy_options *options) {
libusb_device_handle *usb_handle = NULL;
libusb_device *usb_device = NULL;

if (options->use_hid_over_aoa) {
if (options->serial) {
LOGD("USB serial provided, starting in HID over AoAv2 mode");
s->input_manager.use_hid_over_aoa = true;
libusb_init(NULL);
usb_device = aoa_find_usb_device(options->usb_vid,
options->usb_pid);
usb_device = aoa_find_usb_device(options->serial);
if (!usb_device) {
LOGW("USB device %04x:%04x not found", options->usb_vid,
options->usb_pid);
LOGW("USB device of serial %s not found", options->serial);
LOGW("Fallback to inject mode");
s->input_manager.use_hid_over_aoa = false;
}
Expand Down Expand Up @@ -467,6 +466,7 @@ scrcpy(const struct scrcpy_options *options) {

// Finally successfully set up HID over AoAv2.
if (s->input_manager.use_hid_over_aoa) {
LOGD("Successfully set up HID over AoAv2 mode");
s->input_manager.usb_handle = usb_handle;
}

Expand Down
4 changes: 0 additions & 4 deletions app/src/scrcpy.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,8 @@ struct scrcpy_options {
uint16_t window_width;
uint16_t window_height;
uint32_t display_id;
uint16_t usb_vid;
uint16_t usb_pid;
sc_tick display_buffer;
sc_tick v4l2_buffer;
bool use_hid_over_aoa;
bool show_touches;
bool fullscreen;
bool always_on_top;
Expand Down Expand Up @@ -135,7 +132,6 @@ struct scrcpy_options {
.display_id = 0, \
.display_buffer = 0, \
.v4l2_buffer = 0, \
.use_hid_over_aoa = false, \
.show_touches = false, \
.fullscreen = false, \
.always_on_top = false, \
Expand Down

0 comments on commit 60fd7a5

Please sign in to comment.