This document is the single source of truth for feature parity between the USB HID protocol and BLE protocol paths in open-snek.
Target device baseline:
- Basilisk V3 X HyperSpeed (
USB PID 0x00B9,BT PID 0x00BA) - Basilisk V3 (
USB PID 0x0099, OpenRazer-backed USB profile only) - Basilisk V3 Pro (
USB PIDs 0x00AA, 0x00AB) - Basilisk V3 Pro Bluetooth (
BT PID 0x00AC) - Basilisk V3 35K (
USB PID 0x00CB)
Transport paths:
- USB/2.4GHz: 90-byte HID report protocol
- BLE: vendor GATT (
...1524/...1525) + selective HID fallback
Legend:
DONE: implemented and documented on both pathsPARTIAL: implemented but transport-dependent or not fully mappedUSB_ONLY: available only on USB pathBLE_ONLY: available only on BLE pathUNKNOWN: protocol not fully decoded
| Feature | USB Protocol | BLE Protocol | Script Support | Status | Notes |
|---|---|---|---|---|---|
| Serial read | 00:82 |
key 01 83 00 00 |
razer_usb.py + razer_ble.py (USB HID + BT vendor fallback) |
DONE | BT vendor fallback implemented |
| Firmware read | 00:81 |
unknown vendor key | razer_usb.py + razer_ble.py (HID path) |
PARTIAL | HID over BT may fail on some stacks |
| Device mode | 00:84/04 |
01 82 00 00 (read), 01 02 00 00 (write candidate) |
razer_usb.py + razer_ble.py |
PARTIAL | BT read fallback enabled; BT write path disabled for safety. OpenSnek writes/reads mode on USB and shows the card only when readback is available. |
| DPI XY | 04:85/05 |
passive HID read/listen; live apply via vendor stage writes | both scripts | PARTIAL | direct BT HID set_dpi is not reliable on validated stack, but OpenSnek now uses validated passive BT HID reports for immediate on-device DPI-change updates |
| DPI stages + active stage | 04:86/06 |
0B84/0B04, op=0x26 |
both scripts | DONE | OpenSnek normalizes active-stage via stage IDs and preserves USB stage IDs on writes to avoid off-by-one stage mapping. |
| Poll rate | 00:85/05 |
HID fallback only | both scripts | PARTIAL | Need BLE vendor equivalent |
| Battery level | 07:80 |
Battery Service + observed vendor read | both scripts | PARTIAL | Charging-state parity still incomplete on BLE |
| Idle time | 07:83/03 |
05 84 00 00 / 05 04 00 00 |
both scripts | DONE | BT vendor fallback implemented |
| Low battery threshold | 07:81/01 |
05 82 00 00 / 05 02 00 00 |
both scripts | DONE | BT vendor fallback implemented. OpenSnek supports read/write on USB + BT, and hides USB control when unsupported. |
| Scroll mode | 02:94/14 |
unknown vendor key | both scripts (HID path) | PARTIAL | USB semantics validated via OpenRazer. OpenSnek reads/writes on USB and hides the control when unsupported. |
| Scroll acceleration | 02:96/16 |
unknown vendor key | both scripts (HID path) | PARTIAL | BLE vendor mapping missing. OpenSnek reads/writes on USB and hides the control when unsupported. |
| Scroll smart reel | 02:97/17 |
unknown vendor key | both scripts (HID path) | PARTIAL | BLE vendor mapping missing. OpenSnek reads/writes on USB and hides the control when unsupported. |
| Scroll LED brightness | 0F:84/04 (VARSTORE, LED=0x01) |
unknown vendor key | both scripts (HID path) | PARTIAL | USB validated; BLE vendor key not mapped |
| Scroll LED effects | 0F:02 (none/spectrum/wave/static/reactive/breath) |
unknown vendor key | both scripts (HID path) | PARTIAL | USB validated on Basilisk V3 X; multi-zone IDs are also validated on Basilisk V3 Pro / 35K |
| Button remapping | class 0x02, 0x8C/0x0C button-function block |
vendor 08 04 01 <slot> + 10-byte payload |
BLE implemented + USB validated (OpenSnek + OpenSnekProbe) |
PARTIAL | USB uses profile,slot,hypershift + 7-byte function block (class,len,data[5]); mouse + simple keyboard remaps validate on 0x00B9, including default restore behavior and readback. BLE slot 0x06 remains rejected (status 0x03); macro/media catalogs still pending on both paths. |
| Lighting/effects | class 0x0F (OpenRazer documented) |
scalar brightness (10 85/10 05), legacy frame stream (10 84/10 04), and V3 Pro zone static state (10 83/10 03) |
USB zone writes + BLE zone brightness/static-color writes | PARTIAL | OpenSnek now ships static-color Bluetooth lighting for the Basilisk V3 Pro by fanning out per-zone 10 03/10 05 writes across 0x01, 0x04, and 0x0A. Advanced BLE effect streaming remains unshipped. |
| Profiles | partially documented in ecosystem | unknown | none | UNKNOWN | Needs capture-backed mapping |
- Decode remaining BLE vendor keys for USB-equivalent controls:
- poll rate
- scroll mode / acceleration / smart reel
- firmware
- Expand USB button-remap action taxonomy:
- validate advanced classes (consumer/media, macro families, analog variants)
- tighten profile-layer semantics (
directvs persistent) and document per-device differences
- Build common feature abstraction:
- one logical setting model with transport-specific encoders
- predictable fallback ordering per feature
Validated in-session over USB:
- working: serial, firmware, device mode read/write, poll-rate read/write, idle-time read/write, low-battery-threshold read/write, DPI/stages, battery
- working: OpenSnek now arms the shared passive HID DPI listener on the observed
0x01:0x06USB interfaces and upgrades to real-time HID updates once the host delivers a live callback - working: scroll LED brightness + effects (none/spectrum/wave/static/reactive/breath single/dual/random)
- working: button remap read/write on class
0x02(0x8C/0x0C) for tested slots (0x01..0x05,0x09,0x0A,0x60) with readback confirmation viaOpenSnekProbeand hardware XCTest harness - observed non-remappable control on
0x00B9: Hypershift / Boss-sniper slot0x06returns status0x03on0x02:0x8Creads and is outside the validated USB button-function path - unsupported (returns
None): scroll mode, scroll acceleration, scroll smart reel - legacy non-analog remap write (
0x02:0x0D) remains unreliable on this model and is now treated as fallback-only
CLI behavior has been updated to skip unsupported scroll controls with warnings instead of failing runs.
Validated in-session over USB:
- working: serial, firmware, device mode read/write, poll-rate read/write, DPI/stages, battery, core USB telemetry
- working: OpenSnek now arms the shared passive HID DPI listener on the observed
0x01:0x06USB interfaces and upgrades to real-time HID updates once the host delivers a live callback - working: matrix brightness/effect writes on all validated LED IDs (
0x01scroll wheel,0x04logo,0x0Aunderglow) - working: button remap read/write/readback on standard slots plus the additional sensitivity clutch / DPI clutch (
0x0F), wheel-tilt (0x34,0x35), and top DPI-button (0x60) slots - observed clutch behavior on
0x00CB: native slot0x0Fdefault reads back as06 01 05 01 90 01 90, accepts remap writes, and also accepts the V3 Pro-style06 05 05 <dpi> <dpi>DPI-clutch payload; the same DPI-clutch payload also round-trips on slot0x04 - observed non-remappable controls on
0x00CB: scroll-mode (0x0E, protocol-read-only), profile button (0x6A, software-read-only via report-40x50) - observed alternate USB DPI-button payload on slot
0x60:04 02 0F 7B 00 00 00 - shipped client behavior: normalize
0x60to a user-facingDPI Cycleaction and allow bindingDPI Cycleto any writable USB slot - observed HID candidates on an attached
0x00CB:0x01:0x06interfaces withinput=16/8andfeature=1/0, matching the tuple already used for the shipped V3 Pro USB passive DPI listener - client note:
0x02:0x8Cresponse layout is not identical to0x00B9; clients must validate echoedprofile/slotbytes before choosing the 35K function-block offset - observed profile summary getter on
0x00CB:0x00:0x87-><active,0x00,count> - tested active-profile write candidates on
0x00CB:0x00:0x07with payloads02,02 00,02 00 05, and02 00 00all returned status0x05(not supported) - observed profile-model behavior on
0x00CB: persistent slot0x05writes stay isolated, persistent slot0x01writes mirror into direct/live0x00while profile1is active, and later direct/live writes do not write back into persistent slot0x01 - shipped client behavior: per-slot button-function reads/writes remain available to the backend and probe tooling, but the UI keeps onboard button-profile controls disabled until the hardware-selected active-slot model is validated
Mapped from current OpenRazer source, not yet validated in-session with OpenSnek hardware:
- OpenRazer advertises the wired Basilisk V3 as
USB PID 0x0099withDPI_MAX = 26000 - OpenSnek currently maps the wired V3 onto the shipped 35K-style USB profile shape for button slots, multi-zone lighting targets, passive HID DPI listener matching, and
5onboard profiles - OpenSnek caps DPI edits/readback for this profile at
26,000instead of the 35K profile's35,000 - until local protocol captures confirm otherwise, this profile should be treated as best-known support derived from ecosystem sources rather than hardware-validated parity
Validated in-session over USB:
- current alias note: a directly cabled V3 Pro now enumerates as
1532:00AAon the observed macOS host, and OpenSnek maps it onto the same shipped USB profile as1532:00AB - working: serial, firmware, device mode read/write, poll-rate read/write, DPI/stages, battery, core USB telemetry
- working: matrix brightness/effect writes on all validated LED IDs (
0x01scroll wheel,0x04logo,0x0Aunderglow) - working: button remap read/write/readback on the shared writable Basilisk slots, wheel-tilt (
0x34,0x35), and the sensitivity clutch / DPI clutch (0x0F) - observed V3 Pro clutch default block on
0x0F:06 05 05 01 90 01 90 - observed V3 Pro clutch DPI parameterization: writing
06 05 05 03 20 03 20read back cleanly as an 800-DPI clutch payload on slot0x04 - observed V3 Pro clutch remap portability: the same block was written/read back successfully on slot
0x04, so OpenSnek treatsDPI Clutchas a V3 Pro USB remap action and not only as the native clutch button's default - observed V3 Pro wheel-tilt scroll blocks on 2026-04-03 after a working Synapse rebind: slot
0x34read back0e036800140000and slot0x35read back0e036900140000on both persistent and direct layers - inferred client behavior: OpenSnek now uses that same wheel-tilt block for the shared Basilisk V3 / V3 Pro / 35K USB family because those profiles already share the same tilt slots and action taxonomy; only the V3 Pro form is directly hardware-validated so far
- observed profile-button default block on
0x6A:12 01 01 00 00 00 00 - observed profile-button remap behavior on
0x6A: right-click writes/readback can succeed, but repeated write/readback cycles later returned timeout/no-response frames; OpenSnek keeps this slot hidden until the USB ACK/readback path is reliable - observed non-match on
0x60: it does not read back like the 35K top DPI-button block and is not exposed as a validated V3 Pro slot - client note:
0x02:0x8Cresponse layout on the observed extended slots matches the 35K-style offset (response[11..<18]) rather than the Basilisk V3 X shape - observed V3 Pro profile summary reads from
0x00:0x87have not been trustworthy enough to ship as UI state: on March 25, 2026 the bottom profile LED changed while the register continued to report02 00 03 - shipped client behavior: the V3 Pro still uses the validated USB button-function protocol for direct slot read/write/readback work, but OpenSnek keeps onboard profile controls out of the UI until selected-profile semantics are understood
Validated in-session over Bluetooth:
- HID path (
--disable-vendor-gatt): probe works, config command reads returnNone, writes returnFalse - passive HID DPI report on the paired BT HID interface now drives immediate OpenSnek DPI-state updates; observed/app-supported frame prefixes include
05 05 02 <x_hi> <x_lo> <y_hi> <y_lo> ...and the macOS-normalized05 02 ...variant - Vendor GATT path (default-on): working for
- idle-time raw read/write/readback
- low-battery-threshold raw read/write/readback
- lighting raw read/write/readback
- battery vendor raw keys (
05 81 00 01,05 80 00 01) - serial fallback (
01 83 00 00) - device mode read fallback (
01 82 00 00) - idle time fallback (
05 84 00 00/05 04 00 00) - low battery threshold fallback (
05 82 00 00/05 02 00 00) - button remap slots
0x01..0x05,0x09,0x0A,0x60
- Vendor GATT button remap slot
0x06returns error status (0x03) and is treated as a software-read-only Hypershift/sniper control on the current BLE path. scroll-up-down-rebind.pcapngconfirms slot0x09/0x0Awheel-button mappings on BLE (p0=0x0901/0x0A01).right-click-turbo.pcapngconfirms mouse turbo payloads on BLE (action=0x0E, slot0x02) with changing rate field.basic-rebind.pcapngincludes a keyboard turbo-form payload (action=0x0D, key + rate fields).
razer_ble.py now uses vendor battery raw as BT fallback in get_battery() when vendor GATT is enabled.
Validated in-session over Bluetooth:
- vendor GATT path uses the same request headers and key catalog as the Basilisk V3 X HyperSpeed path, but the notify header is the shorter 8-byte variant and payload continuations may end with a short final fragment
- passive HID DPI reports are present on the paired BT HID interface with the same
05 05 02 <x_hi> <x_lo> <y_hi> <y_lo> ...shape used by the validated V3 X Bluetooth path; a live macOS callback capture on0x00ACobserved900,2000, and1100DPI stage frames - working read/write/readback: DPI stages + active stage (
0B84/0B04), sleep timeout (05 84 00 00/05 04 00 00), per-zone lighting brightness (10 85 01 <led>/10 05 01 <led>), per-zone static color (10 83 00 <led>/10 03 00 <led>) - working read: battery raw (
05 81 00 01), battery status (05 80 00 01) - working write ACKs on tested BLE button-remap slots:
0x01..0x05,0x09,0x0A,0x34,0x35 - observed V3 Pro Bluetooth button-layout shape now matches the shared Basilisk family on the tested slots, so OpenSnek ships the core buttons plus wheel-tilt controls on the BT profile
- observed V3 Pro Bluetooth wheel-tilt scroll blocks on 2026-04-03 after a working Synapse rebind: slot
0x34/0x35read from BLE key08 84 01 34/08 84 01 35resolve to the raw function blocks0e036800140000/0e036900140000 - shipped client behavior: OpenSnek now uses that same raw
0x0Ewheel-tilt block for BluetoothScroll Left/Scroll Rightwrites and for wheel-tilt default restore on the V3 Pro BT path - observed V3 Pro Bluetooth lighting zone catalog:
10 80 00 01->04 01 0a, matching the validated zone mapscroll_wheel,logo,underglow - not yet decoded enough to ship: sensitivity clutch (
0x0F) restore/remap payloads, profile button (0x6A) restore/remap payloads - legacy lighting frame-color readback on
10 84 00 00still does not return a usable payload on the V3 Pro path; OpenSnek now treats that frame family as legacy-only and uses the validated zone-state keys instead
Validation notes:
- the required hardware XCTest gate (
OPEN_SNEK_HW=1 swift test --package-path OpenSnek --filter HardwareDpiReliabilityTests) currently aborts under macOS TCC before CoreBluetooth can start in the unbundled test runner on this host - the same five-step DPI stability sequence was rerun successfully through the bundled OpenSnek app/service host, and every step converged for three consecutive reads before restore
Per feature validation should include:
- set operation ACK/success
- read-back value match
- persistence check after reconnect/power-cycle (when applicable)
- behavior verification on hardware (button/scroll/lighting effects)
- USB Protocol
- BLE Protocol
- BLE Reverse Engineering Notes
- OpenRazer driver protocol builders (
driver/razerchromacommon.c/.h)