2012-03-29 72 views
2

我做了一個簡單的應用程序,以相當的方式顯示連接的遊戲杆和按下的按鈕/軸。由於我對可可還不是很熟悉,我使用webview製作了UI,並使用了SDL Joystick庫。 一切工作正常,唯一的問題是,如果用戶在程序運行時連接/斷開連接,hte用戶需要手動掃描新的遊戲杆。如何知道何時在Cocoa中連接HID USB /藍牙設備?

如何在HID設備或最後連接/斷開任何USB /藍牙設備時獲得簡單回撥?所以我可以調用掃描功能。我不想處理設備或者做了什麼特別的,只是知道什麼時候有新的東西發生...

感謝

回答

6

IOServiceAddMatchingNotification()和相關功能看看。我只在串行端口的環境下工作過(實際上USB到串行適配器,儘管這並不重要),但它應該適用於任何IOKit可訪問的設備。我不確定藍牙,但它至少應該適用於USB設備。下面是一個代碼片段我用:

IONotificationPortRef notificationPort = IONotificationPortCreate(kIOMasterPortDefault); 
CFRunLoopAddSource(CFRunLoopGetCurrent(), 
       IONotificationPortGetRunLoopSource(notificationPort), 
       kCFRunLoopDefaultMode); 

CFMutableDictionaryRef matchingDict = IOServiceMatching(kIOSerialBSDServiceValue); 
CFRetain(matchingDict); // Need to use it twice and IOServiceAddMatchingNotification() consumes a reference 

CFDictionaryAddValue(matchingDict, CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDRS232Type)); 

io_iterator_t portIterator = 0; 
// Register for notifications when a serial port is added to the system 
kern_return_t result = IOServiceAddMatchingNotification(notificationPort, 
                 kIOPublishNotification, 
                 matchingDictort, 
                 SerialDeviceWasAddedFunction, 
                 self,   
                 &portIterator); 
while (IOIteratorNext(portIterator)) {}; // Run out the iterator or notifications won't start (you can also use it to iterate the available devices). 

// Also register for removal notifications 
IONotificationPortRef terminationNotificationPort = IONotificationPortCreate(kIOMasterPortDefault); 
CFRunLoopAddSource(CFRunLoopGetCurrent(), 
        IONotificationPortGetRunLoopSource(terminationNotificationPort), 
        kCFRunLoopDefaultMode); 
result = IOServiceAddMatchingNotification(terminationNotificationPort, 
              kIOTerminatedNotification, 
              matchingDict, 
              SerialPortWasRemovedFunction, 
              self,   // refCon/contextInfo 
              &portIterator); 

while (IOIteratorNext(portIterator)) {}; // Run out the iterator or notifications won't start (you can also use it to iterate the available devices). 

SerialPortDeviceWasAddedFunction()SerialPortWasRemovedFunction()當串口分別變爲可用的系統,或者被刪除,被調用。

相關文件is here,特別是標題Getting Notifications of Device Arrival and Departure

+0

嗯...... 我試圖用你的代碼,同時創建回調函數,增加了一些由於IOKit頭...... 但它有一個未定義的引用「 notificationPort「,我錯過了什麼? – Rodrigo 2012-04-06 01:37:13

+0

對不起。我直接從現有項目中複製/粘貼此代碼。我不是說它是一個完整的解決方案,只是一個如何獲得通知的例子。無論如何,我已經更新了我的答案中的代碼,包括創建notificationPort並將其安排在runloop上。請記住,此代碼特定於RS-232端口的通知。它只是一個例子,但需要針對您的應用程序進行修改。 – 2012-04-06 01:44:08

+0

謝謝安德魯。我將IOServiceMatching更改爲kIOHIDDeviceKey,並刪除了CFDictionaryAddValue行,它工作。但只有一次。之後,我需要再次註冊通知,這是正確的? – Rodrigo 2012-04-06 03:46:20

2

使用IOHIDManager獲取通知。

0

基於從安德魯和Arjuna早期的答案,我結束了使用IOHIDManager下面的片段應該與蘋果的HID設備(如藍牙觸控板進行了測試)工作。這似乎也發送通知不止一次而不需要清除/減少任何東西。

- (void) startHIDNotification 
{ 
ioHIDManager = IOHIDManagerCreate (kCFAllocatorDefault, kIOHIDManagerOptionNone ); 

CFMutableDictionaryRef matchingDict = IOServiceMatching(kIOHIDDeviceKey); 
CFDictionaryAddValue(matchingDict, CFSTR(kIOHIDManufacturerKey), CFSTR("Apple")); 

IOHIDManagerSetDeviceMatching (ioHIDManager, matchingDict); 

IOHIDManagerRegisterDeviceMatchingCallback(ioHIDManager, AppleHIDDeviceWasAddedFunction, (__bridge void *)(self)); 
IOHIDManagerRegisterDeviceRemovalCallback(ioHIDManager, AppleHIDDeviceWasRemovedFunction, (__bridge void *)(self)); 

hidNotificationRunLoop = CFRunLoopGetCurrent(); 

IOHIDManagerScheduleWithRunLoop(ioHIDManager, 
           hidNotificationRunLoop, 
           kCFRunLoopDefaultMode); 
} 

和回調方法

void AppleHIDDeviceWasAddedFunction(void *     context, 
          IOReturn    result, 
          void *     sender, 
          IOHIDDeviceRef   device) 
{ 
    NSLog(@"added"); 
} 

void AppleHIDDeviceWasRemovedFunction(void *     context, 
          IOReturn    result, 
          void *     sender, 
          IOHIDDeviceRef   device) 
{ 
    NSLog(@"removed"); 
} 
相關問題