2012-06-01 11 views
7

Sto scrivendo uno strumento Foundation per Mac e sto provando a rilevare quando i dispositivi Apple sono collegati e scollegati tramite USB. Ho trovato aiuto nello insieme allo USBPrivateDataSample, ma sembra che funzioni solo se fornisco sia un ID del fornitore che un ID del prodotto. Vorrei eliminare l'ID prodotto e trovare rilevare tutti gli eventi USB sui dispositivi Apple (ID fornitore 1452). Qualche aiuto qui?Cacao: rilevamento di dispositivi USB per ID fornitore

Ecco il mio codice che non sembra per rilevare tutti i dispositivi:

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

Da notare: Se posso aggiungere un ID prodotto al matchingDict e collegare un dispositivo del genere troverà il dispositivo non è un problema (senza modificare l'ID del fornitore). Ma non riesco a trovarlo con l'ID del venditore da solo.

+0

Io non sono a conoscenza di un modo di fare questo per i dispositivi USB. Con i dispositivi PCI, IOKit consente di fornire una maschera bit per bit con il fornitore e gli ID prodotto, ma questo non sembra essere il caso dell'USB. – pmdj

risposta

4

ottenere l'elenco di tutti i prodotti che appartengono a particolari vendor è possibile utilizzare i caratteri jolly in product ID campo .A condizione di accordo di esempio è il seguente:

  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, vorrei anche prendere nota della pagina [Suggerimenti per la corrispondenza dei driver USB] (http://developer.apple.com/library/mac/#qa/qa1076/_index.html), che contiene una descrizione di come funzionano le regole di corrispondenza. Questo include informazioni sull'uso di caratteri jolly e maschere. – Hasturkun

1

Creazione di un filtro dizionario con solo una voce VID deve corrispondere tutti i PID per quel fornitore. Ti consigliamo di registrarti per le callback di inserimento del dispositivo anziché il polling nel tuo codice. Lascia che il SO gestisca il rilevamento e notifica la tua app in modo asincrono.

Questo codice funziona per me:

#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