From b5aff9d7c347cd9346759fdb8ab0982a3f44bd4f Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 22 Nov 2019 13:12:12 -0800 Subject: [PATCH] Added SDL_GameControllerTypeForIndex() and SDL_GameControllerGetType() to return the type of controller attached. --- include/SDL_gamecontroller.h | 20 ++ src/dynapi/SDL_dynapi_overrides.h | 2 + src/dynapi/SDL_dynapi_procs.h | 2 + src/joystick/SDL_gamecontroller.c | 20 ++ src/joystick/SDL_joystick.c | 72 +++++--- src/joystick/SDL_joystick_c.h | 13 +- src/joystick/hidapi/SDL_hidapi_ps4.c | 2 +- src/joystick/hidapi/SDL_hidapi_xbox360.c | 6 +- src/joystick/hidapi/SDL_hidapi_xboxone.c | 2 +- src/joystick/windows/SDL_dinputjoystick.c | 212 +++++++++++----------- test/testgamecontroller.c | 21 ++- 11 files changed, 227 insertions(+), 145 deletions(-) diff --git a/include/SDL_gamecontroller.h b/include/SDL_gamecontroller.h index ebde38715..883f2fdbe 100644 --- a/include/SDL_gamecontroller.h +++ b/include/SDL_gamecontroller.h @@ -57,6 +57,15 @@ extern "C" { struct _SDL_GameController; typedef struct _SDL_GameController SDL_GameController; +typedef enum +{ + SDL_CONTROLLER_TYPE_UNKNOWN = 0, + SDL_CONTROLLER_TYPE_XBOX360, + SDL_CONTROLLER_TYPE_XBOXONE, + SDL_CONTROLLER_TYPE_PS3, + SDL_CONTROLLER_TYPE_PS4, + SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO, +} SDL_GameControllerType; typedef enum { @@ -175,6 +184,12 @@ extern DECLSPEC SDL_bool SDLCALL SDL_IsGameController(int joystick_index); */ extern DECLSPEC const char *SDLCALL SDL_GameControllerNameForIndex(int joystick_index); +/** + * Get the type of a game controller. + * This can be called before any controllers are opened. + */ +extern DECLSPEC SDL_GameControllerType SDLCALL SDL_GameControllerTypeForIndex(int joystick_index); + /** * Get the mapping of a game controller. * This can be called before any controllers are opened. @@ -204,6 +219,11 @@ extern DECLSPEC SDL_GameController *SDLCALL SDL_GameControllerFromInstanceID(SDL */ extern DECLSPEC const char *SDLCALL SDL_GameControllerName(SDL_GameController *gamecontroller); +/** + * Return the type of this currently opened controller + */ +extern DECLSPEC SDL_GameControllerType SDLCALL SDL_GameControllerGetType(SDL_GameController *gamecontroller); + /** * Get the player index of an opened game controller, or -1 if it's not available * diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index a21d4ba00..56e461ad9 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -731,3 +731,5 @@ #define SDL_strtokr SDL_strtokr_REAL #define SDL_wcsstr SDL_wcsstr_REAL #define SDL_wcsncmp SDL_wcsncmp_REAL +#define SDL_GameControllerTypeForIndex SDL_GameControllerTypeForIndex_REAL +#define SDL_GameControllerGetType SDL_GameControllerGetType_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 65a9a8fab..d7b8f04dd 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -787,3 +787,5 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_HasARMSIMD,(void),(),return) SDL_DYNAPI_PROC(char*,SDL_strtokr,(char *a, const char *b, char **c),(a,b,c),return) SDL_DYNAPI_PROC(wchar_t*,SDL_wcsstr,(const wchar_t *a, const wchar_t *b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_wcsncmp,(const wchar_t *a, const wchar_t *b, size_t c),(a,b,c),return) +SDL_DYNAPI_PROC(SDL_GameControllerType,SDL_GameControllerTypeForIndex,(int a),(a),return) +SDL_DYNAPI_PROC(SDL_GameControllerType,SDL_GameControllerGetType,(SDL_GameController *a),(a),return) diff --git a/src/joystick/SDL_gamecontroller.c b/src/joystick/SDL_gamecontroller.c index 012a45967..47bf1bd1b 100644 --- a/src/joystick/SDL_gamecontroller.c +++ b/src/joystick/SDL_gamecontroller.c @@ -1412,6 +1412,17 @@ SDL_GameControllerNameForIndex(int device_index) } +/** + * Get the type of a game controller. + */ +SDL_GameControllerType +SDL_GameControllerTypeForIndex(int joystick_index) +{ + SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(joystick_index); + return SDL_GetGameControllerTypeFromGUID(guid); +} + + /** * Get the mapping of a game controller. * This can be called before any controllers are opened. @@ -1743,6 +1754,15 @@ SDL_GameControllerName(SDL_GameController * gamecontroller) } } +SDL_GameControllerType +SDL_GameControllerGetType(SDL_GameController *gamecontroller) +{ + if (!gamecontroller) { + return SDL_CONTROLLER_TYPE_UNKNOWN; + } + return SDL_GetGameControllerTypeFromGUID(gamecontroller->joystick->guid); +} + int SDL_GameControllerGetPlayerIndex(SDL_GameController *gamecontroller) { diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index dfbdfeb5c..eec3ea9d7 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -1158,12 +1158,6 @@ void SDL_GetJoystickGUIDInfo(SDL_JoystickGUID guid, Uint16 *vendor, Uint16 *prod } } -SDL_bool -SDL_IsJoystickPS4(Uint16 vendor, Uint16 product) -{ - return (GuessControllerType(vendor, product) == k_eControllerType_PS4Controller); -} - SDL_bool SDL_IsJoystickNintendoSwitchPro(Uint16 vendor, Uint16 product) { @@ -1172,6 +1166,51 @@ SDL_IsJoystickNintendoSwitchPro(Uint16 vendor, Uint16 product) eType == k_eControllerType_SwitchInputOnlyController); } +SDL_GameControllerType +SDL_GetGameControllerTypeFromGUID(SDL_JoystickGUID guid) +{ + SDL_GameControllerType type; + Uint16 vendor, product; + + SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL); + type = SDL_GetGameControllerType(vendor, product); + if (type == SDL_CONTROLLER_TYPE_UNKNOWN) { + if (SDL_IsJoystickXInput(guid)) { + /* This is probably an Xbox One controller */ + return SDL_CONTROLLER_TYPE_XBOXONE; + } + } + return type; +} + +SDL_GameControllerType +SDL_GetGameControllerType(Uint16 vendor, Uint16 product) +{ + /* Filter out some bogus values here */ + if (vendor == 0x0000 && product == 0x0000) { + return SDL_CONTROLLER_TYPE_UNKNOWN; + } + if (vendor == 0x0001 && product == 0x0001) { + return SDL_CONTROLLER_TYPE_UNKNOWN; + } + + switch (GuessControllerType(vendor, product)) { + case k_eControllerType_XBox360Controller: + return SDL_CONTROLLER_TYPE_XBOX360; + case k_eControllerType_XBoxOneController: + return SDL_CONTROLLER_TYPE_XBOXONE; + case k_eControllerType_PS3Controller: + return SDL_CONTROLLER_TYPE_PS3; + case k_eControllerType_PS4Controller: + return SDL_CONTROLLER_TYPE_PS4; + case k_eControllerType_SwitchProController: + case k_eControllerType_SwitchInputOnlyController: + return SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO; + default: + return SDL_CONTROLLER_TYPE_UNKNOWN; + } +} + SDL_bool SDL_IsJoystickNintendoSwitchProInputOnly(Uint16 vendor, Uint16 product) { @@ -1187,25 +1226,6 @@ SDL_IsJoystickSteamController(Uint16 vendor, Uint16 product) eType == k_eControllerType_SteamControllerV2); } -SDL_bool -SDL_IsJoystickXbox360(Uint16 vendor, Uint16 product) -{ - /* Filter out some bogus values here */ - if (vendor == 0x0000 && product == 0x0000) { - return SDL_FALSE; - } - if (vendor == 0x0001 && product == 0x0001) { - return SDL_FALSE; - } - return (GuessControllerType(vendor, product) == k_eControllerType_XBox360Controller); -} - -SDL_bool -SDL_IsJoystickXboxOne(Uint16 vendor, Uint16 product) -{ - return (GuessControllerType(vendor, product) == k_eControllerType_XBoxOneController); -} - SDL_bool SDL_IsJoystickXInput(SDL_JoystickGUID guid) { @@ -1481,7 +1501,7 @@ SDL_bool SDL_ShouldIgnoreJoystick(const char *name, SDL_JoystickGUID guid) } } - if (SDL_IsJoystickPS4(vendor, product) && SDL_IsPS4RemapperRunning()) { + if (SDL_GetGameControllerType(vendor, product) == SDL_CONTROLLER_TYPE_PS4 && SDL_IsPS4RemapperRunning()) { return SDL_TRUE; } diff --git a/src/joystick/SDL_joystick_c.h b/src/joystick/SDL_joystick_c.h index 2b3e7c211..d84c36216 100644 --- a/src/joystick/SDL_joystick_c.h +++ b/src/joystick/SDL_joystick_c.h @@ -25,6 +25,7 @@ #include "../SDL_internal.h" /* Useful functions and variables from SDL_joystick.c */ +#include "SDL_gamecontroller.h" #include "SDL_joystick.h" struct _SDL_JoystickDriver; @@ -51,22 +52,16 @@ extern int SDL_JoystickGetDeviceIndexFromInstanceID(SDL_JoystickID instance_id); /* Function to extract information from an SDL joystick GUID */ extern void SDL_GetJoystickGUIDInfo(SDL_JoystickGUID guid, Uint16 *vendor, Uint16 *product, Uint16 *version); -/* Function to return whether a joystick is a PS4 controller */ -extern SDL_bool SDL_IsJoystickPS4(Uint16 vendor_id, Uint16 product_id); +/* Function to return the type of a controller */ +extern SDL_GameControllerType SDL_GetGameControllerTypeFromGUID(SDL_JoystickGUID guid); +extern SDL_GameControllerType SDL_GetGameControllerType(Uint16 vendor, Uint16 product); /* Function to return whether a joystick is a Nintendo Switch Pro controller */ -extern SDL_bool SDL_IsJoystickNintendoSwitchPro( Uint16 vendor_id, Uint16 product_id ); extern SDL_bool SDL_IsJoystickNintendoSwitchProInputOnly(Uint16 vendor_id, Uint16 product_id); /* Function to return whether a joystick is a Steam Controller */ extern SDL_bool SDL_IsJoystickSteamController(Uint16 vendor_id, Uint16 product_id); -/* Function to return whether a joystick is an Xbox 360 controller */ -extern SDL_bool SDL_IsJoystickXbox360(Uint16 vendor_id, Uint16 product_id); - -/* Function to return whether a joystick is an Xbox One controller */ -extern SDL_bool SDL_IsJoystickXboxOne(Uint16 vendor_id, Uint16 product_id); - /* Function to return whether a joystick guid comes from the XInput driver */ extern SDL_bool SDL_IsJoystickXInput(SDL_JoystickGUID guid); diff --git a/src/joystick/hidapi/SDL_hidapi_ps4.c b/src/joystick/hidapi/SDL_hidapi_ps4.c index af17ad316..f69c43dd3 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps4.c +++ b/src/joystick/hidapi/SDL_hidapi_ps4.c @@ -141,7 +141,7 @@ static Uint32 crc32(Uint32 crc, const void *data, int count) static SDL_bool HIDAPI_DriverPS4_IsSupportedDevice(Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, const char *name) { - return SDL_IsJoystickPS4(vendor_id, product_id); + return (SDL_GetGameControllerType(vendor_id, product_id) == SDL_CONTROLLER_TYPE_PS4); } static const char * diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360.c b/src/joystick/hidapi/SDL_hidapi_xbox360.c index afc21d2ba..5193c35b1 100644 --- a/src/joystick/hidapi/SDL_hidapi_xbox360.c +++ b/src/joystick/hidapi/SDL_hidapi_xbox360.c @@ -249,6 +249,8 @@ HIDAPI_DriverXbox360_QuitWindowsGamingInput(SDL_DriverXbox360_Context *ctx) static SDL_bool HIDAPI_DriverXbox360_IsSupportedDevice(Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, const char *name) { + SDL_GameControllerType type = SDL_GameControllerType(vendor_id, product_id); + #if defined(__MACOSX__) || defined(__WIN32__) if (vendor_id == 0x045e && product_id == 0x028e && version == 1) { /* This is the Steam Virtual Gamepad, which isn't supported by this driver */ @@ -258,9 +260,9 @@ HIDAPI_DriverXbox360_IsSupportedDevice(Uint16 vendor_id, Uint16 product_id, Uint /* This is the old Bluetooth Xbox One S firmware, which isn't supported by this driver */ return SDL_FALSE; } - return SDL_IsJoystickXbox360(vendor_id, product_id) || SDL_IsJoystickXboxOne(vendor_id, product_id); + return (type == SDL_CONTROLLER_TYPE_XBOX360 || type == SDL_CONTROLLER_TYPE_XBOXONE); #else - return SDL_IsJoystickXbox360(vendor_id, product_id); + return (type == SDL_CONTROLLER_TYPE_XBOX360); #endif } diff --git a/src/joystick/hidapi/SDL_hidapi_xboxone.c b/src/joystick/hidapi/SDL_hidapi_xboxone.c index 90f3c09e9..689485412 100644 --- a/src/joystick/hidapi/SDL_hidapi_xboxone.c +++ b/src/joystick/hidapi/SDL_hidapi_xboxone.c @@ -197,7 +197,7 @@ HIDAPI_DriverXboxOne_IsSupportedDevice(Uint16 vendor_id, Uint16 product_id, Uint return SDL_FALSE; } #endif - return SDL_IsJoystickXboxOne(vendor_id, product_id); + return (SDL_GetGameControllerType(vendor_id, product_id) == SDL_CONTROLLER_TYPE_XBOXONE); } static const char * diff --git a/src/joystick/windows/SDL_dinputjoystick.c b/src/joystick/windows/SDL_dinputjoystick.c index 54a10e80b..1a39b7ad9 100644 --- a/src/joystick/windows/SDL_dinputjoystick.c +++ b/src/joystick/windows/SDL_dinputjoystick.c @@ -246,139 +246,141 @@ static const IID IID_IWbemLocator = { 0xdc12a687, 0x737f, 0x11cf,{ 0x88, 0x4d, 0 static SDL_bool WIN_IsXInputDevice(const GUID* pGuidProductFromDirectInput) { - IWbemLocator* pIWbemLocator = NULL; - IEnumWbemClassObject* pEnumDevices = NULL; - IWbemClassObject* pDevices[20]; - IWbemServices* pIWbemServices = NULL; - BSTR bstrNamespace = NULL; - BSTR bstrDeviceID = NULL; - BSTR bstrClassName = NULL; - DWORD uReturned = 0; - SDL_bool bIsXinputDevice = SDL_FALSE; - UINT iDevice = 0; - VARIANT var; - HRESULT hr; + IWbemLocator* pIWbemLocator = NULL; + IEnumWbemClassObject* pEnumDevices = NULL; + IWbemClassObject* pDevices[20]; + IWbemServices* pIWbemServices = NULL; + BSTR bstrNamespace = NULL; + BSTR bstrDeviceID = NULL; + BSTR bstrClassName = NULL; + DWORD uReturned = 0; + SDL_bool bIsXinputDevice = SDL_FALSE; + UINT iDevice = 0; + VARIANT var; + HRESULT hr; - SDL_zero(pDevices); + SDL_zero(pDevices); - // Create WMI - hr = CoCreateInstance(&CLSID_WbemLocator, - NULL, - CLSCTX_INPROC_SERVER, - &IID_IWbemLocator, - (LPVOID*)&pIWbemLocator); - if (FAILED(hr) || pIWbemLocator == NULL) - goto LCleanup; + // Create WMI + hr = CoCreateInstance(&CLSID_WbemLocator, + NULL, + CLSCTX_INPROC_SERVER, + &IID_IWbemLocator, + (LPVOID*)&pIWbemLocator); + if (FAILED(hr) || pIWbemLocator == NULL) + goto LCleanup; - bstrNamespace = SysAllocString(L"\\\\.\\root\\cimv2"); if (bstrNamespace == NULL) goto LCleanup; - bstrClassName = SysAllocString(L"Win32_PNPEntity"); if (bstrClassName == NULL) goto LCleanup; - bstrDeviceID = SysAllocString(L"DeviceID"); if (bstrDeviceID == NULL) goto LCleanup; + bstrNamespace = SysAllocString(L"\\\\.\\root\\cimv2"); if (bstrNamespace == NULL) goto LCleanup; + bstrClassName = SysAllocString(L"Win32_PNPEntity"); if (bstrClassName == NULL) goto LCleanup; + bstrDeviceID = SysAllocString(L"DeviceID"); if (bstrDeviceID == NULL) goto LCleanup; - // Connect to WMI - hr = IWbemLocator_ConnectServer(pIWbemLocator, bstrNamespace, NULL, NULL, 0L, - 0L, NULL, NULL, &pIWbemServices); - if (FAILED(hr) || pIWbemServices == NULL) { - goto LCleanup; + // Connect to WMI + hr = IWbemLocator_ConnectServer(pIWbemLocator, bstrNamespace, NULL, NULL, 0L, + 0L, NULL, NULL, &pIWbemServices); + if (FAILED(hr) || pIWbemServices == NULL) { + goto LCleanup; } - // Switch security level to IMPERSONATE. - CoSetProxyBlanket((IUnknown *)pIWbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, - RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE); + // Switch security level to IMPERSONATE. + CoSetProxyBlanket((IUnknown *)pIWbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, + RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE); - hr = IWbemServices_CreateInstanceEnum(pIWbemServices, bstrClassName, 0, NULL, &pEnumDevices); - if (FAILED(hr) || pEnumDevices == NULL) - goto LCleanup; + hr = IWbemServices_CreateInstanceEnum(pIWbemServices, bstrClassName, 0, NULL, &pEnumDevices); + if (FAILED(hr) || pEnumDevices == NULL) + goto LCleanup; - // Loop over all devices - for (;;) { - // Get 20 at a time - hr = IEnumWbemClassObject_Next(pEnumDevices, 10000, SDL_arraysize(pDevices), pDevices, &uReturned); - if (FAILED(hr)) { - goto LCleanup; + // Loop over all devices + for (;;) { + // Get 20 at a time + hr = IEnumWbemClassObject_Next(pEnumDevices, 10000, SDL_arraysize(pDevices), pDevices, &uReturned); + if (FAILED(hr)) { + goto LCleanup; } - if (uReturned == 0) { - break; + if (uReturned == 0) { + break; } - for (iDevice = 0; iDevice < uReturned; iDevice++) { - // For each device, get its device ID - hr = IWbemClassObject_Get(pDevices[iDevice], bstrDeviceID, 0L, &var, NULL, NULL); - if (SUCCEEDED(hr) && var.vt == VT_BSTR && var.bstrVal != NULL) { - // Check if the device ID contains "IG_". If it does, then it's an XInput device - // This information can not be found from DirectInput - if (SDL_wcsstr(var.bstrVal, L"IG_")) { - char *bstrVal = WIN_StringToUTF8(var.bstrVal); + for (iDevice = 0; iDevice < uReturned; iDevice++) { + // For each device, get its device ID + hr = IWbemClassObject_Get(pDevices[iDevice], bstrDeviceID, 0L, &var, NULL, NULL); + if (SUCCEEDED(hr) && var.vt == VT_BSTR && var.bstrVal != NULL) { + // Check if the device ID contains "IG_". If it does, then it's an XInput device + // This information can not be found from DirectInput + if (SDL_wcsstr(var.bstrVal, L"IG_")) { + char *bstrVal = WIN_StringToUTF8(var.bstrVal); - // If it does, then get the VID/PID from var.bstrVal - DWORD dwPid = 0, dwVid = 0, dwVidPid; - const char *strVid, *strPid; - strVid = SDL_strstr(bstrVal, "VID_"); - if (strVid && SDL_sscanf(strVid, "VID_%4X", &dwVid) != 1) - dwVid = 0; - strPid = SDL_strstr(bstrVal, "PID_"); - if (strPid && SDL_sscanf(strPid, "PID_%4X", &dwPid) != 1) - dwPid = 0; + // If it does, then get the VID/PID from var.bstrVal + DWORD dwPid = 0, dwVid = 0, dwVidPid; + const char *strVid, *strPid; + strVid = SDL_strstr(bstrVal, "VID_"); + if (strVid && SDL_sscanf(strVid, "VID_%4X", &dwVid) != 1) + dwVid = 0; + strPid = SDL_strstr(bstrVal, "PID_"); + if (strPid && SDL_sscanf(strPid, "PID_%4X", &dwPid) != 1) + dwPid = 0; - SDL_free(bstrVal); + SDL_free(bstrVal); - // Compare the VID/PID to the DInput device - dwVidPid = MAKELONG(dwVid, dwPid); - if (dwVidPid == pGuidProductFromDirectInput->Data1) { - bIsXinputDevice = SDL_TRUE; - goto LCleanup; - } - } - } - IWbemClassObject_Release(pDevices[iDevice]); - } - } + // Compare the VID/PID to the DInput device + dwVidPid = MAKELONG(dwVid, dwPid); + if (dwVidPid == pGuidProductFromDirectInput->Data1) { + bIsXinputDevice = SDL_TRUE; + goto LCleanup; + } + } + } + IWbemClassObject_Release(pDevices[iDevice]); + } + } LCleanup: - if (bstrNamespace) { - SysFreeString(bstrNamespace); + if (bstrNamespace) { + SysFreeString(bstrNamespace); } - if (bstrDeviceID) { - SysFreeString(bstrDeviceID); + if (bstrDeviceID) { + SysFreeString(bstrDeviceID); } - if (bstrClassName) { - SysFreeString(bstrClassName); + if (bstrClassName) { + SysFreeString(bstrClassName); + } + for (iDevice = 0; iDevice < SDL_arraysize(pDevices); iDevice++) { + if (pDevices[iDevice]) { + IWbemClassObject_Release(pDevices[iDevice]); + } + } + if (pEnumDevices) { + IEnumWbemClassObject_Release(pEnumDevices); + } + if (pIWbemLocator) { + IWbemLocator_Release(pIWbemLocator); + } + if (pIWbemServices) { + IWbemServices_Release(pIWbemServices); } - for (iDevice = 0; iDevice < SDL_arraysize(pDevices); iDevice++) { - if (pDevices[iDevice]) { - IWbemClassObject_Release(pDevices[iDevice]); - } - } - if (pEnumDevices) { - IEnumWbemClassObject_Release(pEnumDevices); - } - if (pIWbemLocator) { - IWbemLocator_Release(pIWbemLocator); - } - if (pIWbemServices) { - IWbemServices_Release(pIWbemServices); - } - return bIsXinputDevice; + return bIsXinputDevice; } #endif /* 0 */ static SDL_bool SDL_IsXInputDevice(const GUID* pGuidProductFromDirectInput) { - UINT i; + UINT i; - if (!SDL_XINPUT_Enabled()) { - return SDL_FALSE; - } + if (!SDL_XINPUT_Enabled()) { + return SDL_FALSE; + } - if (SDL_memcmp(&pGuidProductFromDirectInput->Data4[2], "PIDVID", 6) == 0) { - Uint16 vendor_id = (Uint16)LOWORD(pGuidProductFromDirectInput->Data1); - Uint16 product_id = (Uint16)HIWORD(pGuidProductFromDirectInput->Data1); - if (SDL_IsJoystickXbox360(vendor_id, product_id) || SDL_IsJoystickXboxOne(vendor_id, product_id) || - (vendor_id == 0x28DE && product_id == 0x11FF)) { - return SDL_TRUE; - } - } + if (SDL_memcmp(&pGuidProductFromDirectInput->Data4[2], "PIDVID", 6) == 0) { + Uint16 vendor_id = (Uint16)LOWORD(pGuidProductFromDirectInput->Data1); + Uint16 product_id = (Uint16)HIWORD(pGuidProductFromDirectInput->Data1); + SDL_GameControllerType type = SDL_GetGameControllerType(vendor_id, product_id); + if (type == SDL_CONTROLLER_TYPE_XBOX360 || + type == SDL_CONTROLLER_TYPE_XBOXONE || + (vendor_id == 0x28DE && product_id == 0x11FF)) { + return SDL_TRUE; + } + } /* Go through RAWINPUT (WinXP and later) to find HID devices. */ /* Cache this if we end up using it. */ diff --git a/test/testgamecontroller.c b/test/testgamecontroller.c index 8b7f48873..1bcf44086 100644 --- a/test/testgamecontroller.c +++ b/test/testgamecontroller.c @@ -292,7 +292,26 @@ main(int argc, char *argv[]) { nController++; name = SDL_GameControllerNameForIndex(i); - description = "Controller"; + switch (SDL_GameControllerTypeForIndex(i)) { + case SDL_CONTROLLER_TYPE_XBOX360: + description = "XBox 360 Controller"; + break; + case SDL_CONTROLLER_TYPE_XBOXONE: + description = "XBox One Controller"; + break; + case SDL_CONTROLLER_TYPE_PS3: + description = "PS3 Controller"; + break; + case SDL_CONTROLLER_TYPE_PS4: + description = "PS4 Controller"; + break; + case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO: + description = "Nintendo Switch Pro Controller"; + break; + default: + description = "Game Controller"; + break; + } } else { name = SDL_JoystickNameForIndex(i); description = "Joystick";