【问题标题】:Finding the USB VID/PID associated with a CoreAudio device on OSX在 OSX 上查找与 CoreAudio 设备关联的 USB VID/PID
【发布时间】:2023-03-31 20:38:01
【问题描述】:

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

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

【问题讨论】:

  • AppleUSBAudioDevice 驱动程序的源代码曾经是公开的,现在仍然在互联网上的某个地方流传,您应该可以在那里获得该信息。

标签: macos usb core-audio iokit


【解决方案1】:

我发现以下post from an Apple CoreAudio engineer 描述了如何从AudioDeviceID 获取IOUSBDeviceInterface

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

  1. 从 HAL 中获取设备的 UID 字符串
  2. 制作一个匹配的字典来搜索 IOAudioEngine 对象
  3. 遍历匹配服务,直到找到 UID 属性与您从 HAL 获得的内容匹配的服务
  4. 从此处遍历 IORegistry 以找到您要查找的 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);
}

【讨论】:

  • 我很确定 vidpid 不会是 NSStrings 而是 NSNumber。我还会在CFEqual 调用之前进行NULL 检查,否则如果对象上缺少kIOAudioEngineGlobalUniqueIDKey,您将面临崩溃的风险。其余代码乍一看相当可靠。
  • 非常好,谢谢。我在示例代码中修复了这些问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多