hidapi icon indicating copy to clipboard operation
hidapi copied to clipboard

hid_enumerate specify multiple VID/PID combos.

Open FabianKopp opened this issue 4 years ago • 12 comments

As of now you can only specify one pair of VID PID in the hid_enumerate function. Is it possible to have a version where you can supply multiple sets of VID PIDs to the function? This would be of great use for anyone scanning for multiple products.

FabianKopp avatar Dec 24 '20 13:12 FabianKopp

use hid_enumerate with (0, 0) VID/PID - it will give you all the devices, so you can filter that list on your own.

Youw avatar Dec 25 '20 11:12 Youw

Right, but it turns out that running hid_enumerate(0,0) repeatedly is very bad and causes many issues on user's computers. For example it can cause clicking sounds on microphones and make other HID devices unusable. It is better to filter within the enumerate function than to run a full getDescriptor request on every single hid device on the computer.

FabianKopp avatar Dec 25 '20 12:12 FabianKopp

Not repeatedly. Enumerate once - search/filter all the devices you need in that list.

Youw avatar Dec 25 '20 12:12 Youw

But if you have a program and device where you have to repeatedly check for when the device was inserted or removed on the fly this does not work.

FabianKopp avatar Dec 25 '20 12:12 FabianKopp

I'm confused. Checking for hotplug/unplug events is entirely different problem, then you originally described (finding multiple devices with a single hid_enumerate).

Youw avatar Dec 25 '20 12:12 Youw

One detects plug and unplug events by repeatedly enumerating the the devices and checking the difference between enumerations

FabianKopp avatar Dec 25 '20 12:12 FabianKopp

And how passing multiple VIDs/PIDs into hid_enumerate help with "audio clicks" each time you call it?

Youw avatar Dec 25 '20 13:12 Youw

When you do hid_enumerate(0,0) it executes getDescriptor requests on every single usb device on your computer even devices such as microphones that I'm not interested in. Resource limited devices with weak CPUs such a microphones cannot do their regular job and respond to the request at the same time. When the microphone receives the request it stops streaming audio data briefly so that it can respond. This can be heard as a short "pop" or "click". If we call hid_enumerate without wildcards and only specify which devices we care about, it avoids sending this disruptive getDescriptor request to sensitive devices such as microphones, etc.

FabianKopp avatar Dec 25 '20 13:12 FabianKopp

In general, I would advise against using hid_enumerate() to detect insertion/removal events because it's so taxing to the USB bus system.

Instead, use an OS-specific USB insertion/removal event system. I don't know of a hidapi-like cross-platform C-based API for doing this, but you can check out the Nodejs package node-usb-detection to see the platform-specific code they use for Windows (RegisterDeviceNotificationA()), MacOS (IONotificationPortCreate()), and Linux (udev_monitor_receive_device()): https://github.com/MadLittleMods/node-usb-detection/tree/master/src

Another thing to note, there is a delay between device inserted and when it's available to hidapi, as the OS has to hook in the USB and HID driver. I've seen this delay be up to several seconds on MacOS and Windows.

todbot avatar Dec 25 '20 20:12 todbot

Very good point from Tod.

Thanks for the explanation @FabianKopp, I think I understand your problem now.

it executes getDescriptor requests on every single usb device

  1. So I presume, it is not called when you enumerate the devices with a specific PID/VID?
  2. There is no direct call to what you call a getDescriptor in windows implementation, after the device is enumerated. All I see is HidD_GetPreparsedData, HidP_GetCaps and HidD_Get***String calls. Can you track down which one of those actually causing the negative "clicks" effect you mentioned?

Youw avatar Dec 25 '20 21:12 Youw

Its pretty much everything after this filtering line: if ((vendor_id == 0x0 || attrib.VendorID == vendor_id) && (product_id == 0x0 || attrib.ProductID == product_id)) { Its HidD_GetPreparsedData, HidP_GetCaps, HidD_GetSerialNumberString, HidD_GetManufacturerString, HidD_GetProductString. These calls are taxing to the usb device and can be avoided on other devices by specifying the vid/pid you are looking for and ignoring the rest. I just think it would really helpful to be able to specify multiple vid/pids in case you are looking for 2 or more types of devices.

FabianKopp avatar Dec 25 '20 23:12 FabianKopp

I'm asking, because I was thinking a more general aproach: enumerate function, that accepts a filter function over devices attrigutes (or even over a hid_device_info), but I guess it wouldn't help your case, since only VID/PID is available for filtering, without causing negative effect on your audio device(s).

Youw avatar Dec 26 '20 08:12 Youw