diff --git a/OSBindings/Mac/Clock Signal/Joystick Manager/CSJoystickManager.m b/OSBindings/Mac/Clock Signal/Joystick Manager/CSJoystickManager.m index 417b65752..6bc827e35 100644 --- a/OSBindings/Mac/Clock Signal/Joystick Manager/CSJoystickManager.m +++ b/OSBindings/Mac/Clock Signal/Joystick Manager/CSJoystickManager.m @@ -11,21 +11,29 @@ @import IOKit; #include +@interface CSJoystickManager () +- (void)deviceMatched:(IOHIDDeviceRef)device result:(IOReturn)result sender:(void *)sender; +- (void)deviceRemoved:(IOHIDDeviceRef)device result:(IOReturn)result sender:(void *)sender; +@end + static void DeviceMatched(void *context, IOReturn result, void *sender, IOHIDDeviceRef device) { - NSLog(@"Matched"); + [(__bridge CSJoystickManager *)context deviceMatched:device result:result sender:sender]; } static void DeviceRemoved(void *context, IOReturn result, void *sender, IOHIDDeviceRef device) { - NSLog(@"Removed"); + [(__bridge CSJoystickManager *)context deviceRemoved:device result:result sender:sender]; } @implementation CSJoystickManager { IOHIDManagerRef _hidManager; + NSMutableSet *_activeDevices; } - (instancetype)init { self = [super init]; if(self) { + _activeDevices = [[NSMutableSet alloc] init]; + _hidManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); if(!_hidManager) return nil; @@ -56,4 +64,57 @@ static void DeviceRemoved(void *context, IOReturn result, void *sender, IOHIDDev CFRelease(_hidManager); } +- (void)deviceMatched:(IOHIDDeviceRef)device result:(IOReturn)result sender:(void *)sender { + NSValue *const deviceKey = [NSValue valueWithPointer:device]; + if([_activeDevices containsObject:deviceKey]) { + return; + } + + [_activeDevices addObject:deviceKey]; + NSLog(@"Matched"); + + const CFArrayRef elements = IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone); + for(CFIndex index = 0; index < CFArrayGetCount(elements); ++index) { + const IOHIDElementRef element = (IOHIDElementRef)CFArrayGetValueAtIndex(elements, index); + + // Check that this element is either on the generic desktop page or else is a button. + const uint32_t usagePage = IOHIDElementGetUsagePage(element); + if(usagePage != kHIDPage_GenericDesktop && usagePage != kHIDPage_Button) continue; + + // Then inspect the usage and type. + const IOHIDElementType type = IOHIDElementGetType(element); + + // IOHIDElementGetCookie + + switch(type) { + default: break; + case kIOHIDElementTypeInput_Button: + // Add a buton + break; + + case kIOHIDElementTypeInput_Misc: + case kIOHIDElementTypeInput_Axis: { + const uint32_t usage = IOHIDElementGetUsage(element); + // Add something depending on usage... + } break; + + case kIOHIDElementTypeCollection: + // TODO: recurse. + break; + } + } + + CFRelease(elements); +} + +- (void)deviceRemoved:(IOHIDDeviceRef)device result:(IOReturn)result sender:(void *)sender { + NSValue *const deviceKey = [NSValue valueWithPointer:device]; + if(![_activeDevices containsObject:deviceKey]) { + return; + } + + [_activeDevices removeObject:deviceKey]; + NSLog(@"Removed"); +} + @end