Windows version doesn't enumerate devices when exactly one is connected #234

Closed
opened 2021-01-20 08:53:35 -06:00 by jm4R · 13 comments
jm4R commented 2021-01-20 08:53:35 -06:00 (Migrated from github.com)

I don't know if this is coincidence, but this is my case:

I plug UPS HID device (CyberPower or APC) as an only HID device in the whole system, and hid_enumerate returns nullptr.

When I plug USB keyboard as a second device, hid_enumerate enumerates both - keyboard and UPS.

On Linux and exactly the same machine it works fine.

I don't know if this is coincidence, but this is my case: I plug UPS HID device (CyberPower or APC) as an only HID device in the whole system, and `hid_enumerate` returns `nullptr`. When I plug USB keyboard as a second device, `hid_enumerate` enumerates both - keyboard and UPS. On Linux and exactly the same machine it works fine.
Youw commented 2021-01-20 09:54:57 -06:00 (Migrated from github.com)

I assume you're using build 0.10.1.

Can you step-trace a "single device" scenario with a debugger and tell what do you get from SetupDiGetClassDevsA/SetupDiEnumDeviceInterfaces (or after those)?

I assume you're using build 0.10.1. Can you step-trace a "single device" scenario with a debugger and tell what do you get from [SetupDiGetClassDevsA](https://github.com/libusb/hidapi/blob/master/windows/hid.c#L330)/[SetupDiEnumDeviceInterfaces](https://github.com/libusb/hidapi/blob/master/windows/hid.c#L339) (or after those)?
jm4R commented 2021-01-20 09:58:29 -06:00 (Migrated from github.com)

driver_name is "Battery" which is weird as in windows device manager the device class shows "HIDClass" as expected.

driver_name is "Battery" which is weird as in windows device manager the device class shows "HIDClass" as expected.
Youw commented 2021-01-20 10:08:12 -06:00 (Migrated from github.com)

And when you have two devices connected?

And when you have two devices connected?
todbot commented 2021-01-20 11:23:13 -06:00 (Migrated from github.com)

Yes, I believe on Windows, with the HID Battery driver, that removes it from the list of devices hidapi can access. (as what happens to gamepads) http://batcmd.com/windows/10/services/hidbatt/

Yes, I believe on Windows, with the HID Battery driver, that removes it from the list of devices hidapi can access. (as what happens to gamepads) http://batcmd.com/windows/10/services/hidbatt/
todbot commented 2021-01-20 16:34:59 -06:00 (Migrated from github.com)

I just tested an APC Back-UPS ES 550 on Windows 10 Pro. It appears as both a HID device and as a "Battery" to device driver (see screenshot below). And it appears to hidapi's hid_enumerate just fine (see hidapitester output below, it's using hidapi@0.10.1). Perhaps you have an additional, non-Microsoft driver on the device?

Screen Shot 2021-01-20 at 2 21 44p Screen Shot 2021-01-20 at 2 33 22p

Oh, wait, but I see, the issue is that if the UPS is the only HID device. Hmmm.

I just tested an APC Back-UPS ES 550 on Windows 10 Pro. It appears as both a HID device and as a "Battery" to device driver (see screenshot below). And it appears to hidapi's `hid_enumerate` just fine (see `hidapitester` output below, it's using `hidapi@0.10.1`). Perhaps you have an additional, non-Microsoft driver on the device? <img width="1042" alt="Screen Shot 2021-01-20 at 2 21 44p" src="https://user-images.githubusercontent.com/274093/105248936-22795e00-5b2c-11eb-82f5-98b3fba24aba.png"> <img width="877" alt="Screen Shot 2021-01-20 at 2 33 22p" src="https://user-images.githubusercontent.com/274093/105249128-74ba7f00-5b2c-11eb-9c08-3b99c2f5cbdc.png"> Oh, wait, but I see, the issue is that if the UPS is the *only* HID device. Hmmm.
Youw commented 2021-01-20 16:41:10 -06:00 (Migrated from github.com)

I think the problem comes if you'd have only this UPS connected, and no other HID devices in the system.

UPD: this conversation looks weird, when we both edit our messages :D

~~I think the problem comes if you'd have only this UPS connected, and no other HID devices in the system.~~ UPD: this conversation looks weird, when we both edit our messages :D
todbot commented 2021-01-20 16:42:08 -06:00 (Migrated from github.com)

Yes I understand that better now. :) Trying to figure out how to test this since RDP just decided to stop working with a recent Win10 update...

Yes I understand that better now. :) Trying to figure out how to test this since RDP just decided to stop working with a recent Win10 update...
jm4R commented 2021-01-21 03:30:56 -06:00 (Migrated from github.com)

@Youw when I plug the keyboard and the mouse in, all iterations returns "Keyborad" as a device name. Something is definetely wrong in this code. I found old, open but abandoned pull request that claims that the index passed to the SetupDiEnumDeviceInfo is wrong:

https://github.com/signal11/hidapi/pull/291/files/f453bda38ff17ea28b7b1d59afd8d09e74e5efb5#diff-8162c58f4630fb0f3a6a21f2e094e883L354

It seems that after simillar change the driver_name shows more apriopriate values to the ones that are shown in Windows Device Manager. To sumarise that, it looks like
hid_enumerate enumerates all USB devices if the first on the list is HIDClass or Mouse or Keyboard

This is coincidence that the code works with my UPS because SetupDiEnumDeviceInfo(device_info_set, device_index, &devinfo_data); after the "quickfix" still returns "Battery", but we should somehow retreive the value which is shown by the Windows device manager as on the screenshot:
a

This way, we can expect that we could get rid of the "Keyboard" and "Mouse" exceptions, because for those devices the device manager also shows "HIDClass" value. Yet, I am not very familiar with WinApi so I don't know (yet) how to retrive it using WinApi.

@Youw when I plug the keyboard and the mouse in, all iterations returns "Keyborad" as a device name. Something is definetely wrong in this code. I found old, open but abandoned pull request that claims that the index passed to the `SetupDiEnumDeviceInfo` is wrong: https://github.com/signal11/hidapi/pull/291/files/f453bda38ff17ea28b7b1d59afd8d09e74e5efb5#diff-8162c58f4630fb0f3a6a21f2e094e883L354 It seems that after simillar change the driver_name shows more apriopriate values to the ones that are shown in Windows Device Manager. To sumarise that, it looks like **hid_enumerate enumerates all USB devices if the first on the list is HIDClass or Mouse or Keyboard** This is coincidence that the code works with my UPS because `SetupDiEnumDeviceInfo(device_info_set, device_index, &devinfo_data);` after the "quickfix" still returns "Battery", but we should somehow retreive the value which is shown by the Windows device manager as on the screenshot: ![a](https://user-images.githubusercontent.com/38551394/105330296-6aeb5700-5bd2-11eb-95e1-7c320245ed4e.png) This way, we can expect that we could get rid of the "Keyboard" and "Mouse" exceptions, because for those devices the device manager also shows "HIDClass" value. Yet, I am not very familiar with WinApi so I don't know (yet) how to retrive it using WinApi.
jm4R commented 2021-01-21 05:06:28 -06:00 (Migrated from github.com)

How about solution straight from Microsoft:

https://github.com/microsoft/Windows-driver-samples/blob/master/hid/hclient/pnp.c#L32

?

It is similar but instead of checking device class name, it just uses HidD_GetHidGuid doc and tries to open it. I will try it and prepare a pull request if it will work.

How about solution straight from Microsoft: https://github.com/microsoft/Windows-driver-samples/blob/master/hid/hclient/pnp.c#L32 ? It is similar but instead of checking device class name, it just uses `HidD_GetHidGuid` [doc](https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/hidsdi/nf-hidsdi-hidd_gethidguid) and tries to open it. I will try it and prepare a pull request if it will work.
Youw commented 2021-01-21 05:26:09 -06:00 (Migrated from github.com)

I'm afraid, opening a device might cause issue, like described here: https://github.com/libusb/hidapi/issues/225#issuecomment-751252471
I'll take a look at this closely

I'm afraid, opening a device might cause issue, like described here: https://github.com/libusb/hidapi/issues/225#issuecomment-751252471 I'll take a look at this closely
jm4R commented 2021-01-21 05:35:22 -06:00 (Migrated from github.com)

We already do this:
https://github.com/libusb/hidapi/blob/master/windows/hid.c#L411

It is being open with open_rw set to FALSE, maybe this doesn't make the issue. I won't change it.

We already do this: https://github.com/libusb/hidapi/blob/master/windows/hid.c#L411 It is being open with `open_rw` set to `FALSE`, maybe this doesn't make the issue. I won't change it.
Youw commented 2021-01-21 05:41:14 -06:00 (Migrated from github.com)

Hmm, right, fair enough.

Hmm, right, fair enough.
jm4R commented 2021-01-21 07:17:05 -06:00 (Migrated from github.com)

The PR works for me, please review. I didn't use HidD_GetHidGuid directly as it would require linking to hid.lib. The hard-coded GUID is the same with the one returned by this function which means the enumeration already filters only HID-class devices.

The PR works for me, please review. I didn't use `HidD_GetHidGuid` directly as it would require linking to `hid.lib`. The hard-coded GUID is the same with the one returned by this function which means the enumeration already filters only HID-class devices.
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
gh-libusb/hidapi#234
No description provided.