Skip to content

Support receiving SetReport requests in usb_hid #2348

Closed
@deshipu

Description

@deshipu

In order to implement a proper keyboard, with working LEDs for CapsLock, NumLock and the like, we need to be able to receive and examine the SetReport requests, as they contain the bitmask of which LEDs should be on.

From https://wiki.osdev.org/USB_Human_Interface_Devices#LED_lamps:

To set the LED lamps, the driver sends a SetReport request to the device using a standard USB Setup Transaction, with a one-byte data stage. The setup packet's request type should contain 0x21, the request code for SetReport is 0x09. The value field of the setup packet contains the report ID in the low byte, which should be zero. The high byte contains the report type, which should be 0x02 to indicate an output report, or a report that is being sent from the software to the hardware. The index field should contain the interface number of the USB keyboard, which is the number present in the interface descriptor which indicated this device was a USB keyboard at all. The data stage should be 1 byte, which is a bitfield. This Setup Transaction should be transferred to control endpoint zero, which would work on all hardware. Other hardware may or may not support the optional interrupt OUT endpoint. If the hardware supports the interrupt OUT endpoint, you can just transfer the 1 byte data stage to the interrupt OUT endpoint, without the extra overhead of the SETUP stage and STATUS stage. If the hardware support the interrupt OUT endpoint, you should avoid the control endpoint when possible, as the interrupt OUT endpoint is faster and can be programmed with interrupt transfers instead of setup transfers. The format of the 1-byte data stage (for SETUP transaction) or 1-byte interrupt OUT transfer is shown below. When a bit is set to 1, the corresponding LED is turned on.

It looks like we already have a callback C function that gets called when a request comes:

// Callbacks invoked when receive Get_Report request through control endpoint
uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) {
// only support Input Report
if ( report_type != HID_REPORT_TYPE_INPUT ) return 0;
// fill buffer with current report
memcpy(buffer, get_hid_device(report_id)->report_buffer, reqlen);
return reqlen;
}
— we just need to decide how to expose the data from the report to the user.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions