PicoGhostHID is native Raspberry Pi Pico firmware that makes a Pico appear as a
USB HID keyboard and mouse. It can periodically move the mouse, send small
random keyboard actions, follow an active-hours schedule, and pause/resume from
the Pico BOOTSEL button.
It runs directly on Pico hardware through TinyUSB. No Linux USB gadget mode, Python runtime, SSH setup, or host-side service is required after flashing.
Ready-built UF2 firmware files are published in the GitHub Releases section.
Download the file for your board, put the Pico into BOOTSEL mode, and copy
the UF2 onto the mounted boot drive:
PicoGhostHID-pico1.uf2for Raspberry Pi Pico / RP2040PicoGhostHID-pico2.uf2for Raspberry Pi Pico 2 / RP2350
- USB HID composite keyboard and mouse device
- Pico 1 and Pico 2 firmware builds
- Logitech-style VID/PID and product strings
- Smooth Bezier-style mouse movement with jitter/nudge actions
- Independent randomized keyboard action emitter
- Active-hours and lunch-break schedule configured over HID feature reports
BOOTSELbutton pause/resume with LED status- GitHub Actions builds and tagged release artifacts
The Pico has no battery-backed clock by default. Time and schedule settings are volatile and must be synced again after reset or unplug.
On Ubuntu/Debian, install the Pico build tools and ARM embedded compiler system-wide:
sudo apt-get update
sudo apt-get install -y \
build-essential \
cmake \
git \
python3 \
gcc-arm-none-eabi \
binutils-arm-none-eabi \
libnewlib-arm-none-eabi \
libnewlib-devIf CMake needs to build picotool from source on your machine, these packages
may also be required:
sudo apt-get install -y pkg-config libusb-1.0-0-devThis project uses the official Raspberry Pi Pico C/C++ SDK:
https://github.com/raspberrypi/pico-sdk
Fetch a local SDK checkout, then build:
./scripts/fetch_sdk.sh
./scripts/build_pico1.sh
./scripts/build_pico2.shBy default, fetch_sdk.sh checks out SDK release 2.3.0 into
deps/pico-sdk. To use another release or branch:
PICO_SDK_VERSION=master ./scripts/fetch_sdk.shYou can also skip deps/pico-sdk and point at an existing SDK checkout:
export PICO_SDK_PATH=/path/to/pico-sdk
./scripts/build_pico2.shThe firmware will be produced as one of:
build/pico1/PicoGhostHID.uf2
build/pico2/PicoGhostHID.uf2
If CMake was previously configured with a different compiler or toolchain path, regenerate the relevant build directory before building again:
cmake -E rm -rf build/pico2
./scripts/build_pico2.shTo flash it, hold the Pico BOOTSEL button while plugging it in, then copy the
UF2 file to the mounted RPI-RP2 drive.
Or use the upload wrappers:
./scripts/upload_pico1.sh
./scripts/upload_pico2.shThe repository includes a firmware workflow that builds both Pico targets on pushes, pull requests, and manual runs. Each run uploads UF2 and ELF artifacts:
PicoGhostHID-pico1.uf2PicoGhostHID-pico1.elfPicoGhostHID-pico2.uf2PicoGhostHID-pico2.elf
Pushing a tag that starts with v creates an automated GitHub release and
attaches those firmware files:
git tag v0.1.0
git push origin v0.1.0Edit include/ghost_config.h before building.
Useful knobs:
GHOST_STARTUP_DELAY_MSGHOST_MIN_IDLE_MSGHOST_MAX_IDLE_MSGHOST_KEY_MIN_IDLE_MSGHOST_KEY_MAX_IDLE_MSGHOST_MOVE_CONTROL_JITTERGHOST_MOVE_WOBBLE_MAXGHOST_DEFAULT_PROFILEGHOST_USB_SERIAL, passed to CMake as the HID USB serial stringGHOST_ACTIVITY_LED_PULSE_MSGHOST_BOOTSEL_PAUSE_ENABLED
The default profile runs mouse movement and keyboard activity as separate random emitters. The current key action set is Space, Escape, Tab, Alt+Tab, Windows/Super, Shift+Tab, and Ctrl+Esc. Keep in mind the key press goes to whichever host window is focused.
With GHOST_BOOTSEL_PAUSE_ENABLED set, pressing the Pico BOOTSEL button
while the firmware is running toggles pause/resume. Paused mode suppresses HID
activity and holds the onboard LED on. This uses the Pico SDK/TinyUSB
flash-chip-select sampling trick rather than a normal GPIO input, so it is best
treated as a temporary convenience. A dedicated GPIO button is the more robust
long-term physical pause control.
The default USB serial is fedcba9876543210, matching the original GhostHID
fallback value. You can override it at configure time:
cmake -E rm -rf build
GHOST_USB_SERIAL=0123456789abcdef ./scripts/build_pico2.shThe firmware accepts volatile time/schedule configuration through a vendor-defined HID feature report on the existing keyboard/mouse HID interface. It does not add a USB serial port.
Sync local host time and enable a 09:00-17:00 window with a 12:00 lunch break:
tools/picoghost_config.py configure --start 09:00 --end 17:00 --lunch 12:00 --lunch-duration 60Read current status:
tools/picoghost_config.py statusDisable the schedule and return to always-active behavior while mounted:
tools/picoghost_config.py set-schedule --no-enableThe Pico has no battery-backed clock by default, so time and schedule state are lost after reset or unplug.
PicoGhostHID/
CMakeLists.txt
LICENSE
pico_sdk_import.cmake
include/
ghost_config.h
ghost_runtime.h
tusb_config.h
usb_descriptors.h
src/
main.c
usb_descriptors.c
tools/
picoghost_config.py
PicoGhostHID is licensed under the GNU General Public License version 3 or
later. See LICENSE for the full license text.
- Add a physical enable/disable button.
- Add flash-backed configuration.
- Add persistent schedule configuration.
- Add optional external RTC support for timekeeping across unplug/reset.
- Split keyboard text generation into a separate, opt-in behavior module.