Ble Packet
工具:WireShark、PacketLogger、Ellisys
设备: Apple Watch 、 OPPLE Enco Free2、 vivo WATCH2、HUAWEI-Watch2、vivo TWS 2e等
在数据通过BLE传输时,数据是以包(packet)的方式收发的,多个包可以在一个连接间隔内发送出去,每个包大小并不一定一样,但包有最大限制,因此又需要引入一个PDU(protocoldata unit)的概念。
最大PDU表示在一个连接间隔中能发送的最大数据能力。不同BLE协议栈中或者不同的芯片支持的值是不同的,例如下图芯片 的是BES2500YP俯视图。https://bbs.16rd.com/thread-579490-1-1.html
[图片上传失败...(image-cd9cf7-1657542297519)]
而BES恒玄型号BES2500BP,在小米watch Color2、华为Watch GT3/Runner、vivo WATCH2 上已使用,集显示、存储、音频、连接为一体;支持BT5.2双模蓝牙,可支持BLE数据传输、蓝牙通话和音乐播放功能;
BLE 包结构如下:
Preamble | Access Address | PDU | CRC |
---|---|---|---|
(1 Byte) | (4 Bytes) | x | (3 Bytes) |
preamble(前导帧)为1个字节,根据Access Address第一个Bit,有两种取值情况:0x55或者0xAA(纯PHY层行为),如下所示:
Access Address用来标示接收者ID或者空中包身份,如前所示,BLE只有一种packet格式,根据Access Address的不同,又区分两种Packet类型:广播包和数据包:
广播包Access Address 固定为0x8E89BED6,广播包只能在广播信道(channel)上传输,即只能在37/38/39信道上传输(注:从蓝牙5.0开始广播包可以在其它信道上传输)。广播包发送给附近所有的observer(扫描者),属于一对多关系。
数据包Access Address 为一个32bit的随机值,由Initiator生成。数据包,其实是数据信道上的空中包的简称,数据包只在数据信道上传输,即除37/38/39之外的其余37信道(BLE总共占用40个信道)。每建立一次连接,重新生成一次Access address。数据包是给连接通信使用的,即用于master和slave之间通信。
CRC为24bit. 顾名思义,这里是数据完整性校验。
蓝牙协议栈
手机发送一段write without repsonse的packet数据流向:
ATT(HOST) -> L2CAP -> HCI(ACL/Conmand/Event/SCO) -> LL-> PHY
HCI(HOST CONTROLLER INTERFACE):主机控制器接口层
LL(link layer):BLE的链路层
PHY:BLE的物理层
L2CAP
逻辑链路控制与适配协议通常简称为L2CAP(Logical Link Control and Adaptation Protocol),它向上连接应用层,向下连接控制器层,发挥主机与控制器之间的适配器的作用,使上层应用操作无需关心控制器的数据处理细节。
经典蓝牙的L2CAP层比较复杂,它实现了如下多个功能操作,使得主机能够支持LE和BR/EDR不同的控制器,实现音频数据流传输等高级功能。
- 协议/信道多路复用
- 片段和重组(Segmentation and reassembly)
- 分段和重组 (Fragmentation and Recombination)
- 每个 L2CAP 通道的流量控制(Flow control per L2CAP channel)
- 错误控制和重传(Error control and retransmissions)
- 支持流媒体(Support for Streaming)
- 服务质量
BLE的L2CAP层是经典蓝牙L2CAP层的简化版本,它在基础模式下,不执行分段和重组,不涉及流程控制和重传机制,仅使用固定信道进行通信,在LE令牌流程控制模式下,实现了流程控制,执行数据分段和重组,使用动态信道进行通信。
L2CAP层包括两个功能模块:资源管理器和信道管理器。
L2CAP层向下连接控制器的HCI接口,向上对应用层暴露数据收发接口。
应用层发送给L2CAP层的数据称为SDU(Service Data Unit),SDU可能是属性协议层的读写数据,也可能是链接配置命令,也可能是配对绑定数据。
SDU在资源管理器中添加L2CAP协议头信息,封装成L2CAP数据包,简称PDU(Protocol Data Unit)。PDU的Payload字段就包含了SDU或SDU的一部分。
通常HCI接口无法发送较长数据包,需要对PDU进行分解(Fragmentation),变成数据碎片(Fragment)再依次发送到控制器。PDU总是包含完整的L2CAP协议头,而数据碎片则不是完整的L2CAP数据包。
PDU(protocol data unit,协议数据单元)结构如下:
LL Header | Payload(MTU) | MIC |
---|---|---|
(2 Bytes) | (7+x) | (4 Bytes) |
对于profile层的characteristic,其最大的长度是x字节。为什么是x呢? 看下面
Payload:BLE底层的协议包格式,一般我们认为这里的Payload属于有效的数据,其类似PDU,也有自己的协议包格式。如下:
蓝牙协议层的MTU = L2CAP(4个Bytes)+ATT头(3个Bytes)+ ATT Data(业务数据), ATT_MTU = ATT头+ATT Data, 这里和硬件侧的沟通需要注意的点, 硬件开发同事说的MUT 往往是蓝牙协议层的, 而我们业务开发,通过API获取到的MTU值,是仅ATT Data,所以沟通上要特别留意。
所以一个包,在业务侧实际可被使用的最大MTU是要减去协议开销-7个byte。
L2CAP(Logical Link Control and Adaptation Protocol,即逻辑链路控制和适配协议),在BLE中 GAP,GATT,SMP 都使用L2CAP 通道将命令及数据打包送到链路层(Link Layer)。
L2CAP层有多种工作模式:
工作模式 | 适用范围 |
---|---|
基础L2CAP模式 | Classic, LE |
流程控制模式 | Classic |
重传模式 | Classic |
增强型重传模式 | Classic |
数据流模式 | Classic |
LE令牌流程控制模式 | LE |
基础模式为默认工作模式,L2CAP层不执行流程控制,对数据不执行分段和重组操作,其他五种模式均使用了流程控制或重传机制,需要执行分段和重组操作。
在L2CAP层配置阶段,会设置参数是否使用流程控制和重传机制,如果不使用则使用基础模式,否则按参数配置情况使用其他模式。
B-Frame:B帧(Basic information frame)是用于 L2CAP 数据包的基本 L2CAP 模式中的 PDU。 它包含一个完整的 SDU 作为其有效载荷,由基本 L2CAP 标头封装。格式如下:
Length: 2个字节 ,Information payload的长度
Channel ID( CID): 2字节长度,对端的目的信道,BLE使用固定的通道编号,可见右表:
Information payload: 有效的数据,小端序,范围(0-65535 字节),但实际上受限于ATT_MTU, 如蓝牙协议5.0中备注了,ATT_MTU最大为255个字节。
信道标识符 | 描述 | 是否支持BLE |
---|---|---|
0x0000 | Null identityer(保留:不能使用) | |
0x0001 | L2CAP Signaling Channel(经典蓝牙信令信道) | |
0x0002 | Connectionless Channel(无连接信道) | |
0x0003 | AMP Manager Protocol(AMP管理协议) | |
0x0004 | Attitude Protocol(ATT协议) | BLE,固定信道 |
0x0005 | LE L2CAP Signaling Channel (BLE信令信道) | BLE,固定信道 |
0x0006 | Security Manager Protocol (安全管理协议) | BLE,固定信道 |
0x0007 ~ 0x001F | reserve (保留) | |
0x0020 ~ 0x003E | reserve (保留) | BLE,固定信道 |
0x003F | AMP Manager Test Protocol (AMP测试协议) | |
0x0040 ~ 0x007F | Connection-oriented Channel (面向连接信道) | BLE,动态信道 |
0x007F ~ 0xFFFF | Connection-oriented Channel (面向连接信道) |
常规信道中,低功耗蓝牙一共使用了三条信道,0x0004、0x0005、0x0006。
分段与重组
PDU 的 分段与重组
分段是将 PDU 拆成更小的部分,以便从 L2CAP 传递到较低层。重组是从较低层传递的片段重新组装 PDU 的过程。分段和重组可以应用于任何 L2CAP PDU。
分段
L2CAP实现可以对任何L2CAP PDU进行分片,以便将其发送到较低层。如果L2CAP在没有HCI的情况下直接在Controller上运行,那么一个执行方发是将PDU分割成多个Controller数据包,以便通过空气进行传输。如果L2CAP运行在HCI之上,那么一个执行方法会向控制器发送HCI传输大小的片段。与一个L2CAP PDU相关联的所有L2CAP分片,在处理任何其他进行相同逻辑传输的L2CAP PDU之前,都应由控制器处理以进行传输。
BR/EDR链路控制器能够通过使用“开始”和“延续”指示在片段被转换成基带数据包时对PDU施加不同的片段。因此,L2CAP和BR/EDR Link Controller都使用相同的机制来控制分片的大小。
重组
控制器将尝试按顺序传递数据包,并且不会出错。片段的重组可能发生在控制器中,但最终由 L2CAP 负责重组 PDU 和 SDU 并检查 SDU 的长度字段。当控制器接收到数据包片段时,它会在每个片段到达时向 L2CAP 层发送信号,或者在将数据包传递到 L2CAP 层之前累积多个片段(在接收缓冲区填满或计时器到期之前)。 L2CAP 应使用 L2CAP PDU 报头中的长度字段,作为一致性检查,并应丢弃任何未能匹配长度字段的 L2CAP PDU。
例子
下面看来之网上的两个例子。
- 如果BLE4.0,ATT_MTU最后client和server协商出来结果是23,那么发送20字节(ATT_payload)不需要拆包:
1字节前导码 + 4字节访问地址 + 2字节链路帧头(其中LLID = 10b,表示一个没有fragmentation的完整包) + 4字节L2CAP帧头 + 3字节ATT帧头 + 20字节的ATT_payload + 3字节CRC
- 如果BLE4.0,ATT_MTU最后client和server协商出来假设是63,那么你发送60字节数据(ATT_payload),L2CAP会将它拆成3包(拆包的原因是因为BLE4.0链路层PDU的限制),最终从空中发出去的包长这样:
1)1字节前导码 + 4字节访问地址 + 2字节链路帧头(其中LLID = 10b,表示这是第一个连续包) + 4字节L2CAP帧头 + 3字节ATT帧头 + 20字节的ATT_payload + 3字节CRC
2)1字节前导码 + 4字节访问地址 + 2字节链路帧头(其中LLID = 01b,表示这是下一包连续包) + 27字节的ATT_payload + 3字节CRC
3)1字节前导码 + 4字节访问地址 + 2字节链路帧头(其中LLID = 01b,表示这是最后一个连续包) + 13字节的ATT_payload + 3字节CRC
上面10b、01b中的“b”表示二进制格式,中间的包和最后的包的LLID都是01b,对方怎么知道什么时候收完包呢?靠的是第一包的4字节L2CAP帧头,这里面会说明后面一共有多少数据待接收。
ATT
ATT 协议就在PDU的 Information payload里.
OptionCode | Handle | ATT Data |
---|---|---|
(1 Byte) | (2 Bytes) |
ATT Commond格式如下:
属性 | Size (octets) | 描述 |
---|---|---|
Attribute Opcode | 1 | 0x52 = ATT_WRITE_CMD PDU |
Attribute Handle | 2 | The handle of the attribute to be set |
Attribute Value | 0 to (ATT_MTU-3) | The value of be written to the attri- bute |
Attribute handle,Attribute句柄,16-bit长度。Client要访问Server的Attribute,都是通过这个句柄来访问的,也就是说ATT PDU一般都包含handle的值。用户在软件代码添加characteristic的时候,系统会自动按顺序地为相关attribute生成句柄。
在ATT中,比较重要的一个环节 MTU Exchange。
MTU 交换 是为了在主从双方设置一个PDU中最大能够交换的数据量, 通过MTU的交换和双方确认(注意这个MTU是不可以协商的,只是通知对方,双方在知道对方的极限后会选择一个较小的值作为以后的MTU,比如说,主设备发出一个150个字节的MTU请求,但是从设备回应MTU是23字节,那么今后双方要以较小的值23字节作为以后的MTU),主从双方约定每次在做数据传输时不超过这个最大数据单元。 如下图的交换:
下面看一段vivo TWS 2e 耳机在连接过程中 MTU交换过程:
连接之后,host可以向controller发起mtu exchange procedure,即host告诉controller自己的最大接收能力ATT_MTU(client’s local att protocol channel MTU),controller也会告诉client自己的最大接收能力ATT_MTU(server’s local att protocol channel MTU),最后取两者的最小值为这条通道的ATT_MTU(actual att protocol channel MTU)。
PHY LAYER
作为软件开发者,对这物理层,基本都不会关心,或者说也不用太小,只需了解理论知识。
蓝牙工作频道:免许可的2.4GHz
范围: 2400MHz - 2483.5MHz,频段宽度为83.5MHz, BLE将这83.5MHz的宽度分成了0到39共40个通道,每一个通道宽度为2MHz。f=2402+k*2 MHz, k=0, … ,39
调制方式:BLE规范目前定义了两种调制速率1Mbit/s和2Mbps,BLE 5.0理论上最高可以支持到2Mbps
[图片上传失败...(image-2c9ced-1657542297519)]
上图为1M PHY和2M PHY在2404频点发送数据0b1010的对比图。
BLE的调制方式为GFSK,BLE定义在信道中传输的是二进制符号(波形),即1个符号(波形)表示1个比特,其中相对频点正偏代表数字基带信号1,相对频点负偏的代表数字基带信号0。
之所以速率提高了,本质应该是2M PHY的码长变小了,即发送一个符号(波形)所需的时间变小了。
可以看出:2M PHY的比特率是1M PHY的两倍,即2M PHY传输完0b1010的时间是1M PHY的一半
其中广播通道为37/38/39,对应的中心频率分别为2402MHz、2426MHz、2480MHz。BLE在广播的时候会轮流使用这3个通道进行广播。
蓝牙协议层,影响ble速度的相关点,上面都有涉及到了。
BLE 传输原理
从上图看出BLE链路层传输速率的快慢主要由以下因素决定:
- Connection Interval 的大小;
- 每个 Connection Event 可以发送多少个 Link Layer Packet;
- 每个 Link Layer Packet 可以负载多少用户数据;
- 相邻 Link Layer Packet之间的时间间隔T_IFS(帧间空间 150μs)。
一旦BLE设备建立连接后,两个设备会以相等的时间间隔交换数据,这个间隔成为连接间隔(Connection Interval),间隔范围是7.5ms-4s。
其中iPhone最小间隔是11.25ms(带HID),Android最小间隔是7.5ms,Android一个间隔最多传6包,iOS最多传4包,这个就是我们再空中抓包时看到的现象。
下图是iPhone手机上,不同应用上,Ellisys抓的两端空中包数据截图:
很明显,第二段的数据包非常漂亮。
总结:
不考虑以下的一些客观因素:
- 射频环境, 如果主从设备之间的环境不好,蓝牙交互肯定会受影响,比如丢包了,Link layer层会尝试丢包重发,这样就会出现一个LL Packet发送多遍。
- CPU任务时的响应速度。
- 多链路复用场景,多个链路分时复用radio,吞吐量会被降低,治理只考虑单链路情况。
看下图:
- 用write without response而不要用write characteristic value
- ATT_MTU尽可能大(这样可以减少L2CAP的帧头数量,通过Fragmentation来尽可能占据带宽,提高吞吐量)
- 减少连接间隔(connection interval),增大连接事件(connection event)
- 启用数据包扩展特性(link layer packet)
- 启用2M PHY特性(BLE5.0可选特性)
附录:
名词 | 描述 |
---|---|
Basic L2CAP header | Minimum L2CAP protocol information that is present in the beginning of each PDU: a length field and a field containing the Channel Identi- fier (CID). |
CID | Channel Identifiers, L2CAP通道ID |
SDU | 来自上层的数据,不包含任何L2CAP层协议字段 |
Segment or SDU segment | SDU 的一部分,由分割过程产生。 一个 SDU 可以分成一个或多个段 |
PDU or L2CAP PDU | (协议数据单元)Protocol Data Unit,协议数据单元:包含 L2CAP 协议信息字段、控制信息和/或上层信息数据的数据包。PDU 总是由基本 L2CAP 报头开始。 PDU 的类型有:B 帧、I 帧、S 帧、C 帧、G 帧和 LE 帧。 |
B-frame | B帧(Basic information frame)是用于 L2CAP 数据包的基本 L2CAP 模式中的 PDU。 它包含一个完整的 SDU 作为其有效载荷,由基本 L2CAP 标头封装。 |
I-frame | I帧(Information frame),I 帧是在增强重传模式、流模式、重传模式和流控制模式中使用的 PDU。 它包含一个 SDU 段和附加协议信息,由基本 L2CAP 头封装 |
S-frame | S帧(Supervisory frame), S 帧是在增强重传模式、重传模式和流控制模式中使用的 PDU。 它仅包含协议信息,由基本 L2CAP 头封装,不包含 SDU 数据。 |
C-frame | C帧(Control frame), C 帧是包含在两端 L2CAP 实体之间交换L2CAP 信令消息的 PDU。 C 帧专门用于 L2CAP 信令信道。 |
G-frame | G帧(Group frame), G 帧是专用于无连接 L2CAP 通道的 PDU。 它由基本 L2CAP 报头封装,包含 PSM,后跟完整的 SDU。 G 帧可用于通过 Active Broadcast 向活动从设备广播数据或将单播数据发送到单个远程设备 |
K-frame | K 帧是在基于 LE 的流量控制模式中使用的 PDU。 它包含一个 SDU 段和附加协议信息,由基本 L2CAP 报头封装。 |
Fragment | 片段是PDU 的一部分,由分片操作产生。 片段仅用于与底层之间的数据传递。 它们不用于点对点传输。 片段可以是关于 L2CAP PDU 的开始或继续片段。 一个片段不包含PDU以外的任何协议信息; 起始片段和延续片段的区别是由底层协议规定来传输的。 |
Fragmentation | 将L2CAP pdu拆分成更小的部分的过程,称为fragments,适合于传送到较低的传输层。尽管在L2CAP层中进行了描述,但碎片实际上可能发生在HCI主机驱动程序中,和/或控制器中,以适应L2CAP PDU传输到HCI数据包或控制器数据包的大小。pdu分片可以应用于所有L2CAP模式。 |
Recombination | 与fragmentation相对应的反向过程,从碎片中重新建立一个L2CAP PDU。在接收路径中,全部或部分重组操作可能发生在控制器和/或主机上,重组的位置不一定对应于发送端发生分片的位置。 |
MTU | 最大传输单元(Maximum Transmission Unit), 上层能够接受的有效载荷数据的最大大小(以字节单位),即 MTU 对应于最大 SDU 大小。 |
MPS | L2CAP可接受最大的payload大小(Maximum PDU payload Size),对应于MTU,在没有分段的情况下,或在基本 L2CAP 模式下,最大传输单元与最大 PDU 有效载荷大小相同,两个配置参数应设置为相同的值。 |
MTU(sig) | L2CAP信令MTU大小 |
参考:
http://jdhblog.com/2020/01/02/%E6%B5%85%E8%B0%88BLE%E5%90%9E%E5%90%90%E9%87%8F/#33-att_mtu%E7%9A%84%E5%AE%9A%E4%B9%89