Skip to content
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

libusb: fix using LIBUSB_DT_REPORT for HID Report Descriptor #438

Closed
Youw opened this issue Aug 13, 2022 · 16 comments · Fixed by #444
Closed

libusb: fix using LIBUSB_DT_REPORT for HID Report Descriptor #438

Youw opened this issue Aug 13, 2022 · 16 comments · Fixed by #444
Labels
enhancement New feature or request libusb Related to libusb backend

Comments

@Youw
Copy link
Member

Youw commented Aug 13, 2022

Sometime it is required to get/parse the HID Report Descriptor, e.g.:

Unfortunately not all devices have LIBUSB_DT_REPORT request implemented, even though raw USB descriptors contain the HID Report Descriptor.
UPD: probably the way HIDAPI uses LIBUSB_DT_REPORT is not correct.

Instead of using LIBUSB_DT_REPORT there are several possible alternatives:

  • get/parse HID interface descriptor from libusb (need to check if this is possible);
    UPD: it only contains HID descriptor, and not the HID Report descriptor;
  • read/parse descriptors from sysfs - linux-specific solution;
    UPD: same limitation as with libusb descriptors - HID Report descriptor is not part of the USB descriptors.
@Youw Youw added enhancement New feature or request libusb Related to libusb backend labels Aug 13, 2022
@Youw
Copy link
Member Author

Youw commented Aug 13, 2022

get/parse HID interface descriptor from libusb (need to check if this is possible);

From HID USB specification:

The HID class uses the standard request Get_Descriptor as described in the USB
Specification. When a Get_Descriptor(Configuration) request is issued, it
returns the Configuration descriptor, all Interface descriptors, all Endpoint
descriptors, and the HID descriptor for each interface. It shall not return the
String descriptor, HID Report descriptor or any of the optional HID class
descriptors.

It shall not return ... HID Report descriptor ... .


Tried this with libusb: true - with my devices the interface descriptor contains the HID descriptor, but it doesn't include the HID Report descriptor.


Looks like it is not an option(

@JoergAtGithub
Copy link
Contributor

I wonder, what

not all devices have LIBUSB_DT_REPORT request implemented

means. What type of error do you get, if you try to gather the Report Descriptor?

Do you know, how operating system drivers of Windows or hidraw request the Report Descriptor from these devices?

I guess that usbutils (lsusb & usbhid-dump) fails for these devices too?

@Youw
Copy link
Member Author

Youw commented Aug 14, 2022

What type of error do you get, if you try to gather the Report Descriptor?

libusb_control_transfer() for getting the HID report descriptor failed with -1: LIBUSB_ERROR_IO


Maybe my assumption about LIBUSB_DT_REPORT not being supported by the device is not correct - that was my itinial thought.


Do you know, how operating system drivers of Windows or hidraw request the Report Descriptor from these devices?

That's what I intent to find out. Not the first time I'll be going thru hidraw sources.

@Youw
Copy link
Member Author

Youw commented Aug 14, 2022

I guess that usbutils (lsusb & usbhid-dump) fails for these devices too?

sudo lsusb -v gives me a similar thing I got with libusb:

Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        2
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface              0 
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.11
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength      93
         Report Descriptors: 
           ** UNAVAILABLE **

Interestingly, sudo usbhid-dump actually gives me what I need:

001:018:002:DESCRIPTOR         1660470384.085296
 06 00 FF 09 01 A1 01 85 10 95 06 75 08 15 00 26
 FF 00 09 01 81 00 09 01 91 00 C0 06 00 FF 09 02
 A1 01 85 11 95 13 75 08 15 00 26 FF 00 09 02 81
 00 09 02 91 00 C0 06 00 FF 09 04 A1 01 85 20 95
 0E 75 08 15 00 26 FF 00 09 41 81 00 09 41 91 00
 85 21 95 1F 09 42 81 00 09 42 91 00 C0

001:018:001:DESCRIPTOR         1660470384.087046
 05 01 09 02 A1 01 85 02 09 01 A1 00 95 10 75 01
 15 00 25 01 05 09 19 01 29 10 81 02 95 02 75 0C
 16 01 F8 26 FF 07 05 01 09 30 09 31 81 06 95 01
 75 08 15 81 25 7F 09 38 81 06 95 01 05 0C 0A 38
 02 81 06 C0 C0 05 0C 09 01 A1 01 85 03 95 02 75
 10 15 01 26 FF 02 19 01 2A FF 02 81 00 C0 05 01
 09 80 A1 01 85 04 95 01 75 02 15 01 25 03 09 82
 09 81 09 83 81 00 75 06 81 03 C0 06 BC FF 09 88
 A1 01 85 08 95 01 75 08 15 01 26 FF 00 19 01 29
 FF 81 00 C0

001:018:000:DESCRIPTOR         1660470384.088021
 05 01 09 06 A1 01 95 08 75 01 15 00 25 01 05 07
 19 E0 29 E7 81 02 81 03 95 05 05 08 19 01 29 05
 91 02 95 01 75 03 91 01 95 06 75 08 15 00 26 FF
 00 05 07 19 00 2A FF 00 81 00 C0

Maybe I just need to poke around its sources.

@JoergAtGithub
Copy link
Contributor

Both are based on libusb. I noticed, that usbhid-dump determines the size of the Report-Descriptor before reading it.

@Youw
Copy link
Member Author

Youw commented Aug 14, 2022

Hm, that information is available from Interface descriptor. Maybe that's what is missing to make it wokr.
I'll try it (passing the actual Report descriptors size) later today.

@Youw Youw changed the title libusb: avoid sending LIBUSB_DT_REPORT for HID Report Descriptor libusb: fix using LIBUSB_DT_REPORT for HID Report Descriptor Aug 14, 2022
@Youw
Copy link
Member Author

Youw commented Aug 14, 2022

Found this in kernel/hidusb driver.
Looks like it uses the LIBUSB_DT_REPORT but it specifically requests the size as per HID descriptor.

@JoergAtGithub
Copy link
Contributor

@Youw
Copy link
Member Author

Youw commented Aug 14, 2022

Yeah, that's basically the same thing.

@Youw
Copy link
Member Author

Youw commented Aug 14, 2022

I made an attempt to fix it here: https://github.com/libusb/hidapi/tree/libusb_report_descriptor_read
But it still doesn't wokr as expected.

I'll be able to check it some time later.

@mcuee
Copy link
Member

mcuee commented Aug 15, 2022

@Youw

libusb xusb may not handle atill the situations but it works to list the HID report descriptors (only for interface 0).
https://github.com/libusb/libusb/blob/master/examples/xusb.c#L609

Example run against teensy 2.0 RawHID device.


mcuee@UbuntuSwift3:~/build/libusb$ ./examples/xusb -s 16c0:0486
Using libusb v1.0.26.11742

Opening device 16C0:0486...

Reading device descriptor:
            length: 18
      device class: 0
               S/N: 0
           VID:PID: 16C0:0486
         bcdDevice: 0102
   iMan:iProd:iSer: 0:1:0
          nb confs: 1

Reading BOS descriptor: no descriptor

Reading first configuration descriptor:
              total length: 73
         descriptor length: 9
             nb interfaces: 2
              interface[0]: id = 0
interface[0].altsetting[0]: num endpoints = 2
   Class.SubClass.Protocol: 03.00.00
       endpoint[0].address: 83
           max packet size: 0040
          polling interval: 01
       endpoint[1].address: 04
           max packet size: 0040
          polling interval: 01
              interface[1]: id = 1
interface[1].altsetting[0]: num endpoints = 2
   Class.SubClass.Protocol: 03.00.00
       endpoint[0].address: 81
           max packet size: 0040
          polling interval: 01
       endpoint[1].address: 02
           max packet size: 0020
          polling interval: 02

Kernel driver attached for interface 0: 1

Claiming interface 0...

Kernel driver attached for interface 1: 1

Claiming interface 1...

Reading string descriptors:
   String (0x01): "Teensyduino RawHID Device"

Reading OS string descriptor: no descriptor

Reading HID Report Descriptors:

  00000000  06 ab ff 0a 00 02 a1 01 75 08 15 00 26 ff 00 95  ........u...&...
  00000010  40 09 01 81 02 95 40 09 02 91 02 c0              @.....@.....

Skipping Feature Report readout (None detected)

Skipping Input Report readout (None detected)

Releasing interface 0...
Releasing interface 1...
Closing device...

mcuee@UbuntuSwift3:~/build/libusb$ lsusb
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 003 Device 004: ID 1c7a:0575 LighTuning Technology Inc. EgisTec EH575
Bus 003 Device 003: ID 04f2:b6dd Chicony Electronics Co., Ltd HD User Facing
Bus 003 Device 002: ID 046d:c52b Logitech, Inc. Unifying Receiver
Bus 003 Device 005: ID 8087:0026 Intel Corp. 
Bus 003 Device 007: ID 16c0:0486 Van Ooijen Technische Informatica Teensyduino RawHID
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub


cuee@UbuntuSwift3:~/build/libusb$ usbhid-dump 
003:002:002:DESCRIPTOR         1660573892.550506
 06 00 FF 09 01 A1 01 85 10 95 06 75 08 15 00 26
 FF 00 09 01 81 00 09 01 91 00 C0 06 00 FF 09 02
 A1 01 85 11 95 13 75 08 15 00 26 FF 00 09 02 81
 00 09 02 91 00 C0 06 00 FF 09 04 A1 01 85 20 95
 0E 75 08 15 00 26 FF 00 09 41 81 00 09 41 91 00
 85 21 95 1F 09 42 81 00 09 42 91 00 C0

003:002:001:DESCRIPTOR         1660573892.552062
 05 01 09 02 A1 01 85 02 09 01 A1 00 95 10 75 01
 15 00 25 01 05 09 19 01 29 10 81 02 95 02 75 0C
 16 01 F8 26 FF 07 05 01 09 30 09 31 81 06 95 01
 75 08 15 81 25 7F 09 38 81 06 95 01 05 0C 0A 38
 02 81 06 C0 C0 05 0C 09 01 A1 01 85 03 95 02 75
 10 15 01 26 FF 02 19 01 2A FF 02 81 00 C0 05 01
 09 80 A1 01 85 04 95 01 75 02 15 01 25 03 09 82
 09 81 09 83 81 00 75 06 81 03 C0 06 BC FF 09 88
 A1 01 85 08 95 01 75 08 15 01 26 FF 00 19 01 29
 FF 81 00 C0

003:002:000:DESCRIPTOR         1660573892.552905
 05 01 09 06 A1 01 95 08 75 01 15 00 25 01 05 07
 19 E0 29 E7 81 02 81 03 95 05 05 08 19 01 29 05
 91 02 95 01 75 03 91 01 95 06 75 08 15 00 26 FF
 00 05 07 19 00 2A FF 00 81 00 C0

003:007:001:DESCRIPTOR         1660573892.553157
 06 C9 FF 09 04 A1 5C 75 08 15 00 26 FF 00 95 40
 09 75 81 02 95 20 09 76 91 02 95 04 09 76 B1 02
 C0

003:007:000:DESCRIPTOR         1660573892.553364
 06 AB FF 0A 00 02 A1 01 75 08 15 00 26 FF 00 95
 40 09 01 81 02 95 40 09 02 91 02 C0

mcuee@UbuntuSwift3:~/build/libusb$ ./examples/xusb -s 046d:c52b
Using libusb v1.0.26.11742

Opening device 046D:C52B...

Reading device descriptor:
            length: 18
      device class: 0
               S/N: 0
           VID:PID: 046D:C52B
         bcdDevice: 1203
   iMan:iProd:iSer: 1:2:0
          nb confs: 1

Reading BOS descriptor: no descriptor

Reading first configuration descriptor:
              total length: 84
         descriptor length: 9
             nb interfaces: 3
              interface[0]: id = 0
interface[0].altsetting[0]: num endpoints = 1
   Class.SubClass.Protocol: 03.01.01
       endpoint[0].address: 81
           max packet size: 0008
          polling interval: 08
              interface[1]: id = 1
interface[1].altsetting[0]: num endpoints = 1
   Class.SubClass.Protocol: 03.01.02
       endpoint[0].address: 82
           max packet size: 0008
          polling interval: 02
              interface[2]: id = 2
interface[2].altsetting[0]: num endpoints = 1
   Class.SubClass.Protocol: 03.00.00
       endpoint[0].address: 83
           max packet size: 0020
          polling interval: 02

Kernel driver attached for interface 0: 1

Claiming interface 0...

Kernel driver attached for interface 1: 1

Claiming interface 1...

Kernel driver attached for interface 2: 1

Claiming interface 2...

Reading string descriptors:
   String (0x01): "Logitech"
   String (0x02): "USB Receiver"

Reading OS string descriptor: no descriptor

Reading HID Report Descriptors:

  00000000  05 01 09 06 a1 01 95 08 75 01 15 00 25 01 05 07  ........u...%...
  00000010  19 e0 29 e7 81 02 81 03 95 05 05 08 19 01 29 05  ..)...........).
  00000020  91 02 95 01 75 03 91 01 95 06 75 08 15 00 26 ff  ....u.....u...&.
  00000030  00 05 07 19 00 2a ff 00 81 00 c0                 .....*.....

Skipping Feature Report readout (None detected)

Reading Input Report (length 8)...

  00000000  00 00 00 00 00 00 00 00                          ........

Testing interrupt read using endpoint 81...
   Operation timed out

Releasing interface 0...
Releasing interface 1...
Releasing interface 2...
Closing device...


@Youw
Copy link
Member Author

Youw commented Aug 15, 2022

Ah, sorry I didn't explicitly mention it here regarding:

But it still doesn't wokr as expected.
I'll be able to check it some time later.

#444 completely resolves the issue now.
The problem was about not sending the correct libusb request to get the HID Report descriptor.

@Youw
Copy link
Member Author

Youw commented Aug 15, 2022

BTW: in the xusb example here - there is a bug: wIndex parameter is set to 0, which means the request will work only if the USB Interface №0 is a HID Interface.
wIndex has to be set to the HID Interface index.

@mcuee
Copy link
Member

mcuee commented Aug 16, 2022

BTW: in the xusb example here - there is a bug: wIndex parameter is set to 0, which means the request will work only if the USB Interface №0 is a HID Interface. wIndex has to be set to the HID Interface index.

Yes that example is only meant for the particular HID device in reality :
// Microsoft Sidewinder Precision Pro Joystick - 1 HID interface
(https://github.com/libusb/libusb/blob/b88f1441856a9ba481dc40c8c6d0415d8556514a/examples/xusb.c#L1054)

@Youw
Copy link
Member Author

Youw commented Aug 16, 2022

Explicitly naming the parameter value as a variable would make a better sample. Just a thought.

@mcuee
Copy link
Member

mcuee commented Aug 16, 2022

#444 completely resolves the issue now. The problem was about not sending the correct libusb request to get the HID Report descriptor.

Thanks. Yes I think this issue is sorted. You can also close #443 as there is a working work-around now.

@Youw Youw closed this as completed in #444 Aug 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request libusb Related to libusb backend
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants