kern_return_t IOHIDGetModifierLockState( io_connect_t handle __unused, int selector, bool *state ) { kern_return_t err = kIOReturnSuccess; boolean_t modifierState = false; IOHIDEventSystemClientRef client = NULL; CFArrayRef services = NULL; if (selector != kIOHIDCapsLockState && selector != kIOHIDNumLockState) { err = kIOReturnBadArgument; goto exit; } client = IOHIDEventSystemClientCreateWithType (kCFAllocatorDefault, kIOHIDEventSystemClientTypePassive, NULL); if (client == NULL) { os_log_error (OS_LOG_DEFAULT, "Failed to create event system client"); return kIOReturnError; } services = (CFArrayRef) IOHIDEventSystemClientCopyServices (client); if (services == NULL || CFArrayGetCount(services) == 0) { err = kIOReturnNoDevice; goto exit; } for (CFIndex index = 0; index < CFArrayGetCount(services); index++) { IOHIDServiceClientRef service = (IOHIDServiceClientRef) CFArrayGetValueAtIndex(services, index); if (service && IOHIDServiceClientConformsTo (service, kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard)) { CFStringRef key = (selector == kIOHIDCapsLockState) ? CFSTR(kIOHIDServiceCapsLockStateKey) : CFSTR(kIOHIDServiceNumLockStateKey); CFBooleanRef modifierStateProp = (CFBooleanRef)IOHIDServiceClientCopyProperty(service, key); if (modifierStateProp) { modifierState = CFBooleanGetValue(modifierStateProp); if (modifierState) { break; } CFRelease(modifierStateProp); } } } exit: *state = modifierState; if (services) { CFRelease(services); } if (client) { CFRelease(client); } return err; }
static void runClient() { IOHIDEventSystemClientRef eventSystem = IOHIDEventSystemClientCreateWithType(kCFAllocatorDefault, __clientType, NULL); require_action(eventSystem, exit, printf("Unable to create client")); require_action(!__dispatchOnly, exit, dispatchClientEvents(eventSystem, __dispatchEventMask)); if ( __dispatchEventMask ) { pthread_attr_t attr; pthread_t tid; assert(!pthread_attr_init(&attr)); assert(!pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE)); assert(!pthread_create(&tid, &attr, &dispatchClientThread, eventSystem)); assert(!pthread_attr_destroy(&attr)); } IOHIDEventSystemClientScheduleWithRunLoop(eventSystem, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); IOHIDEventSystemClientRegisterEventCallback(eventSystem, (IOHIDEventCallback)eventCallback, NULL, NULL); IOHIDEventSystemClientRegisterDeviceMatchingCallback(eventSystem, serviceClientCallback, NULL, (void*)kServiceAdded); CFArrayRef services = IOHIDEventSystemClientCopyServices(eventSystem); if ( services ) { CFIndex index, count; for(index=0, count = CFArrayGetCount(services); index<count; index++) serviceClientCallback(NULL, (void*)kServiceAdded, (IOHIDServiceClientRef)CFArrayGetValueAtIndex(services, index)); CFRelease(services); } CFRunLoopRun(); exit: if ( eventSystem ) CFRelease(eventSystem); }