From 5985f0a327910648aff75ca7134f3a7c7ff83721 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Mon, 17 Mar 2025 19:10:26 -0700
Subject: [PATCH] Fixed infinite recursion in SDL_IsGamepad()
SDL_IsGamepad() calls SDL_GetJoystickTypeForID(), which will call SDL_IsGamepad() if it's not a known controller type. The new code which is breaking was added to prevent Logitech FFB wheels from showing up as gamepads, which we check for separately.
---
src/joystick/SDL_gamepad.c | 12 +++++++-----
src/joystick/SDL_joystick.c | 2 +-
src/joystick/SDL_joystick_c.h | 3 +++
3 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/src/joystick/SDL_gamepad.c b/src/joystick/SDL_gamepad.c
index 59bd217f5b920..0bff7bf5f855b 100644
--- a/src/joystick/SDL_gamepad.c
+++ b/src/joystick/SDL_gamepad.c
@@ -699,6 +699,12 @@ static GamepadMapping_t *SDL_CreateMappingForHIDAPIGamepad(SDL_GUID guid)
SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL, NULL);
+ if (SDL_IsJoystickWheel(vendor, product)) {
+ // We don't want to pick up Logitech FFB wheels here
+ // Some versions of WINE will also not treat devices that show up as gamepads as wheels
+ return NULL;
+ }
+
if ((vendor == USB_VENDOR_NINTENDO && product == USB_PRODUCT_NINTENDO_GAMECUBE_ADAPTER) ||
(vendor == USB_VENDOR_DRAGONRISE &&
(product == USB_PRODUCT_EVORETRO_GAMECUBE_ADAPTER1 ||
@@ -2633,11 +2639,7 @@ bool SDL_IsGamepad(SDL_JoystickID instance_id)
if (SDL_FindInHashTable(s_gamepadInstanceIDs, (void *)(uintptr_t)instance_id, &value)) {
result = (bool)(uintptr_t)value;
} else {
- SDL_JoystickType js_type = SDL_GetJoystickTypeForID(instance_id);
- if (js_type != SDL_JOYSTICK_TYPE_GAMEPAD && js_type != SDL_JOYSTICK_TYPE_UNKNOWN) {
- // avoid creating HIDAPI mapping if SDL_Joystick knows it is not a game pad
- result = false;
- } else if (SDL_PrivateGetGamepadMapping(instance_id, true) != NULL) {
+ if (SDL_PrivateGetGamepadMapping(instance_id, true) != NULL) {
result = true;
} else {
result = false;
diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c
index a4d86688c7302..8f7947b825b3c 100644
--- a/src/joystick/SDL_joystick.c
+++ b/src/joystick/SDL_joystick.c
@@ -3049,7 +3049,7 @@ bool SDL_IsJoystickVIRTUAL(SDL_GUID guid)
return (guid.data[14] == 'v') ? true : false;
}
-static bool SDL_IsJoystickWheel(Uint16 vendor_id, Uint16 product_id)
+bool SDL_IsJoystickWheel(Uint16 vendor_id, Uint16 product_id)
{
return SDL_VIDPIDInList(vendor_id, product_id, &wheel_devices);
}
diff --git a/src/joystick/SDL_joystick_c.h b/src/joystick/SDL_joystick_c.h
index d931cf7ed73f2..6b82365c5865b 100644
--- a/src/joystick/SDL_joystick_c.h
+++ b/src/joystick/SDL_joystick_c.h
@@ -156,6 +156,9 @@ extern bool SDL_IsJoystickRAWINPUT(SDL_GUID guid);
// Function to return whether a joystick guid comes from the Virtual driver
extern bool SDL_IsJoystickVIRTUAL(SDL_GUID guid);
+// Function to return whether a joystick is a wheel
+bool SDL_IsJoystickWheel(Uint16 vendor_id, Uint16 product_id);
+
// Function to return whether a joystick should be ignored
extern bool SDL_ShouldIgnoreJoystick(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name);