基于 BLE 5.1 协议 Core Spec。
目录
1、系统分层
2、HCI
2.1、HCI — UART
2.1.1、HCI Type
2.1.2、HCI Command Packet
2.1.3、HCI Event Packet
2.1.4、HCI ACL Data Packet
3、总结
前面叙述的内容均是 BLE 协议栈中,较为靠近底层的东西,靠近物理层面(硬件和对应 IP 的驱动)的一些内容。蓝牙系统是一个软硬件结合的系统,硬件给了软件良好的支撑,软件需要赋予数据业务逻辑的含义,这样,组成一套完整的 BLE 系统。
在 BLE 系统中不仅仅是物理层和硬件内容,根据整个 BLE 从上到下,大致分为了 Profile,Host,HCI,Controller 以及 硬件部分的 Baseband 和 RF。
两个 BLE 通信,从逻辑上来看,是每个层的单独通信,从数据的流向来看,发送是自上而下,数据接收是自下而上。
Profile:主要是根据不同的应用场景,制定了最上层的协议交互。比如,心率的 Profile,电池电量检测的 Profile 等。
Host:为上层提供接口支持,自身维护了一些软件层次的协议和加密流程等等控制,纯软件行为。
HCI 的全称是:Host Interface Controller,是 Host 和 Controller 通信之间的接口。那么问题来了,Host 与 app 之间是直接的 Function call,那为啥 Host 与 Controller 之间要专门的定义两层软件之间的通信协议呢?这就要从 BLE 的产品形态说起了。稍后呈现。
Controller:向上负责向 Host 汇报状态,向下,接收 Host 的指令,与 Baseband 交互,协调、控制、管理硬件资源。
Modem:负责调制解调
RF:收发机负责接收/发送空中的数据包。
HCI 的全称是:Host Interface Controller,是 Host 和 Controller 通信之间的接口。存在这个薄薄的一层协议的含义是这样的:
一般的,BLE 是一颗单芯片的解决方案,芯片集成了所有的软硬件资源,对于单独的产品来说,可能出现以下产品形态:
1、Full stack:从上到下的协议栈全部都有,用户简单的写 App 调用接口即可,此刻,HCI 退化成为 Function Call(比如手环产品,节点控制器,单车控制器等等)
2、Only Controller:有的产品,只需要 Controller 不要 Host 和 APP,BLE 芯片作为一个外挂芯片,接到主控芯片上,主控芯片通过标准的 HCI 指令(通常介质为 UART)与 BLE 芯片交互。此刻,HCI 便成为了一种两颗芯片之间的通信协议(比如手机上 AP 和 BLE 就是这样的关系)
3、Only Host:Android 不就是么
在 BLE Core Spec 中,HCI 相关的内容定义在 Vol 4:Host Controller Interface [Transport Layer]:
可以看到,BLE Core Spec 支持的 HCI 种类有 4 中:
UART
USB
SDIO
3-Wire UART
也就是说,当我们要使用 BLE 的时候,如果他能够支持外挂的这种类型,并且要知道他支持的 HCI 的类型,那么我们就可以将其挂接到我们的 AP 或者 MCU 上,通过其总线来进行 BLE 芯片的控制(其实就把 BLE当成一个 MCU 的外设一样就可,一个大一点的 IP 而已)。
一般的,一款这样的 BLE 只支持一种传输的 HCI 协议,通常是第一中类型,也就是 UART。那我们就来针对这个进行分析,其余的也是套路。
这里分析 UART 串口的交互过程。
使用 UART 往 Controller 发送字节流,首先将 UART 传输的 Bytes 流分为了如下几类:
第一个字节,代表了这个 HCI 的类型
HCI packet type | HCI packet indicator |
HCI Command Packet |
0x01 |
HCI ACL Data Packet | 0x02 |
HCI Synchronous Data Packet | 0x03 |
HCI Event Packet | 0x04 |
因为 HCI 是双向的,发给 Controller 的命令称之为 HCI Command,Controller 发给上层的成为 HCI Event。
如果上层要给 Controller 发数据,那么叫 HCI ACL Data Packet。
在 LE 中,HCI Synchronous Data Packet 没用,不管它。
上述 4 中格式定义在:
当第一个字节 HCI Type 为 0x01 的时候,说明这个 HCI 是一个下发的命令类型。他的命令字节流构成为:
OpCode:
显示一个 16 bits 的 OpCode,用于标识这个命令的类型,OpCode 切分为两部分:
OCF(6 bits):命令字段, 0x00-0x3F (0x3F reserved for vendor-specific debug commands)
OGF(10 bits): 组字段,0x0000-0x03FF
OGF 细分:
指令类型 | OGF |
链路控制指令(Link Control commands) | 0x01 |
链路策略指令(Link Policy Commands) | 0x02 |
主机控制器与基带指令(HCI Control and Baseband Commands) | 0x03 |
信息参数指令(INFORMATIONAL PARAMETERS) | 0x04 |
状态指令参数(STATUS PARAMETERS) | 0x05 |
测试指令(TESTING COMMANDS) | 0x06 |
LE CONTROLLER COMMANDS | 0x08 |
厂商预留测试命令(Reserved) | 0x3F |
所以,针对 LE 来说,关注 LE CONTROLLER COMMANDS 更多
Parameter Total Length:后续参数的长度
Parameter[0] ~ Parameter[N] : 根据 OpCode 可以知道这波操作的类型,然后根据 Parameter Total Length 可以知道接收多少数据,然后 Contorller 在根据 OpCode 对应的一个数据流,按照数据流每个位域的含义进行解析。
注:参数最多255字节,不包括 HCI 命令包头
与 Command 类似,当第一个字节 HCI Type 为 0x04 的时候,说明这个 HCI 是来自 Controller 到上层的 Event 类型。
Event 的组成格式为:
其中,Event Code 是个枚举,用于区分上报的不同 Evnet 类型。
Event Code:用以区分不同的事件(0x00~0xFF)
Parameter_Total_length:参数的长度(以字节为单位)
Event Parameter[0] ~ Event Parameter[N] :参数列表
ACL Data 的字节流只有在连接的状态才能够发送,当第一个字节 HCI Type 为 0x02 的时候,说明这个 HCI 是 ACL 数据类型,它的组成稍微不同:
Handle:由于 BLE 支持多连接,连接之间使用 Handle 区分,这个参数用于区分不同的连接。
PB Flag:全称叫 Packet Boundary Flag,他的描述为(这里,我们只关注 LE 的 Allowed 的):
设置为 00'b 的时候,代表 Host -> Contoller 的 L2CAP 的首包
设置为 01'b 的时候,代表 Host -> Contoller 或者 Contoller -> Host 的 L2CAP 的续包(中间的)
设置为 10'b 的时候,代表 Contoller -> Host 的 L2CAP 的首包
其实可以看到,这个标志位就是控制 L2CAP 的包的。
BC Flag:全称叫 Broadcast Flag,他的描述分为:
LE 没有 sniff mode,所以都是点对点的数据传输,设置成为 00'b 就好。
Data_Total_Length:代表后面跟的 Data 长度,长度单位是字节,这个由两字节表示,所以最大 255.
Data:数据
由于 HCI 的 Command 和 Event,Core Spec 每个都有细致的详解,所以,针对 LE 的 Bluetooth,主要关注的集中在:
HCI Command:
HCI Event:
在 7.7 Events 中的,7.7.65 LE Meta Event 部分