Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winebus.sys/bus_sdl.c | 141 ++++++++--------------------- dlls/winebus.sys/bus_udev.c | 154 +++++++++----------------------- dlls/winebus.sys/hid.c | 87 ++++++++++++++++++ dlls/winebus.sys/unix_private.h | 6 ++ 4 files changed, 172 insertions(+), 216 deletions(-)
diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c index 6adb0fe913d..7af5f13bcee 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -50,12 +50,6 @@ #include "wine/unicode.h" #include "hidusage.h"
-#ifdef WORDS_BIGENDIAN -# define LE_DWORD(x) RtlUlongByteSwap(x) -#else -# define LE_DWORD(x) (x) -#endif - #include "unix_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(plugplay); @@ -142,64 +136,23 @@ static struct sdl_device *find_device_from_id(SDL_JoystickID id) return NULL; }
-static void set_button_value(struct sdl_device *impl, int index, int value) -{ - struct hid_device_state *state = &impl->unix_device.hid_device_state; - USHORT offset = state->button_start; - int byte_index = offset + index / 8; - int bit_index = index % 8; - BYTE mask = 1 << bit_index; - if (index >= state->button_count) return; - 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) +static void set_hat_value(struct unix_device *iface, int index, int value) { - struct hid_device_state *state = &impl->unix_device.hid_device_state; - USHORT offset = state->abs_axis_start; - if (index >= state->abs_axis_count) return; - offset += index * sizeof(DWORD); - *(DWORD *)&state->report_buf[offset] = LE_DWORD(value); -} - -static void set_ball_value(struct sdl_device *impl, int index, int value1, int value2) -{ - struct hid_device_state *state = &impl->unix_device.hid_device_state; - USHORT offset = state->rel_axis_start; - if (index >= state->rel_axis_count) return; - offset += index * sizeof(DWORD); - *(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) -{ - struct hid_device_state *state = &impl->unix_device.hid_device_state; - USHORT offset = state->hatswitch_start; - unsigned char val; - - if (index >= state->hatswitch_count) return; - offset += index; - + LONG x = 0, y = 0; switch (value) { - /* 8 1 2 - * 7 0 3 - * 6 5 4 */ - case SDL_HAT_CENTERED: val = 0; break; - case SDL_HAT_UP: val = 1; break; - case SDL_HAT_RIGHTUP: val = 2; break; - case SDL_HAT_RIGHT: val = 3; break; - case SDL_HAT_RIGHTDOWN: val = 4; break; - case SDL_HAT_DOWN: val = 5; break; - case SDL_HAT_LEFTDOWN: val = 6; break; - case SDL_HAT_LEFT: val = 7; break; - case SDL_HAT_LEFTUP: val = 8; break; - default: return; + case SDL_HAT_CENTERED: break; + case SDL_HAT_UP: y = 1; break; + case SDL_HAT_RIGHTUP: y = x = 1; break; + case SDL_HAT_RIGHT: x = 1; break; + case SDL_HAT_RIGHTDOWN: x = 1; y = -1; break; + case SDL_HAT_DOWN: y = -1; break; + case SDL_HAT_LEFTDOWN: x = y = -1; break; + case SDL_HAT_LEFT: x = -1; break; + case SDL_HAT_LEFTUP: x = -1; y = 1; break; } - - state->report_buf[offset] = val; + hid_device_set_hatswitch_x(iface, index, x); + hid_device_set_hatswitch_y(iface, index, y); }
static BOOL descriptor_add_haptic(struct sdl_device *impl) @@ -286,40 +239,13 @@ static NTSTATUS build_joystick_report_descriptor(struct unix_device *iface)
/* Initialize axis in the report */ for (i = 0; i < axis_count; i++) - set_axis_value(impl, i, pSDL_JoystickGetAxis(impl->sdl_joystick, i)); + hid_device_set_abs_axis(iface, i, pSDL_JoystickGetAxis(impl->sdl_joystick, i)); for (i = 0; i < hat_count; i++) - set_hat_value(impl, i, pSDL_JoystickGetHat(impl->sdl_joystick, i)); + set_hat_value(iface, i, pSDL_JoystickGetHat(impl->sdl_joystick, i));
return STATUS_SUCCESS; }
-static SHORT compose_dpad_value(SDL_GameController *joystick) -{ - if (pSDL_GameControllerGetButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_UP)) - { - if (pSDL_GameControllerGetButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT)) - return SDL_HAT_RIGHTUP; - if (pSDL_GameControllerGetButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT)) - return SDL_HAT_LEFTUP; - return SDL_HAT_UP; - } - - if (pSDL_GameControllerGetButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_DOWN)) - { - if (pSDL_GameControllerGetButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT)) - return SDL_HAT_RIGHTDOWN; - if (pSDL_GameControllerGetButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT)) - return SDL_HAT_LEFTDOWN; - return SDL_HAT_DOWN; - } - - if (pSDL_GameControllerGetButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT)) - return SDL_HAT_RIGHT; - if (pSDL_GameControllerGetButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT)) - return SDL_HAT_LEFT; - return SDL_HAT_CENTERED; -} - static NTSTATUS build_controller_report_descriptor(struct unix_device *iface) { static const USAGE left_axis_usages[] = {HID_USAGE_GENERIC_X, HID_USAGE_GENERIC_Y}; @@ -358,8 +284,15 @@ static NTSTATUS build_controller_report_descriptor(struct unix_device *iface)
/* 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)); + hid_device_set_abs_axis(iface, i, pSDL_GameControllerGetAxis(impl->sdl_controller, i)); + if (pSDL_GameControllerGetButton(impl->sdl_controller, SDL_CONTROLLER_BUTTON_DPAD_UP)) + hid_device_set_hatswitch_y(iface, 0, -1); + if (pSDL_GameControllerGetButton(impl->sdl_controller, SDL_CONTROLLER_BUTTON_DPAD_DOWN)) + hid_device_set_hatswitch_y(iface, 0, +1); + if (pSDL_GameControllerGetButton(impl->sdl_controller, SDL_CONTROLLER_BUTTON_DPAD_LEFT)) + hid_device_set_hatswitch_x(iface, 0, -1); + if (pSDL_GameControllerGetButton(impl->sdl_controller, SDL_CONTROLLER_BUTTON_DPAD_RIGHT)) + hid_device_set_hatswitch_x(iface, 0, +1);
return STATUS_SUCCESS; } @@ -471,7 +404,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); + hid_device_set_button(iface, ie->button, ie->state); bus_event_queue_input_report(&event_queue, iface, state->report_buf, state->report_len); break; } @@ -479,18 +412,16 @@ static BOOL set_report_from_joystick_event(struct sdl_device *impl, SDL_Event *e { SDL_JoyAxisEvent *ie = &event->jaxis;
- if (ie->axis < 6) - { - set_axis_value(impl, ie->axis, ie->value); - bus_event_queue_input_report(&event_queue, iface, state->report_buf, state->report_len); - } + hid_device_set_abs_axis(iface, ie->axis, ie->value); + bus_event_queue_input_report(&event_queue, iface, state->report_buf, state->report_len); break; } case SDL_JOYBALLMOTION: { SDL_JoyBallEvent *ie = &event->jball;
- set_ball_value(impl, ie->ball, ie->xrel, ie->yrel); + hid_device_set_rel_axis(iface, 2 * ie->ball, ie->xrel); + hid_device_set_rel_axis(iface, 2 * ie->ball + 1, ie->yrel); bus_event_queue_input_report(&event_queue, iface, state->report_buf, state->report_len); break; } @@ -498,7 +429,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); + set_hat_value(iface, ie->hat, ie->value); bus_event_queue_input_report(&event_queue, iface, state->report_buf, state->report_len); break; } @@ -524,10 +455,16 @@ static BOOL set_report_from_controller_event(struct sdl_device *impl, SDL_Event switch ((button = ie->button)) { case SDL_CONTROLLER_BUTTON_DPAD_UP: + hid_device_set_hatswitch_y(iface, 0, ie->state ? -1 : 0); + break; case SDL_CONTROLLER_BUTTON_DPAD_DOWN: + hid_device_set_hatswitch_y(iface, 0, ie->state ? +1 : 0); + break; case SDL_CONTROLLER_BUTTON_DPAD_LEFT: + hid_device_set_hatswitch_x(iface, 0, ie->state ? -1 : 0); + break; case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: - set_hat_value(impl, 0, compose_dpad_value(impl->sdl_controller)); + hid_device_set_hatswitch_x(iface, 0, ie->state ? +1 : 0); break; case SDL_CONTROLLER_BUTTON_LEFTSHOULDER: button = 4; break; case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER: button = 5; break; @@ -538,7 +475,7 @@ static BOOL set_report_from_controller_event(struct sdl_device *impl, SDL_Event case SDL_CONTROLLER_BUTTON_GUIDE: button = 10; break; }
- set_button_value(impl, button, ie->state); + hid_device_set_button(iface, button, ie->state); bus_event_queue_input_report(&event_queue, iface, state->report_buf, state->report_len); break; } @@ -546,7 +483,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); + hid_device_set_abs_axis(iface, ie->axis, ie->value); bus_event_queue_input_report(&event_queue, iface, state->report_buf, state->report_len); break; } diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index cd7eadf7ec0..f4d27090109 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -126,7 +126,6 @@ struct lnxev_device BYTE rel_map[HID_REL_MAX]; BYTE hat_map[8]; BYTE button_map[KEY_MAX]; - int hat_values[8]; };
static inline struct base_device *impl_from_unix_device(struct unix_device *iface) @@ -325,89 +324,6 @@ static const BYTE* what_am_I(struct udev_device *dev) return Unknown; }
-static void set_button_value(struct lnxev_device *impl, int index, int value) -{ - struct hid_device_state *state = &impl->base.unix_device.hid_device_state; - USHORT offset = state->button_start; - int byte_index = offset + index / 8; - int bit_index = index % 8; - BYTE mask = 1 << bit_index; - if (index >= state->button_count) return; - 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) -{ - struct hid_device_state *state = &impl->base.unix_device.hid_device_state; - USHORT offset, index; - /* check for hatswitches */ - if (code <= ABS_HAT3Y && code >= ABS_HAT0X) - { - index = code - ABS_HAT0X; - impl->hat_values[index] = value; - if ((code - ABS_HAT0X) % 2) - index--; - /* 8 1 2 - * 7 0 3 - * 6 5 4 */ - if (impl->hat_values[index] == 0) - { - if (impl->hat_values[index+1] == 0) - value = 0; - else if (impl->hat_values[index+1] < 0) - value = 1; - else - value = 5; - } - else if (impl->hat_values[index] > 0) - { - if (impl->hat_values[index+1] == 0) - value = 3; - else if (impl->hat_values[index+1] < 0) - value = 2; - else - value = 4; - } - else - { - if (impl->hat_values[index+1] == 0) - value = 7; - else if (impl->hat_values[index+1] < 0) - value = 8; - else - value = 6; - } - index = impl->hat_map[index]; - offset = state->hatswitch_start; - if (index >= state->hatswitch_count) return; - offset += index; - state->report_buf[offset] = value; - } - else if (code < HID_ABS_MAX && ABS_TO_HID_MAP[code][0] != 0) - { - index = impl->abs_map[code]; - offset = state->abs_axis_start; - if (index >= state->abs_axis_count) return; - offset += index * sizeof(DWORD); - *(DWORD *)&state->report_buf[offset] = LE_DWORD(value); - } -} - -static void set_rel_axis_value(struct lnxev_device *impl, int code, int value) -{ - struct hid_device_state *state = &impl->base.unix_device.hid_device_state; - USHORT offset, index; - if (code < HID_REL_MAX && REL_TO_HID_MAP[code][0] != 0) - { - index = impl->rel_map[code]; - offset = state->rel_axis_start; - if (index >= state->rel_axis_count) return; - offset += index * sizeof(DWORD); - *(DWORD *)&state->report_buf[offset] = LE_DWORD(value); - } -} - static INT count_buttons(int device_fd, BYTE *map) { int i; @@ -506,12 +422,11 @@ static NTSTATUS build_report_descriptor(struct unix_device *iface, struct udev_d }
hat_count = 0; - for (i = ABS_HAT0X; i <=ABS_HAT3X; i+=2) + for (i = ABS_HAT0X; i <= ABS_HAT3X; i += 2) { if (!test_bit(absbits, i)) continue; - impl->hat_map[i - ABS_HAT0X] = hat_count++; - impl->hat_values[i - ABS_HAT0X] = 0; - impl->hat_values[i - ABS_HAT0X + 1] = 0; + impl->hat_map[i - ABS_HAT0X] = hat_count; + impl->hat_map[i - ABS_HAT0X + 1] = hat_count++; }
if (hat_count && !hid_device_add_hatswitch(iface, hat_count)) @@ -527,8 +442,15 @@ static NTSTATUS build_report_descriptor(struct unix_device *iface, struct udev_d
/* 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); + { + if (!test_bit(absbits, i)) continue; + if (i < ABS_HAT0X || i > ABS_HAT3Y) + hid_device_set_abs_axis(iface, impl->abs_map[i], abs_info[i].value); + else if ((i - ABS_HAT0X) % 2) + hid_device_set_hatswitch_y(iface, impl->hat_map[i - ABS_HAT0X], abs_info[i].value); + else + hid_device_set_hatswitch_x(iface, impl->hat_map[i - ABS_HAT0X], abs_info[i].value); + }
return STATUS_SUCCESS; } @@ -536,33 +458,39 @@ static NTSTATUS build_report_descriptor(struct unix_device *iface, struct udev_d 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) + + switch (ie->type) { #ifdef EV_SYN - case EV_SYN: - switch (ie->code) - { - case SYN_REPORT: return hid_device_sync_report(iface); - case SYN_DROPPED: hid_device_drop_report(iface); break; - } - return FALSE; + case EV_SYN: + switch (ie->code) + { + case SYN_REPORT: return hid_device_sync_report(iface); + case SYN_DROPPED: hid_device_drop_report(iface); break; + } + return FALSE; #endif #ifdef EV_MSC - case EV_MSC: - return FALSE; + case EV_MSC: + return FALSE; #endif - case EV_KEY: - set_button_value(impl, impl->button_map[ie->code], ie->value); - return FALSE; - case EV_ABS: - set_abs_axis_value(impl, ie->code, ie->value); - return FALSE; - case EV_REL: - set_rel_axis_value(impl, ie->code, ie->value); - return FALSE; - default: - ERR("TODO: Process Report (%i, %i)\n",ie->type, ie->code); - return FALSE; + case EV_KEY: + hid_device_set_button(iface, impl->button_map[ie->code], ie->value); + return FALSE; + case EV_ABS: + if (ie->code < ABS_HAT0X || ie->code > ABS_HAT3Y) + hid_device_set_abs_axis(iface, impl->abs_map[ie->code], ie->value); + else if ((ie->code - ABS_HAT0X) % 2) + hid_device_set_hatswitch_y(iface, impl->hat_map[ie->code - ABS_HAT0X], ie->value); + else + hid_device_set_hatswitch_x(iface, impl->hat_map[ie->code - ABS_HAT0X], ie->value); + return FALSE; + case EV_REL: + hid_device_set_rel_axis(iface, impl->rel_map[ie->code], ie->value); + return FALSE; + default: + ERR("TODO: Process Report (%i, %i)\n",ie->type, ie->code); + return FALSE; } } #endif @@ -791,8 +719,6 @@ static void lnxev_device_read_report(struct unix_device *iface) struct input_event ie; int size;
- 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"); diff --git a/dlls/winebus.sys/hid.c b/dlls/winebus.sys/hid.c index ba49c010532..4a4295b9aa8 100644 --- a/dlls/winebus.sys/hid.c +++ b/dlls/winebus.sys/hid.c @@ -369,6 +369,93 @@ void *hid_device_create(const struct hid_device_vtbl *vtbl, SIZE_T size) return impl; }
+#ifdef WORDS_BIGENDIAN +# define LE_ULONG(x) RtlUlongByteSwap((ULONG)(x)) +#else +# define LE_ULONG(x) ((ULONG)(x)) +#endif + +BOOL hid_device_set_abs_axis(struct unix_device *iface, ULONG index, LONG value) +{ + struct hid_device_state *state = &iface->hid_device_state; + ULONG offset = state->abs_axis_start + index * 4; + if (index > state->abs_axis_count) return FALSE; + *(ULONG *)(state->report_buf + offset) = LE_ULONG(value); + return TRUE; +} + +BOOL hid_device_set_rel_axis(struct unix_device *iface, ULONG index, LONG value) +{ + struct hid_device_state *state = &iface->hid_device_state; + ULONG offset = state->rel_axis_start + index * 4; + if (index > state->rel_axis_count) return FALSE; + *(ULONG *)(state->report_buf + offset) = LE_ULONG(value); + return TRUE; +} + +BOOL hid_device_set_button(struct unix_device *iface, ULONG index, BOOL is_set) +{ + struct hid_device_state *state = &iface->hid_device_state; + ULONG offset = state->button_start + (index / 8); + BYTE mask = (1 << (index % 8)); + if (index > state->button_count) return FALSE; + if (is_set) state->report_buf[offset] |= mask; + else state->report_buf[offset] &= ~mask; + return TRUE; +} + +/* hatswitch x / y vs value: + * -1 x +1 + * +--------> + * -1 | 8 1 2 + * y | 7 0 3 + * +1 | 6 5 4 + * v + */ +static void hatswitch_decompose(BYTE value, LONG *x, LONG *y) +{ + *x = *y = 0; + if (value == 8 || value == 1 || value == 2) *y = -1; + if (value == 6 || value == 5 || value == 4) *y = +1; + if (value == 8 || value == 7 || value == 6) *x = -1; + if (value == 2 || value == 3 || value == 4) *x = +1; +} + +static void hatswitch_compose(LONG x, LONG y, BYTE *value) +{ + if (x == 0 && y == 0) *value = 0; + else if (x == 0 && y < 0) *value = 1; + else if (x > 0 && y < 0) *value = 2; + else if (x > 0 && y == 0) *value = 3; + else if (x > 0 && y > 0) *value = 4; + else if (x == 0 && y > 0) *value = 5; + else if (x < 0 && y > 0) *value = 6; + else if (x < 0 && y == 0) *value = 7; + else if (x < 0 && y < 0) *value = 8; +} + +BOOL hid_device_set_hatswitch_x(struct unix_device *iface, ULONG index, LONG new_x) +{ + struct hid_device_state *state = &iface->hid_device_state; + ULONG offset = state->hatswitch_start + index; + LONG x, y; + if (index > state->hatswitch_count) return FALSE; + hatswitch_decompose(state->report_buf[offset], &x, &y); + hatswitch_compose(new_x, y, &state->report_buf[offset]); + return TRUE; +} + +BOOL hid_device_set_hatswitch_y(struct unix_device *iface, ULONG index, LONG new_y) +{ + struct hid_device_state *state = &iface->hid_device_state; + ULONG offset = state->hatswitch_start + index; + LONG x, y; + if (index > state->hatswitch_count) return FALSE; + hatswitch_decompose(state->report_buf[offset], &x, &y); + hatswitch_compose(x, new_y, &state->report_buf[offset]); + return TRUE; +} + BOOL hid_device_sync_report(struct unix_device *iface) { BOOL dropped; diff --git a/dlls/winebus.sys/unix_private.h b/dlls/winebus.sys/unix_private.h index dbec779c67e..543bfda9d79 100644 --- a/dlls/winebus.sys/unix_private.h +++ b/dlls/winebus.sys/unix_private.h @@ -119,6 +119,12 @@ 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_set_abs_axis(struct unix_device *iface, ULONG index, LONG value) DECLSPEC_HIDDEN; +extern BOOL hid_device_set_rel_axis(struct unix_device *iface, ULONG index, LONG value) DECLSPEC_HIDDEN; +extern BOOL hid_device_set_button(struct unix_device *iface, ULONG index, BOOL is_set) DECLSPEC_HIDDEN; +extern BOOL hid_device_set_hatswitch_x(struct unix_device *iface, ULONG index, LONG new_x) DECLSPEC_HIDDEN; +extern BOOL hid_device_set_hatswitch_y(struct unix_device *iface, ULONG index, LONG new_y) 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;