diff --git a/docs/dongle-peripheral-design.md b/docs/dongle-peripheral-design.md new file mode 100644 index 0000000..22c0258 --- /dev/null +++ b/docs/dongle-peripheral-design.md @@ -0,0 +1,476 @@ +# Blinky 键盘 2.4G 端详细设计稿 + +## 1. 背景 + +当前 `C:\projects\blinky` 已经完成了外设侧多槽 BLE 基础能力: + +- `Slot 1~3` 对应普通 BLE 主机 +- `identity 4` 预留为 `Dongle Slot` +- `mode_policy_module` 已经区分: + - `MODE_SWITCH_BLE -> BLE_PROFILE_POLICY_GENERAL` + - `MODE_SWITCH_24G -> BLE_PROFILE_POLICY_DONGLE` + +但目前 `identity 4` 还只是“预留位”,没有真正落成完整的 dongle peer 行为。 +本设计稿的目标,是定义如何在**键盘外设固件内**实现“2.4G 端”,参考 `nrf_desktop` 的外围设备侧 dongle peer 设计。 + +这里的“2.4G 端”在第一阶段的实现语义不是 ESB 或私有无线协议,而是: + +- 键盘继续作为 BLE Peripheral +- 通过专用 local identity 与自家 dongle 建立专用连接 +- 在产品层把该模式呈现为“2.4G” + +这和 `nrf_desktop` 的 `dongle peer` 设计方向一致。 + +## 2. 设计目标 + +本方案的目标如下: + +- 在当前键盘固件内实现专用 `dongle peer` +- `MODE_SWITCH_24G` 时固定使用专用 `identity 4` +- `MODE_SWITCH_BLE` 时继续使用普通 BLE 槽位 `identity 1/2/3` +- `dongle peer` 与普通 BLE 槽位完全隔离 +- `dongle peer` 有独立 bond 和独立状态显示 +- Swift Pair 对普通 BLE 开启,对 `dongle peer` 默认关闭 +- 后续为自家 dongle 识别准备一个最小 `dev_descr` 风格自定义 GATT 服务 + +本设计稿不包含“dongle central 固件”的实现,只定义键盘外设侧。 + +## 3. 参考基线 + +本设计主要参考本地 `nrf_desktop` 的外围设备侧设计: + +- `c:\ncs\v3.2.3\nrf\applications\nrf_desktop\doc\ble_bond.rst` +- `c:\ncs\v3.2.3\nrf\applications\nrf_desktop\doc\dev_descr.rst` +- `c:\ncs\v3.2.3\nrf\applications\nrf_desktop\doc\qos.rst` +- `c:\ncs\v3.2.3\nrf\applications\nrf_desktop\src\modules\dev_descr.c` +- `c:\ncs\v3.2.3\nrf\applications\nrf_desktop\src\modules\qos.c` + +参考结论: + +- `dongle peer` 的核心不是新的无线协议,而是**专用 Bluetooth local identity** +- 外设与 dongle 的专用配对要和普通 BLE peer 隔离 +- `dev_descr` 是未来 dongle 识别外设的关键入口 +- `QoS` 是增强项,不是第一阶段前置条件 + +## 4. 当前工程现状 + +当前工程已经具备实现 `dongle peer` 的关键基础: + +- `ble_bond_multi_module` 已支持固定 identity 多槽 +- `identity 1/2/3` 已用于普通 BLE 槽位 +- `identity 4` 已预留为 `Dongle Slot` +- `mode_policy_module` 已输出 `BLE_PROFILE_POLICY_GENERAL / DONGLE` +- Swift Pair 已默认开启,并且在 `identity 4` 上默认关闭 + +相关文件: + +- `C:\projects\blinky\src\ble_bond_multi_module.c` +- `C:\projects\blinky\src\mode_policy_module.c` +- `C:\projects\blinky\inc\events\transport_policy_event.h` +- `C:\projects\blinky\src\swift_pair_module.c` + +当前缺失点: + +- `MODE_SWITCH_24G` 没有真正强制切到 `identity 4` +- `dongle peer` 没有独立 UI 状态 +- 没有 `dev_descr` 风格自定义服务 +- 没有独立的 dongle 管理接口 + +## 5. 总体设计 + +## 5.1 核心设计结论 + +采用 `nrf_desktop` 风格的“专用 dongle peer”设计: + +- 保持当前键盘为 BLE Peripheral +- 使用 `identity 4` 作为专用 dongle identity +- 以 `MODE_SWITCH_24G` 作为选择 `dongle peer` 的产品模式 +- 普通 BLE 槽位 `1/2/3` 与 `dongle peer` 独立管理 + +也就是说: + +- `2.4G` 是产品语义 +- 第一阶段实现仍然是 BLE Peripheral + 专用 identity + +## 5.2 identity 规划 + +identity 规划继续固定如下: + +| Identity | 角色 | 用途 | +| --- | --- | --- | +| `0` | 默认 identity | 不使用 | +| `1` | BLE Slot 1 | 普通 BLE | +| `2` | BLE Slot 2 | 普通 BLE | +| `3` | BLE Slot 3 | 普通 BLE | +| `4` | Dongle Slot | 专用 2.4G / dongle peer | + +设计原则: + +- `identity 4` 不参与普通槽位轮换 +- `identity 4` 不参与普通 BLE 设置页 +- `identity 4` 有独立 bond 和独立状态 + +## 6. 模块职责分工 + +## 6.1 `mode_policy_module` + +职责保持不变: + +- 根据拨杆位置输出 transport policy + +当前定义: + +- `MODE_SWITCH_BLE -> BLE_PROFILE_POLICY_GENERAL` +- `MODE_SWITCH_24G -> BLE_PROFILE_POLICY_DONGLE` + +它不直接管理 bond,只输出“当前应该走哪种 BLE profile”。 + +## 6.2 `ble_bond_multi_module` + +这是本方案第一阶段的主修改模块。 + +需要扩展职责: + +- 支持根据 `BLE_PROFILE_POLICY_DONGLE` 固定选择 `identity 4` +- 普通 BLE 与 `dongle peer` 分开管理 +- 提供 `dongle peer` 独立状态输出 +- 提供 `dongle peer` 独立擦除操作 + +仍然保留已有职责: + +- 普通 BLE 三槽切换 +- 普通 BLE 三槽擦除 +- slot meta 持久化 + +## 6.3 `swift_pair_module` + +职责保持: + +- 普通 BLE 槽位启用 Swift Pair +- `dongle peer` 默认关闭 Swift Pair payload + +这和 `nrf_desktop` 的思路一致。 + +## 6.4 新增 `dev_descr_module` + +建议新增一个最小版 `dev_descr` 风格服务。 + +目标: + +- 给未来的 dongle 提供外设识别信息 +- 不依赖设备名做唯一识别 + +第一阶段最小字段: + +- `caps` +- `hwid` + +后续可扩展: + +- `role` +- `product type` +- `firmware revision` + +## 6.5 `qos_module` + +第一阶段不做。 + +理由: + +- `nrf_desktop` 已明确说明自家 dongle 不依赖外围设备 QoS +- 当前先做 `dongle peer` identity 和识别就足够 + +## 7. 行为模型 + +## 7.1 普通 BLE 模式 + +条件: + +- `MODE_SWITCH_BLE` +- `BLE_PROFILE_POLICY_GENERAL` + +行为: + +- 当前 active slot 只能为 `1/2/3` +- UI 显示普通 BLE 三槽 +- 允许普通 BLE 切槽和擦除 +- Swift Pair 默认开启 + +## 7.2 2.4G / Dongle 模式 + +条件: + +- `MODE_SWITCH_24G` +- `BLE_PROFILE_POLICY_DONGLE` + +行为: + +- 当前 active identity 固定为 `4` +- 当前 bond 只属于 `identity 4` +- 不允许普通 BLE 三槽逻辑影响 `identity 4` +- Swift Pair 默认关闭 +- UI 应显示: + - `Dongle Searching` + - `Dongle Paired` + - `Dongle Connected` + - `Dongle Empty` + +## 7.3 模式切换语义 + +### BLE -> 24G + +1. `mode_policy_module` 发布 `BLE_PROFILE_POLICY_DONGLE` +2. `ble_bond_multi_module` 切 active identity 到 `4` +3. 提交 `PEER_OPERATION_SELECTED` +4. CAF `ble_adv` 切到 `identity 4` +5. 当前连接断开 +6. 使用 `identity 4` 广播 +7. dongle 重连 + +### 24G -> BLE + +1. `mode_policy_module` 发布 `BLE_PROFILE_POLICY_GENERAL` +2. `ble_bond_multi_module` 恢复普通 BLE 当前槽位 `1/2/3` +3. 提交 `PEER_OPERATION_SELECTED` +4. CAF `ble_adv` 切回对应 identity +5. 当前连接断开 +6. 使用普通 BLE 槽位广播 + +## 8. 状态与事件设计 + +## 8.1 当前已有事件 + +可继续复用: + +- `transport_policy_event` +- `ble_peer_event` +- `ble_peer_operation_event` +- `ble_bond_multi_event` + +## 8.2 建议扩展 `ble_bond_multi_event` + +建议增加字段或语义: + +- `active_profile` + - `GENERAL` + - `DONGLE` +- `dongle_slot_meta` + - `occupied` + - `last_peer_addr` + - `display_name` +- `current_identity` + +如果不想改现有事件结构,也可以新增一个独立事件: + +- `ble_dongle_state_event` + +推荐字段: + +- `state` + - `EMPTY` + - `SEARCHING` + - `PAIRED` + - `CONNECTED` +- `identity_id` +- `display_name` + +## 8.3 UI 状态来源 + +主界面与设置页可以通过以下信息判断: + +- 当前 `mode` +- 当前 `active_identity_id` +- `identity 4` 是否有 bond +- 当前是否有连接且该连接属于 `identity 4` + +## 9. `dev_descr` 设计 + +## 9.1 目标 + +最小化模仿 `nrf_desktop dev_descr`: + +- 为 dongle 提供一个稳定可读的识别服务 +- 避免仅靠设备名判断 + +## 9.2 服务内容 + +建议服务包含两个 characteristic: + +### Characteristic 1: `caps` + +建议字节布局: + +- bit0: `supports_llpm` +- bit1: `supports_dongle_peer` +- bit2: `is_keyboard` + +第一阶段只要能读出: + +- 这个设备支持 dongle peer +- 这是 keyboard 类型 + +### Characteristic 2: `hwid` + +固定长度硬件 ID: + +- 用于以后让 dongle 唯一识别这把键盘 +- 也可用于配置通道映射 + +## 9.3 权限建议 + +建议与 `nrf_desktop` 保持一致: + +- `BT_GATT_PERM_READ_ENCRYPT` + +原因: + +- 避免未加密链路上暴露识别信息 + +## 9.4 依赖 + +需要: + +- `CONFIG_HWINFO` +- 固件内已有或新增 `hwid_get()` 辅助逻辑 + +## 10. Settings 设计 + +继续沿用现有 namespace: + +- `ble_multi/current_slot` +- `ble_multi/meta/1` +- `ble_multi/meta/2` +- `ble_multi/meta/3` +- `ble_multi/meta/4` + +其中 `meta/4` 现在正式用于 dongle peer。 + +建议 `meta/4` 字段仍保持: + +- `occupied` +- `last_peer_addr` +- `display_name` + +显示策略: + +- 有真实名字则显示名字 +- 否则显示 MAC 地址 +- 无 bond 显示 `Empty` + +## 11. UI 设计 + +## 11.1 主界面 + +当前主界面可新增或扩展显示: + +- 当前模式 `USB / BLE / 24G` +- 如果 `24G` 模式: + - 右上角额外状态位显示: + - searching + - connected + +现有 BLE LINK 状态位可以复用,但语义建议细化: + +- BLE 模式下:表示普通 BLE 当前槽状态 +- 24G 模式下:表示 dongle peer 状态 + +## 11.2 设置页 + +建议新增二级入口: + +- `Bluetooth` + - Slot 1 + - Slot 2 + - Slot 3 + - Erase Current +- `Dongle` + - Status + - Erase Dongle Bond + +第一阶段如果不想扩菜单,至少要做到: + +- 主界面显示 dongle peer 状态 +- 设置页不把 `identity 4` 混入 Slot 1~3 + +## 12. 分阶段实施建议 + +## 阶段 1:Dongle Slot 真正接线 + +内容: + +- `ble_bond_multi_module` 支持 `BLE_PROFILE_POLICY_DONGLE` +- `MODE_SWITCH_24G` 时固定切到 `identity 4` +- `identity 4` 独立 bond 和独立状态 +- Swift Pair 在 `identity 4` 默认关闭 + +交付标准: + +- 24G 模式和 BLE 模式切换时 identity 正确切换 +- `identity 4` 与 `1/2/3` 完全隔离 + +## 阶段 2:UI / 状态管理 + +内容: + +- 增加 dongle 状态显示 +- 增加独立擦除 dongle bond 入口 +- 不把 dongle 混入普通 BLE 三槽 UI + +交付标准: + +- 用户可以明确区分: + - 普通 BLE 槽位 + - 2.4G / dongle peer + +## 阶段 3:最小 `dev_descr` + +内容: + +- 实现最小自定义 GATT service +- 提供 `caps + hwid` + +交付标准: + +- 未来 dongle 可稳定识别这把键盘 + +## 阶段 4:后续增强(非当前范围) + +可选项: + +- QoS +- 更强的 dongle 配对约束 +- 生产预绑定 +- 更明确的 dongle selector/恢复流程 + +## 13. 风险与边界 + +## 13.1 “2.4G” 实际仍然是 BLE + +第一阶段产品语义是 2.4G,链路实现仍是 BLE。 +这没有问题,但必须在代码和文档中明确,避免后续和真正私有 2.4G 链路混淆。 + +## 13.2 `dev_descr` 与未来 dongle 要对齐 + +如果未来 dongle 端也参考 `nrf_desktop central`,那这里的 UUID 和字段应该尽量稳定,不要后面再频繁改。 + +## 13.3 `identity 4` 与普通 UI 必须隔离 + +一旦 `identity 4` 被误混入普通三槽,就会造成用户理解混乱: + +- 不知道哪个是普通蓝牙 +- 哪个是 2.4G + +这是 UI 设计上最需要避免的问题。 + +## 14. 结论 + +本方案建议把当前键盘的“2.4G 端”实现为: + +- `BLE Peripheral + 专用 Dongle identity` +- `MODE_SWITCH_24G` 时固定走 `identity 4` +- 与普通 BLE 三槽完全隔离 +- 第一阶段先打通 identity / bond / UI 状态 +- 第二阶段补最小 `dev_descr` +- `QoS` 暂缓 + +这条路径与 `nrf_desktop` 外设侧的 dongle peer 设计一致,也与当前工程已有的 `transport_policy_event` 语义完全匹配。