Cocoa: Discovery of USB Devices by Vendor ID

I am writing a Foundation tool for Mac and trying to detect when Apple devices are connected and disconnected via USB. I found some help with this post along with USBPrivateDataSample - but it only works if I provide the vendor id and product id. I would like to remove the product ID and find all USB events on Apple devices (seller ID 1452). Any help here?

Here is my code that does not seem to detect any devices:

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

Note. If I add the product identifier to matchDict and connect it to the device, it will not detect a problem with the device (without changing the vendor ID). But I can not find it only with the provider ID.

+7
source share
2 answers

To get a list of all products owned by a particular vendor, you can use wildcards in the product identifier field. Sample matching condition:

  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("*")); 
+4
source

Creating a dictionary filter with only a VID entry must match all PIDs for this provider. I would recommend registering for device input callbacks instead of polling in your own code. Let the OS handle detection and notify your application asynchronously.

This code works for 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 
+1
source

All Articles