Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mapping from hid_device to hid_device_info #163

Closed
gotnone opened this issue May 14, 2020 · 2 comments · Fixed by #432
Closed

Mapping from hid_device to hid_device_info #163

gotnone opened this issue May 14, 2020 · 2 comments · Fixed by #432
Labels
Core Related to common codes like hidapi.h enhancement New feature or request

Comments

@gotnone
Copy link

gotnone commented May 14, 2020

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?

@Youw
Copy link
Member

Youw commented May 14, 2020

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.

@gotnone
Copy link
Author

gotnone commented May 14, 2020

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.

@mcuee mcuee added the enhancement New feature or request label Jun 20, 2020
@mcuee mcuee added the Core Related to common codes like hidapi.h label Jul 18, 2021
@Youw Youw closed this as completed in #432 Aug 13, 2022
Youw pushed a commit that referenced this issue Aug 13, 2022
- new API function: `struct hid_device_info * hid_get_device_info(hid_device *dev);` to get `hid_device_info` after the device already opened;
- reused existing implementation on Windows and macOS from enumeration routines to have the implementation;
- refactored libusb implementation to have a shared routine for `hid_enumerate` and `hid_get_device_info`;
- refactored hidraw implementation to have a shared routine for `hid_enumerate` and `hid_get_device_info`;

Resolves: #431
Closes: #164
Closes: #163
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Core Related to common codes like hidapi.h enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants