蓝牙协议栈基础:HCI层、L2CAP层、RFCOMM层、HID Profile概述
蓝牙协议栈是蓝牙设备之间通信的软件骨架。对于嵌入式Linux开发者而言,理解协议栈的分层结构是配置设备树、编写驱动和处理中断的前提。本章将聚焦于与蓝牙HID设备最相关的四个核心层次:HCI、L2CAP、RFCOMM以及HID Profile。
2.1 HCI层:主机与控制器之间的桥梁
HCI(Host Controller Interface)定义了主机(Host)与蓝牙控制器(Controller)之间的通信协议。在嵌入式Linux系统中,主机通常是运行Linux内核的SoC,控制器则是蓝牙芯片(如Broadcom、TI、Realtek等)。
HCI层核心功能
- 命令(Command): 主机向控制器发送控制命令,如重置、扫描、连接建立。
- 事件(Event): 控制器向主机报告状态变化,如连接完成、断开、数据到达。
- 数据(Data): 承载ACL(异步无连接)和SCO(同步面向连接)数据包。
HCI传输层与设备树的关系
设备树中配置的蓝牙节点主要描述HCI传输层的硬件接口参数。最常见的传输方式是UART(H4协议),设备树中需要指定UART端口、波特率、流控引脚以及蓝牙唤醒中断。
| 传输类型 | 设备树关键属性 | 典型驱动 |
|---|---|---|
| UART (H4) | compatible, current-speed, clocks, pinctrl, interrupts | hci_uart.ko / btbcm.ko |
| USB | compatible, reg, interrupt-parent | btusb.ko |
| SDIO | compatible, bus-width, non-removable, interrupts | btintel.ko / btmrvl.ko |
hcitool 和 btmon 工具捕获HCI数据包。设备树中 interrupts 属性的正确配置是蓝牙唤醒主机(BT_WAKE)功能的基础。
2.2 L2CAP层:逻辑链路控制与适配
L2CAP(Logical Link Control and Adaptation Protocol)位于HCI层之上,为上层协议提供面向连接和无连接的数据服务。L2CAP负责:
- 协议复用: 区分上层协议(如RFCOMM、HID、ATT)。
- 分段与重组: 将大包拆分为HCI ACL数据包,并在接收端重组。
- 服务质量(QoS): 管理数据流的优先级和延迟。
L2CAP信道与CID
每个L2CAP连接使用信道标识符(CID)来标识不同的逻辑信道。固定信道用于信令(CID 0x0001),动态信道用于上层协议。
| CID范围 | 用途 | 示例 |
|---|---|---|
| 0x0001 | L2CAP信令信道 | 连接请求、配置参数 |
| 0x0003 - 0x003F | 固定信道(保留) | ATT协议 (0x0004) |
| 0x0040 - 0xFFFF | 动态分配信道 | RFCOMM、HID控制/中断 |
2.3 RFCOMM层:串口仿真协议
RFCOMM(Radio Frequency Communication)协议在L2CAP之上提供串口仿真服务。它模拟RS-232串行接口,使得传统的串口应用程序(如PPP、AT指令)可以透明地运行在蓝牙链路上。
RFCOMM核心特性
- 端口仿真: 最多支持30个虚拟串口(DS-DE)。
- 流控: 支持RTS/CTS硬件流控和XON/XOFF软件流控。
- 多路复用: 多个RFCOMM会话可以共享一个L2CAP信道。
在蓝牙HID场景中,RFCOMM通常用于HID设备配置和固件升级(DFU),而实时输入数据则通过L2CAP中断信道直接传输,不经过RFCOMM。
2.4 HID Profile概述
HID Profile(Human Interface Device Profile)定义了蓝牙键盘、鼠标、游戏手柄等输入设备与主机之间的通信规范。它基于L2CAP层,使用控制信道和中断信道两条逻辑链路。
HID Profile关键要素
| 要素 | 说明 | 典型值 |
|---|---|---|
| 控制信道 | 用于建立连接、获取报告描述符、设置协议模式 | L2CAP PSM 0x0011 |
| 中断信道 | 用于传输低延迟的输入报告(鼠标移动、按键) | L2CAP PSM 0x0013 |
| 报告描述符 | 描述设备输入/输出数据的格式和用途 | USB HID标准格式 |
| 协议模式 | Boot Protocol(兼容BIOS)或 Report Protocol | 键盘通常支持Boot模式 |
HID数据流与中断处理
当蓝牙HID设备(如鼠标)产生输入事件时,数据流如下:
- 设备通过中断信道发送HID报告(如鼠标相对位移)。
- 蓝牙控制器通过HCI事件通知主机有数据到达。
- 主机HCI驱动触发硬件中断(如UART RX中断或GPIO中断)。
- 数据经L2CAP层解包后递交给HID Profile处理。
- HID Profile将报告转换为Linux输入子系统事件(如
input_report_rel)。
interrupts 属性(如BT_HOST_WAKE引脚)决定了主机能否及时响应蓝牙控制器的数据到达事件。错误的电平触发方式(如应设为边沿触发却设为电平触发)会导致中断丢失或CPU占用过高。
2.5 协议栈各层在设备树中的体现
设备树配置主要影响HCI传输层和中断路径,但理解上层协议有助于正确配置和调试。下表总结了各层与设备树的关联程度:
| 协议层 | 设备树直接配置 | 驱动代码关注点 | 调试工具 |
|---|---|---|---|
| HCI传输层 | 是 — UART引脚、波特率、中断 | hci_uart 驱动、DMA配置 | hcitool, btmon |
| HCI层 | 间接 — 传输层参数影响HCI帧 | HCI命令/事件处理 | btmon, wireshark |
| L2CAP层 | 否 — 纯软件协议 | 信道管理、MTU协商 | l2ping, btmon |
| RFCOMM层 | 否 — 纯软件协议 | 串口仿真、流控 | rfcomm, minicom |
| HID Profile | 否 — 纯软件协议 | 报告解析、输入子系统 | hid-recorder, evtest |