hidapi icon indicating copy to clipboard operation
hidapi copied to clipboard

Get vendorId & productId from hid_device or path

Open Julusian opened this issue 2 years ago • 1 comments

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?

Julusian avatar Jun 19 '22 17:06 Julusian

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.

Youw avatar Jun 19 '22 20:06 Youw