Add UHID mouse support
Use the following command: scrcpy --mouse=uhid
This commit is contained in:
parent
759cda1fe4
commit
f52c371cc7
@ -120,7 +120,7 @@ _scrcpy() {
|
||||
return
|
||||
;;
|
||||
--mouse)
|
||||
COMPREPLY=($(compgen -W 'disabled sdk aoa' -- "$cur"))
|
||||
COMPREPLY=($(compgen -W 'disabled sdk uhid aoa' -- "$cur"))
|
||||
return
|
||||
;;
|
||||
--orientation|--display-orientation)
|
||||
|
@ -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 uhid aoa)'
|
||||
{-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',
|
||||
|
@ -242,13 +242,14 @@ Limit the framerate of screen capture (officially supported since Android 10, bu
|
||||
.BI "\-\-mouse " mode
|
||||
Select how to send mouse inputs to the device.
|
||||
|
||||
Possible values are "disabled", "sdk" and "aoa":
|
||||
Possible values are "disabled", "sdk", "uhid" and "aoa":
|
||||
|
||||
- "disabled" does not send mouse inputs to the device.
|
||||
- "sdk" uses the Android system API to deliver mouse events to applications.
|
||||
- "uhid" simulates a physical HID mouse using the Linux HID kernel module on the device.
|
||||
- "aoa" simulates a physical mouse using the AOAv2 protocol. It may only work over USB.
|
||||
|
||||
In "aoa" mode, the computer mouse is captured to control the device directly (relative mouse mode).
|
||||
In "uhid" and "aoa" 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.
|
||||
|
||||
|
@ -462,14 +462,17 @@ static const struct sc_option options[] = {
|
||||
.longopt = "mouse",
|
||||
.argdesc = "mode",
|
||||
.text = "Select how to send mouse inputs to the device.\n"
|
||||
"Possible values are \"disabled\", \"sdk\" and \"aoa\".\n"
|
||||
"Possible values are \"disabled\", \"sdk\", \"uhid\" and "
|
||||
"\"aoa\".\n"
|
||||
"\"disabled\" does not send mouse inputs to the device.\n"
|
||||
"\"sdk\" uses the Android system API to deliver mouse\n"
|
||||
"events to applications.\n"
|
||||
"\"uhid\" simulates a physical HID mouse using the Linux UHID "
|
||||
"kernel module on the device."
|
||||
"\"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"
|
||||
"In \"uhid\" and \"aoa\" 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.",
|
||||
@ -1979,6 +1982,11 @@ parse_mouse(const char *optarg, enum sc_mouse_input_mode *mode) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!strcmp(optarg, "uhid")) {
|
||||
*mode = SC_MOUSE_INPUT_MODE_UHID;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!strcmp(optarg, "aoa")) {
|
||||
#ifdef HAVE_USB
|
||||
*mode = SC_MOUSE_INPUT_MODE_AOA;
|
||||
@ -1989,7 +1997,7 @@ parse_mouse(const char *optarg, enum sc_mouse_input_mode *mode) {
|
||||
#endif
|
||||
}
|
||||
|
||||
LOGE("Unsupported mouse: %s (expected disabled, sdk or aoa)", optarg);
|
||||
LOGE("Unsupported mouse: %s (expected disabled, sdk, uhid or aoa)", optarg);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -151,6 +151,7 @@ enum sc_mouse_input_mode {
|
||||
SC_MOUSE_INPUT_MODE_AUTO,
|
||||
SC_MOUSE_INPUT_MODE_DISABLED,
|
||||
SC_MOUSE_INPUT_MODE_SDK,
|
||||
SC_MOUSE_INPUT_MODE_UHID,
|
||||
SC_MOUSE_INPUT_MODE_AOA,
|
||||
};
|
||||
|
||||
|
@ -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"
|
||||
@ -73,6 +74,7 @@ struct scrcpy {
|
||||
};
|
||||
union {
|
||||
struct sc_mouse_sdk mouse_sdk;
|
||||
struct sc_mouse_uhid mouse_uhid;
|
||||
#ifdef HAVE_USB
|
||||
struct sc_mouse_aoa mouse_aoa;
|
||||
#endif
|
||||
@ -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
89
app/src/uhid/mouse_uhid.c
Normal 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
19
app/src/uhid/mouse_uhid.h
Normal 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
|
Loading…
x
Reference in New Issue
Block a user