From fa2063fb44d42d4894fbab55d62ff8c09186b47a Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Thu, 22 Sep 2022 23:42:25 -0700
Subject: [PATCH] Improved detection of third party PS4 and PS5 controllers
---
src/joystick/SDL_gamecontroller.c | 2 +-
src/joystick/SDL_joystick.c | 5 ++++
src/joystick/hidapi/SDL_hidapi_gamecube.c | 6 ++---
src/joystick/hidapi/SDL_hidapi_luna.c | 5 ++--
src/joystick/hidapi/SDL_hidapi_ps3.c | 22 ++++++++-------
src/joystick/hidapi/SDL_hidapi_ps4.c | 29 +++++++++++++-------
src/joystick/hidapi/SDL_hidapi_ps5.c | 29 +++++++++++++-------
src/joystick/hidapi/SDL_hidapi_shield.c | 5 ++--
src/joystick/hidapi/SDL_hidapi_stadia.c | 5 ++--
src/joystick/hidapi/SDL_hidapi_steam.c | 4 +--
src/joystick/hidapi/SDL_hidapi_switch.c | 8 ++++++
src/joystick/hidapi/SDL_hidapi_xbox360.c | 2 ++
src/joystick/hidapi/SDL_hidapi_xbox360w.c | 2 ++
src/joystick/hidapi/SDL_hidapi_xboxone.c | 2 ++
src/joystick/hidapi/SDL_hidapijoystick.c | 31 ++++++++++++++++------
src/joystick/hidapi/SDL_hidapijoystick_c.h | 4 +++
src/joystick/usb_ids.h | 22 ++++++++++++++-
17 files changed, 132 insertions(+), 51 deletions(-)
diff --git a/src/joystick/SDL_gamecontroller.c b/src/joystick/SDL_gamecontroller.c
index 1565eaa10a62..204ae965b965 100644
--- a/src/joystick/SDL_gamecontroller.c
+++ b/src/joystick/SDL_gamecontroller.c
@@ -568,7 +568,7 @@ static ControllerMapping_t *SDL_CreateMappingForHIDAPIController(SDL_JoystickGUI
SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL, NULL);
if ((vendor == USB_VENDOR_NINTENDO && product == USB_PRODUCT_NINTENDO_GAMECUBE_ADAPTER) ||
- (vendor == USB_VENDOR_SHENZHEN && product == USB_PRODUCT_EVORETRO_GAMECUBE_ADAPTER)) {
+ (vendor == USB_VENDOR_DRAGONRISE && product == USB_PRODUCT_EVORETRO_GAMECUBE_ADAPTER)) {
/* GameCube driver has 12 buttons and 6 axes */
SDL_strlcat(mapping_string, "a:b0,b:b1,dpdown:b6,dpleft:b4,dpright:b5,dpup:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:a5,rightx:a2,righty:a3,start:b8,x:b2,y:b3,", sizeof(mapping_string));
} else if (vendor == USB_VENDOR_NINTENDO &&
diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c
index 9c7c3de70f00..e445fe53ad7e 100644
--- a/src/joystick/SDL_joystick.c
+++ b/src/joystick/SDL_joystick.c
@@ -2167,6 +2167,11 @@ SDL_GetJoystickGameControllerTypeFromGUID(SDL_JoystickGUID guid, const char *nam
if (SDL_IsJoystickVirtual(guid)) {
return SDL_CONTROLLER_TYPE_VIRTUAL;
}
+#ifdef SDL_JOYSTICK_HIDAPI
+ if (SDL_IsJoystickHIDAPI(guid)) {
+ return HIDAPI_GetGameControllerTypeFromGUID(guid);
+ }
+#endif /* SDL_JOYSTICK_HIDAPI */
}
return type;
}
diff --git a/src/joystick/hidapi/SDL_hidapi_gamecube.c b/src/joystick/hidapi/SDL_hidapi_gamecube.c
index d3bd2cb226ea..4e68f47b0fd5 100644
--- a/src/joystick/hidapi/SDL_hidapi_gamecube.c
+++ b/src/joystick/hidapi/SDL_hidapi_gamecube.c
@@ -82,7 +82,7 @@ HIDAPI_DriverGameCube_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *n
/* Nintendo Co., Ltd. Wii U GameCube Controller Adapter */
return SDL_TRUE;
}
- if (vendor_id == USB_VENDOR_SHENZHEN && product_id == USB_PRODUCT_EVORETRO_GAMECUBE_ADAPTER) {
+ if (vendor_id == USB_VENDOR_DRAGONRISE && product_id == USB_PRODUCT_EVORETRO_GAMECUBE_ADAPTER) {
/* EVORETRO GameCube Controller Adapter */
return SDL_TRUE;
}
@@ -145,8 +145,6 @@ HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device)
SDL_EnableGameCubeAdaptors();
#endif
- HIDAPI_SetDeviceName(device, "Nintendo GameCube Controller");
-
ctx = (SDL_DriverGameCube_Context *)SDL_calloc(1, sizeof(*ctx));
if (!ctx) {
SDL_OutOfMemory();
@@ -219,6 +217,8 @@ HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device)
SDL_AddHintCallback(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS,
SDL_GameControllerButtonReportingHintChanged, ctx);
+ HIDAPI_SetDeviceName(device, "Nintendo GameCube Controller");
+
return SDL_TRUE;
}
diff --git a/src/joystick/hidapi/SDL_hidapi_luna.c b/src/joystick/hidapi/SDL_hidapi_luna.c
index 0f8cfd48850f..3bcf3d050757 100644
--- a/src/joystick/hidapi/SDL_hidapi_luna.c
+++ b/src/joystick/hidapi/SDL_hidapi_luna.c
@@ -77,8 +77,6 @@ HIDAPI_DriverLuna_InitDevice(SDL_HIDAPI_Device *device)
{
SDL_DriverLuna_Context *ctx;
- HIDAPI_SetDeviceName(device, "Amazon Luna Controller");
-
ctx = (SDL_DriverLuna_Context *)SDL_calloc(1, sizeof(*ctx));
if (!ctx) {
SDL_OutOfMemory();
@@ -86,6 +84,9 @@ HIDAPI_DriverLuna_InitDevice(SDL_HIDAPI_Device *device)
}
device->context = ctx;
+ device->type = SDL_CONTROLLER_TYPE_AMAZON_LUNA;
+ HIDAPI_SetDeviceName(device, "Amazon Luna Controller");
+
return HIDAPI_JoystickConnected(device, NULL);
}
diff --git a/src/joystick/hidapi/SDL_hidapi_ps3.c b/src/joystick/hidapi/SDL_hidapi_ps3.c
index 99bb613ceaa8..1b60c460f5d7 100644
--- a/src/joystick/hidapi/SDL_hidapi_ps3.c
+++ b/src/joystick/hidapi/SDL_hidapi_ps3.c
@@ -133,13 +133,15 @@ static SDL_bool
HIDAPI_DriverPS3_InitDevice(SDL_HIDAPI_Device *device)
{
SDL_DriverPS3_Context *ctx;
+ SDL_bool is_shanwan = SDL_FALSE;
- if (device->vendor_id == USB_VENDOR_SONY) {
- if (SDL_strncasecmp(device->name, "ShanWan", 7) == 0) {
- HIDAPI_SetDeviceName(device, "ShanWan PS3 Controller");
- } else {
- HIDAPI_SetDeviceName(device, "PS3 Controller");
- }
+ if (device->vendor_id == USB_VENDOR_SONY &&
+ SDL_strncasecmp(device->name, "ShanWan", 7) == 0) {
+ is_shanwan = SDL_TRUE;
+ }
+ if (device->vendor_id == USB_VENDOR_SHANWAN ||
+ device->vendor_id == USB_VENDOR_SHANWAN_ALT) {
+ is_shanwan = SDL_TRUE;
}
ctx = (SDL_DriverPS3_Context *)SDL_calloc(1, sizeof(*ctx));
@@ -148,13 +150,10 @@ HIDAPI_DriverPS3_InitDevice(SDL_HIDAPI_Device *device)
return SDL_FALSE;
}
ctx->device = device;
+ ctx->is_shanwan = is_shanwan;
device->context = ctx;
- if (SDL_strncasecmp(device->name, "ShanWan", 7) == 0) {
- ctx->is_shanwan = SDL_TRUE;
- }
-
/* Set the controller into report mode over Bluetooth */
{
Uint8 data[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 };
@@ -189,6 +188,9 @@ HIDAPI_DriverPS3_InitDevice(SDL_HIDAPI_Device *device)
}
}
+ device->type = SDL_CONTROLLER_TYPE_PS3;
+ HIDAPI_SetDeviceName(device, "PS3 Controller");
+
return HIDAPI_JoystickConnected(device, NULL);
}
diff --git a/src/joystick/hidapi/SDL_hidapi_ps4.c b/src/joystick/hidapi/SDL_hidapi_ps4.c
index 1fe59375bd91..fcc4cca6b5a2 100644
--- a/src/joystick/hidapi/SDL_hidapi_ps4.c
+++ b/src/joystick/hidapi/SDL_hidapi_ps4.c
@@ -168,12 +168,6 @@ HIDAPI_DriverPS4_IsEnabled(void)
SDL_HIDAPI_DEFAULT));
}
-static SDL_bool
-HIDAPI_DriverPS4_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
-{
- return (type == SDL_CONTROLLER_TYPE_PS4) ? SDL_TRUE : SDL_FALSE;
-}
-
static int ReadFeatureReport(SDL_hid_device *dev, Uint8 report_id, Uint8 *report, size_t length)
{
SDL_memset(report, 0, length);
@@ -181,6 +175,21 @@ static int ReadFeatureReport(SDL_hid_device *dev, Uint8 report_id, Uint8 *report
return SDL_hid_get_feature_report(dev, report, length);
}
+static SDL_bool
+HIDAPI_DriverPS4_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
+{
+ Uint8 data[USB_PACKET_LENGTH];
+ int size;
+
+ if (device && SONY_THIRDPARTY_VENDOR(device->vendor_id) &&
+ (size = ReadFeatureReport(device->dev, k_ePS4FeatureReportIdCapabilities, data, sizeof(data))) == 48 &&
+ data[2] == 0x27) {
+ /* Supported third party controller */
+ return SDL_TRUE;
+ }
+ return (type == SDL_CONTROLLER_TYPE_PS4) ? SDL_TRUE : SDL_FALSE;
+}
+
static void
SetLedsForPlayerIndex(DS4EffectsState_t *effects, int player_index)
{
@@ -216,10 +225,6 @@ HIDAPI_DriverPS4_InitDevice(SDL_HIDAPI_Device *device)
int size;
char serial[18];
- if (device->vendor_id == USB_VENDOR_SONY) {
- HIDAPI_SetDeviceName(device, "PS4 Controller");
- }
-
ctx = (SDL_DriverPS4_Context *)SDL_calloc(1, sizeof(*ctx));
if (!ctx) {
SDL_OutOfMemory();
@@ -309,6 +314,10 @@ HIDAPI_DriverPS4_InitDevice(SDL_HIDAPI_Device *device)
}
}
+ device->type = SDL_CONTROLLER_TYPE_PS4;
+ if (device->vendor_id == USB_VENDOR_SONY) {
+ HIDAPI_SetDeviceName(device, "PS4 Controller");
+ }
HIDAPI_SetDeviceSerial(device, serial);
return HIDAPI_JoystickConnected(device, NULL);
diff --git a/src/joystick/hidapi/SDL_hidapi_ps5.c b/src/joystick/hidapi/SDL_hidapi_ps5.c
index 638bc44911c1..e128eda16fa6 100644
--- a/src/joystick/hidapi/SDL_hidapi_ps5.c
+++ b/src/joystick/hidapi/SDL_hidapi_ps5.c
@@ -250,12 +250,6 @@ HIDAPI_DriverPS5_IsEnabled(void)
SDL_HIDAPI_DEFAULT));
}
-static SDL_bool
-HIDAPI_DriverPS5_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
-{
- return (type == SDL_CONTROLLER_TYPE_PS5) ? SDL_TRUE : SDL_FALSE;
-}
-
static int ReadFeatureReport(SDL_hid_device *dev, Uint8 report_id, Uint8 *report, size_t length)
{
SDL_memset(report, 0, length);
@@ -263,6 +257,21 @@ static int ReadFeatureReport(SDL_hid_device *dev, Uint8 report_id, Uint8 *report
return SDL_hid_get_feature_report(dev, report, length);
}
+static SDL_bool
+HIDAPI_DriverPS5_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
+{
+ Uint8 data[USB_PACKET_LENGTH];
+ int size;
+
+ if (device && SONY_THIRDPARTY_VENDOR(device->vendor_id) &&
+ (size = ReadFeatureReport(device->dev, k_EPS5FeatureReportIdCapabilities, data, sizeof(data))) == 48 &&
+ data[2] == 0x28) {
+ /* Supported third party controller */
+ return SDL_TRUE;
+ }
+ return (type == SDL_CONTROLLER_TYPE_PS5) ? SDL_TRUE : SDL_FALSE;
+}
+
static void
SetLedsForPlayerIndex(DS5EffectsState_t *effects, int player_index)
{
@@ -317,10 +326,6 @@ HIDAPI_DriverPS5_InitDevice(SDL_HIDAPI_Device *device)
int size;
char serial[18];
- if (device->vendor_id == USB_VENDOR_SONY) {
- HIDAPI_SetDeviceName(device, "PS5 Controller");
- }
-
ctx = (SDL_DriverPS5_Context *)SDL_calloc(1, sizeof(*ctx));
if (!ctx) {
SDL_OutOfMemory();
@@ -416,6 +421,10 @@ HIDAPI_DriverPS5_InitDevice(SDL_HIDAPI_Device *device)
ctx->use_alternate_report = SDL_TRUE;
}
+ device->type = SDL_CONTROLLER_TYPE_PS5;
+ if (device->vendor_id == USB_VENDOR_SONY) {
+ HIDAPI_SetDeviceName(device, "PS5 Controller");
+ }
HIDAPI_SetDeviceSerial(device, serial);
return HIDAPI_JoystickConnected(device, NULL);
diff --git a/src/joystick/hidapi/SDL_hidapi_shield.c b/src/joystick/hidapi/SDL_hidapi_shield.c
index 42cfea1c8042..1fa75b74a010 100644
--- a/src/joystick/hidapi/SDL_hidapi_shield.c
+++ b/src/joystick/hidapi/SDL_hidapi_shield.c
@@ -112,8 +112,6 @@ HIDAPI_DriverShield_InitDevice(SDL_HIDAPI_Device *device)
{
SDL_DriverShield_Context *ctx;
- HIDAPI_SetDeviceName(device, "NVIDIA SHIELD Controller");
-
ctx = (SDL_DriverShield_Context *)SDL_calloc(1, sizeof(*ctx));
if (!ctx) {
SDL_OutOfMemory();
@@ -121,6 +119,9 @@ HIDAPI_DriverShield_InitDevice(SDL_HIDAPI_Device *device)
}
device->context = ctx;
+ device->type = SDL_CONTROLLER_TYPE_NVIDIA_SHIELD;
+ HIDAPI_SetDeviceName(device, "NVIDIA SHIELD Controller");
+
return HIDAPI_JoystickConnected(device, NULL);
}
diff --git a/src/joystick/hidapi/SDL_hidapi_stadia.c b/src/joystick/hidapi/SDL_hidapi_stadia.c
index 8b20d75ab7d4..a6d54b2a533c 100644
--- a/src/joystick/hidapi/SDL_hidapi_stadia.c
+++ b/src/joystick/hidapi/SDL_hidapi_stadia.c
@@ -78,8 +78,6 @@ HIDAPI_DriverStadia_InitDevice(SDL_HIDAPI_Device *device)
{
SDL_DriverStadia_Context *ctx;
- HIDAPI_SetDeviceName(device, "Google Stadia Controller");
-
ctx = (SDL_DriverStadia_Context *)SDL_calloc(1, sizeof(*ctx));
if (!ctx) {
SDL_OutOfMemory();
@@ -87,6 +85,9 @@ HIDAPI_DriverStadia_InitDevice(SDL_HIDAPI_Device *device)
}
device->context = ctx;
+ device->type = SDL_CONTROLLER_TYPE_GOOGLE_STADIA;
+ HIDAPI_SetDeviceName(device, "Google Stadia Controller");
+
return HIDAPI_JoystickConnected(device, NULL);
}
diff --git a/src/joystick/hidapi/SDL_hidapi_steam.c b/src/joystick/hidapi/SDL_hidapi_steam.c
index 64ce13adeb0c..6df6512b3573 100644
--- a/src/joystick/hidapi/SDL_hidapi_steam.c
+++ b/src/joystick/hidapi/SDL_hidapi_steam.c
@@ -1027,8 +1027,6 @@ HIDAPI_DriverSteam_InitDevice(SDL_HIDAPI_Device *device)
{
SDL_DriverSteam_Context *ctx;
- HIDAPI_SetDeviceName(device, "Steam Controller");
-
ctx = (SDL_DriverSteam_Context *)SDL_calloc(1, sizeof(*ctx));
if (!ctx) {
SDL_OutOfMemory();
@@ -1036,6 +1034,8 @@ HIDAPI_DriverSteam_InitDevice(SDL_HIDAPI_Device *device)
}
device->context = ctx;
+ HIDAPI_SetDeviceName(device, "Steam Controller");
+
return HIDAPI_JoystickConnected(device, NULL);
}
diff --git a/src/joystick/hidapi/SDL_hidapi_switch.c b/src/joystick/hidapi/SDL_hidapi_switch.c
index e05fdc391343..d2e84040087a 100644
--- a/src/joystick/hidapi/SDL_hidapi_switch.c
+++ b/src/joystick/hidapi/SDL_hidapi_switch.c
@@ -1161,32 +1161,40 @@ UpdateDeviceIdentity(SDL_HIDAPI_Device *device)
case k_eSwitchDeviceInfoControllerType_JoyConLeft:
HIDAPI_SetDeviceName(device, "Nintendo Switch Joy-Con (L)");
HIDAPI_SetDeviceProduct(device, USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT);
+ device->type = SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT;
break;
case k_eSwitchDeviceInfoControllerType_JoyConRight:
HIDAPI_SetDeviceName(device, "Nintendo Switch Joy-Con (R)");
HIDAPI_SetDeviceProduct(device, USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT);
+ device->type = SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT;
break;
case k_eSwitchDeviceInfoControllerType_ProController:
HIDAPI_SetDeviceName(device, "Nintendo Switch Pro Controller");
HIDAPI_SetDeviceProduct(device, USB_PRODUCT_NINTENDO_SWITCH_PRO);
+ device->type = SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO;
break;
case k_eSwitchDeviceInfoControllerType_NESLeft:
HIDAPI_SetDeviceName(device, "Nintendo NES Controller (L)");
+ device->type = SDL_CONTROLLER_TYPE_UNKNOWN;
break;
case k_eSwitchDeviceInfoControllerType_NESRight:
HIDAPI_SetDeviceName(device, "Nintendo NES Controller (R)");
+ device->type = SDL_CONTROLLER_TYPE_UNKNOWN;
break;
case k_eSwitchDeviceInfoControllerType_SNES:
HIDAPI_SetDeviceName(device, "Nintendo SNES Controller");
HIDAPI_SetDeviceProduct(device, USB_PRODUCT_NINTENDO_SNES_CONTROLLER);
+ device->type = SDL_CONTROLLER_TYPE_UNKNOWN;
break;
case k_eSwitchDeviceInfoControllerType_N64:
HIDAPI_SetDeviceName(device, "Nintendo N64 Controller");
HIDAPI_SetDeviceProduct(device, USB_PRODUCT_NINTENDO_N64_CONTROLLER);
+ device->type = SDL_CONTROLLER_TYPE_UNKNOWN;
break;
case k_eSwitchDeviceInfoControllerType_SEGA_Genesis:
HIDAPI_SetDeviceName(device, "Nintendo SEGA Genesis Controller");
HIDAPI_SetDeviceProduct(device, USB_PRODUCT_NINTENDO_SEGA_GENESIS_CONTROLLER);
+ device->type = SDL_CONTROLLER_TYPE_UNKNOWN;
break;
default:
break;
diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360.c b/src/joystick/hidapi/SDL_hidapi_xbox360.c
index a73071b94707..191ccb97ff1d 100644
--- a/src/joystick/hidapi/SDL_hidapi_xbox360.c
+++ b/src/joystick/hidapi/SDL_hidapi_xbox360.c
@@ -157,6 +157,8 @@ HIDAPI_DriverXbox360_InitDevice(SDL_HIDAPI_Device *device)
device->context = ctx;
+ device->type = SDL_CONTROLLER_TYPE_XBOX360;
+
return HIDAPI_JoystickConnected(device, NULL);
}
diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360w.c b/src/joystick/hidapi/SDL_hidapi_xbox360w.c
index 5869aff49d2d..f0a1d2931b13 100644
--- a/src/joystick/hidapi/SDL_hidapi_xbox360w.c
+++ b/src/joystick/hidapi/SDL_hidapi_xbox360w.c
@@ -159,6 +159,8 @@ HIDAPI_DriverXbox360W_InitDevice(SDL_HIDAPI_Device *device)
return SDL_FALSE;
}
+ device->type = SDL_CONTROLLER_TYPE_XBOX360;
+
return SDL_TRUE;
}
diff --git a/src/joystick/hidapi/SDL_hidapi_xboxone.c b/src/joystick/hidapi/SDL_hidapi_xboxone.c
index 987fb698764f..5be605917305 100644
--- a/src/joystick/hidapi/SDL_hidapi_xboxone.c
+++ b/src/joystick/hidapi/SDL_hidapi_xboxone.c
@@ -340,6 +340,8 @@ HIDAPI_DriverXboxOne_InitDevice(SDL_HIDAPI_Device *device)
SDL_Log("Controller version: %d (0x%.4x)\n", device->version, device->version);
#endif
+ device->type = SDL_CONTROLLER_TYPE_XBOXONE;
+
return HIDAPI_JoystickConnected(device, NULL);
}
diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c
index 0a3873a71ba1..fd2ce71405f8 100644
--- a/src/joystick/hidapi/SDL_hidapijoystick.c
+++ b/src/joystick/hidapi/SDL_hidapijoystick.c
@@ -235,7 +235,6 @@ HIDAPI_GetDeviceDriver(SDL_HIDAPI_Device *device)
const Uint16 USAGE_GAMEPAD = 0x0005;
const Uint16 USAGE_MULTIAXISCONTROLLER = 0x0008;
int i;
- SDL_GameControllerType type;
if (device->num_children > 0) {
return &SDL_HIDAPI_DriverCombined;
@@ -254,10 +253,9 @@ HIDAPI_GetDeviceDriver(SDL_HIDAPI_Device *device)
}
}
- type = SDL_GetJoystickGameControllerProtocol(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol);
for (i = 0; i < SDL_arraysize(SDL_HIDAPI_drivers); ++i) {
SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i];
- if (driver->enabled && driver->IsSupportedDevice(device, device->name, type, device->vendor_id, device->product_id, device->version, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol)) {
+ if (driver->enabled && driver->IsSupportedDevice(device, device->name, device->type, device->vendor_id, device->product_id, device->version, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol)) {
return driver;
}
}
@@ -690,6 +688,7 @@ HIDAPI_AddDevice(const struct SDL_hid_device_info *info, int num_children, SDL_H
/* FIXME: Is there any way to tell whether this is a Bluetooth device? */
device->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, device->vendor_id, device->product_id, device->version, device->name, 'h', 0);
+ device->type = SDL_GetJoystickGameControllerProtocol(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol);
if (num_children > 0) {
int i;
@@ -914,14 +913,13 @@ HIDAPI_IsEquivalentToDevice(Uint16 vendor_id, Uint16 product_id, SDL_HIDAPI_Devi
/* If we're looking for the raw input Xbox One controller, match it against any other Xbox One controller */
if (product_id == USB_PRODUCT_XBOX_ONE_XBOXGIP_CONTROLLER &&
- SDL_GetJoystickGameControllerProtocol(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol) == SDL_CONTROLLER_TYPE_XBOXONE) {
+ device->type == SDL_CONTROLLER_TYPE_XBOXONE) {
return SDL_TRUE;
}
/* If we're looking for an XInput controller, match it against any other Xbox controller */
if (product_id == USB_PRODUCT_XBOX_ONE_XINPUT_CONTROLLER) {
- SDL_GameControllerType type = SDL_GetJoystickGameControllerProtocol(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol);
- if (type == SDL_CONTROLLER_TYPE_XBOX360 || type == SDL_CONTROLLER_TYPE_XBOXONE) {
+ if (device->type == SDL_CONTROLLER_TYPE_XBOX360 || device->type == SDL_CONTROLLER_TYPE_XBOXONE) {
return SDL_TRUE;
}
}
@@ -947,8 +945,7 @@ HIDAPI_IsDeviceTypePresent(SDL_GameControllerType type)
SDL_LockJoysticks();
for (device = SDL_HIDAPI_devices; device; device = device->next) {
- if (device->driver &&
- SDL_GetJoystickGameControllerProtocol(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol) == type) {
+ if (device->driver && device->type == type) {
result = SDL_TRUE;
break;
}
@@ -1013,6 +1010,24 @@ HIDAPI_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, cons
return result;
}
+SDL_GameControllerType
+HIDAPI_GetGameControllerTypeFromGUID(SDL_JoystickGUID guid)
+{
+ SDL_HIDAPI_Device *device;
+ SDL_GameControllerType type = SDL_CONTROLLER_TYPE_UNKNOWN;
+
+ SDL_LockJoysticks();
+ for (device = SDL_HIDAPI_devices; device; device = device->next) {
+ if (SDL_memcmp(&guid, &device->guid, sizeof(guid)) == 0) {
+ type = device->type;
+ break;
+ }
+ }
+ SDL_UnlockJoysticks();
+
+ return type;
+}
+
static void
HIDAPI_JoystickDetect(void)
{
diff --git a/src/joystick/hidapi/SDL_hidapijoystick_c.h b/src/joystick/hidapi/SDL_hidapijoystick_c.h
index 3b574d6572ad..c653d15bea4c 100644
--- a/src/joystick/hidapi/SDL_hidapijoystick_c.h
+++ b/src/joystick/hidapi/SDL_hidapijoystick_c.h
@@ -73,6 +73,7 @@ typedef struct _SDL_HIDAPI_Device
int interface_protocol;
Uint16 usage_page; /* Available on Windows and Mac OS X */
Uint16 usage; /* Available on Windows and Mac OS X */
+ SDL_GameControllerType type;
struct _SDL_HIDAPI_DeviceDriver *driver;
void *context;
@@ -144,6 +145,9 @@ extern SDL_bool HIDAPI_IsDeviceTypePresent(SDL_GameControllerType type);
/* Return true if a HID device is present and supported as a joystick */
extern SDL_bool HIDAPI_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name);
+/* Return the type of a game controller if it's present and supported */
+extern SDL_GameControllerType HIDAPI_GetGameControllerTypeFromGUID(SDL_JoystickGUID guid);
+
extern void HIDAPI_UpdateDevices(void);
extern void HIDAPI_SetDeviceName(SDL_HIDAPI_Device *device, const char *name);
extern void HIDAPI_SetDeviceProduct(SDL_HIDAPI_Device *device, Uint16 product_id);
diff --git a/src/joystick/usb_ids.h b/src/joystick/usb_ids.h
index 3a62bc462595..e9f27fb4c2a0 100644
--- a/src/joystick/usb_ids.h
+++ b/src/joystick/usb_ids.h
@@ -27,21 +27,41 @@
#define USB_VENDOR_8BITDO 0x2dc8
#define USB_VENDOR_AMAZON 0x1949
#define USB_VENDOR_APPLE 0x05ac
+#define USB_VENDOR_DRAGONRISE 0x0079
#define USB_VENDOR_GOOGLE 0x18d1
#define USB_VENDOR_HORI 0x0f0d
#define USB_VENDOR_HYPERKIN 0x2e24
+#define USB_VENDOR_MADCATZ 0x0738
#define USB_VENDOR_MICROSOFT 0x045e
+#define USB_VENDOR_NACON 0x146b
#define USB_VENDOR_NINTENDO 0x057e
#define USB_VENDOR_NVIDIA 0x0955
#define USB_VENDOR_PDP 0x0e6f
#define USB_VENDOR_POWERA 0x24c6
#define USB_VENDOR_POWERA_ALT 0x20d6
+#define USB_VENDOR_QANBA 0x2c22
#define USB_VENDOR_RAZER 0x1532
#define USB_VENDOR_SHANWAN 0x2563
-#define USB_VENDOR_SHENZHEN 0x0079
+#define USB_VENDOR_SHANWAN_ALT 0x20bc
#define USB_VENDOR_SONY 0x054c
+#define USB_VENDOR_THRUSTMASTER 0x044f
#define USB_VENDOR_VALVE 0x28de
+#define SONY_THIRDPARTY_VENDOR(X) \
+ (X == USB_VENDOR_DRAGONRISE || \
+ X == USB_VENDOR_HORI || \
+ X == USB_VENDOR_MADCATZ || \
+ X == USB_VENDOR_NACON || \
+ X == USB_VENDOR_PDP || \
+ X == USB_VENDOR_POWERA || \
+ X == USB_VENDOR_POWERA_ALT || \
+ X == USB_VENDOR_QANBA || \
+ X == USB_VENDOR_RAZER || \
+ X == USB_VENDOR_SHANWAN || \
+ X == USB_VENDOR_SHANWAN_ALT || \
+ X == USB_VENDOR_THRUSTMASTER || \
+ X == 0x7545 /* SZ-MYPOWER */)
+
#define USB_PRODUCT_8BITDO_XBOX_CONTROLLER 0x2002
#define USB_PRODUCT_AMAZON_LUNA_CONTROLLER 0x0419
#define USB_PRODUCT_GOOGLE_STADIA_CONTROLLER 0x9400