-
Notifications
You must be signed in to change notification settings - Fork 448
Properly determine libusb read size for large reports (Fixes #274) #728
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
Conversation
068fd62 to
52c6cd9
Compare
PR updated to remove different signedness comparison compiler warning when compiling with -Wall.
Thank you for finally taking care of this longstanding bug.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for this, I'll perform a thorrow review a bit later.
@Be-ing can you confirm it fixes the issue with long reports too?
libusb/hid.c
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function seems to be the functional the same as InputReportByteLength from https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/hidpi/ns-hidpi-_hidp_caps on Windows.
We have a lot of test data for the Windows unit test, which stores the result of this function:
together with the real ReportDescriptor https://github.com/libusb/hidapi/blob/master/windows/test/data/045E_02FF_0005_0001_real.rpt_desc
What do you think about creating a unit test for the new get_max_input_size function using the _real.rpt_desc files as input and compare the result with the value stored in the .pp_data.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! That does look like a great dataset. I'll see if I can figure a clean way to make a unit test, and see how it fares with that data.
Currently the get_max_input_size is a static function, but I need a way to use it externally in the unit test. It seems that the windows library has some extensions prefixed with winapi. Should I rename the get max function to hid_libusbapi_get_max_input_report_size and mark it HID_API_EXPORT_CALL?
I will also need to change how it gets the report descriptor, but that won't be a problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Making it with HID_API_EXPORT_CALL would make it a public (at least on binary level) function, which is undesirable, if it is required for tests only. Maybe export it only when building unit-tests etc. or try to avoid it by using static linking or smth else (or have it in an internal header file?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have a look at the Windows unit test ( https://github.com/libusb/hidapi/tree/master/windows/test ) for the report descriptor reconstructor. There we had exactly the same challenges, hid_winapi_descriptor_reconstruct_pp_data was the internal function to test there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JoergAtGithub I did actually look at hid_winapi_descriptor_reconstruct_pp_data, and it is marked as HID_API_EXPORT_CALL in the header file:
hidapi/windows/hidapi_winapi.h
Line 68 in 0ab6c14
Although, now that I am looking, it is not marked in the C file:
WRT @Youw's suggestion. I could simplify the function a bit so that it doesn't depend on anything in hid.c and then move it to hid_max_input_report.h. If that is acceptable, it is probably the easiest solution.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hid_winapi_descriptor_reconstruct_pp_data, and it is marked as HID_API_EXPORT_CALL in the header file
Right - that is a public API function. That is also the reason why there is a winapi prefix in the name.
it is not marked in the C file
Not required, if it is marked in the header.
I could simplify the function a bit so that it doesn't depend on anything in hid.c and then move it to hid_max_input_report.h. If that is acceptable, it is probably the easiest solution.
Yes, sounds like simples solution for now. Go for it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a test, but it isn't passing. It could be that I am misunderstanding the Windows HID structures. I have only a vague understanding of them.
For example, in the 046A_0011_0006_0001 test data, it gives a max input size of 9 bytes:
hidapi/windows/test/data/046A_0011_0006_0001.pp_data
Lines 16 to 19 in 0ab6c14
But two input caps (cap[0] and cap[1]) are:
hidapi/windows/test/data/046A_0011_0006_0001.pp_data
Lines 37 to 38 in 0ab6c14
hidapi/windows/test/data/046A_0011_0006_0001.pp_data
Lines 83 to 84 in 0ab6c14
According to the documentation I read, the report size is just BitSize * ReportCount (plus a byte for the report number I assume).
This gives report sizes of (1*8)/8 + 1 = 2 and (8*6)/8 + 1 = 7. So I don't know where the ReportByteLength = 9 value is coming from.
Do either of you know what I am missing here?
BTW, there is a typo here.
@Youw and @JoergAtGithub.
dev->manufacturer_string = "dev->product_string = "dev->release_number = 0x0100
I put 046A_0011_0006_0001_real.rpt_desc into https://eleccelerator.com/usbdescreqparser/ and got:
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
0x09, 0x06, // Usage (Keyboard)
0xA1, 0x01, // Collection (Application)
0x05, 0x07, // Usage Page (Kbrd/Keypad)
0x19, 0xE0, // Usage Minimum (0xE0)
0x29, 0xE7, // Usage Maximum (0xE7)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x75, 0x01, // Report Size (1)
0x95, 0x08, // Report Count (8)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x75, 0x08, // Report Size (8)
0x95, 0x01, // Report Count (1)
0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x19, 0x00, // Usage Minimum (0x00)
0x29, 0xDD, // Usage Maximum (0xDD)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xDD, 0x00, // Logical Maximum (221)
0x75, 0x08, // Report Size (8)
0x95, 0x06, // Report Count (6)
0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x05, 0x08, // Usage Page (LEDs)
0x19, 0x01, // Usage Minimum (Num Lock)
0x29, 0x03, // Usage Maximum (Scroll Lock)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x75, 0x01, // Report Size (1)
0x95, 0x03, // Report Count (3)
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x75, 0x05, // Report Size (5)
0x95, 0x01, // Report Count (1)
0x91, 0x03, // Output (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0xC0, // End Collection
The InputReport contains:
- 8x1bit data
- 1x8bit constant padding
- 6x8bit data
This sums to 8byte, butInputReportByteLengthis defined as follows:
Specifies the maximum size, in bytes, of all the input reports. Includes the report ID, which is prepended to the report data. If report ID is not used, the ID value is zero.
So we've to add a byte for the ReportID and are at 9 bytes.
BTW, there is a typo here. @Youw and @JoergAtGithub.
dev->manufacturer_string = "dev->product_string = "dev->release_number = 0x0100dev->manufacturer_string = "dev->product_string = "dev->release_number = 0x0100
There is something missing, as this is autogenerated by pp_data_dump, I guess there was something in the manufacturer_string , that pp_data_dump couldn't handle. Could you please open a dedicated issue for this, as this is unrelated to this PR.
There is something missing, as this is autogenerated by pp_data_dump, I guess there was something in the manufacturer_string , that pp_data_dump couldn't handle. Could you please open a dedicated issue for this, as this is unrelated to this PR.
52c6cd9 to
2708264
Compare
2708264 to
3710895
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to parse the _real.rpt_desc, not the _expected.rpt_desc. The real is what is dumped from the device, and the expected is what the Windows ReportDescriptor-Reconstructor generates out of the .pp_data.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. I assumed that the real and expected should contain equivalent reports.
The _real.rpt_desc files do not follow a consistent format, so should I parse them manually (should be pretty doable with a bit of regex) into new files and add them to the repo?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe you can put them into https://eleccelerator.com/usbdescreqparser/ to unify the format. That makes them also human readable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would mean a corrupt ReportDescriptor
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn't consistent with whether I was using size_t or ssize_t. In my last commit, I settled on size_t, but perhaps I should change it back to ssize_t so that we can more clearly differentiate between errors and a zero value (if there are no feature reports, it will return 0, which is not an error).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense!
Thanks @JoergAtGithub for walking me through that. I was misreading the descriptor.
I have added tests for libusb using the same data as the windows tests. And I extended the functionality of the libusb method to be able to calculate the maximum output and feature report sizes as well. This has no functional use currently, but it lets us run three times as many tests since the pp_data files have all three max sizes available.
And I extended the functionality of the libusb method to be able to calculate the maximum output and feature report sizes as well. This has no functional use currently, but it lets us run three times as many tests since the pp_data files have all three max sizes available.
Independent of this PR, I think it would generally make sense to store these 3 values in the device structure. On Windows we would have to use the values InputReportByteLength, OutputReportByteLength and FeatureReportByteLength from https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/hidpi/ns-hidpi-_hidp_caps . On all other backends we could use your parser to determine them - and with the testcase you proved that they are the same as on Windows.
In this way, we were able to programmatically determine the required buffer sizes for read/write operations on all platforms. @Youw What do you think about this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also need to update builds.yml
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe move the test data to <root>/test_data ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't have a strong opinion on test implementation (I trust @JoergAtGithub on this one).
libusb implementation seem fine.
Lets make sure it runs with CI on Github Actions and we're good to go here.
And I extended the functionality of the libusb method to be able to calculate the maximum output and feature report sizes as well. This has no functional use currently, but it lets us run three times as many tests since the pp_data files have all three max sizes available.
Independent of this PR, I think it would generally make sense to store these 3 values in the device structure. On Windows we would have to use the values
InputReportByteLength,OutputReportByteLengthandFeatureReportByteLengthfrom https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/hidpi/ns-hidpi-_hidp_caps . On all other backends we could use your parser to determine them - and with the testcase you proved that they are the same as on Windows. In this way, we were able to programmatically determine the required buffer sizes for read/write operations on all platforms. @Youw What do you think about this?
Lets continue here: #731
This PR does not seem to work.
Test device is the same as the one used in Issue #274. The FW is a mod of Jan Axelson's FX2HID example and codes are included in the following #274 comment.
I can reproduce the issue reported in #274 with hidapi git libusb backend, hidraw backend is okay.
mcuee@UbuntuSwift3 ~/build/hid/hidapitester (master)$ sudo ./hidapitester_hidraw_git --vidpid 0925:1234 --open --buflen 256 -l 129 --send-output 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128 --read-input
Opening device, vid/pid: 0x0925/0x1234
Writing output report of 129-bytes...wrote 129 bytes:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
80
Reading 129-byte input report 0, 250 msec timeout...read 128 bytes:
01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20
21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40
41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 60
61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F 80
00
Closing device
mcuee@UbuntuSwift3 ~/build/hid/hidapitester (master)$ sudo ./hidapitester_libusb_git --vidpid 0925:1234 --open --buflen 256 -l 129 --send-output 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128 --read-input
Opening device, vid/pid: 0x0925/0x1234
Writing output report of 129-bytes...wrote 129 bytes:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
80
Reading 129-byte input report 0, 250 msec timeout...read 64 bytes:
01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20
21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00
Closing device
With this PR, no change in hidraw backend behavior, which is good.
mcuee@UbuntuSwift3 ~/build/hid/hidapitester (master)$ sudo ./hidapitester_hidraw_pr728 --vidpid 0925:1234 --open --buflen 256 -l 129 --send-output 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128 --read-input
Opening device, vid/pid: 0x0925/0x1234
Writing output report of 129-bytes...wrote 129 bytes:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
80
Reading 129-byte input report 0, 250 msec timeout...read 128 bytes:
01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20
21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40
41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 60
61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F 80
00
Closing device
But the libusb backend fix is not working.
mcuee@UbuntuSwift3 ~/build/hid/hidapitester (master)$ make -f Makefile_pr728.libusb
cc -I/usr/local/include/libusb-1.0 -I ../hidapi_pr728/hidapi -c ../hidapi_pr728/libusb/hid.c -o ../hidapi_pr728/libusb/hid.o
cc -I/usr/local/include/libusb-1.0 -I ../hidapi_pr728/hidapi -c hidapitester.c -o hidapitester.o
cc -I/usr/local/include/libusb-1.0 -I ../hidapi_pr728/hidapi ../hidapi_pr728/libusb/hid.o hidapitester.o -o hidapitester -L/usr/local/lib -lusb-1.0 -pthread
mcuee@UbuntuSwift3 ~/build/hid/hidapitester (master)$ mv hidapitester hidapitester_libusb_pr728
mcuee@UbuntuSwift3 ~/build/hid/hidapitester (master)$ sudo ./hidapitester_libusb_pr728 --vidpid 0925:1234 --open --buflen 256 -l 128 --send-output 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128 --read-input
Opening device, vid/pid: 0x0925/0x1234
Writing output report of 128-bytes...wrote 128 bytes:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
Reading 128-byte input report 0, 250 msec timeout...read 0 bytes:
Closing device
HID Report Descriptor.
ReportDscr:
db 06h, 0A0h, 0FFh ; Usage Page (FFA0h, vendor defined)
db 09h, 01h ; Usage (vendor defined)
db 0A1h, 01h ; Collection (Application)
db 09h, 02h ; Usage (vendor defined)
db 0A1h, 00h ; Collection (Physical)
db 06h, 0A1h, 0FFh ; Usage Page (vendor defined)
;; The Input report
db 09h, 03h ; Usage (vendor defined)
db 09h, 04h ; Usage (vendor defined)
db 15h, 80h ; Logical minimum (80h or -128)
db 25h, 7Fh ; Logical maximum (7Fh or 127)
db 35h, 00h ; Physical minimum (0)
db 45h, 0FFh ; Physical maximum (255)
db 75h, 08h ; Report size (8 bits)
db 95h, 80h ; Report count (128 fields)
db 81h, 02h ; Input (data, variable, absolute)
;; The Output report
db 09h, 05h ; Usage (vendor defined)
db 09h, 06h ; Usage (vendor defined)
db 15h, 80h ; Logical minimum (80h or -128)
db 25h, 7Fh ; Logical maximum (7Fh or 127)
db 35h, 00h ; Physical minimum (0)
db 45h, 0FFh ; Physical maximum (255)
db 75h, 08h ; Report size (8 bits)
db 95h, 80h ; Report count (128 fields)
db 91h, 02h ; Output (data, variable, absolute)
db 0C0h ; End Collection (Physical)
db 0C0h ; End Collection (Application)
ReportDscrEnd:
hidtest is okay.
mcuee@UbuntuSwift3 ~/build/hid/hidapi (master)$ sudo ./hidtest/hidtest-libusb
hidapi test/example tool. Compiled with hidapi version 0.15.0, runtime version 0.15.0.
Compile-time version matches runtime version of hidapi.
Device Found
type: 0925 1234
path: 3-2.1:1.0
serial_number: (null)
Manufacturer: CYPRESS
Product: EZ-USB FX2 HID USBHIDIO
Release: 0
Interface: 0
Usage (page): 0x0 (0x0)
Bus type: 1 (USB)
Report Descriptor: (52 bytes)
0x06, 0xa0, 0xff, 0x09, 0x01, 0xa1, 0x01, 0x09, 0x02, 0xa1,
0x00, 0x06, 0xa1, 0xff, 0x09, 0x03, 0x09, 0x04, 0x15, 0x80,
0x25, 0x7f, 0x35, 0x00, 0x45, 0xff, 0x75, 0x08, 0x95, 0x80,
0x81, 0x02, 0x09, 0x05, 0x09, 0x06, 0x15, 0x80, 0x25, 0x7f,
0x35, 0x00, 0x45, 0xff, 0x75, 0x08, 0x95, 0x80, 0x91, 0x02,
0xc0, 0xc0,
unable to open device
@mcuee builds okay, could you please provide test steps, its a long thread :-P
Great.
Test steps: using the normal libusb backend of HIDAPI and this PR.
-
Test with your normal generic USB HID device using hidapi's built-in hidtest and hidapitester. This should be okay.
https://github.com/todbot/hidapitester -
Test with USB Full Speed HID device with >64 Bytes HID report size. This may fail.
-
Test with USB High Speed HID device with >64 Bytes HID report side. This may fail.
I have mentioned my test device in the comments above (EZ-USB FX2LP) but you can use other test device if you can.
FW binary and source codes are here.
Thanks. I finally got my EZ-USB FX2LP dev board from ebay. I've never worked with these before. How do I flash the hex file onto them? This is as far as I got:
stephen@taurus:~$ lsusb | grep FX2
Bus 001 Device 017: ID 04b4:8613 Cypress Semiconductor Corp. CY7C68013 EZ-USB FX2 USB 2.0 Development Kit
stephen@taurus:~$ sudo fxload -D /dev/bus/usb/001/017 -I fx2hid_128bytes/fx2hid.hex -v
microcontroller type: fx
single stage: load on-chip memory
open RAM hexfile image fx2hid_128bytes/fx2hid.hex
stop CPU
write on-chip, addr 0x0600 len 234 (0x00ea)
write on-chip, addr 0x09e5 len 10 (0x000a)
write on-chip, addr 0x0380 len 428 (0x01ac)
write on-chip, addr 0x0080 len 768 (0x0300)
write on-chip, addr 0x0033 len 3 (0x0003)
write on-chip, addr 0x09ff len 7 (0x0007)
write on-chip, addr 0x07b8 len 92 (0x005c)
write on-chip, addr 0x0851 len 59 (0x003b)
write on-chip, addr 0x05fe len 2 (0x0002)
write on-chip, addr 0x0a07 len 4 (0x0004)
write on-chip, addr 0x09ef len 8 (0x0008)
write on-chip, addr 0x09b0 len 18 (0x0012)
write on-chip, addr 0x09f7 len 8 (0x0008)
write on-chip, addr 0x09c2 len 18 (0x0012)
write on-chip, addr 0x0a0b len 6 (0x0006)
write on-chip, addr 0x091d len 40 (0x0028)
write on-chip, addr 0x096a len 24 (0x0018)
write on-chip, addr 0x06ea len 22 (0x0016)
write on-chip, addr 0x099a len 22 (0x0016)
write on-chip, addr 0x088c len 54 (0x0036)
write on-chip, addr 0x0982 len 24 (0x0018)
write on-chip, addr 0x0814 len 61 (0x003d)
write on-chip, addr 0x0a11 len 36 (0x0024)
write on-chip, addr 0x08f1 len 44 (0x002c)
write on-chip, addr 0x08c2 len 47 (0x002f)
write on-chip, addr 0x0945 len 20 (0x0014)
write on-chip, addr 0x05b8 len 70 (0x0046)
write on-chip, addr 0x0959 len 17 (0x0011)
write on-chip, addr 0x0043 len 3 (0x0003)
write on-chip, addr 0x0053 len 3 (0x0003)
write on-chip, addr 0x0700 len 184 (0x00b8)
write on-chip, addr 0x0000 len 3 (0x0003)
write on-chip, addr 0x052c len 12 (0x000c)
write on-chip, addr 0x09d4 len 17 (0x0011)
write on-chip, addr 0x0538 len 128 (0x0080)
write on-chip, addr 0x0a06 len 1 (0x0001)
... WROTE: 2497 bytes, 36 segments, avg 69
reset CPU
No errors, but nothing seems to happen. No hid device shows up & there is no USB re-enumeration. (Fedora 42, Linux kernel 6.14.11)
cederom
commented
Jun 17, 2025
I also ordered EZ-USB FX2LP will arrive next week will report back test results :-)
How do I flash the hex file onto them? This is as far as I got:
stephen@taurus:~$ lsusb | grep FX2 Bus 001 Device 017: ID 04b4:8613 Cypress Semiconductor Corp. CY7C68013 EZ-USB FX2 USB 2.0 Development Kit stephen@taurus:~$ sudo fxload -D /dev/bus/usb/001/017 -I fx2hid_128bytes/fx2hid.hex -v microcontroller type: fx ... No errors, but nothing seems to happen. No hid device shows up & there is no USB re-enumeration. (Fedora 42, Linux kernel 6.14.11)
You are almost there. Just need to add -t fx2lp in the command line to specify the type to be EZ-USB FX2LP.
FX --> EZ-USB FX
FX2 --> EZ-USB FX2
FX2LP --> EZ-USB FX2LP
FX3 --> EZ-USB FX3
[mcuee@CachyN100 fx2hid_128bytes]$ yay -S yay
[mcuee@CachyN100 fx2hid_128bytes]$ lsusb | grep FX2
Bus 003 Device 011: ID 04b4:8613 Cypress Semiconductor Corp. CY7C68013 EZ-USB FX2 USB 2.0 Development Kit
[mcuee@CachyN100 fx2hid_128bytes]$ fxload
no firmware specified!
Usage: fxload [-v] [-V] [-t type] [-d vid:pid] [-p bus,addr] [-s loader] -i firmware
-i <path> -- Firmware to upload
-s <path> -- Second stage loader
-t <type> -- Target type: an21, fx, fx2, fx2lp, fx3
-d <vid:pid> -- Target device, as an USB VID:PID
-p <bus,addr> -- Target device, as a libusb bus number and device address path
-v -- Increase verbosity
-q -- Decrease verbosity (silent mode)
-V -- Print program version
[mcuee@CachyN100 fx2hid_128bytes]$ sudo fxload -t fx2lp -i ./fx2hid.hex
found device 'Cypress EZ-USB FX2LP (68013A/68014A/68015A/68016A)' [04b4:8613] (3,11)
microcontroller type: fx2lp
./fx2hid.hex: type Intel HEX
stop CPU
... WROTE: 2497 bytes, 36 segments, avg 69
reset CPU
[mcuee@CachyN100 fx2hid_128bytes]$ lsusb | grep FX2
Bus 003 Device 014: ID 0925:1234 Lakeview Research EZ-USB FX2 HID USBHIDIO
Fedora 42's fxload (kind of original version of fxload) is a bit different and it does not support FX3. But it does support FX2LP.
mcuee@fedoran100:~/build/cypress/fx2hid_128bytes$ fxload
no device specified!
usage: fxload [-vV] [-l] [-t type] [-D devpath]
[-I firmware_hexfile] [-s loader] [-c config_byte]
[-L link] [-m mode]
... [-D devpath] overrides DEVICE= in env
... device types: one of an21, fx, fx2, fx2lp
... at least one of -I, -L, -m is required
mcuee@fedoran100:~/build/cypress/fx2hid_128bytes$ lsusb | grep FX2
Bus 003 Device 009: ID 04b4:8613 Cypress Semiconductor Corp. CY7C68013 EZ-USB FX2 USB 2.0 Development Kit
mcuee@fedoran100:~/build/cypress/fx2hid_128bytes$ sudo fxload -D /dev/bus/usb/003/009 -t fx2lp -I ./fx2hid.hex -v
microcontroller type: fx2lp
single stage: load on-chip memory
open RAM hexfile image ./fx2hid.hex
stop CPU
write on-chip, addr 0x0600 len 234 (0x00ea)
write on-chip, addr 0x09e5 len 10 (0x000a)
write on-chip, addr 0x0380 len 428 (0x01ac)
write on-chip, addr 0x0080 len 768 (0x0300)
write on-chip, addr 0x0033 len 3 (0x0003)
write on-chip, addr 0x09ff len 7 (0x0007)
write on-chip, addr 0x07b8 len 92 (0x005c)
write on-chip, addr 0x0851 len 59 (0x003b)
write on-chip, addr 0x05fe len 2 (0x0002)
write on-chip, addr 0x0a07 len 4 (0x0004)
write on-chip, addr 0x09ef len 8 (0x0008)
write on-chip, addr 0x09b0 len 18 (0x0012)
write on-chip, addr 0x09f7 len 8 (0x0008)
write on-chip, addr 0x09c2 len 18 (0x0012)
write on-chip, addr 0x0a0b len 6 (0x0006)
write on-chip, addr 0x091d len 40 (0x0028)
write on-chip, addr 0x096a len 24 (0x0018)
write on-chip, addr 0x06ea len 22 (0x0016)
write on-chip, addr 0x099a len 22 (0x0016)
write on-chip, addr 0x088c len 54 (0x0036)
write on-chip, addr 0x0982 len 24 (0x0018)
write on-chip, addr 0x0814 len 61 (0x003d)
write on-chip, addr 0x0a11 len 36 (0x0024)
write on-chip, addr 0x08f1 len 44 (0x002c)
write on-chip, addr 0x08c2 len 47 (0x002f)
write on-chip, addr 0x0945 len 20 (0x0014)
write on-chip, addr 0x05b8 len 70 (0x0046)
write on-chip, addr 0x0959 len 17 (0x0011)
write on-chip, addr 0x0043 len 3 (0x0003)
write on-chip, addr 0x0053 len 3 (0x0003)
write on-chip, addr 0x0700 len 184 (0x00b8)
write on-chip, addr 0x0000 len 3 (0x0003)
write on-chip, addr 0x052c len 12 (0x000c)
write on-chip, addr 0x09d4 len 17 (0x0011)
write on-chip, addr 0x0538 len 128 (0x0080)
write on-chip, addr 0x0a06 len 1 (0x0001)
... WROTE: 2497 bytes, 36 segments, avg 69
reset CPU
mcuee@fedoran100:~/build/cypress/fx2hid_128bytes$ lsusb | grep FX2
Bus 003 Device 010: ID 0925:1234 Lakeview Research EZ-USB FX2 HID USBHIDIO
Interestingly Arch Linux AUR fxload is actually packing libusb project's fxload example.
https://github.com/libusb/libusb/tree/master/examples
https://aur.archlinux.org/packages/fxload
Git Clone URL: https://aur.archlinux.org/fxload.git (read-only, click to copy)
Package Base: fxload
Description: fxload firmware loader. Used with udev or devfs/hotplug.
Upstream URL: http://libusb.info/
Interestingly there is a Fedora request to package libusb's fxload example (probably as libusb-fxload) but it is not implemented in the end.
https://bugzilla.redhat.com/show_bug.cgi?id=1907078
Take note libusb's fxload does not support EEPROM. So the suggeston from @jwrdegoede is good in the above discussion. libusb's fxload example cannot replace the original fxload, it is better to have both packages in Fedora.
Initial commit in libusb project
libusb/libusb@0597533
FX3 support:
libusb/libusb@b74b7f7
@mcuee Thanks, I have it running now. I am experiencing the same things you are. I added a quick printf to libusb/hid.c to check the dev->max_input_report_size. It reports 129:
stephen@taurus:~/src/hidapitester/hidapitester$ git -C ../hidapi-fork/ diff
diff --git i/libusb/hid.c w/libusb/hid.c
index aee5782..05a3370 100644
--- i/libusb/hid.c
+++ w/libusb/hid.c
@@ -1313,6 +1313,7 @@ static int hidapi_initialize_device(hid_device *dev, const struct libusb_interfa
int desc_size = hid_get_report_descriptor_libusb(dev->device_handle, dev->interface, dev->report_descriptor_size, report_descriptor, sizeof(report>
if (desc_size > 0) {
dev->max_input_report_size = get_max_report_size(report_descriptor, desc_size, REPORT_DESCR_INPUT);
+ printf("computed max input report size (rounded): %zu\n", dev->max_input_report_size);
} else {
dev->max_input_report_size = 0;
}
stephen@taurus:~/src/hidapitester/hidapitester$ sudo ./hidapitester --vidpid 0925:1234 --open --buflen 256 -l 129 --send-output 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128 --read-input | grep "computed"
computed max input report size (rounded): 129
So, this PR is computing what I would have expected for the max input report size from the device descriptor. But I notice with hidraw, it is only reading 128 bytes (not 129). So as a quick kludge test, I removed the + 1 from the report size, and it works:
stephen@taurus:~/src/hidapitester/hidapitester$ git -C ../hidapi-fork/ diff
diff --git i/libusb/hid.c w/libusb/hid.c
index aee5782..7d28b17 100644
--- i/libusb/hid.c
+++ w/libusb/hid.c
@@ -356,7 +356,7 @@ static size_t get_max_report_size(uint8_t * report_descriptor, int desc_size, en
} else {
/* report_size is in bits. Determine the total size convert to bytes
(rounded up), and add one byte for the report number. */
- return ((max_size + 7) / 8) + 1;
+ return ((max_size + 7) / 8);
}
}
stephen@taurus:~/src/hidapitester/hidapitester$ sudo ./hidapitester --vidpid 0925:1234 --open --buflen 256 -l 129 --send-output 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128 --read-input
Opening device, vid/pid: 0x0925/0x1234
Writing output report of 129-bytes...wrote 129 bytes:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
80
Reading up to 129-byte input report, 250 msec timeout...read 128 bytes:
01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20
21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40
41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 60
61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F 80
00
Closing device
It looks like the input report doesn't use a report number, so there are only 128 bytes sent. Right now, I'm guessing that the issue is something to do with the fact that 128 is an even multiple of the packet size, so USB isn't sending any short packet.
I've got a cold right now, so my head has been a bit fuzzy. I will have to revisit this at a later time with a clearer head.
tl;dr
It looks like the code in this PR to parse the report descriptor is working, but libusb isn't reading a 128 byte message when it expected a 129-byte one.
Anybody have more insight into this?
Cheers! 🍻
For interupt transfers, which are send without requests from the device to the computer, the ReportId byte ist only prepend to the report data, if the device uses ReportIDs.
Therefore you need to determine from the report descriptor, if the device uses ReportIDs. If anywhere in the report descriptor REPORT_ID occurs, you need, to increase all transfer sizes by one byte for the ReportID.
I think you are close to find the root cause of the issue.
https://github.com/sudobash1/hidapi/blob/libusb_input_size/libusb/hid.c
if (max_size == 0) {
// No matching reports found
return 0;
} else {
/* report_size is in bits. Determine the total size convert to bytes
(rounded up), and add one byte for the report number. */
return ((max_size + 7) / 8) + 1;
}
It is kind of a complicated topic. Please refer to the following discussion.
Good comments in that issue by @JoergAtGithub
0is a placeholder and not a Report ID. This is because the HID class specification specifies "If a Report ID tag was used in the Report descriptor, all reports include a single byte ID prefix. If the Report ID tag was not used, all values are returned in a single report and a prefix ID is not included in that report." and further about the representation in the ReportDescriptor "Set Report ID to 0 (zero) if Report IDs are not used."Therefore only values from 1 to 255 can be Report IDs. The value 0 can be used in the ReportDescriptor, to define that the reports do not contain a ReportID.
Windows implements it as specified in the class specification and adds the Report ID prefix byte only for devices that use Report IDs.
I know that we need to keep backward compatibility, but from a clean API I would expect a clear seperation between address and data in two arguments.
You can also refer to my comment.
That's exactly my point. Having report ID at the beginning of the buffer - means not extra buffer "prepending" on HIDAPI side.
There are two aspects of the issue.
1. Buffer handling -- platform specific.
I think the current codes already do that. For example, Windows codes have already done that, at least for Output Report and Feature Report (first byte of the report is the report ID, 0 when there is no report ID). And I believe all platforms are doing that for Feature report, based on my testing results.
I tend to believe the current codes are already fine in this aspect, i.e, we do not have issues in terms of getting thngs done (the device will receive the right data, host will also receive the right data).
2. Read/Write lentgh reporting
I think this is the issue now. It is not consistent.
Two ways of reporting -- now we are mixing the two. a) lengh of the buffer used by underlying OS driver -- Feature Report (including the 0 byte for device without Report ID). Currently I believe there is no behaviour differences for Feature Report across platforms.
b) length of the data bytes appearing on the USB Bus -- Input Report (not including the 0 byte for device without Report ID). For Windows, this could be due to the way we handle Input Report differently from Output Report and Feature report. Currently I believe there is no behaviour differences for Input Report across platforms.
c) mix of the two ways -- Output Report (Windows always including the 0 byte for device without Report ID, other platforms may or may not including). So Windows may report one byte more than the other platforms or may report the same length as the other platforms. I think we should at least fix this one.
3. Potential Solution for Issue 2. a) If we really want to unify all platforms in terms of the read/write length report mechanism, then I tend to htink Option b is the way to go for all three types of reports. But then it may require some jobs across all platforms and for Output and Feature reports..
b) If we just want to unify the behavior across platforms, then we only need to fix Output Report write length reporting to the user. I tend to think we only need to make Windows consistent with others. So only one platform (Windows) and one report type (Output Report) needs to be fixed.
f56c2d7 to
40132e9
Compare
Thank you @JoergAtGithub and @mcuee. That is clearly the issue. I reviewed the HID spec again and indeed it says:
If a Report ID tag is used anywhere in Report descriptor, all data reports for the device are preceded by a single byte ID field
The Windows behavior when there is no ReportID was tripping me up.
I've pushed a simple commit to address this, and the FX2LP 128-byte report test works fine for me now.
The tests also needed to be fixed for the cases when there is no ReportID (ReportId = 0x00 in the pp_data file).
Am I forgetting anything, or does that finish everything outstanding on this PR (provided CI completes and @mcuee's & @cederom's tests pass)?
@sudobash1 great news! I will be able to provide soonest feedback around Monday sorry if you are ready before and want to go ahead then go ahead :-) I am waiting for the board and will have to see how to set things up but then I will be able to help you in other cases :-)
Is there any sort of bad-usb device out there that could provide us various test cases from hardware point of view (i.e. simulate bad descriptors, strange transfers, etc)?
Other than testing, @Youw will need to review the codes and then approve this PR.
But now the first thing is to fix the CI build -- two builds failed because of the same issue.
[ 37%] Building C object src/libusb/CMakeFiles/hidapi_libusb.dir/hid.c.o
/__w/hidapi/hidapi/hidapisrc/libusb/hid.c: In function ‘get_max_report_size’:
/__w/hidapi/hidapi/hidapisrc/libusb/hid.c:333:29: error: comparison of integer expressions of different signedness: ‘int’ and ‘enum report_descr_type’ [-Werror=sign-compare]
333 | if (key_cmd == report_type) { /* Input / Output / Feature */
| ^~
cc1: all warnings being treated as errors
make[2]: *** [src/libusb/CMakeFiles/hidapi_libusb.dir/build.make:79: src/libusb/CMakeFiles/hidapi_libusb.dir/hid.c.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:206: src/libusb/CMakeFiles/hidapi_libusb.dir/all] Error 2
make: *** [Makefile:[13](https://github.com/libusb/hidapi/actions/runs/15746712859/job/44397056740?pr=728#step:7:14)6: all] Error 2
c06470e to
44328f8
Compare
44328f8 to
e2391b6
Compare
But now the first thing is to fix the CI build -- two builds failed because of the same issue.
Oops. I thought I had fixed that. I guess not. I have pushed e2391b6 to address compiler warnings. It compiles cleanly with -Wall -Wextra on gcc-15 and clang-20 on my Fedora box now. Hopefully all the CI compile now.
Oops. I thought I had fixed that. I guess not. I have pushed e2391b6 to address compiler warnings. It compiles cleanly with
-Wall -Wextraon gcc-15 and clang-20 on my Fedora box now. Hopefully all the CI compile now.
Yes, CI builds are okay now.
Ah, it looks like there a few comments from @Youw that I need to address too. Most significant is probably updating builds.yml (to make sure the tests are enabled).
I'll look through this on Friday.
It would be good if it could clarify in the comments what exactly the "report size" returned by get_max_report_size comprises.
- Here it is only about the InputReports that are sent unrequested by the HID device via interupt transfers (hid_read / hid_read_timeout).
- However, InputReports can also be actively retrieved with hid_get_input_report via ControlTransfers, where the ReportId byte is always included, even if the device does not use ReportIDs (in this case the ReportID-byte contains the value 0).
- And get_max_report_size also supports feature and output reports, where it's different too.
In other code of mine, I introduced the unofficial term payload-size for the report size without the ReportID-byte. There I add 1 depending on the context where it is used. There I've also a boolean that indicates, if the device uses ReportIDs.
First test under Windows -- it seems the reported write/read length is not consistent with native API, one byte higher.
Native Windows HID backend-- wrote 129 bytes, read 128 bytes
libusb backend -- wrote 130 bytes, read 129 bytes
But this is getting close. I will test under Linux and FreeBSD later.
UCRT64 /c/work/libusb/hidapitester
$ ./hidapitester_git_winapi.exe --vidpid 0925:1234 --open --buflen 256 -l 129 --send-output 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128 --read-input
Opening device, vid/pid: 0x0925/0x1234
Writing output report of 129-bytes...wrote 129 bytes:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
80
Reading up to 129-byte input report, 250 msec timeout...read 128 bytes:
01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20
21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40
41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 60
61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F 80
00
Closing device
$ ./hidapitester_pr728_libusb_new.exe --vidpid 0925:1234 --open --buflen 256 -l 129 --send-output 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128 --read-input
Opening device, vid/pid: 0x0925/0x1234
Writing output report of 129-bytes...wrote 130 bytes:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
80
Reading up to 129-byte input report, 250 msec timeout...read 129 bytes:
01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20
21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40
41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 60
61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F 80
00
Closing device
$ ./hidapitester_pr728_winapi_new.exe --vidpid 0925:1234 --open --buflen 256 -l 129 --send-output 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37
,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,10
3,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128 --read-input
Opening device, vid/pid: 0x0925/0x1234
Writing output report of 129-bytes...wrote 129 bytes:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
80
Reading up to 129-byte input report, 250 msec timeout...read 128 bytes:
01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20
21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40
41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 60
61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F 80
00
Closing device
Dirty fix to be able to build under Windows.
PS C:\work\libusb\hidapi_pr728_new> git diff
diff --git a/libusb/hid.c b/libusb/hid.c
index 0f06389..c830479 100644
--- a/libusb/hid.c
+++ b/libusb/hid.c
@@ -34,8 +34,8 @@
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <sys/utsname.h>
+///#include <sys/ioctl.h>
+//#include <sys/utsname.h>
#include <fcntl.h>
#include <wchar.h>
hidapitester Makefile hack and binaries (against hidapi git and this PR, Windows native backend and libusb backend).
Co-authored-by: Ihor Dutchak <ihor.youw@gmail.com>
acolombier
commented
Oct 1, 2025
Some findings when testing this patch (on Android) - It looks like report of MAX_SIZE bytes works great now, however, it seems like smaller reports are either slow to be received or sometime even gets discarded
Sorry for the delay, extremely overloaded, I have the CY7C680 board, working on FreeBSD.
# uname -a
FreeBSD hexagon 14.2-RELEASE-p1 FreeBSD 14.2-RELEASE-p1 GENERIC amd64
# usbconfig
(..)
ugen1.12: <CY7C68013 EZ-USB FX2 USB 2.0 Development Kit Cypress Semiconductor Corp.> at usbus1, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=ON (100mA)
# usbconfig -d 1.12 dump_all_desc
ugen1.12: <CY7C68013 EZ-USB FX2 USB 2.0 Development Kit Cypress Semiconductor Corp.> at usbus1, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=ON (100mA)
bLength = 0x0012
bDescriptorType = 0x0001
bcdUSB = 0x0200
bDeviceClass = 0x00ff <Vendor specific>
bDeviceSubClass = 0x00ff
bDeviceProtocol = 0x00ff
bMaxPacketSize0 = 0x0040
idVendor = 0x04b4
idProduct = 0x8613
bcdDevice = 0xa001
iManufacturer = 0x0000 <no string>
iProduct = 0x0000 <no string>
iSerialNumber = 0x0000 <no string>
bNumConfigurations = 0x0001
Configuration index 0
bLength = 0x0009
bDescriptorType = 0x0002
wTotalLength = 0x00ab
bNumInterfaces = 0x0001
bConfigurationValue = 0x0001
iConfiguration = 0x0000 <no string>
bmAttributes = 0x0080
bMaxPower = 0x0032
Interface 0
bLength = 0x0009
bDescriptorType = 0x0004
bInterfaceNumber = 0x0000
bAlternateSetting = 0x0000
bNumEndpoints = 0x0000
bInterfaceClass = 0x00ff <Vendor specific>
bInterfaceSubClass = 0x00ff
bInterfaceProtocol = 0x00ff
iInterface = 0x0000 <no string>
Interface 0 Alt 1
bLength = 0x0009
bDescriptorType = 0x0004
bInterfaceNumber = 0x0000
bAlternateSetting = 0x0001
bNumEndpoints = 0x0006
bInterfaceClass = 0x00ff <Vendor specific>
bInterfaceSubClass = 0x00ff
bInterfaceProtocol = 0x00ff
iInterface = 0x0000 <no string>
Endpoint 0
bLength = 0x0007
bDescriptorType = 0x0005
bEndpointAddress = 0x0001 <OUT>
bmAttributes = 0x0002 <BULK>
wMaxPacketSize = 0x0200
bInterval = 0x0000
bRefresh = 0x0000
bSynchAddress = 0x0000
Endpoint 1
bLength = 0x0007
bDescriptorType = 0x0005
bEndpointAddress = 0x0081 <IN>
bmAttributes = 0x0002 <BULK>
wMaxPacketSize = 0x0200
bInterval = 0x0000
bRefresh = 0x0000
bSynchAddress = 0x0000
Endpoint 2
bLength = 0x0007
bDescriptorType = 0x0005
bEndpointAddress = 0x0002 <OUT>
bmAttributes = 0x0002 <BULK>
wMaxPacketSize = 0x0200
bInterval = 0x0000
bRefresh = 0x0000
bSynchAddress = 0x0000
Endpoint 3
bLength = 0x0007
bDescriptorType = 0x0005
bEndpointAddress = 0x0004 <OUT>
bmAttributes = 0x0002 <BULK>
wMaxPacketSize = 0x0200
bInterval = 0x0000
bRefresh = 0x0000
bSynchAddress = 0x0000
Endpoint 4
bLength = 0x0007
bDescriptorType = 0x0005
bEndpointAddress = 0x0086 <IN>
bmAttributes = 0x0002 <BULK>
wMaxPacketSize = 0x0200
bInterval = 0x0000
bRefresh = 0x0000
bSynchAddress = 0x0000
Endpoint 5
bLength = 0x0007
bDescriptorType = 0x0005
bEndpointAddress = 0x0088 <IN>
bmAttributes = 0x0002 <BULK>
wMaxPacketSize = 0x0200
bInterval = 0x0000
bRefresh = 0x0000
bSynchAddress = 0x0000
Interface 0 Alt 2
bLength = 0x0009
bDescriptorType = 0x0004
bInterfaceNumber = 0x0000
bAlternateSetting = 0x0002
bNumEndpoints = 0x0006
bInterfaceClass = 0x00ff <Vendor specific>
bInterfaceSubClass = 0x00ff
bInterfaceProtocol = 0x00ff
iInterface = 0x0000 <no string>
Endpoint 0
bLength = 0x0007
bDescriptorType = 0x0005
bEndpointAddress = 0x0001 <OUT>
bmAttributes = 0x0003 <INTERRUPT>
wMaxPacketSize = 0x0040
bInterval = 0x0001
bRefresh = 0x0000
bSynchAddress = 0x0000
Endpoint 1
bLength = 0x0007
bDescriptorType = 0x0005
bEndpointAddress = 0x0081 <IN>
bmAttributes = 0x0003 <INTERRUPT>
wMaxPacketSize = 0x0040
bInterval = 0x0001
bRefresh = 0x0000
bSynchAddress = 0x0000
Endpoint 2
bLength = 0x0007
bDescriptorType = 0x0005
bEndpointAddress = 0x0002 <OUT>
bmAttributes = 0x0003 <INTERRUPT>
wMaxPacketSize = 0x0200
bInterval = 0x0001
bRefresh = 0x0000
bSynchAddress = 0x0000
Endpoint 3
bLength = 0x0007
bDescriptorType = 0x0005
bEndpointAddress = 0x0004 <OUT>
bmAttributes = 0x0002 <BULK>
wMaxPacketSize = 0x0200
bInterval = 0x0000
bRefresh = 0x0000
bSynchAddress = 0x0000
Endpoint 4
bLength = 0x0007
bDescriptorType = 0x0005
bEndpointAddress = 0x0086 <IN>
bmAttributes = 0x0003 <INTERRUPT>
wMaxPacketSize = 0x0200
bInterval = 0x0001
bRefresh = 0x0000
bSynchAddress = 0x0000
Endpoint 5
bLength = 0x0007
bDescriptorType = 0x0005
bEndpointAddress = 0x0088 <IN>
bmAttributes = 0x0002 <BULK>
wMaxPacketSize = 0x0200
bInterval = 0x0000
bRefresh = 0x0000
bSynchAddress = 0x0000
Interface 0 Alt 3
bLength = 0x0009
bDescriptorType = 0x0004
bInterfaceNumber = 0x0000
bAlternateSetting = 0x0003
bNumEndpoints = 0x0006
bInterfaceClass = 0x00ff <Vendor specific>
bInterfaceSubClass = 0x00ff
bInterfaceProtocol = 0x00ff
iInterface = 0x0000 <no string>
Endpoint 0
bLength = 0x0007
bDescriptorType = 0x0005
bEndpointAddress = 0x0001 <OUT>
bmAttributes = 0x0003 <INTERRUPT>
wMaxPacketSize = 0x0040
bInterval = 0x0001
bRefresh = 0x0000
bSynchAddress = 0x0000
Endpoint 1
bLength = 0x0007
bDescriptorType = 0x0005
bEndpointAddress = 0x0081 <IN>
bmAttributes = 0x0003 <INTERRUPT>
wMaxPacketSize = 0x0040
bInterval = 0x0001
bRefresh = 0x0000
bSynchAddress = 0x0000
Endpoint 2
bLength = 0x0007
bDescriptorType = 0x0005
bEndpointAddress = 0x0002 <OUT>
bmAttributes = 0x0001 <ISOCHRONOUS>
wMaxPacketSize = 0x0200
bInterval = 0x0001
bRefresh = 0x0000
bSynchAddress = 0x0000
Endpoint 3
bLength = 0x0007
bDescriptorType = 0x0005
bEndpointAddress = 0x0004 <OUT>
bmAttributes = 0x0002 <BULK>
wMaxPacketSize = 0x0200
bInterval = 0x0000
bRefresh = 0x0000
bSynchAddress = 0x0000
Endpoint 4
bLength = 0x0007
bDescriptorType = 0x0005
bEndpointAddress = 0x0086 <IN>
bmAttributes = 0x0001 <ISOCHRONOUS>
wMaxPacketSize = 0x0200
bInterval = 0x0001
bRefresh = 0x0000
bSynchAddress = 0x0000
Endpoint 5
bLength = 0x0007
bDescriptorType = 0x0005
bEndpointAddress = 0x0088 <IN>
bmAttributes = 0x0002 <BULK>
wMaxPacketSize = 0x0200
bInterval = 0x0000
bRefresh = 0x0000
bSynchAddress = 0x0000
% ./hidapitester --version
hidapitester version: v0.5
hidapi version: 0.16.0
% ./hidapitester --list
0B05/19AF: AsusTek Computer Inc. - AURA LED Controller
534D/2109: MACROSILICON - USB3. 0 capture
0B0E/24CA: - Jabra Link 380
09DA/6406: A4tech - A4tech KB
09DA/6406: A4tech - A4tech KB
046D/C099: Logitech - G502 X
046D/C099: Logitech - G502 X
044F/B106: Thrustmaster - T.Flight Stick X
Had to power on board with button pressed to be able to flash firmware:
# fxload -t fx2 -I fx2hid_128bytes/fx2hid.hex -D vid=04b4,pid=8613 -v
microcontroller type: fx2
single stage: load on-chip memory
open RAM hexfile image fx2hid_128bytes/fx2hid.hex
stop CPU
write on-chip, addr 0x0600 len 234 (0x00ea)
write on-chip, addr 0x09e5 len 10 (0x000a)
write on-chip, addr 0x0380 len 428 (0x01ac)
write on-chip, addr 0x0080 len 768 (0x0300)
write on-chip, addr 0x0033 len 3 (0x0003)
write on-chip, addr 0x09ff len 7 (0x0007)
write on-chip, addr 0x07b8 len 92 (0x005c)
write on-chip, addr 0x0851 len 59 (0x003b)
write on-chip, addr 0x05fe len 2 (0x0002)
write on-chip, addr 0x0a07 len 4 (0x0004)
write on-chip, addr 0x09ef len 8 (0x0008)
write on-chip, addr 0x09b0 len 18 (0x0012)
write on-chip, addr 0x09f7 len 8 (0x0008)
write on-chip, addr 0x09c2 len 18 (0x0012)
write on-chip, addr 0x0a0b len 6 (0x0006)
write on-chip, addr 0x091d len 40 (0x0028)
write on-chip, addr 0x096a len 24 (0x0018)
write on-chip, addr 0x06ea len 22 (0x0016)
write on-chip, addr 0x099a len 22 (0x0016)
write on-chip, addr 0x088c len 54 (0x0036)
write on-chip, addr 0x0982 len 24 (0x0018)
write on-chip, addr 0x0814 len 61 (0x003d)
write on-chip, addr 0x0a11 len 36 (0x0024)
write on-chip, addr 0x08f1 len 44 (0x002c)
write on-chip, addr 0x08c2 len 47 (0x002f)
write on-chip, addr 0x0945 len 20 (0x0014)
write on-chip, addr 0x05b8 len 70 (0x0046)
write on-chip, addr 0x0959 len 17 (0x0011)
write on-chip, addr 0x0043 len 3 (0x0003)
write on-chip, addr 0x0053 len 3 (0x0003)
write on-chip, addr 0x0700 len 184 (0x00b8)
write on-chip, addr 0x0000 len 3 (0x0003)
write on-chip, addr 0x052c len 12 (0x000c)
write on-chip, addr 0x09d4 len 17 (0x0011)
write on-chip, addr 0x0538 len 128 (0x0080)
write on-chip, addr 0x0a06 len 1 (0x0001)
... WROTE: 2497 bytes, 36 segments, avg 69
reset CPU
Now it shows as:
ugen1.12: <CYPRESS EZ-USB FX2 HID USBHIDIO> at usbus1, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=ON (80mA)
% usbconfig -d 1.12 dump_all_desc
ugen1.12: <CYPRESS EZ-USB FX2 HID USBHIDIO> at usbus1, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=ON (80mA)
bLength = 0x0012
bDescriptorType = 0x0001
bcdUSB = 0x0200
bDeviceClass = 0x0000 <Probed by interface class>
bDeviceSubClass = 0x0000
bDeviceProtocol = 0x0000
bMaxPacketSize0 = 0x0040
idVendor = 0x0925
idProduct = 0x1234
bcdDevice = 0x0000
iManufacturer = 0x0001 <CYPRESS>
iProduct = 0x0002 <EZ-USB FX2 HID USBHIDIO>
iSerialNumber = 0x0000 <no string>
bNumConfigurations = 0x0001
Configuration index 0
bLength = 0x0009
bDescriptorType = 0x0002
wTotalLength = 0x0029
bNumInterfaces = 0x0001
bConfigurationValue = 0x0001
iConfiguration = 0x0003 <retrieving string failed>
bmAttributes = 0x0080
bMaxPower = 0x0028
Interface 0
bLength = 0x0009
bDescriptorType = 0x0004
bInterfaceNumber = 0x0000
bAlternateSetting = 0x0000
bNumEndpoints = 0x0002
bInterfaceClass = 0x0003 <HID device>
bInterfaceSubClass = 0x0000
bInterfaceProtocol = 0x0000
iInterface = 0x0000 <no string>
Additional Descriptor
bLength = 0x09
bDescriptorType = 0x21
bDescriptorSubType = 0x10
RAW dump:
0x00 | 0x09, 0x21, 0x10, 0x01, 0x00, 0x01, 0x22, 0x34,
0x08 | 0x00
Endpoint 0
bLength = 0x0007
bDescriptorType = 0x0005
bEndpointAddress = 0x0081 <IN>
bmAttributes = 0x0003 <INTERRUPT>
wMaxPacketSize = 0x0040
bInterval = 0x0005
bRefresh = 0x0000
bSynchAddress = 0x0000
Endpoint 1
bLength = 0x0007
bDescriptorType = 0x0005
bEndpointAddress = 0x0001 <OUT>
bmAttributes = 0x0003 <INTERRUPT>
wMaxPacketSize = 0x0040
bInterval = 0x0005
bRefresh = 0x0000
bSynchAddress = 0x0000
% ./hidapitester --list
0B05/19AF: AsusTek Computer Inc. - AURA LED Controller
534D/2109: MACROSILICON - USB3. 0 capture
0B0E/24CA: - Jabra Link 380
09DA/6406: A4tech - A4tech KB
09DA/6406: A4tech - A4tech KB
044F/B106: Thrustmaster - T.Flight Stick X
046D/C099: Logitech - G502 X
046D/C099: Logitech - G502 X
0925/1234: CYPRESS - EZ-USB FX2 HID USBHIDIO
% ./hidapitester --vidpid 0925:1234 --open --buflen 256 -l 129 --send-output 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128 --read-input
Opening device, vid/pid: 0x0925/0x1234
Writing output report of 129-bytes...wrote 129 bytes:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
80
Reading up to 129-byte input report, 250 msec timeout...read 64 bytes:
68 89 37 FE 79 58 09 E7 88 CE 3F 33 9D CF B7 7D 95 C7 8F AD 2E 84 97 EF FF 71 FC 3F F5 D7 70 6E
9E 93 5E FE F8 DF BA 74 DE B7 AB 6F 9D 3F AF BB 5B FE BF CF BE FB EE 03 B7 EF 8A 0C B3 BB E7 6A
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00
Closing device
% ./hidapitester --vidpid 0925:1234 --open --buflen 256 -l 129 --send-output 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128 --read-input
Opening device, vid/pid: 0x0925/0x1234
Writing output report of 129-bytes...wrote 129 bytes:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
80
Reading up to 129-byte input report, 250 msec timeout...read 64 bytes:
41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 60
61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F 80
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00
Closing device
% ./hidapitester --vidpid 0925:1234 --open --buflen 256 -l 129 --send-output 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37
Opening device, vid/pid: 0x0925/0x1234
Writing output report of 129-bytes...wrote 129 bytes:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
20 21 22 23 24 25 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00
Closing device
Uh oh!
There was an error while loading. Please reload this page.
Currently the libusb version of hidapi simply reads up to
wMaxPacketSizebytes as the report. This is problematic when reports are longer thanwMaxPacketSize. The current behavior will split that report up.The proper solution is to review the report descriptor to find the longest input report and use that as the length of the
libusb_fill_interrupt_transferbuffer. (Note: there is no need to manually get multiple USB packets and concatenate them together to fit the report length. USB already handles that for us.)This will still work for HID devices when some input reports are shorter than others. The HID device will just send a short packet terminator and libusb will give us the shorter buffer.
The substance of these changes is in the
get_max_input_sizemethod. It uses the same basic report descriptor parsing asget_usage. I considered changing the code so that there could be shared parsing code, but I decided that was overkill for this.Fixes #274