Mapping from hid_device to hid_device_info #163

Closed
opened 2020-05-13 22:02:54 -05:00 by gotnone · 2 comments
gotnone commented 2020-05-13 22:02:54 -05:00 (Migrated from github.com)

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?

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 commented 2020-05-14 05:14:19 -05:00 (Migrated from github.com)

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.

> 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 commented 2020-05-14 16:29:58 -05:00 (Migrated from github.com)

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.

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.
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#163
No description provided.