XInput: Use XInputGetCapabilitiesEx instead of fragile GuessXInputDevice

XInputGetCapabilitiesEx (ordinal 108) is available in XInput 1.4 that is shipped with Windows 8 and newer.
This commit is contained in:
Dimitriy Ryazantcev
2023-12-15 17:09:15 +02:00
committed by Sam Lantinga
parent 7f75178908
commit 08a7ca4d53
4 changed files with 42 additions and 136 deletions

View File

@@ -30,6 +30,7 @@ extern "C" {
XInputGetState_t SDL_XInputGetState = NULL;
XInputSetState_t SDL_XInputSetState = NULL;
XInputGetCapabilities_t SDL_XInputGetCapabilities = NULL;
XInputGetCapabilitiesEx_t SDL_XInputGetCapabilitiesEx = NULL;
XInputGetBatteryInformation_t SDL_XInputGetBatteryInformation = NULL;
DWORD SDL_XInputVersion = 0;
@@ -111,6 +112,8 @@ int WIN_LoadXInputDLL(void)
}
SDL_XInputSetState = (XInputSetState_t)GetProcAddress(s_pXInputDLL, "XInputSetState");
SDL_XInputGetCapabilities = (XInputGetCapabilities_t)GetProcAddress(s_pXInputDLL, "XInputGetCapabilities");
/* 108 is the ordinal for _XInputGetCapabilitiesEx, which additionally returns VID/PID of the controller. */
SDL_XInputGetCapabilitiesEx = (XInputGetCapabilitiesEx_t)GetProcAddress(s_pXInputDLL, (LPCSTR)108);
SDL_XInputGetBatteryInformation = (XInputGetBatteryInformation_t)GetProcAddress(s_pXInputDLL, "XInputGetBatteryInformation");
if (!SDL_XInputGetState || !SDL_XInputSetState || !SDL_XInputGetCapabilities) {
WIN_UnloadXInputDLL();

View File

@@ -44,6 +44,9 @@ using namespace XInputOnGameInput;
#ifndef XINPUT_CAPS_FFB_SUPPORTED
#define XINPUT_CAPS_FFB_SUPPORTED 0x0001
#endif
#ifndef XINPUT_CAPS_WIRELESS
#define XINPUT_CAPS_WIRELESS 0x0002
#endif
#ifndef XINPUT_DEVSUBTYPE_UNKNOWN
#define XINPUT_DEVSUBTYPE_UNKNOWN 0x00
@@ -207,6 +210,17 @@ typedef struct
#endif /* HAVE_XINPUT_H */
/* This struct is not defined in XInput headers. */
typedef struct _XINPUT_CAPABILITIES_EX
{
XINPUT_CAPABILITIES Capabilities;
WORD VendorId;
WORD ProductId;
WORD ProductVersion;
WORD unk1;
DWORD unk2;
} XINPUT_CAPABILITIES_EX, *PXINPUT_CAPABILITIES_EX;
/* Forward decl's for XInput API's we load dynamically and use if available */
typedef DWORD(WINAPI *XInputGetState_t)(
DWORD dwUserIndex, /* [in] Index of the gamer associated with the device */
@@ -224,6 +238,14 @@ typedef DWORD(WINAPI *XInputGetCapabilities_t)(
XINPUT_CAPABILITIES *pCapabilities /* [out] Receives the capabilities */
);
/* Only available in XInput 1.4 that is shipped with Windows 8 and newer. */
typedef DWORD(WINAPI *XInputGetCapabilitiesEx_t)(
DWORD dwReserved, /* [in] Must be 1 */
DWORD dwUserIndex, /* [in] Index of the gamer associated with the device */
DWORD dwFlags, /* [in] Input flags that identify the device type */
XINPUT_CAPABILITIES_EX *pCapabilitiesEx /* [out] Receives the capabilities */
);
typedef DWORD(WINAPI *XInputGetBatteryInformation_t)(
DWORD dwUserIndex,
BYTE devType,
@@ -235,6 +257,7 @@ extern void WIN_UnloadXInputDLL(void);
extern XInputGetState_t SDL_XInputGetState;
extern XInputSetState_t SDL_XInputSetState;
extern XInputGetCapabilities_t SDL_XInputGetCapabilities;
extern XInputGetCapabilitiesEx_t SDL_XInputGetCapabilitiesEx;
extern XInputGetBatteryInformation_t SDL_XInputGetBatteryInformation;
extern DWORD SDL_XInputVersion; /* ((major << 16) & 0xFF00) | (minor & 0xFF) */
@@ -246,6 +269,7 @@ extern DWORD SDL_XInputVersion; /* ((major << 16) & 0xFF00) | (minor & 0xFF) */
#define XINPUTGETSTATE SDL_XInputGetState
#define XINPUTSETSTATE SDL_XInputSetState
#define XINPUTGETCAPABILITIES SDL_XInputGetCapabilities
#define XINPUTGETCAPABILITIESEX SDL_XInputGetCapabilitiesEx
#define XINPUTGETBATTERYINFORMATION SDL_XInputGetBatteryInformation
#endif /* SDL_xinput_h_ */