Как получить дескриптор USB-устройства, выполнив DeviceIoControl() непосредственно на устройстве?

Я хочу получить дескриптор устройства USB-устройств в моей системе. Я создаю приложение пользовательского пространства в Windows (неуправляемый, собственный С++). Из этих дескрипторов я хочу идентифицировать рекламные щиты и проанализировать дескриптор возможностей рекламного щита (анализ дескриптора bos).

Вот мой подход.

  1. Получите USB-устройства в системе с помощью SetupDiGetClassDevs(&GUID_CLASS_USB_DEVICE,...)
  2. Получите путь к каждому устройству, используя SetupDiGetDeviceInterfaceDetail()
  3. Используйте CreateFile() в пути к устройству, чтобы получить дескриптор устройства.
  4. Выполните IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION IOCTL, используя DeviceIoControl() и дескриптор, чтобы получить дескриптор устройства.

Я застрял на 4-м шаге (getLastError() - Invalid Function).
Другие проекты (подобно этому примеру кода от Intel), перечислите все USB-контроллеры в системе, корневые концентраторы, порты и интерфейсы и выдайте IOCTL на дескриптор корневого концентратора, указывающий номер порта, к которому подключено устройство.

Я не хочу беспокоиться об иерархии USB в системе. Это менее подвержено ошибкам и проще получить USB-устройства в системе с помощью API установки. Однако нигде я не вижу, чтобы IOCTL выдавался им напрямую.

Обновление1

Из docs.microsoft.com:
IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION Запрос управления вводом-выводом извлекает один или несколько дескрипторов для устройства, связанного с указанным индексом порта. Этот запрос нацелен на USB-концентратор (GUID_DEVINTERFACE_USB_HUB). Таким образом, этот ioctl, который может дать мне дескриптор USB-устройства, предназначен для обработки USB-концентратором, а НЕ USB-устройством.

Поэтому другие решения передают дескриптор концентратора в DeviceIoControl(), как видно на Строка 68 исходного кода от Intel (Linked здесь).

Вместо этого я хочу использовать дескриптор, полученный на шаге 3 (дескриптор устройства) выше, чтобы получить дескриптор устройства. Таким образом, IOCTL может быть другим, или, возможно, есть способ получить дескриптор концентратора и индекс порта, к которому подключено устройство, используя дескриптор USB-устройства.

На мой взгляд, дескриптор устройства является неотъемлемым свойством USB-устройства, и поэтому должен быть способ получить его непосредственно с USB-устройства.


person Sahil Singh    schedule 05.06.2018    source источник
comment
Должен быть способ сделать это, потому что утилита USBView от Microsoft показывает все дескрипторы USB-устройств. Это с открытым исходным кодом, поэтому вы можете просмотреть его исходный код. код, и вы можете попробовать пакет MSYS2 для него (pacman -S mingw-w64-x86_64-usbview в MSYS2).   -  person David Grayson    schedule 05.06.2018
comment
Я видел исходный код утилиты USBView, она тоже перечисляет все хабы, контроллеры, порты и т.д.   -  person Sahil Singh    schedule 05.06.2018
comment
Тем не менее, вы должны иметь возможность посмотреть на отдельные его части, использующие IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, и убедиться, что вы делаете то же самое.   -  person David Grayson    schedule 05.06.2018
comment
В любом случае, кому-либо будет очень сложно отлаживать ваш код, не видя его в виде минимально воспроизводимого примера, поэтому лучшее, что я могу сделать, это указать на работающий пример кода во вселенной и предложить вам скопировать его.   -  person David Grayson    schedule 05.06.2018
comment
Что именно в 4-м шаге заставляет вас застрять? Вы должны включить полное описание всех кодов ошибок, которые вы получаете вместе с MCVE.   -  person David Grayson    schedule 05.06.2018
comment
Я получаю сообщение об ошибке Invalid Function. Обновление вопроса с более подробной информацией.   -  person Sahil Singh    schedule 05.06.2018
comment
Я обновил вопрос. Если это все еще необходимо, я попытаюсь создать минимальный, полный и проверяемый пример.   -  person Sahil Singh    schedule 05.06.2018
comment
Спасибо за обновление. Я сомневаюсь, что вы сможете найти именно то, что ищете, и вам действительно нужно будет открыть дескриптор USB-концентратора, и вы, вероятно, не сможете получить такой дескриптор из дескриптора устройства.   -  person David Grayson    schedule 05.06.2018
comment
Я нашел этот вопрос. В нем упоминаются те же проблемы, с которыми я сталкиваюсь. Я попробую решения, упомянутые там, и в случае успеха отмечу этот вопрос как дубликат. stackoverflow.com/questions/28007468/   -  person Sahil Singh    schedule 06.06.2018


Ответы (1)


Предполагая, что у вас уже есть дескриптор USB-устройства, сначала вам нужно получить от него строку свойства DEVPKEY_Device_Driver (с помощью CM_Get_DevNode_PropertyW или SetupDiGetDevicePropertyW).

Вы получите строку вида {36fc9e60-c465-11cf-8056-444553540000}\0010.

Затем вам нужно перебрать каждый USB-концентратор в системе (устройства с интерфейсом GUID_DEVINTERFACE_USB_HUB) и для каждого:

  1. Откройте его с помощью CreateFile() вызова
  2. Вызовите DeviceIoControl(hubInterfaceHandle, IOCTL_USB_GET_NODE_INFORMATION, ...), чтобы получить структуру USB_NODE_INFORMATION, содержащую количество портов USB в его hubInfo.u.HubInformation.HubDescriptor.bNumberOfPorts
  3. Для каждого порта от 1 (они основаны на одном!!!) до bNumberOfPorts вызовите DeviceIoControl(hubInterfaceHandle, IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME, ...), чтобы получить уникальное DriverKey устройство, подключенное к этому порту.
  4. Сравните строку DriverKey, полученную на предыдущем шаге, со строкой, полученной при вызове DEVPKEY_Device_Driver. Если они совпадают - поздравляем, вы нашли USB-концентратор и порт, к которым подключено ваше USB-устройство!

Теперь вы можете позвонить DeviceIoControl(usbHubInterfaceHandle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION, ...), чтобы получить USB_NODE_CONNECTION_INFORMATION структура, содержащая USB_DEVICE_DESCRIPTOR!

Также вы можете дополнительно вызвать DeviceIoControl(usbHubInterfaceHandle, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, ...) с помощью USB_DESCRIPTOR_REQUEST чтобы получить другие дескрипторы USB в дополнение к базовому USB_DEVICE_DESCRIPTOR.

Пример кода см. EnumerateHubPorts() и GetDriverKeyName() в официальном примере USBView .

Также я только что сделал это в своем репозитории RawInputDemo.

person DJm00n    schedule 14.06.2021