SergeyZh/emotion-control-re
GitHub: SergeyZh/emotion-control-re
通过 SPI 总线嗅探完整逆向还原了 L&S Emotion Control 灯具的 2.4 GHz 射频通信协议及数据包格式。
Stars: 0 | Forks: 0
[](README.en.md)
[](README.md)
[](README.de.md)
# Emotion Control (L&S) — 射频协议逆向工程
以 L&S 公司的 **Emotion Control** 灯具控制射频协议逆向工程为例
单通道遥控器 **KZQ-8YKC-K** (Emotion-Control Fernbedienung 1-Kanal)。
**状态:协议已完全破解**(应用层 + RF 层),RF 参数已通过
空中信号测量确认。仅剩在真实灯具上进行可选的实时验证。
## 遥控器硬件
| 组件 | 作用 |
|---|---|
| PIC16F1503 (SOIC-14) | MCU,包含所有逻辑;固件已受保护(`CP=ON`,无法读取) |
| CC2500 (QFN-20) | 2.4 GHz 射频收发器,由 PIC 通过 SPI 控制 |
| 26.000 MHz 晶振 | CC2500 的基准频率 |
| 3 个按钮 + 电位器 | S1 开/关,S2 调亮,S3 调暗,W1 色温 |
## 方法
PIC 固件受防读取保护,因此协议是通过**嗅探 PIC 和 CC2500 之间的 SPI 总线**
(使用 Saleae Logic Pro 8 逻辑分析仪;由于出现锁定问题,廉价的 FX2 克隆版无法胜任)提取的。
已破解内容:CC2500 配置(初始 burst)和有效载荷(写入 TX FIFO 的数据),
并与遥控器的操作进行了关联匹配。RF 参数已通过 HackRF 接收进一步确认。
## RF 配置(CC2500,26 MHz 晶振)
| 参数 | 值 |
|---|---|
| 载波频率 | **2436.2 MHz**(基准 2433.0 + CHANNR 16 × 199.95 kHz)—— 在 FCC 认证文件 `2ARQD-KZQ8YKCK` 中标注为 2436.26 MHz |
| 调制方式 | **MSK**(极性:位=1 → 负频偏) |
| 频偏 | ≈ **62.5 kHz**(MSK:波特率/4) |
| 波特率 | **250 kBaud** |
| 信道带宽 | 542 kHz |
| 同步字 | **0xD391**,30/32 位检测 |
| 前导码 | 4 字节 |
| FEC | 开启 |
| Whitening | 关闭(空中的 payload = FIFO 字节) |
| CRC | 开启(硬件生成) |
| 数据包长度 | 可变(第一个字节 = 长度) |
| 发射功率 | 最大(PATABLE[0]=0xFF) |
完整的寄存器映射表见 [`captures/PROTOCOL-FINDINGS.md`](captures/PROTOCOL-FINDINGS.md)。
## 数据包格式(空中 14 字节)
```
[ ID: 4 байта ][ cmd ][ val ][ 0x00 × 6 ][ chk ][ 0x16 ]
68 04 F7 4D
```
- **ID** `68 04 F7 4D` —— 遥控器自身的标识符(在配对时声明)。
- **cmd** —— 命令代码(见下文)。
- **val** —— 参数值(色温等级;对于其他命令为 `0x00`)。
- **chk** —— 校验和:**`chk = 0x7E ⊕ ID₀ ⊕ ID₁ ⊕ ID₂ ⊕ ID₃ ⊕ 0x16 ⊕ cmd ⊕ val`**,
即 `0x7E` 对数据包中所有其余字节进行异或(第 6-11 位的 0 不影响结果)。
对于我们这台 `68 04 F7 4D` 的遥控器,常量会被折叠为 `chk = 0xBE ⊕ cmd ⊕ val`,但
**`0xBE` 取决于 ID** —— 对于不同的遥控器,需要根据通用公式重新计算。
- **0x16** —— 固定的类型字节。
### 命令 (cmd)
| cmd | 操作 | val |
|---|---|---|
| `0x01` | 打开 | 色温等级 (W1 的 ADC 值) |
| `0x02` | 关闭 | `0x00` |
| `0x10` | 开始平滑增加亮度(长按 S2) | `0x00` |
| `0x11` | 亮度增加一个台阶(短按 S2) | `0x00` |
| `0x20` | 开始平滑降低亮度(长按 S3) | `0x00` |
| `0x21` | 亮度降低一个台阶(短按 S3) | `0x00` |
| `0x40` | 停止平滑变化(松开 S2/S3) | `0x00` |
| `0x50` | 色温 | `0x00` 暖色 … `0xFF` 冷色 |
| `0x60` | 配对(长按 ON/OFF ≥5 秒) | `0x00` |
开/关方向已通过已配对的灯具确认(按下 S1 → 当 `cmd 01/02/01` 时表现为 On/Off/On 反应)。
开启命令带有当前色温;关闭命令 —— `val=0x00`。
**亮度在两种模式下运行。** 短按 —— 步进(`0x11`/`0x21`,共 5 个级别)。
长按 —— 平滑变化:`0x10` 向上,`0x20` 向下,从最低到最高的完整过程大约持续 1 秒;松开按钮会发送
`0x40`,将渐变停在当前水平。因此,`0x10`/`0x20` **并非**瞬间跳变到极限值:最终水平取决于
`0x40` 到达的时刻。更可靠的做法是通过带有余量的 `0x11`/`0x21` 步进逼近极值 —— 灯具会自动停在极限位置。
大多数命令会连续发送 5 次,但亮度命令 —— **仅发送一次**,因此在空中传输时
有时会丢失。
### 传输过程(在 SPI 总线上)
`SIDLE (0x36)` → `SFTX (0x3B)` → burst 写入 TX FIFO(`0x7F` + 数据包)→ `STX (0x35)` → 休眠 `SPWD (0x39)`。
遥控器**仅负责发送**(无 RX 分支)。CC2500 的配置在冷启动时加载一次,
并在休眠期间保持。
## 如何复现
任何带有 **CC2500**(2.4 GHz;CC1101 不适用 —— 它是 Sub-GHz 频段)的 MCU,在加载提取出的
寄存器配置后,都可以:
- **接收**遥控器命令,或者
- **控制灯具**:组装数据包 `ID₀ ID₁ ID₂ ID₃ | cmd | val | 00×6 | chk | 16`,计算
`chk = 0x7E ⊕ ID₀ ⊕ ID₁ ⊕ ID₂ ⊕ ID₃ ⊕ 0x16 ⊕ cmd ⊕ val`,将其写入 TX FIFO 并发送。Whitening
已关闭,因此无需对 payload 进行额外处理;CRC 由硬件自动添加。
ID 采用与灯具配对的遥控器的标识符。
为了控制特定的灯具,必须先将其配对(灯具在学习模式下会记住遥控器的 ID)。
## 仓库结构
| 路径 | 内容 |
|---|---|
| [`PLAN.md`](PLAN.md) | 按阶段划分的项目计划 |
| [`CONFIG-BITS.md`](CONFIG-BITS.md) | PIC16F1503 的 Config Bits / Device ID |
| [`READING-FIRMWARE.md`](READING-FIRMWARE.md) | 读取固件步骤 (ICSP) |
| [`SPI-TRACING.md`](SPI-TRACING.md) | PIC↔CC2500 引脚分布,分析仪连接方式 |
| [`captures/`](captures/) | SPI 捕获文件 (`.sr`/`.csv`),指南,详细的协议解析 |
| [`captures/PROTOCOL-FINDINGS.md`](captures/PROTOCOL-FINDINGS.md) | 完整的解析:寄存器、数据包、命令 |
| [`datasheets/README.md`](datasheets/README.md) | 指向制造商数据手册和文档的链接(`fetch.sh` 可下载它们) |
| `photos/` | 电路板照片 |
## 免责声明
- 所有发现均是为了实现互操作性,对自行购买的遥控器进行逆向工程获得的。
- `68 04 F7 4D` —— 是特定遥控器实例的 ID;其他遥控器的 ID 将会有所不同。
- FEC 在数据包长度可变时已开启 —— 在构建接收器时,建议在实践中对此进行验证
(数据手册在形式上仅描述了固定长度下的 FEC)。
## 许可证
代码和文档 —— © 2026 Sergey Zhukov,基于 **Apache License 2.0** 许可证:见 [`LICENSE`](LICENSE)。
`captures/` 中的捕获文件、电路板照片和寄存器映射表同样受其约束 —— 这些均为作者本人的
测量成果。
## 第三方资料与商标
- CC2500 芯片的 FEC/CRC(卷积码 r=1/2 K=4,4×4 交织器,CRC-16 `0x8005`)由
Texas Instruments 发布 —— 包括描述和 C 语言参考代码实现 —— 包含在设计说明 **DN504** (SWRA113A)
和 **DN507** (SWRA313) 中。在 `sdr/cc2500_fec.py` 中,编码器和 CRC 是从 DN504 的代码清单移植到 Python 的,
交织器的排列是从相同的循环中推导出来的,而解码器(解交织器 + Viterbi)是独立编写的;
其正确性已通过 DN504 的测试向量确认。相关文档和参考代码的
版权归 Texas Instruments 所有。
- 制造商的数据手册和指南在仓库中**不予存储**:
[`datasheets/README.md`](datasheets/README.md) 仅包含指向原始来源的链接,而
`fetch.sh` 会将它们本地下载。
- 遥控器的固件**从未被提取也未曾发布** —— `CP` 位保护其不被读取
(见 [`CONFIG-BITS.md`](CONFIG-BITS.md))。
- **L&S**、**Emotion Control**、**CC2500**、**PIC** 及其他名称均为其
所有者的商标。本项目与 L&S Deutschland GmbH、Texas Instruments 或 Microchip 没有任何关联,未经它们
认可,也不代表它们。
标签:2.4GHz协议, CC2500, SPI总线, 云资产清单, 射频, 智能照明, 硬件, 逆向工具, 逆向工程