Extract mouse HID handling
Split the mouse implementation using AOA and the code handling HID events, so that HID events can be reused for another protocol (UHID).
This commit is contained in:
parent
dd1df43e34
commit
b2ecbcd92e
@ -32,6 +32,7 @@ src = [
|
||||
'src/server.c',
|
||||
'src/version.c',
|
||||
'src/hid/hid_keyboard.c',
|
||||
'src/hid/hid_mouse.c',
|
||||
'src/trait/frame_source.c',
|
||||
'src/trait/packet_source.c',
|
||||
'src/util/acksync.c',
|
||||
@ -90,7 +91,7 @@ if usb_support
|
||||
src += [
|
||||
'src/usb/aoa_hid.c',
|
||||
'src/usb/keyboard_aoa.c',
|
||||
'src/usb/hid_mouse.c',
|
||||
'src/usb/mouse_aoa.c',
|
||||
'src/usb/scrcpy_otg.c',
|
||||
'src/usb/screen_otg.c',
|
||||
'src/usb/usb.c',
|
||||
|
@ -1,15 +1,5 @@
|
||||
#include "hid_mouse.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "input_events.h"
|
||||
#include "util/log.h"
|
||||
|
||||
/** Downcast mouse processor to hid_mouse */
|
||||
#define DOWNCAST(MP) container_of(MP, struct sc_hid_mouse, mouse_processor)
|
||||
|
||||
#define HID_MOUSE_ACCESSORY_ID 2
|
||||
|
||||
// 1 byte for buttons + padding, 1 byte for X position, 1 byte for Y position,
|
||||
// 1 byte for wheel motion
|
||||
#define HID_MOUSE_EVENT_SIZE 4
|
||||
@ -24,7 +14,7 @@
|
||||
* <https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf>
|
||||
* §4 Generic Desktop Page (0x01) (p26)
|
||||
*/
|
||||
static const unsigned char mouse_report_desc[] = {
|
||||
const uint8_t SC_HID_MOUSE_REPORT_DESC[] = {
|
||||
// Usage Page (Generic Desktop)
|
||||
0x05, 0x01,
|
||||
// Usage (Mouse)
|
||||
@ -90,6 +80,9 @@ static const unsigned char mouse_report_desc[] = {
|
||||
0xC0,
|
||||
};
|
||||
|
||||
const size_t SC_HID_MOUSE_REPORT_DESC_LEN =
|
||||
sizeof(SC_HID_MOUSE_REPORT_DESC);
|
||||
|
||||
/**
|
||||
* A mouse HID event is 4 bytes long:
|
||||
*
|
||||
@ -138,9 +131,9 @@ sc_hid_mouse_event_init(struct sc_hid_event *hid_event) {
|
||||
// callers
|
||||
}
|
||||
|
||||
static unsigned char
|
||||
buttons_state_to_hid_buttons(uint8_t buttons_state) {
|
||||
unsigned char c = 0;
|
||||
static uint8_t
|
||||
sc_hid_buttons_from_buttons_state(uint8_t buttons_state) {
|
||||
uint8_t c = 0;
|
||||
if (buttons_state & SC_MOUSE_BUTTON_LEFT) {
|
||||
c |= 1 << 0;
|
||||
}
|
||||
@ -159,55 +152,36 @@ buttons_state_to_hid_buttons(uint8_t buttons_state) {
|
||||
return c;
|
||||
}
|
||||
|
||||
static void
|
||||
sc_mouse_processor_process_mouse_motion(struct sc_mouse_processor *mp,
|
||||
const struct sc_mouse_motion_event *event) {
|
||||
struct sc_hid_mouse *mouse = DOWNCAST(mp);
|
||||
void
|
||||
sc_hid_mouse_event_from_motion(struct sc_hid_event *hid_event,
|
||||
const struct sc_mouse_motion_event *event) {
|
||||
sc_hid_mouse_event_init(hid_event);
|
||||
|
||||
struct sc_hid_event hid_event;
|
||||
sc_hid_mouse_event_init(&hid_event);
|
||||
|
||||
unsigned char *data = hid_event.data;
|
||||
data[0] = buttons_state_to_hid_buttons(event->buttons_state);
|
||||
uint8_t *data = hid_event->data;
|
||||
data[0] = sc_hid_buttons_from_buttons_state(event->buttons_state);
|
||||
data[1] = CLAMP(event->xrel, -127, 127);
|
||||
data[2] = CLAMP(event->yrel, -127, 127);
|
||||
data[3] = 0; // wheel coordinates only used for scrolling
|
||||
|
||||
if (!sc_aoa_push_hid_event(mouse->aoa, HID_MOUSE_ACCESSORY_ID,
|
||||
&hid_event)) {
|
||||
LOGW("Could not request 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_hid_mouse *mouse = DOWNCAST(mp);
|
||||
void
|
||||
sc_hid_mouse_event_from_click(struct sc_hid_event *hid_event,
|
||||
const struct sc_mouse_click_event *event) {
|
||||
sc_hid_mouse_event_init(hid_event);
|
||||
|
||||
struct sc_hid_event hid_event;
|
||||
sc_hid_mouse_event_init(&hid_event);
|
||||
|
||||
unsigned char *data = hid_event.data;
|
||||
data[0] = buttons_state_to_hid_buttons(event->buttons_state);
|
||||
uint8_t *data = hid_event->data;
|
||||
data[0] = sc_hid_buttons_from_buttons_state(event->buttons_state);
|
||||
data[1] = 0; // no x motion
|
||||
data[2] = 0; // no y motion
|
||||
data[3] = 0; // wheel coordinates only used for scrolling
|
||||
|
||||
if (!sc_aoa_push_hid_event(mouse->aoa, HID_MOUSE_ACCESSORY_ID,
|
||||
&hid_event)) {
|
||||
LOGW("Could not request 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_hid_mouse *mouse = DOWNCAST(mp);
|
||||
void
|
||||
sc_hid_mouse_event_from_scroll(struct sc_hid_event *hid_event,
|
||||
const struct sc_mouse_scroll_event *event) {
|
||||
sc_hid_mouse_event_init(hid_event);
|
||||
|
||||
struct sc_hid_event hid_event;
|
||||
sc_hid_mouse_event_init(&hid_event);
|
||||
|
||||
unsigned char *data = hid_event.data;
|
||||
uint8_t *data = hid_event->data;
|
||||
data[0] = 0; // buttons state irrelevant (and unknown)
|
||||
data[1] = 0; // no x motion
|
||||
data[2] = 0; // no y motion
|
||||
@ -215,43 +189,4 @@ sc_mouse_processor_process_mouse_scroll(struct sc_mouse_processor *mp,
|
||||
// are possible
|
||||
data[3] = CLAMP(event->vscroll, -127, 127);
|
||||
// Horizontal scrolling ignored
|
||||
|
||||
if (!sc_aoa_push_hid_event(mouse->aoa, HID_MOUSE_ACCESSORY_ID,
|
||||
&hid_event)) {
|
||||
LOGW("Could not request HID event (mouse scroll)");
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
sc_hid_mouse_init(struct sc_hid_mouse *mouse, struct sc_aoa *aoa) {
|
||||
mouse->aoa = aoa;
|
||||
|
||||
bool ok = sc_aoa_setup_hid(aoa, HID_MOUSE_ACCESSORY_ID, mouse_report_desc,
|
||||
ARRAY_LEN(mouse_report_desc));
|
||||
if (!ok) {
|
||||
LOGW("Register HID mouse failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
sc_hid_mouse_destroy(struct sc_hid_mouse *mouse) {
|
||||
bool ok = sc_aoa_unregister_hid(mouse->aoa, HID_MOUSE_ACCESSORY_ID);
|
||||
if (!ok) {
|
||||
LOGW("Could not unregister HID mouse");
|
||||
}
|
||||
}
|
26
app/src/hid/hid_mouse.h
Normal file
26
app/src/hid/hid_mouse.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef SC_HID_MOUSE_H
|
||||
#define SC_HID_MOUSE_H
|
||||
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "hid/hid_event.h"
|
||||
#include "input_events.h"
|
||||
|
||||
extern const uint8_t SC_HID_MOUSE_REPORT_DESC[];
|
||||
extern const size_t SC_HID_MOUSE_REPORT_DESC_LEN;
|
||||
|
||||
void
|
||||
sc_hid_mouse_event_from_motion(struct sc_hid_event *hid_event,
|
||||
const struct sc_mouse_motion_event *event);
|
||||
|
||||
void
|
||||
sc_hid_mouse_event_from_click(struct sc_hid_event *hid_event,
|
||||
const struct sc_mouse_click_event *event);
|
||||
|
||||
void
|
||||
sc_hid_mouse_event_from_scroll(struct sc_hid_event *hid_event,
|
||||
const struct sc_mouse_scroll_event *event);
|
@ -28,7 +28,7 @@
|
||||
#ifdef HAVE_USB
|
||||
# include "usb/aoa_hid.h"
|
||||
# include "usb/keyboard_aoa.h"
|
||||
# include "usb/hid_mouse.h"
|
||||
# include "usb/mouse_aoa.h"
|
||||
# include "usb/usb.h"
|
||||
#endif
|
||||
#include "util/acksync.h"
|
||||
@ -71,7 +71,7 @@ struct scrcpy {
|
||||
union {
|
||||
struct sc_mouse_inject mouse_inject;
|
||||
#ifdef HAVE_USB
|
||||
struct sc_hid_mouse mouse_hid;
|
||||
struct sc_mouse_aoa mouse_aoa;
|
||||
#endif
|
||||
};
|
||||
struct sc_timeout timeout;
|
||||
@ -331,7 +331,7 @@ scrcpy(struct scrcpy_options *options) {
|
||||
#ifdef HAVE_USB
|
||||
bool aoa_hid_initialized = false;
|
||||
bool keyboard_aoa_initialized = false;
|
||||
bool hid_mouse_initialized = false;
|
||||
bool mouse_aoa_initialized = false;
|
||||
#endif
|
||||
bool controller_initialized = false;
|
||||
bool controller_started = false;
|
||||
@ -545,9 +545,9 @@ scrcpy(struct scrcpy_options *options) {
|
||||
#ifdef HAVE_USB
|
||||
bool use_keyboard_aoa =
|
||||
options->keyboard_input_mode == SC_KEYBOARD_INPUT_MODE_AOA;
|
||||
bool use_aoa_mouse =
|
||||
bool use_mouse_aoa =
|
||||
options->mouse_input_mode == SC_MOUSE_INPUT_MODE_AOA;
|
||||
if (use_keyboard_aoa || use_aoa_mouse) {
|
||||
if (use_keyboard_aoa || use_mouse_aoa) {
|
||||
bool ok = sc_acksync_init(&s->acksync);
|
||||
if (!ok) {
|
||||
goto end;
|
||||
@ -599,16 +599,16 @@ scrcpy(struct scrcpy_options *options) {
|
||||
}
|
||||
}
|
||||
|
||||
if (use_aoa_mouse) {
|
||||
if (sc_hid_mouse_init(&s->mouse_hid, &s->aoa)) {
|
||||
hid_mouse_initialized = true;
|
||||
mp = &s->mouse_hid.mouse_processor;
|
||||
if (use_mouse_aoa) {
|
||||
if (sc_mouse_aoa_init(&s->mouse_aoa, &s->aoa)) {
|
||||
mouse_aoa_initialized = true;
|
||||
mp = &s->mouse_aoa.mouse_processor;
|
||||
} else {
|
||||
LOGE("Could not initialized HID mouse");
|
||||
}
|
||||
}
|
||||
|
||||
bool need_aoa = keyboard_aoa_initialized || hid_mouse_initialized;
|
||||
bool need_aoa = keyboard_aoa_initialized || mouse_aoa_initialized;
|
||||
|
||||
if (!need_aoa || !sc_aoa_start(&s->aoa)) {
|
||||
sc_acksync_destroy(&s->acksync);
|
||||
@ -628,9 +628,9 @@ aoa_hid_end:
|
||||
sc_keyboard_aoa_destroy(&s->keyboard_aoa);
|
||||
keyboard_aoa_initialized = false;
|
||||
}
|
||||
if (hid_mouse_initialized) {
|
||||
sc_hid_mouse_destroy(&s->mouse_hid);
|
||||
hid_mouse_initialized = false;
|
||||
if (mouse_aoa_initialized) {
|
||||
sc_mouse_aoa_destroy(&s->mouse_aoa);
|
||||
mouse_aoa_initialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -639,7 +639,7 @@ aoa_hid_end:
|
||||
options->keyboard_input_mode = SC_KEYBOARD_INPUT_MODE_SDK;
|
||||
}
|
||||
|
||||
if (use_aoa_mouse && !hid_mouse_initialized) {
|
||||
if (use_mouse_aoa && !mouse_aoa_initialized) {
|
||||
LOGE("Fallback to --keyboard=sdk (--keyboard=aoa ignored)");
|
||||
options->mouse_input_mode = SC_MOUSE_INPUT_MODE_SDK;
|
||||
}
|
||||
@ -816,8 +816,8 @@ end:
|
||||
if (keyboard_aoa_initialized) {
|
||||
sc_keyboard_aoa_destroy(&s->keyboard_aoa);
|
||||
}
|
||||
if (hid_mouse_initialized) {
|
||||
sc_hid_mouse_destroy(&s->mouse_hid);
|
||||
if (mouse_aoa_initialized) {
|
||||
sc_mouse_aoa_destroy(&s->mouse_aoa);
|
||||
}
|
||||
sc_aoa_stop(&s->aoa);
|
||||
sc_usb_stop(&s->usb);
|
||||
|
89
app/src/usb/mouse_aoa.c
Normal file
89
app/src/usb/mouse_aoa.c
Normal file
@ -0,0 +1,89 @@
|
||||
#include "mouse_aoa.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "hid/hid_mouse.h"
|
||||
#include "input_events.h"
|
||||
#include "util/log.h"
|
||||
|
||||
/** Downcast mouse processor to mouse_aoa */
|
||||
#define DOWNCAST(MP) container_of(MP, struct sc_mouse_aoa, mouse_processor)
|
||||
|
||||
#define HID_MOUSE_ACCESSORY_ID 2
|
||||
|
||||
static void
|
||||
sc_mouse_processor_process_mouse_motion(struct sc_mouse_processor *mp,
|
||||
const struct sc_mouse_motion_event *event) {
|
||||
struct sc_mouse_aoa *mouse = DOWNCAST(mp);
|
||||
|
||||
struct sc_hid_event hid_event;
|
||||
sc_hid_mouse_event_from_motion(&hid_event, event);
|
||||
|
||||
if (!sc_aoa_push_hid_event(mouse->aoa, HID_MOUSE_ACCESSORY_ID,
|
||||
&hid_event)) {
|
||||
LOGW("Could not request 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_aoa *mouse = DOWNCAST(mp);
|
||||
|
||||
struct sc_hid_event hid_event;
|
||||
sc_hid_mouse_event_from_click(&hid_event, event);
|
||||
|
||||
if (!sc_aoa_push_hid_event(mouse->aoa, HID_MOUSE_ACCESSORY_ID,
|
||||
&hid_event)) {
|
||||
LOGW("Could not request 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_aoa *mouse = DOWNCAST(mp);
|
||||
|
||||
struct sc_hid_event hid_event;
|
||||
sc_hid_mouse_event_from_scroll(&hid_event, event);
|
||||
|
||||
if (!sc_aoa_push_hid_event(mouse->aoa, HID_MOUSE_ACCESSORY_ID,
|
||||
&hid_event)) {
|
||||
LOGW("Could not request HID event (mouse scroll)");
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
sc_mouse_aoa_init(struct sc_mouse_aoa *mouse, struct sc_aoa *aoa) {
|
||||
mouse->aoa = aoa;
|
||||
|
||||
bool ok = sc_aoa_setup_hid(aoa, HID_MOUSE_ACCESSORY_ID,
|
||||
SC_HID_MOUSE_REPORT_DESC,
|
||||
SC_HID_MOUSE_REPORT_DESC_LEN);
|
||||
if (!ok) {
|
||||
LOGW("Register HID mouse failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
sc_mouse_aoa_destroy(struct sc_mouse_aoa *mouse) {
|
||||
bool ok = sc_aoa_unregister_hid(mouse->aoa, HID_MOUSE_ACCESSORY_ID);
|
||||
if (!ok) {
|
||||
LOGW("Could not unregister HID mouse");
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
#ifndef SC_HID_MOUSE_H
|
||||
#define SC_HID_MOUSE_H
|
||||
#ifndef SC_MOUSE_AOA_H
|
||||
#define SC_MOUSE_AOA_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
@ -8,16 +8,16 @@
|
||||
#include "aoa_hid.h"
|
||||
#include "trait/mouse_processor.h"
|
||||
|
||||
struct sc_hid_mouse {
|
||||
struct sc_mouse_aoa {
|
||||
struct sc_mouse_processor mouse_processor; // mouse processor trait
|
||||
|
||||
struct sc_aoa *aoa;
|
||||
};
|
||||
|
||||
bool
|
||||
sc_hid_mouse_init(struct sc_hid_mouse *mouse, struct sc_aoa *aoa);
|
||||
sc_mouse_aoa_init(struct sc_mouse_aoa *mouse, struct sc_aoa *aoa);
|
||||
|
||||
void
|
||||
sc_hid_mouse_destroy(struct sc_hid_mouse *mouse);
|
||||
sc_mouse_aoa_destroy(struct sc_mouse_aoa *mouse);
|
||||
|
||||
#endif
|
@ -11,7 +11,7 @@ struct scrcpy_otg {
|
||||
struct sc_usb usb;
|
||||
struct sc_aoa aoa;
|
||||
struct sc_keyboard_aoa keyboard;
|
||||
struct sc_hid_mouse mouse;
|
||||
struct sc_mouse_aoa mouse;
|
||||
|
||||
struct sc_screen_otg screen_otg;
|
||||
};
|
||||
@ -74,7 +74,7 @@ scrcpy_otg(struct scrcpy_options *options) {
|
||||
enum scrcpy_exit_code ret = SCRCPY_EXIT_FAILURE;
|
||||
|
||||
struct sc_keyboard_aoa *keyboard = NULL;
|
||||
struct sc_hid_mouse *mouse = NULL;
|
||||
struct sc_mouse_aoa *mouse = NULL;
|
||||
bool usb_device_initialized = false;
|
||||
bool usb_connected = false;
|
||||
bool aoa_started = false;
|
||||
@ -136,7 +136,7 @@ scrcpy_otg(struct scrcpy_options *options) {
|
||||
}
|
||||
|
||||
if (enable_mouse) {
|
||||
ok = sc_hid_mouse_init(&s->mouse, &s->aoa);
|
||||
ok = sc_mouse_aoa_init(&s->mouse, &s->aoa);
|
||||
if (!ok) {
|
||||
goto end;
|
||||
}
|
||||
@ -185,7 +185,7 @@ end:
|
||||
sc_usb_stop(&s->usb);
|
||||
|
||||
if (mouse) {
|
||||
sc_hid_mouse_destroy(&s->mouse);
|
||||
sc_mouse_aoa_destroy(&s->mouse);
|
||||
}
|
||||
if (keyboard) {
|
||||
sc_keyboard_aoa_destroy(&s->keyboard);
|
||||
|
@ -7,11 +7,11 @@
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#include "keyboard_aoa.h"
|
||||
#include "hid_mouse.h"
|
||||
#include "mouse_aoa.h"
|
||||
|
||||
struct sc_screen_otg {
|
||||
struct sc_keyboard_aoa *keyboard;
|
||||
struct sc_hid_mouse *mouse;
|
||||
struct sc_mouse_aoa *mouse;
|
||||
|
||||
SDL_Window *window;
|
||||
SDL_Renderer *renderer;
|
||||
@ -23,7 +23,7 @@ struct sc_screen_otg {
|
||||
|
||||
struct sc_screen_otg_params {
|
||||
struct sc_keyboard_aoa *keyboard;
|
||||
struct sc_hid_mouse *mouse;
|
||||
struct sc_mouse_aoa *mouse;
|
||||
|
||||
const char *window_title;
|
||||
bool always_on_top;
|
||||
|
Loading…
x
Reference in New Issue
Block a user