# esp32_mouse_keyboard: an ESP32 as a BLE HID keyboard and mouse

> The AsTeRICS firmware turns an ESP32 into a Bluetooth Low Energy HID keyboard and mouse with a serial control protocol for external microcontrollers, and compatibility rather than features is its hard limit.

**asterics/esp32_mouse_keyboard** — ESP32 implementation for HID over GATT Keyboard and Mouse (Bluetooth Low Energy). Including serial API for external modules (similar to Adafruit EZKey HID)

- Repository: https://github.com/asterics/esp32_mouse_keyboard
- Stars: 912 · Forks: 123
- Language: HTML
- License: GPL-3.0
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/asterics-esp32-mouse-keyboard

## An ESP32 pretending to be a mouse and keyboard over BLE HID

This is ESP32 firmware that implements the HID profile over GATT, Bluetooth Low Energy, for both keyboard and mouse, and it adds a serial API so an external module can drive it. The AsTeRICS project uses it in assistive input devices, and that context explains the design. The point is not a general purpose Bluetooth keyboard: it is a microcontroller that has to look like an ordinary pointing device and keyboard to a phone or tablet, while the actual input decisions are made somewhere else. The repository is a typical ESP-IDF project, with a CMakeLists.txt at the root, a main/ directory, a hardware/ directory, a doxygen/ directory for generated documentation, and a sdkconfig.defaults file. The hardware directory is unusual and useful, because it holds the board definitions for the two products the firmware runs on.

## Two host boards share one firmware, and menuconfig decides which

The same firmware runs on two different boards, and getting that wrong is the first trap. On the esp32miniBT module, which lives in this repository, the ESP32 is an add-on board for version 2 of the FLipMouse, FABI and FLipPad PCBs, which use either a TeensyLC or a ProMicro controller as the main processor. On the Arduino Nano RP2040 Connect, used by version 3 of FLipMouse and FLipPad and possibly FABI as well, the RP2040 controller and the ESP32 sit on the same board, which the documentation describes as more RAM, more flash and cheaper than two separate boards. The selection is made at build time: the documentation states plainly that the correct board type must be selected in idf.py menuconfig. For a custom board, the same menu lets you set the external UART interface options, whereas on the official boards the pinning, baudrate and UART configuration are already fixed.

## Building and flashing, with only one supported IDF release

The firmware is built with the Espressif ESP-IDF toolchain, and the documentation points at the step-by-step setup instructions in the IDF manual for the toolchain. Once that infrastructure is in place, the build and flash cycle is the familiar one:

```bash
idf.py build
make
idf.py -p (PORT) flash
make flash
idf.py -p (PORT) monitor
make monitor
```

Each command has a make equivalent, so the Makefile at the repository root covers the same ground. The Makefile is small and points at the standard IDF project machinery, with the project name set to hidd_demos. The constraint to note is the one in bold in the documentation: the currently tested IDF version is release/v5.0, and other versions are not supported. That is narrower than it sounds for a project whose last push was on 2026-09-08, because a firmware repository that pins a single toolchain release gives you a reproducible build but also freezes you on that toolchain until the pin moves.

## The serial monitor doubles as a mouse and keyboard test harness

The monitor console is not only for log output. The documentation notes that basic mouse and keyboard HID reports can be triggered from the keyboard while the monitor is running, which gives you a way to test the Bluetooth side without any external controller attached. The key map is short: w, a, s and d move the mouse up, left, down and right in 30 pixel steps, where the step size comes from the MOUSE_SPEED define; l and r trigger a left and a right mouse click; and q types the letter y on a US layout, which the documentation describes as a test of the keyboard reports. That is a complete smoke test in seven keystrokes, and it is the fastest way to find out whether a pairing problem is in the firmware or in the host before any assistive hardware is involved.

## The second UART speaks a dollar-prefixed command protocol

The external controller interface is the part meant for real products. Each command starts with a dollar sign, then an uppercase command name, then a variable number of parameters, and every command must be terminated by a line feed character. The available commands cover identification, pairing and device switching:

```bash
$ID
$GP
$GC
$SW
$DP
$PM
$NAME
$UG
$SV
$GV
$CV
```

$ID prints the firmware version. $GP lists the MAC addresses of paired devices, and the order it prints is the pairing numbering used by $DP. $GC lists currently connected devices in connection order. $SW switches which connected device receives the HID packets, taking a Bluetooth address such as 001122334455. $PM enables or disables discovery and advertising and terminates an existing connection when enabled. $NAME sets the BLE device name, with a restart required. $UG switches the boot partition to factory and restarts the device so it can receive a firmware binary over UART2. The $SV, $GV and $CV trio stores, reads and clears key/value pairs in the ESP32 NVS storage, and the documentation notes that keys must not contain spaces. The authors also state that they do not test this interface on a regular basis, which is the honest caveat to plan around.

## The HID report format is Adafruit EZKey compatible, with a US layout only

The wire format is the one used by the Adafruit EZKey HID module, and the project adds a few backwards compatible features on top. That compatibility is the design's key decision, and it is also what makes the project different from a bare ESP32 BLE HID example. A mouse report is nine bytes: a 0xFD marker, a don't care byte, a 0x03 identifier, then the button mask, the X axis, the Y axis, the wheel, and two don't care bytes. A keyboard report is also nine bytes: 0xFD, a modifier mask, a 0x00 identifier, then six keycode slots. Two limits follow directly from the format. The keyboard supports only the US layout, as the documentation states, which rules out the firmware for anything that needs a non-US character set without a translation layer. And the format is a serial module convention rather than a standard HID descriptor, so any host that expects a full keyboard and mouse composite device still has to be tested one by one.

## Compatibility is the real constraint, and it is documented as a table

The project page opens with an honest warning: given the wide variety of hardware and software combinations, it is hard to guarantee compatibility, although the team tries to test as many devices as possible. The table of tested devices is the most useful part of the documentation. A Lenovo T440s on Debian Buster and a PC with a CSR 4.0 Bluetooth dongle on Windows 10 Build 2004 work for both mouse and keyboard, as does a MacBook Pro Mid 2012 on macOS Mojave 10.14 and a Xiaomi Mi A1 on LineageOS 16.0. The one total failure in the table is a Lenovo T440s running Windows 10 Build 2004 inside VirtualBox, marked no for both mouse and keyboard. iPads are marked yes for keyboard, and for mouse only with Assistive Touch, and on some iPad models a Bluetooth menu notification warns that the device may affect WiFi or Bluetooth performance, which the documentation says can be ignored since there is no clear reason for the message. The project asks for compatibility reports through an issue with the device-testreport label. On licences, the repository carries a GPL-3.0 LICENSE file, and the releases stop at v0.3.7 on 2024-03-26, with v0.3.6 covering iOS 16 gamepad activation and v0.3.5 adding gamepad support.

## Conclusion

esp32_mouse_keyboard suits a hardware team building an assistive input device around an ESP32 that has to appear to a phone or tablet as a plain HID keyboard and mouse, and it does not suit anyone who needs a non-US keyboard layout, a guaranteed pairing with a specific host, or a keyboard report format other than the Adafruit EZKey one. Verify three things first: that your host appears in the tested device table with both mouse and keyboard marked yes, that you can build against ESP-IDF release/v5.0 since the documentation states other versions are not supported, and that the board type you select in idf.py menuconfig matches the hardware you are flashing.

## FAQ

### Which ESP-IDF version does esp32_mouse_keyboard require?

The documentation states that the currently tested IDF version is release/v5.0 and that other versions are not supported, with the build, flash and monitor commands run through idf.py or their make equivalents.

### How does an external microcontroller control the esp32_mouse_keyboard firmware?

Over a second UART using a text protocol where each command starts with a dollar sign and an uppercase name and ends with a line feed, for example $ID for the firmware version and $SV to store a key/value pair in NVS storage.

### Does esp32_mouse_keyboard support non-US keyboard layouts?

No. The documentation states that only the US keyboard layout is currently supported, and the keycode report format is the one compatible with the Adafruit EZKey module.

### Which boards can the esp32_mouse_keyboard firmware be flashed onto?

The esp32miniBT module in the repository and the Arduino Nano RP2040 Connect, with the correct board type selected in idf.py menuconfig, or a custom board with the external UART settings configured there.

## Sources

- [asterics/esp32_mouse_keyboard on GitHub](https://github.com/asterics/esp32_mouse_keyboard)
- [Issues](https://github.com/asterics/esp32_mouse_keyboard/issues)
- [License: GPL-3.0](https://github.com/asterics/esp32_mouse_keyboard/blob/master/LICENSE)
- [README](https://github.com/asterics/esp32_mouse_keyboard/blob/master/README.md)
- [Releases](https://github.com/asterics/esp32_mouse_keyboard/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/asterics-esp32-mouse-keyboard
