2012-06-01 10 views
7

Ich schreibe ein Foundation-Tool für Mac und versuche zu erkennen, wenn Apple-Geräte über USB angeschlossen und getrennt werden. Ich fand Hilfe in this post zusammen mit der USBPrivateDataSample - aber es scheint nur zu funktionieren, wenn ich sowohl eine Hersteller-ID und eine Produkt-ID. Ich möchte die Produkt-ID beseitigen und finde alle USB-Ereignisse auf Apple-Geräten (Hersteller-ID 1452). Irgendwelche Hilfe hier?Cocoa: Erkennen von USB-Geräten nach Hersteller-ID

Hier ist mein Code, der alle Geräte nicht zu erkennen scheint:

#include <CoreFoundation/CoreFoundation.h> 

#include <IOKit/IOKitLib.h> 
#include <IOKit/IOMessage.h> 
#include <IOKit/IOCFPlugIn.h> 
#include <IOKit/usb/IOUSBLib.h> 

#define kMyVendorID 1452 

int list_devices(void); 

int list_devices(void){ 
    CFMutableDictionaryRef matchingDict; 
    io_iterator_t iter; 
    kern_return_t kr; 
    io_service_t device; 
    CFNumberRef numberRef; 
    long usbVendor = kMyVendorID; 

    /* set up a matching dictionary for the class */ 
    matchingDict = IOServiceMatching(kIOUSBDeviceClassName); // Interested in instances of class 
    // IOUSBDevice and its subclasses 
    if (matchingDict == NULL) { 
     fprintf(stderr, "IOServiceMatching returned NULL.\n"); 
     return -1; 
    } 

    // We are interested in all USB devices (as opposed to USB interfaces). The Common Class Specification 
    // tells us that we need to specify the idVendor, idProduct, and bcdDevice fields, or, if we're not interested 
    // in particular bcdDevices, just the idVendor and idProduct. Note that if we were trying to match an 
    // IOUSBInterface, we would need to set more values in the matching dictionary (e.g. idVendor, idProduct, 
    // bInterfaceNumber and bConfigurationValue. 

    // Create a CFNumber for the idVendor and set the value in the dictionary 
    numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbVendor); 
    CFDictionarySetValue(matchingDict, 
         CFSTR(kUSBVendorID), 
         numberRef); 
    CFRelease(numberRef); 
    numberRef = NULL;  


    /* Now we have a dictionary, get an iterator.*/ 
    kr = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, &iter); 
    if (kr != KERN_SUCCESS) 
     return -1; 

    /* iterate */ 
    while ((device = IOIteratorNext(iter))) 
    { 
     io_name_t  deviceName; 
     CFStringRef  deviceNameAsCFString; 

     /* do something with device, eg. check properties */ 
     /* ... */ 
     /* And free the reference taken before continuing to the next item */ 

     // Get the USB device's name. 
     kr = IORegistryEntryGetName(device, deviceName); 
     if (KERN_SUCCESS != kr) { 
      deviceName[0] = '\0'; 
     } 

     deviceNameAsCFString = CFStringCreateWithCString(kCFAllocatorDefault, deviceName, 
                 kCFStringEncodingASCII); 

     // Dump our data to stderr just to see what it looks like. 
     fprintf(stderr, "deviceName: "); 
     CFShow(deviceNameAsCFString); 

     IOObjectRelease(device); 
    } 

    /* Done, release the iterator */ 
    IOObjectRelease(iter); 

    return 1; 
} 

int main(int argc, char* argv[]) 
{ 
    while(1){ 
     list_devices(); 
     sleep(1); 
    } 
    return 0; 
} 

Bemerkenswert: Wenn ich ein Produkt-ID an den matchingDict und stecken in einem solchen Gerät hinzufügen wird es das Gerät kein Problem finden (ohne die Hersteller-ID zu ändern). Aber ich kann es nicht mit der Verkäufer-ID allein finden.

+0

Ich bin mir nicht bewusst, eine Möglichkeit, diese Geräte für USB zu tun. Mit PCI-Geräten können Sie mit IOKit eine bitweise Maske für Ihre Lieferanten- und Produkt-IDs erstellen, was bei USB jedoch nicht der Fall ist. – pmdj

Antwort

4

Zur Liste aller Produkte zu erhalten, die zu bestimmten Lieferanten gehört Sie Platzhalter in Produkt-ID-Feld .Eine Probe Anpassungsbedingung ist, wie unten verwenden:

  long vid = 1452; //Apple vendor ID 
     CFNumberRef refVendorId = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &vid); 
     CFDictionarySetValue (matchingDict, CFSTR ("idVendor"), refVendorId); 
     CFRelease(refVendorId); 
     //all product by same vendor 
     CFDictionarySetValue (matchingDict, CFSTR ("idProduct"), CFSTR("*")); 
+3

+1, möchte ich auch Apples [Tipps auf USB-Treiber-Abgleich] (http://developer.apple.com/library/mac/#qa/qa1076/_index.html) Seite, die eine Beschreibung enthält Wie funktionieren die Matching-Regeln? Dies umfasst Informationen zur Verwendung von Platzhaltern und Masken. – Hasturkun

1

Erstellen eines Wörterbuch-Filter mit nur einem VID Eintrag sollte übereinstimmen Alle PIDs für diesen Anbieter. Ich würde empfehlen, sich für Callbacks zur Geräteeinfügung zu registrieren, anstatt in Ihrem eigenen Code zu pollen. Lassen Sie das Betriebssystem die Erkennung behandeln und benachrichtigen Sie Ihre App asynchron.

Dieser Code funktioniert für mich:

#import "IOKit/hid/IOHIDManager.h" 
#include <IOKit/usb/IOUSBLib.h> 

@implementation MyApp 

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { 

    IOHIDManagerRef HIDManager = IOHIDManagerCreate(kCFAllocatorDefault, 
                kIOHIDOptionsTypeNone); 
    CFMutableDictionaryRef matchDict = CFDictionaryCreateMutable(
                kCFAllocatorDefault, 
                2, 
                &kCFTypeDictionaryKeyCallBacks, 
                &kCFTypeDictionaryValueCallBacks); 
    int vid = 0x1234; // ToDo: Place your VID here 
    CFNumberRef vid_num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &vid); 
    CFDictionarySetValue(matchDict, CFSTR(kUSBVendorID), vid_num); 
    CFRelease(vid_num); 

    IOHIDManagerSetDeviceMatching(HIDManager, matchDict); 
    // Here we use the same callback for insertion & removal. 
    // Use separate handlers if desired. 
    IOHIDManagerRegisterDeviceMatchingCallback(HIDManager, Handle_UsbDetectionCallback, (__bridge void*)self); 
    IOHIDManagerRegisterDeviceRemovalCallback(HIDManager, Handle_UsbDetectionCallback, (__bridge void*)self); 
    IOHIDManagerScheduleWithRunLoop(HIDManager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); 
    IOHIDManagerOpen(HIDManager, kIOHIDOptionsTypeNone); 
} 

// New USB device specified in the matching dictionary has been added (callback function) 
static void Handle_UsbDetectionCallback(void *inContext, IOReturn inResult, void *inSender, IOHIDDeviceRef inIOHIDDeviceRef) { 
    //ToDo: Code for dealing with the USB device 
} 

@end