在OSX系統全局監聽鍵盤的按下事件,並能夠捕獲事件源的硬件的接口位置,用於區分是哪一個鍵盤產生的事件。下面的代碼只是以鍵盤爲例子,實際上是能夠適用於其餘輸入外設的。若有須要可搜索相關外設的匹配字典的建立代碼。函數
CFMutableDictionaryRef myCreateDeviceMatchingDictionary(UInt32 usagePage, UInt32 usage ) { CFMutableDictionaryRef dict = CFDictionaryCreateMutable( kCFAllocatorDefault, 0 , & kCFTypeDictionaryKeyCallBacks , & kCFTypeDictionaryValueCallBacks ); if ( ! dict ) return NULL; CFNumberRef pageNumberRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, & usagePage ); if ( ! pageNumberRef ) { CFRelease( dict ); return NULL; } CFDictionarySetValue( dict, CFSTR(kIOHIDDeviceUsagePageKey), pageNumberRef ); CFRelease( pageNumberRef ); CFNumberRef usageNumberRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, & usage ); if ( ! usageNumberRef ) { CFRelease( dict ); return NULL; } CFDictionarySetValue( dict, CFSTR(kIOHIDDeviceUsageKey), usageNumberRef ); CFRelease( usageNumberRef ); return dict; }
void myHIDKeyboardCallback(void* context, IOReturn result, void* sender, IOHIDValueRef value ) { //get device product id and vendor id IOHIDDeviceRef device = sender; // int32_t pid = 1; // CFNumberGetValue(IOHIDDeviceGetProperty(device, CFSTR(kIOHIDVendorIDKey)), kCFNumberSInt32Type, &pid); // int32_t vendorID = 0; // CFNumberGetValue(IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductIDKey)), kCFNumberSInt32Type, &vendorID); // NSLog(@"vendor:%d product:%d", vendorID, pid); IOHIDElementRef elem = IOHIDValueGetElement( value ); // if (IOHIDElementGetUsagePage(elem) != 0x07) // return; uint32_t scancode = IOHIDElementGetUsage( elem ); if (scancode < 3 || scancode > 231) return; int32_t locationID = 0; CFNumberGetValue(IOHIDDeviceGetProperty(device, CFSTR(kIOHIDLocationIDKey)), kCFNumberSInt32Type, &locationID); NSLog(@"location:%d", locationID); long pressed = IOHIDValueGetIntegerValue( value ); uint64_t timestamp = IOHIDValueGetTimeStamp(value); printf( "scancode: %3d, %s timestamp:%llu \n", scancode, pressed?"keydown":"keyup ", timestamp); //send the keyboard event NSDictionary* userInfo = [[NSDictionary alloc]initWithObjectsAndKeys: [NSNumber numberWithInt:scancode], NOTIFICATION_KEY_ScanCode, [NSNumber numberWithInt:locationID], NOTIFICATION_KEY_Location, [NSNumber numberWithLong:pressed], NOTIFICATION_KEY_IsKeyDown, [NSNumber numberWithLong:timestamp], NOTIFICATION_KEY_Timestamp, nil]; NSNotification* notification = [NSNotification notificationWithName:NOTIFICATION_KeyBoardEvent object:nil userInfo:userInfo]; [[NSNotificationCenter defaultCenter] postNotification:notification]; UsbSignalController* controller = (__bridge UsbSignalController*)context; [controller onKeyEvent:scancode Location:locationID IsDown:pressed Timestamp:timestamp]; }
-(void)registerKeyboardHook { IOHIDManagerRef hidManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone ); CFMutableDictionaryRef keyboard = myCreateDeviceMatchingDictionary( 0x01, 6 ); CFArrayRef matches; { //CFMutableDictionaryRef keypad = myCreateDeviceMatchingDictionary( 0x01, 7 ); CFMutableDictionaryRef matchesList[] = { keyboard/*, keypad*/ }; matches = CFArrayCreate( kCFAllocatorDefault, (const void **)matchesList, 1/*2*/, NULL ); } IOHIDManagerSetDeviceMatchingMultiple(hidManager, matches ); CFRelease(matches); CFRelease(keyboard ); IOHIDManagerRegisterInputValueCallback(hidManager, myHIDKeyboardCallback, (__bridge void*)self); IOHIDManagerScheduleWithRunLoop(hidManager, CFRunLoopGetMain(), kCFRunLoopDefaultMode ); IOHIDManagerOpen(hidManager, kIOHIDOptionsTypeNone ); }