Get vendorId & productId from hid_device or path #431

Closed
opened 2022-06-19 12:42:18 -05:00 by Julusian · 1 comment
Julusian commented 2022-06-19 12:42:18 -05:00 (Migrated from github.com)

I maintain a couple of nodejs libraries (such as elgato-stream-deck) which use this library via node-hid.

In those I expose a method which takes in a path to the device and opens it (such as function openStreamDeck(devicePath: string): StreamDeck), returning a class to interact with the device.
But to do this, I need to check the productId of the hid device to determine the model being opened. In this streamdeck library there are 6 models of compatible device, each with a slightly different protocol.

My current method for this is to do a hid_enumerate before opening the device to find the productId, but this is horribly inefficient.
Ideally there would be a method to get the hid_device_info for a specific path, or be able to get the productId and vendorId from a hid_device
I might be able to achieve the same with hid_get_manufacturer_string and hid_get_product_string, but I suspect that two of the models will report the same name, even though their protocol is completely different.

I can try and implement one of these, but would like to discuss what the api should look like first.

It looks like for windows there is already a hid_device_info stored inside hid_device.
macos has the create_device_info_with_usage function that could be used to create and store a hid_device_info, and at the same time the hid_get_manufacturer_string and related methods could be updated to copy off that struct like windows is doing.
linux looks like it will take a bit of work to refactor parts of hid_enumerate to be reusable, but it doesnt look like there is anything stopping it from being done. As another bonus, get_device_string could be removed.
libusb also looks like it will need a bit of refactoring to be compatible.

So as windows already has a hid_device_info stored inside hid_device, I think it makes sense to replicate this for all backends.
Then one of these methods could be added to access some more of the information it stores:

  • int HID_API_EXPORT HID_API_CALL hid_get_device_ids(hid_device *dev, unsigned short *vendor_id, unsinged short *product_id);
  • struct hid_device_info HID_API_EXPORT HID_API_CALL hid_get_device_info(hid_device *dev);
  • or something else?
I maintain a couple of nodejs libraries (such as [elgato-stream-deck](https://github.com/Julusian/node-elgato-stream-deck)) which use this library via [node-hid](https://github.com/node-hid/node-hid). In those I expose a method which takes in a path to the device and opens it (such as `function openStreamDeck(devicePath: string): StreamDeck`), returning a class to interact with the device. But to do this, I need to check the productId of the hid device to determine the model being opened. In this streamdeck library there are 6 models of compatible device, each with a slightly different protocol. My current method for this is to do a hid_enumerate before opening the device to find the productId, but this is horribly inefficient. Ideally there would be a method to get the `hid_device_info` for a specific path, or be able to get the productId and vendorId from a `hid_device` I might be able to achieve the same with `hid_get_manufacturer_string` and `hid_get_product_string`, but I suspect that two of the models will report the same name, even though their protocol is completely different. I can try and implement one of these, but would like to discuss what the api should look like first. It looks like for windows there is already a `hid_device_info` stored inside `hid_device`. macos has the `create_device_info_with_usage` function that could be used to create and store a `hid_device_info`, and at the same time the `hid_get_manufacturer_string` and related methods could be updated to copy off that struct like windows is doing. linux looks like it will take a bit of work to refactor parts of `hid_enumerate` to be reusable, but it doesnt look like there is anything stopping it from being done. As another bonus, `get_device_string` could be removed. libusb also looks like it will need a bit of refactoring to be compatible. So as windows already has a `hid_device_info` stored inside `hid_device`, I think it makes sense to replicate this for all backends. Then one of these methods could be added to access some more of the information it stores: * `int HID_API_EXPORT HID_API_CALL hid_get_device_ids(hid_device *dev, unsigned short *vendor_id, unsinged short *product_id);` * `struct hid_device_info HID_API_EXPORT HID_API_CALL hid_get_device_info(hid_device *dev);` * or something else?
Youw commented 2022-06-19 15:35:27 -05:00 (Migrated from github.com)

Thanks for the analysis.

struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_get_device_info(hid_device *dev);

I think this would be the way to go - way more flexible in a long term.

libusb also looks like it will need a bit of refactoring to be compatible.

That should be almost trivial. libusb has all the API for it.

linux looks like it will take a bit of work

That I agree. Right now linux/hidraw backend uses udev to gather all the information about the device, and I believe that long-term that is not a good approach. hidraw is a kernel API, so we better use kernel API to gather the information on the device, i.e. sysfs. The most difficulty is the variety of protocols (USB/Bluetooth/I2C/etc.) that needs to be tested with sysfs, and personally I only have USB HID devices that I can reliebly test.

Thanks for the analysis. > `struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_get_device_info(hid_device *dev);` I think this would be the way to go - way more flexible in a long term. > libusb also looks like it will need a bit of refactoring to be compatible. That should be almost trivial. libusb has all the API for it. > linux looks like it will take a bit of work That I agree. Right now linux/hidraw backend uses `udev` to gather all the information about the device, and I believe that long-term that is not a good approach. `hidraw` is a kernel API, so we better use kernel API to gather the information on the device, i.e. `sysfs`. The most difficulty is the variety of protocols (USB/Bluetooth/I2C/etc.) that needs to be tested with `sysfs`, and personally I only have USB HID devices that I can reliebly test.
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#431
No description provided.