diff --git a/app/meson.build b/app/meson.build index 6d572b7b..f78afa15 100644 --- a/app/meson.build +++ b/app/meson.build @@ -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', diff --git a/app/src/usb/hid_mouse.c b/app/src/hid/hid_mouse.c similarity index 59% rename from app/src/usb/hid_mouse.c rename to app/src/hid/hid_mouse.c index de961265..9d814448 100644 --- a/app/src/usb/hid_mouse.c +++ b/app/src/hid/hid_mouse.c @@ -1,15 +1,5 @@ #include "hid_mouse.h" -#include - -#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 @@ * * ยง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); - - struct sc_hid_event hid_event; - sc_hid_mouse_event_init(&hid_event); +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); - 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); - - struct sc_hid_event hid_event; - sc_hid_mouse_event_init(&hid_event); +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); - 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); - - struct sc_hid_event hid_event; - sc_hid_mouse_event_init(&hid_event); +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); - 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"); - } } diff --git a/app/src/hid/hid_mouse.h b/app/src/hid/hid_mouse.h new file mode 100644 index 00000000..e514d7d9 --- /dev/null +++ b/app/src/hid/hid_mouse.h @@ -0,0 +1,26 @@ +#ifndef SC_HID_MOUSE_H +#define SC_HID_MOUSE_H + +#endif + +#include "common.h" + +#include + +#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); diff --git a/app/src/scrcpy.c b/app/src/scrcpy.c index 1d5e67dc..bd448052 100644 --- a/app/src/scrcpy.c +++ b/app/src/scrcpy.c @@ -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); diff --git a/app/src/usb/mouse_aoa.c b/app/src/usb/mouse_aoa.c new file mode 100644 index 00000000..93b32328 --- /dev/null +++ b/app/src/usb/mouse_aoa.c @@ -0,0 +1,89 @@ +#include "mouse_aoa.h" + +#include + +#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"); + } +} diff --git a/app/src/usb/hid_mouse.h b/app/src/usb/mouse_aoa.h similarity index 55% rename from app/src/usb/hid_mouse.h rename to app/src/usb/mouse_aoa.h index b89f7795..afaed761 100644 --- a/app/src/usb/hid_mouse.h +++ b/app/src/usb/mouse_aoa.h @@ -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 diff --git a/app/src/usb/scrcpy_otg.c b/app/src/usb/scrcpy_otg.c index 9064ad10..c1d38da3 100644 --- a/app/src/usb/scrcpy_otg.c +++ b/app/src/usb/scrcpy_otg.c @@ -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); diff --git a/app/src/usb/screen_otg.h b/app/src/usb/screen_otg.h index cfc3bfa2..c4e03b87 100644 --- a/app/src/usb/screen_otg.h +++ b/app/src/usb/screen_otg.h @@ -7,11 +7,11 @@ #include #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;