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

HID reports of more than 64 bytes and libusb backend #274

Open
JoergAtGithub opened this issue May 15, 2021 · 121 comments
Open

HID reports of more than 64 bytes and libusb backend #274

JoergAtGithub opened this issue May 15, 2021 · 121 comments
Labels
bug Something isn't working documentation Improvements or additions to documentation libusb Related to libusb backend

Comments

@JoergAtGithub
Copy link
Contributor

JoergAtGithub commented May 15, 2021

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:

  • Can the speed or max. package size be determined using HIDAPI to report an error about the USB misconfiguration?
  • Can the application tell the device somehow to switch to USB High-Speed mode?
  • Can HIDAPI check, if a report descriptor contains report sizes of more than 64Bytes for a device in Full-Speed mode?
Windows-Output:
Debug [Controller]: Traktor Kontrol S4 MK3 HID A79A_3: t:92905 ms, 79 bytes:
02 6A 08 00 00 00 00 03 07 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

Linux-Output (libusb):
Debug [Controller]: Traktor Kontrol S4 MK3 A79A_3: t:15558 ms, 64 bytes:
02 6E 08 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

Debug [Controller]: Traktor Kontrol S4 MK3 A79A_3: t:15559 ms, 15 bytes:
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

This is the lsusb output:
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        3
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface             11 Traktor Kontrol S4 MK3 HID
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.10
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength     673
         Report Descriptors: 
           ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               2
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        4
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass    189 
      bInterfaceProtocol      0 
      iInterface             12 Traktor Kontrol S4 MK3 BD
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x03  EP 3 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               1
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        5
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass       254 Application Specific Interface
      bInterfaceSubClass      1 Device Firmware Update
      bInterfaceProtocol      1 
      iInterface             10 Traktor Kontrol S4 MK3 DFU
      Device Firmware Upgrade Interface Descriptor:
        bLength                             9
        bDescriptorType                    33
        bmAttributes                        7
          Will Not Detach
          Manifestation Tolerant
          Upload Supported
          Download Supported
        wDetachTimeout                    250 milliseconds
        wTransferSize                      64 bytes
        bcdDFUVersion                   1.10
Device Qualifier (for other device speed):
  bLength                10
  bDescriptorType         6
  bcdUSB               2.00
  bDeviceClass            0 
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        64
  bNumConfigurations      1
@Youw
Copy link
Member

Youw commented May 15, 2021

Do I understand it correctly that the problem on Linux with libusb backend?

@Youw Youw added the libusb Related to libusb backend label May 15, 2021
@JoergAtGithub
Copy link
Contributor Author

Yes, it's reported by two independend Linux libusb users. I'm myself just relaying this, since I've neither the device nor Linux.

@Youw
Copy link
Member

Youw commented May 15, 2021

How could a cross platform application using HIDAPI handle this:

Can the speed or max. package size be determined using HIDAPI to report an error about the USB misconfiguration?

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.
How would a client application know what it should expect (unless it is a known device, expected to run in a specific mode)?

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.

Can the application tell the device somehow to switch to USB High-Speed mode?

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.

Can HIDAPI check, if a report descriptor contains report sizes of more than 64Bytes for a device in Full-Speed mode?

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.
If device's FW can be modified, I'd rather suggest to make an API and ask the device in which USB mode is it running.

@JoergAtGithub
Copy link
Contributor Author

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.
Mixxx works with this device on MacOS and even on a Windows 10 VM under Linux, but not if under Linux with libusb backend.

@Youw
Copy link
Member

Youw commented May 15, 2021

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.

@JoergAtGithub
Copy link
Contributor Author

hidraw is not yet tried. Further investigation is needed to understand this specific case.
But I think this is a general issue which could also occur with other HID devices, maybe also on other operating systems. Therfore it would be better to detect this somehow as error in hid_open instead of adding a check on application level.

@Youw
Copy link
Member

Youw commented May 15, 2021

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.
HID protocol is not design to send large packets in a first place. It is specifically designed to send many small packets (2/4/8/16 bytes of data), and that's what is being done by all devices I've seen. I've had one device that has been using 64 bytes data packets, and that was considered an edge case.
For ceses when large data packets needs to be send between host and device, usually different protocols are used, like USB BULK.

@Youw
Copy link
Member

Youw commented May 15, 2021

Can HIDAPI check, if a report descriptor contains report sizes of more than 64Bytes for a device in Full-Speed mode?

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.
If someone is going to develop a patch to detect such a thing for libusb backend, I don't see strong reasons not to accept it.

@Be-ing
Copy link
Contributor

Be-ing commented May 17, 2021

I have a Native Instruments Traktor Kontrol S4 Mk3, one of the affected devices. Here is the output of lsusb -t for the device:

    |__ Port 7: Dev 25, If 0, Class=Hub, Driver=hub/4p, 480M
        |__ Port 1: Dev 29, If 0, Class=Hub, Driver=hub/2p, 480M
            |__ Port 1: Dev 30, If 4, Class=Vendor Specific Class, Driver=, 480M
            |__ Port 1: Dev 30, If 2, Class=Audio, Driver=snd-usb-audio, 480M
            |__ Port 1: Dev 30, If 0, Class=Audio, Driver=snd-usb-audio, 480M
            |__ Port 1: Dev 30, If 5, Class=Application Specific Interface, Driver=, 480M
            |__ Port 1: Dev 30, If 3, Class=Human Interface Device, Driver=usbhid, 480M
            |__ Port 1: Dev 30, If 1, Class=Audio, Driver=snd-usb-audio, 480M

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.

@Youw
Copy link
Member

Youw commented May 17, 2021

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 lsusb -t too?

@Be-ing
Copy link
Contributor

Be-ing commented May 17, 2021

It seems that libusb can only read a device's speed with libusb_get_device_speed() but has no API to set the speed.

@Be-ing
Copy link
Contributor

Be-ing commented May 17, 2021

Here is the lsusb -v output with formatting... the wMaxPacketSize 0x0040 1x 64 bytes for the HID endpoint is interesting...

Bus 001 Device 032: ID 17cc:1720 Native Instruments Traktor Kontrol S4 MK3
Couldn't open device, some information will be missing
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass          239 Miscellaneous Device
  bDeviceSubClass         2 
  bDeviceProtocol         1 Interface Association
  bMaxPacketSize0        64
  idVendor           0x17cc Native Instruments
  idProduct          0x1720 
  bcdDevice            0.60
  iManufacturer           1 Native Instruments
  iProduct                3 Traktor Kontrol S4 MK3
  iSerial                 2 69DDA7A8
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x0124
    bNumInterfaces          6
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0xc0
      Self Powered
    MaxPower                0mA
    Interface Association:
      bLength                 8
      bDescriptorType        11
      bFirstInterface         0
      bInterfaceCount         3
      bFunctionClass          1 Audio
      bFunctionSubClass       0 
      bFunctionProtocol      32 
      iFunction               0 
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass         1 Audio
      bInterfaceSubClass      1 Control Device
      bInterfaceProtocol     32 
      iInterface              3 
      AudioControl Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      1 (HEADER)
        bcdADC               2.00
        bCategory               8
        wTotalLength       0x0053
        bmControls           0x00
      AudioControl Interface Descriptor:
        bLength                 8
        bDescriptorType        36
        bDescriptorSubtype     10 (CLOCK_SOURCE)
        bClockID               41
        bmAttributes            3 Internal programmable clock 
        bmControls           0x07
          Clock Frequency Control (read/write)
          Clock Validity Control (read-only)
        bAssocTerminal          0
        iClockSource            9 
      AudioControl Interface Descriptor:
        bLength                 8
        bDescriptorType        36
        bDescriptorSubtype     11 (CLOCK_SELECTOR)
        bClockID               40
        bNrInPins               1
        baCSourceID(0)         41
        bmControls           0x03
          Clock Selector Control (read/write)
        iClockSelector          8 
      AudioControl Interface Descriptor:
        bLength                17
        bDescriptorType        36
        bDescriptorSubtype      2 (INPUT_TERMINAL)
        bTerminalID             2
        wTerminalType      0x0101 USB Streaming
        bAssocTerminal          0
        bCSourceID             40
        bNrChannels             4
        bmChannelConfig    0x00000000
        iChannelNames          13 
        bmControls         0x0000
        iTerminal               6 
      AudioControl Interface Descriptor:
        bLength                12
        bDescriptorType        36
        bDescriptorSubtype      3 (OUTPUT_TERMINAL)
        bTerminalID            20
        wTerminalType      0x0301 Speaker
        bAssocTerminal          0
        bSourceID               2
        bCSourceID             40
        bmControls         0x0000
        iTerminal               0 
      AudioControl Interface Descriptor:
        bLength                17
        bDescriptorType        36
        bDescriptorSubtype      2 (INPUT_TERMINAL)
        bTerminalID             1
        wTerminalType      0x0201 Microphone
        bAssocTerminal          0
        bCSourceID             40
        bNrChannels             8
        bmChannelConfig    0x00000000
        iChannelNames          17 
        bmControls         0x0000
        iTerminal               0 
      AudioControl Interface Descriptor:
        bLength                12
        bDescriptorType        36
        bDescriptorSubtype      3 (OUTPUT_TERMINAL)
        bTerminalID            22
        wTerminalType      0x0101 USB Streaming
        bAssocTerminal          0
        bSourceID               1
        bCSourceID             40
        bmControls         0x0000
        iTerminal               7 
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass         1 Audio
      bInterfaceSubClass      2 Streaming
      bInterfaceProtocol     32 
      iInterface              4 
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       1
      bNumEndpoints           2
      bInterfaceClass         1 Audio
      bInterfaceSubClass      2 Streaming
      bInterfaceProtocol     32 
      iInterface              4 
      AudioStreaming Interface Descriptor:
        bLength                16
        bDescriptorType        36
        bDescriptorSubtype      1 (AS_GENERAL)
        bTerminalLink           2
        bmControls           0x00
        bFormatType             1
        bmFormats          0x00000001
          PCM
        bNrChannels             4
        bmChannelConfig    0x00000000
        iChannelNames          13 
      AudioStreaming Interface Descriptor:
        bLength                 6
        bDescriptorType        36
        bDescriptorSubtype      2 (FORMAT_TYPE)
        bFormatType             1 (FORMAT_TYPE_I)
        bSubslotSize            4
        bBitResolution         24
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            5
          Transfer Type            Isochronous
          Synch Type               Asynchronous
          Usage Type               Data
        wMaxPacketSize     0x00d0  1x 208 bytes
        bInterval               1
        AudioStreaming Endpoint Descriptor:
          bLength                 8
          bDescriptorType        37
          bDescriptorSubtype      1 (EP_GENERAL)
          bmAttributes         0x00
          bmControls           0x00
          bLockDelayUnits         2 Decoded PCM samples
          wLockDelay         0x0008
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes           17
          Transfer Type            Isochronous
          Synch Type               None
          Usage Type               Feedback
        wMaxPacketSize     0x0004  1x 4 bytes
        bInterval               4
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        2
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass         1 Audio
      bInterfaceSubClass      2 Streaming
      bInterfaceProtocol     32 
      iInterface              5 
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        2
      bAlternateSetting       1
      bNumEndpoints           1
      bInterfaceClass         1 Audio
      bInterfaceSubClass      2 Streaming
      bInterfaceProtocol     32 
      iInterface              5 
      AudioStreaming Interface Descriptor:
        bLength                16
        bDescriptorType        36
        bDescriptorSubtype      1 (AS_GENERAL)
        bTerminalLink          22
        bmControls           0x00
        bFormatType             1
        bmFormats          0x00000001
          PCM
        bNrChannels             8
        bmChannelConfig    0x00000000
        iChannelNames          17 
      AudioStreaming Interface Descriptor:
        bLength                 6
        bDescriptorType        36
        bDescriptorSubtype      2 (FORMAT_TYPE)
        bFormatType             1 (FORMAT_TYPE_I)
        bSubslotSize            4
        bBitResolution         24
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            5
          Transfer Type            Isochronous
          Synch Type               Asynchronous
          Usage Type               Data
        wMaxPacketSize     0x01a0  1x 416 bytes
        bInterval               1
        AudioStreaming Endpoint Descriptor:
          bLength                 8
          bDescriptorType        37
          bDescriptorSubtype      1 (EP_GENERAL)
          bmAttributes         0x00
          bmControls           0x00
          bLockDelayUnits         2 Decoded PCM samples
          wLockDelay         0x0008
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        3
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface             11 
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.10
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength     673
         Report Descriptors: 
           ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               2
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        4
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass    189 
      bInterfaceProtocol      0 
      iInterface             12 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x03  EP 3 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               1
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        5
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass       254 Application Specific Interface
      bInterfaceSubClass      1 Device Firmware Update
      bInterfaceProtocol      1 
      iInterface             10 
      Device Firmware Upgrade Interface Descriptor:
        bLength                             9
        bDescriptorType                    33
        bmAttributes                        7
          Will Not Detach
          Manifestation Tolerant
          Upload Supported
          Download Supported
        wDetachTimeout                    250 milliseconds
        wTransferSize                      64 bytes
        bcdDFUVersion                   1.10

@Be-ing
Copy link
Contributor

Be-ing commented May 17, 2021

How do I tell hidapi to use the hidraw backend instead of libusb? I don't see any documentation for this. ./configure --help has no information. It looks like make builds both hidraw and libusb. If I uninstall the libusbx-devel package on Fedora, hidapi fails to build.

@Youw
Copy link
Member

Youw commented May 17, 2021

You can still have both hidraw and libusb backends of hidapi installed and use either one of them.
Technically those are two different libraries (even though with identical public API/ABI).
If you want to switch the backend for you application, you need to link against libhidapi-hidraw instead of libhidapi-libusb.

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.

@Be-ing
Copy link
Contributor

Be-ing commented May 17, 2021

I hacked the application build system to use hidraw instead of libusb. Now it fails to open the device, both with hid_open_path and hid_open without any error message from hidapi indicating the problem...

debug [Controller] CDBG Opening HID device Traktor Kontrol S4 MK3 A7A8_3 by HID path /dev/hidraw3
debug [Controller] CDBG Failed. Trying to open with make, model & serial no: 6092 5920 69DDA7A8
warning [Controller] Unable to open specific HID device "Traktor Kontrol S4 MK3 A7A8_3" Trying now with just make and model. (This may only open the first of multiple identical devices.)
warning [Controller] Unable to open HID device "Traktor Kontrol S4 MK3 A7A8_3"
debug [Controller] Controller polling stopped.

Here is the application code.

@Be-ing
Copy link
Contributor

Be-ing commented May 17, 2021

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?

@JoergAtGithub
Copy link
Contributor Author

@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:

lsusb -D /dev/bus/usb/005/006

Device: ID 17cc:1723 Native Instruments Traktor Kontrol S4 MK3 Hub
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            9 Hub
  bDeviceSubClass         0 
  bDeviceProtocol         2 TT per port
  bMaxPacketSize0        64
  idVendor           0x17cc Native Instruments
  idProduct          0x1723 
  bcdDevice            0.01
  iManufacturer           1 Native Instruments
  iProduct                2 Traktor Kontrol S4 MK3 Hub
  iSerial                 3 7AB2CCAD
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x0029
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0xe0
      Self Powered
      Remote Wakeup
    MaxPower                0mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         9 Hub
      bInterfaceSubClass      0 
      bInterfaceProtocol      1 Single TT
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0001  1x 1 bytes
        bInterval              12
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       1
      bNumEndpoints           1
      bInterfaceClass         9 Hub
      bInterfaceSubClass      0 
      bInterfaceProtocol      2 TT per port
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0001  1x 1 bytes
        bInterval              12
Hub Descriptor:
  bLength               9
  bDescriptorType      41
  nNbrPorts             2
  wHubCharacteristic 0x0009
    Per-port power switching
    Per-port overcurrent protection
    TT think time 8 FS bits
  bPwrOn2PwrGood        0 * 2 milli seconds
  bHubContrCurrent      0 milli Ampere
  DeviceRemovable    0x00
  PortPwrCtrlMask    0xff
 Hub Port Status:
   Port 1: 0000.0503 highspeed power enable connect
   Port 2: 0000.0100 power
Device Qualifier (for other device speed):
  bLength                10
  bDescriptorType         6
  bcdUSB               2.00
  bDeviceClass            9 Hub
  bDeviceSubClass         0 
  bDeviceProtocol         0 Full speed (or root) hub
  bMaxPacketSize0        64
  bNumConfigurations      1
can't get debug descriptor: Resource temporarily unavailable
Device Status:     0x0001
  Self Powered

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.

@Be-ing
Copy link
Contributor

Be-ing commented May 17, 2021

The hub operates at 480 Mb too. Here is lsusb -v with a USB 3.0 drive plugged into the USB-A port on the device:

    |__ Port 3: Dev 5, If 0, Class=Hub, Driver=hub/2p, 480M
        |__ Port 2: Dev 8, If 0, Class=Mass Storage, Driver=usb-storage, 480M
        |__ Port 1: Dev 6, If 5, Class=Application Specific Interface, Driver=, 480M
        |__ Port 1: Dev 6, If 3, Class=Human Interface Device, Driver=usbhid, 480M
        |__ Port 1: Dev 6, If 1, Class=Audio, Driver=snd-usb-audio, 480M
        |__ Port 1: Dev 6, If 4, Class=Vendor Specific Class, Driver=, 480M
        |__ Port 1: Dev 6, If 2, Class=Audio, Driver=snd-usb-audio, 480M
        |__ Port 1: Dev 6, If 0, Class=Audio, Driver=snd-usb-audio, 480M

@Be-ing
Copy link
Contributor

Be-ing commented May 17, 2021

I don't think the USB speed is the problem here. I think it is the wMaxPacketSize of 64.

@Youw
Copy link
Member

Youw commented May 17, 2021

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??

I wouldn't be suprised.

@Be-ing
Copy link
Contributor

Be-ing commented May 17, 2021

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.

@Be-ing
Copy link
Contributor

Be-ing commented May 17, 2021

The HID specification has this to say about wMaxPacketSize:

All reports except the longest which exceed wMaxPacketSize for the endpoint must terminate with a short packet. The longest report does not require a short packet terminator.

I'm unclear exactly what that means but it seems that it permits wMaxPacketSize to be shorter than the report size.

@Be-ing
Copy link
Contributor

Be-ing commented May 17, 2021

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??

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.

@Be-ing
Copy link
Contributor

Be-ing commented May 17, 2021

hidapi can determine this.

hidapi would need to parse the report descriptor to determine this, so I guess #249 is a prerequisite for this?

@JoergAtGithub
Copy link
Contributor Author

Isn't the report_descriptor already available internal in the libusb backend:

/* Get the HID Report Descriptor. */

@Be-ing
Copy link
Contributor

Be-ing commented May 17, 2021

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.

@Be-ing
Copy link
Contributor

Be-ing commented May 17, 2021

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. :/

@Youw
Copy link
Member

Youw commented May 17, 2021

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.

@Be-ing
Copy link
Contributor

Be-ing commented May 17, 2021

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.

This issue makes the API not 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 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.

@mcuee
Copy link
Member

mcuee commented May 13, 2023

Past discussions and comments by the original author of HIDAPI Alan Ott.

On 30-Jan-2013

It's more complicated than that, and it needs to be done on the device side. You can have HID reports (interrupt transfers) longer than 64-bytes, but on full-speed connections you will need to send them as 64-byte transactions, the same as you'd do for a long bulk transaction (with a zero-length-packet at the end, if needed, per the USB spec).

It will take more than one frame to do this though. Interrupt endpoints only get one IN token per frame (and on Windows, it seems they get one every other frame). The HID code in windows, mac, and linux/hidraw will piece them together. The libusb HIDAPI implementation will not and you'll get each piece separately. This is a longstanding limitation (which can be worked around), which I'll get to one day (patches appreciated).

@mcuee
Copy link
Member

mcuee commented May 13, 2023

Past discussions and comments by the original author of HIDAPI Alan Ott.

On 25-Feb-2014

It's a rather big problem if you are affected by it. In reality, almost no devices have reports larger than 64 bytes. VRPN simply works around it.

The real solution is to parse the report descriptor and determine the maximum report length and use that length as the maximum transfer size. HIDAPI currently does not parse report descriptors.

Setting the length to 512, or some arbitrarily large number, will cause libusb to buffer transactions until it gets to that number of bytes (or until it receives a short transaction), and then return all the data as a single transfer. This is probably not what you want.

If you have a report which is 80 bytes long, for example, set the length to 80. Libusb will then collect transactions until 80 bytes are reached and return it as one transfer.

This whole issue has to do with multi-transaction transfers. There's nothing in the underlying USB protocol which says that a transfer has ended, or whether the transfer has more data. Yes, a short transaction does indicate end-of-transfer, but an endpoint-length-sized packet does not necessarily indicate that the transfer will contain another transaction. It's up to the agreed-upon protocol between the device and host. For HID devices, the agreed-upon protocol is described by the report descriptor, which HIDAPI does not have a parser for.

@mcuee
Copy link
Member

mcuee commented May 13, 2023

Application level work-around from probe-rs

Also here from Microchip (hard-coded table)
https://github.com/microchip-pic-avr-tools/pyedbglib/blob/main/pyedbglib/hidtransport/toolinfo.py

        {'pid': USB_TOOL_DEVICE_PRODUCT_ID_JTAGICE3, 'default_report_size': 512},
        {'pid': USB_TOOL_DEVICE_PRODUCT_ID_ATMELICE, 'default_report_size': 512},
        {'pid': USB_TOOL_DEVICE_PRODUCT_ID_POWERDEBUGGER, 'default_report_size': 512},
        {'pid': USB_TOOL_DEVICE_PRODUCT_ID_EDBG_A, 'default_report_size': 512},
        {'pid': USB_TOOL_DEVICE_PRODUCT_ID_MSD, 'default_report_size': 512},

Alan Ott mentioned about VRPN application side work-around. I believe it is here (512 Bytest report)
https://github.com/vrpn/vrpn/blob/master/vrpn_HumanInterface.C

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.

@mcuee
Copy link
Member

mcuee commented May 13, 2023

@MCUdude

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 lsusb -vvv under macOS or Linux. You can install usbutils under macOS Homebrew.

brew install usbutils

And also the outout of hidapi hidtest or mac-hid-dump.
https://github.com/todbot/mac-hid-dump

@wulf7
Copy link

wulf7 commented May 13, 2023

[To be confimred]
It seems to me because Windows inbox HID driver most likely does not really support Interrupt IN/OUT Endpoint with wMaxPacketSize greater than 64 bytes, so for the High Speed USB HID device out in the market, the Interrupt IN/OUT Endpoint will still have wMaxPacketSize at 64Bytes.

Can not confirm. I own the laptop with USB touchscreen which input report is greater than 100 bytes. It had Windows 8.0 preinstalled.

@mcuee
Copy link
Member

mcuee commented May 13, 2023

[To be confimred]
It seems to me because Windows inbox HID driver most likely does not really support Interrupt IN/OUT Endpoint with wMaxPacketSize greater than 64 bytes, so for the High Speed USB HID device out in the market, the Interrupt IN/OUT Endpoint will still have wMaxPacketSize at 64Bytes.

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.

@wulf7
Copy link

wulf7 commented May 13, 2023

wMaxPacketSize is 64 as it is USB 2.0 LowSpeed device

@mcuee
Copy link
Member

mcuee commented May 13, 2023

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.

@mcuee
Copy link
Member

mcuee commented May 13, 2023

[To be confimred --> confirmed to be wrong]
It seems to me because Windows inbox HID driver most likely does not really support Interrupt IN/OUT Endpoint with wMaxPacketSize greater than 64 bytes, so for the High Speed USB HID device out in the market, the Interrupt IN/OUT Endpoint will still have wMaxPacketSize at 64Bytes.

Later version of Windows may or may not have such limitations but the device out in the market have to support older version of Windows.
[/To be confirmed --> 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.

@hselasky
Copy link

hselasky commented May 13, 2023

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.

I really need a picture, but this is what I've got:

Bus /dev/usb Device /dev/ugen0.3: ID 03eb:2103 Atmel Corp. JTAG ICE mkII
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               1.10
  bDeviceClass          255 Vendor Specific Class
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        16
  idVendor           0x03eb Atmel Corp.
  idProduct          0x2103 JTAG ICE mkII
  bcdDevice            2.00
  iManufacturer           1 ATMEL
  iProduct                2 JTAGICE mkII
  iSerial                 3 (redacted)
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           32
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0x80
      (Bus Powered)
    MaxPower              500mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval              10
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval              10
Device Status:     0x0001
  Self Powered



Bus /dev/usb Device /dev/ugen0.3: ID 03eb:2104 Atmel Corp. AVR ISP mkII
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               1.10
  bDeviceClass          255 Vendor Specific Class
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        16
  idVendor           0x03eb Atmel Corp.
  idProduct          0x2104 AVR ISP mkII
  bcdDevice            2.00
  iManufacturer           1 ATMEL
  iProduct                2 AVRISP mkII
  iSerial                 3 (redacted)
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           32
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0xc0
      Self Powered
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval              10
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval              10
Device Status:     0x0001
  Self Powered

@Be-ing
Copy link
Contributor

Be-ing commented May 13, 2023

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?

@mcuee
Copy link
Member

mcuee commented May 14, 2023

Hi Hans, would you please do me a favor to dump the USB Prober output of your Atmel-ICE or Power Debugger if you still have them. Thanks.

I really need a picture, but this is what I've got:

Hi HPS,
Sorry the request is to @MCUdude (another Hans) who has the access to the two High Speed USB Composite devices with an HID interface (Atmel-ICE and Atmel Power Debugger). What you have (Jtag ICE mkII and AVR ISP mkII) are not HID devices.

@mcuee
Copy link
Member

mcuee commented May 14, 2023

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?

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.

@mcuee
Copy link
Member

mcuee commented May 14, 2023

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:

@mcuee
Copy link
Member

mcuee commented May 14, 2023

@wulf7 and @hselasky

FYI as well. libfido2 uses FreeBSD hidraw on FreeBSD13+.
I think it is also good for hidapi to move to FreeBSD hidraw for newer version of FreeBSD.
https://github.com/Yubico/libfido2/blob/main/src/hid_freebsd.c

#include <dev/usb/usb_ioctl.h>
#include <dev/usb/usbhid.h>
#if __FreeBSD_version >= 1300500
#include <dev/hid/hidraw.h>
#define USE_HIDRAW /* see usbhid(4) and hidraw(4) on FreeBSD 13+ */
#endif

@MCUdude
Copy link

MCUdude commented May 14, 2023

@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
$ lsusb -vvv

Bus 020 Device 006: ID 03eb:2144  
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass          239 
  bDeviceSubClass         2 
  bDeviceProtocol         1 
  bMaxPacketSize0        64
  idVendor           0x03eb 
  idProduct          0x2144 
  bcdDevice            1.01
  iManufacturer           1 
  iProduct                2 
  iSerial                 3 
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x0082
    bNumInterfaces          4
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0x80
      (Bus Powered)
    MaxPower              500mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass         3 
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface              4 Power Debugger CMSIS-DAP
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.11
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength      35
         Report Descriptors: 
           ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               1
    Interface Association:
      bLength                 8
      bDescriptorType        11
      bFirstInterface         1
      bInterfaceCount         2
      bFunctionClass          2 
      bFunctionSubClass       2 
      bFunctionProtocol       1 
      iFunction               6 Power Debugger Virtual COM Port
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         2 
      bInterfaceSubClass      2 
      bInterfaceProtocol      1 
      iInterface              0 
      CDC Header:
        bcdCDC               1.10
      CDC ACM:
        bmCapabilities       0x06
          sends break
          line coding and serial state
      CDC Union:
        bMasterInterface        1
        bSlaveInterface         2 
      CDC Call Management:
        bmCapabilities       0x03
          call management
          use DataInterface
        bDataInterface          2
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               8
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        2
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass        10 
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x84  EP 4 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x05  EP 5 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        3
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass       255 
      bInterfaceSubClass    255 
      bInterfaceProtocol    255 
      iInterface              5 Power Debugger Data Gateway
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x87  EP 7 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval             255
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x06  EP 6 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval             255
Device Qualifier (for other device speed):
  bLength                10
  bDescriptorType         6
  bcdUSB               2.00
  bDeviceClass          239 
  bDeviceSubClass         2 
  bDeviceProtocol         1 
  bMaxPacketSize0        64
  bNumConfigurations      1
can't get debug descriptor: Operation timed out
Device Status:     0x0000
  (Bus Powered)

mac-hid-dump with only the Power Debugger plugged in
$ ./mac-hid-dump 
mac-hid-dump:
05AC 0273:  - Apple Internal Keyboard / Trackpad
DESCRIPTOR:
  06  00  ff  09  03  a1  01  06  00  ff  09  03  15  00  26  ff 
  00  85  c0  96  6b  00  75  08  81  02  c0  
  (27 bytes)
05AC 0273:  - Apple Internal Keyboard / Trackpad
DESCRIPTOR:
  05  01  09  06  a1  01  85  01  05  07  19  e0  29  e7  15  00 
  25  01  75  01  95  08  81  02  95  01  75  08  81  01  95  05 
  75  01  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  29  ff  81 
  00  05  0c  75  01  95  01  09  b8  15  00  25  01  81  02  05 
  ff  09  03  75  07  95  01  81  02  c0  05  0c  09  01  a1  01 
  85  52  15  00  25  01  75  01  95  01  09  cd  81  02  09  b3 
  81  02  09  b4  81  02  09  b5  81  02  09  b6  81  02  81  01 
  81  01  81  01  85  09  15  00  25  01  75  08  95  01  06  01 
  ff  09  0b  b1  02  75  08  95  02  b1  01  c0  06  00  ff  09 
  06  a1  01  06  00  ff  09  06  15  00  26  ff  00  75  08  95 
  40  85  3f  81  22  c0  
  (182 bytes)
05AC 0273:  - Apple Internal Keyboard / Trackpad
DESCRIPTOR:
  06  00  ff  09  0b  a1  01  06  00  ff  09  0b  15  00  26  ff 
  00  75  08  96  04  00  85  e0  81  22  c0  
  (27 bytes)
05AC 0273:  - Apple Internal Keyboard / Trackpad
DESCRIPTOR:
  05  01  09  02  a1  01  09  01  a1  00  05  09  19  01  29  03 
  15  00  25  01  85  02  95  03  75  01  81  02  95  01  75  05 
  81  01  05  01  09  30  09  31  15  81  25  7f  75  08  95  02 
  81  06  95  04  75  08  81  01  c0  c0  05  0d  09  05  a1  01 
  06  00  ff  09  0c  15  00  26  ff  00  75  08  95  10  85  3f 
  81  22  c0  06  00  ff  09  0c  a1  01  06  00  ff  09  0c  15 
  00  26  ff  00  85  44  75  08  96  df  03  81  00  c0  
  (110 bytes)
03EB 2144: Atmel Corp. - Power Debugger CMSIS-DAP
DESCRIPTOR:
  06  00  ff  09  01  a1  01  15  00  26  ff  00  75  08  96  00 
  02  09  01  81  02  96  00  02  09  01  91  02  95  04  09  01 
  b1  02  c0  
  (35 bytes)
05AC 0273:  - Apple Internal Keyboard / Trackpad
DESCRIPTOR:
  06  00  ff  09  0d  a1  01  06  00  ff  09  0d  15  00  26  ff 
  00  75  08  85  3f  96  0f  00  81  02  85  53  96  3f  00  91 
  02  c0  
  (34 bytes)

@mcuee
Copy link
Member

mcuee commented May 15, 2023

@MCUdude

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.

    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass         3 
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface              4 Power Debugger CMSIS-DAP
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.11
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength      35
         Report Descriptors: 
           ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               1

The hid report parser output.
https://eleccelerator.com/usbdescreqparser/

0x06, 0x00, 0xFF,  // Usage Page (Vendor Defined 0xFF00)
0x09, 0x01,        // Usage (0x01)
0xA1, 0x01,        // Collection (Application)
0x15, 0x00,        //   Logical Minimum (0)
0x26, 0xFF, 0x00,  //   Logical Maximum (255)
0x75, 0x08,        //   Report Size (8)
0x96, 0x00, 0x02,  //   Report Count (512)
0x09, 0x01,        //   Usage (0x01)
0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x96, 0x00, 0x02,  //   Report Count (512)
0x09, 0x01,        //   Usage (0x01)
0x91, 0x02,        //   Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x95, 0x04,        //   Report Count (4)
0x09, 0x01,        //   Usage (0x01)
0xB1, 0x02,        //   Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0xC0,              // End Collection

// 35 bytes

@mcuee
Copy link
Member

mcuee commented May 15, 2023

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.
(wMaxPacketSize = 64, high speed or full speed).

PS C:\work\hid\hidapitester> .\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 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
Copy link
Member

mcuee commented May 16, 2023

I hope #478 (comment) is correct. In that case, I can probably carry out some tests for this issue in different OS.

Indeed I can reproduce the issue using hidapitester under Linux.

  1. using hidapitester with hidraw -- no issue
mcuee@UbuntuSwift3:~/build/hid/hidapitester$ /hidapitester_libusb --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

Using libusb backend, I can reproduce the issue under Linux. You can see that it only reads back 64 Bytes.

mcuee@UbuntuSwift3:~/build/hid/hidapitester$ ./hidapitester_libusb --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

@JoergAtGithub
Copy link
Contributor Author

The documentation of libusb_interrupt_transfer() states: "You should also check the transferred parameter for interrupt writes. Not all of the data may have been written."
https://libusb.sourceforge.io/api-1.0/group__libusb__syncio.html#ga0f171a72904a552fc43e6e6564d108a3

@mcuee
Copy link
Member

mcuee commented Mar 6, 2024

@JoergAtGithub and @Youw

Just wondering if you are still looking at this issue or not. Thanks.

@JoergAtGithub
Copy link
Contributor Author

This is clearly a bug in hidapi libusb backend, confirmed by several affected users.
But I'm not working on a fix curently.

@Youw
Copy link
Member

Youw commented Mar 6, 2024

Agree.
I don't have capacity for this either.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working documentation Improvements or additions to documentation libusb Related to libusb backend
Projects
None yet
Development

No branches or pull requests

8 participants