From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winebus.sys/bus_udev.c | 58 ++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 33 deletions(-)
diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index 70b96c12c04..729501aa982 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -509,13 +509,34 @@ static const USAGE_AND_PAGE *what_am_I(struct udev_device *dev, int fd) return &Unknown; }
+static void set_abs_axis_value(struct unix_device *iface, int code, int value) +{ + struct lnxev_device *impl = lnxev_impl_from_unix_device(iface); + + if (code < ABS_HAT0X || code > ABS_HAT3Y) + { + if (!(code = impl->abs_map[code])) return; + hid_device_set_abs_axis(iface, code - 1, value); + } + else if ((code - ABS_HAT0X) % 2) + { + if (!(code = impl->hat_map[code - ABS_HAT0X])) return; + hid_device_set_hatswitch_y(iface, code - 1, value); + } + else + { + if (!(code = impl->hat_map[code - ABS_HAT0X])) return; + hid_device_set_hatswitch_x(iface, code - 1, value); + } +} + static NTSTATUS build_report_descriptor(struct unix_device *iface, struct udev_device *dev, struct lnxev_info *info) { struct input_absinfo abs_info[ABS_CNT]; struct ff_effect effect; USHORT count = 0; USAGE usages[16]; - INT i, axis; + int i; struct lnxev_device *impl = lnxev_impl_from_unix_device(iface); const USAGE_AND_PAGE device_usage = *what_am_I(dev, impl->base.device_fd);
@@ -597,22 +618,7 @@ static NTSTATUS build_report_descriptor(struct unix_device *iface, struct udev_d USAGE_AND_PAGE usage = absolute_usages[i]; if (!usage.UsagePage || !usage.Usage) continue; if (!test_bit(info->abs, i)) continue; - - if (i < ABS_HAT0X || i > ABS_HAT3Y) - { - if (!(axis = impl->abs_map[i])) continue; - hid_device_set_abs_axis(iface, axis - 1, abs_info[i].value); - } - else if ((i - ABS_HAT0X) % 2) - { - if (!(axis = impl->hat_map[i - ABS_HAT0X])) continue; - hid_device_set_hatswitch_y(iface, axis - 1, abs_info[i].value); - } - else - { - if (!(axis = impl->hat_map[i - ABS_HAT0X])) continue; - hid_device_set_hatswitch_x(iface, axis - 1, abs_info[i].value); - } + set_abs_axis_value(iface, i, abs_info[i].value); }
return STATUS_SUCCESS; @@ -623,7 +629,7 @@ static BOOL set_report_from_event(struct unix_device *iface, struct input_event struct hid_effect_state *effect_state = &iface->hid_physical.effect_state; struct lnxev_device *impl = lnxev_impl_from_unix_device(iface); ULONG effect_flags = InterlockedOr(&impl->effect_flags, 0); - unsigned int i, axis, button; + unsigned int i, button;
switch (ie->type) { @@ -645,21 +651,7 @@ static BOOL set_report_from_event(struct unix_device *iface, struct input_event hid_device_set_button(iface, button - 1, ie->value); return FALSE; case EV_ABS: - if (ie->code < ABS_HAT0X || ie->code > ABS_HAT3Y) - { - if (!(axis = impl->abs_map[ie->code])) return FALSE; - hid_device_set_abs_axis(iface, axis - 1, ie->value); - } - else if ((ie->code - ABS_HAT0X) % 2) - { - if (!(axis = impl->hat_map[ie->code - ABS_HAT0X])) return FALSE; - hid_device_set_hatswitch_y(iface, axis - 1, ie->value); - } - else - { - if (!(axis = impl->hat_map[ie->code - ABS_HAT0X])) return FALSE; - hid_device_set_hatswitch_x(iface, axis - 1, ie->value); - } + set_abs_axis_value(iface, ie->code, ie->value); return FALSE; case EV_REL: hid_device_set_rel_axis(iface, impl->rel_map[ie->code], ie->value);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winebus.sys/bus_udev.c | 38 +++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-)
diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index 729501aa982..d8766f9e345 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -201,6 +201,7 @@ struct lnxev_device BYTE button_map[KEY_CNT]; int hat_count; int button_count; + BOOL is_gamepad;
int haptic_effect_id; int effect_ids[256]; @@ -521,11 +522,21 @@ static void set_abs_axis_value(struct unix_device *iface, int code, int value) else if ((code - ABS_HAT0X) % 2) { if (!(code = impl->hat_map[code - ABS_HAT0X])) return; + if (impl->is_gamepad) + { + hid_device_set_button(iface, 11, value < 0); + hid_device_set_button(iface, 12, value > 0); + } hid_device_set_hatswitch_y(iface, code - 1, value); } else { if (!(code = impl->hat_map[code - ABS_HAT0X])) return; + if (impl->is_gamepad) + { + hid_device_set_button(iface, 13, value < 0); + hid_device_set_button(iface, 14, value > 0); + } hid_device_set_hatswitch_x(iface, code - 1, value); } } @@ -565,8 +576,16 @@ static NTSTATUS build_report_descriptor(struct unix_device *iface, struct udev_d return STATUS_NO_MEMORY; }
- if (impl->hat_count && !hid_device_add_hatswitch(iface, impl->hat_count)) return STATUS_NO_MEMORY; - if (impl->button_count && !hid_device_add_buttons(iface, HID_USAGE_PAGE_BUTTON, 1, impl->button_count)) return STATUS_NO_MEMORY; + if (impl->is_gamepad) + { + if (!hid_device_add_hatswitch(iface, 1)) return STATUS_NO_MEMORY; + if (!hid_device_add_buttons(iface, HID_USAGE_PAGE_BUTTON, 1, 15)) return STATUS_NO_MEMORY; + } + else + { + if (impl->hat_count && !hid_device_add_hatswitch(iface, impl->hat_count)) return STATUS_NO_MEMORY; + if (impl->button_count && !hid_device_add_buttons(iface, HID_USAGE_PAGE_BUTTON, 1, impl->button_count)) return STATUS_NO_MEMORY; + }
if (!hid_device_end_input_report(iface)) return STATUS_NO_MEMORY; @@ -648,6 +667,13 @@ static BOOL set_report_from_event(struct unix_device *iface, struct input_event #endif case EV_KEY: if (!(button = impl->button_map[ie->code])) return FALSE; + if (impl->is_gamepad && !impl->hat_count) + { + if (button == 12) hid_device_set_hatswitch_y(iface, 0, -1); + if (button == 13) hid_device_set_hatswitch_y(iface, 0, +1); + if (button == 14) hid_device_set_hatswitch_x(iface, 0, -1); + if (button == 15) hid_device_set_hatswitch_x(iface, 0, +1); + } hid_device_set_button(iface, button - 1, ie->value); return FALSE; case EV_ABS: @@ -1223,9 +1249,9 @@ static NTSTATUS lnxev_device_create(struct udev_device *dev, int fd, const char }
if (is_xbox_gamepad(desc.vid, desc.pid)) desc.is_gamepad = TRUE; - else if (axis_count == 6 && button_count >= 14) desc.is_gamepad = TRUE; + else if (axis_count == 6 && button_count >= (impl->hat_count ? 10 : 14)) desc.is_gamepad = TRUE;
- if (desc.is_gamepad) + if ((impl->is_gamepad = desc.is_gamepad)) { static const UINT gamepad_buttons[] = { @@ -1253,14 +1279,14 @@ static NTSTATUS lnxev_device_create(struct udev_device *dev, int fd, const char { int button = gamepad_buttons[i]; if (!test_bit(info.key, button)) continue; - if (impl->button_count > 14) break; + if (impl->button_count > (impl->hat_count ? 10 : 14)) break; impl->button_map[button] = ++impl->button_count; }
for (int i = BTN_MISC; i < KEY_MAX; i++) { if (i >= BTN_GAMEPAD && i < BTN_DIGI) continue; - if (impl->button_count > 14) break; + if (impl->button_count > (impl->hat_count ? 10 : 14)) break; if (!test_bit(info.key, i)) continue; impl->button_map[i] = ++impl->button_count; }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winebus.sys/bus_sdl.c | 42 ++++----------------------------- dlls/winebus.sys/hid.c | 18 ++++++++++++++ dlls/winebus.sys/unix_private.h | 1 + 3 files changed, 24 insertions(+), 37 deletions(-)
diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c index dd8a1eb24b9..6e2c8bef3e4 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -382,50 +382,18 @@ static NTSTATUS build_joystick_report_descriptor(struct unix_device *iface) static NTSTATUS build_controller_report_descriptor(struct unix_device *iface) { const USAGE_AND_PAGE device_usage = {.UsagePage = HID_USAGE_PAGE_GENERIC, .Usage = HID_USAGE_GENERIC_GAMEPAD}; - static const USAGE left_axis_usages[] = {HID_USAGE_GENERIC_X, HID_USAGE_GENERIC_Y}; - static const USAGE right_axis_usages[] = {HID_USAGE_GENERIC_RX, HID_USAGE_GENERIC_RY}; - static const USAGE trigger_axis_usages[] = {HID_USAGE_GENERIC_Z, HID_USAGE_GENERIC_RZ}; struct sdl_device *impl = impl_from_unix_device(iface); - ULONG i, button_count = SDL_CONTROLLER_BUTTON_MAX - 1; BOOL state;
C_ASSERT(SDL_CONTROLLER_AXIS_MAX == 6);
- if (!hid_device_begin_report_descriptor(iface, &device_usage)) - return STATUS_NO_MEMORY; - - if (!hid_device_begin_input_report(iface, &device_usage)) - return STATUS_NO_MEMORY; - - if (!hid_device_add_axes(iface, 2, HID_USAGE_PAGE_GENERIC, left_axis_usages, - FALSE, -32768, 32767)) - return STATUS_NO_MEMORY; - - if (!hid_device_add_axes(iface, 2, HID_USAGE_PAGE_GENERIC, right_axis_usages, - FALSE, -32768, 32767)) - return STATUS_NO_MEMORY; - - if (!hid_device_add_axes(iface, 2, HID_USAGE_PAGE_GENERIC, trigger_axis_usages, - FALSE, 0, 32767)) - return STATUS_NO_MEMORY; - - if (!hid_device_add_hatswitch(iface, 1)) - return STATUS_NO_MEMORY; - - if (!hid_device_add_buttons(iface, HID_USAGE_PAGE_BUTTON, 1, button_count)) - return STATUS_NO_MEMORY; - - if (!hid_device_end_input_report(iface)) - return STATUS_NO_MEMORY; - - if (!descriptor_add_haptic(impl, FALSE)) - return STATUS_NO_MEMORY; - - if (!hid_device_end_report_descriptor(iface)) - return STATUS_NO_MEMORY; + if (!hid_device_begin_report_descriptor(iface, &device_usage)) return STATUS_NO_MEMORY; + if (!hid_device_add_gamepad(iface)) return STATUS_NO_MEMORY; + if (!descriptor_add_haptic(impl, FALSE)) return STATUS_NO_MEMORY; + if (!hid_device_end_report_descriptor(iface)) return STATUS_NO_MEMORY;
/* Initialize axis in the report */ - for (i = SDL_CONTROLLER_AXIS_LEFTX; i < SDL_CONTROLLER_AXIS_MAX; i++) + for (int i = SDL_CONTROLLER_AXIS_LEFTX; i < SDL_CONTROLLER_AXIS_MAX; i++) hid_device_set_abs_axis(iface, i, pSDL_GameControllerGetAxis(impl->sdl_controller, i));
state = pSDL_GameControllerGetButton(impl->sdl_controller, SDL_CONTROLLER_BUTTON_DPAD_UP); diff --git a/dlls/winebus.sys/hid.c b/dlls/winebus.sys/hid.c index e2f667fd1ea..5b274d20e18 100644 --- a/dlls/winebus.sys/hid.c +++ b/dlls/winebus.sys/hid.c @@ -343,6 +343,24 @@ BOOL hid_device_add_axes(struct unix_device *iface, BYTE count, USAGE usage_page return TRUE; }
+BOOL hid_device_add_gamepad(struct unix_device *iface) +{ + static const USAGE_AND_PAGE device_usage = {.UsagePage = HID_USAGE_PAGE_GENERIC, .Usage = HID_USAGE_GENERIC_GAMEPAD}; + static const USAGE left[] = {HID_USAGE_GENERIC_X, HID_USAGE_GENERIC_Y}; + static const USAGE right[] = {HID_USAGE_GENERIC_RX, HID_USAGE_GENERIC_RY}; + static const USAGE trigger[] = {HID_USAGE_GENERIC_Z, HID_USAGE_GENERIC_RZ}; + + if (!hid_device_begin_input_report(iface, &device_usage)) return FALSE; + if (!hid_device_add_axes(iface, 2, HID_USAGE_PAGE_GENERIC, left, FALSE, -32768, 32767)) return FALSE; + if (!hid_device_add_axes(iface, 2, HID_USAGE_PAGE_GENERIC, right, FALSE, -32768, 32767)) return FALSE; + if (!hid_device_add_axes(iface, 2, HID_USAGE_PAGE_GENERIC, trigger, FALSE, 0, 32767)) return FALSE; + if (!hid_device_add_hatswitch(iface, 1)) return FALSE; + if (!hid_device_add_buttons(iface, HID_USAGE_PAGE_BUTTON, 1, 15)) return FALSE; + if (!hid_device_end_input_report(iface)) return FALSE; + + return TRUE; +} + #pragma pack(push,1) struct hid_haptics_intensity { diff --git a/dlls/winebus.sys/unix_private.h b/dlls/winebus.sys/unix_private.h index 5c39cae1409..11328caee08 100644 --- a/dlls/winebus.sys/unix_private.h +++ b/dlls/winebus.sys/unix_private.h @@ -253,6 +253,7 @@ extern BOOL hid_device_add_hatswitch(struct unix_device *iface, INT count); extern BOOL hid_device_add_axes(struct unix_device *iface, BYTE count, USAGE usage_page, const USAGE *usages, BOOL rel, LONG min, LONG max);
+extern BOOL hid_device_add_gamepad(struct unix_device *iface); extern BOOL hid_device_add_haptics(struct unix_device *iface); extern BOOL hid_device_add_physical(struct unix_device *iface, USAGE *usages, USHORT count, USHORT axes_count);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winebus.sys/bus_udev.c | 83 +++++++++++++++++++++++-------------- 1 file changed, 51 insertions(+), 32 deletions(-)
diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index d8766f9e345..9951e3d0ec8 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -80,12 +80,6 @@ # include "hidusage.h" #endif
-#ifdef WORDS_BIGENDIAN -#define LE_DWORD(x) RtlUlongByteSwap(x) -#else -#define LE_DWORD(x) (x) -#endif - #include "unix_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(hid); @@ -195,6 +189,8 @@ struct lnxev_device { struct base_device base;
+ LONG abs_min[ABS_CNT]; + LONG abs_max[ABS_CNT]; BYTE abs_map[ABS_CNT]; BYTE rel_map[REL_CNT]; BYTE hat_map[8]; @@ -516,7 +512,15 @@ static void set_abs_axis_value(struct unix_device *iface, int code, int value)
if (code < ABS_HAT0X || code > ABS_HAT3Y) { + LONG min = impl->abs_min[code], range = impl->abs_max[code] - impl->abs_min[code]; if (!(code = impl->abs_map[code])) return; + + if (impl->is_gamepad) + { + double scale = (code == 5 || code == 6 ? 32767.0 : 65535.0) / range; + value = (value - min) * scale - (code == 5 || code == 6 ? 0 : 32768); + } + hid_device_set_abs_axis(iface, code - 1, value); } else if ((code - ABS_HAT0X) % 2) @@ -554,41 +558,42 @@ static NTSTATUS build_report_descriptor(struct unix_device *iface, struct udev_d if (!hid_device_begin_report_descriptor(iface, &device_usage)) return STATUS_NO_MEMORY;
- if (!hid_device_begin_input_report(iface, &device_usage)) - return STATUS_NO_MEMORY; - - for (i = 0; i < ABS_CNT; i++) + if (impl->is_gamepad) { - USAGE_AND_PAGE usage = absolute_usages[i]; - if (!impl->abs_map[i]) continue; - ioctl(impl->base.device_fd, EVIOCGABS(i), abs_info + i); - if (!hid_device_add_axes(iface, 1, usage.UsagePage, &usage.Usage, FALSE, - LE_DWORD(abs_info[i].minimum), LE_DWORD(abs_info[i].maximum))) + if (!hid_device_add_gamepad(iface)) return STATUS_NO_MEMORY; } - - for (i = 0; i < REL_CNT; i++) + else { - USAGE_AND_PAGE usage = relative_usages[i]; - if (!impl->rel_map[i]) continue; - if (!hid_device_add_axes(iface, 1, usage.UsagePage, &usage.Usage, TRUE, - INT32_MIN, INT32_MAX)) + if (!hid_device_begin_input_report(iface, &device_usage)) return STATUS_NO_MEMORY; - }
- if (impl->is_gamepad) - { - if (!hid_device_add_hatswitch(iface, 1)) return STATUS_NO_MEMORY; - if (!hid_device_add_buttons(iface, HID_USAGE_PAGE_BUTTON, 1, 15)) return STATUS_NO_MEMORY; - } - else - { + for (i = 0; i < ABS_CNT; i++) + { + LONG min = impl->abs_min[i], max = impl->abs_max[i]; + USAGE_AND_PAGE usage = absolute_usages[i]; + if (!impl->abs_map[i]) continue; + ioctl(impl->base.device_fd, EVIOCGABS(i), abs_info + i); + if (!hid_device_add_axes(iface, 1, usage.UsagePage, &usage.Usage, FALSE, + min, max)) + return STATUS_NO_MEMORY; + } + + for (i = 0; i < REL_CNT; i++) + { + USAGE_AND_PAGE usage = relative_usages[i]; + if (!impl->rel_map[i]) continue; + if (!hid_device_add_axes(iface, 1, usage.UsagePage, &usage.Usage, TRUE, + INT32_MIN, INT32_MAX)) + return STATUS_NO_MEMORY; + } + if (impl->hat_count && !hid_device_add_hatswitch(iface, impl->hat_count)) return STATUS_NO_MEMORY; if (impl->button_count && !hid_device_add_buttons(iface, HID_USAGE_PAGE_BUTTON, 1, impl->button_count)) return STATUS_NO_MEMORY; - }
- if (!hid_device_end_input_report(iface)) - return STATUS_NO_MEMORY; + if (!hid_device_end_input_report(iface)) + return STATUS_NO_MEMORY; + }
impl->haptic_effect_id = -1; for (i = 0; i < ARRAY_SIZE(impl->effect_ids); ++i) impl->effect_ids[i] = -1; @@ -1222,9 +1227,13 @@ static NTSTATUS lnxev_device_create(struct udev_device *dev, int fd, const char for (int i = 0; i < ABS_CNT; i++) { USAGE_AND_PAGE usage = absolute_usages[i]; + struct input_absinfo abs; if (!usage.UsagePage || !usage.Usage) continue; if (!test_bit(info.abs, i)) continue; + ioctl(fd, EVIOCGABS(i), &abs); impl->abs_map[i] = ++axis_count; + impl->abs_min[i] = abs.minimum; + impl->abs_max[i] = abs.maximum; }
for (int i = 0, count = 0; i < REL_CNT; i++) @@ -1253,6 +1262,7 @@ static NTSTATUS lnxev_device_create(struct udev_device *dev, int fd, const char
if ((impl->is_gamepad = desc.is_gamepad)) { + static const int gamepad_axes[] = {1, 2, 5, 3, 4, 6}; static const UINT gamepad_buttons[] = { BTN_A, @@ -1272,9 +1282,18 @@ static NTSTATUS lnxev_device_create(struct udev_device *dev, int fd, const char BTN_TR2, };
+ memset(impl->abs_map, 0, sizeof(impl->abs_map)); memset(impl->button_map, 0, sizeof(impl->button_map)); impl->button_count = 0;
+ for (int i = 0, count = 0; i < ABS_CNT; i++) + { + USAGE_AND_PAGE usage = absolute_usages[i]; + if (!usage.UsagePage || !usage.Usage) continue; + if (!test_bit(info.abs, i)) continue; + impl->abs_map[i] = gamepad_axes[count++]; + } + for (int i = 0; i < ARRAY_SIZE(gamepad_buttons); i++) { int button = gamepad_buttons[i];