149 lines
7.1 KiB
Markdown
149 lines
7.1 KiB
Markdown
# ADR-264: Versioned wire protocol for RTL8720F CFR and Range-FFT reports
|
||
|
||
- **Status**: proposed
|
||
- **Date**: 2026-07-18
|
||
- **Deciders**: ruv
|
||
- **Tags**: realtek, rtl8720f, protocol, cfr, range-fft, udp, serial
|
||
- **Depends on**: ADR-263
|
||
- **Relates to**: ADR-018, ADR-095, ADR-097, ADR-099, ADR-260
|
||
|
||
## Context
|
||
|
||
ADR-263 adopts RTL8720F radar behind an anti-corruption boundary. The Realtek presentation names
|
||
CFR, near Range-FFT, far Range-FFT, and interference reports, but does not specify their binary ABI.
|
||
RuView needs a stable, testable contract that can be implemented before the vendor SDK arrives and
|
||
that will not expose vendor structs, pointer layouts, padding, or callback lifetime rules over the
|
||
network.
|
||
|
||
ADR-018 already defines ESP32 CSI framing. Reusing its magic or pretending that Realtek radar is an
|
||
ESP32 packet would make source detection ambiguous and erase radar-specific calibration metadata.
|
||
|
||
## Decision
|
||
|
||
Define a new little-endian `RtlRadarFrameV1` envelope with its own magic and explicit payload type.
|
||
This is a RuView protocol, not a claim about Realtek's native memory layout.
|
||
|
||
### Envelope
|
||
|
||
All integer fields are little-endian. Floating-point payloads use IEEE-754 binary32. No C struct is
|
||
sent by `memcpy`; firmware serializes each field explicitly.
|
||
|
||
| Offset | Size | Field | Meaning |
|
||
|---:|---:|---|---|
|
||
| 0 | 4 | magic | ASCII `RTR1` (`0x31525452`) |
|
||
| 4 | 1 | version | `1` |
|
||
| 5 | 1 | report_type | 1 CFR, 2 range-near, 3 range-far, 4 interference, 5 capabilities |
|
||
| 6 | 2 | header_len | complete header size, initially 56 |
|
||
| 8 | 4 | frame_len | header + payload + CRC |
|
||
| 12 | 4 | sequence | wraps modulo 2^32 |
|
||
| 16 | 8 | timestamp_us | monotonic device time at acquisition |
|
||
| 24 | 8 | device_id | stable pseudonymous identifier, not a MAC address |
|
||
| 32 | 4 | center_freq_khz | RF centre frequency |
|
||
| 36 | 2 | bandwidth_mhz | 20, 40, or 70 |
|
||
| 38 | 2 | flags | calibration/interference/saturation/time-sync flags |
|
||
| 40 | 2 | element_count | complex samples or range bins |
|
||
| 42 | 1 | element_format | 0 bytes/TLV, 1 complex-i16, 2 complex-f32, 3 power-u16, 4 power-f32 |
|
||
| 43 | 1 | antenna_count | expected to be 1 for the deck's 1T1R configuration |
|
||
| 44 | 4 | scale | quantized-to-physical multiplier; `1.0` for float payloads |
|
||
| 48 | 4 | bin_spacing | Hz for CFR, metres for Range-FFT |
|
||
| 52 | 4 | calibration_id | device calibration revision/hash prefix |
|
||
| 56 | variable | payload | determined by type, count, and format |
|
||
| final-4 | 4 | crc32 | IEEE CRC-32 over header and payload |
|
||
|
||
If vendor evidence shows that 56 bytes is too costly, a later protocol version may introduce a
|
||
compact header. V1 favors auditable provenance over premature byte savings.
|
||
|
||
### Payload semantics
|
||
|
||
- **CFR** contains ordered complex channel-frequency samples. The adapter must know the frequency
|
||
origin/order and must not fabricate missing phase. Uncalibrated frames carry the uncalibrated flag
|
||
and cannot enter phase-sensitive processing.
|
||
- **Range-near/range-far** contains ordered range bins. Near and far are separate report types so
|
||
filtering and leakage behavior are never hidden from consumers.
|
||
- **Interference** contains a versioned TLV set for channel-busy, detected-during-chirp, estimated
|
||
interference power, and packet jitter. Unknown TLVs are skipped by length.
|
||
- **Capabilities** is emitted at boot and on request. It declares supported report types, bandwidths,
|
||
chirp lengths, maximum elements/report, maximum frame rate, firmware version, and SDK identifier.
|
||
|
||
### Transport
|
||
|
||
The identical envelope is supported over:
|
||
|
||
- UDP datagrams for normal RuView ingestion;
|
||
- USB CDC or UART with COBS framing and a zero-byte delimiter;
|
||
- file replay as a length-prefixed sequence of envelopes.
|
||
|
||
One envelope must fit one UDP datagram. Fragmentation is not part of V1; firmware rejects a profile
|
||
whose maximum report exceeds the configured MTU and reports the required size through capabilities.
|
||
|
||
### Parser and trust rules
|
||
|
||
The host parser:
|
||
|
||
1. validates magic, version, lengths, enum values, element count/format multiplication, and CRC
|
||
before allocating or decoding the payload;
|
||
2. caps frames at 64 KiB and elements at a configured hardware maximum;
|
||
3. rejects non-finite float metadata/payload values;
|
||
4. tracks sequence gaps and timestamp regressions per device;
|
||
5. preserves unknown flags but never interprets them as trusted;
|
||
6. attaches transport source, firmware/SDK version, calibration ID, and interference state to
|
||
provenance;
|
||
7. labels fixture/generated frames as synthetic.
|
||
|
||
No vendor-provided presence probability bypasses RuView privacy, provenance, or quality gates.
|
||
|
||
## Consequences
|
||
|
||
### Positive
|
||
|
||
- Firmware, transport, parser, replay, and fusion can evolve independently.
|
||
- Fuzzing and golden fixtures require no Realtek SDK or board.
|
||
- CFR and Range-FFT retain correct axes and calibration provenance.
|
||
- A boot-time capabilities frame makes SDK/API drift observable.
|
||
|
||
### Negative
|
||
|
||
- Serialization adds CPU and bandwidth overhead compared with dumping a vendor buffer.
|
||
- V1 fields may need revision after the actual API and report limits are disclosed.
|
||
- UDP provides integrity/error detection, not authenticity or confidentiality.
|
||
|
||
### Neutral
|
||
|
||
- Authentication can be layered with ADR-032 device identity or a signed RuField receipt without
|
||
changing report semantics.
|
||
- ESP32 ADR-018 framing remains unchanged.
|
||
|
||
## Implementation plan
|
||
|
||
1. Add `rtl8720f` types/parser module to `wifi-densepose-hardware` behind no vendor dependency.
|
||
2. Add golden CFR, near/far Range-FFT, interference, and capabilities fixtures.
|
||
3. Add property/fuzz tests for length arithmetic, enum handling, CRC, and float validation.
|
||
4. Add a replay CLI that prints normalized metadata without running inference.
|
||
5. Once SDK access exists, implement the embedded serializer and verify captured frames against the
|
||
host golden decoder.
|
||
6. Revise this proposed ADR with measured element counts, rates, and API names before acceptance.
|
||
|
||
Host-side steps 1–3 are implemented in `wifi-densepose-hardware::rtl8720f`: typed report and
|
||
element enums, semantic type/format validation, bounded length arithmetic, CRC verification,
|
||
finite-float checks, encode/decode round trips, corruption/truncation tests, and deterministic
|
||
arbitrary-input panic checks. Cross-language vectors remain blocked on the vendor SDK callback ABI.
|
||
Bit 15 of `flags` is reserved by RuView as `SYNTHETIC`; the Rust simulator always sets it and real
|
||
firmware must never set it. The simulator is deterministic by seed and exercises the production
|
||
encoder/parser rather than a parallel mock representation.
|
||
|
||
## Acceptance criteria
|
||
|
||
- Rust encode/decode round-trip for every report type.
|
||
- Cross-language golden vector produced by the RTL8720F firmware.
|
||
- Zero parser panics over the fuzz corpus and arbitrary byte input.
|
||
- Detection of single-bit corruption, truncation, count overflow, timestamp regression, and gaps.
|
||
- Captured CFR frequency order and Range-FFT bin spacing verified against vendor documentation and a
|
||
measured target.
|
||
|
||
## Sources
|
||
|
||
- Realtek Semiconductor, `RTL8720F-2.4G-Radar-Advantages_EN.pptx`, slides 11–19, supplied
|
||
2026-07-18.
|
||
- ADR-018 (ESP32 framing), ADR-095/097 (hardware normalization), ADR-260 (multimodal event model),
|
||
and ADR-263 (platform decision).
|