Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
* Send the patches separately from the others, they should not conflict
* Force the &MI_00 suffix on all gamepad devices where we cannot figure the correct interface number (SDL and IOHID bus).
dlls/winexinput.sys/winexinput.inf | 13 +++++++++++++ 1 file changed, 13 insertions(+)
diff --git a/dlls/winexinput.sys/winexinput.inf b/dlls/winexinput.sys/winexinput.inf index 2f388c190ca..a2b74863c63 100644 --- a/dlls/winexinput.sys/winexinput.inf +++ b/dlls/winexinput.sys/winexinput.inf @@ -8,6 +8,19 @@ Wine=mfg_section
[mfg_section] Wine XInput compatible device=device_section,WINEBUS\WINE_COMP_XINPUT +Xbox Controller=device_section,WINEBUS\VID_045E&PID_0202&MI_00 +Xbox Controller S=device_section,WINEBUS\VID_045E&PID_0285&MI_00 +Xbox Controller S=device_section,WINEBUS\VID_045E&PID_0289&MI_00 +Xbox360 Controller=device_section,WINEBUS\VID_045E&PID_028E&MI_00 +Xbox360 Wireless Controller=device_section,WINEBUS\VID_045E&PID_028F&MI_00 +Xbox One Controller=device_section,WINEBUS\VID_045E&PID_02D1&MI_00 +Xbox One Controller (Covert Forces/Firmware 2015)=device_section,WINEBUS\VID_045E&PID_02DD&MI_00 +Xbox One X Controller=device_section,WINEBUS\VID_045E&PID_02E0&MI_00 +Xbox One Elite Controller=device_section,WINEBUS\VID_045E&PID_02E3&MI_00 +Wireless XBox Controller Dongle=device_section,WINEBUS\VID_045E&PID_02E6&MI_00 +Xbox One S Controller=device_section,WINEBUS\VID_045E&PID_02EA&MI_00 +Xbox One S Controller (Firmware 2017)=device_section,WINEBUS\VID_045E&PID_02FD&MI_00 +Xbox 360 Wireless Adapter=device_section,WINEBUS\VID_045E&PID_0719&MI_00
[device_section.Services] AddService = xinput,0x2,svc_section
As we're unable to figure the interface number, unlike the UDEV bus which usually always is.
This will make sure the devices will be reported a bit more consistencly between buses, and for instance that the XBox controllers all have the &MI_00 suffix to match them in winexinput.inf.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winebus.sys/bus_iohid.c | 1 - dlls/winebus.sys/bus_sdl.c | 1 - 2 files changed, 2 deletions(-)
diff --git a/dlls/winebus.sys/bus_iohid.c b/dlls/winebus.sys/bus_iohid.c index 3df60a1b516..61758304837 100644 --- a/dlls/winebus.sys/bus_iohid.c +++ b/dlls/winebus.sys/bus_iohid.c @@ -293,7 +293,6 @@ static void handle_DeviceMatchingCallback(void *context, IOReturn result, void * struct device_desc desc = { .busid = busidW, - .input = -1, .serial = {'0','0','0','0',0}, }; struct platform_private *private; diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c index 80252e7e6b1..ccaac6d9d94 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -737,7 +737,6 @@ static void sdl_add_device(unsigned int index) struct device_desc desc = { .busid = sdl_busidW, - .input = -1, .serial = {'0','0','0','0',0}, }; struct platform_private *private;
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winebus.sys/main.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/dlls/winebus.sys/main.c b/dlls/winebus.sys/main.c index 42614b09f3a..65385055729 100644 --- a/dlls/winebus.sys/main.c +++ b/dlls/winebus.sys/main.c @@ -289,13 +289,26 @@ static WCHAR *get_device_id(DEVICE_OBJECT *device)
static WCHAR *get_hardware_ids(DEVICE_OBJECT *device) { + static const WCHAR input_formatW[] = {'&','M','I','_','%','0','2','u',0}; + static const WCHAR winebus_formatW[] = + { + 'W','I','N','E','B','U','S','\','V','I','D','_','%','0','4','X', + '&','P','I','D','_','%','0','4','X',0 + }; struct device_extension *ext = (struct device_extension *)device->DeviceExtension; + DWORD pos = 0, len = 0, input_len = 0, winebus_len = 25; WCHAR *dst;
- if ((dst = ExAllocatePool(PagedPool, (strlenW(ext->desc.busid) + 2) * sizeof(WCHAR)))) + if (ext->desc.input != -1) input_len = 14; + + len += winebus_len + input_len + 1; + + if ((dst = ExAllocatePool(PagedPool, (len + 1) * sizeof(WCHAR)))) { - strcpyW(dst, ext->desc.busid); - dst[strlenW(dst) + 1] = 0; + pos += snprintfW(dst + pos, len - pos, winebus_formatW, ext->desc.vid, ext->desc.pid); + if (input_len) pos += snprintfW(dst + pos, len - pos, input_formatW, ext->desc.input); + pos += 1; + dst[pos] = 0; }
return dst;
Native XBox controllers should now be listed in winexinput.inf, and the axis or button checks should be enough to set the compatible id anyway.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winebus.sys/bus.h | 2 -- dlls/winebus.sys/bus_iohid.c | 56 ++++++++++++++++-------------------- dlls/winebus.sys/bus_udev.c | 13 ++------- dlls/winebus.sys/main.c | 13 --------- 4 files changed, 28 insertions(+), 56 deletions(-)
diff --git a/dlls/winebus.sys/bus.h b/dlls/winebus.sys/bus.h index 75ff218c26d..c9af7cea1f0 100644 --- a/dlls/winebus.sys/bus.h +++ b/dlls/winebus.sys/bus.h @@ -34,6 +34,4 @@ DEVICE_OBJECT *bus_find_hid_device(const WCHAR *bus_id, void *platform_dev) DECL void process_hid_report(DEVICE_OBJECT *device, BYTE *report, DWORD length) DECLSPEC_HIDDEN;
/* General Bus Functions */ -BOOL is_xbox_gamepad(WORD vid, WORD pid) DECLSPEC_HIDDEN; - extern HANDLE driver_key DECLSPEC_HIDDEN; diff --git a/dlls/winebus.sys/bus_iohid.c b/dlls/winebus.sys/bus_iohid.c index 61758304837..fd80af8f29f 100644 --- a/dlls/winebus.sys/bus_iohid.c +++ b/dlls/winebus.sys/bus_iohid.c @@ -315,46 +315,40 @@ static void handle_DeviceMatchingCallback(void *context, IOReturn result, void * if (IOHIDDeviceConformsTo(IOHIDDevice, kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad) || IOHIDDeviceConformsTo(IOHIDDevice, kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick)) { - if (is_xbox_gamepad(desc.vid, desc.pid)) - desc.is_gamepad = TRUE; - else + int axes = 0, buttons = 0; + CFArrayRef element_array = IOHIDDeviceCopyMatchingElements(IOHIDDevice, NULL, kIOHIDOptionsTypeNone); + + if (element_array) { - int axes=0, buttons=0; - CFArrayRef element_array = IOHIDDeviceCopyMatchingElements( - IOHIDDevice, NULL, kIOHIDOptionsTypeNone); - - if (element_array) { - CFIndex index; - CFIndex count = CFArrayGetCount(element_array); - for (index = 0; index < count; index++) + CFIndex index; + CFIndex count = CFArrayGetCount(element_array); + for (index = 0; index < count; index++) + { + IOHIDElementRef element = (IOHIDElementRef)CFArrayGetValueAtIndex(element_array, index); + if (element) { - IOHIDElementRef element = (IOHIDElementRef)CFArrayGetValueAtIndex(element_array, index); - if (element) + int type = IOHIDElementGetType(element); + if (type == kIOHIDElementTypeInput_Button) buttons++; + if (type == kIOHIDElementTypeInput_Axis) axes++; + if (type == kIOHIDElementTypeInput_Misc) { - int type = IOHIDElementGetType(element); - if (type == kIOHIDElementTypeInput_Button) buttons++; - if (type == kIOHIDElementTypeInput_Axis) axes++; - if (type == kIOHIDElementTypeInput_Misc) + uint32_t usage = IOHIDElementGetUsage(element); + switch (usage) { - uint32_t usage = IOHIDElementGetUsage(element); - switch (usage) - { - case kHIDUsage_GD_X: - case kHIDUsage_GD_Y: - case kHIDUsage_GD_Z: - case kHIDUsage_GD_Rx: - case kHIDUsage_GD_Ry: - case kHIDUsage_GD_Rz: - case kHIDUsage_GD_Slider: - axes ++; - } + case kHIDUsage_GD_X: + case kHIDUsage_GD_Y: + case kHIDUsage_GD_Z: + case kHIDUsage_GD_Rx: + case kHIDUsage_GD_Ry: + case kHIDUsage_GD_Rz: + case kHIDUsage_GD_Slider: axes++; } } } - CFRelease(element_array); } - desc.is_gamepad = (axes == 6 && buttons >= 14); + CFRelease(element_array); } + desc.is_gamepad = (axes == 6 && buttons >= 14); }
TRACE("dev %p, desc %s.\n", IOHIDDevice, debugstr_device_desc(&desc)); diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index 78e74de842a..d650dd2ba3e 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -1138,6 +1138,7 @@ static void udev_add_device(struct udev_device *dev) else if (!strcmp(subsystem, "input")) { struct input_id device_id = {0}; + int axes = 0, buttons = 0; char device_uid[255];
desc.busid = lnxev_busidW; @@ -1154,23 +1155,15 @@ static void udev_add_device(struct udev_device *dev) device_uid[0] = 0; if (ioctl(fd, EVIOCGUNIQ(254), device_uid) >= 0 && device_uid[0]) MultiByteToWideChar(CP_UNIXCP, 0, device_uid, -1, desc.serial, ARRAY_SIZE(desc.serial)); - } -#endif
- if (!desc.serial[0]) lstrcpyW(desc.serial, base_serial); - - if (is_xbox_gamepad(desc.vid, desc.pid)) - desc.is_gamepad = TRUE; -#ifdef HAS_PROPER_INPUT_HEADER - else - { - int axes=0, buttons=0; axes = count_abs_axis(fd); buttons = count_buttons(fd, NULL); desc.is_gamepad = (axes == 6 && buttons >= 14); } #endif
+ if (!desc.serial[0]) lstrcpyW(desc.serial, base_serial); + TRACE("dev %p, node %s, desc %s.\n", dev, debugstr_a(devnode), debugstr_device_desc(&desc));
if (strcmp(subsystem, "hidraw") == 0) diff --git a/dlls/winebus.sys/main.c b/dlls/winebus.sys/main.c index 65385055729..c505ff3a1f0 100644 --- a/dlls/winebus.sys/main.c +++ b/dlls/winebus.sys/main.c @@ -1094,19 +1094,6 @@ void process_hid_report(DEVICE_OBJECT *device, BYTE *report, DWORD length) LeaveCriticalSection(&ext->cs); }
-BOOL is_xbox_gamepad(WORD vid, WORD pid) -{ - int i; - - if (vid != VID_MICROSOFT) - return FALSE; - - for (i = 0; i < ARRAY_SIZE(XBOX_CONTROLLERS); i++) - if (pid == XBOX_CONTROLLERS[i].pid) return TRUE; - - return FALSE; -} - static NTSTATUS WINAPI driver_add_device(DRIVER_OBJECT *driver, DEVICE_OBJECT *pdo) { NTSTATUS ret;
I'm not completely sure to see what's wrong with these patches but I'm going to assume that it wasn't great to have a hardcoded VID&PID list from the beginning and that it would be better to use a good heuristic instead.
The axis and button count heuristic should cover the XBox gamepad list, but I don't think it's good, as it will match any joystick with a lot of axes and buttons, although they may not be gamepads.
It could also be interesting to have some user-facing configurable settings so we can force or prevent some devices to be seen by XInput (and use DInput instead).
I'll just keep the is_xbox_gamepad helper for now, and resend something later. What I wanted to move to winexinput was actually more the custom product strings rather than this helper.