USB: Keyboard

This code implements a USB keyboard, which you can use to control almost any PC or Mac software.

Download Source Files

Example Application

The example program configures all Port B and Port D pins as inputs with pullup resistors. When any of these 16 pins is shorted to ground, 2 keystrokes are sent to the PC naming that pin.

An idle timeout is also implemented which send a spacebar keystroke after 8 seconds of inactivity.

USB Keyboard Example, 16 keys on Port B and Port D

Operating System Setup

All modern operating systems support USB keyboards. No special drivers need to be loaded.

This code also supports the keyboard "boot protocol" for compatability with the BIOS before an operating system has loaded.

Simple Keypress Function

#include <usb_keyboard.h>

usb_keyboard_press(key, modifier)

This simple function sends a single keypress. The following table lists definitions for the standard keys and modifiers. If no modifier is needed, use 0.


Complex Keyboard Functionality

Most applications only require the single press function above, which rapidly presses and releases a single key (plus modifiers) at a time. However, for multiple simultaneous keys pressed, holding keys down for periods of time, and complex sequences, the raw USB key code data may be accessed.

For example, to copy from the clipboard in Windows, some programs may require the CTRL key to be held for a period of time before the C key is pressed. Using usb_keyboard_press() presses and quickly releases the C and CTRL keys together at exactly the same instant. To send a timed sequence, you must set the keyboard state variables and use usb_keyboard_send() to transmit each state change.


This 6 byte array represents the non-modifier keys that are currently pressed. You can only press 6 of the non-modifier keys at once. Set these to zero when not pressing a key.


This variable represents the modifier keys currently pressed. Set this to a bitwise OR of all modifier keys pressed, or zero if none are pressed.


After setting the varibles above, call this function to transmit the key state to the PC. The PC automatically implements auto-repeat when you send a key state that has a non-modifier key pressed, and you allow a long delay before sending a zero to release the key.

// first, press the CTRL key
keyboard_modifier_keys = KEY_CTRL;
keyboard_keys[0] = 0;
keyboard_keys[1] = 0;
keyboard_keys[2] = 0;
keyboard_keys[3] = 0;
keyboard_keys[4] = 0;
keyboard_keys[5] = 0;

// next, press ALT while still holding CTRL
keyboard_modifier_keys = KEY_CTRL | KEY_ALT;

// now press DELETE, while still keeping CTRL and ALT
keyboard_keys[0] = KEY_DELETE;

// release DELETE, while still keeping CTRL and ALT
keyboard_keys[0] = 0;

// release both CTRL and ALT at exactly the same moment
keyboard_modifier_keys = 0;


This variable is updated with the current keyboard LED setting.

USB Connection Management Functions


Initialize the USB controller. This must be called before any others, typically as your program initializes everything. This function always returns immediately and never waits for any USB communication.


Is the USB controller configured?

Returns 0 (false) if the host has not enumerated (auto-detected) and configured the USB controller. Returns non-zero (true) if configuration is complete.

Many PC and Macintosh drivers are not immediately ready to transfer data, even after configuration is complete. An additional delay of 1 second is generally a good idea to allow drivers to load on the PC before initiating data transfers.

USB Debug Message Functions

The debug version includes all the debug message functions, which may be used indepentently from the keyboard functions for display in HID Listen.

About USB Keyboard Bandwidth

The USB keyboard protocol is not designed for high bandwidth data transfer. Each change of keyboard state is transmitted as a packet. Because the USB interrupt transfer type is used, a maximum of 1000 packets per second can be sent.

Using usb_keyboard_press(), two packets are sent for every keystroke, the first to press the key (and modifier keys) and the second to release. This results in a maximum of 500 keystrokes per second. Using usb_keyboard_send(), a single packet is sent with the contents of the keyboard_keys[6] and keyboard_modifier_keys.

Software on the PC may spend considerable CPU time processing each keystroke, with the assumption that no human could possibly press more than several keys per second. Even 500 keys per second may overwhelm such software.