Search code examples
keyboardstm32hidusb-hid

More keypresses per second on STM32L476RE Keyboard emulation


I have recently got the STM32L476 to work as HID keyboard where I am able to send out the keypresses however it is very slow for my use-case. I have followed a typical example like this one.

I have observed that when I tried to give a little bigger custom payload complying the HID report format to the USBD_HID_SendReport API the data transfer is little faster as all the keypresses are done immediately. However I want to know if there's a better approach to do this instead of manually building the array myself.

The example array I am sending now is

{0x00.0x00,0x04,0x05,0x07,0x08,0x09,0x0A, 0x00,0x00,0xB,0xC,0xD,0xE,0xF,0x10, 0x00,0x00,.......}

Here the first 2 bytes for every 8 bytes are 0x00 because first byte is modifier and second byte is reserved and the next 6 bytes are HID keyboard scan codes data in this case ASCII A, B, C, D, E, F, G etc., are appended.

Please let me know if any of my explanation doesn't makes sense.

I have sent the below array

final[0]    uint8_t 0x0 (Hex)   
final[1]    uint8_t 0x0 (Hex)   
final[2]    uint8_t 0xc (Hex)   
final[3]    uint8_t 0x16 (Hex)  
final[4]    uint8_t 0x12 (Hex)  
final[5]    uint8_t 0x1e (Hex)  
final[6]    uint8_t 0x22 (Hex)  
final[7]    uint8_t 0x23 (Hex)  
final[8]    uint8_t 0x0 (Hex)   
final[9]    uint8_t 0x0 (Hex)   
final[10]   uint8_t 0x26 (Hex)  
final[11]   uint8_t 0x20 (Hex)  
final[12]   uint8_t 0x2d (Hex)  
final[13]   uint8_t 0x19 (Hex)  
final[14]   uint8_t 0x2c (Hex)  
final[15]   uint8_t 0x17 (Hex)  
final[16]   uint8_t 0x0 (Hex)   
final[17]   uint8_t 0x0 (Hex)   
final[18]   uint8_t 0x4 (Hex)   
final[19]   uint8_t 0xa (Hex)   
final[20]   uint8_t 0x2d (Hex)  
final[21]   uint8_t 0x2c (Hex)  
final[22]   uint8_t 0x26 (Hex)  
final[23]   uint8_t 0x25 (Hex)  
final[24]   uint8_t 0x0 (Hex)   
final[25]   uint8_t 0x0 (Hex)   
final[26]   uint8_t 0x2c (Hex)  
final[27]   uint8_t 0x9 (Hex)   
final[28]   uint8_t 0x24 (Hex)  
final[29]   uint8_t 0x2c (Hex)  
final[30]   uint8_t 0x1e (Hex)  
final[31]   uint8_t 0x4 (Hex)   
final[32]   uint8_t 0x0 (Hex)   
final[33]   uint8_t 0x0 (Hex)   
final[34]   uint8_t 0x2c (Hex)  
final[35]   uint8_t 0x27 (Hex)  
final[36]   uint8_t 0x4 (Hex)   
final[37]   uint8_t 0x2c (Hex)  
final[38]   uint8_t 0x27 (Hex)  
final[39]   uint8_t 0x25 (Hex)  
final[40]   uint8_t 0x0 (Hex)   
final[41]   uint8_t 0x0 (Hex)   
final[42]   uint8_t 0x2c (Hex)  
final[43]   uint8_t 0x27 (Hex)  
final[44]   uint8_t 0x1e (Hex)  
final[45]   uint8_t 0x2c (Hex)  
final[46]   uint8_t 0x27 (Hex)  
final[47]   uint8_t 0x21 (Hex)  
final[48]   uint8_t 0x0 (Hex)   
final[49]   uint8_t 0x0 (Hex)   
final[50]   uint8_t 0x2c (Hex)  
final[51]   uint8_t 0x8 (Hex)   
final[52]   uint8_t 0x27 (Hex)  
final[53]   uint8_t 0xd (Hex)   
final[54]   uint8_t 0x28 (Hex)  
final[55]   uint8_t 0x0 (Hex)       
USBD_HID_SendReport(&hUsbDeviceFS,&final,56);
HAL_Delay(150);
memset(&final,0x00,56);
USBD_HID_SendReport(&hUsbDeviceFS,&final,56);
HAL_Delay(150);

You can see from the debugger snapshot the data is formatted correctly

debugger snapshot

However, the output that comes out is as shown below output from HID keyboard

Lot of characters are missed especially repeated chars and some of the chars are mis-typed as well.


Solution

  • USB HID keyboards don't work that way. Each report sent to the host contains a list of codes (indexes to USB Usage codes as defined by your USB Report Descriptor) that represent the keys that are currently pressed. The host usually processes the content of each report sequentially but that is not guaranteed behaviour. For example, if you send a report indicating X is pressed, and then send another report indicating X is pressed, you will see a single X (not two) on your terminal.

    You need to send a report of all zeros to indicate that no keys are currently pressed so that the host knows when keys are released. Failure to release keys this way usually results in the host performing a "type-o-matic key repeat" function (which has nothing to do with USB).

    Also, the host polls HID devices for input at a fixed rate (1000 polls per second - if i recall correctly) so you can't increase throughput much by sending larger buffers.