hidapi icon indicating copy to clipboard operation
hidapi copied to clipboard

Mapping from hid_device to hid_device_info

Open gotnone opened this issue 5 years ago • 2 comments

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?

gotnone avatar May 14 '20 03:05 gotnone

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.

Youw avatar May 14 '20 10:05 Youw

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.

gotnone avatar May 14 '20 21:05 gotnone