docs: translate Bragi protocol reference to English
Translate docs/bragi-protocol.md from German to English ahead of open-source publication. Drop the local reference path and note additional Bragi devices (HS65, Virtuoso SE).
This commit is contained in:
+75
-75
@@ -1,136 +1,136 @@
|
||||
# Bragi-Protokoll — Reverse-Engineerte Dokumentation
|
||||
# Bragi Protocol — Reverse-Engineered Documentation
|
||||
|
||||
Dieses Dokument beschreibt das Corsair Bragi HID-Protokoll, wie es von neueren
|
||||
Corsair-Wireless-Geräten (HS80 RGB Wireless, etc.) verwendet wird. Reverse-Engineered
|
||||
aus USB-Traces und den Python-Probes in `~/Projects/hs80-battery/`.
|
||||
This document describes the Corsair Bragi HID protocol used by newer Corsair
|
||||
wireless devices (HS80 RGB Wireless, HS65, Virtuoso SE, etc.). Reverse-engineered
|
||||
from USB traces and protocol analysis.
|
||||
|
||||
## Übersicht
|
||||
## Overview
|
||||
|
||||
Bragi kommuniziert über HID Feature Reports auf **Interface 3** des USB-Receivers.
|
||||
Jedes Paket ist 65 Bytes (1 Byte Report ID + 64 Bytes Daten).
|
||||
Bragi communicates via HID Feature Reports on **Interface 3** of the USB receiver.
|
||||
Each packet is 65 bytes (1 byte Report ID + 64 bytes data).
|
||||
|
||||
## Paketformat
|
||||
## Packet Format
|
||||
|
||||
### Request (Host → Gerät)
|
||||
### Request (Host → Device)
|
||||
|
||||
```
|
||||
Byte 0: 0x00 — HID Report ID
|
||||
Byte 1: 0x02 — Protokoll-Marker (immer 0x02)
|
||||
Byte 1: 0x02 — Protocol marker (always 0x02)
|
||||
Byte 2: Endpoint — 0x08 = Receiver, 0x09 = Headset (via Receiver)
|
||||
Byte 3: Command — 0x01 = SET, 0x02 = GET
|
||||
Byte 4: Property — Property-ID (siehe unten)
|
||||
Byte 5+: Daten — Bei SET: die zu setzenden Werte
|
||||
Rest: 0x00-gepaddet auf 65 Bytes
|
||||
Byte 4: Property — Property ID (see below)
|
||||
Byte 5+: Data — For SET: the values to write
|
||||
Rest: 0x00-padded to 65 bytes
|
||||
```
|
||||
|
||||
### Response (Gerät → Host)
|
||||
### Response (Device → Host)
|
||||
|
||||
```
|
||||
Byte 0: 0x01 — Report-Typ (immer 0x01, NICHT 0x02 wie im Request)
|
||||
Byte 1: Endpoint — 0x00 = Receiver, 0x01 = Headset (andere IDs als im Request!)
|
||||
Bei Fehler: 0xF0/0xF1 = Error/Not Supported
|
||||
Byte 0: 0x01 — Report type (always 0x01, NOT 0x02 like the request marker)
|
||||
Byte 1: Endpoint — 0x00 = Receiver, 0x01 = Headset (different IDs than request!)
|
||||
On error: 0xF0/0xF1 = Error/Not Supported
|
||||
Byte 2: Command — Echo: 0x01 = SET, 0x02 = GET
|
||||
Byte 3: Status — 0x00 = OK
|
||||
Byte 4+: Daten — Property-Wert (typisch uint16 Little-Endian in Bytes 4-5)
|
||||
Byte 4+: Data — Property value (typically uint16 Little-Endian in bytes 4-5)
|
||||
```
|
||||
|
||||
**Achtung:** Das Response-Format weicht vom Request-Format ab:
|
||||
- Byte 0 ist `0x01` (nicht `0x02` wie der Request-Marker)
|
||||
- Endpoint-IDs sind `0x00`/`0x01` (nicht `0x08`/`0x09` wie im Request)
|
||||
**Note:** The response format differs from the request format:
|
||||
- Byte 0 is `0x01` (not `0x02` like the request marker)
|
||||
- Endpoint IDs are `0x00`/`0x01` (not `0x08`/`0x09` like in the request)
|
||||
|
||||
**Fehler-Erkennung:** Byte 1 == 0xF0 oder 0xF1 bedeutet, dass die Property nicht
|
||||
unterstützt wird oder der Request ungültig war.
|
||||
**Error detection:** Byte 1 == 0xF0 or 0xF1 indicates that the property is not
|
||||
supported or the request was invalid.
|
||||
|
||||
## Endpoints
|
||||
|
||||
| ID | Name | Beschreibung |
|
||||
| ID | Name | Description |
|
||||
|------|----------|---------------------------------|
|
||||
| 0x08 | Receiver | Der USB-Dongle selbst |
|
||||
| 0x09 | Headset | Das verbundene Wireless-Gerät |
|
||||
| 0x08 | Receiver | The USB dongle itself |
|
||||
| 0x09 | Headset | The connected wireless device |
|
||||
|
||||
## Commands
|
||||
|
||||
| ID | Name | Beschreibung |
|
||||
| ID | Name | Description |
|
||||
|------|------|-----------------------|
|
||||
| 0x01 | SET | Property-Wert setzen |
|
||||
| 0x02 | GET | Property-Wert lesen |
|
||||
| 0x01 | SET | Set a property value |
|
||||
| 0x02 | GET | Read a property value |
|
||||
|
||||
## Properties
|
||||
|
||||
| ID | Name | Typ | Beschreibung |
|
||||
| ID | Name | Type | Description |
|
||||
|------|-------------------|---------|-----------------------------------------------|
|
||||
| 0x01 | Polling Rate | uint16 | Polling-Rate in Hz |
|
||||
| 0x02 | Brightness | uint16 | LED-Helligkeit (0-1000) |
|
||||
| 0x01 | Polling Rate | uint16 | Polling rate in Hz |
|
||||
| 0x02 | Brightness | uint16 | LED brightness (0-1000) |
|
||||
| 0x03 | Mode | uint8 | 0x01 = Hardware, 0x02 = Software |
|
||||
| 0x09 | Sidetone | uint16 | Sidetone-Level |
|
||||
| 0x0F | Battery Level | uint16 | Batterie in Promille (0-1000, /10 = Prozent) |
|
||||
| 0x10 | Battery Status | uint8 | Lade-/Entladestatus (siehe unten) |
|
||||
| 0x09 | Sidetone | uint16 | Sidetone level |
|
||||
| 0x0F | Battery Level | uint16 | Battery in per-mille (0-1000, /10 = percent) |
|
||||
| 0x10 | Battery Status | uint8 | Charging/discharging status (see below) |
|
||||
| 0x11 | Vendor ID | uint16 | USB Vendor ID |
|
||||
| 0x12 | Product ID | uint16 | USB Product ID |
|
||||
| 0x13 | App Firmware | uint16 | Applikations-Firmware-Version |
|
||||
| 0x14 | Build Firmware | uint16 | Build-Firmware-Version |
|
||||
| 0x15 | Radio App FW | uint16 | Radio-Applikations-Firmware |
|
||||
| 0x16 | Radio Build FW | uint16 | Radio-Build-Firmware |
|
||||
| 0x13 | App Firmware | uint16 | Application firmware version |
|
||||
| 0x14 | Build Firmware | uint16 | Build firmware version |
|
||||
| 0x15 | Radio App FW | uint16 | Radio application firmware |
|
||||
| 0x16 | Radio Build FW | uint16 | Radio build firmware |
|
||||
|
||||
## Battery Status Werte
|
||||
## Battery Status Values
|
||||
|
||||
Empirisch ermittelt am HS80 RGB Wireless (2026-03-27).
|
||||
Weicht von ckb-next-Quellen ab — dort sind die Werte anders zugeordnet.
|
||||
Empirically determined on the HS80 RGB Wireless.
|
||||
Differs from ckb-next sources where values are mapped differently.
|
||||
|
||||
| Wert | Bedeutung |
|
||||
|------|---------------|
|
||||
| Value | Meaning |
|
||||
|-------|---------------|
|
||||
| 0x00 | Offline |
|
||||
| 0x01 | Laden |
|
||||
| 0x02 | Entladen |
|
||||
| 0x03 | Niedrig |
|
||||
| 0x04 | Voll geladen |
|
||||
| 0x01 | Charging |
|
||||
| 0x02 | Discharging |
|
||||
| 0x03 | Low |
|
||||
| 0x04 | Fully charged |
|
||||
|
||||
## Initialisierungssequenz
|
||||
## Initialization Sequence
|
||||
|
||||
Das Gerät muss in den Software-Modus versetzt werden, bevor Properties gelesen werden
|
||||
können. Die vollständige Sequenz:
|
||||
The device must be switched to software mode before properties can be read.
|
||||
Full sequence:
|
||||
|
||||
### Phase 1: Receiver initialisieren
|
||||
### Phase 1: Initialize Receiver
|
||||
|
||||
1. **Wake-Up:** `GET App Firmware` an Receiver (0x08)
|
||||
- Weckt den Receiver auf und bestätigt Kommunikation
|
||||
2. **Software-Modus:** `SET Mode = 0x02` an Receiver (0x08)
|
||||
- Schaltet Receiver in Software-Modus
|
||||
3. **Heartbeat:** `GET Product ID` an Receiver (0x08)
|
||||
- Bestätigt dass Receiver im Software-Modus antwortet
|
||||
1. **Wake-up:** `GET App Firmware` to Receiver (0x08)
|
||||
- Wakes the receiver and confirms communication
|
||||
2. **Software mode:** `SET Mode = 0x02` to Receiver (0x08)
|
||||
- Switches receiver to software mode
|
||||
3. **Heartbeat:** `GET Product ID` to Receiver (0x08)
|
||||
- Confirms receiver responds in software mode
|
||||
|
||||
### Phase 2: Headset initialisieren
|
||||
### Phase 2: Initialize Headset
|
||||
|
||||
4. **Software-Modus:** `SET Mode = 0x02` an Headset (0x09)
|
||||
- Schaltet Headset in Software-Modus (via Receiver)
|
||||
5. **Flush:** HID-Puffer leeren (nonblocking reads bis leer)
|
||||
6. **Heartbeat:** `GET Product ID` an Headset (0x09)
|
||||
- Bestätigt dass Headset erreichbar ist und antwortet
|
||||
- Keine Antwort = Headset ausgeschaltet/nicht verbunden
|
||||
4. **Software mode:** `SET Mode = 0x02` to Headset (0x09)
|
||||
- Switches headset to software mode (via receiver)
|
||||
5. **Flush:** Clear HID buffer (non-blocking reads until empty)
|
||||
6. **Heartbeat:** `GET Product ID` to Headset (0x09)
|
||||
- Confirms headset is reachable and responding
|
||||
- No response = headset powered off / not connected
|
||||
|
||||
### Cleanup
|
||||
|
||||
Nach allen Abfragen **müssen** beide Geräte zurück in den Hardware-Modus:
|
||||
After all queries, both devices **must** be switched back to hardware mode:
|
||||
|
||||
7. `SET Mode = 0x01` an Headset (0x09)
|
||||
8. `SET Mode = 0x01` an Receiver (0x08)
|
||||
7. `SET Mode = 0x01` to Headset (0x09)
|
||||
8. `SET Mode = 0x01` to Receiver (0x08)
|
||||
|
||||
**Wichtig:** Ohne Cleanup bleibt das Gerät im Software-Modus und verhält sich
|
||||
möglicherweise nicht normal (z.B. keine automatische Abschaltung).
|
||||
**Important:** Without cleanup the device stays in software mode and may not
|
||||
behave normally (e.g. no automatic power-off).
|
||||
|
||||
## Wert-Extraktion
|
||||
## Value Extraction
|
||||
|
||||
Für uint16-Werte: Little-Endian aus Response-Bytes 4 und 5:
|
||||
For uint16 values: Little-Endian from response bytes 4 and 5:
|
||||
```
|
||||
value = response[4] | (response[5] << 8)
|
||||
```
|
||||
|
||||
Für Batterie: Wert ist in Promille (0-1000), Division durch 10 ergibt Prozent.
|
||||
For battery: value is in per-mille (0-1000), divide by 10 for percent.
|
||||
|
||||
## USB-Identifikation
|
||||
## USB Identification
|
||||
|
||||
- **Vendor ID:** 0x1B1C (Corsair)
|
||||
- **Product ID:** 0x0A6B (HS80 RGB Wireless)
|
||||
- **Interface:** 3 (HID Control Interface)
|
||||
|
||||
Andere Bragi-Geräte verwenden dasselbe Protokoll mit unterschiedlichen Product IDs.
|
||||
Other Bragi devices use the same protocol with different Product IDs.
|
||||
|
||||
Reference in New Issue
Block a user