Mapping from hid_device to hid_device_info
Assuming the manufacturer of a device did not use serial_numbers to make particular hid devices unique. Is there a way to uniquely map from a given already open hid_device opaque pointer / handle back to a hid_device_info struct in the linked list provided by hid_enumerate(0,0)?
I initially thought that I could do something like the following:
hid_device_info match_device(hid_device *given_dev) {
hid_device_info info = {};
hid_device_info *first = hid_enumerate(0,0);
for(hid_device_info *cur=first, cur; cur=cur->next) {
hid_device *test_dev = hid_open_path(cur->path);
if (test_dev == given_dev) {
memcpy(&info, cur, sizeof(info));
info->next = NULL;
} else {
hid_close(test_dev);
}
}
hid_free_enumeration(first);
return info;
}
Unfortunately, on windows the second hid_open_path function returns a handle that is not identical to the provided handle. As such this code can not return a match.
An alternative method would be if there were a function to extract the path from a given hid_device. In this case, the above code could be modified as following:
hid_device_info match_device(hid_device *given_dev) {
hid_device_info info = {};
/* hypothetical function to get path given an hid_device pointer */
const char *path = hid_device_path(given_dev);
hid_device_info *first = hid_enumerate(0,0);
for(hid_device_info *cur=first, cur; cur=cur->next) {
if (strcmp(path, cur->path) == 0) {
memcpy(&info, cur, sizeof(info));
info->next = NULL;
break;
}
}
hid_free_enumeration(first);
return info;
}
Is there a way to get the path from a hid_device pointer?
Unfortunately, on windows the second hid_open_path function returns a handle that is not identical to the provided handle.
Sounds about right for all platforms, not only for Windows.
memcpy(&info, cur, sizeof(info)); ... hid_free_enumeration(first); ... return info;
Unfortunately, this is not a well-formed piece of code. hid_device_info owns a few pointers, and if you simply make a copy of those, and then hid_free_enumeration of the original data - your info structure would contain dangling pointers, which is undefined behavior in C/C++ world.
Now answering your question:
Is there a way to get the path from a hid_device pointer?
Not right now. In all backends (libusb/hidraw/WinAPI/macOS) the path isn't saved anywhere, so it can't be simply retrieved, nor reliably generated from native handle on each platform.
I had to solve a similar task as you have (to match a device, when SN isn't available from the device descriptor). In my case I was able to send some commands to/from the device, and I could match it by communicating with the device.
You're free to open a PR that implements a new API.
I have submitted a pull request. The pros of the PR is that it adds hid_get_path which can get the path from a hid_device pointer. The biggest con is that now we dynamically allocate space for this path string. Each implementation hid_device structure has an additional new char *path member to point to the allocated path string.
There are some caveats with this PR, please see the second post there for details.