RuView Qualcomm CSI 有线协议 ADR-269 深度解析:QCS1 信封格式、验证规则与确定性模拟器
本文是 RuView 项目中关于 Qualcomm Atheros CSI 接入的架构决策记录 ADR-269 的技术指南,围绕其定义的 QCS1 版本 1 线协议展开。文章会逐字节拆解 72 字节小端信封头部、CSI 与能力载荷的编码规则、解析器 fail-closed 校验矩阵,并对照仓库中 wifi-densepose-hardware 的 Rust 实现与 qualcomm-csi-sim 仿真工具,说明如何在拿到真实 Qualcomm 硬件数据前,就能通过确定性模拟帧打通采集、解析、感知与验证全链路。
读完本文,你将掌握 QCS1 帧的完整内存布局与字段语义、三类芯片档案(QCA9300 / QCN9074 / QCN9274)的带宽与链路上限约束、UDP 与 replay 两种传输封装方式,以及如何用随仓库发布的 CLI 工具生成、校验和回放仿真 CSI 流。
一、为什么需要一个"厂商边界信封":QCS1 的定位
RuView 的目标是把商用 WiFi 信号转成实时空间智能与存在感知。在 Qualcomm 侧,硬件生态并不统一:QCA9300 经 ath9k / PicoScenes 类研究工具验证可导出 CSI,而 QCN9074(Wi-Fi 6/6E)与 QCN9274(Wi-Fi 7)虽有上游 Linux 驱动,但上游 ath11k/ath12k 支持本身并不证明公开固件会导出逐包复数 CSI(见 ADR-268 的 Context)。
因此 ADR-269 的关键决策是:将 QCS1 定义为一个"厂商边界信封"(vendor-boundary envelope),而不是 Qualcomm 固件 ABI。换句话说,QCS1 不声称复刻任何私有固件结构,只是 RuView 内部约定的应用层容器;真实硬件数据通过 Rust 适配器翻译成 QCS1 后再进入下游感知管线。这样既保证了稳定、可模糊测试的边界,又不会在仓库中表示或再分发任何私有固件布局。
这一设计在代码中通过 wifi-densepose-hardware 的模块文档直接落地:
//! Vendor-neutral Qualcomm Atheros MIMO CSI transport and deterministic simulator.
//! This is not a Qualcomm firmware ABI; see ADR-268/269.
对应地,lib.rs 将该模块与 MediaTek Filogic(ADR-267)、Realtek RTL8720F(ADR-264)、ESP32(ADR-018)等硬件适配层并列,共同遵循"同一套经校验的 Rust API 服务模拟器、回放与未来硬件适配器"这一后果。
二、QCS1 帧的总体布局与常量约束
QCS1 v1 的帧由三部分组成:72 字节小端序头部 + 变长载荷 + 4 字节 CRC-32/IEEE 校验。全部整数字段按 little-endian 编码。仓库源码定义了以下协议常量(qualcomm_csi.rs):
| 常量 | 值 | 含义 |
|---|---|---|
QUALCOMM_CSI_MAGIC |
0x3153_4351 |
小端字节序即 ASCII "QCS1" |
QUALCOMM_CSI_VERSION |
1 |
协议版本 |
QUALCOMM_CSI_HEADER_LEN |
72 |
头部固定字节数 |
QUALCOMM_CSI_CRC_LEN |
4 |
尾部 CRC 长度 |
QUALCOMM_CSI_MAX_FRAME_LEN |
65_507 |
单帧字节上限 |
QUALCOMM_CSI_MAX_ELEMENTS |
16_384 |
单帧复数元素上限 |
其中 65_507 直接对应 IPv4 UDP 有效载荷天花板(65535 - 20 - 8 = 65507),从协议层面保证"一帧 QCS1 = 一个 UDP 数据报"不会发生 IP 层分片。
三、72 字节头部:字段语义与字节偏移对照
ADR-269 记录的头部字段为:report kind、total length、sequence、单调时间戳、device ID、chipset profile、中心频率、带宽、flags、Tx/Rx 计数、数值格式、PPDU 类型、子载波数、噪底、scale、子载波间隔、calibration ID 与 payload length。
对照 to_bytes 实现与 from_bytes 解析,可以精确还原各字段在 72 字节中的偏移:
| 偏移 | 长度 | 字段 | 说明 |
|---|---|---|---|
| 0 | 4 | magic | 固定 0x3153_4351("QCS1") |
| 4 | 1 | version | 固定 1 |
| 5 | 1 | report_kind | 1=Csi,2=Capabilities |
| 6 | 2 | header_len | 必须等于 72 |
| 8 | 4 | frame_len | header+payload+CRC 总长 |
| 12 | 4 | sequence | 单调递增序号(u32) |
| 16 | 8 | timestamp_us | 单调微秒时间戳(u64) |
| 24 | 8 | device_id | 设备标识(u64) |
| 32 | 2 | chipset | QCA9300/QCN9074/QCN9274 |
| 34 | 2 | bandwidth_mhz | 20/40/80/160 |
| 36 | 4 | center_freq_khz | 中心频率(kHz) |
| 40 | 2 | flags | 位标志(见下文) |
| 42 | 1 | tx_count | 发射链数 |
| 43 | 1 | rx_count | 接收链数 |
| 44 | 1 | element_format | 载荷数值格式 |
| 45 | 1 | ppdu_type | HT/VHT/HE SU/HE MU/EHT |
| 46 | 2 | subcarrier_count | 子载波数 |
| 48 | 1 | rssi_count | 载荷中 RSSI 字节数 |
| 49 | 1 | noise_floor_dbm | 噪底(dBm,有符号) |
| 50 | 2 | (保留填充) | 写入 0 |
| 52 | 4 | scale | f32 幅度缩放系数 |
| 56 | 4 | subcarrier_spacing_hz | f32 子载波间隔 |
| 60 | 4 | calibration_id | 校准会话 ID |
| 64 | 4 | payload_len | 载荷字节数 |
| 68 | 4 | (保留) | 写入 0 |
在 from_bytes 中,魔数、版本、header_len、frame_len 与 CRC 会先于字段解析被逐一核对;任何不匹配都会返回对应的 CsiParseError 变体,而不是产生半解析结果。
3.1 枚举字段与整数上限
协议中的多个字段是受限枚举,解析器通过 TryFrom<u8>/TryFrom<u16> 强制校验(源码枚举定义):
- ReportKind:
Csi = 1(复数信道状态信息)、Capabilities = 2(能力上报)。 - ElementFormat:
ComplexI16 = 1(复数 i16)、ComplexF32 = 2(复数 f32)、Bytes = 3(能力上报的不透明字节)。 - PpduType:
Ht = 1、Vht = 2、HeSu = 3、HeMu = 4、Eht = 5。
3.2 CsiFlags 位域
flags 是一个 u16 位掩码(CsiFlags),各语义位如下:
| 位 | 常量 | 含义 |
|---|---|---|
1 << 0 |
CALIBRATED |
已校准数据 |
1 << 1 |
SATURATED |
接收链饱和 |
1 << 2 |
TIME_SYNCHRONIZED |
跨节点时间同步 |
1 << 3 |
DROPPED_PREDECESSOR |
前序帧丢失 |
1 << 15 |
SYNTHETIC |
仿真来源标志(用于端到端 provenance) |
SYNTHETIC 位是诚实性设计的核心:仿真器产出的每一帧都会置位,下游感知服务据此把数据源标记为 qualcomm:simulated,绝不允许把模拟帧伪装成硬件实采帧(ADR-268 决策 4、v0.9.2 发行说明也强调 provenance 端到端保留)。
四、载荷编码规则
4.1 CSI 载荷(report_kind = Csi)
CSI 载荷由两部分组成(CsiPayload 定义):
- 每接收链一个带符号 RSSI 字节,即
rx_count个i8(dBm); - 随后是
tx × rx × subcarriers个复数采样,按 Tx 主序 → Rx 主序 → 子载波主序 排列。
复数采样有两种合法数值格式:
- ComplexI16:每个复数 4 字节,I/Q 各一个 i16,适合硬件量化数据(编码后每元素 4 字节);
- ComplexF32:每个复数 8 字节,I/Q 各一个有限 f32,适合浮点管线(编码后每元素 8 字节),且不允许出现 NaN/Inf。
编码总长的自校验非常严格:header(72) + payload_len + CRC(4) == frame_len,同时 payload_len - rssi_count 必须严格等于 elements × 每元素字节数,其中 elements = tx × rx × subcarriers,超差即判为 PayloadLengthMismatch。
在物理意义上,单帧复数矩阵的维度上限由 QUALCOMM_CSI_MAX_ELEMENTS = 16_384 约束;而 scale(f32,须为正有限值)用于把整数量化还原为物理幅度,subcarrier_spacing_hz 描述子载波间隔。感知服务会按 hypot(i,q) × scale 计算幅度统计(见下文快照说明)。
4.2 能力载荷(report_kind = Capabilities)
能力上报使用 ElementFormat::Bytes,携带"有界的"不透明字节(bounded opaque bytes)。从模拟器的 capabilities_frame(qualcomm_csi.rs)可以看到示例内容:包括主版本、次版本、最大链数、MIMO 能力、支持的带宽掩码、PPDU 能力及子载波数高低字节等。该载荷不需要也不允许附加虚假的信号统计。
4.3 CRC-32/IEEE
帧尾 4 字节是对"头部+载荷"整体计算的 CRC-32/IEEE(IEEE 802.3),仓库实现见 crc32_ieee:初值 0xffff_ffff、反射多项式 0xedb8_8320、末尾异或取反。编码时对整帧求 CRC 追加;解码时先对 frame_len - 4 字节求实际 CRC 再与帧尾比对,不一致即报 CrcMismatch。
五、Fail-closed:解析器的强制校验矩阵
ADR-269 明确要求解析器对以下情形一律失败关闭(fail closed),源码中对应 CsiParseError 枚举的每一个变体(错误类型):
| 异常类别 | 错误变体 | 说明 |
|---|---|---|
| 数据不足/截断 | InsufficientData |
输入短于所需字节 |
| 魔数错误 | InvalidMagic |
首 4 字节不是 QCS1 |
| 版本不支持 | UnsupportedVersion |
version ≠ 1 |
| 未知枚举 | UnknownReportKind / UnknownChipset / UnknownElementFormat / UnknownPpduType |
未知值一律拒绝 |
| 头部/帧长异常 | InvalidHeaderLength / InvalidFrameLength / FrameTooLarge |
header 非 72、frame_len 越界 |
| 算术溢出 | LengthOverflow |
长度运算用 checked_add/checked_mul |
| 维度不一致 | InvalidDimensions |
tx/rx 为 0 或超芯片上限;元素数超 16384 |
| 载荷长度不匹配 | PayloadLengthMismatch |
长度恒等式不成立 |
| 载荷与上报类型不符 | PayloadTypeMismatch |
如 Csi 上报携带 Bytes 载荷 |
| 非有限/非正值 | NonFiniteValue |
f32 NaN/Inf,或 scale/spacing ≤ 0 |
| 带宽违规 | InvalidBandwidth |
带宽非 20/40/80/160 或超芯片上限 |
| CRC 不匹配 | CrcMismatch |
帧尾校验失败 |
此外,validate()(qualcomm_csi.rs)还会在解码成功后做语义复核:CSI 载荷的 RSSI 字节数必须等于 rx_count,复数元素总数必须等于 tx × rx × subcarriers;任何越界都判失败,绝不产出部分可信数据。这一"先长度后 CRC 再枚举再语义"的多级防线,配合测试中"解析器对所有前缀永不 panic"的验证,构成了协议的安全底座。
六、芯片档案与协议 v1 能力上限
协议 v1 定义了三档芯片档案(ChipsetProfile):
| 档案 | 编码值 | 对应芯片/标准 | 最大链数 | 最大带宽 |
|---|---|---|---|---|
Qca9300 |
1 | 802.11n(ath9k 类系统) | 3 链 | 40 MHz |
Qcn9074 |
2 | Wi-Fi 6/6E | 4 链 | 160 MHz |
Qcn9274 |
3 | Wi-Fi 7 | 4 链 | 160 MHz |
结合 ADR-268 的分级策略:QCA9300 是首个物理基线(有公开研究工具链路验证),QCN9074/QCN9274 在 v1 中被明确标为实验性仿真档案——物理支持必须等固件配合与真实采证。因此任何声称 320 MHz 的 EHT 信道矩阵在当前 v1 下都不被表示,ADR-269 的 Consequences 明确记录了这一点:320 MHz / EHT 矩阵需要分段传输或留待后续协议修订。
代码中的 validate 与测试 qca9300_rejects_wifi6_bandwidths(qualcomm_csi.rs)共同保证:QCA9300 档案拒绝 80/160 MHz 带宽配置,现代档案拒绝超过 4 链的维度——芯片链数/带宽违规在编码阶段(Simulator::new)即被拦截。
七、UDP 与回放文件两种传输封装
QCS1 的传输假设非常简洁:一个 QCS1 帧映射到一个 UDP 数据报,因而天然适合局域网内以低时延推流。对需要离线复现、确定性回放的场景,回放文件格式为:每个帧前追加一个小端 u32 长度前缀,随后紧跟完整 QCS1 信封(见 ADR-269 与 qualcomm-csi-sim 参数注释)。模拟器 emit 逻辑演示了这套双通道输出:可同时把同一帧 send_to UDP 目标并写入回放文件,UDP 半包(WriteZero)被视为错误。
八、确定性模拟器:原理与默认参数
为了让开发、测试与下游感知在硬件到位前即可推进,仓库实现了 QualcommCsiSimulator(qualcomm_csi.rs)。其默认 SimulatorConfig 对应一个典型的 802.11n 2×3 MIMO 链路:
seed: 0x5143_4143_5349_0001,
device_id: 0x5255_5651_4341_3031,
chipset: ChipsetProfile::Qca9300,
bandwidth_mhz: 40,
center_freq_khz: 5_210_000, // 5.21 GHz
tx_count: 2,
rx_count: 3,
subcarriers: 114,
frame_period_us: 20_000, // 50 Hz
模拟器用 Xorshift 风格位运算生成带噪声的复数信道,并对每个子载波加入与子载波序号、链路序号及一个随帧推进的 motion_phase 相关的正弦相位项,从而在复数幅度上模拟出"存在移动"的物理形态;RSSI 按接收链递减(-42、-44、-46 dBm),噪底 -95 dBm,PPDU 类型为 HE SU,scale 为 1/2048,子载波间隔 312.5 kHz——这些取值都对应真实 WiFi 协议的典型量级。序列号与时间戳按 wrapping_add 单调推进,同一 seed 下逐帧字节完全确定。
九、实战:用 qualcomm-csi-sim 生成、推流与回放
仓库随 v0.9.2-qualcomm-beta.1 提供命令行工具 qualcomm-csi-sim(源码),完整参数如下:
| 参数 | 默认值 | 说明 |
|---|---|---|
--profile |
qca9300 |
芯片档案:qca9300 / qcn9074 / qcn9274 |
--frames |
100 |
生成的 CSI 帧数(另有 1 帧能力上报前置) |
--seed |
0x5143414353490001 |
确定性种子,支持 0x 十六进制 |
--bandwidth |
随档案 | 20/40/80/160(须不超档案上限) |
--tx |
2 |
发射链数 |
--rx |
随档案(3/4) | 接收链数 |
--subcarriers |
随档案(114/256) | 子载波数 |
--interval-ms |
20 |
相邻帧间隔(ms),对应 frame_period_us |
--udp |
无 | UDP 目标地址,如 127.0.0.1:6014 |
--output |
无 | 回放文件路径(u32 长度前缀 + 信封) |
--realtime |
关 | 按 interval 休眠实现实时节奏 |
--udp 与 --output 至少选一。典型用法:
# 1) QCA9300 档案,推 500 帧到本机感知服务(udp)
cargo run -p wifi-densepose-hardware --bin qualcomm-csi-sim -- \
--profile qca9300 --frames 500 --udp 127.0.0.1:6014
# 2) 生成确定性回放文件(含能力上报,共 frames+1 帧)
qualcomm-csi-sim --profile qcn9274 --bandwidth 160 --tx 4 --rx 4 \
--subcarriers 256 --frames 1000 --output qualcomm-9274.rqf
# 3) 指定 seed 复现完全一致的帧序列
qualcomm-csi-sim --seed 0x5143414353490001 --frames 10 --output same.rqf
每档档案的默认维度(Profile 实现)为:QCA9300 默认 3 链/40 MHz/114 子载波,QCN9074 与 QCN9274 默认 4 链/80 MHz/256 子载波(带宽可显式上调至 160)。工具结束时在 stderr 打印实际发出的合成帧数与字节总量。
十、端到端:仿真来源标志与感知服务接入
QCS1 帧进入 RuView 感知服务后,由 wifi-densepose-sensing-server 按 UDP magic 识别 QCS1 数据报、调用 CsiFrame::from_bytes 解码,再映射成有界快照(QualcommCsiSnapshot),并通过 GET /api/v1/csi/qualcomm/latest 暴露最新状态(路由注册)。
快照字段与 ADR-269 的头部一一对应:report_kind、sequence、timestamp_us、device_id(十六进制格式化)、chipset、center_freq_khz、bandwidth_mhz、tx/rx_count、subcarrier_count、ppdu_type、逐链 rssi_dbm、noise_floor_dbm、calibration_id、subcarrier_spacing_hz,以及 flags 展开后的 calibrated / saturated / time_synchronized / dropped_predecessor / synthetic 布尔值。
关键设计点是来源归属与统计诚实性:
synthetic为真时快照的source被标记为qualcomm:simulated,为假时才标记qualcomm;- CSI 帧会附带
mean_amplitude与peak_amplitude(按hypot(i,q) × scale计算),而能力上报帧的幅度统计必须为None,测试capability_summary_does_not_invent_signal_statistics(qualcomm_csi.rs)专门锁定"不为能力帧虚构信号统计"。
十一、测试与验证边界
协议实现内置了大量自动化测试(qualcomm_csi.rs 测试模块),覆盖 ADR-269 声明的主要防线:
| 测试 | 验证点 |
|---|---|
simulator_round_trip_is_deterministic |
同 seed 逐字节确定;解码往返一致;2×3×114=684 元素完整保留 |
capabilities_round_trip |
能力上报可无损编解码 |
crc_corruption_is_rejected |
篡改第 80 字节即报 CrcMismatch |
truncation_is_rejected |
少一字节即报 InsufficientData |
invalid_dimensions_are_rejected |
QCA9300 档案配 4 接收链被拒 |
non_finite_float_is_rejected |
NaN 复数载荷编码阶段被拒 |
parser_never_panics_on_prefixes |
对任意长度前缀解析永不 panic |
qca9300_rejects_wifi6_bandwidths |
旧芯片档案拒绝 Wi-Fi 6 带宽 |
结合 v0.9.2-qualcomm-beta.1 发行说明:codec、corruption、truncation、finite-value、dimensions、chipset bandwidth、determinism 与 prefix parsing 均已自动化;回环 UDP/API 验证覆盖全部三档档案。物理 QCA9300 实测对比与现代固件导出验证仍是硬件门,会在取得固件与校准细节后另行发布——这正是 ADR-268"绝不把仿真帧标为硬件"原则的落地。
十二、在厂商接入体系中的位置
ADR-269 是 RuView 厂商接入三部曲之一,与之相关的文档形成完整闭环:
- ADR-268 Qualcomm Atheros 平台策略:解释为何 QCA9300 为首个物理基线、现代档案为何先以模拟器推进,以及"固件/内核格式藏在 Rust 适配器后面、RuView 只摄取经校验的 QCS1 信封"的整体架构;
- ADR-270 厂商 RF 感知集成项目:定义
ComplexCsi / DerivedSensing / RfTelemetry / NetworkOnly / Unsupported能力分层,并规定"模拟器成功永远不能满足硬件支持门"的验收门槛; - 协议层面还参照 ADR-267 MediaTek MTC1 协议,其头部同样位于 wifi-densepose-hardware,与 QCS1 共享同一套"厂商中立信封 + 确定性模拟 + fail-closed 解析 + synthetic provenance"的设计范式,便于下游感知管线以统一 Rust 类型消费多厂商数据。
小结
QCS1 v1 为 RuView 的 Qualcomm 路线提供了一个经 CRC 保护、版本化、严格边界校验的传输协议:72 字节小端头部承载完整的无线上下文元数据,CSI 载荷按 Tx→Rx→子载波主序组织复数矩阵,能力上报携带受限字节,一帧一数据报满足 UDP 传输,回放文件用 u32 长度前缀实现逐帧定界。配合确定性模拟器与 qualcomm-csi-sim CLI,开发者在真实硬件采证之前即可端到端演练采集、解析、感知与验证流程,同时通过 SYNTHETIC 标志与 qualcomm:simulated 来源标记守住"仿真绝不冒充实测"的诚实边界。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0631
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
video-shotcraftAI宣传片skill,使用 Remotion 制作电影级产品视频:提供106 张镜头配方卡和可复用的视频魔板。适用于 Claude Code 与 Codex以及所有其他智能体Markdown00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python09
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00