Commit 4572dd2ae6e13836cd40ede273d840b06014996a

Sam Lantinga 2020-03-02T10:37:28

Fixed bug 4854 - Add a way to extend the values in controller_type.h Added a hint SDL_HINT_GAMECONTROLLERTYPE to allow overriding the built-in controller type database

diff --git a/include/SDL_hints.h b/include/SDL_hints.h
index 04e92e1..a3a5373 100644
--- a/include/SDL_hints.h
+++ b/include/SDL_hints.h
@@ -469,6 +469,24 @@ extern "C" {
 #define SDL_HINT_XINPUT_USE_OLD_JOYSTICK_MAPPING "SDL_XINPUT_USE_OLD_JOYSTICK_MAPPING"
 
 /**
+ *  \brief  A variable that overrides the automatic controller type detection
+ *
+ *  The variable should be comma separated entries, in the form: VID/PID=type
+ *
+ *  The VID and PID should be hexadecimal with exactly 4 digits, e.g. 0x00fd
+ *
+ *  The type should be one of:
+ *      Xbox360
+ *      XboxOne
+ *      PS3
+ *      PS4
+ *      SwitchPro
+ *
+ *  This hint affects what driver is used, and must be set before calling SDL_Init(SDL_INIT_GAMECONTROLLER)
+ */
+#define SDL_HINT_GAMECONTROLLERTYPE "SDL_GAMECONTROLLERTYPE"
+
+/**
  *  \brief  A variable that lets you manually hint extra gamecontroller db entries.
  *
  *  The variable should be newline delimited rows of gamecontroller config data, see SDL_gamecontroller.h
diff --git a/src/joystick/controller_type.h b/src/joystick/controller_type.h
index a744a2b..0ea1cbf 100644
--- a/src/joystick/controller_type.h
+++ b/src/joystick/controller_type.h
@@ -540,6 +540,30 @@ static const ControllerDescription_t arrControllers[] = {
 	{ MAKE_CONTROLLER_ID( 0x28de, 0x1202 ), k_eControllerType_SteamControllerV2, NULL },	// Valve Bluetooth Steam Controller (HEADCRAB)
 };
 
+static SDL_INLINE const char *GetControllerTypeOverride( int nVID, int nPID )
+{
+	const char *hint = SDL_GetHint(SDL_HINT_GAMECONTROLLERTYPE);
+	if (hint) {
+		char key[32];
+		const char *spot = NULL;
+
+		SDL_snprintf(key, sizeof(key), "0x%.4x/0x%.4x=", nVID, nPID);
+		spot = SDL_strstr(hint, key);
+		if (!spot) {
+			SDL_snprintf(key, sizeof(key), "0x%.4X/0x%.4X=", nVID, nPID);
+			spot = SDL_strstr(hint, key);
+		}
+		if (spot) {
+			spot += SDL_strlen(key);
+			if (SDL_strncmp(spot, "k_eControllerType_", 18) == 0) {
+				spot += 18;
+			}
+			return spot;
+		}
+	}
+	return NULL;
+}
+
 static SDL_INLINE EControllerType GuessControllerType( int nVID, int nPID )
 {
 #if 0//def _DEBUG
@@ -565,6 +589,37 @@ static SDL_INLINE EControllerType GuessControllerType( int nVID, int nPID )
 
 	unsigned int unDeviceID = MAKE_CONTROLLER_ID( nVID, nPID );
 	int iIndex;
+
+	const char *pszOverride = GetControllerTypeOverride( nVID, nPID );
+	if ( pszOverride )
+	{
+		if ( SDL_strncasecmp( pszOverride, "Xbox360", 7 ) == 0 )
+		{
+			return k_eControllerType_XBox360Controller;
+		}
+		if ( SDL_strncasecmp( pszOverride, "XboxOne", 7 ) == 0 )
+		{
+			return k_eControllerType_XBoxOneController;
+		}
+		if ( SDL_strncasecmp( pszOverride, "PS3", 3 ) == 0 )
+		{
+			return k_eControllerType_PS3Controller;
+		}
+		if ( SDL_strncasecmp( pszOverride, "PS4", 3 ) == 0 )
+		{
+			return k_eControllerType_PS4Controller;
+		}
+		if ( SDL_strncasecmp( pszOverride, "SwitchPro", 9 ) == 0 )
+		{
+			return k_eControllerType_SwitchProController;
+		}
+		if ( SDL_strncasecmp( pszOverride, "Steam", 5 ) == 0 )
+		{
+			return k_eControllerType_SteamController;
+		}
+		return k_eControllerType_UnknownNonSteamController;
+	}
+
 	for ( iIndex = 0; iIndex < sizeof( arrControllers ) / sizeof( arrControllers[0] ); ++iIndex )
 	{
 		if ( unDeviceID == arrControllers[ iIndex ].m_unDeviceID )