4
votes

I would like to monitor the the USB bus of a computer running Windows for (un)plug events. When a device is (un)plugged, I would like to know it's USB address, vendor id, the root hub id and the hub ports above the device. For example usb_addr: 10, vendor_id: 1234, product_id: 5678, bus_id: 2, port_path: 5/4/3

This would mean it is a device on bus id 2 port 5 and there is another hub plugged in and on port 4 of that hub there is another hub and on port 3 of that hub is the device being reported.

I am trying to write a small OS-specific chunk of code to do USB device hotplug detection to integrate into a larger cross-platform (Linux, Windows, Mac) testing program. The code that uses this hotplug code is written in Python 3, so I would prefer to write the hotplug code in Python as well, but I'm a little bit flexible on that, but I really want to avoid anything that requires me to pay for a license.

It seems like there are two main options:

I've seen some discussion of the Windows API function RegisterDeviceNotification, but it's not clear to me whether it is possible to register to receive events for all USB devices or whether you need to know a GUID for the specific device interface (eg. keyboards, mice, etc). If that's the case, it seems that this solution won't work as I want to monitor all USB devices.

The other option seems to involve something called "WMI" which seems to come up mostly in discussion of "managed" code which would to force me into writing this component in a .NET language such as C# or IronPython. This question (Get List of connected USB Devices) asks about how to query for USB devices and provides an example, but it doesn't deal with hotplug events and user "Nedko" suggests that class Win32_USBControllerDevice should have been used rather than Win32_USBHub. I don't really understand what the Win32_USBControllerDevice object actually models. It seems like perhaps the Dependent member is a reference to a CIM_LogicalDevice object, but even that seems like it is missing the USB specific information that I am seeking.

Which APIs should I be looking at to solve this problem?

1

1 Answers

1
votes

What you saw were the USB device classes. There are also interface classes. Passing GUID_DEVINTERFACE_USB_DEVICE (usbiodef.h, driver documentation) generates events for any USB activity. The other likely candidate, GUID_DEVCLASS_USB, appears to be for unrecognized USB devices. I was not able to get it to trigger during my testing.

Note that an article by Doran Holan (a Microsoft developer) seems to claim that passing interface class GUIDs does not work. His article is from 2006, before this answer (2009) was posted, claiming the method I detailed is valid.

If you need to interact with low level features of Windows you will be fighting an uphill battle trying to do it from Python (circa 2018). IronPython may fare well. C# is hit-or-miss - generally you will find important functionality lacking. Bindings for any given library will typically not work well.

To use WMI from C++ as you would in C# (e.g. with ManagementObjectSearcher and ManagementObject) you should instantiate an IWbemServices using IWbemLocator::ConnectServer and then call IWbemServices::ExecQuery.

You can check the WMI C++ Application Examples for more information.