zwischenstand
This commit is contained in:
108
protocol.md
108
protocol.md
@@ -3,7 +3,7 @@
|
||||
Stand: 2026-03-18
|
||||
Quelle: aktueller Implementierungsstand aus Firmware (`buzz_proto`, `fs_mgmt`, `ble_mgmt`) und Web-Client (`transport`, `parser`).
|
||||
|
||||
## 1. Ziel und Scope
|
||||
## Ziel und Scope
|
||||
|
||||
Das Buzzer Protocol ist ein binäres Frame-Protokoll für Host <-> Device Kommunikation.
|
||||
|
||||
@@ -19,7 +19,7 @@ Nicht produktiv implementiert:
|
||||
- `DEVICE_INFO` (`0x02`)
|
||||
- Firmware-Update (`FW_*`, `FW_UPDATE`)
|
||||
|
||||
## 2. Transport und Grundregeln
|
||||
## Transport und Grundregeln
|
||||
|
||||
- Alle Integer-Felder sind Little Endian.
|
||||
- Jedes Frame hat einen 3-Byte Header.
|
||||
@@ -32,9 +32,9 @@ BLE Service UUIDs:
|
||||
- RX: `e517d988-bab5-4574-8479-97c6cb115ca1`
|
||||
- TX: `e517d988-bab5-4574-8479-97c6cb115ca2`
|
||||
|
||||
## 3. Frame-Format
|
||||
## Frame-Format
|
||||
|
||||
### 3.1 Header
|
||||
### Header
|
||||
|
||||
```c
|
||||
uint8_t frame_type;
|
||||
@@ -42,7 +42,7 @@ uint16_t payload_length; // LE
|
||||
```
|
||||
|
||||
|
||||
### 3.2 Paketstruktur
|
||||
### Paketstruktur
|
||||
|
||||
```mermaid
|
||||
---
|
||||
@@ -54,7 +54,7 @@ packet
|
||||
+40: "Payload (variable length)"
|
||||
```
|
||||
|
||||
### 3.3 Maximalgröße
|
||||
### Maximalgröße
|
||||
|
||||
Firmware-Buffer ist slab-basiert (`CONFIG_BUZZ_PROTO_SLAB_SIZE`).
|
||||
Der effektive Chunk für Transfers wird zusätzlich durch den Transport limitiert. Bei Bluetooth sind das zum Beispiel 3 Bytes:
|
||||
@@ -65,7 +65,7 @@ Der effektive Chunk für Transfers wird zusätzlich durch den Transport limitier
|
||||
|
||||
Das Protokoll ist so ausgelegt, dass es mit mindestens 100 Bytes auskommen sollte.
|
||||
|
||||
## 4. Frame-Typen
|
||||
## Frame-Typen
|
||||
|
||||
| Wert | Name | Richtung | Bedeutung |
|
||||
|---|---|---|---|
|
||||
@@ -84,13 +84,14 @@ Das Protokoll ist so ausgelegt, dass es mit mindestens 100 Bytes auskommen sollt
|
||||
| `0x41` | `LS_ENTRY` | Device -> Host | Verzeichniseintrag |
|
||||
| `0x42` | `LS_END` | Device -> Host | Ende Verzeichnis-Stream |
|
||||
|
||||
## 5. Data-Typen (`REQUEST`)
|
||||
## Data-Typen (`REQUEST`)
|
||||
|
||||
| Wert | Name | Status | Beschreibung |
|
||||
|---|---|---|---|
|
||||
| `0x01` | `PROTO_INFO` | aktiv | Protokollversion + max Chunkgröße |
|
||||
| `0x02` | `DEVICE_INFO` | reserviert | aktuell nicht bedient |
|
||||
| `0x02` | `DEVICE_INFO` | aktiv | Device-Infos (Board, Revision, SOC, ID) |
|
||||
| `0x03` | `FS_INFO` | aktiv | Dateisystem- und Pfadinfos |
|
||||
| `0x04` | `FW_INFO` | aktiv | Info über Firmware-Status und -Version sowie Kernelversion |
|
||||
| `0x20` | `FILE_GET` | aktiv | Datei vom Device streamen |
|
||||
| `0x21` | `FILE_PUT` | aktiv | Datei zum Device hochladen |
|
||||
| `0x22` | `TAGS_GET` | aktiv | nur Tag-Bereich streamen |
|
||||
@@ -100,9 +101,9 @@ Das Protokoll ist so ausgelegt, dass es mit mindestens 100 Bytes auskommen sollt
|
||||
| `0x30` | `FW_UPDATE` | reserviert | aktuell nicht bedient |
|
||||
| `0x40` | `LS` | aktiv | Verzeichnisliste starten |
|
||||
|
||||
## 6. Request/Response-Formate
|
||||
## Request/Response-Formate
|
||||
|
||||
## 6.1 Generischer Request
|
||||
### Generischer Request
|
||||
|
||||
```c
|
||||
uint8_t data_type;
|
||||
@@ -126,7 +127,7 @@ packet
|
||||
+32: "Optional payload (variable length)"
|
||||
```
|
||||
|
||||
## 6.2 `PROTO_INFO` (`0x01`)
|
||||
### `PROTO_INFO` (`0x01`)
|
||||
|
||||
Request: keine Zusatzdaten.
|
||||
|
||||
@@ -150,7 +151,24 @@ packet
|
||||
+16: "Max Chunk Size (LE)"
|
||||
```
|
||||
|
||||
## 6.3 `FS_INFO` (`0x03`)
|
||||
### `DEVICE_INFO` (`0x02`)
|
||||
|
||||
Request: keine Zusatzdaten.
|
||||
|
||||
Respone-Payload:
|
||||
|
||||
```c
|
||||
uint8_t data_type; // 0x02
|
||||
uint8_t[8] device_id;
|
||||
uint8_t board_len;
|
||||
uint8_t rev_len;
|
||||
uint8_t soc_len;
|
||||
uint8_t data[]; // board, rev und soc, ohne Nullterminierung
|
||||
```
|
||||
|
||||
***Hinweis:*** In der aktuellen implementierung werden die Strings auf eine maximale Länge von 32 Zeichen beschränkt. Dies sollte für alle Fälle genügen.
|
||||
|
||||
### `FS_INFO` (`0x03`)
|
||||
|
||||
Request: keine Zusatzdaten.
|
||||
|
||||
@@ -163,7 +181,7 @@ uint32_t free_size; // LE
|
||||
uint8_t max_path_length;
|
||||
uint8_t sys_path_length;
|
||||
uint8_t audio_path_length;
|
||||
uint8_t data[]; // sys_path + audio_path (beide nicht nullterminiert)
|
||||
uint8_t data[]; // sys_path + audio_path ohne Nullterminierung
|
||||
```
|
||||
|
||||
Im `data` folgen sich System- und Audiopfad ohne Abstand, und ohne 0-Terminierung (`\0`). Beispiel für Systempfad `/lfs/sys`und Audiopfad `/lfs/a`:
|
||||
@@ -213,7 +231,23 @@ Das Beispiel schaut in HEX so aus:
|
||||
0x2F 0x6C 0x66 0x73 0x2F 0x73 0x79 0x73 0x2F 0x6C 0x66 0x73 0x2F 0x61
|
||||
```
|
||||
|
||||
## 6.4 `LS` (`0x40`)
|
||||
### `FW_INFO` (`0x04`)
|
||||
|
||||
Request: keine Zusatzdaten
|
||||
|
||||
Response:
|
||||
|
||||
```c
|
||||
uint8_t fw_status; /* 0x00: Confirmed, 0x01: Pending, 0x02: Testing, 0xFF: Unbekannt */
|
||||
uint32_t slot1_size; /* (LE) Grösse des Firmware Update Slots */
|
||||
uint8_t fw_version_len; /* Länge des Firmware-Versionsstring */
|
||||
uint8_t kernel_version_len; /* Länge des Kernel-Versionsstrings */
|
||||
uint8_t data[]; /* FW-Version und Kernelversion, ohne Nullterminierung */
|
||||
```
|
||||
|
||||
***Hinweis:*** in der Aktuellen implementierung werden die Versionen auf 32 Zeichen limitiert.
|
||||
|
||||
### `LS` (`0x40`)
|
||||
|
||||
Request-Payload:
|
||||
|
||||
@@ -222,7 +256,7 @@ uint8_t data_type; // 0x40
|
||||
char path[]; // ohne Nullterminierung
|
||||
```
|
||||
|
||||
## 6.5 `FILE_GET` (`0x20`) und `TAGS_GET` (`0x22`)
|
||||
### `FILE_GET` (`0x20`) und `TAGS_GET` (`0x22`)
|
||||
|
||||
Request-Payload:
|
||||
|
||||
@@ -233,7 +267,7 @@ char path[]; // ohne Nullterminierung
|
||||
|
||||
Antwort ist ein Stream aus `FILE_START` -> `FILE_CHUNK`* -> `FILE_END`.
|
||||
|
||||
## 6.6 `FILE_PUT` (`0x21`) und `TAGS_PUT` (`0x23`)
|
||||
### `FILE_PUT` (`0x21`) und `TAGS_PUT` (`0x23`)
|
||||
|
||||
Request-Payload:
|
||||
|
||||
@@ -247,7 +281,7 @@ Danach sendet der Host:
|
||||
- `FILE_CHUNK` Frames
|
||||
- abschließend `FILE_END` mit CRC32
|
||||
|
||||
## 6.7 `RM_FILE` (`0x24`)
|
||||
### `RM_FILE` (`0x24`)
|
||||
|
||||
Request-Payload:
|
||||
|
||||
@@ -257,7 +291,7 @@ uint8_t path_length;
|
||||
char path[]; // ohne Nullterminierung
|
||||
```
|
||||
|
||||
## 6.8 `RENAME_FILE` (`0x25`)
|
||||
### `RENAME_FILE` (`0x25`)
|
||||
|
||||
Request-Payload:
|
||||
|
||||
@@ -268,9 +302,9 @@ uint8_t new_path_length;
|
||||
char paths[]; // old_path + new_path (jeweils ohne Nullterminierung)
|
||||
```
|
||||
|
||||
## 7. ACK / ERROR / SUCCESS
|
||||
## ACK / ERROR / SUCCESS
|
||||
|
||||
## 7.1 ACK (`0x11`)
|
||||
### ACK (`0x11`)
|
||||
|
||||
Payload:
|
||||
|
||||
@@ -285,7 +319,7 @@ Wichtig: Es gibt zwei Semantiken je nach Richtung.
|
||||
- Upload (`FILE_PUT`, `TAGS_PUT`):
|
||||
Device -> Host, Credits sind zusätzlich gewährte Tokens (Host addiert sie).
|
||||
|
||||
## 7.2 ERROR (`0x12`)
|
||||
### ERROR (`0x12`)
|
||||
|
||||
Payload:
|
||||
|
||||
@@ -310,7 +344,7 @@ Häufige Codes:
|
||||
| `116` | `ETIMEDOUT` | Credit-/Stream-Timeout |
|
||||
| `134` | `ENOTSUP` | nicht unterstützt |
|
||||
|
||||
## 7.3 SUCCESS (`0x13`)
|
||||
### SUCCESS (`0x13`)
|
||||
|
||||
Payload:
|
||||
|
||||
@@ -320,9 +354,7 @@ uint8_t data_type; // erfolgreich abgeschlossener Befehl
|
||||
|
||||
Wird derzeit u.a. für `FILE_PUT`, `TAGS_PUT`, `RM_FILE`, `RENAME_FILE` genutzt.
|
||||
|
||||
## 8. Stream-Sequenzen (Mermaid)
|
||||
|
||||
## 8.1 Verzeichnisliste (`LS`)
|
||||
## Verzeichnisliste (`LS`)
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
@@ -346,7 +378,7 @@ sequenceDiagram
|
||||
|
||||
Hinweis zum aktuellen Web-Client (März 2026): Für `LS` wird initial `ACK(64)` gesendet, ein dynamisches Nachfüllen ist noch nicht implementiert. Große Verzeichnisse können deshalb in `ETIMEDOUT` laufen.
|
||||
|
||||
## 8.2 Datei-/Tag-Download (`FILE_GET`, `TAGS_GET`)
|
||||
## Datei-/Tag-Download (`FILE_GET`, `TAGS_GET`)
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
@@ -369,7 +401,7 @@ sequenceDiagram
|
||||
Note over Host: CRC prüfen
|
||||
```
|
||||
|
||||
## 8.3 Datei-/Tag-Upload (`FILE_PUT`, `TAGS_PUT`)
|
||||
## Datei-/Tag-Upload (`FILE_PUT`, `TAGS_PUT`)
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
@@ -395,9 +427,9 @@ sequenceDiagram
|
||||
end
|
||||
```
|
||||
|
||||
## 9. Payload-Frames im Detail
|
||||
## Payload-Frames im Detail
|
||||
|
||||
## 9.1 `LS_ENTRY` (`0x41`)
|
||||
### `LS_ENTRY` (`0x41`)
|
||||
|
||||
```c
|
||||
uint8_t type; // 0x00 file, 0x01 dir
|
||||
@@ -406,13 +438,13 @@ uint8_t name_length;
|
||||
char name[]; // ohne Nullterminierung
|
||||
```
|
||||
|
||||
## 9.2 `LS_END` (`0x42`)
|
||||
### `LS_END` (`0x42`)
|
||||
|
||||
```c
|
||||
uint32_t total_entries; // LE
|
||||
```
|
||||
|
||||
## 9.3 `FILE_START` (`0x20`)
|
||||
### `FILE_START` (`0x20`)
|
||||
|
||||
```c
|
||||
uint32_t total_size; // LE
|
||||
@@ -421,19 +453,19 @@ uint32_t total_size; // LE
|
||||
`FILE_GET`: komplette Dateigröße.
|
||||
`TAGS_GET`: nur Tag-Teil der Datei.
|
||||
|
||||
## 9.4 `FILE_CHUNK` (`0x21`)
|
||||
### `FILE_CHUNK` (`0x21`)
|
||||
|
||||
Payload sind rohe Nutzdatenbytes.
|
||||
|
||||
## 9.5 `FILE_END` (`0x22`)
|
||||
### `FILE_END` (`0x22`)
|
||||
|
||||
```c
|
||||
uint32_t crc32; // LE, IEEE CRC32
|
||||
```
|
||||
|
||||
## 10. Beispiel-Frames (Hex)
|
||||
## Beispiel-Frames (Hex)
|
||||
|
||||
## 10.1 `PROTO_INFO` Request/Response
|
||||
### `PROTO_INFO` Request/Response
|
||||
|
||||
Request:
|
||||
|
||||
@@ -454,7 +486,7 @@ Interpretation:
|
||||
- `01 00`: Version 1
|
||||
- `FD 00`: max_chunk_size = 253
|
||||
|
||||
## 10.2 `LS` Request für `/a`
|
||||
### `LS` Request für `/a`
|
||||
|
||||
```text
|
||||
00 03 00 40 2F 61
|
||||
@@ -466,7 +498,7 @@ Interpretation:
|
||||
- `40`: data_type LS
|
||||
- `2F 61`: `/a`
|
||||
|
||||
## 11. Implementierungsnotizen
|
||||
### Implementierungsnotizen
|
||||
|
||||
- Unknown `REQUEST.data_type` wird aktuell mit `ERROR(EINVAL)` beantwortet.
|
||||
- Unbekannte/unerwartete `frame_type` im aktiven Protokollthread führen zu `ERROR(EPROTO)`.
|
||||
|
||||
Reference in New Issue
Block a user