A Python DSL for HID device protocols. Cross-platform, zero boilerplate.
Project description
hidproto
A Python DSL for HID device protocols. Define commands and effects as pure data, the runtime handles transport, discovery, checksums, and state tracking. Works on Linux, Windows, and macOS.
Why
Every HID device project (OpenRGB, keyRGB, rivalcfg, openrazer) rewrites the same boilerplate: open device, build reports, send ioctl, manage state. hidproto lets you define a protocol in ~50 lines of pure data and get a working device driver.
Existing Python RGB libraries (PyRGBDev, pychroma, python-rgbkeyboards) all depend on vendor SDKs and only work on Windows. hidproto talks HID directly, no vendor SDK needed.
Install
pip install hidproto # Linux (hidraw, zero deps)
pip install hidproto[hidapi] # Windows / macOS (cross-platform)
Platform support
| Platform | Transport | Dependencies |
|---|---|---|
| Linux | hidraw (native ioctl) | None |
| Windows | hidapi | pip install hidapi |
| macOS | hidapi | pip install hidapi |
On Linux, hidraw is used by default for zero-dependency operation. On other platforms, the hidapi backend is auto-selected. You can also force hidapi on Linux with pip install hidproto[hidapi].
Supported devices
25 protocols across 19 vendors, all auto-discovered:
| Vendor | Device | Effects |
|---|---|---|
| Alienware | AW510K | 7 (static, breathing, spectrum, wave, rainbow, scanner, off) |
| ASUS | TUF/ROG keyboards | 9 (static, breathing, wave, ripple, reactive, starry, rain, direct, off) |
| Cherry | MX Board | 8 (wave, spectrum, breathing, static, radar, fire, stars, rain) |
| CoolerMaster | MasterKeys Pro | 9 (direct, static, breathing, cycle, wave, ripple, snake, reactive, stars) |
| Corsair | K70/K95 | 7 (color shift, color pulse, rainbow wave, color wave, rain, spiral, visor) |
| Das | Q5 | XOR checksum protocol |
| Ducky | One 2 RGB | Multi-packet direct mode |
| Fnatic | Streak | 6 (pulse, wave, reactive, ripple, rain, fade) |
| HyperX | Alloy Elite | 8 (wave variants, static, breathing) with 6 directions |
| ITE | 8291 rev3 | 9 (breathing, wave, random, rainbow, ripple, marquee, raindrop, aurora, fireworks) |
| ITE | 8297 | Uniform color |
| ITE | 8910 | 11 (full per-key + animations with 8 wave / 4 snake directions) |
| Keychron | K3 V2 | 7 (static, breathing, spectrum, sparkle, rain, random, off) |
| Logitech | G815 (HID++) | 6 (off, static, spectrum, wave, breathing, ripple) |
| Mountain | Everest | 6 (static, breathing, wave, reactive, tornado, off) |
| MSI | Vigor GK30 | 7 (off, static, breathing, rainbow, meteor, ripple, dimming) |
| NZXT | Lift mouse | Direct LED control |
| Obinslab | Anne Pro 2 | Static mode |
| QMK | OpenRGB firmware | 8 (direct, solid, breathing, rainbow, swirl, snake, knight, splash) |
| Razer | BlackWidow | 5 (static, wave, breathing, spectrum, off) with XOR checksum |
| Redragon | M711 mouse | 5 (wave, breathing, static, rainbow, flashing) |
| Roccat | Vulcan | 3 (direct, static, wave) with 16-bit checksum |
| Sony | DualShock 4 | Lightbar RGB control |
| SteelSeries | Apex Pro | Direct mode + profiles |
| Wooting | 60HE | Magic byte protocol |
Adding a new device is one Python file in protocols/<vendor>/. The registry auto-discovers it.
Quick start
from hidproto import HIDDevice, HIDProtocol, command, effect
class MyKeyboard(HIDProtocol):
vendor_id = 0x048D
product_id = 0x8910
report_id = 0xCC
report_size = 6
rows = 6
cols = 20
preset_base = 0x71
custom_base = 0xA1
color_custom = 0xAA
animation_mode = command(0x00, args=1, doc="Animation mode")
set_led = command(0x01, args=4, doc="Per-key color")
brightness_speed = command(0x09, args=4, doc="Brightness + speed")
wave_slot = command(0x15, args=4, doc="Wave slot")
effects = {
"off": effect("off", animation=0x0C, needs_clear=True),
"wave": effect("wave", animation=0x04, slot_cmd="wave_slot",
directions=("up", "down", "left", "right")),
}
Keyboard = HIDDevice.for_protocol(MyKeyboard)
with Keyboard() as kb:
kb.brightness(8)
kb.speed(5)
kb.effect("wave", direction="right", color=(255, 0, 0))
No boilerplate, no subclassing, no transport code.
CLI
hidproto devices # list connected HID devices
hidproto info ite8910 # show commands, effects, matrix size
hidproto ite8910 wave -d right -b 8 -s 5 # wave rainbow, right, brightness 8
hidproto ite8910 wave -d left -c ff0000 # wave red, left
hidproto ite8910 breathing -c 00ff00 -b 8 # breathing green
hidproto ite8910 scan -c ff0000 --color2 0000ff # scan red + blue
hidproto ite8910 off # turn off
All options are auto-generated from the protocol definition. Each device gets its own subcommands with --help.
Features
- DSL -
command()andeffect()descriptors generate everything from pure data - Multi-step effects -
step()chains multiple commands for complex protocols (Corsair, Cherry) - Auto-discovery - protocols registered via entry points or filesystem scan
- Cross-platform - hidraw on Linux, hidapi on Windows/macOS
- Checksums - XOR (Razer, Das), SUM (Cherry), custom via
_with_checksum() - State caching - skip redundant sends, invalidate on resume
- CLI - Click-based with per-device subcommands
- GUI - Qt keyboard visualizer with per-key editing, color picker, auto-connect, dynamic effect controls (directions, colors, random toggle), brightness glow rendering
GUI
pip install hidproto[gui]
hidproto-gui
Auto-detects connected devices and shows the keyboard layout with per-key RGB editing. Effect controls (directions, color pickers, random toggle) are auto-generated from the protocol's EffectSpec.
Architecture
hidproto/
cli.py Click CLI with auto-generated subcommands
command.py CommandSpec + @command descriptor
effect.py EffectSpec + step() for multi-step effects
protocol.py HIDProtocol base (report building, transport)
device.py HIDDevice wrapper (effects, caching, brightness/speed)
transport.py HidrawTransport (Linux native)
transport_hidapi.py HidapiTransport (cross-platform)
discovery.py sysfs device discovery
registry.py Auto-discovery + entry point plugin system
checksum.py xor/sum checksum helpers
layout.py Key dataclass for keyboard layouts
gui/
app.py Qt main window with auto-connect
keyboard_widget.py Per-key RGB keyboard renderer
effect_panel.py Dynamic effect controls from EffectSpec
protocols/
alienware/ asus/ cherry/ coolermaster/
corsair/ das/ ducky/ fnatic/
hyperx/ ite/ keychron/ logitech/
mountain/ msi/ nzxt/ obinslab/
qmk/ razer/ redragon/ roccat/
sony/ steelseries/ wooting/
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hidproto-0.3.1.tar.gz.
File metadata
- Download URL: hidproto-0.3.1.tar.gz
- Upload date:
- Size: 31.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
667f22d44c5e8323af58a7f3ba9db5e655bd4d0f8883cfa63fbd51241312220b
|
|
| MD5 |
d4d923619a50770a54359a2343147428
|
|
| BLAKE2b-256 |
e44ae5f6c141e6be6102bbefb38446d08aae8f8e3ae4d134fd2ddc6d3e1fc289
|
Provenance
The following attestation bundles were made for hidproto-0.3.1.tar.gz:
Publisher:
publish.yml on Chocapikk/hidproto
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hidproto-0.3.1.tar.gz -
Subject digest:
667f22d44c5e8323af58a7f3ba9db5e655bd4d0f8883cfa63fbd51241312220b - Sigstore transparency entry: 1201524946
- Sigstore integration time:
-
Permalink:
Chocapikk/hidproto@65ae32e301a976dd8eceafdf5eac933defff1e02 -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/Chocapikk
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@65ae32e301a976dd8eceafdf5eac933defff1e02 -
Trigger Event:
push
-
Statement type:
File details
Details for the file hidproto-0.3.1-py3-none-any.whl.
File metadata
- Download URL: hidproto-0.3.1-py3-none-any.whl
- Upload date:
- Size: 50.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6b686606dca175a5feb1c8e8ca596b05b6e957310e008c50575c9b4e7fb45df2
|
|
| MD5 |
52b097fb383df14c2d781bb4835af3f1
|
|
| BLAKE2b-256 |
62fc56dc19054a0abdb1793eeb7be74c57689d782d5a3c63b8bd49b9c62e251b
|
Provenance
The following attestation bundles were made for hidproto-0.3.1-py3-none-any.whl:
Publisher:
publish.yml on Chocapikk/hidproto
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hidproto-0.3.1-py3-none-any.whl -
Subject digest:
6b686606dca175a5feb1c8e8ca596b05b6e957310e008c50575c9b4e7fb45df2 - Sigstore transparency entry: 1201524949
- Sigstore integration time:
-
Permalink:
Chocapikk/hidproto@65ae32e301a976dd8eceafdf5eac933defff1e02 -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/Chocapikk
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@65ae32e301a976dd8eceafdf5eac933defff1e02 -
Trigger Event:
push
-
Statement type: