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.
This commit is contained in:
Sam Lantinga
2025-12-30 10:35:32 -08:00
parent 95ac0ff4d6
commit d33642b710
8 changed files with 16 additions and 42 deletions

View File

@@ -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

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -999,7 +999,7 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
}
/* 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;
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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