Added SDL_HINT_HIDAPI_ENUMERATE_ONLY_CONTROLLERS to control whether SDL_hid_enumerate() enumerates all HID devices or only controllers.

By default SDL will only enumerate controllers, to reduce risk of hanging or crashing on devices with bad drivers and avoiding macOS keyboard capture permission prompts.
This commit is contained in:
Sam Lantinga
2023-05-27 09:37:38 -07:00
parent 77e59d4fa9
commit 0ffeca8a1c
10 changed files with 66 additions and 89 deletions

View File

@@ -38,11 +38,6 @@
#include "hidapi_darwin.h"
/* Only matching controllers is a more safe option and prevents input monitoring permissions dialogs */
#ifndef HIDAPI_ONLY_ENUMERATE_CONTROLLERS
#define HIDAPI_ONLY_ENUMERATE_CONTROLLERS 0
#endif
/* As defined in AppKit.h, but we don't need the entire AppKit for a single constant. */
extern const double NSAppKitVersionNumber;
@@ -716,51 +711,6 @@ static struct hid_device_info *create_device_info(IOHIDDeviceRef device)
return root;
}
static CFDictionaryRef create_usage_match(const UInt32 page, const UInt32 usage, int *okay)
{
CFDictionaryRef retval = NULL;
CFNumberRef pageNumRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &page);
CFNumberRef usageNumRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage);
const void *keys[2] = { (void *) CFSTR(kIOHIDDeviceUsagePageKey), (void *) CFSTR(kIOHIDDeviceUsageKey) };
const void *vals[2] = { (void *) pageNumRef, (void *) usageNumRef };
if (pageNumRef && usageNumRef) {
retval = CFDictionaryCreate(kCFAllocatorDefault, keys, vals, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
}
if (pageNumRef) {
CFRelease(pageNumRef);
}
if (usageNumRef) {
CFRelease(usageNumRef);
}
if (!retval) {
*okay = 0;
}
return retval;
}
static CFDictionaryRef create_vendor_match(const UInt32 vendor, int *okay)
{
CFDictionaryRef retval = NULL;
CFNumberRef vidNumRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &vendor);
const void *keys[1] = { (void *) CFSTR(kIOHIDVendorIDKey) };
const void *vals[1] = { (void *) vidNumRef };
if (vidNumRef) {
retval = CFDictionaryCreate(kCFAllocatorDefault, keys, vals, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFRelease(vidNumRef);
}
if (!retval) {
*okay = 0;
}
return retval;
}
struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id)
{
struct hid_device_info *root = NULL; /* return object */
@@ -778,8 +728,9 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
process_pending_events();
/* Get a list of the Devices */
CFMutableDictionaryRef matching = NULL;
if (vendor_id != 0 || product_id != 0) {
CFMutableDictionaryRef matching = CFDictionaryCreateMutable(kCFAllocatorDefault, kIOHIDOptionsTypeNone, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
matching = CFDictionaryCreateMutable(kCFAllocatorDefault, kIOHIDOptionsTypeNone, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
if (matching && vendor_id != 0) {
CFNumberRef v = CFNumberCreate(kCFAllocatorDefault, kCFNumberShortType, &vendor_id);
@@ -792,35 +743,10 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
CFDictionarySetValue(matching, CFSTR(kIOHIDProductIDKey), p);
CFRelease(p);
}
IOHIDManagerSetDeviceMatching(hid_mgr, matching);
if (matching != NULL) {
CFRelease(matching);
}
} else if (HIDAPI_ONLY_ENUMERATE_CONTROLLERS) {
const UInt32 VALVE_USB_VID = 0x28DE;
int okay = 1;
const void *vals[] = {
(void *) create_usage_match(kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick, &okay),
(void *) create_usage_match(kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad, &okay),
(void *) create_usage_match(kHIDPage_GenericDesktop, kHIDUsage_GD_MultiAxisController, &okay),
(void *) create_vendor_match(VALVE_USB_VID, &okay),
};
CFIndex numElements = sizeof(vals) / sizeof(vals[0]);
CFArrayRef matching = okay ? CFArrayCreate(kCFAllocatorDefault, vals, numElements, &kCFTypeArrayCallBacks) : NULL;
for (i = 0; i < numElements; i++) {
if (vals[i]) {
CFRelease((CFTypeRef) vals[i]);
}
}
IOHIDManagerSetDeviceMatchingMultiple(hid_mgr, matching);
if (matching != NULL) {
CFRelease(matching);
}
} else {
IOHIDManagerSetDeviceMatching(hid_mgr, NULL);
}
IOHIDManagerSetDeviceMatching(hid_mgr, matching);
if (matching != NULL) {
CFRelease(matching);
}
CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr);
@@ -848,7 +774,9 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
/* See if there are any devices we should skip in enumeration */
unsigned short dev_vid = get_vendor_id(dev);
unsigned short dev_pid = get_product_id(dev);
if (HIDAPI_IGNORE_DEVICE(dev_vid, dev_pid)) {
unsigned short usage_page = get_int_property(dev, CFSTR(kIOHIDPrimaryUsagePageKey));
unsigned short usage = get_int_property(dev, CFSTR(kIOHIDPrimaryUsageKey));
if (HIDAPI_IGNORE_DEVICE(dev_vid, dev_pid, usage_page, usage)) {
continue;
}
#endif