Add UHID mouse support

Use the following command:

    scrcpy --mouse=uhid
uhid.25
Romain Vimont 3 months ago
parent 038f6c55e9
commit 18628fdcfa

@ -121,7 +121,7 @@ _scrcpy() {
return
;;
--mouse)
COMPREPLY=($(compgen -W 'disabled sdk aoa' -- "$cur"))
COMPREPLY=($(compgen -W 'disabled sdk aoa uhid' -- "$cur"))
return
;;
--orientation|--display-orientation)

@ -45,7 +45,7 @@ arguments=(
{-m,--max-size=}'[Limit both the width and height of the video to value]'
{-M,--hid-mouse}'[Simulate a physical mouse by using HID over AOAv2]'
'--max-fps=[Limit the frame rate of screen capture]'
'--mouse[Set the mouse input mode]:mode:(disabled sdk aoa)'
'--mouse[Set the mouse input mode]:mode:(disabled sdk aoa uhid)'
{-n,--no-control}'[Disable device control \(mirror the device in read only\)]'
{-N,--no-playback}'[Disable video and audio playback]'
'--no-audio[Disable audio forwarding]'

@ -36,6 +36,7 @@ src = [
'src/trait/frame_source.c',
'src/trait/packet_source.c',
'src/uhid/keyboard_uhid.c',
'src/uhid/mouse_uhid.c',
'src/uhid/uhid_output.c',
'src/util/acksync.c',
'src/util/audiobuf.c',

@ -247,8 +247,9 @@ Possible values are "disabled", "sdk" and "aoa":
- "disabled" does not send mouse inputs to the device.
- "sdk" uses the Android system API to deliver mouse events to applications.
- "aoa" simulates a physical mouse using the AOAv2 protocol. It may only work over USB.
- "uhid" simulates a physical HID mouse using the Linux HID kernel module on the device.
In "aoa" mode, the computer mouse is captured to control the device directly (relative mouse mode).
In "aoa" and "uhid" modes, the computer mouse is captured to control the device directly (relative mouse mode).
LAlt, LSuper or RSuper toggle the capture mode, to give control of the mouse back to the computer.

@ -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;
}

@ -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 {

@ -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);

@ -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 *kb,
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(kb->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;
}

@ -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
Loading…
Cancel
Save