2012-03-29 2 views
2

Я сделал простое приложение, которое показывает подключенные джойстики и нажатые кнопки/ось для mac красиво. Поскольку я пока еще не очень хорошо знаком с какао, я создал пользовательский интерфейс, используя веб-просмотр, и использовал библиотеку джойстиков SDL. Все работает хорошо, единственная проблема заключается в том, что пользователю hte требуется сканировать новые джойстики вручную, если он/она подключает/отключает что-то во время работы программы.Как узнать, когда подключено устройство HID USB/Bluetooth в какао?

Как я могу получить простой вызов, когда устройство HID или, наконец, подключено или отключено какое-либо устройство USB/Bluetooth? Так что я могу просто вызвать функцию сканирования. Я не хочу, чтобы обрабатывать устройство или сделать что-то фантазии, просто знаю, когда есть что-то новое происходит ...

Благодаря

ответ

6

Взгляните на IOServiceAddMatchingNotification() и связанных с ними функций. Я работал с ним только в контексте последовательных портов (которые на самом деле являются USB-последовательными адаптерами, хотя это и не имеет значения), но оно должно быть применимо к любому доступному устройству IOKit. Я не уверен в отношении Bluetooth, но он должен по крайней мере работать на устройствах 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

+0

Извините. Я копирую/вставляю этот код непосредственно из существующего проекта. Я не имел в виду, чтобы это было полным решением, просто пример того, как получать уведомления. Во всяком случае, я обновил код в своем ответе, включив в него создание уведомлений и планирование его на runloop. Имейте в виду, что этот код относится к уведомлениям о портах RS-232. Это должно быть примером, но его нужно будет изменить для вашего приложения. –

+0

Спасибо, Андрей. Я изменил IOServiceMatching на kIOHIDDeviceKey и удалил строку CFDictionaryAddValue, и она сработала. Но только один раз. После этого мне нужно снова зарегистрироваться для уведомления, это правильно? – Rodrigo

2

Используйте IOHIDManager для получения уведомлений.

0

Основываясь на более ранних ответах от Andrew and Arjuna, я получил следующий фрагмент, используя IOHIDManager, который должен работать с устройством Apple HID (например, тестировался трекпад bluetooth). Похоже, что он также отправляет уведомления не один раз, не требуя ничего.

- (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"); 
} 
Смежные вопросы