An open-source keyboard and mouse sharing switch for two nearby computers. PC 1 captures the USB input and sends it over serial to an ESP32; PC 2 sees the ESP32 as a normal Bluetooth Low Energy keyboard and mouse.
USB keyboard + mouse
│
▼
PC 1 (Linux/X11) ── USB serial ──► ESP32 ── BLE HID ──► PC 2
Press Scroll Lock once to move both devices to PC 2. Press it again to return them to PC 1. PC 2 needs no client software or network connection.
| Component | Tested |
|---|---|
| Keyboard | Logitech K270 receiver (046d:4003) |
| Mouse | Logitech M331/B330/M330 receiver (046d:4057) |
| Bridge | ESP32-WROOM-32D (classic ESP32) |
| PC 1 | Linux, systemd-logind, X11 |
| PC 2 | Windows with Bluetooth Low Energy |
Other USB keyboards and mice can be selected at runtime, but are not yet part of the tested matrix.
- Python 3,
dbus-python, andxinputon PC 1 - PlatformIO Core to build and flash the firmware
- A classic ESP32 board with BLE support
- A BLE-capable target computer
On Debian or Ubuntu, install the host dependencies with:
sudo apt install python3 python3-dbus xinputClone the repository and flash the ESP32:
git clone https://github.com/cinunii/esp32-keyboard-mouse-switch.git
cd esp32-keyboard-mouse-switch
platformio run --target uploadIf several serial devices are connected, select the ESP32 explicitly:
platformio run --target upload --upload-port /dev/ttyUSB0Pair PC 2 with ESP32 Input Bridge, then start the host bridge on PC 1:
python3 host/bridge.pyThe bridge starts on PC 1. It restores local input when stopped with Ctrl+C
or when the BLE connection is lost.
List the IDs reported by the Linux input subsystem:
python3 host/bridge.py --list-devicesPass the selected IDs to the bridge:
python3 host/bridge.py \
--keyboard-id 046d:4003 \
--mouse-id 046d:4057Use the same ID for both options when a single receiver exposes both devices.
The serial port is detected when only one is present; otherwise pass
--serial /dev/ttyUSB0.
The host obtains input file descriptors from the active session through systemd-logind, so it does not require root or a persistent udev rule. In remote mode it disables only the selected X11 devices locally, while continuing to read their events.
Keyboard, mouse, wheel, and media-key reports are framed with SLIP and CRC-8 before crossing the USB serial link. The ESP32 validates each frame and exposes a composite BLE HID device. The wire format is documented in docs/protocol.md.
- PC 1 currently requires Linux with X11; Wayland is not supported.
- BLE HID is generally unavailable in BIOS/UEFI and before PC 2 loads Bluetooth.
- The keyboard report supports six simultaneous non-modifier keys.
- Compatibility beyond the tested hardware above is not guaranteed.
- Initial BLE bonding uses the
Just Worksassociation model. Pair in a trusted physical location; see SECURITY.md.
Run the host tests and build the firmware:
python3 -m unittest discover -s host -v
platformio runCI performs both checks on every push and pull request. Reports should not contain captured input, Bluetooth addresses, serial numbers, or credentials.
MIT. Dependencies retain their own licenses; see THIRD_PARTY.md. Logitech product names are trademarks of their respective owner. This project is independent and is not endorsed by Logitech.