From a160bc8de50a9ed7b612e84002539273c3bdca63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 9 Jan 2024 15:28:03 +0800 Subject: [PATCH] Gamepad (macOS): detect manufacturer --- src/detection/gamepad/gamepad_apple.c | 41 ++++++++++++++++++++------- src/util/apple/cf_helpers.c | 35 +++++++++++++---------- src/util/apple/cf_helpers.h | 1 + 3 files changed, 52 insertions(+), 25 deletions(-) diff --git a/src/detection/gamepad/gamepad_apple.c b/src/detection/gamepad/gamepad_apple.c index 814e2c3b8..de20ae5d8 100644 --- a/src/detection/gamepad/gamepad_apple.c +++ b/src/detection/gamepad/gamepad_apple.c @@ -1,5 +1,6 @@ #include "gamepad.h" #include "util/apple/cf_helpers.h" +#include "util/mallocHelper.h" #include #include @@ -11,11 +12,23 @@ static void enumSet(IOHIDDeviceRef value, FFlist* results) ffStrbufInit(&device->name); device->battery = 0; - CFStringRef serialNumber = IOHIDDeviceGetProperty(value, CFSTR(kIOHIDSerialNumberKey)); - ffCfStrGetString(serialNumber, &device->identifier); + CFStringRef manufacturer = IOHIDDeviceGetProperty(value, CFSTR(kIOHIDManufacturerKey)); + ffCfStrGetString(manufacturer, &device->name); CFStringRef product = IOHIDDeviceGetProperty(value, CFSTR(kIOHIDProductKey)); - ffCfStrGetString(product, &device->name); + if (device->name.length) + { + ffCfStrGetString(product, &device->identifier); + ffStrbufAppendC(&device->name, ' '); + ffStrbufAppend(&device->name, &device->identifier); + } + else + { + ffCfStrGetString(product, &device->name); + } + + CFStringRef serialNumber = IOHIDDeviceGetProperty(value, CFSTR(kIOHIDSerialNumberKey)); + ffCfStrGetString(serialNumber, &device->identifier); } const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */) @@ -24,21 +37,29 @@ const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */) if (IOHIDManagerOpen(manager, kIOHIDOptionsTypeNone) != kIOReturnSuccess) return "IOHIDManagerOpen() failed"; - CFNumberRef FF_CFTYPE_AUTO_RELEASE genericDesktop = ffCfCreateInt(kHIDPage_GenericDesktop); - CFNumberRef FF_CFTYPE_AUTO_RELEASE gamePad = ffCfCreateInt(kHIDUsage_GD_GamePad); - CFDictionaryRef FF_CFTYPE_AUTO_RELEASE matching = CFDictionaryCreate(kCFAllocatorDefault, (const void **)(CFStringRef[]){ + CFDictionaryRef FF_CFTYPE_AUTO_RELEASE matching1 = CFDictionaryCreate(kCFAllocatorDefault, (const void **)(CFStringRef[]){ CFSTR(kIOHIDDeviceUsagePageKey), CFSTR(kIOHIDDeviceUsageKey) }, (const void **)(CFNumberRef[]){ - genericDesktop, - gamePad + ffCfCreateInt(kHIDPage_GenericDesktop), + ffCfCreateInt(kHIDUsage_GD_Joystick) }, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - IOHIDManagerSetDeviceMatching(manager, matching); + CFDictionaryRef FF_CFTYPE_AUTO_RELEASE matching2 = CFDictionaryCreate(kCFAllocatorDefault, (const void **)(CFStringRef[]){ + CFSTR(kIOHIDDeviceUsagePageKey), + CFSTR(kIOHIDDeviceUsageKey) + }, (const void **)(CFNumberRef[]){ + ffCfCreateInt(kHIDPage_GenericDesktop), + ffCfCreateInt(kHIDUsage_GD_GamePad) + }, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFArrayRef FF_CFTYPE_AUTO_RELEASE matchings = CFArrayCreate(kCFAllocatorDefault, (const void **)(CFTypeRef[]){ + matching1, matching2 + }, 2, &kCFTypeArrayCallBacks); + IOHIDManagerSetDeviceMatchingMultiple(manager, matchings); CFSetRef FF_CFTYPE_AUTO_RELEASE set = IOHIDManagerCopyDevices(manager); if (set) CFSetApplyFunction(set, (CFSetApplierFunction) &enumSet, devices); - IOHIDManagerClose(manager, 0); + IOHIDManagerClose(manager, kIOHIDOptionsTypeNone); return NULL; } diff --git a/src/util/apple/cf_helpers.c b/src/util/apple/cf_helpers.c index 7b501af71..a0bc534c7 100644 --- a/src/util/apple/cf_helpers.c +++ b/src/util/apple/cf_helpers.c @@ -19,6 +19,25 @@ const char* ffCfNumGetInt64(CFTypeRef cf, int64_t* result) return "TypeID is neither 'CFNumber' nor 'CFData'"; } +const char* ffCfNumGetInt(CFTypeRef cf, int32_t* result) +{ + if(CFGetTypeID(cf) == CFNumberGetTypeID()) + { + if(!CFNumberGetValue((CFNumberRef)cf, kCFNumberSInt32Type, result)) + return "Number type is not SInt32"; + return NULL; + } + else if(CFGetTypeID(cf) == CFDataGetTypeID()) + { + if(CFDataGetLength((CFDataRef)cf) != sizeof(int)) + return "Data length is not sizeof(int)"; + CFDataGetBytes((CFDataRef)cf, CFRangeMake(0, sizeof(int)), (uint8_t*)result); + return NULL; + } + + return "TypeID is neither 'CFNumber' nor 'CFData'"; +} + const char* ffCfStrGetString(CFTypeRef cf, FFstrbuf* result) { if (!cf) @@ -86,21 +105,7 @@ const char* ffCfDictGetInt(CFDictionaryRef dict, CFStringRef key, int* result) if(cf == NULL) return "CFDictionaryGetValue() failed"; - if(CFGetTypeID(cf) == CFNumberGetTypeID()) - { - if(!CFNumberGetValue((CFNumberRef)cf, kCFNumberSInt32Type, result)) - return "Number type is not SInt32"; - return NULL; - } - else if(CFGetTypeID(cf) == CFDataGetTypeID()) - { - if(CFDataGetLength((CFDataRef)cf) != sizeof(int)) - return "Data length is not sizeof(int)"; - CFDataGetBytes((CFDataRef)cf, CFRangeMake(0, sizeof(int)), (uint8_t*)result); - return NULL; - } - - return "TypeID is neither 'CFNumber' nor 'CFData'"; + return ffCfNumGetInt(cf, result); } const char* ffCfDictGetInt64(CFDictionaryRef dict, CFStringRef key, int64_t* result) diff --git a/src/util/apple/cf_helpers.h b/src/util/apple/cf_helpers.h index a0e494710..fbfa47383 100644 --- a/src/util/apple/cf_helpers.h +++ b/src/util/apple/cf_helpers.h @@ -9,6 +9,7 @@ //Return error info if failed, NULL otherwise const char* ffCfStrGetString(CFTypeRef cf, FFstrbuf* result); +const char* ffCfNumGetInt(CFTypeRef cf, int32_t* result); const char* ffCfNumGetInt64(CFTypeRef cf, int64_t* result); const char* ffCfDictGetString(CFDictionaryRef dict, CFStringRef key, FFstrbuf* result); const char* ffCfDictGetBool(CFDictionaryRef dict, CFStringRef key, bool* result);