如何知道Cocoa中何时连接HID USB /蓝牙设备?

时间:2012-03-29 02:43:50

标签: macos cocoa bluetooth usb joystick

如何在HID设备或最后任何USB / Bluetooth设备连接/断开连接时进行简单回叫?

我制作了一个简单的应用程序,以漂亮的方式显示连接的操纵杆和按下的按钮/轴。由于我对cocoa不是很熟悉,我使用webview制作了UI,并使用了SDL Joystick库。 一切都运行良好,唯一的问题是如果用户在程序运行时连接/断开某些东西,用户需要手动扫描新的操纵杆。

通过回调,我可以调用扫描功能。我不想处理设备或做一些奇特的事情,只知道什么时候发生了新的事情......

感谢。

3 个答案:

答案 0 :(得分:7)

查看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

答案 1 :(得分:3)

使用IOHIDManager获取通知。

答案 2 :(得分:1)

基于Andrew和Arjuna的早期答案,我最终得到了以下使用IOHIDManager的片段,该片段应该与Apple 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");
}