From cdaafcec0d39b8567009e4b3e1ca1e532f06df9a Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Tue, 30 Aug 2022 14:56:11 -0700
Subject: [PATCH] The Kinvoca Joy-Cons are handled by the Joy-Con driver, not
the Switch Pro driver.
---
src/joystick/hidapi/SDL_hidapi_combined.c | 2 +-
src/joystick/hidapi/SDL_hidapi_gamecube.c | 2 +-
src/joystick/hidapi/SDL_hidapi_luna.c | 2 +-
src/joystick/hidapi/SDL_hidapi_ps3.c | 2 +-
src/joystick/hidapi/SDL_hidapi_ps4.c | 2 +-
src/joystick/hidapi/SDL_hidapi_ps5.c | 2 +-
src/joystick/hidapi/SDL_hidapi_shield.c | 2 +-
src/joystick/hidapi/SDL_hidapi_stadia.c | 2 +-
src/joystick/hidapi/SDL_hidapi_steam.c | 2 +-
src/joystick/hidapi/SDL_hidapi_switch.c | 455 +++++++++++----------
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 | 4 +-
src/joystick/hidapi/SDL_hidapijoystick_c.h | 2 +-
15 files changed, 247 insertions(+), 238 deletions(-)
diff --git a/src/joystick/hidapi/SDL_hidapi_combined.c b/src/joystick/hidapi/SDL_hidapi_combined.c
index 8dae1a2f250..04710b45e7b 100644
--- a/src/joystick/hidapi/SDL_hidapi_combined.c
+++ b/src/joystick/hidapi/SDL_hidapi_combined.c
@@ -46,7 +46,7 @@ HIDAPI_DriverCombined_IsEnabled(void)
}
static SDL_bool
-HIDAPI_DriverCombined_IsSupportedDevice(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)
+HIDAPI_DriverCombined_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)
{
/* This is always explicitly created for combined devices */
return SDL_FALSE;
diff --git a/src/joystick/hidapi/SDL_hidapi_gamecube.c b/src/joystick/hidapi/SDL_hidapi_gamecube.c
index 97321b853be..bbd7a05cbca 100644
--- a/src/joystick/hidapi/SDL_hidapi_gamecube.c
+++ b/src/joystick/hidapi/SDL_hidapi_gamecube.c
@@ -76,7 +76,7 @@ HIDAPI_DriverGameCube_IsEnabled(void)
}
static SDL_bool
-HIDAPI_DriverGameCube_IsSupportedDevice(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)
+HIDAPI_DriverGameCube_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)
{
if (vendor_id == USB_VENDOR_NINTENDO && product_id == USB_PRODUCT_NINTENDO_GAMECUBE_ADAPTER) {
/* Nintendo Co., Ltd. Wii U GameCube Controller Adapter */
diff --git a/src/joystick/hidapi/SDL_hidapi_luna.c b/src/joystick/hidapi/SDL_hidapi_luna.c
index 3d285809e12..7808052a8b3 100644
--- a/src/joystick/hidapi/SDL_hidapi_luna.c
+++ b/src/joystick/hidapi/SDL_hidapi_luna.c
@@ -67,7 +67,7 @@ HIDAPI_DriverLuna_IsEnabled(void)
}
static SDL_bool
-HIDAPI_DriverLuna_IsSupportedDevice(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)
+HIDAPI_DriverLuna_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_AMAZON_LUNA) ? SDL_TRUE : SDL_FALSE;
}
diff --git a/src/joystick/hidapi/SDL_hidapi_ps3.c b/src/joystick/hidapi/SDL_hidapi_ps3.c
index c52a87bb4ad..15ceb96fa1d 100644
--- a/src/joystick/hidapi/SDL_hidapi_ps3.c
+++ b/src/joystick/hidapi/SDL_hidapi_ps3.c
@@ -104,7 +104,7 @@ HIDAPI_DriverPS3_IsEnabled(void)
}
static SDL_bool
-HIDAPI_DriverPS3_IsSupportedDevice(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)
+HIDAPI_DriverPS3_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)
{
if (vendor_id == USB_VENDOR_SONY && product_id == USB_PRODUCT_SONY_DS3) {
return SDL_TRUE;
diff --git a/src/joystick/hidapi/SDL_hidapi_ps4.c b/src/joystick/hidapi/SDL_hidapi_ps4.c
index cdabd60bf8c..36856795234 100644
--- a/src/joystick/hidapi/SDL_hidapi_ps4.c
+++ b/src/joystick/hidapi/SDL_hidapi_ps4.c
@@ -171,7 +171,7 @@ HIDAPI_DriverPS4_IsEnabled(void)
}
static SDL_bool
-HIDAPI_DriverPS4_IsSupportedDevice(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)
+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;
}
diff --git a/src/joystick/hidapi/SDL_hidapi_ps5.c b/src/joystick/hidapi/SDL_hidapi_ps5.c
index fa8a8ff0fee..172d5e60a26 100644
--- a/src/joystick/hidapi/SDL_hidapi_ps5.c
+++ b/src/joystick/hidapi/SDL_hidapi_ps5.c
@@ -273,7 +273,7 @@ HIDAPI_DriverPS5_IsEnabled(void)
}
static SDL_bool
-HIDAPI_DriverPS5_IsSupportedDevice(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)
+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;
}
diff --git a/src/joystick/hidapi/SDL_hidapi_shield.c b/src/joystick/hidapi/SDL_hidapi_shield.c
index 36bb794689a..69ab1a4a098 100644
--- a/src/joystick/hidapi/SDL_hidapi_shield.c
+++ b/src/joystick/hidapi/SDL_hidapi_shield.c
@@ -102,7 +102,7 @@ HIDAPI_DriverShield_IsEnabled(void)
}
static SDL_bool
-HIDAPI_DriverShield_IsSupportedDevice(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)
+HIDAPI_DriverShield_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_NVIDIA_SHIELD) ? SDL_TRUE : SDL_FALSE;
}
diff --git a/src/joystick/hidapi/SDL_hidapi_stadia.c b/src/joystick/hidapi/SDL_hidapi_stadia.c
index 435031b31f6..23056acff98 100644
--- a/src/joystick/hidapi/SDL_hidapi_stadia.c
+++ b/src/joystick/hidapi/SDL_hidapi_stadia.c
@@ -68,7 +68,7 @@ HIDAPI_DriverStadia_IsEnabled(void)
}
static SDL_bool
-HIDAPI_DriverStadia_IsSupportedDevice(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)
+HIDAPI_DriverStadia_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_GOOGLE_STADIA) ? SDL_TRUE : SDL_FALSE;
}
diff --git a/src/joystick/hidapi/SDL_hidapi_steam.c b/src/joystick/hidapi/SDL_hidapi_steam.c
index 27a541cc9d0..2faf65c3635 100644
--- a/src/joystick/hidapi/SDL_hidapi_steam.c
+++ b/src/joystick/hidapi/SDL_hidapi_steam.c
@@ -1017,7 +1017,7 @@ HIDAPI_DriverSteam_IsEnabled(void)
}
static SDL_bool
-HIDAPI_DriverSteam_IsSupportedDevice(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)
+HIDAPI_DriverSteam_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 SDL_IsJoystickSteamController(vendor_id, product_id);
}
diff --git a/src/joystick/hidapi/SDL_hidapi_switch.c b/src/joystick/hidapi/SDL_hidapi_switch.c
index 3b2c0036655..60d5bf6b135 100644
--- a/src/joystick/hidapi/SDL_hidapi_switch.c
+++ b/src/joystick/hidapi/SDL_hidapi_switch.c
@@ -302,229 +302,6 @@ typedef struct {
} SDL_DriverSwitch_Context;
-static SDL_bool
-HasHomeLED(SDL_DriverSwitch_Context *ctx)
-{
- Uint16 vendor_id = ctx->device->vendor_id;
- Uint16 product_id = ctx->device->product_id;
-
- /* The Power A Nintendo Switch Pro controllers don't have a Home LED */
- if (vendor_id == 0 && product_id == 0) {
- return SDL_FALSE;
- }
-
- /* HORI Wireless Switch Pad */
- if (vendor_id == 0x0f0d && product_id == 0x00f6) {
- return SDL_FALSE;
- }
-
- /* The Nintendo Online classic controllers don't have a Home LED */
- if (vendor_id == USB_VENDOR_NINTENDO &&
- ctx->m_eControllerType > k_eSwitchDeviceInfoControllerType_ProController) {
- return SDL_FALSE;
- }
-
- return SDL_TRUE;
-}
-
-static SDL_bool
-AlwaysUsesLabels(int vendor_id, int product_id, ESwitchDeviceInfoControllerType eControllerType)
-{
- /* These controllers don't have a diamond button configuration, so always use labels */
- switch (eControllerType) {
- case k_eSwitchDeviceInfoControllerType_NESLeft:
- case k_eSwitchDeviceInfoControllerType_NESRight:
- case k_eSwitchDeviceInfoControllerType_N64:
- case k_eSwitchDeviceInfoControllerType_SEGA_Genesis:
- return SDL_TRUE;
- default:
- return SDL_FALSE;
- }
-}
-
-static SDL_bool
-IsGameCubeFormFactor(int vendor_id, int product_id)
-{
- static Uint32 gamecube_formfactor[] = {
- MAKE_VIDPID(0x0e6f, 0x0185), /* PDP Wired Fight Pad Pro for Nintendo Switch */
- MAKE_VIDPID(0x20d6, 0xa711), /* Core (Plus) Wired Controller */
- };
- Uint32 id = MAKE_VIDPID(vendor_id, product_id);
- int i;
-
- for (i = 0; i < SDL_arraysize(gamecube_formfactor); ++i) {
- if (id == gamecube_formfactor[i]) {
- return SDL_TRUE;
- }
- }
- return SDL_FALSE;
-}
-
-static void
-HIDAPI_DriverNintendoClassic_RegisterHints(SDL_HintCallback callback, void *userdata)
-{
- SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_NINTENDO_CLASSIC, callback, userdata);
-}
-
-static void
-HIDAPI_DriverNintendoClassic_UnregisterHints(SDL_HintCallback callback, void *userdata)
-{
- SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_NINTENDO_CLASSIC, callback, userdata);
-}
-
-static SDL_bool
-HIDAPI_DriverNintendoClassic_IsEnabled(void)
-{
- return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_NINTENDO_CLASSIC,
- SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI,
- SDL_HIDAPI_DEFAULT));
-}
-
-static SDL_bool
-HIDAPI_DriverNintendoClassic_IsSupportedDevice(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)
-{
- if (vendor_id == USB_VENDOR_NINTENDO) {
- if (product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT) {
- if (SDL_strncmp(name, "NES Controller", 14) == 0) {
- return SDL_TRUE;
- }
- }
-
- if (product_id == USB_PRODUCT_NINTENDO_N64_CONTROLLER) {
- return SDL_TRUE;
- }
-
- if (product_id == USB_PRODUCT_NINTENDO_SEGA_GENESIS_CONTROLLER) {
- return SDL_TRUE;
- }
-
- if (product_id == USB_PRODUCT_NINTENDO_SNES_CONTROLLER) {
- return SDL_TRUE;
- }
- }
-
- return SDL_FALSE;
-}
-
-static void
-HIDAPI_DriverJoyCons_RegisterHints(SDL_HintCallback callback, void *userdata)
-{
- SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, callback, userdata);
-}
-
-static void
-HIDAPI_DriverJoyCons_UnregisterHints(SDL_HintCallback callback, void *userdata)
-{
- SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, callback, userdata);
-}
-
-static SDL_bool
-HIDAPI_DriverJoyCons_IsEnabled(void)
-{
- return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS,
- SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI,
- SDL_HIDAPI_DEFAULT));
-}
-
-static SDL_bool
-HIDAPI_DriverJoyCons_IsSupportedDevice(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)
-{
- if (vendor_id == USB_VENDOR_NINTENDO) {
- if (product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT ||
- product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT ||
- product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_GRIP) {
- return SDL_TRUE;
- }
- }
- return SDL_FALSE;
-}
-
-static void
-HIDAPI_DriverSwitch_RegisterHints(SDL_HintCallback callback, void *userdata)
-{
- SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, callback, userdata);
-}
-
-static void
-HIDAPI_DriverSwitch_UnregisterHints(SDL_HintCallback callback, void *userdata)
-{
- SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, callback, userdata);
-}
-
-static SDL_bool
-HIDAPI_DriverSwitch_IsEnabled(void)
-{
- return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_SWITCH,
- SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI,
- SDL_HIDAPI_DEFAULT));
-}
-
-static SDL_bool
-HIDAPI_DriverSwitch_IsSupportedDevice(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)
-{
- /* The HORI Wireless Switch Pad enumerates as a HID device when connected via USB
- with the same VID/PID as when connected over Bluetooth but doesn't actually
- support communication over USB. The most reliable way to block this without allowing the
- controller to continually attempt to reconnect is to filter it out by manufactuer/product string.
- Note that the controller does have a different product string when connected over Bluetooth.
- */
- if (SDL_strcmp(name, "HORI Wireless Switch Pad") == 0) {
- return SDL_FALSE;
- }
-
- /* If it's handled by another driver, it's not handled here */
- if (HIDAPI_DriverNintendoClassic_IsSupportedDevice(name, type, vendor_id, product_id, version, interface_number, interface_class, interface_subclass, interface_protocol) ||
- HIDAPI_DriverJoyCons_IsSupportedDevice(name, type, vendor_id, product_id, version, interface_number, interface_class, interface_subclass, interface_protocol)) {
- return SDL_FALSE;
- }
-
- return (type == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO) ? SDL_TRUE : SDL_FALSE;
-}
-
-static const char *
-HIDAPI_DriverSwitch_GetDeviceName(const char *name, Uint16 vendor_id, Uint16 product_id)
-{
- /* Give a user friendly name for this controller */
- if (vendor_id == USB_VENDOR_NINTENDO) {
- if (product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_GRIP) {
- /* We don't know if this is left or right, just leave it alone */
- return NULL;
- }
-
- if (product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT) {
- return "Nintendo Switch Joy-Con (L)";
- }
-
- if (product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT) {
- if (SDL_strncmp(name, "NES Controller", 14) == 0) {
- if (SDL_strstr(name, "(L)") != 0) {
- return "Nintendo NES Controller (L)";
- } else if (SDL_strstr(name, "(R)") != 0) {
- return "Nintendo NES Controller (R)";
- } else {
- /* Not sure what this is, just leave it alone */
- return NULL;
- }
- }
- return "Nintendo Switch Joy-Con (R)";
- }
-
- if (product_id == USB_PRODUCT_NINTENDO_N64_CONTROLLER) {
- return "Nintendo N64 Controller";
- }
-
- if (product_id == USB_PRODUCT_NINTENDO_SEGA_GENESIS_CONTROLLER) {
- return "Nintendo SEGA Genesis Controller";
- }
-
- if (product_id == USB_PRODUCT_NINTENDO_SNES_CONTROLLER) {
- return "Nintendo SNES Controller";
- }
- }
-
- return "Nintendo Switch Pro Controller";
-}
-
static int ReadInput(SDL_DriverSwitch_Context *ctx)
{
/* Make sure we don't try to read at the same time a write is happening */
@@ -1180,6 +957,238 @@ ReadJoyConControllerType(SDL_HIDAPI_Device *device)
return eControllerType;
}
+static SDL_bool
+HasHomeLED(SDL_DriverSwitch_Context *ctx)
+{
+ Uint16 vendor_id = ctx->device->vendor_id;
+ Uint16 product_id = ctx->device->product_id;
+
+ /* The Power A Nintendo Switch Pro controllers don't have a Home LED */
+ if (vendor_id == 0 && product_id == 0) {
+ return SDL_FALSE;
+ }
+
+ /* HORI Wireless Switch Pad */
+ if (vendor_id == 0x0f0d && product_id == 0x00f6) {
+ return SDL_FALSE;
+ }
+
+ /* The Nintendo Online classic controllers don't have a Home LED */
+ if (vendor_id == USB_VENDOR_NINTENDO &&
+ ctx->m_eControllerType > k_eSwitchDeviceInfoControllerType_ProController) {
+ return SDL_FALSE;
+ }
+
+ return SDL_TRUE;
+}
+
+static SDL_bool
+AlwaysUsesLabels(int vendor_id, int product_id, ESwitchDeviceInfoControllerType eControllerType)
+{
+ /* These controllers don't have a diamond button configuration, so always use labels */
+ switch (eControllerType) {
+ case k_eSwitchDeviceInfoControllerType_NESLeft:
+ case k_eSwitchDeviceInfoControllerType_NESRight:
+ case k_eSwitchDeviceInfoControllerType_N64:
+ case k_eSwitchDeviceInfoControllerType_SEGA_Genesis:
+ return SDL_TRUE;
+ default:
+ return SDL_FALSE;
+ }
+}
+
+static SDL_bool
+IsGameCubeFormFactor(int vendor_id, int product_id)
+{
+ static Uint32 gamecube_formfactor[] = {
+ MAKE_VIDPID(0x0e6f, 0x0185), /* PDP Wired Fight Pad Pro for Nintendo Switch */
+ MAKE_VIDPID(0x20d6, 0xa711), /* Core (Plus) Wired Controller */
+ };
+ Uint32 id = MAKE_VIDPID(vendor_id, product_id);
+ int i;
+
+ for (i = 0; i < SDL_arraysize(gamecube_formfactor); ++i) {
+ if (id == gamecube_formfactor[i]) {
+ return SDL_TRUE;
+ }
+ }
+ return SDL_FALSE;
+}
+
+static void
+HIDAPI_DriverNintendoClassic_RegisterHints(SDL_HintCallback callback, void *userdata)
+{
+ SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_NINTENDO_CLASSIC, callback, userdata);
+}
+
+static void
+HIDAPI_DriverNintendoClassic_UnregisterHints(SDL_HintCallback callback, void *userdata)
+{
+ SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_NINTENDO_CLASSIC, callback, userdata);
+}
+
+static SDL_bool
+HIDAPI_DriverNintendoClassic_IsEnabled(void)
+{
+ return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_NINTENDO_CLASSIC,
+ SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI,
+ SDL_HIDAPI_DEFAULT));
+}
+
+static SDL_bool
+HIDAPI_DriverNintendoClassic_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)
+{
+ if (vendor_id == USB_VENDOR_NINTENDO) {
+ if (product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT) {
+ if (SDL_strncmp(name, "NES Controller", 14) == 0) {
+ return SDL_TRUE;
+ }
+ }
+
+ if (product_id == USB_PRODUCT_NINTENDO_N64_CONTROLLER) {
+ return SDL_TRUE;
+ }
+
+ if (product_id == USB_PRODUCT_NINTENDO_SEGA_GENESIS_CONTROLLER) {
+ return SDL_TRUE;
+ }
+
+ if (product_id == USB_PRODUCT_NINTENDO_SNES_CONTROLLER) {
+ return SDL_TRUE;
+ }
+ }
+
+ return SDL_FALSE;
+}
+
+static void
+HIDAPI_DriverJoyCons_RegisterHints(SDL_HintCallback callback, void *userdata)
+{
+ SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, callback, userdata);
+}
+
+static void
+HIDAPI_DriverJoyCons_UnregisterHints(SDL_HintCallback callback, void *userdata)
+{
+ SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, callback, userdata);
+}
+
+static SDL_bool
+HIDAPI_DriverJoyCons_IsEnabled(void)
+{
+ return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS,
+ SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI,
+ SDL_HIDAPI_DEFAULT));
+}
+
+static SDL_bool
+HIDAPI_DriverJoyCons_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)
+{
+ if (vendor_id == USB_VENDOR_NINTENDO) {
+ if (product_id == USB_PRODUCT_NINTENDO_SWITCH_PRO && device) {
+ /* This might be a Kinvoca Joy-Con that reports VID/PID as a Switch Pro controller */
+ ESwitchDeviceInfoControllerType eControllerType = ReadJoyConControllerType(device);
+ if (eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft ||
+ eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
+ return SDL_TRUE;
+ }
+ }
+
+ if (product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT ||
+ product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT ||
+ product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_GRIP) {
+ return SDL_TRUE;
+ }
+ }
+ return SDL_FALSE;
+}
+
+static void
+HIDAPI_DriverSwitch_RegisterHints(SDL_HintCallback callback, void *userdata)
+{
+ SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, callback, userdata);
+}
+
+static void
+HIDAPI_DriverSwitch_UnregisterHints(SDL_HintCallback callback, void *userdata)
+{
+ SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, callback, userdata);
+}
+
+static SDL_bool
+HIDAPI_DriverSwitch_IsEnabled(void)
+{
+ return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_SWITCH,
+ SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI,
+ SDL_HIDAPI_DEFAULT));
+}
+
+static SDL_bool
+HIDAPI_DriverSwitch_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)
+{
+ /* The HORI Wireless Switch Pad enumerates as a HID device when connected via USB
+ with the same VID/PID as when connected over Bluetooth but doesn't actually
+ support communication over USB. The most reliable way to block this without allowing the
+ controller to continually attempt to reconnect is to filter it out by manufactuer/product string.
+ Note that the controller does have a different product string when connected over Bluetooth.
+ */
+ if (SDL_strcmp(name, "HORI Wireless Switch Pad") == 0) {
+ return SDL_FALSE;
+ }
+
+ /* If it's handled by another driver, it's not handled here */
+ if (HIDAPI_DriverNintendoClassic_IsSupportedDevice(device, name, type, vendor_id, product_id, version, interface_number, interface_class, interface_subclass, interface_protocol) ||
+ HIDAPI_DriverJoyCons_IsSupportedDevice(device, name, type, vendor_id, product_id, version, interface_number, interface_class, interface_subclass, interface_protocol)) {
+ return SDL_FALSE;
+ }
+
+ return (type == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO) ? SDL_TRUE : SDL_FALSE;
+}
+
+static const char *
+HIDAPI_DriverSwitch_GetDeviceName(const char *name, Uint16 vendor_id, Uint16 product_id)
+{
+ /* Give a user friendly name for this controller */
+ if (vendor_id == USB_VENDOR_NINTENDO) {
+ if (product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_GRIP) {
+ /* We don't know if this is left or right, just leave it alone */
+ return NULL;
+ }
+
+ if (product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT) {
+ return "Nintendo Switch Joy-Con (L)";
+ }
+
+ if (product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT) {
+ if (SDL_strncmp(name, "NES Controller", 14) == 0) {
+ if (SDL_strstr(name, "(L)") != 0) {
+ return "Nintendo NES Controller (L)";
+ } else if (SDL_strstr(name, "(R)") != 0) {
+ return "Nintendo NES Controller (R)";
+ } else {
+ /* Not sure what this is, just leave it alone */
+ return NULL;
+ }
+ }
+ return "Nintendo Switch Joy-Con (R)";
+ }
+
+ if (product_id == USB_PRODUCT_NINTENDO_N64_CONTROLLER) {
+ return "Nintendo N64 Controller";
+ }
+
+ if (product_id == USB_PRODUCT_NINTENDO_SEGA_GENESIS_CONTROLLER) {
+ return "Nintendo SEGA Genesis Controller";
+ }
+
+ if (product_id == USB_PRODUCT_NINTENDO_SNES_CONTROLLER) {
+ return "Nintendo SNES Controller";
+ }
+ }
+
+ return "Nintendo Switch Pro Controller";
+}
+
static void
UpdateDeviceIdentity(SDL_HIDAPI_Device *device)
{
diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360.c b/src/joystick/hidapi/SDL_hidapi_xbox360.c
index a3a968ba9fb..5254a16ad49 100644
--- a/src/joystick/hidapi/SDL_hidapi_xbox360.c
+++ b/src/joystick/hidapi/SDL_hidapi_xbox360.c
@@ -69,7 +69,7 @@ HIDAPI_DriverXbox360_IsEnabled(void)
}
static SDL_bool
-HIDAPI_DriverXbox360_IsSupportedDevice(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)
+HIDAPI_DriverXbox360_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)
{
const int XB360W_IFACE_PROTOCOL = 129; /* Wireless */
diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360w.c b/src/joystick/hidapi/SDL_hidapi_xbox360w.c
index 2d0ad026ef1..c3fd3a01039 100644
--- a/src/joystick/hidapi/SDL_hidapi_xbox360w.c
+++ b/src/joystick/hidapi/SDL_hidapi_xbox360w.c
@@ -75,7 +75,7 @@ HIDAPI_DriverXbox360W_IsEnabled(void)
}
static SDL_bool
-HIDAPI_DriverXbox360W_IsSupportedDevice(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)
+HIDAPI_DriverXbox360W_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)
{
const int XB360W_IFACE_PROTOCOL = 129; /* Wireless */
diff --git a/src/joystick/hidapi/SDL_hidapi_xboxone.c b/src/joystick/hidapi/SDL_hidapi_xboxone.c
index 94f04b6e066..17a30a072b0 100644
--- a/src/joystick/hidapi/SDL_hidapi_xboxone.c
+++ b/src/joystick/hidapi/SDL_hidapi_xboxone.c
@@ -289,7 +289,7 @@ HIDAPI_DriverXboxOne_IsEnabled(void)
}
static SDL_bool
-HIDAPI_DriverXboxOne_IsSupportedDevice(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)
+HIDAPI_DriverXboxOne_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)
{
#ifdef __LINUX__
if (vendor_id == USB_VENDOR_POWERA && product_id == 0x541a) {
diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c
index ebe666d32ff..014d64c30ef 100644
--- a/src/joystick/hidapi/SDL_hidapijoystick.c
+++ b/src/joystick/hidapi/SDL_hidapijoystick.c
@@ -217,7 +217,7 @@ HIDAPI_IsDeviceSupported(Uint16 vendor_id, Uint16 product_id, Uint16 version, co
for (i = 0; i < SDL_arraysize(SDL_HIDAPI_drivers); ++i) {
SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i];
- if (driver->enabled && driver->IsSupportedDevice(name, type, vendor_id, product_id, version, -1, 0, 0, 0)) {
+ if (driver->enabled && driver->IsSupportedDevice(NULL, name, type, vendor_id, product_id, version, -1, 0, 0, 0)) {
return SDL_TRUE;
}
}
@@ -254,7 +254,7 @@ 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->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, type, device->vendor_id, device->product_id, device->version, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol)) {
return driver;
}
}
diff --git a/src/joystick/hidapi/SDL_hidapijoystick_c.h b/src/joystick/hidapi/SDL_hidapijoystick_c.h
index fbf21acd27c..b5d23e26f21 100644
--- a/src/joystick/hidapi/SDL_hidapijoystick_c.h
+++ b/src/joystick/hidapi/SDL_hidapijoystick_c.h
@@ -101,7 +101,7 @@ typedef struct _SDL_HIDAPI_DeviceDriver
void (*RegisterHints)(SDL_HintCallback callback, void *userdata);
void (*UnregisterHints)(SDL_HintCallback callback, void *userdata);
SDL_bool (*IsEnabled)(void);
- SDL_bool (*IsSupportedDevice)(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);
+ SDL_bool (*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);
const char *(*GetDeviceName)(const char *name, Uint16 vendor_id, Uint16 product_id);
SDL_bool (*InitDevice)(SDL_HIDAPI_Device *device);
int (*
(Patch may be truncated, please check the link at the top of this post.)