蓝牙HCI四种数据包格式详解:HCI Command Packet、HCI ACL Data Packet、HCI Synchronous Data Packet、HCI Event Packet

〇、序言

HCI (Host Controller Interface) 数据包是蓝牙通信中主机与控制器之间交换信息的基本单元。HCI 定义了主机与蓝牙控制器之间如何交换命令、数据和事件。它提供了一种标准的接口和协议,使得蓝牙设备(如手机、计算机、耳机、音响等)能够通过主机控制器接口进行通信。

蓝牙 HCI 数据包通常分为以下几类:

#define HCI_COMMAND_DATA_PACKET   0x01
#define HCI_ACL_DATA_PACKET       0x02
#define HCI_SCO_DATA_PACKET       0x03
#define HCI_EVENT_PACKET          0x04

一、HCI Command Packet(HCI命令包 0x01)

这个数据包的作用是通过命令向Controller传输操作指令,Controller根据命令执行特定操作,并返回相应的事件信息。如果是厂商特定的调试命令,Controller会进行特殊处理。

1、数据包格式(参照Core spec)

2、具体数据位详解

① Op_Code: Size: 2 Octets

Op_Code命令操作码(Operation Code),它用于标识命令类型。这个字段占用 2 字节(16 位),由两个部分组成:

  • OGF(Opcode Group Field):6 位,用于指定命令分组的类型。
  • OCF(Opcode Command Field):10 位,表示特定命令在该命令分组下的编号。

② Parameter_Total_Length: Size: 1 Octet

Parameter_Total_Length参数总长度,它指定了命令中所有参数的总长度。这个字段占用 1 字节(8 位),其值表示命令后续参数的总字节数。

注意:

  • 这个字段表示的是 所有参数的字节长度总和,而不是参数的个数。
  • 例如,如果命令有两个参数,第一个参数占用 2 字节,第二个参数占用 3 字节,那么 Parameter_Total_Length 的值为 5。

③ Parameter 0 - N: Size: Parameter Total Length

这个部分是 命令参数,其大小由 Parameter_Total_Length 字段指定。每个命令都有一个特定的参数集合,参数的个数和每个参数的大小根据命令类型而不同。

  • Parameter 0 - N 代表命令的所有参数,具体的参数大小和格式会根据命令的类型进行定义。
  • 每个命令的参数数量、大小以及每个参数的含义在蓝牙协议规范中是事先定义的。④以实际数据包举例

④ 结合实际数据包分析

我通过抓取了btsnoop(btsnoop用于记录Host与Controller的通信)来详细分析一包HCI Command Packets。

高亮部分的左边第一个字节0x01代表这一包数据类型为Command Packet。

高亮部分的从左边数第二三字节0x0c1a(Frontline这里显示低位在前高位在后,二进制为0000 1100 0001 1010),其中从高位开始算15~10Bit为OGF(Opcode Group Field),其值为0x03,通过查阅core spec得知是归属于CONTROLLER &BASEBAND COMMANDS组,这类命令是用来访问和控制蓝牙硬件的各种功能

接着从高位开始的9~0Bit为OCF(Opcode Command Field),其值为0x001a,同样通过查阅core spec得知是Write Scan Enable Command,该命令的作用是 写入扫描使能参数,即控制设备是否启用扫描功能。

高亮部分的从左边数第四字节0x01代表Parameter的字节总长度。

高亮部分的从左边数第五字节0x02代表实际的Parameter参数值,通过上图可知0x02代表Inquiry Scan disabled,Page Scan enabled。

综上所述这条命令HCI_Write_Scan_Enable 用于设置蓝牙设备的扫描状态,禁用询问扫描(Inquiry Scan),并启用配对扫描(Page Scan)。

二、 HCI ACL Data Packet(HCI ACL数据包 0x02)

这个数据包的主要作用是进行主机与控制器之间的数据交换,具有不同的刷新策略来控制数据包的传输和处理。

1、数据包格式(参照Core spec)

2、具体数据包详解 

① Handle: 12 Bits

Handle 是一个 12 位的字段,用于标识连接句柄。在不同的情景下,这个字段有不同的用途。

  • Connection_Handle 用于在主控制器(Primary Controller)上发送数据包。
  • Logical_Link_Handle 用于在AMP 控制器上发送数据包。

在接收端(从 AMP 控制器到主机),这个字段的最低 8 位是Physical_Link_Handle,而最高的 4 位被保留供未来使用。

② Packet_Boundary_Flag: 2 Bits

这个标志字段用于标识数据包边界的类型,特别是在分片和数据包传输中非常重要。它包含以下几种值:

  • 00b:表示一个非自动刷新的数据包的开始,即更高层消息的第一部分。例如,L2CAP PDU 的开始。
  • 01b:表示继续分片,即高层消息的后续分片。
  • 10b:表示自动刷新的数据包的开始,即 L2CAP PDU 的开始部分。
  • 11b:表示一个完整的 L2CAP PDU,并且是可自动刷新的。

根据不同的传输方向(从Host到Controller,或从Controller到Host),这些数据包的传输规则和允许的传输场景是不同的。例如,非自动刷新的数据包只能在Host到Controller的传输中使用,而自动刷新的数据包只允许从Controller到Host传输。

③ Broadcast_Flag: 2 Bits

这个标志字段用于指示是否为广播包,它的作用如下:

  • 从Host到Controller

    • 00b:没有广播,仅限点对点通信(这种情况适用于 AMP)。
    • 01b活动从设备广播,即数据包会被发送给所有活动的从设备,并可能被处于 sniff 模式的从设备接收。
    • 10b 和 11b:保留给未来使用。
  • 从Controller到Host

    • 同样的值含义,表明广播包的类型,是否会广播到所有活动的从设备等。

注意:

  • 处于sniff模式的从设备可能会接收到广播包,具体取决于它是否在相应的 sniff 时隙内接收到数据包。

④ Data_Total_Length: 2 Octets

Data_Total_Length 字段用于指示数据部分的总长度(以字节为单位),它占用 2 字节。其作用是告诉接收方数据包的长度,便于解析和处理。

⑤ Data: x Octets

LE-U 逻辑连接:是为满足低功耗且单向数据传输的需求而设计的,其数据部分的长度最大为27字节,不包括数据包的头部(即 HCI ACL Data Packet Header)。

其他连接类型(如 AMP 逻辑连接):AMP(Alternate MAC/PHY)逻辑连接上的数据包可以更大一些,因为它不受LE-U 逻辑连接数据包长度限制的影响。所有通过 AMP 逻辑连接传输的数据包都受到自动刷新定时器的影响,但最大有效载荷长度会根据设备和使用的协议而有所不同。

⑥ 结合实际数据包分析

我通过抓取了btsnoop(btsnoop用于记录Host与Controller的通信)来详细分析一包HCI ACL Data Packets。

高亮部分的左边第一个字节0x02代表这一包数据类型为ACL Data Packet。

高亮部分的左边第二三字节0x0001(Frontline这里显示低位在前 高位在后,二进制为0000 0000 0000 0001),其中从低位往高位开始算的0~11Bit为Handle,其值为0x001,代表一个有效的连接句柄。

接着从低位往高位开始算的12~13Bit为PB flag,其值为00b,这表示这是一个完整的数据包,没有分片

接着从低位往高位开始算的14~15Bit为BC flag,其值为00b,这表示这是一个点对点通信数据包,而不是广播包。

高亮部分的左边第四个字节0x000a(Frontline这里显示低位在前 高位在后),这代表后面data字段的数据长度为10个字节

高亮部分最后十个字节为有效data数据,此段data数据为L2CAP层数据,具体解析不在本文档中分析。

三、HCI Synchronous Data Packet(HCI同步数据包 0x03)

这个数据包主要用于Host和Controller之间传输同步数据。SCO (Synchronous Connection-Oriented) 和 eSCO (Extended Synchronous Connection-Oriented) 是蓝牙中的两种同步连接模式,专门用于音频和实时数据传输,它们通常用于语音传输、音频流以及其他低延迟、稳定的数据流

(目前笔者还未接触到该数据包,如若在后续的工作内容中接触到了此类数据包,届时会来更新这一部分)

、HCI Event Packet(HCI事件包 0x04)

HCI事件数据包是由Controller用来在事件发生时通知Host的。Host必须能够接收包含最多255个字节(octet,即字节)数据的HCI事件数据包,这里的数据量不包括HCI事件数据包的头部。

1、数据包格式(参照Core spec)

2、具体数据位详解

① Event_Code: 1 Octet

Event_Code 是一个 1 字节(8位)的字段,用于唯一标识不同类型的事件。Core spec有对于不同事件有。

  • 用途:标识事件类型。
  • 取值范围:0x00 到 0xFF(十六进制),其中 0xFF 保留用于供应商特定的调试事件。

② Parameter_Total_Length: 1 Octet

Parameter_Total_Length 字段表示该数据包中所有事件参数的总长度,以字节为单位。这个信息对于正确解析数据包至关重要。

  • 用途:指示数据包中参数的总大小。
  • 大小:1 字节(8位)。

③ Event_Parameter 0 - N: Variable Length

Event_Parameter 字段包含与特定事件相关的参数。每个事件都有其独特的参数集和参数大小,这些参数在事件定义中指定。

  • 用途:包含与事件相关的数据。
  • 大小:根据 Parameter_Total_Length 字段的值而变化。
  • 数量:0 到 N 个,具体取决于事件类型。

④ 结合实际数据包分析

我通过抓取了btsnoop(btsnoop用于记录Host与Controller的通信)来详细分析一包HCI Envent Packet。

高亮部分的左边第一个字节0x04代表这一包数据类型为HCI Envent Packet。

高亮部分的左边第二个字节0x07,通过查阅Core spec得知这是Remote Name Request Complete事件,可以得知这是Controller通知Host远端友好名称请求完成。

高亮部分的左边第三个字节0xFF,这代表Event_Parameter后面字段的数据长度为255个字节。

高亮部分最后的255个字节,这代表Event_Parameter字段的具体内容。

此处可以简单分析一下Remote Name Request Complete事件的Event_Parameter:

  • Event_Parameter里的从左边开始算第一个字节0x00,代表了回复成功的状态
  • Event_Parameter里的从左边开始算第二到六个字节01 e8 fc ef 66 7c,代表了远端设备的MAC地址。(需要做一个大小端序的转换,实际MAC地址为7c:66:ef:fc:e8:01)
  • Event_Parameter里的剩下的字节代表远端设备的友好名称,其为ASCII值。(转换成字符为BRAVIA VU31)

综上所述这条事件Remote Name Request Complete,用于通知Host已完成远端设备友好名称请求,远端MAC地址为7c:66:ef:fc:e8:01,远端友好名称为BRAVIA VU31。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值