Add UHID mouse support

Use the following command:

    scrcpy --mouse=uhid
This commit is contained in:
Romain Vimont
2024-02-25 15:43:36 +01:00
parent 27edeeb248
commit 9db64f83a4
9 changed files with 132 additions and 6 deletions

View File

@@ -468,8 +468,10 @@ static const struct sc_option options[] = {
"events to applications.\n"
"\"aoa\" simulates a physical mouse using the AOAv2 protocol\n"
"It may only work over USB.\n"
"In \"aoa\" mode, the computer mouse is captured to control "
"the device directly (relative mouse mode).\n"
"\"uhid\" simulates a physical HID mouse using the Linux UHID "
"kernel module on the device."
"In \"aoa\" and \"uhid\" modes, the computer mouse is captured "
"to control the device directly (relative mouse mode).\n"
"LAlt, LSuper or RSuper toggle the capture mode, to give "
"control of the mouse back to the computer.\n"
"Also see --keyboard.",
@@ -1989,7 +1991,12 @@ parse_mouse(const char *optarg, enum sc_mouse_input_mode *mode) {
#endif
}
LOGE("Unsupported mouse: %s (expected disabled, sdk or aoa)", optarg);
if (!strcmp(optarg, "uhid")) {
*mode = SC_MOUSE_INPUT_MODE_UHID;
return true;
}
LOGE("Unsupported mouse: %s (expected disabled, sdk, aoa or uhid)", optarg);
return false;
}

View File

@@ -152,6 +152,7 @@ enum sc_mouse_input_mode {
SC_MOUSE_INPUT_MODE_DISABLED,
SC_MOUSE_INPUT_MODE_SDK,
SC_MOUSE_INPUT_MODE_AOA,
SC_MOUSE_INPUT_MODE_UHID,
};
enum sc_key_inject_mode {

View File

@@ -26,6 +26,7 @@
#include "screen.h"
#include "server.h"
#include "uhid/keyboard_uhid.h"
#include "uhid/mouse_uhid.h"
#ifdef HAVE_USB
# include "usb/aoa_hid.h"
# include "usb/keyboard_aoa.h"
@@ -76,6 +77,7 @@ struct scrcpy {
#ifdef HAVE_USB
struct sc_mouse_aoa mouse_aoa;
#endif
struct sc_mouse_uhid mouse_uhid;
};
struct sc_timeout timeout;
};
@@ -681,6 +683,12 @@ aoa_hid_end:
if (options->mouse_input_mode == SC_MOUSE_INPUT_MODE_SDK) {
sc_mouse_sdk_init(&s->mouse_sdk, &s->controller);
mp = &s->mouse_sdk.mouse_processor;
} else if (options->mouse_input_mode == SC_MOUSE_INPUT_MODE_UHID) {
bool ok = sc_mouse_uhid_init(&s->mouse_uhid, &s->controller);
if (!ok) {
goto end;
}
mp = &s->mouse_uhid.mouse_processor;
}
sc_controller_configure(&s->controller, acksync, uhid_devices);

89
app/src/uhid/mouse_uhid.c Normal file
View File

@@ -0,0 +1,89 @@
#include "mouse_uhid.h"
#include "hid/hid_mouse.h"
#include "input_events.h"
#include "util/log.h"
/** Downcast mouse processor to mouse_uhid */
#define DOWNCAST(MP) container_of(MP, struct sc_mouse_uhid, mouse_processor)
#define UHID_MOUSE_ID 2
static void
sc_mouse_uhid_send_input(struct sc_mouse_uhid *mouse,
const struct sc_hid_event *event, const char *name) {
struct sc_control_msg msg;
msg.type = SC_CONTROL_MSG_TYPE_UHID_INPUT;
msg.uhid_input.id = UHID_MOUSE_ID;
assert(event->size <= SC_HID_MAX_SIZE);
memcpy(msg.uhid_input.data, event->data, event->size);
msg.uhid_input.size = event->size;
if (!sc_controller_push_msg(mouse->controller, &msg)) {
LOGE("Could not send UHID_INPUT message (%s)", name);
}
}
static void
sc_mouse_processor_process_mouse_motion(struct sc_mouse_processor *mp,
const struct sc_mouse_motion_event *event) {
struct sc_mouse_uhid *mouse = DOWNCAST(mp);
struct sc_hid_event hid_event;
sc_hid_mouse_event_from_motion(&hid_event, event);
sc_mouse_uhid_send_input(mouse, &hid_event, "mouse motion");
}
static void
sc_mouse_processor_process_mouse_click(struct sc_mouse_processor *mp,
const struct sc_mouse_click_event *event) {
struct sc_mouse_uhid *mouse = DOWNCAST(mp);
struct sc_hid_event hid_event;
sc_hid_mouse_event_from_click(&hid_event, event);
sc_mouse_uhid_send_input(mouse, &hid_event, "mouse click");
}
static void
sc_mouse_processor_process_mouse_scroll(struct sc_mouse_processor *mp,
const struct sc_mouse_scroll_event *event) {
struct sc_mouse_uhid *mouse = DOWNCAST(mp);
struct sc_hid_event hid_event;
sc_hid_mouse_event_from_scroll(&hid_event, event);
sc_mouse_uhid_send_input(mouse, &hid_event, "mouse scroll");
}
bool
sc_mouse_uhid_init(struct sc_mouse_uhid *mouse,
struct sc_controller *controller) {
mouse->controller = controller;
static const struct sc_mouse_processor_ops ops = {
.process_mouse_motion = sc_mouse_processor_process_mouse_motion,
.process_mouse_click = sc_mouse_processor_process_mouse_click,
.process_mouse_scroll = sc_mouse_processor_process_mouse_scroll,
// Touch events not supported (coordinates are not relative)
.process_touch = NULL,
};
mouse->mouse_processor.ops = &ops;
mouse->mouse_processor.relative_mode = true;
struct sc_control_msg msg;
msg.type = SC_CONTROL_MSG_TYPE_UHID_CREATE;
msg.uhid_create.id = UHID_MOUSE_ID;
msg.uhid_create.report_desc = SC_HID_MOUSE_REPORT_DESC;
msg.uhid_create.report_desc_size = SC_HID_MOUSE_REPORT_DESC_LEN;
if (!sc_controller_push_msg(controller, &msg)) {
LOGE("Could not send UHID_CREATE message (mouse)");
return false;
}
return true;
}

19
app/src/uhid/mouse_uhid.h Normal file
View File

@@ -0,0 +1,19 @@
#ifndef SC_MOUSE_UHID_H
#define SC_MOUSE_UHID_H
#include <stdbool.h>
#include "controller.h"
#include "trait/mouse_processor.h"
struct sc_mouse_uhid {
struct sc_mouse_processor mouse_processor; // mouse processor trait
struct sc_controller *controller;
};
bool
sc_mouse_uhid_init(struct sc_mouse_uhid *mouse,
struct sc_controller *controller);
#endif