Unleashed 固件 SubGHz 计数器实验模式(CounterMode)完全指南:协议支持、.sub 配置与源码原理
【免费下载链接】unleashed-firmwareFlipper Zero Unleashed Firmware项目地址: https://gitcode.com/GitHub_Trending/un/unleashed-firmware
导读
SubGHz Counter Experimental Mode 是 Unleashed 固件为 Flipper Zero 提供的一项高级实验特性,它允许你自定义 SubGHz 滚动码信号发射时计数器的递增方式。其核心目标是:让克隆的遥控器与原装遥控器在滚动码(rolling code)系统中同时使用而不互相冲突、不失步(desync)——不同品牌的接收器对计数器序列的校验规则不同,通过切换不同的 CounterMode,可以让 Flipper 发送的计数器序列与特定接收器型号的预期行为对齐。读完本文,你将掌握如何手工编辑.sub文件启用 CounterMode、五个支持协议的完整模式对照表(含源码级验证),以及模式选择背后的实现原理与风险边界。
⚠️重要警告(原文保留):不要对你没有访问权限的设备做实验。如果你不确定哪种模式适合你的系统、且无法对接收器重新编程,不要使用这些模式!如果你有接收器访问权限并能进行测试,可以在这些模式中尝试并到 GitHub issues 或社区反馈结果。
一、什么是 CounterMode:实验模式的设计动机
滚动码(rolling code)协议每次按键都会改变发射数据中的计数器(counter)字段,接收器只接受"预期范围内的下一个计数值",以此防止重放攻击。Flipper 克隆了信号后,如果每次发送都简单地把计数器 +1,当原装遥控器也同时被使用时,两边会互相"抢占"计数器序列,导致接收器判定失步(desync),最终双方都失效。
Experimental Counter Mode 的思路是:改变 Flipper 发送时计数器的步进序列(sequence pattern),使其与特定接收器固件/型号实际校验的序列保持一致,从而让 Flipper 与原装遥控器可以在同一套滚动码系统里"井水不犯河水"地共存。
从源码看,这是纯粹在编码器(encoder)侧实现的特性:lib/subghz/protocols/下每个支持该特性的协议文件中,都有一个静态全局变量保存当前模式,例如nice_flors_counter_mode(nice_flor_s.c)、keeloq_counter_mode(keeloq.c)、came_atomo_counter_mode(came_atomo.c)、alutech_at4n_counter_mode(alutech_at_4n.c)、v2_phoenix_counter_mode(phoenix_v2.c)。该变量在反序列化.sub文件时通过flipper_format_read_uint32(flipper_format, "CounterMode", ...)读取(缺失时置 0),随后在生成发射波形时决定计数器如何递增。
二、如何启用 CounterMode:手工编辑 .sub 文件
启用某个计数器模式,需要手工编辑你的.sub文件并添加一行CounterMode配置。
操作步骤
- 在 Flipper Zero 的 SD 卡上找到你的
.sub文件(位于/ext/subghz/目录); - 用文本编辑器打开该文件;
- 在文件末尾添加如下一行:
CounterMode: X其中X是模式编号(0、1、2……),具体取值范围取决于协议,详见下文模式对照表。
完整示例 .sub 文件
Filetype: Flipper SubGhz Key File Version: 1 Frequency: 433920000 Preset: FuriHalSubGhzPresetOok650Async Protocol: Nice FloR-S Bit: 52 Key: AA AA AA AA AA AA AA CounterMode: 1源码层面的读取逻辑
在固件源码中,这一行的解析路径是:编码器/解码器的*_deserialize()函数调用flipper_format_read_uint32()读取CounterMode,读取失败则回退到模式 0(标准模式)。以 KeeLoq 为例(keeloq.c):
uint32_t tmp_counter_mode; if(flipper_format_read_uint32(flipper_format, "CounterMode", &tmp_counter_mode, 1)) { keeloq_counter_mode = (uint8_t)tmp_counter_mode; } else { keeloq_counter_mode = 0; }因此语法上要求CounterMode:后紧跟空格再写数字,且模式号必须在该协议支持范围内。如果你使用无效的模式号,根据 SubGHzCounterMode.md 的 FAQ,最后一个模式会被采用——从源码看,这正是各协议if/else链末端兜底分支的行为(例如 KeeLoq 中keeloq_counter_mode == 7之外的任何值都会落入else的 Mode 7 分支)。
三、无需手动编辑文件:Signal Settings 菜单中的 CounterMode 选项
除了手工编辑.sub,固件还在 SubGHz 应用的信号设置场景中提供了图形化配置入口。场景代码 subghz_scene_signal_settings.c 中定义了 8 个可选项("System" 即模式 0,以及 Mode 1~Mode 7),并根据协议动态限制可选数量:
| 协议名(源码中的字符串) | 可用模式数 |
|---|---|
| Nice FloR-S | 3(模式 0~2) |
| CAME Atomo | 4(模式 0~3) |
| Alutech AT-4N | 3(模式 0~2) |
| KeeLoq | 8(模式 0~7) |
| Phoenix_V2 | 3(模式 0~2) |
该场景通过flipper_format_insert_or_update_uint32()把所选模式写回.sub文件;如果文件中的协议不在上表内,该项会被锁定并提示 "Not available for this protocol"(对应源码中counter_mode == 0xff的状态)。
四、支持协议与计数器模式对照表(附源码验证)
以下所有模式均已在对应协议源码的计数器递增逻辑中逐一确认。五种协议的模式 0(默认)行为完全一致:
模式 0(默认 / 标准模式)
- 行为与普通遥控器一致;
- 使用全局设置中的滚动计数器乘数(rolling counter multiplier,默认 +1)递增;
- 计数器溢出(> 0xFFFF)时归零重置。
该乘数由 HAL 层维护:furi_hal_subghz.c中rolling_counter_mult默认值为 1,furi_hal_subghz_get_rolling_counter_mult()返回当前值(furi_hal_subghz.c)。标准模式下的递增逻辑形如(以 Nice Flor-S 为例,nice_flor_s.c):
if((instance->generic.cnt + furi_hal_subghz_get_rolling_counter_mult()) > 0xFFFF) { instance->generic.cnt = 0; } else { instance->generic.cnt += furi_hal_subghz_get_rolling_counter_mult(); }此外,五种协议还共享一个隐藏分支:当全局滚动计数器乘数被设置为-0x7FFFFFFF(即 OFEX / overflow experimental 溢出实验模式)时,模式 0 会退化为0x0001 / 0xFFFE交替序列。
1. Nice Flor-S(源码:lib/subghz/protocols/nice_flor_s.c)
| 模式 | 计数器序列 | 适用场景 |
|---|---|---|
| 0(默认) | 标准递增(+乘数),溢出归零 | 普通遥控器模拟 |
| 1(floxi2r) | 0x0001 / 0xFFFE交替 | 适用于 floxi2r 型号接收器 |
| 2(ox2) | 0x0000 / 0x0001交替 | 适用于 ox2 型号接收器 |
源码实现位于 nice_flor_s.c:Mode 1 在计数器为0xFFFE时置回0x0001,否则强制置为0xFFFE;Mode 2 在计数器 ≥ 1 时归零,否则 +1。
2. Came Atomo(源码:lib/subghz/protocols/came_atomo.c)
| 模式 | 计数器序列 | 适用场景 |
|---|---|---|
| 0(默认) | 标准递增(+乘数),溢出归零 | 普通遥控器模拟 |
| 1 | 0x0000 / 0x0001 / 0xFFFE / 0xFFFF循环 | 兼容外置 CAME RE432 接收器,可能兼容其他接收器 |
| 2 | 0x807B / 0x807C / 0x007B / 0x007C循环 | 兼容外置 CAME RE432 接收器,可能兼容其他接收器 |
| 3 | 计数器冻结(不递增) | 固定计数值发送 |
源码实现位于 came_atomo.c。需要说明的是,CAME Atomo 的发射报文里还包含一个独立的"按键按住周期计数器"(8-bit,0~0x7F),这与我们讨论的 16-bit 滚动计数器是两回事,详见源码注释 came_atomo.c。
3. Alutech AT-4N(源码:lib/subghz/protocols/alutech_at_4n.c)
| 模式 | 计数器序列 | 适用场景 |
|---|---|---|
| 0(默认) | 标准递增(+乘数),溢出归零 | 普通遥控器模拟 |
| 1 | 0x0000 / 0x0001 / 0xFFFE / 0xFFFF循环 | 适用于 MCSW-3.3M 接收器 |
| 2 | 0x0000 / 0x0001 / 0x0002 / 0x0003 / 0x0004 / 0x0005循环 | 适用于其他接收器板 |
源码实现位于 alutech_at_4n.c:Mode 2 在计数器 ≥ 0x0005 时归零,否则 +1,实现 0~5 循环。
4. KeeLoq(源码:lib/subghz/protocols/keeloq.c)
| 模式 | 计数器序列 | 适用场景 |
|---|---|---|
| 0(默认) | 标准递增(+乘数),溢出归零 | 普通遥控器模拟 |
| 1 | 0x0000 / 0x0001 / 0xFFFE / 0xFFFF循环 | 可能兼容某些系统(欢迎反馈) |
| 2 | 增量模式:每次发射 +0x3333(十进制 13107),溢出归零 | 可能兼容 Doorhan,常见于某些"万能遥控器" |
| 3 | 0x8006 / 0x8007 / 0x0006 / 0x0007循环 | 可能兼容 Hormann EcoStar 等系统 |
| 4 | 0x807B / 0x807C / 0x007B / 0x007C循环 | 可能兼容 Nice Smilo 等系统 |
| 5 | 0x0000 / 0xFFFF交替(在 0 与最大值 65535 之间跳变) | 可能兼容某些系统(欢迎反馈) |
| 6 | 计数器冻结(不递增) | 固定计数值发送 |
| 7 | 对当前计数器连续做 5 次 +0x3333,然后恢复原值依次 +1 两次,一包共 7 条信号 | 可能兼容 Doorhan,常见于某些"万能遥控器" |
KeeLoq 的 Mode 2 实现位于 keeloq.c:(cnt + 0x3333) > 0xFFFF时归零,否则cnt += 0x3333。Mode 7 则是一个多信号序列:在 keeloq.c 中可以看到,它循环 7 次生成上传序列——前 4 次以计数器 +0x3333 递增(counter_up = true),第 3 次固定为0x0000,最后两次分别用原计数器和原计数器 +1 各发射一帧。
文档特别提示:Mode 7 下在 Flipper 上单击一次 Send 按钮即可发射整包 7 条信号,可能绕过接收器的计数器校验窗口,请等待完整传输结束。
5. V2 Phoenix(Phox)(源码:lib/subghz/protocols/phoenix_v2.c)
| 模式 | 计数器序列 | 适用场景 |
|---|---|---|
| 0(默认) | 标准递增(+乘数),溢出归零 | 普通遥控器模拟 |
| 1(类 ofex) | 0x0000 / 0x0001 / 0xFFFE / 0xFFFF循环 | 已验证可用 |
| 2(0~4) | 0x0000 / 0x0001 / 0x0002 / 0x0003 / 0x0004循环 | 可能可用(欢迎反馈) |
源码实现位于 phoenix_v2.c:Mode 1 与 OFEX 序列一致;Mode 2 在计数器 ≥ 0x0004 时归零,否则 +1。与 KeeLoq 类似,Phoenix V2 的计数器在写入波形前还会经过subghz_protocol_phoenix_v2_encrypt_counter()加密处理。
五、重要注意事项与故障排查
关键考量
- 默认行为:如果
.sub文件中未指定CounterMode,固件默认使用普通遥控器模拟(计数器 +1),这是标准模式,在大多数场景下都能正常工作; - 协议兼容性:并非所有协议都支持所有计数器模式。使用不支持的编号可能导致意外行为(如落入最后一个模式的兜底分支);
- 务必先测试:在依赖某个配置之前,始终先验证其行为。
故障排查
如果你的文件在添加CounterMode后不工作:
- 复查语法:
CounterMode: X(冒号后必须有空格); - 确认该模式编号对当前协议是有效的(对照上文模式表)。
安全与合规边界
- 根据原文档 FAQ:该功能可能会损坏你的遥控器或接收器——取决于接收器实现,它可能导致你的原装遥控器失步;不要对你没有访问权限的设备做实验;
- 不确定该用哪个模式时,不要使用这些模式;
CounterMode不是必须逐文件添加的:只有需要非默认行为时才需要加,未指定时自动使用模式 0(SubGHzCounterMode.md)。
一个值得注意的源码细节:bypass 机制
在所有五个协议实现中,都存在一个bypass标志:当你在 Signal Settings 菜单中通过界面直接修改了 Counter 或 Button 时,固件会置位bypass,从而跳过 CounterMode 序列逻辑,按你手动指定的计数值直接生成信号(例如 nice_flor_s.c 注释:"if we change counter/button in SignalSettings menu then we must bypass counter_modes, just gen and save signal file")。这意味着界面手动改计数与 CounterMode 序列是互斥的两条路径,理解这一点有助于解释"为什么我改了计数但 CounterMode 好像没生效"。
六、完整配置示例
示例 1:Nice Flor-S 使用模式 1(floxi2r)
Filetype: Flipper SubGhz Key File Version: 1 Frequency: 433920000 Preset: FuriHalSubGhzPresetOok650Async Protocol: Nice FloR-S Bit: 52 Key: 01 23 45 67 89 AB CD CounterMode: 1示例 2:KeeLoq 使用模式 2(+0x3333,Doorhan)
Filetype: Flipper SubGhz Key File Version: 1 Frequency: 433920000 Preset: FuriHalSubGhzPresetOok650Async Protocol: KeeLoq Bit: 64 Key: DE AD BE EF CA FE BA BE Manufacture: Doorhan CounterMode: 2提示:KeeLoq 协议的
.sub文件通常还包含Manufacture(厂商)字段,编码器会根据厂商名选择不同的学习方式与加密密钥(keeloq.c),CounterMode 与该字段相互独立、可组合使用。
七、FAQ 速查
Q: 这会损坏我的遥控器或接收器吗?A: 可能会。取决于接收器实现,它可能导致你的遥控器失步。请注意风险,不要对你没有访问权限的设备做实验。
Q: 我应该用哪个模式?A: 如果你不确定,就不要使用这些模式。
Q: 如果我用了无效的模式编号会怎样?A: 会采用列表中的最后一个模式(源码中即if/else链的兜底分支)。
Q: 我需要给每个 .sub 文件都加 CounterMode 吗?A: 不需要。只有需要非默认行为时才加;未指定时自动使用模式 0。
本文基于 Unleashed 固件仓库中的 SubGHzCounterMode.md 撰写,并结合 lib/subghz/protocols/ 下五个协议的编码器实现、furi_hal_subghz.c 的全局计数器乘数实现以及 subghz_scene_signal_settings.c 的界面配置逻辑进行了源码级验证。引用时请注明出处。
【免费下载链接】unleashed-firmwareFlipper Zero Unleashed Firmware项目地址: https://gitcode.com/GitHub_Trending/un/unleashed-firmware
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考