Inverting left/right trigger usages and Y values, so that WGI doesn't need to mess with axes order.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/windows.gaming.input/provider.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/dlls/windows.gaming.input/provider.c b/dlls/windows.gaming.input/provider.c index 69737dbafbd..b1d6b1c6c81 100644 --- a/dlls/windows.gaming.input/provider.c +++ b/dlls/windows.gaming.input/provider.c @@ -170,16 +170,18 @@ static HRESULT WINAPI wine_provider_get_Type( IWineGameControllerProvider *iface { struct provider *impl = impl_from_IWineGameControllerProvider( iface ); DIDEVICEINSTANCEW instance = {.dwSize = sizeof(DIDEVICEINSTANCEW)}; + const WCHAR *tmp; HRESULT hr;
TRACE( "iface %p, value %p.\n", iface, value );
if (FAILED(hr = IDirectInputDevice8_GetDeviceInfo( impl->dinput_device, &instance ))) return hr;
- switch (GET_DIDEVICE_TYPE( instance.dwDevType )) + if ((tmp = wcschr( impl->device_path + 8, '#' )) && !wcsnicmp( tmp - 6, L"&XI_", 4 )) + *value = WineGameControllerType_Gamepad; + else switch (GET_DIDEVICE_TYPE( instance.dwDevType )) { case DI8DEVTYPE_DRIVING: *value = WineGameControllerType_RacingWheel; break; - case DI8DEVTYPE_GAMEPAD: *value = WineGameControllerType_Gamepad; break; default: { DWORD count = 0;
From: Rémi Bernon rbernon@codeweavers.com
Inverting left/right trigger usages and Y values, so that WGI doesn't need to mess with axes order. --- dlls/windows.gaming.input/gamepad.c | 4 ++-- dlls/winebus.sys/bus_sdl.c | 11 +++++++++-- dlls/winebus.sys/bus_udev.c | 1 + dlls/winebus.sys/hid.c | 6 ++++-- dlls/winexinput.sys/main.c | 4 ++-- dlls/xinput1_3/main.c | 4 ++-- 6 files changed, 20 insertions(+), 10 deletions(-)
diff --git a/dlls/windows.gaming.input/gamepad.c b/dlls/windows.gaming.input/gamepad.c index def2c9dcf5e..ba0944cd6da 100644 --- a/dlls/windows.gaming.input/gamepad.c +++ b/dlls/windows.gaming.input/gamepad.c @@ -322,10 +322,10 @@ static HRESULT WINAPI gamepad_GetCurrentReading( IGamepad *iface, struct Gamepad }
value->LeftThumbstickX = 2. * state.axes[0] - 1.; - value->LeftThumbstickY = 1. - 2. * state.axes[1]; + value->LeftThumbstickY = 2. * state.axes[1] - 1.; value->LeftTrigger = state.axes[2]; value->RightThumbstickX = 2. * state.axes[3] - 1.; - value->RightThumbstickY = 1. - 2. * state.axes[4]; + value->RightThumbstickY = 2. * state.axes[4] - 1.; value->RightTrigger = state.axes[5];
value->Timestamp = state.timestamp; diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c index 6e2c8bef3e4..a9d28fb28ac 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -392,9 +392,13 @@ static NTSTATUS build_controller_report_descriptor(struct unix_device *iface) 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 (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)); + { + int value = pSDL_GameControllerGetAxis(impl->sdl_controller, i); + if (i == SDL_CONTROLLER_AXIS_LEFTY || i == SDL_CONTROLLER_AXIS_RIGHTY) + value = -value - 1; /* match XUSB / GIP protocol */ + hid_device_set_abs_axis(iface, i, value); + }
state = pSDL_GameControllerGetButton(impl->sdl_controller, SDL_CONTROLLER_BUTTON_DPAD_UP); hid_device_move_hatswitch(iface, 0, 0, state ? -1 : +1); @@ -883,6 +887,9 @@ static BOOL set_report_from_controller_event(struct sdl_device *impl, SDL_Event { SDL_ControllerAxisEvent *ie = &event->caxis;
+ if (ie->axis == SDL_CONTROLLER_AXIS_LEFTY || ie->axis == SDL_CONTROLLER_AXIS_RIGHTY) + ie->value = -ie->value - 1; /* match XUSB / GIP protocol */ + 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 9951e3d0ec8..f83b0998f27 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -519,6 +519,7 @@ static void set_abs_axis_value(struct unix_device *iface, int code, int value) { double scale = (code == 5 || code == 6 ? 32767.0 : 65535.0) / range; value = (value - min) * scale - (code == 5 || code == 6 ? 0 : 32768); + if (code == 2 || code == 4) value = -value - 1; /* match XUSB / GIP protocol */ }
hid_device_set_abs_axis(iface, code - 1, value); diff --git a/dlls/winebus.sys/hid.c b/dlls/winebus.sys/hid.c index 5b274d20e18..a6318143342 100644 --- a/dlls/winebus.sys/hid.c +++ b/dlls/winebus.sys/hid.c @@ -348,12 +348,14 @@ 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}; + static const USAGE lt = HID_USAGE_GENERIC_Z; + static const USAGE rt = 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_axes(iface, 1, HID_USAGE_PAGE_GENERIC, <, FALSE, 0, 32767)) return FALSE; + if (!hid_device_add_axes(iface, 1, HID_USAGE_PAGE_GENERIC, &rt, 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; diff --git a/dlls/winexinput.sys/main.c b/dlls/winexinput.sys/main.c index 45c6835bfe7..48743d6adf6 100644 --- a/dlls/winexinput.sys/main.c +++ b/dlls/winexinput.sys/main.c @@ -236,9 +236,9 @@ static void translate_report_to_xinput_state(struct func_device *fdo) fdo->xinput_state.buttons |= (1 << (usages[i] - 1)); } fdo->xinput_state.lx_axis = scale_value(lx, &fdo->lx_caps, 0, 65535); - fdo->xinput_state.ly_axis = scale_value(ly, &fdo->ly_caps, 0, 65535); + fdo->xinput_state.ly_axis = scale_value(-ly - 1, &fdo->ly_caps, 0, 65535); fdo->xinput_state.rx_axis = scale_value(rx, &fdo->rx_caps, 0, 65535); - fdo->xinput_state.ry_axis = scale_value(ry, &fdo->ry_caps, 0, 65535); + fdo->xinput_state.ry_axis = scale_value(-ry - 1, &fdo->ry_caps, 0, 65535); rt = scale_value(rt, &fdo->rt_caps, 0, 255); lt = scale_value(lt, &fdo->lt_caps, 0, 255); fdo->xinput_state.trigger = 0x8000 + (lt - rt) * 128; diff --git a/dlls/xinput1_3/main.c b/dlls/xinput1_3/main.c index c2539483398..b9971a11e1f 100644 --- a/dlls/xinput1_3/main.c +++ b/dlls/xinput1_3/main.c @@ -625,7 +625,7 @@ static void read_controller_state(struct xinput_controller *controller)
status = HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Y, &value, controller->hid.preparsed, report_buf, report_len); if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetUsageValue HID_USAGE_PAGE_GENERIC / HID_USAGE_GENERIC_Y returned %#lx\n", status); - else state.Gamepad.sThumbLY = -scale_value(value, &controller->hid.ly_caps, -32768, 32767) - 1; + else state.Gamepad.sThumbLY = scale_value(value, &controller->hid.ly_caps, -32768, 32767);
status = HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RX, &value, controller->hid.preparsed, report_buf, report_len); if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetUsageValue HID_USAGE_PAGE_GENERIC / HID_USAGE_GENERIC_RX returned %#lx\n", status); @@ -633,7 +633,7 @@ static void read_controller_state(struct xinput_controller *controller)
status = HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RY, &value, controller->hid.preparsed, report_buf, report_len); if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetUsageValue HID_USAGE_PAGE_GENERIC / HID_USAGE_GENERIC_RY returned %#lx\n", status); - else state.Gamepad.sThumbRY = -scale_value(value, &controller->hid.ry_caps, -32768, 32767) - 1; + else state.Gamepad.sThumbRY = scale_value(value, &controller->hid.ry_caps, -32768, 32767);
status = HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RZ, &value, controller->hid.preparsed, report_buf, report_len); if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetUsageValue HID_USAGE_PAGE_GENERIC / HID_USAGE_GENERIC_RZ returned %#lx\n", status);
From: Rémi Bernon rbernon@codeweavers.com
To avoid the builtin axis mapping that c_dfDIJoystick2 does, we need IRawGameController to expose the axes / povs / buttons in their raw order. --- dlls/windows.gaming.input/gamepad.c | 8 +- dlls/windows.gaming.input/provider.c | 156 ++++++++++++++++++++++++++- 2 files changed, 159 insertions(+), 5 deletions(-)
diff --git a/dlls/windows.gaming.input/gamepad.c b/dlls/windows.gaming.input/gamepad.c index ba0944cd6da..ecac632ec3b 100644 --- a/dlls/windows.gaming.input/gamepad.c +++ b/dlls/windows.gaming.input/gamepad.c @@ -321,11 +321,11 @@ static HRESULT WINAPI gamepad_GetCurrentReading( IGamepad *iface, struct Gamepad break; }
- value->LeftThumbstickX = 2. * state.axes[0] - 1.; - value->LeftThumbstickY = 2. * state.axes[1] - 1.; - value->LeftTrigger = state.axes[2]; + value->LeftThumbstickX = 2. * state.axes[1] - 1.; + value->LeftThumbstickY = 2. * state.axes[0] - 1.; + value->LeftTrigger = state.axes[4]; value->RightThumbstickX = 2. * state.axes[3] - 1.; - value->RightThumbstickY = 2. * state.axes[4] - 1.; + value->RightThumbstickY = 2. * state.axes[2] - 1.; value->RightTrigger = state.axes[5];
value->Timestamp = state.timestamp; diff --git a/dlls/windows.gaming.input/provider.c b/dlls/windows.gaming.input/provider.c index b1d6b1c6c81..7153ec38ad7 100644 --- a/dlls/windows.gaming.input/provider.c +++ b/dlls/windows.gaming.input/provider.c @@ -565,6 +565,160 @@ failed: CloseHandle( device ); }
+static const DIOBJECTDATAFORMAT data_format_objs[] = +{ + {NULL,DIJOFS_X,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_Y,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_Z,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_RX,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_RY,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_RZ,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_SLIDER(0),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_SLIDER(1),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_POV(0),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_POV(1),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_POV(2),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_POV(3),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(0),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(1),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(2),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(3),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(4),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(5),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(6),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(7),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(8),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(9),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(10),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(11),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(12),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(13),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(14),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(15),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(16),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(17),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(18),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(19),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(20),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(21),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(22),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(23),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(24),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(25),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(26),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(27),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(28),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(29),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(30),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(31),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(32),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(33),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(34),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(35),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(36),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(37),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(38),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(39),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(40),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(41),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(42),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(43),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(44),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(45),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(46),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(47),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(48),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(49),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(50),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(51),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(52),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(53),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(54),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(55),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(56),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(57),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(58),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(59),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(60),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(61),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(62),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(63),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(64),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(65),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(66),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(67),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(68),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(69),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(70),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(71),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(72),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(73),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(74),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(75),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(76),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(77),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(78),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(79),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(80),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(81),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(82),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(83),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(84),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(85),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(86),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(87),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(88),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(89),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(90),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(91),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(92),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(93),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(94),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(95),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(96),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(97),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(98),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(99),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(100),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(101),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(102),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(103),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(104),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(105),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(106),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(107),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(108),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(109),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(110),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(111),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(112),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(113),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(114),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(115),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(116),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(117),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(118),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(119),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(120),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(121),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(122),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(123),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(124),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(125),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(126),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, + {NULL,DIJOFS_BUTTON(127),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE}, +}; + +static const DIDATAFORMAT data_format = +{ + sizeof(DIDATAFORMAT), + sizeof(DIOBJECTDATAFORMAT), + DIDF_ABSAXIS, + sizeof(DIJOYSTATE2), + ARRAY_SIZE(data_format_objs), + (LPDIOBJECTDATAFORMAT)data_format_objs +}; + void provider_create( const WCHAR *device_path ) { IDirectInputDevice8W *dinput_device; @@ -589,7 +743,7 @@ void provider_create( const WCHAR *device_path ) if (FAILED(hr)) return;
if (FAILED(hr = IDirectInputDevice8_SetCooperativeLevel( dinput_device, 0, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE ))) goto done; - if (FAILED(hr = IDirectInputDevice8_SetDataFormat( dinput_device, &c_dfDIJoystick2 ))) goto done; + if (FAILED(hr = IDirectInputDevice8_SetDataFormat( dinput_device, &data_format ))) goto done; if (FAILED(hr = IDirectInputDevice8_Acquire( dinput_device ))) goto done;
if (!(impl = calloc( 1, sizeof(*impl) ))) goto done;
From: Rémi Bernon rbernon@codeweavers.com
To avoid exposing it with the other buttons, the XUSB / GIP frontends don't expose it to applications (for instance in Windows.Gaming.Input). --- dlls/dinput/joystick_hid.c | 2 +- dlls/winebus.sys/bus_sdl.c | 30 ++++++++++++++++-------------- dlls/winebus.sys/bus_udev.c | 18 ++++++++++-------- dlls/winebus.sys/hid.c | 3 ++- dlls/xinput1_3/main.c | 6 +++++- 5 files changed, 34 insertions(+), 25 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index 27d08fd2af2..e492fa51bbf 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -1288,7 +1288,7 @@ static HRESULT hid_joystick_read( IDirectInputDevice8W *iface ) { usages = impl->usages_buf + count; if (usages->UsagePage != HID_USAGE_PAGE_BUTTON) - FIXME( "unimplemented usage page %x.\n", usages->UsagePage ); + WARN( "unimplemented usage page %x.\n", usages->UsagePage ); else if (usages->Usage >= 128) FIXME( "ignoring extraneous button %d.\n", usages->Usage ); else diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c index a9d28fb28ac..0529b35fbea 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -856,29 +856,31 @@ static BOOL set_report_from_controller_event(struct sdl_device *impl, SDL_Event SDL_ControllerButtonEvent *ie = &event->cbutton; int button;
- switch ((button = ie->button)) + switch (ie->button) { - case SDL_CONTROLLER_BUTTON_DPAD_UP: - hid_device_move_hatswitch(iface, 0, 0, ie->state ? -1 : +1); - break; - case SDL_CONTROLLER_BUTTON_DPAD_DOWN: - hid_device_move_hatswitch(iface, 0, 0, ie->state ? +1 : -1); - break; - case SDL_CONTROLLER_BUTTON_DPAD_LEFT: - hid_device_move_hatswitch(iface, 0, ie->state ? -1 : +1, 0); - break; - case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: - hid_device_move_hatswitch(iface, 0, ie->state ? +1 : -1, 0); - break; + case SDL_CONTROLLER_BUTTON_A: button = 0; break; + case SDL_CONTROLLER_BUTTON_B: button = 1; break; + case SDL_CONTROLLER_BUTTON_X: button = 2; break; + case SDL_CONTROLLER_BUTTON_Y: button = 3; break; case SDL_CONTROLLER_BUTTON_LEFTSHOULDER: button = 4; break; case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER: button = 5; break; case SDL_CONTROLLER_BUTTON_BACK: button = 6; break; case SDL_CONTROLLER_BUTTON_START: button = 7; break; case SDL_CONTROLLER_BUTTON_LEFTSTICK: button = 8; break; case SDL_CONTROLLER_BUTTON_RIGHTSTICK: button = 9; break; - case SDL_CONTROLLER_BUTTON_GUIDE: button = 10; break; + case SDL_CONTROLLER_BUTTON_DPAD_UP: button = 10; break; + case SDL_CONTROLLER_BUTTON_DPAD_DOWN: button = 11; break; + case SDL_CONTROLLER_BUTTON_DPAD_LEFT: button = 12; break; + case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: button = 13; break; + case SDL_CONTROLLER_BUTTON_GUIDE: button = 16; break; + default: button = -1; break; }
+ if (button == -1) break; + if (button == 10) hid_device_move_hatswitch(iface, 0, 0, ie->state ? -1 : +1); + if (button == 11) hid_device_move_hatswitch(iface, 0, 0, ie->state ? +1 : -1); + if (button == 12) hid_device_move_hatswitch(iface, 0, ie->state ? -1 : +1, 0); + if (button == 13) hid_device_move_hatswitch(iface, 0, ie->state ? +1 : -1, 0); hid_device_set_button(iface, button, ie->state); 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 f83b0998f27..65cabff09e4 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -529,8 +529,8 @@ static void set_abs_axis_value(struct unix_device *iface, int code, int value) 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_button(iface, 10, value < 0); + hid_device_set_button(iface, 11, value > 0); } hid_device_set_hatswitch_y(iface, code - 1, value); } @@ -539,8 +539,8 @@ static void set_abs_axis_value(struct unix_device *iface, int code, int value) 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_button(iface, 12, value < 0); + hid_device_set_button(iface, 13, value > 0); } hid_device_set_hatswitch_x(iface, code - 1, value); } @@ -675,10 +675,10 @@ static BOOL set_report_from_event(struct unix_device *iface, struct input_event 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); + if (button == 11) hid_device_set_hatswitch_y(iface, 0, -1); + if (button == 12) hid_device_set_hatswitch_y(iface, 0, +1); + if (button == 13) hid_device_set_hatswitch_x(iface, 0, -1); + if (button == 14) hid_device_set_hatswitch_x(iface, 0, +1); } hid_device_set_button(iface, button - 1, ie->value); return FALSE; @@ -1301,6 +1301,7 @@ static NTSTATUS lnxev_device_create(struct udev_device *dev, int fd, const char if (!test_bit(info.key, button)) continue; if (impl->button_count > (impl->hat_count ? 10 : 14)) break; impl->button_map[button] = ++impl->button_count; + if (impl->hat_count && impl->button_count == 11) impl->button_map[button] = 17; }
for (int i = BTN_MISC; i < KEY_MAX; i++) @@ -1309,6 +1310,7 @@ static NTSTATUS lnxev_device_create(struct udev_device *dev, int fd, const char if (impl->button_count > (impl->hat_count ? 10 : 14)) break; if (!test_bit(info.key, i)) continue; impl->button_map[i] = ++impl->button_count; + if (impl->hat_count && impl->button_count == 11) impl->button_map[i] = 17; } }
diff --git a/dlls/winebus.sys/hid.c b/dlls/winebus.sys/hid.c index a6318143342..46ad0c69065 100644 --- a/dlls/winebus.sys/hid.c +++ b/dlls/winebus.sys/hid.c @@ -357,7 +357,8 @@ BOOL hid_device_add_gamepad(struct unix_device *iface) if (!hid_device_add_axes(iface, 1, HID_USAGE_PAGE_GENERIC, <, FALSE, 0, 32767)) return FALSE; if (!hid_device_add_axes(iface, 1, HID_USAGE_PAGE_GENERIC, &rt, 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_add_buttons(iface, HID_USAGE_PAGE_BUTTON, 1, 14)) return FALSE; + if (!hid_device_add_buttons(iface, HID_USAGE_PAGE_VENDOR_DEFINED_BEGIN, 1, 8)) return FALSE; if (!hid_device_end_input_report(iface)) return FALSE;
return TRUE; diff --git a/dlls/xinput1_3/main.c b/dlls/xinput1_3/main.c index b9971a11e1f..831874dea73 100644 --- a/dlls/xinput1_3/main.c +++ b/dlls/xinput1_3/main.c @@ -597,10 +597,14 @@ static void read_controller_state(struct xinput_controller *controller) case 8: state.Gamepad.wButtons |= XINPUT_GAMEPAD_START; break; case 9: state.Gamepad.wButtons |= XINPUT_GAMEPAD_LEFT_THUMB; break; case 10: state.Gamepad.wButtons |= XINPUT_GAMEPAD_RIGHT_THUMB; break; - case 11: state.Gamepad.wButtons |= XINPUT_GAMEPAD_GUIDE; break; } }
+ button_length = ARRAY_SIZE(buttons); + status = HidP_GetUsages(HidP_Input, HID_USAGE_PAGE_VENDOR_DEFINED_BEGIN, 0, buttons, &button_length, controller->hid.preparsed, report_buf, report_len); + if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetUsages HID_USAGE_PAGE_VENDOR_DEFINED_BEGIN returned %#lx\n", status); + if (button_length) state.Gamepad.wButtons |= XINPUT_GAMEPAD_GUIDE; + status = HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_HATSWITCH, &value, controller->hid.preparsed, report_buf, report_len); if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetUsageValue HID_USAGE_PAGE_GENERIC / HID_USAGE_GENERIC_HATSWITCH returned %#lx\n", status); else switch (value)