Учитывая точку монтирования, могу ли я получить значения поставщика/продукта/серийного номера USB с помощью IOKit?

Используя 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 или чего-либо похожего на него. Но устройство, которое я хочу, вернуто обратно. Если я посмотрю в System Profiler, я увижу устройство, на которое я нацелился, и там появится имя BSD.

Как они это получают?

В качестве альтернативы, есть ли способ обойти необходимость зацикливания этого материала и просто напрямую перейти с устройства BSD на устройство USB?


person Trejkaz    schedule 24.09.2013    source источник


Ответы (1)


Я думаю, что вам, вероятно, нужно разобрать реестр IO. Это можно сделать либо с помощью API-интерфейсов IOKit (например, путем перечисления USB-устройств, а затем с помощью IORegistryEntryGetChildIterator()), либо путем анализа вывода консольной команды «ioreg».

Вам нужно посмотреть в плоскости реестра «IOService». Один из подходов заключается в повторении всех экземпляров класса IOUSBDevice (который даст идентификаторы USB), а затем анализе дочерних объектов до тех пор, пока не будет найден объект IOMedia, описывающий точку подключения устройства. В качестве альтернативы вы можете найти все объекты IOMedia, а затем выполнить итерацию вверх, чтобы найти объект с требуемым IOUSBDevice.

Иерархия довольно глубокая - на моей машине:

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

(а также есть объекты IOFDiskPartitionScheme под IOMedia, которые описывают отдельные разделы на диске).

Команда ioreg для отображения всего этого — «ioreg -l» или «ioreg -l -a», если вы хотите, чтобы вывод был в формате XML для упрощения синтаксического анализа.

person Mark Moore    schedule 19.10.2013
comment
Это был бит иерархии, которого мне не хватало. В конечном итоге логика выглядит так: (1) IOBSDNameMatching для поиска блочного устройства (2) Пройдите вверх по дереву, пока не наткнетесь на устройство, где IOObjectConformsTo kIOUSBDeviceClassName (3) IORegistryEntryCreateCFProperties и вырвите всю информацию из словаря. Есть то, что выглядит как более быстрый способ получить № 3, но он требует гораздо большего количества API, и пока этот способ работает нормально. - person Trejkaz; 21.10.2013