From 878259722f60976ed5e9e74c2d311e8c15fe5da9 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Mon, 8 Aug 2022 08:22:20 -0700
Subject: [PATCH] Added SDL_GameControllerType enumeration for Nintendo Switch
Joy-Con controllers
---
include/SDL_gamecontroller.h | 5 +++-
src/joystick/SDL_joystick.c | 23 ++++++++++++-----
src/joystick/hidapi/SDL_hidapi_switch.c | 33 ++++++++++++++----------
src/joystick/hidapi/SDL_hidapijoystick.c | 4 +--
src/joystick/usb_ids.h | 8 +++---
test/testgamecontroller.c | 5 ++++
6 files changed, 51 insertions(+), 27 deletions(-)
diff --git a/include/SDL_gamecontroller.h b/include/SDL_gamecontroller.h
index 0ef0090ad17..00f08d34a71 100644
--- a/include/SDL_gamecontroller.h
+++ b/include/SDL_gamecontroller.h
@@ -70,7 +70,10 @@ typedef enum
SDL_CONTROLLER_TYPE_PS5,
SDL_CONTROLLER_TYPE_AMAZON_LUNA,
SDL_CONTROLLER_TYPE_GOOGLE_STADIA,
- SDL_CONTROLLER_TYPE_NVIDIA_SHIELD
+ SDL_CONTROLLER_TYPE_NVIDIA_SHIELD,
+ SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT,
+ SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT,
+ SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR
} SDL_GameControllerType;
typedef enum
diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c
index c5c56e5ecaa..2155a48d0c9 100644
--- a/src/joystick/SDL_joystick.c
+++ b/src/joystick/SDL_joystick.c
@@ -1833,11 +1833,6 @@ SDL_CreateJoystickName(Uint16 vendor, Uint16 product, const char *vendor_name, c
char *name;
size_t i, len;
- /* Use the given name for the Nintendo Online NES Controllers */
- if (product_name && SDL_strncmp(product_name, "NES Controller", 14) == 0) {
- return SDL_strdup(product_name);
- }
-
custom_name = GuessControllerName(vendor, product);
if (custom_name) {
return SDL_strdup(custom_name);
@@ -1977,6 +1972,20 @@ SDL_GetJoystickGameControllerTypeFromVIDPID(Uint16 vendor, Uint16 product, const
} else if (vendor == USB_VENDOR_GOOGLE && product == USB_PRODUCT_GOOGLE_STADIA_CONTROLLER) {
type = SDL_CONTROLLER_TYPE_GOOGLE_STADIA;
+ } else if (vendor == USB_VENDOR_NINTENDO && product == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT) {
+ type = SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT;
+
+ } else if (vendor == USB_VENDOR_NINTENDO && product == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT) {
+ if (name && SDL_strstr(name, "NES Controller") != NULL) {
+ /* We don't have a type for the Nintendo Online NES Controller */
+ type = SDL_CONTROLLER_TYPE_UNKNOWN;
+ } else {
+ type = SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT;
+ }
+
+ } else if (vendor == USB_VENDOR_NINTENDO && product == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_PAIR) {
+ type = SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR;
+
} else if (vendor == USB_VENDOR_NVIDIA && product == USB_PRODUCT_NVIDIA_SHIELD_CONTROLLER) {
type = SDL_CONTROLLER_TYPE_NVIDIA_SHIELD;
@@ -2165,13 +2174,13 @@ SDL_IsJoystickNintendoSwitchJoyConRight(Uint16 vendor_id, Uint16 product_id)
SDL_bool
SDL_IsJoystickNintendoSwitchJoyConGrip(Uint16 vendor_id, Uint16 product_id)
{
- return (vendor_id == USB_VENDOR_NINTENDO && product_id == USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_GRIP);
+ return (vendor_id == USB_VENDOR_NINTENDO && product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_GRIP);
}
SDL_bool
SDL_IsJoystickNintendoSwitchJoyConPair(Uint16 vendor_id, Uint16 product_id)
{
- return (vendor_id == USB_VENDOR_NINTENDO && product_id == USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_PAIR);
+ return (vendor_id == USB_VENDOR_NINTENDO && product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_PAIR);
}
SDL_bool
diff --git a/src/joystick/hidapi/SDL_hidapi_switch.c b/src/joystick/hidapi/SDL_hidapi_switch.c
index 9b9be148a1b..35c5dedef9e 100644
--- a/src/joystick/hidapi/SDL_hidapi_switch.c
+++ b/src/joystick/hidapi/SDL_hidapi_switch.c
@@ -363,7 +363,7 @@ 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_JOY_CON_RIGHT) {
+ if (product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT) {
if (SDL_strncmp(name, "NES Controller", 14) == 0) {
return SDL_TRUE;
}
@@ -389,9 +389,9 @@ 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_JOY_CON_LEFT ||
- product_id == USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_RIGHT ||
- product_id == USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_GRIP) {
+ 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;
}
}
@@ -425,18 +425,25 @@ HIDAPI_DriverSwitch_GetDeviceName(const char *name, Uint16 vendor_id, Uint16 pro
{
/* Give a user friendly name for this controller */
if (vendor_id == USB_VENDOR_NINTENDO) {
- if (product_id == USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_GRIP) {
- return "Nintendo Switch Joy-Con Grip";
+ 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_JOY_CON_LEFT) {
+ if (product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT) {
return "Nintendo Switch Joy-Con (L)";
}
- if (product_id == USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_RIGHT) {
- /* Use the given name for the Nintendo Online NES Controllers */
+ if (product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT) {
if (SDL_strncmp(name, "NES Controller", 14) == 0) {
- return name;
+ 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)";
}
@@ -1062,7 +1069,7 @@ static int
GetMaxWriteAttempts(SDL_HIDAPI_Device *device)
{
if (device->vendor_id == USB_VENDOR_NINTENDO &&
- device->product_id == USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_GRIP) {
+ device->product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_GRIP) {
/* This device is a little slow and we know we're always on USB */
return 20;
} else {
@@ -1159,7 +1166,7 @@ HIDAPI_DriverSwitch_InitDevice(SDL_HIDAPI_Device *device)
switch (eControllerType) {
case k_eSwitchDeviceInfoControllerType_Unknown:
/* This might be a Joy-Con that's missing from a charging grip slot */
- if (device->product_id == USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_GRIP) {
+ if (device->product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_GRIP) {
if (device->interface_number == 1) {
SDL_free(device->name);
device->name = SDL_strdup("Nintendo Switch Joy-Con (L)");
@@ -2006,7 +2013,7 @@ HIDAPI_DriverSwitch_UpdateDevice(SDL_HIDAPI_Device *device)
}
if (!ctx->m_bInputOnly && !ctx->m_bUsingBluetooth &&
- ctx->device->product_id != USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_GRIP) {
+ ctx->device->product_id != USB_PRODUCT_NINTENDO_SWITCH_JOYCON_GRIP) {
const Uint32 INPUT_WAIT_TIMEOUT_MS = 100;
if (SDL_TICKS_PASSED(now, ctx->m_unLastInput + INPUT_WAIT_TIMEOUT_MS)) {
/* Steam may have put the controller back into non-reporting mode */
diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c
index 4a9b80fd3f9..fdeacc0f7ed 100644
--- a/src/joystick/hidapi/SDL_hidapijoystick.c
+++ b/src/joystick/hidapi/SDL_hidapijoystick.c
@@ -312,7 +312,7 @@ HIDAPI_SetupDeviceDriver(SDL_HIDAPI_Device *device)
if (device->driver) {
SDL_bool enabled;
- if (device->vendor_id == USB_VENDOR_NINTENDO && device->product_id == USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_PAIR) {
+ if (device->vendor_id == USB_VENDOR_NINTENDO && device->product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_PAIR) {
enabled = SDL_HIDAPI_combine_joycons;
} else {
enabled = device->driver->enabled;
@@ -770,7 +770,7 @@ HIDAPI_CreateCombinedJoyCons()
SDL_zero(info);
info.path = "nintendo_joycons_combined";
info.vendor_id = USB_VENDOR_NINTENDO;
- info.product_id = USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_PAIR;
+ info.product_id = USB_PRODUCT_NINTENDO_SWITCH_JOYCON_PAIR;
info.interface_number = -1;
info.usage_page = USB_USAGEPAGE_GENERIC_DESKTOP;
info.usage = USB_USAGE_GENERIC_GAMEPAD;
diff --git a/src/joystick/usb_ids.h b/src/joystick/usb_ids.h
index 779f552a042..a22a2865259 100644
--- a/src/joystick/usb_ids.h
+++ b/src/joystick/usb_ids.h
@@ -48,10 +48,10 @@
#define USB_PRODUCT_NINTENDO_N64_CONTROLLER 0x2019
#define USB_PRODUCT_NINTENDO_SEGA_GENESIS_CONTROLLER 0x201e
#define USB_PRODUCT_NINTENDO_SNES_CONTROLLER 0x2017
-#define USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_GRIP 0x200e
-#define USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_LEFT 0x2006
-#define USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_PAIR 0x2008 /* Used by joycond */
-#define USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_RIGHT 0x2007
+#define USB_PRODUCT_NINTENDO_SWITCH_JOYCON_GRIP 0x200e
+#define USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT 0x2006
+#define USB_PRODUCT_NINTENDO_SWITCH_JOYCON_PAIR 0x2008 /* Used by joycond */
+#define USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT 0x2007
#define USB_PRODUCT_NINTENDO_SWITCH_PRO 0x2009
#define USB_PRODUCT_NVIDIA_SHIELD_CONTROLLER 0x7214
#define USB_PRODUCT_RAZER_PANTHERA 0x0401
diff --git a/test/testgamecontroller.c b/test/testgamecontroller.c
index fce349a14e1..7e51bcbfcef 100644
--- a/test/testgamecontroller.c
+++ b/test/testgamecontroller.c
@@ -814,6 +814,11 @@ main(int argc, char *argv[])
case SDL_CONTROLLER_TYPE_GOOGLE_STADIA:
description = "Google Stadia Controller";
break;
+ case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT:
+ case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT:
+ case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR:
+ description = "Nintendo Switch Joy-Con";
+ break;
case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO:
description = "Nintendo Switch Pro Controller";
break;