2012-03-29 77 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"); 
}