HID Usage is property of a HID top-level-collection, not of a HID device
The HID standard doesn't define a Usage for an whole HID device. These property belongs to a top level collection.
- This fits only with HIDAPIs Windows backend, because an hid_device structure is returned per top-level collection.
- For the other backends, the hid_device structure is returned for an whole HID device, which can consist multiple top-level collections. Therefore you can get only the Usage of the first top-level collection that appears in the report descriptor of an HID device.
From USB HID spec 1.11 page 34:

Sure, that is true.
But to "fix" it right, we would have to introduce a breaking API change - hid_device_info should contain some kind of collection of usage_page/usage pages, instead of a single one. That way the API/behavior will be uniform on all platforms.
Current approach (with duplicating the devices) is more about having the functionality and keep full backward compatibility.
I'd say, to make it "right" - is something we should consider for V1.
@Youw
Just a minor thing, you change the title of this issue to "a HID" from "an HID", but actually I think it is more correct to use "an HID".
Ref: https://www.pristineword.com/grammar-an-h/
Be aware that the choice between a and an depends on the initial sound of the following word
It’s an H. Because the character H starts with a vowel sound (aitch)
So the question here is what is the correct pronounce of a HID - is it 'an (aitch i di)', or as a single word - 'a (hid)'. Maybe I'm biased by my cultural environment (english in not my native), but I always pronounce it as 'a hid'.
So the question here is what is the correct pronounce of a HID - is it 'an (aitch i di)', or as a single word - 'a (hid)'. Maybe I'm biased by my cultural environment (english in not my native), but I always pronounce it as 'a hid'.
I see, I always pronouce it as H-I-D, but I am not a native English speaker either...
Got some interesting argument from my colleague:
MS documentation refers to HID as "a HID":
and multiple other occurrences.
But to "fix" it right, we would have to introduce a breaking API change
Or, we could just introduce a separate structure called something in the lines of hid_device_collection or hid_top_level_device that represents the top-level collection (a single physical device) ~~and can contain multiple hid_device_info's~~. Then we introduce a function hid_enumerate_collections() that makes them. Problem solved.
The structure would be basically a copy of hid_device_info with no usage_page and on Windows it's path field would be empty. On other systems it would be able to be opened by path, if necessary.
Might interfere with the current hotplug implementation, though. On Windows each of them gets a separate event and there isn't much we can do.
UPD: hid_free_collection would also be needed.
UPD2: found a solution on how to merge them on Windows, but it might degrade the performance.
UPD3: if we really care about performance, we can avoid writing the hid_device_info's into the collection structure and instead have a separate function hid_enumerate_collection_devices() that retrieves all hid_device_info's for one on request. This will save some time on Linux and on MacOS, where this data is retrieved for each collection from a single source on every enumeration. On Windows it would have to be assembled from multiple endpoints that aren't connected with one another.
I could make a simplified implementation if it sounds like a good idea to you.
a solution on how to merge them on Windows
If you imply having a single "virtual" device on HIDAPI level that would agregate all top level collections as reported by WinAPI - I'm against that idea. That would complicate the backend implementation.
I'd be happier to see a hid_device_info with a list of available collections (usaga/usage_page pairs) where on most systems there would be a list of available pairs, and on Windows there would be multiple devices with a list contain a single element.
I'm more into having as simpler wrapper/implementation over what OS provides as possible.