Skip to content

Commit

Permalink
Add UHID mouse support
Browse files Browse the repository at this point in the history
Use the following command:

    scrcpy --mouse=uhid
  • Loading branch information
rom1v committed Feb 26, 2024
1 parent fec2abe commit 0b25cef
Show file tree
Hide file tree
Showing 9 changed files with 132 additions and 6 deletions.
2 changes: 1 addition & 1 deletion app/data/bash-completion/scrcpy
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ _scrcpy() {
return
;;
--mouse)
COMPREPLY=($(compgen -W 'disabled sdk aoa' -- "$cur"))
COMPREPLY=($(compgen -W 'disabled sdk aoa uhid' -- "$cur"))
return
;;
--orientation|--display-orientation)
Expand Down
2 changes: 1 addition & 1 deletion app/data/zsh-completion/_scrcpy
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ arguments=(
'--lock-video-orientation=[Lock video orientation]:orientation:(unlocked initial 0 90 180 270)'
{-m,--max-size=}'[Limit both the width and height of the video to value]'
'--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]'
Expand Down
1 change: 1 addition & 0 deletions app/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
3 changes: 2 additions & 1 deletion app/scrcpy.1
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
13 changes: 10 additions & 3 deletions app/src/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.",
Expand Down Expand Up @@ -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;
}

Expand Down
1 change: 1 addition & 0 deletions app/src/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
8 changes: 8 additions & 0 deletions app/src/scrcpy.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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;
};
Expand Down Expand Up @@ -681,6 +683,12 @@ scrcpy(struct scrcpy_options *options) {
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);
Expand Down
89 changes: 89 additions & 0 deletions app/src/uhid/mouse_uhid.c
Original file line number Diff line number Diff line change
@@ -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;
}
19 changes: 19 additions & 0 deletions app/src/uhid/mouse_uhid.h
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 0b25cef

Please sign in to comment.