hidapi
hidapi copied to clipboard
Can the Device Capabilities Add FeatureReportLength
Many devices require fixed lengths for getting and setting feature reports. This info is available from the caps structure but it is not exposed. ex. dev->feature_report_length = caps.FeatureReportByteLength;
I guess that's possible
PRs are welcome
I found this issue while investigating the same problem for my own project. I even made a patch ready for pull request, when I realized this is not the correct way to do it.
I use get/set feature to get serial communication over HID with a device I build. I typically only write part of the buffer feature report, and this causes the API call to fail. I knew the WDK API had the size of the buffer, so I hoped I wouldn't have to fill every feature up with zeros to this exact size. This was further motivated by that variations of my product used different buffer feature report sizes.
I am not sure if the driver will attempt to set or get a feature with a different size than inferred from the report descriptor. Regardless, this commit will at least allocate a buffer of the size of the largest feature report for every set feature call. If, for instance, the device has a feature that is a 10 kB calibration table, and a 1 byte feature setting the update frequency, every call to set the frequency will allocate the full 10 kB.
If this commit also affects the size sent by the driver, which I doubt, it could break compatibility with devices relying upon this size.
So if anyone wants this you are welcome to try, but I advice against it.
This looks great. I have several devices that use one code base in windows. The Windows versions have always filled the buffer based on the reported size. When I did this in libusb, I had to build a table of the known devices and their sizes. Being able to get the size from the device is, in my opinion, the correct way to do this.
Regards,
Paul
sorry- I did not mean to close it
Would your application to know the size of the feature being written to? This patch doesn't help with that. As far as I can tell this patch is the equivalent of zero-padding your report data to some size guaranteed to exceed any feature on your devices. I believe in both cases the driver will silently cut away the report data that that is beyond the report as declared by the report descriptor, but I am not sure.
Hi Per, The application does not, however, the underlying code the communicates to our device does (usually a dll). My understanding is that USB always sends and receives full reports. At least every device that MagTek ( the company I work for) has ever made does. By making the report a fixed length, extracting data elements becomes very straight forward. It does require that empty values get filled with nulls or some other space. In windows, we use HidP_GetUsageValue. This would allow us to change around the report and have the report usages describe where to get the item from in the report.
Any updates on this? I have a device that is identified by it's FeatureReportLength. It shows up 3x via the usage page 0xFF00 and is separated by the feature report lengths of 520 and 6. The 520 one being for writes and the 6 one for reads.
This is difficult to do in a cross-platform way, so I expect there won't be much movement on this. It requires reading and parsing the HID Report Descriptor for each device, which means opening each device on Linux and MacOS I think.
@crashniels, in your case, you should be able to disambiguate your devices by looking at the HID Report Descriptor for each device and finding which reportIds you should send on.
Thanks for the quick reply. I already made a quick hack that is Windows only. Linux does not need this as I can just claim interface 1 and it is done. Windows is special and the descriptor was made by some random Chinese company which does not combine all usage pages under 0xFF00 but rather splits them into separate devices. The report ids that I need are 4 and 5. One 0xFF00 device accepts 4 and the other 5. The de-compiled software does the same in its detector function.
Wow what a mess. Good luck. :)
The hid_device_info
struct does return interface_number
so can you hid_enumerate(vid,pid)
and then pick which device as the interface_number
, usage_page
and usage
you are looking for?
Thanks and yes I can. On mine however it lists three. That is why I have to filter further by going after the feature report length sizes.
That is why I have to filter further by going after the feature report length sizes
Aren't usage + usage_page combination isn't enough, to identify it on Win?
It shows up 3x via the usage page 0xFF00
So the usage_page
is the same, but usage
is expected to be different. That's how windows separates it into a different devices.
It is expected to, but somehow it isn't. A single physical device shows up as 6 different HID devices, 3 of which have the same interface no (1), the same usage page and the same usage. But they behave differently. If there was any other way to distinguish them, it would have been used already.
It looks like this:
\\?\hid#vid_258a&pid_0033&mi_01&col04#9&3d7401&0&0003#{4d1e55b2-f16f-11cf-88cb-001111000030} < ff00:1
\\?\hid#vid_258a&pid_0033&mi_01&col02#9&3d7401&0&0001#{4d1e55b2-f16f-11cf-88cb-001111000030} < c:1
\\?\hid#vid_258a&pid_0033&mi_01&col05#9&3d7401&0&0004#{4d1e55b2-f16f-11cf-88cb-001111000030} < ff00:1
\\?\hid#vid_258a&pid_0033&mi_00#9&136d903f&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030} < 1:2
\\?\hid#vid_258a&pid_0033&mi_01&col03#9&3d7401&0&0002#{4d1e55b2-f16f-11cf-88cb-001111000030} < ff00:1
\\?\hid#vid_258a&pid_0033&mi_01&col01#9&3d7401&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}\kbd < 1:6
Numbers after the '<' are the page and usage respectively.
Usage page and usage is usually enough looking at other devices in OpenRGB. This device however is weird. The report descriptor from the USB dump lists 3 devices with the usage page 0xFF00 and usage 0x01. The only difference is as mentioned the size it accepts. The Corsair Keyboard I have only lists one device with the usage page 0xFFC2.
The parsed report descriptor of the device:
// 213 bytes
Judging from that HID Report Descriptor, I think you can do hid_open_path()
on any of those devices with usage_page/usage:0xFF00/0x0001 and send on reportIds 4, 5, or 7 and it should behave as you expect.
The problem comes when trying to call SendFeatureReport. If you don’t know the length and send an entire report then an error is thrown.
Paul Deignan
From: Tod E. Kurt [email protected] Sent: Friday, December 25, 2020 3:55:33 PM To: libusb/hidapi [email protected] Cc: Paul Deignan [email protected]; State change [email protected] Subject: Re: [libusb/hidapi] Can the Device Capabilities Add FeatureReportLength (#160)
Judging from that HID Report Descriptor, I think you can do hid_open_path() on any of those devices with usage_page/usage:0xFF00/0x0001 and send on reportIds 4, 5, or 7 and it should behave as you expect.
— You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHubhttps://github.com/libusb/hidapi/issues/160#issuecomment-751290160, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AANO7KCVSNCFM5APUP3D4XDSWT34LANCNFSM4MWDRHXA.
If you don’t know the length and send an entire report then an error is thrown.
That's fixed in current master. Can you try it out?
It looks like this:
Weird, this is the first time I see a device like that.
Is that only fixed on windows or is it also fixed on Linux?
Paul Deignan
From: Ihor Dutchak [email protected] Sent: Friday, December 25, 2020 4:20:05 PM To: libusb/hidapi [email protected] Cc: Paul Deignan [email protected]; State change [email protected] Subject: Re: [libusb/hidapi] Can the Device Capabilities Add FeatureReportLength (#160)
If you don’t know the length and send an entire report then an error is thrown.
That's fixedhttps://github.com/libusb/hidapi/commit/fb4135c7a87e87fb9f3f2fb95c3389677eb35ac9 in current master. Can you try it out?
It looks like this:
Weird, this is the first time I see a device like that.
— You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHubhttps://github.com/libusb/hidapi/issues/160#issuecomment-751291801, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AANO7KG6TWGSCAR45NFKBYLSWT6YLANCNFSM4MWDRHXA.
The problem comes when trying to call SendFeatureReport. If you don’t know the length and send an entire report then an error is thrown. Paul Deignan
That's how USB HID works. Both the device and the application have to heed the USB HID Report Descriptor. I know there's a fix for Windows, but if you send a 8-byte buffer to a reportId expecting a 519-byte payload, you're going to get undefined behavior.
That's fixed for Windows only, because Windows API requires it.
@PaulDeignan are you having a different issue than @crashniels has?
hidapi originally designed for applications that specifically know all the device they are going to work with in advance, including the report size. So identifying a device is a one thing, and sending a correct-size reports - that's a "must have".
Judging from that HID Report Descriptor, I think you can do
hid_open_path()
on any of those devices with usage_page/usage:0xFF00/0x0001 and send on reportIds 4, 5, or 7 and it should behave as you expect.
No as writing with a different report id as what the device accepts results in hid_send_feature_report returning -1.
hidapi originally designed for applications that specifically know all the device they are going to work with in advance, including the report size. So identifying a device is a one thing, and sending a correct-size reports - that's a "must have".
I know the report sizes I need to send. I just need to know which device accepts them.
On Windows I have a quick hack implemented in my fork of hidapi. I have it working in this fork of OpenRGB. If Linux is now also using the usage page changes I am not quite sure how I should go from there. There is no accessible function to return the maximum report length.
@crashniels do you have an Amazon ASIN or similar link to the device in question? I'd like to get one of these myself to experiment on.
Its the Glorious Model O.
aha, hilarious name and looks like something out of a movie set. sold. 👍
I believe this is fixed with https://github.com/libusb/hidapi/pull/224 as much as possible.