2012-03-29 9 views
2

Ich habe eine einfache App gemacht, die die angeschlossenen Joysticks und die gedrückten Tasten/Achsen für Mac in einer schönen Weise zeigt. Da ich mit Kakao noch nicht sehr vertraut bin, habe ich die Benutzeroberfläche mit einem Webview erstellt und die SDL Joystick-Bibliothek verwendet. Alles funktioniert gut, das einzige Problem ist, dass der Benutzer manuell nach neuen Joysticks suchen muss, wenn er etwas verbindet/trennt, während das Programm läuft.Wie kann man wissen, wann ein HID USB/Bluetooth-Gerät in Cocoa angeschlossen ist?

Wie kann ich einen einfachen Rückruf erhalten, wenn ein HID Gerät oder zuletzt ein USB/Bluetooth Gerät angeschlossen/getrennt wird? So kann ich nur die Scan-Funktion aufrufen. Ich möchte nicht, das Gerät zu handhaben oder etwas Phantasie, weiß nur, wenn es etwas Neues passiert ist ...

Dank

Antwort

6

Werfen Sie einen Blick auf IOServiceAddMatchingNotification() und verwandte Funktionen. Ich habe damit nur im Zusammenhang mit seriellen Ports gearbeitet (die zwar USB-zu-Seriell-Adapter sind, obwohl das egal ist), aber es sollte für jedes IOKit-zugängliche Gerät anwendbar sein. Ich bin mir nicht sicher über Bluetooth, aber es sollte zumindest für USB-Geräte funktionieren. Hier ist ein Ausschnitt von Code, den ich verwenden:

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). 

Meine SerialPortDeviceWasAddedFunction() und SerialPortWasRemovedFunction() werden aufgerufen, wenn eine serielle Schnittstelle auf dem System verfügbar ist oder entfernt wird, respectively.

Relevante Dokumentation is here, insbesondere unter der Überschrift Getting Notifications of Device Arrival and Departure.

+0

Hmm ... Ich habe versucht, den Code zu verwenden, beide Callback-Funktionen erstellt, fügte einige IOKit Header ... Aber es wurde eine nicht definierte Verweis auf " notificationPort ", fehlt mir etwas? – Rodrigo

+0

Entschuldigung. Ich kopiere diesen Code direkt aus einem bestehenden Projekt. Ich wollte damit nicht sagen, dass es sich um eine Komplettlösung handelt, nur ein Beispiel dafür, wie man Benachrichtigungen erhält. Wie auch immer, ich habe den Code in meiner Antwort aktualisiert, um die Erstellung von notificationPort zusammen mit der Planung auf dem Runloop einzuschließen. Beachten Sie, dass dieser Code speziell für Benachrichtigungen für RS-232-Ports gilt. Es soll ein Beispiel sein, muss aber für Ihre Anwendung modifiziert werden. –

+0

Danke Andrew. Ich habe IOServiceMatching in kIOHIDDeviceKey geändert und die Zeile CFDictionaryAddValue entfernt und es hat funktioniert. Aber nur einmal. Danach muss ich mich erneut für die Benachrichtigung registrieren, das ist richtig? – Rodrigo

2

Verwenden Sie IOHIDManager, um die Benachrichtigungen zu erhalten.

0

Basierend auf den früheren Antworten von Andrew und Arjuna, endete ich mit dem folgenden Ausschnitt mit IOHIDManager, der mit einem Apple HID-Gerät funktionieren sollte (z. B. wurde ein Bluetooth-Trackpad getestet). Dies scheint auch Benachrichtigungen mehr als einmal zu senden, ohne etwas zu löschen oder zu dekrementieren.

- (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); 
} 

und die Callback-Methoden

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

void AppleHIDDeviceWasRemovedFunction(void *     context, 
          IOReturn    result, 
          void *     sender, 
          IOHIDDeviceRef   device) 
{ 
    NSLog(@"removed"); 
} 
Verwandte Themen