cancel
Showing results for 
Search instead for 
Did you mean: 

USB Device HID Keyboard example

AlexSmart
Senior
Posted on September 24, 2016 at 12:00

Does anyone USB Device HID Keyboard example? I'm struggling to modify USB mouse example into keyboard. Read some literature, tried to modify descriptors, but no luck...

#hid #hid #hid #usb-device #device #keyboard #keyboard #usb-hid #consumer
13 REPLIES 13
Posted on September 26, 2016 at 08:28

You have to modify Middlewares/ST/STM32_USB_Device_Library/Class/HID/

Inc/usbd_hid.h

Src/usbd_hid.c

see attached.

Look for stuff that uses #ifdef KEYBOARD

Then the code to send characters to the PC has lots of details. The buffer has 8 bytes. The second byte is always 0. The first byte contains the modifier bits (left and right shift, controls, alts, windows). And the final 6 bytes are your USB control codes that represent your characters, that you can look up in the USB HID manual.

You will be sending a key down buffer, wait a little time, then send the key up buffer, where I set the character code to 0.

The fragments are from a work in progress. Unfortunately, I got distracted by a blown processor, but I had some characters being sent to my Mac before I put this project away.

uint8_t HIDbuffer[8] = {0}; 
// modifiers in 0, zero in 1, char code in 2-7
uint8_t *buf;
uint32_t USBDelay;
buf = HIDbuffer;
USBDelay = USBD_HID_GetPollingInterval(&hUsbDeviceFS);
 HIDbuffer[2] = 0x38;

/* send out a slash character */

USBD_HID_SendReport(&hUsbDeviceFS, buf, 8);

HAL_Delay(USBDelay);

HIDbuffer[2] = 0;
USBD_HID_SendReport(&hUsbDeviceFS, buf, 8);

Andrei from The Great White North

________________

Attachments :

usbd_hid.c : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006HtrB&d=%2Fa%2F0X0000000aXx%2FNbD.YfaVDQd2UqBJBDhoml9N40P2_dM_N7y9npXy2Z0&asPdf=false

usbd_hid.h : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006HtrG&d=%2Fa%2F0X0000000aXy%2F8neL4FEvlCMiORhN22frKJ69bPDs769ApM0deVsqMVM&asPdf=false
slimen
Senior
Posted on September 26, 2016 at 09:39

Hello,

You may find a HID examples within STM32Cube firmware package that use HAL library. 

You can start from one of the provided example, like i

n the STM32CubeF4 package you have 

: STM32Cube_FW_F4_V1.13.0\Projects\STM324xG_EVAL\Applications\USB_Host\HID_Standalone

It is a typical application on how to use the STM32F4xx USB OTG Host peripheral to interact with an USB HID Device such as a Mouse or a Keyboard.

You can also get more details on the HID class used to access the mouse or keyboard referring to

http://www.st.com/content/ccc/resource/technical/document/user_manual/b8/5a/28/c2/cf/b6/47/d6/DM00105256.pdf/files/DM00105256.pdf/jcr:content/translations/en.DM00105256.pdf

(STM32Cube USB host library).

Regards

Kraal
Senior III
Posted on September 26, 2016 at 11:28

@forumstm32 : Except that OP wanted to make a USB device, not host.

@Andrei : Can you please explain why need the delay between 2 keyboard stroke ? Is it because you are using the control endpoint ?

slimen
Senior
Posted on September 26, 2016 at 16:08

''@Andrei : Can you please explain why need the delay between 2 keyboard stroke ? Is it because you are using the control endpoint ?''

I used the delay because, without any specific examples of how to use the device properly, I had to use ''voodoo'' programming.

Initially, I sent the key down buffer alone. This caused a stream of characters to be transmitted instead of just one.

Next, I remembered from my work on PICs that you had to send a key up as well. So I expected some sort of buffering and send a key down buffer and then a key up buffer and got nothing at all. I figured that the peripheral must be single buffered and I'm just buzzing the buffer, so I put in a large delay and it started to work. I did a binary search with the delays to see when it stopped working again.

Eventually, I either noticed the get polling interval call or found it in some other demo code, but it gave me a stable system that fit my mental model.

Basically, the thing is polled (USBD_HID_GetPollingInterval) and dumping character buffers out faster than the polling interval just buzzes the buffer and does nothing useful.

I have no specific knowledge of how the USB device works, so this is all conjecture mostly based on Microchip's sample code from a few years ago.

The .c and .h files that you have to munge to get a keyboard device descriptor are so far down in the middleware(s) stack that it doesn't feel like the proper way to achieve what we want, and the stack really wants to be a mouse/joystick HID.

Andrei from The Great White North

(as seen on the embedded.fm podcast and blog)

Kraal
Senior III
Posted on September 27, 2016 at 08:23

''The .c and .h files that you have to munge to get a keyboard device descriptor are so far down in the middleware(s) stack that it doesn't feel like the proper way to achieve what we want, and the stack really wants to be a mouse/joystick HID.''

I totally agree with you, this library is not well structured at all. The LUFA library made for Atmel by Dean Camera was really good in this regard.

Back to the point, I have also made a keyboard device, but I'm using interrupt endpoints for both IN and OUT reports, instead of the Control endpoint. This way I don't have to care about delays, USBD_HID_DataOut is called when my keyboard receive a new packet (don't forget to call DCD_EP_PrepareRx at the end of this function to be able to receive the next packet), and USBD_HID_DataIn is called when the host is ready to receive a new packet, which is sent with USBD_HID_SendReport.

I'm not sure about everything. I can send any complete sentence I want, but it seems slower than what the interrupt interval should achieve, so something is amiss here.

To OP, I'm using a F0 device, what device are you using ?

AlexSmart
Senior
Posted on September 29, 2016 at 11:31

I'm using STM32F407

I found a way to solve my problem. I modified mouse example (report descriptor) according to original keyboard (sniffed with USBLyzer).

Now I'm struggling to make multimedia keys work.

And btw, while there is good DFP for F4 devices, with drivers and examples... Is there such thing for F3? There is no USB drivers in latest DFP...

Kraal
Senior III
tsuneo
Senior
Posted on September 29, 2016 at 13:02

Hi andrei and Kraal

> I used the delay

 

> so something is amiss here.

The points of HID keyboard device implementation are,

1. The timing (interval) to send the input report is specified by host

Host appoints report interval by Set_Idle request.

Windows and Linux issue Set_Idle(0) just after enumeration.

- this means 'indefinite' interval, ie. just when any one key would be pressed or released

MacOS specifies Set_Idle(9) - 36 ms interval

These OS are tolerant on interval, even when your keyboard device wouldn't strictly follow this rule by HID spec. When your device would continue to send input reports in steady interval, Windows/Linus should interpret the reports train correctly. Also, your device would apply ''when any one key would be pressed or released'' rule, MacOS doesn't complain.

2. The input report is a 'snapshot' of pressed keys at the timing when the report is made.

- When three keys are pressed, the keycode array holds the pressed three keys, the rest is filled with 0 (no event)

- When no key is pressed, the keycode array is zero-filled

In

http://community.silabs.com/t5/8-bit-MCU/USB-HID-KEYBOARD-Search-a-Programmer/m-p/73843/highlight/true#M30245

, I wrote on HID keyboard implementation about 10 years ago.

Tsuneo