在OSX上找到与CoreAudio设备相关的USB VID/PID



我需要确定任意CoreAduio AudioDevice与哪个物理USB设备(通过VID/PID/SerialNumber)相关。CoreAudio允许查询各种设备属性,如传输类型(在我的情况下是USB), UID(跨会话和机器的唯一)和一些配置字符串。

IOKit和CoreAudio的音频部分都有音频设备的表示,但我不清楚如何弥合两者之间的差距。(似乎我应该能够查询AudioDevice的IOAudioDevice…)

我发现了苹果CoreAudio工程师的以下帖子,描述了如何从AudioDeviceID中获得IOUSBDeviceInterface:

两者之间没有直接的映射关系。但最好的方法是是:

  1. 从HAL
  2. 获取设备的UID字符串
  3. 创建一个查找IOAudioEngine对象的匹配字典
  4. 遍历匹配服务,直到找到UID属性与您从HAL
  5. 获得的匹配的服务。
  6. 从这里走到iregistry找到您正在寻找的USB对象

代码应该是这样的:

#include <IOKit/IOKitLib.h>
#include <IOKit/audio/IOAudioDefines.h>
#include <IOKit/usb/USB.h>
AudioDeviceID deviceID = ...
// get device UID for AudioDevice ID
AudioObjectPropertyAddress address = {kAudioDevicePropertyDeviceUID, kAudioObjectPropertyScopeOutput, 0};
UInt32 size = sizeof(CFStringRef);
CFStringRef uid = NULL;
OSStatus err = AudioObjectGetPropertyData(deviceID, &address, 0, NULL, &size, &uid);
NSNumber *vid, *pid;
// find matching IOAudioEngine object
io_iterator_t it;
if (IOServiceGetMatchingServices(kIOMasterPortDefault, IOServiceMatching(kIOAudioEngineClassName), &it) == KERN_SUCCESS) {
    io_service_t service;
    while ((service = IOIteratorNext(it)) != 0) {
        CFStringRef uniqueID = IORegistryEntryCreateCFProperty(service, CFSTR(kIOAudioEngineGlobalUniqueIDKey), kCFAllocatorDefault, 0);
        if (uniqueID && CFEqual(uniqueID, uid)) {
            vid = CFBridgingRelease(IORegistryEntryCreateCFProperty(service, CFSTR(kUSBVendorID), kCFAllocatorDefault, 0));
            pid = CFBridgingRelease(IORegistryEntryCreateCFProperty(service, CFSTR(kUSBProductID), kCFAllocatorDefault, 0));
        }
        CFRelease(uniqueID);
        if (vid || pid) break;
    }
    IOObjectRelease(it);
}

最新更新