1

使用 IOKit,我已经弄清楚了如何获取挂载点的 BSD 设备名称,但后来我无法弄清楚如何获取具有该名称的 USB 设备。

我发现我可以像这样枚举设备(如果代码看起来很奇怪,那是因为它是 Java):

int kr;
IOKit ioKit = IOKit.INSTANCE;
CoreFoundation coreFoundation = CoreFoundation.INSTANCE;

CFDictionary.CFMutableDictionaryRef matchingDict =
    ioKit.IOServiceMatching(IOUSBLib.kIOUSBDeviceClassName);
if (matchingDict == null)
{
    logger.error("Couldn't create a USB matching dictionary");
    return null;
}

PointerByReference iterator = new PointerByReference();
kr = ioKit.IOServiceGetMatchingServices(null, matchingDict, iterator);
if (kr != IOReturn.kIOReturnSuccess)
{
    logger.error(String.format("Couldn't enumerate devices: %08x", kr));
    return null;
}

while (true)
{
    Pointer device = ioKit.IOIteratorNext(iterator.getValue()); // returns an io_object_t
    if (device == null)
    {
        break; // end of the iterator.
    }

    // do stuff with the device here

    kr = ioKit.IOObjectRelease(usbRef);
    if (kr != IOReturn.kIOReturnSuccess)
    {
        logger.warn(String.format("Couldn't release device object: %08x", kr));
    }
}

这会返回很多设备,但它们似乎都没有 BSD Name 属性或任何类似的东西。但是我想要的设备退回了。如果我查看 System Profiler,我确实看到了我所针对的设备,并且 BSD 名称确实出现在其中。

他们是如何得到它的?

或者,有什么方法可以绕过循环这些东西,直接从 BSD 设备到 USB 设备?

4

1 回答 1

2

我认为您可能需要解析 IO 注册表。这可以使用 IOKit API(例如,通过枚举 USB 设备,然后使用 IORegistryEntryGetChildIterator())或通过解析“ioreg”控制台命令的输出来完成。

您需要查看“IOService”注册表平面。一种方法是迭代 IOUSBDevice 类的所有实例(它将提供 USB 标识符),然后解析子对象,直到找到描述设备安装点的 IOMedia 对象。或者,您可以找到所有 IOMedia 对象,然后向上迭代以找到具有所需 IOUSBDevice 的对象。

层次结构很深 - 在我的机器上:

IOUSBDevice:IOUSBInterface:IOUSBInterface:IOSCSIDevicePeripheralDeviceNub:IOSCSIPeripheralDeviceType00:IOBlockStorageServices:IOBlockStorageDriver:IOMedia

(并且在 IOMedia 下还有 IOFDiskPartitionScheme 对象,用于描述磁盘上的各个分区)。

显示所有这些的 ioreg 命令是“ioreg -l”或“ioreg -l -a”,如果您希望以 XML 格式输出以便于解析。

于 2013-10-19T19:45:17.003 回答