Можно ли программно определить физический порт USB для устройства в Windows? - PullRequest
10 голосов
/ 21 июня 2011

У меня есть USB-устройство, которое перечисляет другой интерфейс, VID, PID и серийный номер, когда мне приказано сделать это, и я хотел бы отслеживать физическое устройство после того, как это изменение произойдет. Я думал о том, чтобы отследить его по его концентратору и порту.

Класс Win32_PnPSignedDriver имеет поле «Местоположение», которое кажется идеальным (например, Port_#0001.Hub_#0010), но содержит местоположение устройства только при первой загрузке драйвера. Подключение оборудования к другому порту не обновляет это поле.

Однако эта информация доступна где-то, потому что есть поле «Информация о местоположении» на вкладке «Сведения» при просмотре устройства через диспетчер устройств. Можно ли получить эту информацию с помощью запросов WMI или каким-либо другим способом? Есть ли лучший подход к решению этой проблемы?

РЕДАКТИРОВАТЬ: Я знаю, это звучит как странный сценарий. Микроконтроллер в этих устройствах содержит ПЗУ, которое перечисляется как устройство CDC (то есть последовательный порт) и позволяет программировать. Во время производства было бы полезно отслеживать устройство, поскольку оно изменяется между ПЗУ производителя (уникальный VID / PID / серийный номер) и моим пользовательским интерфейсом прошивки (другой VID / PID / серийный номер).

Ответы [ 5 ]

8 голосов
/ 09 февраля 2013

Я знаю, что прошло какое-то время с момента какого-либо действия над этим ответом, но я работаю над проектом, который также требует функциональности, аналогичной этой, и я могу сказать вам, что это действительно возможно. Насколько я могу судить, для этого требуются DDK и PInvoke, для этой информации нет интерфейса C # или WMI. Это требует открытия низкоуровневых устройств корневого концентратора USB и прямой отправки им команд IOCTL драйвера.

Хорошей новостью является то, что Microsoft предоставляет пример приложения C ++, которое полностью перечисляет все USB-устройства и показывает, к каким именно портам они подключены. Это приложение является примером приложения USBView .

Я думаю, вы найдете, если вы скомпилируете и запустите это приложение, вы увидите, что оно точно показывает, где подключено ваше устройство, и если вы подключите какое-либо устройство к этому порту, оно появится там же. Возможно, будет проще, если вы создадите неуправляемую C ++ DLL, которая предоставляет несколько вызовов, которые ваше приложение C # может использовать для получения необходимой информации.

Он имеет это сказать о функции "EnumerateHubPorts ()" в своем коде:

С учетом дескриптора открытого концентратора и количества нисходящих портов на отправьте концентратору IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX запрос для каждого нижестоящего порта концентратора, чтобы получить информацию о устройство (если есть), подключенное к каждому порту.

Чтобы дать представление обо всем, что для этого требуется (все должно быть перечислено, начиная сверху, даже если вас интересует только один порт), вот комментарии, перечисленные в верхней части файла enum.c в коде. :

/*

This source file contains the routines which enumerate the USB bus
and populate the TreeView control.

The enumeration process goes like this:

(1) Enumerate Host Controllers and Root Hubs
EnumerateHostControllers()
EnumerateHostController()
Host controllers currently have symbolic link names of the form HCDx,
where x starts at 0.  Use CreateFile() to open each host controller
symbolic link.  Create a node in the TreeView to represent each host
controller.

GetRootHubName()
After a host controller has been opened, send the host controller an
IOCTL_USB_GET_ROOT_HUB_NAME request to get the symbolic link name of
the root hub that is part of the host controller.

(2) Enumerate Hubs (Root Hubs and External Hubs)
EnumerateHub()
Given the name of a hub, use CreateFile() to map the hub.  Send the
hub an IOCTL_USB_GET_NODE_INFORMATION request to get info about the
hub, such as the number of downstream ports.  Create a node in the
TreeView to represent each hub.

(3) Enumerate Downstream Ports
EnumerateHubPorts()
Given an handle to an open hub and the number of downstream ports on
the hub, send the hub an IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX
request for each downstream port of the hub to get info about the
device (if any) attached to each port.  If there is a device attached
to a port, send the hub an IOCTL_USB_GET_NODE_CONNECTION_NAME request
to get the symbolic link name of the hub attached to the downstream
port.  If there is a hub attached to the downstream port, recurse to
step (2).  

GetAllStringDescriptors()
GetConfigDescriptor()
Create a node in the TreeView to represent each hub port
and attached device.
*/
2 голосов
/ 01 июля 2011

Вы пробовали SetupDi?Вы можете использовать класс API функции SetupDi для получения информации из DeviceManager.

2 голосов
/ 01 июля 2011

«Информация о местоположении» в диспетчере устройств - это та же строка, которую вы получили через WMI.

Рассматривали ли вы, что, когда устройство подключено к другому порту, вместо обновления метаданных с новым местоположением Windows создает новый экземпляр драйвера и новые метаданные. Попробуйте отфильтровать экземпляры объекта Win32_PnPDevice только для тех, которые в данный момент подключены, и я думаю, вы найдете информацию о текущем местоположении.

Например, если я перевожу USB-мышь на другой порт, есть копия мыши, связанная со старым портом, все еще указанная в Диспетчере устройств, по умолчанию она просто скрыта. См. http://oreilly.com/pub/h/3105 для получения инструкций по просмотру этих отключенных устройств. Или выполните следующую команду из командной строки администратора с повышенными правами:

C:\Windows\system32>set devmgr_show_nonpresent_devices=1
C:\Windows\system32>devmgmt
0 голосов
/ 23 мая 2012

Насколько я могу судить, корреляция USB-устройства с физическим портом невозможна в Windows. Пожалуйста, не стесняйтесь доказать, что я неправ.

0 голосов
/ 27 июня 2011

Лучшей идеей будет использование уникального серийного номера устройства USB.

...