2024-06-13 10:55 AM
Hello,
I am trying to implement a USB HID keyboard on an STM32F042 without HAL or LL, just simple register defs. I took an example code generated in CubeIDE with HAL and a few other examples. I extended the example with HAL to also implement the LEDs which all works fine.
I understand how it basically works. I define the descriptors and configure the Endpoints etc. Then I need to transfer the descriptors when the host requires them. But what I can not figure out is how exactly the descriptors are actually transferred. The HAL is so overloaded that it seems impossible to find the exact lines of code where the descriptors are transferred to the host and how that is done exactly. Also where do I put the report descriptor to send some key presses? Can anyone give me some info on how that is done?
Solved! Go to Solution.
2025-09-12 2:16 AM - edited 2025-09-12 8:52 AM
So all "seems" to work correctly. I can see on a logic analyzer that the descriptor requests are received and served correctly. But my EP1 is never polled and the USB bus is reset in intervals of 3 to 5 seconds and enumeration starts new. So there must be something wrong in my descriptors. Also it seems that the report descriptor is never requested.
const uint8_t USB_DeviceDescriptor[] =
{
0x12, // lenght
0x01, // descriptor type device
0x00, 0x02, // usb 2.0
0x00, // device class 0 = defined in interface
0x00, // subclass
0x00, // protocoll
0x40, // packetsize 64 byte
0x83, 0x04, // vendor ST
0x52, 0x57, // product id
0x00, 0x01, // device
0x01, // Manufacturer
0x02, // Product
0x03, // SerialNumber
0x01 // bNumConfigurations
};
const uint8_t USB_ConfigDescriptor[] =
{
0x09, // length
0x02, // descriptor type configuration
0x22, 0x00, // total length 34 bytes
0x01, // interfaces 1
0x01, // config value
0x00, // config
0x80, // attributes bus powered remote wakeup
0x32, // power 100 mA
// interface descriptor
0x09, // length
0x04, // descriptor type interface
0x00, // interface number
0x00, // alternate setting
0x01, // endpoints
0x03, // interface class HID
0x01, // subclass (boot = 1, extended = 0)
0x01, // protocol keyboard
0x00, // interface
// HID descriptor
0x09, // length
0x21, // descriptor type HID
0x11, 0x01, // HID 1.11
0x00, // country code 0
0x01, // num descriptors
0x22, // descriptor type report
45, 0x00, // length of USB_HID_KeyboardReportDescriptor (set to 0 for only boot mode) 45
// endpoint descriptor in interrupt
0x07, // length
0x05, // descriptor type endpoint
0x81, // endpoint address 1
0x03, // attributes interrupt
0x08, 0x00, // packet size 8
0x0A // polling interval in ms
};
// standard report descriptor without media keys
const uint8_t USB_HID_KeyboardReportDescriptor[] =
{
0x05, 0x01, // usage page generic desktop
0x09, 0x06, // usage keyboard
0xA1, 0x01, // collection application
0x05, 0x07, // usage page key codes
0x19, 0xE0, // usage min 224
0x29, 0xE7, // usage max 231
0x15, 0x00, // logical min 0
0x25, 0x01, // logical max 1
0x75, 0x01, // report size 1
0x95, 0x08, // report count 8
0x81, 0x02, // input data, var, abs modifier byte
0x95, 0x01, // report count 1
0x75, 0x08, // report size 8
0x81, 0x01, // input const, array, abs reserved byte
0x95, 0x06, // report count 6
0x75, 0x08, // report size 8
0x15, 0x00, // logical min 0
0x25, 0x65, // logical max 101 keys
0x05, 0x07, // usage page key codes
0x19, 0x00, // usage min 0
0x29, 0x65, // usage max 101
0x81, 0x00, // input data, array
0xC0 // end collection
};
The request for qualifier descriptor is stalled.
I have compared and tried all sorts of different examples but it just wont get past the enumeration.
Edit: the point where it stops is when the host requests the clear feature. What is the response to that? Now I just Ack it.
2025-09-13 1:01 AM
Found the issue, cant edit the post. Now the USB driver works and I have my HID running. It was EP1 not configured in combination with missing the token.