Search code examples
usbprotocolsdevicehidfirmware

USB HID difference between "Get Input Report" and "Input report"


I'm implementing a custom HID device that has the following interface:

0x06, 0xA0, 0xFF,  // Usage Page (Vendor Defined 0xFFA0)
0x09, 0x01,        // Usage (0x01)
0xA1, 0x01,        // Collection (Application)

0x85, 0x01,        //   Report ID (1)
0x15, 0x00,        //   Logical Minimum (0)
0x26, 0x01, 0x00,  //   Logical Maximum (1)
0x75, 0x08,        //   Report Size (8)
0x95, 0x01,        //   Report Count (1)
0x91, 0x02,        //   Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)

0x85, 0x01,        //   Report ID (1)
0x15, 0x00,        //   Logical Minimum (0)
0x26, 0x01, 0x00,  //   Logical Maximum (1)
0x75, 0x01,        //   Report Size (1)
0x95, 0x02,        //   Report Count (2)
0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x75, 0x06,        //   Report Size (6)
0x95, 0x01,        //   Report Count (1)
0x81, 0x01,        //   Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)

0x85, 0x03,        //   Report ID (1)
0x15, 0x00,        //   Logical Minimum (0)
0x26, 0xFF, 0xFF,  //   Logical Maximum (65535)
0x75, 0x10,        //   Report Size (16)
0x95, 0x01,        //   Report Count (1)
0xB1, 0x02,        //   Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)

0xC0,              // End Collection

When I plug this device into the computer through a USB logic analyzer I see it enumerate, then something (I'm not sure what, any ideas?) uses the HID report descriptor to intelligently grab a bunch of reports:

(control)(endpoint 0) Get Input Report[1]
(control)(endpoint 0) Get Feature Report[1]

The "Get Input Report" entry confused me as I thought input reports were sent via an interrupt transfer. If I use usbhid's hid_write, I see the following entry, so I must be at least half right about input reports being sent via interrupt transfers...:

(interrupt)(endpoint 1) Input Report[1]"

I have been unable to find information that describes the difference between control "get input reports" and interrupt "input report" transfers which I am hoping one of you will know about.

Why do control "get input reports" exist?

Why not just have the spec mandate a "get feature report" entry exist for every "input report" id entry?

Why is whatever is grabbing input/feature reports for every defined input/feature report using a control transfer for the input reports vs. an interrupt transfer?


Solution

  • Have a look at USB HID v1.1. There is definition for Get_Report request on page 51:

    This request is useful at initialization time for absolute items and for determining the state of feature items. This request is not intended to be used for polling the device state on a regular basis.

    Here, this is exactly what the driver is doing: it is retrieving the various reports to initialize its current state. Note the host cannot request the device to send a report on its interrupt pipe. Hence the request on control pipe.

    Chapter 4.4 explains various endpoints usage.

    Also note feature reports and input reports do not address the same data, even if they have the same report ID (report IDs are per report type).