一、HCI 概述
HCI(Host Controller Interface) 是蓝牙协议栈中 Host(主机) 与 Controller(控制器) 之间的标准接口层。
核心职责
| 功能 | 说明 |
|---|---|
| 命令下发 | Host 向 Controller 发送控制命令(如扫描、连接、设置参数) |
| 事件上报 | Controller 向 Host 上报异步事件(如连接完成、数据到达) |
| 数据传输 | ACL 数据(面向连接)和 SCO/eSCO 数据(同步语音)的双向传输 |
二、HCI 数据包类型
HCI 定义了 4 种数据包格式,每种都有固定的 Packet Indicator:
| Packet Type | Indicator | 方向 2.1 ### Command Packet(命令包) | 用途 |
|---|---|---|---|
| Command Packet | 0x01 | Host → Controller | Host 发送命令给控制器 |
| ACL Data Packet | 0x02 | 双向 | 传输 L2CAP 数据(异步连接) |
| SCO Data Packet | 0x03 | 双向 | 传输同步语音数据 |
| Event Packet | 0x04 | Controller → Host | 控制器上报事件 |
2.1 Command Packet(命令包)
┌─────────┬─────────┬──────────┬─────────┐
│ Opcode │Param Len│ Params │ CRC │
│ 2 bytes │ 1 byte │ 0-255 B │ (可选) │
└─────────┴─────────┴──────────┴─────────┘
- Opcode(操作码) :16 位,分为
OGF(Opcode Group Field,高 6 位)和OCF(Opcode Command Field,低 10 位)
OGF 标识命令组(如链路控制、链路策略、HCI 控制等)
OCF 标识具体命令
2.2 Event Packet(事件包)
┌─────────┬─────────┬──────────┐
│ Event │Param Len│ Params │
│ Code │ 1 byte │ 0-255 B │
│ 1 byte │ │ │
└─────────┴─────────┴──────────┘
重要事件类型:
| Event Code | 事件名 | 说明 |
|---|---|---|
0x0E | Command Complete | 命令执行完成,返回执行结果 |
0x0F | Command Status | 命令状态(正在处理中) |
0x13 | Number Of Completed Packets | 通知 Host 可以发送更多 ACL 包 |
0x3E | LE Meta Event | BLE 相关事件(如广告报告、连接完成) |
关键机制:大多数命令需要等待
Command Complete或Command Status事件确认。
2.3 ACL Data Packet(异步数据包)
┌─────────┬─────────┬─────────┬──────────┐
│ Handle │ PB Flag │ BC Flag │ Data Len │ Payload (L2CAP)
│ 12 bits │ 2 bits │ 2 bits │ 2 bytes │
└─────────┴─────────┴─────────┴──────────┘
-
Handle:连接句柄,标识某个 ACL 连接
-
PB Flag(Packet Boundary Flag) :
00:First non-automatically-flushable packet
01:Continuing fragment
10:First automatically-flushable packet
- BC Flag(Broadcast Flag) :用于广播/活动从设备广播
2.4 SCO Data Packet(同步数据包)
无论下面用哪种物理传输(UART/USB等),上层逻辑统一使用以下三种包格式:
| 包类型 | 方向 | 核心字段 | 用途 |
|---|---|---|---|
| HCI Command | Host → Controller | OpCode (操作码, 2字节) + 参数长度 + 参数 | 让Controller执行动作:扫描、连接、断开、配对等。 |
| HCI Event | Controller → Host | 事件码 (1字节) + 参数长度 + 参数 | 通知Host状态变化:命令完成、连接建立、数据到达、断开、新设备发现等。 |
| HCI ACL Data | 双向 | 句柄 (Handle, 12位) + PB标志 (2位) + 广播标志 (2位) + 数据长度 + 有效载荷 | 传输普通数据(最常用,如SPP传输文件、BLE的GATT数据)。ACL = 异步无连接链路。 |
| HCI SCO/eSCO Data | 双向 | 句柄 + 数据长度 + 有效载荷 | 传输同步音频数据(电话语音)。同步连接导向链路。 |
三、HCI 传输层(Transport Layer)
HCI 是逻辑协议,可以承载在多种物理传输层上:
| 传输层 | 常用变体 | 主要应用 | 特点与细节 |
|---|---|---|---|
| UART | H4 (标准), H5 (三线流控), BCSP (CSR私有,已少用) | 嵌入式、IoT设备、模块化产品 (如ESP32+蓝牙模块、手机主板基带处理器与蓝牙芯片之间) | 最普及、简单、低成本。需要硬件流控(RTS/CTS)保证高速不丢包。 H4协议:每个HCI包前加一个1字节标识符(01=Command,02=ACL Data,04=Event)。 面试重点:容易丢字节,无差错控制,需流控。 |
| USB | H2 (实际使用HCI over USB) | PC、笔记本、USB蓝牙适配器 | 高速、即插即用。将蓝牙控制器模拟成一个USB设备(通常复合设备:HCI接口+音频接口等)。 内部使用Bulk传输(数据/命令/事件)和Isochronous传输(音频)。 驱动层面:Windows使用btusb.sys,Linux使用btusb内核驱动。 |
| SDIO | SDIO over HCI | Wi-Fi/蓝牙二合一模块 (如笔记本电脑内部的内置无线网卡) | 高速、多引脚复用。SDIO总线除了接SD卡,也接蓝牙/WiFi combo芯片。能同时传输蓝牙ACL数据和WiFi数据。 协议复杂,需要为蓝牙分配一个“功能号(Function)”和“块(Block)”。 |
| SPI | H4 over SPI (非标准) | 调试、低端嵌入式原型 | 极简单、无流控、效率低。因为SPI是主从式,Host必须作为主设备主动轮询,Controller无法主动上报事件(需要引入中断引脚)。极少用于量产产品。 |
3.1 UART(最常用)
┌─────────┬────────────────────────┐
│ 0x01/02 │ HCI Packet │
│Indicator│ (Command/ACL/SCO/Event)│
└─────────┴────────────────────────┘
特点:
- 最简单、成本最低
- 需要额外 1 字节 Packet Indicator(数据包指示器)
- 波特率通常 115200 ~ 4Mbps(可协商)
- 蓝牙芯片常用 `H4` 协议(原始 HCI over UART)
- 也有 `H5`(Three-wire UART,带流控和重传)和 `BCSP`(BlueCore Serial Protocol)
H4 vs H5:
| 特性 | H4 | H5 |
|---|---|---|
| 线数 | 2(TX/RX) | 3(TX/RX/STATE) |
| 流控 | 软件 XON/XOFF | 硬件 + 软件 |
| 可靠性 | 无重传 | 有重传机制 |
| 适用场景 | 简单场景 | 高可靠需求 |
3.2 USB
使用 USB Class Definition for Bluetooth 规范。
特点:
- 即插即用,驱动标准化
- 支持多个端点:控制、中断(事件)、批量(ACL)、等时(SCO)
- PC 上最常见的 HCI 接口(USB 蓝牙适配器)
- USB 描述符中声明为 Class 0xE0(Wireless Controller),SubClass 0x01,Protocol 0x01
端点分配:
| 端点类型 | 用途 |
|---|---|
| Control EP0 | HCI 命令 + 部分事件 |
| Interrupt IN | 异步事件上报 |
| Bulk IN/OUT | ACL 数据传输 |
| Isochronous IN/OUT | SCO 语音数据 |
3.3 SPI
特点:
- 高速传输,适合对带宽要求高的场景
- 主从架构,Host 为主设备
- 需要额外的中断线通知 Host 有数据到达
- 常用于嵌入式系统
3.4 SDIO
特点:
- 主要用于 WiFi + 蓝牙 Combo 芯片
- 共享 SDIO 总线,节省引脚
- 需要分时复用或专用功能分区
- 常见于手机、平板等移动设备
四、HCI 工作流程示例
经典流程:BLE (低功耗)设备扫描并连接
Host Controller
│ │
│── HCI_LE_Set_Scan_Parameters ──────────►│ 设置扫描参数
│ │
│── HCI_LE_Set_Scan_Enable(1) ───────────►│ 开始扫描
│ │
│◄────────── HCI_LE_Advertising_Report ───│ 收到广播包(事件 0x3E)
│ │
│── HCI_LE_Create_Connection ────────────►│ 发起连接
│ │
│◄────────── HCI_Command_Status ──────────│ 命令已接收(事件 0x0F)
│ │
│◄────────── HCI_LE_Connection_Complete ──│ 连接建立(事件 0x3E,子事件 0x01)
│ │
│── HCI_LE_Read_Remote_Features ─────────►│ 读取对端特性
│ │
│◄────────── HCI_Command_Complete ────────│ 命令完成(事件 0x0E)
│ │
│══ ACL Data =================════════════│ L2CAP 数据交换
│ │
五、关键机制详解
5.1 流控(Flow Control)
HCI 定义了两种流控:
| 类型 | 方向 | 机制 |
|---|---|---|
| Host to Controller Flow Control | Host → Controller | 基于 Credit(令牌),Controller 通过 Number Of Completed Packets 事件返还 Credit |
| Controller to Host Flow Control | Controller → Host | 基于 Host Buffer Size 和 Host Number Of Completed Packets 命令 |
为什么需要流控?
- Controller 的硬件缓冲区有限
- 防止 Host 发送过快导致丢包
- 每个 ACL 连接独立维护 Credit
数据流控是HCI协议能否稳定工作的关键,尤其是在UART上。
问题:Host比Controller快得多。如果Host疯狂发ACL数据,Controller的缓冲区会溢出丢包。
解决:基于数字的流控 (Number of Completed Packets)。
- Controller 在初始化时通过
Read_Buffer_Size命令告诉 Host:我的ACL Buffer大小和ACL Buffer个数。- Host 确保同时发送的未确认 ACL 包数量 ≤ Controller 的 Buffer 个数。
- 每发一个包,Host 减少一个“信用” (Credits)。
- Controller 每处理完一个包,就向 Host 发一个
Number_Of_Completed_Packets事件,Host 增加一个“信用”。- Host 在信用为 0 时必须停止发送。
面试常问:为什么HCI over UART容易丢包?
答:因为UART本身无重传机制,且流控实现不当或RTS/CTS信号错误,导致Controller缓冲区满后Host还在发。
5.2 事件屏蔽(Event Mask)
Host 可以通过 HCI_Set_Event_Mask 命令选择接收哪些事件,减少不必要的处理。
Set_Event_Mask 参数(8 字节位掩码):
- Bit 0: Inquiry Complete
- Bit 1: Inquiry Result
- ...
- Bit 61: LE Meta Event(BLE 必须开启)
5.3 LE Meta Event(0x3E)
BLE 所有事件都封装在 LE Meta Event 中,通过 Subevent Code 区分:
| Subevent Code | 事件名 | 中文翻译 |
|---|---|---|
0x01 | LE Connection Complete | 蓝牙低功耗连接完成 |
0x02 | LE Advertising Report | 蓝牙低功耗广播上报 |
0x03 | LE Connection Update Complete | 蓝牙低功耗连接参数更新完成 |
0x04 | LE Read Remote Features Complete | 蓝牙低功耗读取远端特性完成 |
0x0A | LE Enhanced Connection Complete | 蓝牙低功耗增强型连接完成 |
0x0D | LE Extended Advertising Report | 蓝牙低功耗扩展广播上报 |