2012-06-01 25 views
7

Piszę narzędzie Foundation dla Mac i próbuję wykryć, kiedy urządzenia Apple są podłączone i odłączone przez USB. Znalazłem pomoc w this post wraz z USBPrivateDataSample - ale wygląda na to, że działa tylko wtedy, gdy podam zarówno identyfikator dostawcy, jak i identyfikator produktu. Chciałbym wyeliminować identyfikator produktu i znaleźć wszystkie zdarzenia USB na urządzeniach Apple (identyfikator dostawcy 1452). Jakąkolwiek pomoc tutaj?Kakao: wykrywanie urządzeń USB według identyfikatora dostawcy

Oto mój kod, który nie wydaje się w celu wykrycia wszelkich urządzeń:

#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; 
} 

Of Uwaga: Jeśli mogę dodać identyfikator produktu do matchingDict i podłączyć takie urządzenie będzie odnaleźć urządzenia bez problemu (bez zmiany identyfikatora dostawcy). Ale nie mogę go znaleźć z samym identyfikatorem dostawcy.

+0

nie jestem świadomy sposób robi to dla urządzeń USB. W przypadku urządzeń PCI IOKit pozwala na dostarczenie maski bitowej z identyfikatorami dostawców i produktów, ale nie wydaje się, że dotyczy to USB. – pmdj

Odpowiedz

4

Aby uzyskać listę wszystkich produktów, które należy do określonego dostawcy można używać symboli wieloznacznych w ID produktu .A pole stanu dopasowania próbka jest jak poniżej:

  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, chciałbym również zwrócić uwagę na stronę [Porady na temat dopasowania sterownika USB] (http://developer.apple.com/library/mac/#qa/qa1076/_index.html) firmy Apple, która zawiera opis jak działają reguły dopasowania. Obejmuje to informacje na temat używania symboli wieloznacznych i masek. – Hasturkun

1

Tworzenie filtru słownika tylko z wejściem VID powinien pasować wszystkie PID dla tego dostawcy. Zalecałbym rejestrowanie wywołań zwrotnych od urządzenia zamiast odpytywania we własnym kodzie. Pozwól systemowi obsługiwać wykrywanie i powiadamiaj swoją aplikację asynchronicznie.

Ten kod działa dla mnie:

#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