Embed HID event data

In the implementation, an HID event is at most 8 bytes. Embed the data
in the HID event structure to avoid allocations and simplify the code.

PR #4473 <https://github.com/Genymobile/scrcpy/pull/4473>
uhid.38
Romain Vimont 4 months ago
parent ae303b8d07
commit 2d32557fde

@ -33,20 +33,6 @@ sc_hid_event_log(const struct sc_hid_event *event) {
free(buffer); free(buffer);
} }
void
sc_hid_event_init(struct sc_hid_event *hid_event, uint16_t accessory_id,
unsigned char *data, uint16_t size) {
hid_event->accessory_id = accessory_id;
hid_event->data = data;
hid_event->size = size;
hid_event->ack_to_wait = SC_SEQUENCE_INVALID;
}
void
sc_hid_event_destroy(struct sc_hid_event *hid_event) {
free(hid_event->data);
}
bool bool
sc_aoa_init(struct sc_aoa *aoa, struct sc_usb *usb, sc_aoa_init(struct sc_aoa *aoa, struct sc_usb *usb,
struct sc_acksync *acksync) { struct sc_acksync *acksync) {
@ -76,12 +62,7 @@ sc_aoa_init(struct sc_aoa *aoa, struct sc_usb *usb,
void void
sc_aoa_destroy(struct sc_aoa *aoa) { sc_aoa_destroy(struct sc_aoa *aoa) {
// Destroy remaining events sc_vecdeque_destroy(&aoa->queue);
while (!sc_vecdeque_is_empty(&aoa->queue)) {
struct sc_hid_event *event = sc_vecdeque_popref(&aoa->queue);
assert(event);
sc_hid_event_destroy(event);
}
sc_cond_destroy(&aoa->event_cond); sc_cond_destroy(&aoa->event_cond);
sc_mutex_destroy(&aoa->mutex); sc_mutex_destroy(&aoa->mutex);
@ -177,7 +158,7 @@ sc_aoa_send_hid_event(struct sc_aoa *aoa, const struct sc_hid_event *event) {
// index (arg1): 0 (unused) // index (arg1): 0 (unused)
uint16_t value = event->accessory_id; uint16_t value = event->accessory_id;
uint16_t index = 0; uint16_t index = 0;
unsigned char *data = event->data; unsigned char *data = (uint8_t *) event->data; // discard const
uint16_t length = event->size; uint16_t length = event->size;
int result = libusb_control_transfer(aoa->usb->handle, request_type, int result = libusb_control_transfer(aoa->usb->handle, request_type,
request, value, index, data, length, request, value, index, data, length,
@ -271,17 +252,14 @@ run_aoa_thread(void *data) {
if (result == SC_ACKSYNC_WAIT_TIMEOUT) { if (result == SC_ACKSYNC_WAIT_TIMEOUT) {
LOGW("Ack not received after 500ms, discarding HID event"); LOGW("Ack not received after 500ms, discarding HID event");
sc_hid_event_destroy(&event);
continue; continue;
} else if (result == SC_ACKSYNC_WAIT_INTR) { } else if (result == SC_ACKSYNC_WAIT_INTR) {
// stopped // stopped
sc_hid_event_destroy(&event);
break; break;
} }
} }
bool ok = sc_aoa_send_hid_event(aoa, &event); bool ok = sc_aoa_send_hid_event(aoa, &event);
sc_hid_event_destroy(&event);
if (!ok) { if (!ok) {
LOGW("Could not send HID event to USB device"); LOGW("Could not send HID event to USB device");
} }

@ -12,21 +12,15 @@
#include "util/tick.h" #include "util/tick.h"
#include "util/vecdeque.h" #include "util/vecdeque.h"
#define SC_HID_MAX_SIZE 8
struct sc_hid_event { struct sc_hid_event {
uint16_t accessory_id; uint16_t accessory_id;
unsigned char *data; uint8_t data[SC_HID_MAX_SIZE];
uint16_t size; uint8_t size;
uint64_t ack_to_wait; uint64_t ack_to_wait;
}; };
// Takes ownership of buffer
void
sc_hid_event_init(struct sc_hid_event *hid_event, uint16_t accessory_id,
unsigned char *data, uint16_t size);
void
sc_hid_event_destroy(struct sc_hid_event *hid_event);
struct sc_hid_event_queue SC_VECDEQUE(struct sc_hid_event); struct sc_hid_event_queue SC_VECDEQUE(struct sc_hid_event);
struct sc_aoa { struct sc_aoa {

@ -231,21 +231,17 @@ sdl_keymod_to_hid_modifiers(uint16_t mod) {
return modifiers; return modifiers;
} }
static bool static void
sc_hid_keyboard_event_init(struct sc_hid_event *hid_event) { sc_hid_keyboard_event_init(struct sc_hid_event *hid_event) {
unsigned char *data = malloc(HID_KEYBOARD_EVENT_SIZE); hid_event->accessory_id = HID_KEYBOARD_ACCESSORY_ID;
if (!data) { hid_event->size = HID_KEYBOARD_EVENT_SIZE;
LOG_OOM(); hid_event->ack_to_wait = SC_SEQUENCE_INVALID;
return false;
} uint8_t *data = hid_event->data;
data[HID_KEYBOARD_INDEX_MODIFIER] = HID_MODIFIER_NONE; data[HID_KEYBOARD_INDEX_MODIFIER] = HID_MODIFIER_NONE;
data[1] = HID_RESERVED; data[1] = HID_RESERVED;
memset(&data[HID_KEYBOARD_INDEX_KEYS], 0, HID_KEYBOARD_MAX_KEYS); memset(&data[HID_KEYBOARD_INDEX_KEYS], 0, HID_KEYBOARD_MAX_KEYS);
sc_hid_event_init(hid_event, HID_KEYBOARD_ACCESSORY_ID, data,
HID_KEYBOARD_EVENT_SIZE);
return true;
} }
static inline bool static inline bool
@ -268,10 +264,7 @@ convert_hid_keyboard_event(struct sc_hid_keyboard *kb,
return false; return false;
} }
if (!sc_hid_keyboard_event_init(hid_event)) { sc_hid_keyboard_event_init(hid_event);
LOGW("Could not initialize HID keyboard event");
return false;
}
unsigned char modifiers = sdl_keymod_to_hid_modifiers(event->mods_state); unsigned char modifiers = sdl_keymod_to_hid_modifiers(event->mods_state);
@ -324,10 +317,7 @@ push_mod_lock_state(struct sc_hid_keyboard *kb, uint16_t mods_state) {
} }
struct sc_hid_event hid_event; struct sc_hid_event hid_event;
if (!sc_hid_keyboard_event_init(&hid_event)) { sc_hid_keyboard_event_init(&hid_event);
LOGW("Could not initialize HID keyboard event");
return false;
}
unsigned i = 0; unsigned i = 0;
if (capslock) { if (capslock) {
@ -340,7 +330,6 @@ push_mod_lock_state(struct sc_hid_keyboard *kb, uint16_t mods_state) {
} }
if (!sc_aoa_push_hid_event(kb->aoa, &hid_event)) { if (!sc_aoa_push_hid_event(kb->aoa, &hid_event)) {
sc_hid_event_destroy(&hid_event);
LOGW("Could not request HID event (mod lock state)"); LOGW("Could not request HID event (mod lock state)");
return false; return false;
} }
@ -382,7 +371,6 @@ sc_key_processor_process_key(struct sc_key_processor *kp,
} }
if (!sc_aoa_push_hid_event(kb->aoa, &hid_event)) { if (!sc_aoa_push_hid_event(kb->aoa, &hid_event)) {
sc_hid_event_destroy(&hid_event);
LOGW("Could not request HID event (key)"); LOGW("Could not request HID event (key)");
} }
} }

@ -131,17 +131,13 @@ static const unsigned char mouse_report_desc[] = {
* +---------------+ * +---------------+
*/ */
static bool static void
sc_hid_mouse_event_init(struct sc_hid_event *hid_event) { sc_hid_mouse_event_init(struct sc_hid_event *hid_event) {
unsigned char *data = calloc(1, HID_MOUSE_EVENT_SIZE); hid_event->accessory_id = HID_MOUSE_ACCESSORY_ID;
if (!data) { hid_event->size = HID_MOUSE_EVENT_SIZE;
LOG_OOM(); hid_event->ack_to_wait = SC_SEQUENCE_INVALID;
return false; // Leave hid_event->data uninitialized, it will be fully initialized by
} // callers
sc_hid_event_init(hid_event, HID_MOUSE_ACCESSORY_ID, data,
HID_MOUSE_EVENT_SIZE);
return true;
} }
static unsigned char static unsigned char
@ -171,9 +167,7 @@ sc_mouse_processor_process_mouse_motion(struct sc_mouse_processor *mp,
struct sc_hid_mouse *mouse = DOWNCAST(mp); struct sc_hid_mouse *mouse = DOWNCAST(mp);
struct sc_hid_event hid_event; struct sc_hid_event hid_event;
if (!sc_hid_mouse_event_init(&hid_event)) { sc_hid_mouse_event_init(&hid_event);
return;
}
unsigned char *data = hid_event.data; unsigned char *data = hid_event.data;
data[0] = buttons_state_to_hid_buttons(event->buttons_state); data[0] = buttons_state_to_hid_buttons(event->buttons_state);
@ -182,7 +176,6 @@ sc_mouse_processor_process_mouse_motion(struct sc_mouse_processor *mp,
data[3] = 0; // wheel coordinates only used for scrolling data[3] = 0; // wheel coordinates only used for scrolling
if (!sc_aoa_push_hid_event(mouse->aoa, &hid_event)) { if (!sc_aoa_push_hid_event(mouse->aoa, &hid_event)) {
sc_hid_event_destroy(&hid_event);
LOGW("Could not request HID event (mouse motion)"); LOGW("Could not request HID event (mouse motion)");
} }
} }
@ -193,9 +186,7 @@ sc_mouse_processor_process_mouse_click(struct sc_mouse_processor *mp,
struct sc_hid_mouse *mouse = DOWNCAST(mp); struct sc_hid_mouse *mouse = DOWNCAST(mp);
struct sc_hid_event hid_event; struct sc_hid_event hid_event;
if (!sc_hid_mouse_event_init(&hid_event)) { sc_hid_mouse_event_init(&hid_event);
return;
}
unsigned char *data = hid_event.data; unsigned char *data = hid_event.data;
data[0] = buttons_state_to_hid_buttons(event->buttons_state); data[0] = buttons_state_to_hid_buttons(event->buttons_state);
@ -204,7 +195,6 @@ sc_mouse_processor_process_mouse_click(struct sc_mouse_processor *mp,
data[3] = 0; // wheel coordinates only used for scrolling data[3] = 0; // wheel coordinates only used for scrolling
if (!sc_aoa_push_hid_event(mouse->aoa, &hid_event)) { if (!sc_aoa_push_hid_event(mouse->aoa, &hid_event)) {
sc_hid_event_destroy(&hid_event);
LOGW("Could not request HID event (mouse click)"); LOGW("Could not request HID event (mouse click)");
} }
} }
@ -215,9 +205,7 @@ sc_mouse_processor_process_mouse_scroll(struct sc_mouse_processor *mp,
struct sc_hid_mouse *mouse = DOWNCAST(mp); struct sc_hid_mouse *mouse = DOWNCAST(mp);
struct sc_hid_event hid_event; struct sc_hid_event hid_event;
if (!sc_hid_mouse_event_init(&hid_event)) { sc_hid_mouse_event_init(&hid_event);
return;
}
unsigned char *data = hid_event.data; unsigned char *data = hid_event.data;
data[0] = 0; // buttons state irrelevant (and unknown) data[0] = 0; // buttons state irrelevant (and unknown)
@ -229,7 +217,6 @@ sc_mouse_processor_process_mouse_scroll(struct sc_mouse_processor *mp,
// Horizontal scrolling ignored // Horizontal scrolling ignored
if (!sc_aoa_push_hid_event(mouse->aoa, &hid_event)) { if (!sc_aoa_push_hid_event(mouse->aoa, &hid_event)) {
sc_hid_event_destroy(&hid_event);
LOGW("Could not request HID event (mouse scroll)"); LOGW("Could not request HID event (mouse scroll)");
} }
} }

Loading…
Cancel
Save