Keyboard Device

Keyboard device settings control how your keyboard identifies itself to computers: its USB vendor and product IDs, manufacturer, product name, and serial number. In keyboard.toml, they also select the chip or board that RMK builds for.

Configuring the keyboard device

Set device information in the [keyboard] section of keyboard.toml. With the Rust API, set it in the device_config field of RmkConfig.

Toml
Rust
keyboard.toml
[keyboard]
name = "My Custom Keyboard"       # A label for your configuration; it does not appear on USB or BLE
vendor_id = 0x4c4b                # USB vendor ID (16-bit hex)
product_id = 0x4643               # USB product ID (16-bit hex)
manufacturer = "YourName"         # (Optional) Manufacturer string, defaults to "RMK"
product_name = "KeyboardName"     # (Optional) USB product string and BLE device name, defaults to "RMK Keyboard"
# serial_number = "board-0001"    # (Optional) Device Serial ID; defaults to one derived from the hardware UID
chip = "nrf52840"                 # Target microcontroller
usb_enable = true                 # (Optional) Enable USB functionality. If omitted, RMK uses the board/chip default.

For BLE keyboards, manufacturer can contain up to 32 UTF-8 bytes. The advertised product_name must fit in 16 UTF-8 bytes with RMK's advertising data.

Selecting the chip or board

Set either chip or board in the [keyboard] section, but not both. A board also selects its chip and applies the board's default settings.

To build for a chip, set chip:

keyboard.toml
[keyboard]
chip = "nrf52840"

To build for a supported development board, set board:

keyboard.toml
[keyboard]
board = "nice!nano_v2"

Supported chips

The chip setting accepts chips from four families:

  • Espressif ESP32: esp32c3, esp32c6, esp32h2, esp32s3
  • Nordic nRF52: nrf52840, nrf52833, nrf52832, nrf52811, nrf52810
  • Raspberry Pi: rp2040
  • STM32: Any STM32 chip with USB that embassy-stm32 supports
Info

keyboard.toml recognizes rp2040 but not rp2350 yet. To build for an RP2350, use the Rust API.

Supported development boards

The board setting accepts seven development boards. Board names are case-sensitive.

  • bluemicro840: nRF52840-based Pro Micro replacement
  • nice!nano: nRF52840-based wireless board
  • nice!nano_v2: Updated version of nice!nano
  • nrfmicro: nRF52840-based Pro Micro replacement
  • pi_pico_w: Raspberry Pi Pico W with Wi-Fi and BLE
  • puchi_ble: nRF52840-based wireless board
  • XIAO BLE: Seeed Studio XIAO nRF52840

Disabling USB

Chips without full USB device support, such as the nRF52832 and ESP32-C3, have USB off by default. To turn off USB on a chip that has it, for example for a BLE-only keyboard, set usb_enable = false:

keyboard.toml
[keyboard]
chip = "nrf52840"
usb_enable = false

About serial numbers

RMK reports the same serial number over USB, BLE, and Rynk. It contains a protocol marker and a device ID, so an RMK version change alone does not change it.

The host protocol selects the marker. Vial uses its marker to discover keyboards.

Host protocolProtocol marker
Vialvial:f64c2b3c:
Rynk, or a dongle without Vialrynk:
No host protocolNone

For example, Vial reports vial:f64c2b3c:0a1b2c for the device ID 0a1b2c.

Default device serial IDs

Omit serial_number to derive a six-digit hex ID from hardware where available. TOML projects read the UID automatically; the Rust API needs the calls listed below.

ChipHardware UIDWith the Rust API
ESP32, BLE buildsLast 3 bytes of the factory MAC addressAutomatic
nRF, BLE buildsTop 24 bits of the FICR device ID, or of the device address on nRF54Automatic
RP2040Hash of the external flash's unique IDCall rp2040_serial_number
STM32Hash of the 96-bit unique IDCall build_serial_number(&uid)
Warning

Without a usable UID, RMK uses RMK as the device ID. Windows can confuse boards with the same VID, PID, and serial number; give each such board a distinct ID.

Setting a device serial ID

Set serial_number to assign a fixed device ID. Every board flashed with the same value reports the same ID.

Toml
Rust
keyboard.toml
[keyboard]
serial_number = "board-0001"

RMK replaces existing Vial or Rynk markers, including Vial's legacy semicolon form, with the current protocol marker.

In Rust, DeviceConfig.serial_number stores the complete, owned string returned by build_serial_number.

A device serial ID has two limits:

  • It can contain only printable ASCII characters, without commas. Windows ignores a serial number with any other character.
  • It must fit in 32 bytes together with its protocol marker: up to 18 bytes for the ID with Vial, 27 with Rynk, or 32 without a marker.

RMK checks TOML values at build time. The Rust builder panics if the final string is too long; it never truncates.

Reading the hardware UID with the Rust API

Only nRF and ESP32 BLE builds read the UID in DeviceConfig::default(). Use the following calls on other targets.

For STM32:

main.rs
let uid = embassy_stm32::uid::uid();
let keyboard_device_config = DeviceConfig {
    serial_number: rmk::config::build_serial_number(&uid),
    ..Default::default()
};

For RP2040, read the flash UID before creating a storage or DFU driver:

main.rs
let mut p = embassy_rp::init(Default::default());
let serial_number = rmk::config::rp2040_serial_number(p.FLASH.reborrow());
let keyboard_device_config = DeviceConfig {
    serial_number,
    ..Default::default()
};

For other chips, pass a stable UID as &[u8] or &[u8; N]. UIDs of up to three bytes become six hex digits; longer UIDs are hashed to the same length. Empty strings or UIDs use RMK.

The input type selects the conversion: build_serial_number("123") uses the custom ID 123, while build_serial_number(b"123") encodes the UID as 313233 before adding the marker.