-
Notifications
You must be signed in to change notification settings - Fork 397
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
HID reports of more than 64 bytes and libusb backend #274
Comments
Do I understand it correctly that the problem on Linux with libusb backend? |
Yes, it's reported by two independend Linux libusb users. I'm myself just relaying this, since I've neither the device nor Linux. |
It is hard to define in a first place what is a "misconfiguration". From USB stack POV, if a device is successfully initialized in Full-Speed it is a successfull configuration. Otherwise it wouldn't be configured at all. And one more time: hidapi is agnostic of the device bus most of the time. On Windows/macOS/hidraw communicationis done using an OS API and there is nothing USB-specific.
It is only negotiated by the OS/USB driver/stack and device itself. The application has no control of this. Each device always tries to initialize itself in a highest possible mode, unless explicitly required otherwise by the device FW/HW limitations.
Again no cross-platform solution is possible. And right now there is no API to get the descriptor. And the USB speed mode is ony easily can be checked by libusb backend. The device's FW is way mo easily can check/know current USB configuration. |
Modification of the the device firmware is not possible. The device is a commerical DJ controller, which is sold for use with the commercial DJ software Traktor Pro for Windows and MacOS. The users try to use it on the cross platform DJ software Mixxx under Linux, which is based on HIDAPI. |
What about hidraw backend, as anyone tried it with that device? If there is no known issues with Windows/macOS, I think it would be feasible to perform an explicit check on Linux using libusb directly, even before trying to open it with hidapi. |
hidraw is not yet tried. Further investigation is needed to understand this specific case. |
That's what I'm trying to say: a USB/HID device running at Full-Speed - is not an error. As for the inability to send packets larger than 64 bytes: this looks like an undesirable behavior of a specific device, but that's definitely not a HID issue. |
After giving it a second though, we can call a case like this a "broken device" or "hardware missconfiguration" which can be detected by libusb backend of hidapi. |
I have a Native Instruments Traktor Kontrol S4 Mk3, one of the affected devices. Here is the output of
The HID component is at 480M speed, so I don't think the bug is in the kernel. The audio interface of the device works fine with Linux. I don't know if the bug here is in libusb or hidapi's use of libusb. My hunch is the latter but I have no evidence to demonstrate that. |
I don't believe libusb (as a result - hidapi too) has any control of how to initialize the device, select speed, etc. USB stack driver is responsible for that. Do you have the same issue on Application level on your machine with this configuration? @JoergAtGithub can you ask users who reported this issue to share the output of |
It seems that libusb can only read a device's speed with |
Here is the
|
How do I tell hidapi to use the hidraw backend instead of libusb? I don't see any documentation for this. |
You can still have both hidraw and libusb backends of hidapi installed and use either one of them. If you have a prebuilt application, it is already hard linked to one of the backends (presumably libhidapi-libusb in your case), and there is no "official" way to change it. |
I hacked the application build system to use hidraw instead of libusb. Now it fails to open the device, both with
Here is the application code. |
I'm confused why the manufacturer set the wMaxPacketSize for the HID endpoint to 64 when they made the HID protocol have packets larger than 64 byes. I'm also confused how the packets are not split on macOS and Windows... do those operating systems concatenate the packet fragments in their HID drivers?? @JoergAtGithub what makes you think that the devices are opened as Full-Speed USB 1 devices? Is it only that the packets are split at 64 bytes or is there some other hint? |
One of the Linux users reported this:
AFAIK the slowest element in the USB bus chain defines the speed. I assumed, that the HUB limits the speed of the HID endpoint to Full-Speed. |
The hub operates at 480 Mb too. Here is
|
I don't think the USB speed is the problem here. I think it is the wMaxPacketSize of 64. |
I wouldn't be suprised. |
Does the HID specification say to concatenate the packet fragments in this case with wMaxPacketSize smaller than the report size? I wouldn't be surprised if this is an edge case where the specification does not say what to do... I'm still at a loss why the manufacturer would create this situation. |
The HID specification has this to say about wMaxPacketSize:
I'm unclear exactly what that means but it seems that it permits wMaxPacketSize to be shorter than the report size. |
This would make some sense. libusb by itself has no awareness that the split USB packets should be concatenated for the HID protocol. However hidapi can determine this. |
hidapi would need to parse the report descriptor to determine this, so I guess #249 is a prerequisite for this? |
Isn't the report_descriptor already available internal in the libusb backend: Line 643 in b72a367
|
Yes, getting the report descriptor is there. Parsing it is another task. hidapi would need to compare the size of the reports described in the report descriptor to wMaxPacketSize. If any reports are bigger than wMaxPacketSize, keep incoming packets that are equal in length to wMaxPacketSize in a buffer, then concatenate the buffer with the short part when the incoming packet length is equal to the long report length minus wMaxPacketSize. |
The quick and ugly hack around this is for the application to concatenate the packets for devices know to be affected by this, but that means the application requires platform-specific code to use a cross-platform library. :/ |
Advanced parsing and packet (re-)construction/verification was never the intention of hidapi. It always tried to be the thinest proxy library possible, with remarks to keeping the API uniform across platforms. In defence of the application side workaround for a specific device - I believe the reconstruction code can be written uniformly for all platforms, it just that some of the branches of the code will be executed when run on linux only. |
This issue makes the API not uniform across platforms.
This could not be done in a generic way for any device because that would require hidapi to expose the wMaxPacketSize -- or possibly directly invoke libusb to get that, which kinda defeats the point of using hidapi. For the few devices known to be affected by this for Mixxx, it isn't hard to hack around this in the device-specific JavaScript code that maps the HID I/O to application logic. |
Past discussions and comments by the original author of HIDAPI Alan Ott. On 30-Jan-2013
|
Past discussions and comments by the original author of HIDAPI Alan Ott. On 25-Feb-2014
|
Application level work-around from probe-rs
Also here from Microchip (hard-coded table)
Alan Ott mentioned about VRPN application side work-around. I believe it is here (512 Bytest report) So yes there are quite some devices with >64 Bytes HID report size. I need to find one of them and check if they still use wMaxPacketSize=64 bytest or if any of them use higher one. |
Hi Hans, would you please do me a favor to dump the USB Prober output of your Atmel-ICE or Power Debuger if you still have them. Thanks. Something like this: Or you can post the output from
And also the outout of hidapi hidtest or mac-hid-dump. |
Can not confirm. I own the laptop with USB touchscreen which input report is greater than 100 bytes. It had Windows 8.0 preinstalled. |
There are certainly devices with input report size greater than 64 Bytes as mentioned in the above (like 512 Bytes or even 1024 Bytes). However, please check the wMaxPacketSize of the Interupt IN endpoint of your USB touch deviice. I bet it is still 64 Bytes. |
wMaxPacketSize is 64 as it is USB 2.0 LowSpeed device |
I think you mean to say USB 2.0 Full Speed Device. It is good that you have such device, probably you can use it to test the current HIDAPI FreeBSD implementation which use libusb. And if you would like to work on FreeBSD hidraw backend for HIDAPI, it can be useful as a comparison. |
[To be confimred --> confirmed to be wrong]
Hopefully some people will have some High Speed USB HID device to check if their HID interrupt Endpoint have greater than 64 Bytest wMaxPacketSize or not. So far I have only seen High Speed USB HID Devices with their Interrupt Endpoint having only 64 Bytes wMaxPacketSize. |
I really need a picture, but this is what I've got:
|
I'm confused about the discussion regarding Windows. Why does it matter? Is there some use case for using the libusb backend on Windows instead of Windows' HID API? |
Hi HPS, |
Ahh, it is a side topic -- I am trying to understand why High Speed USB HID device developers would not choose to have the Interrupt IN endpoint's wMaxPacketSize to be higher value (up to 1024 Bytes). From what I read the HID report size is usually less than 1024 Bytes. In that case they can simplify their Firmware development efforts (send the report in one packet and no need to deal with multiple packets on the device side). Of course the issue is not as bad as this one since the device firmware developer only needs to deal with one paticular device or a group of similar devices. As for hidapi Windows libusb backend, in fact there are some use cases. |
Interestingly I see a similar issue from the libfido2 project. But they do not use libusb backend. I see they have platfrom specific backend and even one hidapi backend. Issue: Fixes:
|
FYI as well. libfido2 uses FreeBSD hidraw on FreeBSD13+.
|
@mcuee I've only borrowed an Atmel ICE, so I cant test with this at the moment, but here are the Power Debugger dump, which is very similar hardware vice: lsusb -vvv with only the Power Debugger plugged in
mac-hid-dump with only the Power Debugger plugged in
|
Great. So we can see that the HID report size is 512 Bytes and the Interrupt IN/OUT Endpoint's wMaxPacketSize is 512 Bytes. Since the Power Debugger works well under Windows, so this confirms that Windows does support HID interface with the Interrupt IN/OUT Endpoint's wMaxPacketSize greater than 64 Bytes.
The hid report parser output.
|
I hope my modification to Jan Axelson's FX2HID FW is correct. In that case, I can probably carry out some tests for this issue in different OS. INPUT/OUTPUT report size 128 bytes, loop back, no report ID.
|
Indeed I can reproduce the issue using hidapitester under Linux.
Using libusb backend, I can reproduce the issue under Linux. You can see that it only reads back 64 Bytes.
|
The documentation of |
@JoergAtGithub and @Youw Just wondering if you are still looking at this issue or not. Thanks. |
This is clearly a bug in hidapi libusb backend, confirmed by several affected users. |
Agree. |
At Mixxx, users reported problems with USB 2.0 High-Speed devices, which are limited to Full-Speed mode for some reasons. Under MacOS and Windows they operate as High-Speed device.
This is not only a performance limitation, but it has functional implications for the HID communication, because USB Full-Speed is limited to a package size of 64 Bytes instead of 1024 in High-Speed mode.
The result is, that HIDAP returns a 79Byte input report correct on Windows and MacOS, but two reports on Linux (libusb backend), the first with correct report ID, the second with report ID 0x00.
How could a cross platform application using HIDAPI handle this:
The text was updated successfully, but these errors were encountered: