SDL: SDL_ShouldIgnoreGamepad() should take product IDs rather than a guid.

From c41b2bb855d541cdb67d00bd99735b3cbad15951 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Wed, 16 Oct 2024 13:52:02 -0700
Subject: [PATCH] SDL_ShouldIgnoreGamepad() should take product IDs rather than
 a guid.

This lets us early out when scanning for new hardware more quickly.
---
 src/joystick/SDL_gamepad.c                    | 14 ++++-------
 src/joystick/SDL_gamepad_c.h                  |  2 +-
 src/joystick/SDL_joystick.c                   | 13 ++++-------
 src/joystick/SDL_joystick_c.h                 |  2 +-
 src/joystick/apple/SDL_mfijoystick.m          |  8 +++----
 src/joystick/bsd/SDL_bsdjoystick.c            |  2 +-
 src/joystick/darwin/SDL_iokitjoystick.c       |  9 ++++----
 src/joystick/hidapi/SDL_hidapijoystick.c      |  2 +-
 src/joystick/linux/SDL_sysjoystick.c          |  5 ++--
 src/joystick/windows/SDL_dinputjoystick.c     |  6 ++---
 src/joystick/windows/SDL_rawinputjoystick.c   |  2 ++
 .../windows/SDL_windows_gaming_input.c        | 23 ++++++++-----------
 src/joystick/windows/SDL_xinputjoystick.c     | 19 ++++++---------
 13 files changed, 42 insertions(+), 65 deletions(-)

diff --git a/src/joystick/SDL_gamepad.c b/src/joystick/SDL_gamepad.c
index c8a4cb8932bff..3c5e7edd94a93 100644
--- a/src/joystick/SDL_gamepad.c
+++ b/src/joystick/SDL_gamepad.c
@@ -2595,12 +2595,8 @@ bool SDL_IsGamepad(SDL_JoystickID instance_id)
 /*
  * Return 1 if the gamepad should be ignored by SDL
  */
-bool SDL_ShouldIgnoreGamepad(const char *name, SDL_GUID guid)
+bool SDL_ShouldIgnoreGamepad(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
 {
-    Uint16 vendor;
-    Uint16 product;
-    Uint16 version;
-
 #ifdef SDL_PLATFORM_LINUX
     if (SDL_endswith(name, " Motion Sensors")) {
         // Don't treat the PS3 and PS4 motion controls as a separate gamepad
@@ -2624,19 +2620,17 @@ bool SDL_ShouldIgnoreGamepad(const char *name, SDL_GUID guid)
         return true;
     }
 
-    SDL_GetJoystickGUIDInfo(guid, &vendor, &product, &version, NULL);
-
-    if (SDL_IsJoystickSteamVirtualGamepad(vendor, product, version)) {
+    if (SDL_IsJoystickSteamVirtualGamepad(vendor_id, product_id, version)) {
         return !SDL_GetHintBoolean("SDL_GAMECONTROLLER_ALLOW_STEAM_VIRTUAL_GAMEPAD", false);
     }
 
     if (SDL_allowed_gamepads.num_included_entries > 0) {
-        if (SDL_VIDPIDInList(vendor, product, &SDL_allowed_gamepads)) {
+        if (SDL_VIDPIDInList(vendor_id, product_id, &SDL_allowed_gamepads)) {
             return false;
         }
         return true;
     } else {
-        if (SDL_VIDPIDInList(vendor, product, &SDL_ignored_gamepads)) {
+        if (SDL_VIDPIDInList(vendor_id, product_id, &SDL_ignored_gamepads)) {
             return true;
         }
         return false;
diff --git a/src/joystick/SDL_gamepad_c.h b/src/joystick/SDL_gamepad_c.h
index 6fffe8a37fce1..b58dd31a433d0 100644
--- a/src/joystick/SDL_gamepad_c.h
+++ b/src/joystick/SDL_gamepad_c.h
@@ -39,7 +39,7 @@ extern void SDL_PrivateGamepadRemoved(SDL_JoystickID instance_id);
 extern bool SDL_IsGamepadNameAndGUID(const char *name, SDL_GUID guid);
 
 // Function to return whether a gamepad should be ignored
-extern bool SDL_ShouldIgnoreGamepad(const char *name, SDL_GUID guid);
+extern bool SDL_ShouldIgnoreGamepad(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name);
 
 // Handle delayed guide button on a gamepad
 extern void SDL_GamepadHandleDelayedGuideButton(SDL_Joystick *joystick);
diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c
index e595aa8a825e4..8e27bc4d15658 100644
--- a/src/joystick/SDL_joystick.c
+++ b/src/joystick/SDL_joystick.c
@@ -3236,24 +3236,19 @@ static SDL_JoystickType SDL_GetJoystickGUIDType(SDL_GUID guid)
     return SDL_JOYSTICK_TYPE_UNKNOWN;
 }
 
-bool SDL_ShouldIgnoreJoystick(const char *name, SDL_GUID guid)
+bool SDL_ShouldIgnoreJoystick(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
 {
-    Uint16 vendor;
-    Uint16 product;
-
-    SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL, NULL);
-
     // Check the joystick blacklist
-    if (SDL_VIDPIDInList(vendor, product, &blacklist_devices)) {
+    if (SDL_VIDPIDInList(vendor_id, product_id, &blacklist_devices)) {
         return true;
     }
     if (!SDL_GetHintBoolean(SDL_HINT_JOYSTICK_ROG_CHAKRAM, false)) {
-        if (SDL_VIDPIDInList(vendor, product, &rog_gamepad_mice)) {
+        if (SDL_VIDPIDInList(vendor_id, product_id, &rog_gamepad_mice)) {
             return true;
         }
     }
 
-    if (SDL_ShouldIgnoreGamepad(name, guid)) {
+    if (SDL_ShouldIgnoreGamepad(vendor_id, product_id, version, name)) {
         return true;
     }
 
diff --git a/src/joystick/SDL_joystick_c.h b/src/joystick/SDL_joystick_c.h
index bee3814c2213d..d8b84c0cbf928 100644
--- a/src/joystick/SDL_joystick_c.h
+++ b/src/joystick/SDL_joystick_c.h
@@ -157,7 +157,7 @@ extern bool SDL_IsJoystickRAWINPUT(SDL_GUID guid);
 extern bool SDL_IsJoystickVIRTUAL(SDL_GUID guid);
 
 // Function to return whether a joystick should be ignored
-extern bool SDL_ShouldIgnoreJoystick(const char *name, SDL_GUID guid);
+extern bool SDL_ShouldIgnoreJoystick(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name);
 
 // Internal event queueing functions
 extern void SDL_PrivateJoystickAddTouchpad(SDL_Joystick *joystick, int nfingers);
diff --git a/src/joystick/apple/SDL_mfijoystick.m b/src/joystick/apple/SDL_mfijoystick.m
index bf0b002ea4815..0e62494fee4be 100644
--- a/src/joystick/apple/SDL_mfijoystick.m
+++ b/src/joystick/apple/SDL_mfijoystick.m
@@ -498,6 +498,10 @@ static bool IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle
         return false;
     }
 
+    if (SDL_ShouldIgnoreJoystick(vendor, product, 0, name)) {
+        return false;
+    }
+
 #ifdef ENABLE_PHYSICAL_INPUT_PROFILE
     if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) {
         NSDictionary<NSString *, GCControllerElement *> *elements = controller.physicalInputProfile.elements;
@@ -666,10 +670,6 @@ static bool IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle
     }
     device->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor, product, signature, NULL, name, 'm', subtype);
 
-    if (SDL_ShouldIgnoreJoystick(name, device->guid)) {
-        return false;
-    }
-
     /* This will be set when the first button press of the controller is
      * detected. */
     controller.playerIndex = -1;
diff --git a/src/joystick/bsd/SDL_bsdjoystick.c b/src/joystick/bsd/SDL_bsdjoystick.c
index 195c6928627d3..4b34116c31eae 100644
--- a/src/joystick/bsd/SDL_bsdjoystick.c
+++ b/src/joystick/bsd/SDL_bsdjoystick.c
@@ -426,7 +426,7 @@ static bool MaybeAddDevice(const char *path)
             name = SDL_CreateJoystickName(di.udi_vendorNo, di.udi_productNo, di.udi_vendor, di.udi_product);
             guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, di.udi_vendorNo, di.udi_productNo, di.udi_releaseNo, di.udi_vendor, di.udi_product, 0, 0);
 
-            if (SDL_ShouldIgnoreJoystick(name, guid) ||
+            if (SDL_ShouldIgnoreJoystick(di.udi_vendorNo, di.udi_productNo, di.udi_releaseNo, name) ||
                 SDL_JoystickHandledByAnotherDriver(&SDL_BSD_JoystickDriver, di.udi_vendorNo, di.udi_productNo, di.udi_releaseNo, name)) {
                 SDL_free(name);
                 FreeHwData(hw);
diff --git a/src/joystick/darwin/SDL_iokitjoystick.c b/src/joystick/darwin/SDL_iokitjoystick.c
index c51a558090736..19e503aee97b3 100644
--- a/src/joystick/darwin/SDL_iokitjoystick.c
+++ b/src/joystick/darwin/SDL_iokitjoystick.c
@@ -495,6 +495,10 @@ static bool GetDeviceInfo(IOHIDDeviceRef hidDevice, recDevice *pDevice)
         SDL_free(name);
     }
 
+    if (SDL_ShouldIgnoreJoystick(vendor, product, version, pDevice->product)) {
+        return false;
+    }
+
     if (SDL_JoystickHandledByAnotherDriver(&SDL_DARWIN_JoystickDriver, vendor, product, version, pDevice->product)) {
         return false;
     }
@@ -553,11 +557,6 @@ static void JoystickDeviceWasAddedCallback(void *ctx, IOReturn res, void *sender
         return; // not a device we care about, probably.
     }
 
-    if (SDL_ShouldIgnoreJoystick(device->product, device->guid)) {
-        FreeDevice(device);
-        return;
-    }
-
     // Get notified when this device is disconnected.
     IOHIDDeviceRegisterRemovalCallback(ioHIDDeviceObject, JoystickDeviceWasRemovedCallback, device);
     IOHIDDeviceScheduleWithRunLoop(ioHIDDeviceObject, CFRunLoopGetCurrent(), SDL_JOYSTICK_RUNLOOP_MODE);
diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c
index f5ca002bc4aad..c65d6b9a99e4e 100644
--- a/src/joystick/hidapi/SDL_hidapijoystick.c
+++ b/src/joystick/hidapi/SDL_hidapijoystick.c
@@ -328,7 +328,7 @@ static SDL_HIDAPI_DeviceDriver *HIDAPI_GetDeviceDriver(SDL_HIDAPI_Device *device
         return &SDL_HIDAPI_DriverCombined;
     }
 
-    if (SDL_ShouldIgnoreJoystick(device->name, device->guid)) {
+    if (SDL_ShouldIgnoreJoystick(device->vendor_id, device->product_id, device->version, device->name)) {
         return NULL;
     }
 
diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c
index d1eb66dd15bf1..d4a1cedd6cd2d 100644
--- a/src/joystick/linux/SDL_sysjoystick.c
+++ b/src/joystick/linux/SDL_sysjoystick.c
@@ -329,15 +329,14 @@ static bool IsJoystick(const char *path, int *fd, char **name_return, Uint16 *ve
     SDL_Log("Joystick: %s, bustype = %d, vendor = 0x%.4x, product = 0x%.4x, version = %d\n", name, inpid.bustype, inpid.vendor, inpid.product, inpid.version);
 #endif
 
-    *guid = SDL_CreateJoystickGUID(inpid.bustype, inpid.vendor, inpid.product, inpid.version, NULL, product_string, 0, 0);
-
-    if (SDL_ShouldIgnoreJoystick(name, *guid)) {
+    if (SDL_ShouldIgnoreJoystick(inpid.vendor, inpid.product, inpid.version, name)) {
         SDL_free(name);
         return false;
     }
     *name_return = name;
     *vendor_return = inpid.vendor;
     *product_return = inpid.product;
+    *guid = SDL_CreateJoystickGUID(inpid.bustype, inpid.vendor, inpid.product, inpid.version, NULL, product_string, 0, 0);
     return true;
 }
 
diff --git a/src/joystick/windows/SDL_dinputjoystick.c b/src/joystick/windows/SDL_dinputjoystick.c
index c463ce5fc40a9..03f2704faa1f5 100644
--- a/src/joystick/windows/SDL_dinputjoystick.c
+++ b/src/joystick/windows/SDL_dinputjoystick.c
@@ -472,6 +472,8 @@ static BOOL CALLBACK EnumJoystickDetectCallback(LPCDIDEVICEINSTANCE pDeviceInsta
     CHECK(QueryDeviceInfo(device, &vendor, &product));
 
     CHECK(!SDL_IsXInputDevice(vendor, product, hidPath));
+    CHECK(!SDL_ShouldIgnoreJoystick(vendor, product, version, name));
+    CHECK(!SDL_JoystickHandledByAnotherDriver(&SDL_WINDOWS_JoystickDriver, vendor, product, version, name));
 
     pNewJoystick = *(JoyStick_DeviceData **)pContext;
     while (pNewJoystick) {
@@ -514,10 +516,6 @@ static BOOL CALLBACK EnumJoystickDetectCallback(LPCDIDEVICEINSTANCE pDeviceInsta
         pNewJoystick->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor, product, version, NULL, name, 0, 0);
     }
 
-    CHECK(!SDL_ShouldIgnoreJoystick(pNewJoystick->joystickname, pNewJoystick->guid));
-
-    CHECK(!SDL_JoystickHandledByAnotherDriver(&SDL_WINDOWS_JoystickDriver, vendor, product, version, pNewJoystick->joystickname));
-
     WINDOWS_AddJoystickDevice(pNewJoystick);
     pNewJoystick = NULL;
 
diff --git a/src/joystick/windows/SDL_rawinputjoystick.c b/src/joystick/windows/SDL_rawinputjoystick.c
index b49a703de3732..a32dd7a58f084 100644
--- a/src/joystick/windows/SDL_rawinputjoystick.c
+++ b/src/joystick/windows/SDL_rawinputjoystick.c
@@ -881,7 +881,9 @@ static void RAWINPUT_AddDevice(HANDLE hDevice)
     CHECK(GetRawInputDeviceInfoA(hDevice, RIDI_DEVICENAME, dev_name, &size) != (UINT)-1);
     // Only take XInput-capable devices
     CHECK(SDL_strstr(dev_name, "IG_") != NULL);
+    CHECK(!SDL_ShouldIgnoreJoystick((Uint16)rdi.hid.dwVendorId, (Uint16)rdi.hid.dwProductId, (Uint16)rdi.hid.dwVersionNumber, ""));
     CHECK(!SDL_JoystickHandledByAnotherDriver(&SDL_RAWINPUT_JoystickDriver, (Uint16)rdi.hid.dwVendorId, (Uint16)rdi.hid.dwProductId, (Uint16)rdi.hid.dwVersionNumber, ""));
+
     device = (SDL_RAWINPUT_Device *)SDL_calloc(1, sizeof(SDL_RAWINPUT_Device));
     CHECK(device);
     device->hDevice = hDevice;
diff --git a/src/joystick/windows/SDL_windows_gaming_input.c b/src/joystick/windows/SDL_windows_gaming_input.c
index e17933d17e2e7..72bb2d7472cfa 100644
--- a/src/joystick/windows/SDL_windows_gaming_input.c
+++ b/src/joystick/windows/SDL_windows_gaming_input.c
@@ -399,7 +399,6 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde
     hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(e, &IID___x_ABI_CWindows_CGaming_CInput_CIRawGameController, (void **)&controller);
     if (SUCCEEDED(hr)) {
         char *name = NULL;
-        SDL_GUID guid = { 0 };
         Uint16 bus = SDL_HARDWARE_BUS_USB;
         Uint16 vendor = 0;
         Uint16 product = 0;
@@ -446,6 +445,10 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde
             name = SDL_strdup("");
         }
 
+        if (!ignore_joystick && SDL_ShouldIgnoreJoystick(vendor, product, version, name)) {
+            ignore_joystick = true;
+        }
+
         if (!ignore_joystick && SDL_JoystickHandledByAnotherDriver(&SDL_WGI_JoystickDriver, vendor, product, version, name)) {
             ignore_joystick = true;
         }
@@ -455,18 +458,6 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde
             ignore_joystick = true;
         }
 
-        if (!ignore_joystick) {
-            if (game_controller) {
-                type = GetGameControllerType(game_controller);
-            }
-
-            guid = SDL_CreateJoystickGUID(bus, vendor, product, version, NULL, name, 'w', (Uint8)type);
-
-            if (SDL_ShouldIgnoreJoystick(name, guid)) {
-                ignore_joystick = true;
-            }
-        }
-
         if (!ignore_joystick) {
             // New device, add it
             WindowsGamingInputControllerState *controllers = SDL_realloc(wgi.controllers, sizeof(wgi.controllers[0]) * (wgi.controller_count + 1));
@@ -474,11 +465,15 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde
                 WindowsGamingInputControllerState *state = &controllers[wgi.controller_count];
                 SDL_JoystickID joystickID = SDL_GetNextObjectID();
 
+                if (game_controller) {
+                    type = GetGameControllerType(game_controller);
+                }
+
                 SDL_zerop(state);
                 state->instance_id = joystickID;
                 state->controller = controller;
                 state->name = name;
-                state->guid = guid;
+                state->guid = SDL_CreateJoystickGUID(bus, vendor, product, version, NULL, name, 'w', (Uint8)type);
                 state->type = type;
                 state->steam_virtual_gamepad_slot = GetSteamVirtualGamepadSlot(controller, vendor, product);
 
diff --git a/src/joystick/windows/SDL_xinputjoystick.c b/src/joystick/windows/SDL_xinputjoystick.c
index 9c36e677d8770..d1328ce56d766 100644
--- a/src/joystick/windows/SDL_xinputjoystick.c
+++ b/src/joystick/windows/SDL_xinputjoystick.c
@@ -185,13 +185,18 @@ static void AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pC
         pNewJoystick = pNewJoystick->pNext;
     }
 
+    name = GetXInputName(userid, SubType);
+    GetXInputDeviceInfo(userid, &vendor, &product, &version);
+    if (SDL_ShouldIgnoreJoystick(vendor, product, version, name) ||
+        SDL_JoystickHandledByAnotherDriver(&SDL_WINDOWS_JoystickDriver, vendor, product, version, name)) {
+        return;
+    }
+
     pNewJoystick = (JoyStick_DeviceData *)SDL_calloc(1, sizeof(JoyStick_DeviceData));
     if (!pNewJoystick) {
         return; // better luck next time?
     }
 
-    name = GetXInputName(userid, SubType);
-    GetXInputDeviceInfo(userid, &vendor, &product, &version);
     pNewJoystick->bXInputDevice = true;
     pNewJoystick->joystickname = SDL_CreateJoystickName(vendor, product, NULL, name);
     if (!pNewJoystick->joystickname) {
@@ -203,16 +208,6 @@ static void AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pC
     pNewJoystick->SubType = SubType;
     pNewJoystick->XInputUserId = userid;
 
-    if (SDL_ShouldIgnoreJoystick(pNewJoystick->joystickname, pNewJoystick->guid)) {
-        SDL_free(pNewJoystick);
-        return;
-    }
-
-    if (SDL_JoystickHandledByAnotherDriver(&SDL_WINDOWS_JoystickDriver, vendor, product, version, pNewJoystick->joystickname)) {
-        SDL_free(pNewJoystick);
-        return;
-    }
-
     WINDOWS_AddJoystickDevice(pNewJoystick);
 }