This happens if any of the vendor-specific reports is used.
SDL triggers the mode switch when calling SDL_GameControllerSetSensorEnabled() on supported devices.
This is a one-way transition, i.e. cannot be undone without restarting the controller, so it's fine to have it tied to lifetime of winebus.
Signed-off-by: Arkadiusz Hiler ahiler@codeweavers.com --- dlls/winebus.sys/bus_udev.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index 2269f5b904e..4bd0907fdfd 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -360,6 +360,21 @@ static void hidraw_device_read_report(struct unix_device *iface) } }
+static void hidraw_disable_sony_quirks(struct unix_device *iface) +{ + struct hidraw_device *impl = hidraw_impl_from_unix_device(iface); + + /* FIXME: we may want to validate CRC at the end of the outbound HID reports, + * as controllers do not switch modes if it is incorrect. + */ + + if ((impl->quirks & QUIRK_DS4_BT)) + { + TRACE("Disabling report quirk for Bluetooth DualShock4 controller iface %p\n", iface); + impl->quirks &= ~QUIRK_DS4_BT; + } +} + static void hidraw_device_set_output_report(struct unix_device *iface, HID_XFER_PACKET *packet, IO_STATUS_BLOCK *io) { struct hidraw_device *impl = hidraw_impl_from_unix_device(iface); @@ -379,6 +394,7 @@ static void hidraw_device_set_output_report(struct unix_device *iface, HID_XFER_
if (count > 0) { + hidraw_disable_sony_quirks(iface); io->Information = count; io->Status = STATUS_SUCCESS; } @@ -411,6 +427,7 @@ static void hidraw_device_get_feature_report(struct unix_device *iface, HID_XFER
if (count > 0) { + hidraw_disable_sony_quirks(iface); io->Information = count; io->Status = STATUS_SUCCESS; } @@ -447,6 +464,7 @@ static void hidraw_device_set_feature_report(struct unix_device *iface, HID_XFER
if (count > 0) { + hidraw_disable_sony_quirks(iface); io->Information = count; io->Status = STATUS_SUCCESS; }
Signed-off-by: Arkadiusz Hiler ahiler@codeweavers.com --- dlls/winebus.sys/bus_udev.c | 40 +++++++++++++++++++++++++++++++++ dlls/winebus.sys/unix_private.h | 1 + dlls/winebus.sys/unixlib.c | 6 +++++ 3 files changed, 47 insertions(+)
diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index 4bd0907fdfd..c6185adf23d 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -117,6 +117,7 @@ static inline struct base_device *impl_from_unix_device(struct unix_device *ifac }
#define QUIRK_DS4_BT 0x1 +#define QUIRK_DUALSENSE_BT 0x2
struct hidraw_device { @@ -356,6 +357,36 @@ static void hidraw_device_read_report(struct unix_device *iface) buff[0] = 1; }
+ /* The behavior of DualSense is very similar to DS4 described above with a few exceptions. + * + * The report number #41 is used for the extended bluetooth input report. The report comes + * with only one extra byte in front and the format is not exactly the same as the one used + * for the report #1 so we need to shuffle a few bytes around. + * + * Basic #1 report: + * X Y Z RZ Buttons[3] TriggerLeft TriggerRight + * + * Extended #41 report: + * Prefix X Y Z Rz TriggerLeft TriggerRight Counter Buttons[3] ... + */ + if ((impl->quirks & QUIRK_DUALSENSE_BT) && report_buffer[0] == 0x31 && size >= 11) + { + BYTE trigger[2]; + size = 10; + buff += 1; + + buff[0] = 1; /* fake report #1 */ + + trigger[0] = buff[5]; /* TriggerLeft*/ + trigger[1] = buff[6]; /* TriggerRight */ + + buff[5] = buff[8]; /* Buttons[0] */ + buff[6] = buff[9]; /* Buttons[1] */ + buff[7] = buff[10]; /* Buttons[2] */ + buff[8] = trigger[0]; /* TriggerLeft */ + buff[9] = trigger[1]; /* TirggerRight */ + } + bus_event_queue_input_report(&event_queue, iface, buff, size); } } @@ -373,6 +404,12 @@ static void hidraw_disable_sony_quirks(struct unix_device *iface) TRACE("Disabling report quirk for Bluetooth DualShock4 controller iface %p\n", iface); impl->quirks &= ~QUIRK_DS4_BT; } + + if ((impl->quirks & QUIRK_DUALSENSE_BT)) + { + TRACE("Disabling report quirk for Bluetooth DualSense controller iface %p\n", iface); + impl->quirks &= ~QUIRK_DUALSENSE_BT; + } }
static void hidraw_device_set_output_report(struct unix_device *iface, HID_XFER_PACKET *packet, IO_STATUS_BLOCK *io) @@ -1219,6 +1256,9 @@ static void hidraw_set_quirks(struct hidraw_device *impl, DWORD bus_type, WORD v { if (bus_type == BUS_BLUETOOTH && is_dualshock4_gamepad(vid, pid)) impl->quirks |= QUIRK_DS4_BT; + + if (bus_type == BUS_BLUETOOTH && is_dualsense_gamepad(vid, pid)) + impl->quirks |= QUIRK_DUALSENSE_BT; }
static void udev_add_device(struct udev_device *dev, int fd) diff --git a/dlls/winebus.sys/unix_private.h b/dlls/winebus.sys/unix_private.h index efecf6cdbe3..e897251dea8 100644 --- a/dlls/winebus.sys/unix_private.h +++ b/dlls/winebus.sys/unix_private.h @@ -266,5 +266,6 @@ extern void hid_device_set_effect_state(struct unix_device *iface, BYTE index, B
BOOL is_xbox_gamepad(WORD vid, WORD pid) DECLSPEC_HIDDEN; BOOL is_dualshock4_gamepad(WORD vid, WORD pid) DECLSPEC_HIDDEN; +BOOL is_dualsense_gamepad(WORD vid, WORD pid) DECLSPEC_HIDDEN;
#endif /* __WINEBUS_UNIX_PRIVATE_H */ diff --git a/dlls/winebus.sys/unixlib.c b/dlls/winebus.sys/unixlib.c index 1269ae05c2b..3a7c3a16428 100644 --- a/dlls/winebus.sys/unixlib.c +++ b/dlls/winebus.sys/unixlib.c @@ -70,6 +70,12 @@ BOOL is_dualshock4_gamepad(WORD vid, WORD pid) return FALSE; }
+BOOL is_dualsense_gamepad(WORD vid, WORD pid) +{ + if (vid == 0x054c && pid == 0x0ce6) return TRUE; + return FALSE; +} + struct mouse_device { struct unix_device unix_device;
Signed-off-by: Rémi Bernon rbernon@codeweavers.com
This makes it so that all the devices on the HID bus now have Class, ClassGUID, Driver and DriverDesc register properties populated.
Without having at least Driver and Class set SDL2 refuses to use HID devices directly.
Signed-off-by: Arkadiusz Hiler ahiler@codeweavers.com --- dlls/hidclass.sys/Makefile.in | 2 ++ dlls/hidclass.sys/hidclass.rc | 20 ++++++++++++++++++++ dlls/hidclass.sys/input.inf | 13 +++++++++++++ loader/wine.inf.in | 1 + 4 files changed, 36 insertions(+) create mode 100644 dlls/hidclass.sys/hidclass.rc create mode 100644 dlls/hidclass.sys/input.inf
diff --git a/dlls/hidclass.sys/Makefile.in b/dlls/hidclass.sys/Makefile.in index 25a0396dabe..788828ad66a 100644 --- a/dlls/hidclass.sys/Makefile.in +++ b/dlls/hidclass.sys/Makefile.in @@ -5,3 +5,5 @@ IMPORTS = hal ntoskrnl user32 hidparse C_SRCS = \ device.c \ pnp.c + +RC_SRCS = hidclass.rc diff --git a/dlls/hidclass.sys/hidclass.rc b/dlls/hidclass.sys/hidclass.rc new file mode 100644 index 00000000000..409bdc16b45 --- /dev/null +++ b/dlls/hidclass.sys/hidclass.rc @@ -0,0 +1,20 @@ +/* + * Copyright 2022 Arkadiusz Hiler + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* @makedep: input.inf */ +1 WINE_DATA_FILE input.inf diff --git a/dlls/hidclass.sys/input.inf b/dlls/hidclass.sys/input.inf new file mode 100644 index 00000000000..d9222b13672 --- /dev/null +++ b/dlls/hidclass.sys/input.inf @@ -0,0 +1,13 @@ +[Version] +Signature="$CHICAGO$" +ClassGuid={745a17a0-74d3-11d0-b6fe-00a0c90f57da} +Class=HIDClass + +[Manufacturer] +Wine=mfg_section + +[mfg_section] +Wine HID device=device_section,HID\ + +[device_section.Services] +AddService = ,0x2 diff --git a/loader/wine.inf.in b/loader/wine.inf.in index c0251934dfc..afa344ffa80 100644 --- a/loader/wine.inf.in +++ b/loader/wine.inf.in @@ -5717,6 +5717,7 @@ protocol,"@%11%\ws2_32.dll,-3" services,"@%11%\ws2_32.dll,-4"
[InfFiles] +input.inf,"@%12%\hidclass.sys,-1" winebus.inf,"@%12%\winebus.sys,-1" winehid.inf,"@%12%\winehid.sys,-1" wineusb.inf,"@%12%\wineusb.sys,-1"
Signed-off-by: Rémi Bernon rbernon@codeweavers.com