[PATCH 0/2] MR4693: Draft: xinput: Implement XInputGetCapabilitiesEx.
For after the code freeze -- https://gitlab.winehq.org/wine/wine/-/merge_requests/4693
From: Etaash Mathamsetty <etaash.mathamsetty(a)gmail.com> --- dlls/xinput1_3/main.c | 32 ++++++++++++++++++++++++++++++++ dlls/xinput1_4/xinput1_4.spec | 1 + include/xinput.h | 11 +++++++++++ 3 files changed, 44 insertions(+) diff --git a/dlls/xinput1_3/main.c b/dlls/xinput1_3/main.c index e69553fba16..c4b2d5e871b 100644 --- a/dlls/xinput1_3/main.c +++ b/dlls/xinput1_3/main.c @@ -1129,3 +1129,35 @@ DWORD WINAPI DECLSPEC_HOTPATCH XInputGetBatteryInformation(DWORD index, BYTE typ return ERROR_NOT_SUPPORTED; } + +DWORD WINAPI DECLSPEC_HOTPATCH XInputGetCapabilitiesEx(DWORD unk, DWORD index, DWORD flags, XINPUT_CAPABILITIES_EX *caps) +{ + HIDD_ATTRIBUTES attr; + TRACE("unk %lu, index %lu, flags %#lx, capabilities %p.\n", unk, index, flags, caps); + + start_update_thread(); + + if (index >= XUSER_MAX_COUNT) return ERROR_BAD_ARGUMENTS; + + if (!controller_lock(&controllers[index])) return ERROR_DEVICE_NOT_CONNECTED; + + if (flags & XINPUT_FLAG_GAMEPAD && controllers[index].caps.SubType != XINPUT_DEVSUBTYPE_GAMEPAD) + { + controller_unlock(&controllers[index]); + return ERROR_DEVICE_NOT_CONNECTED; + } + + memcpy(&caps->Capabilities, &controllers[index].caps, sizeof(caps->Capabilities)); + + if (!HidD_GetAttributes(controllers[index].device, &attr)) + { + controller_unlock(&controllers[index]); + return ERROR_DEVICE_NOT_CONNECTED; + } + + caps->VendorId = attr.VendorID; + caps->ProductId = attr.ProductID; + caps->VersionNumber = attr.VersionNumber; + + return ERROR_SUCCESS; +} diff --git a/dlls/xinput1_4/xinput1_4.spec b/dlls/xinput1_4/xinput1_4.spec index 8c3f4c0cd73..22c511237dd 100644 --- a/dlls/xinput1_4/xinput1_4.spec +++ b/dlls/xinput1_4/xinput1_4.spec @@ -7,3 +7,4 @@ 8 stdcall XInputGetKeystroke(long long ptr) 10 stub XInputGetAudioDeviceIds(long ptr ptr ptr ptr) 100 stdcall XInputGetStateEx(long ptr) +108 stdcall XInputGetCapabilitiesEx(long long long ptr) diff --git a/include/xinput.h b/include/xinput.h index f7c291630cb..4fca5a04480 100644 --- a/include/xinput.h +++ b/include/xinput.h @@ -210,6 +210,16 @@ typedef struct _XINPUT_CAPABILITIES { XINPUT_VIBRATION Vibration; } XINPUT_CAPABILITIES, *PXINPUT_CAPABILITIES; +typedef struct _XINPUT_CAPABILITIES_EX +{ + XINPUT_CAPABILITIES Capabilities; + WORD VendorId; + WORD ProductId; + WORD VersionNumber; + WORD unk1; + DWORD unk2; +} XINPUT_CAPABILITIES_EX, *PXINPUT_CAPABILITIES_EX; + /* * Defines the structure for a joystick input event which is * retrieved using the function XInputGetKeystroke @@ -237,6 +247,7 @@ DWORD WINAPI XInputSetState(DWORD, XINPUT_VIBRATION*); DWORD WINAPI XInputGetState(DWORD, XINPUT_STATE*); DWORD WINAPI XInputGetKeystroke(DWORD, DWORD, PXINPUT_KEYSTROKE); DWORD WINAPI XInputGetCapabilities(DWORD, DWORD, XINPUT_CAPABILITIES*); +DWORD WINAPI XInputGetCapabilitiesEx(DWORD, DWORD, DWORD, XINPUT_CAPABILITIES_EX*); DWORD WINAPI XInputGetDSoundAudioDeviceGuids(DWORD, GUID*, GUID*); DWORD WINAPI XInputGetBatteryInformation(DWORD, BYTE, XINPUT_BATTERY_INFORMATION*); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/4693
From: Etaash Mathamsetty <etaash.mathamsetty(a)gmail.com> --- dlls/xinput1_3/main.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/dlls/xinput1_3/main.c b/dlls/xinput1_3/main.c index c4b2d5e871b..beba90b4b45 100644 --- a/dlls/xinput1_3/main.c +++ b/dlls/xinput1_3/main.c @@ -1086,25 +1086,17 @@ DWORD WINAPI DECLSPEC_HOTPATCH XInputGetKeystroke(DWORD index, DWORD reserved, P DWORD WINAPI DECLSPEC_HOTPATCH XInputGetCapabilities(DWORD index, DWORD flags, XINPUT_CAPABILITIES *capabilities) { - TRACE("index %lu, flags %#lx, capabilities %p.\n", index, flags, capabilities); - - start_update_thread(); - - if (index >= XUSER_MAX_COUNT) return ERROR_BAD_ARGUMENTS; + XINPUT_CAPABILITIES_EX caps_ex; + DWORD ret; - if (!controller_lock(&controllers[index])) return ERROR_DEVICE_NOT_CONNECTED; + ret = XInputGetCapabilitiesEx(0, index, flags, &caps_ex); - if (flags & XINPUT_FLAG_GAMEPAD && controllers[index].caps.SubType != XINPUT_DEVSUBTYPE_GAMEPAD) + if (!ret) { - controller_unlock(&controllers[index]); - return ERROR_DEVICE_NOT_CONNECTED; + memcpy(capabilities, &caps_ex.Capabilities, sizeof(*capabilities)); } - memcpy(capabilities, &controllers[index].caps, sizeof(*capabilities)); - - controller_unlock(&controllers[index]); - - return ERROR_SUCCESS; + return ret; } DWORD WINAPI DECLSPEC_HOTPATCH XInputGetDSoundAudioDeviceGuids(DWORD index, GUID *render_guid, GUID *capture_guid) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/4693
Rémi Bernon (@rbernon) commented about include/xinput.h:
XINPUT_VIBRATION Vibration; } XINPUT_CAPABILITIES, *PXINPUT_CAPABILITIES;
+typedef struct _XINPUT_CAPABILITIES_EX +{ + XINPUT_CAPABILITIES Capabilities; + WORD VendorId; + WORD ProductId; + WORD VersionNumber; + WORD unk1; + DWORD unk2; +} XINPUT_CAPABILITIES_EX, *PXINPUT_CAPABILITIES_EX;
Please use spaces. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/4693#note_56889
Rémi Bernon (@rbernon) commented about dlls/xinput1_3/main.c:
+ { + controller_unlock(&controllers[index]); + return ERROR_DEVICE_NOT_CONNECTED; + } + + memcpy(&caps->Capabilities, &controllers[index].caps, sizeof(caps->Capabilities)); + + if (!HidD_GetAttributes(controllers[index].device, &attr)) + { + controller_unlock(&controllers[index]); + return ERROR_DEVICE_NOT_CONNECTED; + } + + caps->VendorId = attr.VendorID; + caps->ProductId = attr.ProductID; + caps->VersionNumber = attr.VersionNumber; You're missing unlock here, something like that would be better:
```suggestion:-16+0 DWORD ret = ERROR_SUCCESS; /* ... */ if (!controller_lock(&controllers[index])) return ERROR_DEVICE_NOT_CONNECTED; if (flags & XINPUT_FLAG_GAMEPAD && controllers[index].caps.SubType != XINPUT_DEVSUBTYPE_GAMEPAD) ret = ERROR_DEVICE_NOT_CONNECTED; if (!HidD_GetAttributes(controllers[index].device, &attr)) ret = ERROR_DEVICE_NOT_CONNECTED; else { caps->Capabilities = controllers[index].caps; caps->VendorId = attr.VendorID; caps->ProductId = attr.ProductID; caps->VersionNumber = attr.VersionNumber; } controller_unlock(&controllers[index]); ``` -- https://gitlab.winehq.org/wine/wine/-/merge_requests/4693#note_56890
Rémi Bernon (@rbernon) commented about dlls/xinput1_3/main.c:
return ERROR_NOT_SUPPORTED; } + +DWORD WINAPI DECLSPEC_HOTPATCH XInputGetCapabilitiesEx(DWORD unk, DWORD index, DWORD flags, XINPUT_CAPABILITIES_EX *caps) +{ + HIDD_ATTRIBUTES attr; + TRACE("unk %lu, index %lu, flags %#lx, capabilities %p.\n", unk, index, flags, caps); +
```suggestion:-2+0 HIDD_ATTRIBUTES attr; TRACE("unk %lu, index %lu, flags %#lx, capabilities %p.\n", unk, index, flags, caps); ``` -- https://gitlab.winehq.org/wine/wine/-/merge_requests/4693#note_56891
Rémi Bernon (@rbernon) commented about dlls/xinput1_3/main.c:
- start_update_thread(); - - if (index >= XUSER_MAX_COUNT) return ERROR_BAD_ARGUMENTS; + XINPUT_CAPABILITIES_EX caps_ex; + DWORD ret;
- if (!controller_lock(&controllers[index])) return ERROR_DEVICE_NOT_CONNECTED; + ret = XInputGetCapabilitiesEx(0, index, flags, &caps_ex);
- if (flags & XINPUT_FLAG_GAMEPAD && controllers[index].caps.SubType != XINPUT_DEVSUBTYPE_GAMEPAD) + if (!ret) { - controller_unlock(&controllers[index]); - return ERROR_DEVICE_NOT_CONNECTED; + memcpy(capabilities, &caps_ex.Capabilities, sizeof(*capabilities)); }
TRACE("index %lu, flags %#lx, capabilities %p.\n", index, flags, capabilities);
ret = XInputGetCapabilitiesEx(0, index, flags, &caps_ex);
if (!ret) capabilities = caps_ex.Capabilities;
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/4693#note_56892
Fwiw this is also used by SDL2 to find out the actual underlying device VID/PID. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/4693#note_56895
Also, I wouldn't mind having a couple of tests to show that it's actually present (and maybe check that it's missing from other xinput versions). -- https://gitlab.winehq.org/wine/wine/-/merge_requests/4693#note_56896
participants (3)
-
Etaash Mathamsetty -
Etaash Mathamsetty (@etaash.mathamsetty) -
Rémi Bernon