From d33642b710d8cb4ae8e5a63d92a953ee9fee7c61 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Tue, 30 Dec 2025 10:35:32 -0800
Subject: [PATCH] Filter libusb devices early in enumeration
Some device drivers crash if you query things like manufacturer and product name, so make sure we only touch devices that we're really interested in.
---
src/hidapi/SDL_hidapi.c | 44 ++++++++------------------------------
src/hidapi/SDL_hidapi_c.h | 2 +-
src/hidapi/android/hid.cpp | 2 +-
src/hidapi/ios/hid.m | 2 +-
src/hidapi/libusb/hid.c | 2 +-
src/hidapi/linux/hid.c | 2 +-
src/hidapi/mac/hid.c | 2 +-
src/hidapi/windows/hid.c | 2 +-
8 files changed, 16 insertions(+), 42 deletions(-)
diff --git a/src/hidapi/SDL_hidapi.c b/src/hidapi/SDL_hidapi.c
index 276a33f8592b7..d008bb5ab0714 100644
--- a/src/hidapi/SDL_hidapi.c
+++ b/src/hidapi/SDL_hidapi.c
@@ -540,8 +540,8 @@ static void HIDAPI_ShutdownDiscovery(void)
// Platform HIDAPI Implementation
#define HIDAPI_USING_SDL_RUNTIME
-#define HIDAPI_IGNORE_DEVICE(BUS, VID, PID, USAGE_PAGE, USAGE) \
- SDL_HIDAPI_ShouldIgnoreDevice(BUS, VID, PID, USAGE_PAGE, USAGE)
+#define HIDAPI_IGNORE_DEVICE(BUS, VID, PID, USAGE_PAGE, USAGE, LIBUSB) \
+ SDL_HIDAPI_ShouldIgnoreDevice(BUS, VID, PID, USAGE_PAGE, USAGE, LIBUSB)
struct PLATFORM_hid_device_;
typedef struct PLATFORM_hid_device_ PLATFORM_hid_device;
@@ -1049,8 +1049,14 @@ static void SDLCALL IgnoredDevicesChanged(void *userdata, const char *name, cons
}
}
-bool SDL_HIDAPI_ShouldIgnoreDevice(int bus, Uint16 vendor_id, Uint16 product_id, Uint16 usage_page, Uint16 usage)
+bool SDL_HIDAPI_ShouldIgnoreDevice(int bus, Uint16 vendor_id, Uint16 product_id, Uint16 usage_page, Uint16 usage, bool libusb)
{
+#ifdef HAVE_LIBUSB
+ if (libusb && use_libusb_whitelist && !IsInWhitelist(vendor_id, product_id)) {
+ return true;
+ }
+#endif
+
// See if there are any devices we should skip in enumeration
if (SDL_hidapi_only_controllers && usage_page) {
if (vendor_id == USB_VENDOR_VALVE) {
@@ -1290,34 +1296,6 @@ static void RemoveDeviceFromEnumeration(const char *driver_name, struct hid_devi
}
#endif // HAVE_LIBUSB || HAVE_PLATFORM_BACKEND
-#ifdef HAVE_LIBUSB
-static void RemoveNonWhitelistedDevicesFromEnumeration(struct hid_device_info **devs, void (*free_device_info)(struct hid_device_info *))
-{
- struct hid_device_info *last = NULL, *curr, *next;
-
- for (curr = *devs; curr; curr = next) {
- next = curr->next;
-
- if (!IsInWhitelist(curr->vendor_id, curr->product_id)) {
-#ifdef DEBUG_HIDAPI
- SDL_Log("Device was not in libusb whitelist, skipping: %ls %ls 0x%.4hx/0x%.4hx/%d",
- curr->manufacturer_string, curr->product_string, curr->vendor_id, curr->product_id, curr->interface_number);
-#endif
- if (last) {
- last->next = next;
- } else {
- *devs = next;
- }
-
- curr->next = NULL;
- free_device_info(curr);
- continue;
- }
- last = curr;
- }
-}
-#endif // HAVE_LIBUSB
-
struct SDL_hid_device_info *SDL_hid_enumerate(unsigned short vendor_id, unsigned short product_id)
{
struct hid_device_info *driver_devs = NULL;
@@ -1338,10 +1316,6 @@ struct SDL_hid_device_info *SDL_hid_enumerate(unsigned short vendor_id, unsigned
#ifdef HAVE_LIBUSB
if (libusb_ctx) {
usb_devs = LIBUSB_hid_enumerate(vendor_id, product_id);
-
- if (use_libusb_whitelist) {
- RemoveNonWhitelistedDevicesFromEnumeration(&usb_devs, LIBUSB_hid_free_enumeration);
- }
}
#endif // HAVE_LIBUSB
diff --git a/src/hidapi/SDL_hidapi_c.h b/src/hidapi/SDL_hidapi_c.h
index 77272d3e6125d..2c2c8d14d5b27 100644
--- a/src/hidapi/SDL_hidapi_c.h
+++ b/src/hidapi/SDL_hidapi_c.h
@@ -22,5 +22,5 @@
/* Return true if the HIDAPI should ignore a device during enumeration */
-extern bool SDL_HIDAPI_ShouldIgnoreDevice(int bus_type, Uint16 vendor_id, Uint16 product_id, Uint16 usage_page, Uint16 usage);
+extern bool SDL_HIDAPI_ShouldIgnoreDevice(int bus_type, Uint16 vendor_id, Uint16 product_id, Uint16 usage_page, Uint16 usage, bool libusb);
diff --git a/src/hidapi/android/hid.cpp b/src/hidapi/android/hid.cpp
index 2dbfb8ed8892a..934912962a78a 100644
--- a/src/hidapi/android/hid.cpp
+++ b/src/hidapi/android/hid.cpp
@@ -1092,7 +1092,7 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor
const hid_device_info *info = pDevice->GetDeviceInfo();
/* See if there are any devices we should skip in enumeration */
- if (SDL_HIDAPI_ShouldIgnoreDevice(HID_API_BUS_UNKNOWN, info->vendor_id, info->product_id, 0, 0)) {
+ if (SDL_HIDAPI_ShouldIgnoreDevice(HID_API_BUS_UNKNOWN, info->vendor_id, info->product_id, 0, 0, false)) {
continue;
}
diff --git a/src/hidapi/ios/hid.m b/src/hidapi/ios/hid.m
index 24a3c791ee1d7..4ab72e3c1905a 100644
--- a/src/hidapi/ios/hid.m
+++ b/src/hidapi/ios/hid.m
@@ -999,7 +999,7 @@ int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock)
}
/* See if there are any devices we should skip in enumeration */
- if (SDL_HIDAPI_ShouldIgnoreDevice(HID_API_BUS_BLUETOOTH, VALVE_USB_VID, device.pid, 0, 0)) {
+ if (SDL_HIDAPI_ShouldIgnoreDevice(HID_API_BUS_BLUETOOTH, VALVE_USB_VID, device.pid, 0, 0, false)) {
continue;
}
diff --git a/src/hidapi/libusb/hid.c b/src/hidapi/libusb/hid.c
index 16bec68f188b3..f8d6dc9260943 100644
--- a/src/hidapi/libusb/hid.c
+++ b/src/hidapi/libusb/hid.c
@@ -982,7 +982,7 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
#ifdef HIDAPI_IGNORE_DEVICE
/* See if there are any devices we should skip in enumeration */
- if (HIDAPI_IGNORE_DEVICE(HID_API_BUS_USB, dev_vid, dev_pid, 0, 0)) {
+ if (HIDAPI_IGNORE_DEVICE(HID_API_BUS_USB, dev_vid, dev_pid, 0, 0, true)) {
continue;
}
#endif
diff --git a/src/hidapi/linux/hid.c b/src/hidapi/linux/hid.c
index 278b794a78c73..c0cb6a7b0e255 100644
--- a/src/hidapi/linux/hid.c
+++ b/src/hidapi/linux/hid.c
@@ -906,7 +906,7 @@ static struct hid_device_info * create_device_info_for_device(struct udev_device
cur_dev = root;
while (cur_dev) {
- if (HIDAPI_IGNORE_DEVICE(cur_dev->bus_type, cur_dev->vendor_id, cur_dev->product_id, cur_dev->usage_page, cur_dev->usage)) {
+ if (HIDAPI_IGNORE_DEVICE(cur_dev->bus_type, cur_dev->vendor_id, cur_dev->product_id, cur_dev->usage_page, cur_dev->usage, false)) {
struct hid_device_info *tmp = cur_dev;
cur_dev = tmp->next;
diff --git a/src/hidapi/mac/hid.c b/src/hidapi/mac/hid.c
index 3bb40aa1b97f8..4936fe12625e8 100644
--- a/src/hidapi/mac/hid.c
+++ b/src/hidapi/mac/hid.c
@@ -596,7 +596,7 @@ static struct hid_device_info *create_device_info_with_usage(IOHIDDeviceRef dev,
#ifdef HIDAPI_IGNORE_DEVICE
/* See if there are any devices we should skip in enumeration */
- if (HIDAPI_IGNORE_DEVICE(get_bus_type(dev), dev_vid, dev_pid, usage_page, usage)) {
+ if (HIDAPI_IGNORE_DEVICE(get_bus_type(dev), dev_vid, dev_pid, usage_page, usage, false)) {
free(cur_dev);
return NULL;
}
diff --git a/src/hidapi/windows/hid.c b/src/hidapi/windows/hid.c
index e8bfb026b5e40..aa67a466d3c60 100644
--- a/src/hidapi/windows/hid.c
+++ b/src/hidapi/windows/hid.c
@@ -1042,7 +1042,7 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor
HidP_GetCaps(pp_data, &caps);
HidD_FreePreparsedData(pp_data);
}
- if (HIDAPI_IGNORE_DEVICE(bus_type, attrib.VendorID, attrib.ProductID, caps.UsagePage, caps.Usage)) {
+ if (HIDAPI_IGNORE_DEVICE(bus_type, attrib.VendorID, attrib.ProductID, caps.UsagePage, caps.Usage, false)) {
goto cont_close;
}
#endif