prazuber
prazuber

Reputation: 1362

USB interface of an AVCaptureDevice

If I have an AVCaptureDevice, how can I get the related USB interface so I can access the underlying hardware via IOKit?

I've tried finding it via vid & pid, but this won't work if I plug in two devices with the same vid, pid. Here's the code I use to extract vid and pid from AVCaptureDevice:

AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithDeviceType:AVMediaTypeVideo];
NSString *modelID = [device modelID];

NSRange vidRange = [modelID rangeOfString:@"VendorID_"];
int vid = [[modelID substringWithRange:NSMakeRange(vidRange.location + 9, 5)] intValue];

NSRange pidRange = [modelID rangeOfString:@"ProductID_"];
int vid = [[modelID substringWithRange:NSMakeRange(pidRange.location + 10, 5)] intValue];

And then I search for a matching IOService:

CFMutableDictionaryRef matchingDict = IOServiceMatching(kIOUSBDeviceClassName);
CFNumberRef numberRef;

numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vid);
CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID), numberRef);
CFRelease(numberRef);

numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &pid);
CFDictionarySetValue(matchingDict, CFSTR(kUSBProductID), numberRef);
CFRelease(numberRef);

io_service_t camera = IOServiceGetMatchingService(kIOMasterPortDefault, matchingDict);

Upvotes: 2

Views: 1175

Answers (2)

Mark Coniglio
Mark Coniglio

Reputation: 391

In the case of video devices, the AVCaptureDevice uniqueID seems to a string in the form "0xLLLLLLLLVVVVPPPP", where:

  • LLLLLLLL is the hexadecimal string representing the USB device's location ID
  • VVVV is the hexadecimal string representing the USB device's manufacturer ID
  • PPPP is the hexadecimal string representing the USB device's product ID.

e.g. 0x144000002E1A4C01

(This not documented anywhere by Apple; what I'm saying above is completely by inference, which is why I say "seems to be".)

These three values should correspond to the values returned when interrogating an io_service_t

CFNumberRef vendorIdObj = IORegistryEntrySearchCFProperty(ioService, kIOUSBPlane, CFSTR(kUSBVendorID), kCFAllocatorDefault, 0);
CFNumberRef productIdObj = IORegistryEntrySearchCFProperty(ioService, kIOUSBPlane, CFSTR(kUSBProductID), kCFAllocatorDefault, 0);
CFNumberRef locationIdObj = IORegistryEntrySearchCFProperty(ioService, kIOUSBPlane, CFSTR(kUSBDevicePropertyLocationID), kCFAllocatorDefault, 0);

By decoding the uniqueID string into its three components, you should be able to then compare them to the values returned by the IORegistryEntrySearchCFProperty functions above, allowing you to get the USB Interface for the AVCaptureDevice.

Upvotes: 0

Gordon Childs
Gordon Childs

Reputation: 36072

Maybe a combination of AVCaptureDevice modelID and uniqueID could help you find the matching IOService. The formatting of the two IDs looks to be both undocumented and dependent on transport and media-type, but you should be able to figure something out. Here is a tentative mapping for USB audio (because I don't have any USB cameras), based on two devices:

modelID: USB Headphone Set:0C76:1607
uniqueID: AppleUSBAudioEngine:Unknown Manufacturer:USB Headphone Set:14200000:2,1,
    USB Headphone Set:

    Product ID: 0x1607
    Vendor ID:  0x0c76  (Solid State System Co., Ltd.)
Version:    1.00
Speed:  Up to 12 Mb/sec
    Location ID:    0x14200000 / 9
    Current Available (mA): 1000
    Current Required (mA):  100
    Extra Operating Current (mA):   0


uniqueID: AppleUSBAudioEngine:Burr-Brown from TI              :USB Audio CODEC :14200000:2,
modelID: USB Audio CODEC :08BB:2902
    USB Audio CODEC :

    Product ID: 0x2902
    Vendor ID:  0x08bb  (Texas Instruments Japan)
Version:    1.00
Speed:  Up to 12 Mb/sec
Manufacturer:   Burr-Brown from TI
    Location ID:    0x14200000 / 10
    Current Available (mA): 1000
    Current Required (mA):  100
    Extra Operating Current (mA):   0

The (usb audio) format is something like

modelID: name:vendorID:productID
uniqueID: AppleUSBAudioEngine:Manufacturer or Unknown Manufacturer:location ID:???

If USB video's uniqueID is similar, then the combination of productID, vendorID and locationID (which USB port) should be enough to uniquely identify the underlying device's hardware, albeit in a fragile and undocumented way.

Upvotes: 1

Related Questions