From c6df23fed3f43bbb331e51f2ec56be56d7ba23e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Bernon?= Date: Thu, 23 Sep 2021 08:55:26 +0200 Subject: [PATCH] winebus.sys: Factor out HID report buffers allocation. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: RĂ©mi Bernon Signed-off-by: Alexandre Julliard --- dlls/winebus.sys/bus_sdl.c | 44 ++++++++----------------- dlls/winebus.sys/bus_udev.c | 58 ++++++++------------------------- dlls/winebus.sys/hid.c | 27 ++++++++++++++- dlls/winebus.sys/unix_private.h | 6 ++++ 4 files changed, 59 insertions(+), 76 deletions(-) diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c index e6b67fae3c0..6adb0fe913d 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -123,9 +123,6 @@ struct sdl_device SDL_GameController *sdl_controller; SDL_JoystickID id; - int buffer_length; - BYTE *report_buffer; - SDL_Haptic *sdl_haptic; int haptic_effect_id; }; @@ -153,8 +150,8 @@ static void set_button_value(struct sdl_device *impl, int index, int value) int bit_index = index % 8; BYTE mask = 1 << bit_index; if (index >= state->button_count) return; - if (value) impl->report_buffer[byte_index] |= mask; - else impl->report_buffer[byte_index] &= ~mask; + if (value) state->report_buf[byte_index] |= mask; + else state->report_buf[byte_index] &= ~mask; } static void set_axis_value(struct sdl_device *impl, int index, short value) @@ -163,7 +160,7 @@ static void set_axis_value(struct sdl_device *impl, int index, short value) USHORT offset = state->abs_axis_start; if (index >= state->abs_axis_count) return; offset += index * sizeof(DWORD); - *(DWORD *)&impl->report_buffer[offset] = LE_DWORD(value); + *(DWORD *)&state->report_buf[offset] = LE_DWORD(value); } static void set_ball_value(struct sdl_device *impl, int index, int value1, int value2) @@ -172,8 +169,8 @@ static void set_ball_value(struct sdl_device *impl, int index, int value1, int v USHORT offset = state->rel_axis_start; if (index >= state->rel_axis_count) return; offset += index * sizeof(DWORD); - *(DWORD *)&impl->report_buffer[offset] = LE_DWORD(value1); - *(DWORD *)&impl->report_buffer[offset + sizeof(DWORD)] = LE_DWORD(value2); + *(DWORD *)&state->report_buf[offset] = LE_DWORD(value1); + *(DWORD *)&state->report_buf[offset + sizeof(DWORD)] = LE_DWORD(value2); } static void set_hat_value(struct sdl_device *impl, int index, int value) @@ -202,7 +199,7 @@ static void set_hat_value(struct sdl_device *impl, int index, int value) default: return; } - impl->report_buffer[offset] = val; + state->report_buf[offset] = val; } static BOOL descriptor_add_haptic(struct sdl_device *impl) @@ -287,9 +284,6 @@ static NTSTATUS build_joystick_report_descriptor(struct unix_device *iface) if (!hid_device_end_report_descriptor(iface)) return STATUS_NO_MEMORY; - impl->buffer_length = iface->hid_device_state.report_len; - if (!(impl->report_buffer = calloc(1, impl->buffer_length))) goto failed; - /* Initialize axis in the report */ for (i = 0; i < axis_count; i++) set_axis_value(impl, i, pSDL_JoystickGetAxis(impl->sdl_joystick, i)); @@ -297,10 +291,6 @@ static NTSTATUS build_joystick_report_descriptor(struct unix_device *iface) set_hat_value(impl, i, pSDL_JoystickGetHat(impl->sdl_joystick, i)); return STATUS_SUCCESS; - -failed: - free(impl->report_buffer); - return STATUS_NO_MEMORY; } static SHORT compose_dpad_value(SDL_GameController *joystick) @@ -366,19 +356,12 @@ static NTSTATUS build_controller_report_descriptor(struct unix_device *iface) if (!hid_device_end_report_descriptor(iface)) return STATUS_NO_MEMORY; - impl->buffer_length = impl->unix_device.hid_device_state.report_len; - if (!(impl->report_buffer = calloc(1, impl->buffer_length))) goto failed; - /* Initialize axis in the report */ for (i = SDL_CONTROLLER_AXIS_LEFTX; i < SDL_CONTROLLER_AXIS_MAX; i++) set_axis_value(impl, i, pSDL_GameControllerGetAxis(impl->sdl_controller, i)); set_hat_value(impl, 0, compose_dpad_value(impl->sdl_controller)); return STATUS_SUCCESS; - -failed: - free(impl->report_buffer); - return STATUS_NO_MEMORY; } static void sdl_device_destroy(struct unix_device *iface) @@ -477,6 +460,7 @@ static const struct hid_device_vtbl sdl_device_vtbl = static BOOL set_report_from_joystick_event(struct sdl_device *impl, SDL_Event *event) { struct unix_device *iface = &impl->unix_device; + struct hid_device_state *state = &iface->hid_device_state; if (impl->sdl_controller) return TRUE; /* use controller events instead */ @@ -488,8 +472,7 @@ static BOOL set_report_from_joystick_event(struct sdl_device *impl, SDL_Event *e SDL_JoyButtonEvent *ie = &event->jbutton; set_button_value(impl, ie->button, ie->state); - - bus_event_queue_input_report(&event_queue, iface, impl->report_buffer, impl->buffer_length); + bus_event_queue_input_report(&event_queue, iface, state->report_buf, state->report_len); break; } case SDL_JOYAXISMOTION: @@ -499,7 +482,7 @@ static BOOL set_report_from_joystick_event(struct sdl_device *impl, SDL_Event *e if (ie->axis < 6) { set_axis_value(impl, ie->axis, ie->value); - bus_event_queue_input_report(&event_queue, iface, impl->report_buffer, impl->buffer_length); + bus_event_queue_input_report(&event_queue, iface, state->report_buf, state->report_len); } break; } @@ -508,7 +491,7 @@ static BOOL set_report_from_joystick_event(struct sdl_device *impl, SDL_Event *e SDL_JoyBallEvent *ie = &event->jball; set_ball_value(impl, ie->ball, ie->xrel, ie->yrel); - bus_event_queue_input_report(&event_queue, iface, impl->report_buffer, impl->buffer_length); + bus_event_queue_input_report(&event_queue, iface, state->report_buf, state->report_len); break; } case SDL_JOYHATMOTION: @@ -516,7 +499,7 @@ static BOOL set_report_from_joystick_event(struct sdl_device *impl, SDL_Event *e SDL_JoyHatEvent *ie = &event->jhat; set_hat_value(impl, ie->hat, ie->value); - bus_event_queue_input_report(&event_queue, iface, impl->report_buffer, impl->buffer_length); + bus_event_queue_input_report(&event_queue, iface, state->report_buf, state->report_len); break; } default: @@ -528,6 +511,7 @@ static BOOL set_report_from_joystick_event(struct sdl_device *impl, SDL_Event *e static BOOL set_report_from_controller_event(struct sdl_device *impl, SDL_Event *event) { struct unix_device *iface = &impl->unix_device; + struct hid_device_state *state = &iface->hid_device_state; switch(event->type) { @@ -555,7 +539,7 @@ static BOOL set_report_from_controller_event(struct sdl_device *impl, SDL_Event } set_button_value(impl, button, ie->state); - bus_event_queue_input_report(&event_queue, iface, impl->report_buffer, impl->buffer_length); + bus_event_queue_input_report(&event_queue, iface, state->report_buf, state->report_len); break; } case SDL_CONTROLLERAXISMOTION: @@ -563,7 +547,7 @@ static BOOL set_report_from_controller_event(struct sdl_device *impl, SDL_Event SDL_ControllerAxisEvent *ie = &event->caxis; set_axis_value(impl, ie->axis, ie->value); - bus_event_queue_input_report(&event_queue, iface, impl->report_buffer, impl->buffer_length); + bus_event_queue_input_report(&event_queue, iface, state->report_buf, state->report_len); break; } default: diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index 9f3b731364d..cd7eadf7ec0 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -122,11 +122,6 @@ struct lnxev_device { struct base_device base; - int buffer_length; - BYTE *last_report_buffer; - BYTE *current_report_buffer; - enum { FIRST, NORMAL, DROPPED } report_state; - BYTE abs_map[HID_ABS_MAX]; BYTE rel_map[HID_REL_MAX]; BYTE hat_map[8]; @@ -338,8 +333,8 @@ static void set_button_value(struct lnxev_device *impl, int index, int value) int bit_index = index % 8; BYTE mask = 1 << bit_index; if (index >= state->button_count) return; - if (value) impl->current_report_buffer[byte_index] |= mask; - else impl->current_report_buffer[byte_index] &= ~mask; + if (value) state->report_buf[byte_index] |= mask; + else state->report_buf[byte_index] &= ~mask; } static void set_abs_axis_value(struct lnxev_device *impl, int code, int value) @@ -387,7 +382,7 @@ static void set_abs_axis_value(struct lnxev_device *impl, int code, int value) offset = state->hatswitch_start; if (index >= state->hatswitch_count) return; offset += index; - impl->current_report_buffer[offset] = value; + state->report_buf[offset] = value; } else if (code < HID_ABS_MAX && ABS_TO_HID_MAP[code][0] != 0) { @@ -395,7 +390,7 @@ static void set_abs_axis_value(struct lnxev_device *impl, int code, int value) offset = state->abs_axis_start; if (index >= state->abs_axis_count) return; offset += index * sizeof(DWORD); - *(DWORD *)&impl->current_report_buffer[offset] = LE_DWORD(value); + *(DWORD *)&state->report_buf[offset] = LE_DWORD(value); } } @@ -409,7 +404,7 @@ static void set_rel_axis_value(struct lnxev_device *impl, int code, int value) offset = state->rel_axis_start; if (index >= state->rel_axis_count) return; offset += index * sizeof(DWORD); - *(DWORD *)&impl->current_report_buffer[offset] = LE_DWORD(value); + *(DWORD *)&state->report_buf[offset] = LE_DWORD(value); } } @@ -530,48 +525,25 @@ static NTSTATUS build_report_descriptor(struct unix_device *iface, struct udev_d if (!hid_device_end_report_descriptor(iface)) return STATUS_NO_MEMORY; - impl->buffer_length = iface->hid_device_state.report_len; - if (!(impl->current_report_buffer = calloc(1, impl->buffer_length))) goto failed; - if (!(impl->last_report_buffer = calloc(1, impl->buffer_length))) goto failed; - impl->report_state = FIRST; - /* Initialize axis in the report */ for (i = 0; i < HID_ABS_MAX; i++) if (test_bit(absbits, i)) set_abs_axis_value(impl, i, abs_info[i].value); return STATUS_SUCCESS; - -failed: - free(impl->current_report_buffer); - free(impl->last_report_buffer); - return STATUS_NO_MEMORY; } -static BOOL set_report_from_event(struct lnxev_device *impl, struct input_event *ie) +static BOOL set_report_from_event(struct unix_device *iface, struct input_event *ie) { + struct lnxev_device *impl = lnxev_impl_from_unix_device(iface); switch(ie->type) { #ifdef EV_SYN case EV_SYN: switch (ie->code) { - case SYN_REPORT: - if (impl->report_state == NORMAL) - { - memcpy(impl->last_report_buffer, impl->current_report_buffer, impl->buffer_length); - return TRUE; - } - else - { - if (impl->report_state == DROPPED) - memcpy(impl->current_report_buffer, impl->last_report_buffer, impl->buffer_length); - impl->report_state = NORMAL; - } - break; - case SYN_DROPPED: - TRACE_(hid_report)("received SY_DROPPED\n"); - impl->report_state = DROPPED; + case SYN_REPORT: return hid_device_sync_report(iface); + case SYN_DROPPED: hid_device_drop_report(iface); break; } return FALSE; #endif @@ -785,10 +757,6 @@ static const struct raw_device_vtbl hidraw_device_vtbl = static void lnxev_device_destroy(struct unix_device *iface) { struct lnxev_device *impl = lnxev_impl_from_unix_device(iface); - - free(impl->current_report_buffer); - free(impl->last_report_buffer); - udev_device_unref(impl->base.udev_device); } @@ -818,20 +786,20 @@ static void lnxev_device_stop(struct unix_device *iface) static void lnxev_device_read_report(struct unix_device *iface) { + struct hid_device_state *state = &iface->hid_device_state; struct lnxev_device *impl = lnxev_impl_from_unix_device(iface); struct input_event ie; int size; - if (!impl->current_report_buffer || impl->buffer_length == 0) - return; + if (!state->report_buf || !state->report_len) return; size = read(impl->base.device_fd, &ie, sizeof(ie)); if (size == -1) TRACE_(hid_report)("Read failed. Likely an unplugged device\n"); else if (size == 0) TRACE_(hid_report)("Failed to read report\n"); - else if (set_report_from_event(impl, &ie)) - bus_event_queue_input_report(&event_queue, iface, impl->current_report_buffer, impl->buffer_length); + else if (set_report_from_event(iface, &ie)) + bus_event_queue_input_report(&event_queue, iface, state->report_buf, state->report_len); } static void lnxev_device_set_output_report(struct unix_device *iface, HID_XFER_PACKET *packet, IO_STATUS_BLOCK *io) diff --git a/dlls/winebus.sys/hid.c b/dlls/winebus.sys/hid.c index acf0c52cfa8..ba49c010532 100644 --- a/dlls/winebus.sys/hid.c +++ b/dlls/winebus.sys/hid.c @@ -89,12 +89,15 @@ BOOL hid_device_begin_report_descriptor(struct unix_device *iface, USAGE usage_p BOOL hid_device_end_report_descriptor(struct unix_device *iface) { struct hid_report_descriptor *desc = &iface->hid_report_descriptor; + struct hid_device_state *state = &iface->hid_device_state; static const BYTE template[] = { END_COLLECTION, }; - iface->hid_device_state.report_len = (iface->hid_device_state.bit_size + 7) / 8; + state->report_len = (state->bit_size + 7) / 8; + if (!(state->report_buf = calloc(1, state->report_len))) return FALSE; + if (!(state->last_report_buf = calloc(1, state->report_len))) return FALSE; return hid_report_descriptor_append(desc, template, sizeof(template)); } @@ -307,6 +310,8 @@ static void hid_device_destroy(struct unix_device *iface) { iface->hid_vtbl->destroy(iface); free(iface->hid_report_descriptor.data); + free(iface->hid_device_state.report_buf); + free(iface->hid_device_state.last_report_buf); } static NTSTATUS hid_device_start(struct unix_device *iface) @@ -363,3 +368,23 @@ void *hid_device_create(const struct hid_device_vtbl *vtbl, SIZE_T size) return impl; } + +BOOL hid_device_sync_report(struct unix_device *iface) +{ + BOOL dropped; + + if (!(dropped = iface->hid_device_state.dropped)) + memcpy(iface->hid_device_state.last_report_buf, iface->hid_device_state.report_buf, + iface->hid_device_state.report_len); + else + memcpy(iface->hid_device_state.report_buf, iface->hid_device_state.last_report_buf, + iface->hid_device_state.report_len); + iface->hid_device_state.dropped = FALSE; + + return !dropped; +} + +void hid_device_drop_report(struct unix_device *iface) +{ + iface->hid_device_state.dropped = TRUE; +} diff --git a/dlls/winebus.sys/unix_private.h b/dlls/winebus.sys/unix_private.h index ec0568faa6f..dbec779c67e 100644 --- a/dlls/winebus.sys/unix_private.h +++ b/dlls/winebus.sys/unix_private.h @@ -69,6 +69,9 @@ struct hid_device_state USHORT button_start; USHORT button_count; USHORT report_len; + BYTE *report_buf; + BYTE *last_report_buf; + BOOL dropped; }; struct unix_device @@ -116,6 +119,9 @@ extern BOOL hid_device_add_axes(struct unix_device *iface, BYTE count, USAGE usa extern BOOL hid_device_add_haptics(struct unix_device *iface) DECLSPEC_HIDDEN; +extern BOOL hid_device_sync_report(struct unix_device *iface) DECLSPEC_HIDDEN; +extern void hid_device_drop_report(struct unix_device *iface) DECLSPEC_HIDDEN; + BOOL is_xbox_gamepad(WORD vid, WORD pid) DECLSPEC_HIDDEN; #endif /* __WINEBUS_UNIX_PRIVATE_H */