蓝牙技术栈笔记(2)
蓝牙笔记(2)
本笔记为作者再学习蓝牙Host协议栈的一些心得体会,如有不对的地方,请包含与谅解!
————by wsoz
本章开始我们正式进入到传统蓝牙host的学习,先学习一下HCI控制器接口层
主机控制器接口层(HCI)
主机控制器接口 (Host Controller Interface, HCI) 是一套标准的协议和接口,它定义了蓝牙协议栈的主机 (Host) 部分和控制器 (Controller) 部分之间如何通信。
首先HCI协议已经被蓝牙SIG组织规定好了,所以对于主机Host以及控制器Controlller都必须遵循这个协议,这样才可以实现不同厂商之间的通信,这也是为什么主机层以及控制器层为啥都有主机控制接口层的原因。
首先先介绍一下core文档的内容,以便于我们在解决问题时可以准确定位
Introduction
主要是HCI 的总体介绍Over of Host Controller transport layer
主要介绍 Transport 层Over of Host commands and events
主要是汇总了HCI command 和 event的内容HCI flow control
主要介绍的是HCI的流控HCI data formats
主要介绍的是几种通信的格式HCI configuration parameters
主要介绍HCI data的参数HCI commands and events
主要介绍通信的命令以及事件,重点Appendix A Deprecated commands,events,and configuration parameters
主要介绍以及被抛弃的events和command参数
下图为core文档中的协议架构图
下图为core文档中的一个蓝牙系统的数据交互图
在整个蓝牙系统中我们可以直接简化为层与层之间的通信,如图所示及HOST层与HOST层之间进行通信,Controlller层与Controlller层之间相互进行通信
HCI流控
流控制用于在主机和主机控制器之间,避免传送到主机控制器的未应答远程设备的 ACL 数据溢出主机控制器数据缓冲区(控制器内部缓冲区小无法容纳的情况下会丢弃新包)。主机(蓝牙协议栈)负责管理主机控制器(蓝牙芯片)的数据缓冲区。流控又分为了两种:1.主机到控制器的流控 2.控制器到主机的流控
主机到控制器的流控
这个流控的方法又分为两种:'packet-based' flow control
和'data-block-based' flow control
对于这两种流控模式的切换可以借助HCI_Write_Flow_Control_Mode
命令来切换,对于BR/EDR蓝牙来说,,默认使用的是'packet-based' flow control
的流控方式,对于AMP来说,默认使用的是'data-block-based' flow control
的流控方式。
HCI_Write_Flow_Control_Mode
命令
Command | OCF | Command Parameters | Return Parameters |
---|---|---|---|
HCI_Write_Flow_Control_Mode | 0x0067 | Flow_Control_Mode | Status |
Flow_Control_Mode
Value | Parameter Description |
---|---|
0x00 | Packet based data flow control mode (default for a BR/EDR or LE Controller) |
0x01 | Data block based data flow control mode (default for an AMP Controller) |
All other values | Reserved for future use |
Status
Value | Parameter Description |
---|---|
0x00 | Packet based data flow control mode (default for a BR/EDR or LE Controller) |
0x01 | Data block based data flow control mode (default for an AMP Controller) |
All other values | Reserved for future use |
Return Parameters
是控制器(Controller)处理完命令后,返回给主机(Host)的内容。主机在发送命令时,绝对不会包含 Return Parameters
。
下面主要讲解一下'packet-based' flow control
流控模式的原理
- 初始化时,主机先向控制器发送
HCI_Read_Buffer_Size
查询最大能接收的ACL 和 SCO 数据分组包数 - 控制器接收到查询后返回
HCI_ACL_Data_Packet_Length
以及HCI_SCO_Data_Packet_Length
(每个ACL和 SCO 数据包的最大长度字节,不包括包头)以及**Total_Num_ACL_Data_Packets
以及Total_Num_SCO_Data_Packets
**(控制器总共能缓存多少个ACL数据包,重要) - 在至少有一个连接或处于本地回送的情况下,主机控制器利用
Number Of Completed Packets
事件控制从主机发来的数据流。 - 事件分组包括一个连接句柄列表, 以及自从前一个事件返回后已经完成的 HCI 数据分组的相应数目(如果对于一个特定的连接句柄,没有事件返回发生,就从连接建立的时间算起 )。发送完成是指数据分组的传输、清除和回送至主机。。当主机控制器在其缓存中存放有 HCI 数据分组时,它必须向主机周期性持续发送
Number Of Completed Packets
事件, 直到最终所有 ACL 数据分组都已发送完毕或溢出。 - 当主机收到
Number Of Completed Packets
事件时,主机的协议栈会增加其内部维护的可用缓冲区计数器(例如Host_Available_Packets
)。随后,主机检查该计数器。如果计数器的值大于0,主机就可以从其发送队列中取出相应数量的数据包,发送给控制器。每发送一个数据包,主机便将此计数器减一。这个过程的另一端是:控制器通过射频将数据发送给对端设备后,其内部的物理缓冲区被释放。控制器会记录这些被释放的缓冲区数量,并在合适的时机(例如累积了一定数量或经过了一段时间后),通过Number Of Completed Packets
事件将这些“已完成”的数量报告给主机。
控制器到主机的流控
这个控制器到主机的流控不是必须的,因为此时蓝牙空中传输的数据相较于主机CPU处理的速率更慢所以在大多数情况下是没有必要开启控制器到主机的流控的。只有在当我们的主机资源受限以及主机任务量大负载高的情况下需要开启此流控。
在初始化时主机向控制器发送HCI_Set_Host_Controller_To_Host_Flow_Control command
决定是不是需要开启流控,默认acl和sco流控都是关闭的。
HCI_Set_Host_Controller_To_Host_Flow_Control command
命令
Command | OCF | Command Parameters | Return Parameters |
---|---|---|---|
HCI_Set_Controller_To_Host_Flow_Control | 0x0031 | Flow_Control_Enable | Status |
Flow_Control_Enable
Value | Parameter Description |
---|---|
0x00 | Flow control off in direction from Controller to Host. Default. |
0x01 | Flow control on for HCI ACL Data packets and off for HCI Synchronous Data packets in direction from Controller to Host. |
0x02 | Flow control off for HCI ACL Data packets and on for HCI Synchronous Data packets in direction from Controller to Host. |
0x03 | Flow control on both for HCI ACL Data packets and HCI Synchronous Data packets in direction from Controller to Host. |
All other values | Reserved for future use |
Status
Value | Parameter Description |
---|---|
0x00 | HCI_Set_Controller_To_Host_Flow_Control command succeeded. |
0x01 to 0xFF | HCI_Set_Controller_To_Host_Flow_Control command failed. See [Vol 1] Part F, Controller Error Codes for a list of error codes and descriptions. |
值得注意的是我们主机发送对应的开启命令之后,当控制器响应了就会返回相应的完成事件,通过查询状态码看是不是成功开启。
整个控制器向主机流控的流程
-
初始化的时候协议栈给蓝牙芯片发送
Set Controller To Host Flow Control command
命令,决定来开启 acl 或者 sco 流控 -
初始化的时候通过
Host Buffer Size command
由蓝牙协议栈发送给芯片acl,sco packet num,以及 lengthHost Buffer Size command
命令Command OCF Command Parameters Return Parameters HCI_Host_Buffer_Size 0x0033 Host_ACL_Data_Packet_Length,
Host_Synchronous_Data_Packet_Length,
Host_Total_Num_ACL_Data_Packets,
Host_Total_Num_Synchronous_Data_PacketsStatus Host_ACL_Data_Packet_Length
Size: 2 octets (2字节)Value Parameter Description 0xXXXX 主机能够接收的每个 HCI ACL 数据包中数据部分的最大长度 (以字节为单位)。 Host_Synchronous_Data_Packet_Length
Size: 1 octet (1字节)Value Parameter Description 0xXX 主机能够接收的每个 HCI 同步数据包中数据部分的最大长度 (以字节为单位)。 Host_Total_Num_ACL_Data_Packets
Size: 2 octets (2字节)Value Parameter Description 0xXXXX 可存储在主机数据缓冲区中的 HCI ACL 数据包总数。 Host_Total_Num_Synchronous_Data_Packets
Size: 2 octets (2字节)Value Parameter Description 0xXXXX 可存储在主机数据缓冲区中的 HCI 同步数据包总数。 Status
Size: 1 octet (1字节)Value Parameter Description 0x00 HCI_Host_Buffer_Size
命令成功。0x01 to 0xFF HCI_Host_Buffer_Size
命令失败。请参阅 [Vol 1] Part F, Controller Error Codes (卷1, F部分, 控制器错误代码) 以获取错误代码和描述列表。 -
协议栈收到 acl 后发送给芯片
Host Number Of Completed Packets command
Host Number Of Completed Packets command
命令Command OCF Command Parameters Return Parameters HCI_Host_Number_Of_Completed_Packets
0x0035 Num_Handles
,Connection_Handle[i]
,Host_Num_Completed_Packets[i]
Num_Handles
Size: 1 octets (1字节)Value Parameter Description 0xXX The number of Connection_Handles and Host_Num_Completed_Packets parameters pairs contained in this command.
Range: 0 to 255
Connection_Handle[i]
Size: 大小:句柄数量 × 2字节,其中12位有效Value Parameter Description 0xXXXX Connection_Handle
Range: 0x0000 to 0x0EFF
Host_Num_Completed_Packets[i]
Size: 2 octets (2字节)Value Parameter Description 0xXXXX The number of HCI Data packets that have been completed for the associated Connection_Handle since the previous time the event was returned.
Range: 0x0000 to 0xFFFF -
控制器通过接收
Host Number Of Completed Packets command
来维护内部的一个计数器确定是不是该向主机发送数据
蓝牙HCI数据包格式
主机和控制器之间的数据包有command/event/acl/sco/iso,每一种类型的分组都有其对应的格式,下面我们将会来依次看一下各个数据包的格式。
需要注意的是如果没有特别说明的情况下,接收和发送的数据包均为小端字节序列(低位在前)
command数据包
HCI 命令包是从协议栈发送给芯片的命令。其命令格式如下图:
下面进行解释
-
命令格式由三个字段组成:opcode(操作码,唯一标识) parameter total length(所有参数总长度) parameter(参数字段)
-
opcode操作码(2个字节):
用来唯一标识不同的命令。又由OCF(操作码命令字段,低10位)和OGF(操作码组字段,高6位)组成-
OGF的组类型:
OGF 值 分组名称 说明 0x01 Link Control Commands 链路控制命令,如查询、连接、断开等。 0x02 Link Policy Commands 链路策略命令,如角色切换、保持模式等。 0x03 Controller & Baseband Commands 控制器和基带命令,如重置、读缓冲区大小等。 0x04 Informational Parameters 信息参数命令,读版本、支持的特性等。 0x05 Status Parameters 状态参数命令。 0x06 Testing Commands 测试命令。 0x08 LE Controller Commands 低功耗控制器命令,如设置广播参数、创建连接等。 0x3F Vendor Specific Commands 厂商特定命令(OCF范围:0x0000-0x00FF)。
-
-
parameter total length参数长度(1字节):
该参数标定了后续参数的长度
-
parameter参数字段(0-n个字节由命令类型决定):
不同的hci command对应的参数不一样
分析一下组装hci命令的源码:
struct bt_pbuf_t *hci_cmd_ass(struct bt_pbuf_t *p, uint16_t ocf, uint8_t ogf, uint8_t len)
{((uint8_t *)p->payload)[0] = (ocf & 0xff); /* OCF & OGF */((uint8_t *)p->payload)[1] = (ocf >> 8)|(ogf << 2);((uint8_t *)p->payload)[2] = len-HCI_CMD_HDR_LEN; /* Param len = plen - cmd hdr */if(hci_pcb->numcmd != 0){--hci_pcb->numcmd; /* Reduce number of cmd packets that the host controller can buffer */}return p;
}
下面为了深入理解我们利用btsnoop读取的原始数据来分析一下:
可以看到我们的原始数据为:0x01 0x01 0x04 0x05 0x33 0x8b 0x9e 0x0a 0x00
这是捕获的传输层的数据所以0x01
就是数据包类型即是CMD数据包,后面的就是HCI命令包的数据
我们可以看到我们这个cmd的功能是inquiry查询,所以0x01 0x04
提取我们的操作码为0x0401
,其中经过计算后OGF为0x01
,OCF为0x001
parameter length参数就0x05
就是后续参数长度为5个字节 可以看到后续确实为5个字节数据
event数据包
HCI event 是蓝牙芯片发送给协议栈的事件。其格式如下图:
下面进行解释:
-
事件由三个字段组成:Event Code(事件码,唯一标识) parameter totallength(所有参数长度) event parameter(事件参数)
-
Event Code事件码(1个字节)
唯一 event 编码,用来区分不同的事件
-
parameter total length参数长度(1个字节)
该参数标定了后续参数的字节长度
-
event parameter事件参数(0-n个字节由事件类型决定)
对于不同的事件而言参数的长度是不同的
下面我们依旧结合btsnoop数据来看:
可以看到我们协议栈接收到原始数据为:0x04 0x0f 0x04 0x00 0x01 0x01 0x04
这是捕获的传输层的数据所以0x04
就是数据包类型即是event数据包,后面的就是接收到的HCI事件的数据
其中0X0F
就是我们的事件码,0x04
就是我们的参数长度,后续的参数长度也确实是4个字节长度
acl数据包
HCI acl 用于从协议栈跟蓝牙芯片双向交互异步数据上层协议的数据。下图为具体的格式:
下面进行解释:
-
acl数据包由5个字段组成:Handle(连接句柄) PBFlag(用于上层数据【L2CAP】,是否是分隔数据) BCFlag(是否为广播)
data total length(后续data数据长度)
-
handle连接句柄(12位)
这个标志是当我们主机和控制器连接时,控制器为主机分配一个12位的连接句柄,该句柄的作用就是区分不同链路的蓝牙连接,方便蓝牙连接后跟 remote 交互 acl 数据用
-
PBFlag包边界标志(2位)
这个标志位用于指示当前 ACL 数据包在逻辑链路层 (L2CAP 层) 协议数据单元 (PDU) 中的位置。因为ACL数据包很大可能需要分组发送。
值 参数描述 0b00 L2CAP PDU 的起始片段 (Start of a L2CAP PDU)。这可以是一个完整的 PDU,也可以是一个被分段 PDU 的第一个片段。 0b01 L2CAP PDU 的延续片段 (Continuation of a L2CAP PDU)。 0b10 保留 0b11 保留 比如我们有一长包分为3个包依次传送那包的
PBFlag
依次为0b00 0b01 0b01
-
BCFlag广播标志(2位)
这个标志位用于指示当前 HCI ACL 数据包是发送给单个设备还是多个设备(广播)。
值 参数描述 0b00 点对点 (Point-to-point) 用于 ACL-U, AMP-U 或 LE-U 链路类型 0b01 BR/EDR 广播 (BR/EDR broadcast) 主要用于 ASB-U 链路类型 0b10 保留,供将来使用 (Reserved for future use) 0b11 保留,供将来使用 (Reserved for future use)值
其中广播方式只能在以下两种情况下使用:
- 从主机 (Host) 到控制器 (Controller),并且该主机是微网的主设备 (master)。这意味着主设备主机向其控制器发送一个广播数据包,由控制器广播出去。
- 从控制器 (Controller) 到主机 (Host),并且该主机是微网的**从设备 (slave)。**这意味着从设备的控制器接收到一个广播包后,将其上报给从设备主机。
-
data total length数据长度(2个字节)
该数据长度指的是该分组中后续的data字节长度
-
data数据字段(不同acl数据长度不同)
下面依旧通过btsnoop数据来分析一下:
可以看到我们协议栈接收到原始数据为:0x02 0x33 0x00 0x0c 0x00 0x08 0x00 0x01 0x00 0x06 0x08 0x04 0x00 0x42 0x00 0x41 0x00
这是传输层的数据其中0x02
表示了这是一组acl数据,从0x33 0x00
提取句柄为0x033
包边界符为0b00
表示这是首包 然后广播标识符为0b00
表示就是点对点通信
data length是0x0c
就是12个字节的后续data,然后可以看到后续确实有12个字节的数据。
sco数据包
HCI sco 用于从协议栈跟蓝牙芯片双向交互音频数据,主要用于传统蓝牙。下面为其的格式:
下面进行具体的解释:
-
sco数据包由4个字段组成:Handle(连接句柄) Packet_status_flag(包状态标志) RFU(保留) Data_Total_Length(数据长度) data(sco数据)
-
Handle连接句柄(12位)
在主机和控制器连接时,控制器分配的一个唯一标识符给sco数据包的用于蓝牙连接后跟 remote 交互 sco 数据用。
-
Packet_status_flag包状态标志(2位)
正常情况下这个包标状态通常都是
0b00
值 描述 含义 0b00 Valid data (有效数据) Host -> Controller: 表示这是一个新的、首次发送的 SCO/eSCO 数据包。
Controller -> Host: 表示控制器成功接收并提交了一个新的数据包。对于标准 SCO,这是唯一常见的值。0b01 First retransmission (首次重传) (仅限 eSCO)
Host -> Controller: 表示这是 Host 对一个特定数据包的第一次重传。
Controller -> Host: 表示控制器收到的数据包是远程设备对先前丢失或损坏的数据包的第一次重传。0b10 Subsequent retransmission (后续重传) (仅限 eSCO)
Host -> Controller: 表示这是 Host 对一个特定数据包的第二次或更多次的重传。
Controller -> Host: 表示控制器收到的数据包是远程设备对先前丢失或损坏的数据包的后续重传。0b11 Flushed/Discarded (已刷新/丢弃) (仅限 eSCO,且仅由 Controller -> Host 发送)
Controller -> Host: 表示控制器由于达到最大重传次数、超时或其他原因,已丢弃了某个数据包,无法成功传输,并通知 Host 该数据包已丢失。Host 不会发送此状态的数据包给 Controller。 -
Data_Total_Length数据长度(1字节)
就是这个参数表示了该组sco数据data的字节长度
-
data数据字段(不同sco数据长度不同)
iso数据包
此部分是从 core5.2 开始增加,主要是蓝牙协议栈跟蓝牙芯片交互同步数据,主要用来传输 BLE Audio 的数据。下图为其格式:
下面进行具体解释:
-
该iso数据包由7个字段组成:Handle(连接句柄) pb_flag(分包标志符) ts_flag(开启时间戳标志位) RFU(保留) iso_data_load_length(iso数据包长度)RFU(保留) iso_data_load(iso数据字段)
-
Handle连接句柄(12位)
在主机和控制器连接时,控制器分配的一个唯一标识符给iso数据包的用于蓝牙连接后跟 remote 交互 iso 数据用。
-
pb_flag分包标志符(2位)
值 | 参数描述 |
---|---|
0b00 | ISO_Data_Load 字段中包含的是一个被分段的 SDU (Service Data Unit) 的起始片段。 |
0b01 | ISO_Data_Load 字段中包含的是一个 SDU 的中间连续片段。 |
0b10 | ISO_Data_Load 字段中包含的是一个完整的 SDU(即 SDU 未被分段)。 |
0b11 | ISO_Data_Load 字段中包含的是一个被分段的 SDU 的最后一个片段。 |
-
ts_flag时间戳标志位(1位)
当开启Timestamp功能时,会在
ISO_Data_Load_Length
字段之后(即ISO_Data_Load
的起始处)包含一个 4 字节的Time_Stamp
字段。开启该功能时置1,关闭时置0
-
iso_data_load_length数据包长度(14位)
就是这个参数表示了该组iso数据data的字节长度
-
data数据字段(不同iso数据长度不同)
蓝牙命令部分
下面为列出的蓝牙 HCI 命令 (部分):
OGF (Opcode Group Field) | OCF (Opcode Command Field) | 命令 (Command) | 命令描述 (Command Description) |
---|---|---|---|
Link Control Commands (0x01) | 0x0001 | Inquiry command | 让BR/EDR芯片进行搜索模式,搜索周边的BR/EDR设备 |
0x0002 | Inquiry Cancel command | 如果BR/EDR芯片在搜索状态,那么停止BR/EDR芯片的搜索 | |
(未命名命令) | 让BR/EDR芯片进入周期性搜索状态,但是此命令不常用,并且有的芯片会返回错误,所以不在此处扩展讲解 | ||
0x0003 | Periodic Inquiry Mode command | 进入周期性搜索状态的BR/EDR蓝牙芯片退出周期性搜索 | |
0x0004 | Exit Periodic Inquiry Mode command | 根据参数跟特定的蓝牙地址创建连接 | |
0x0005 | Create Connection command | 根据参数跟特定的连接句柄断开连接,可以用来断开ACL,也可以用来断开SCO、eSCO等 | |
0x0006 | Disconnect command | "连接中的"取消指令,此功能感觉比较鸡肋,同样我也没用过 | |
0x0008 | Create Connection Cancel command | 接受连接请求 | |
0x0009 | Accept Connection Request command | 拒绝连接请求 | |
0x000A | Reject Connection Request command | 对方向请求linkkey的时候,而我们没有link key,我们回复link key | |
0x000B | Link Key Request Reply command | 用于请求linkkey时,而我们没有link key的情形下回复 | |
0x000C | Link Key Request Negative Reply command | 用于响应芯片发送的pincode申请,并把pincode用于连接 | |
0x000D | PIN Code Request Reply command | 不能用于pincode连接 | |
0x000E | PIN Code Request Negative Reply command | 改变正在连接的交互封装类型 | |
0x000F | Change Connection Packet Type command | 用于指令连接句柄的两个蓝牙地址进行身份认证 | |
0x0011 | Authentication Requested command | 建立或取消连接层次的加密 | |
0x0013 | Set Connection Encryption command | 用于指定链路句柄,生成一个新的link key | |
0x0015 | Change Connection Link Key command | 用于强制主设备设备使用的临时或永久link key | |
0x0017 | Master Link Key command | 获取远端设备名称 | |
0x0019 | Remote Name Request command | 获取远端设备名称 | |
0x001A | Remote Name Request Cancel command | 获取Remote端支持的feature | |
0x001B | Read Remote Supported Features command | 获取Remote端支持的扩展feature | |
0x001C | Read Remote Extended Features command | 获取Remote端版本信息,注意此部分是LMP或者LL的版本 | |
0x001D | Read Remote Version Information command | 获取时钟偏移 | |
0x001F | Read Clock Offset command | 获取LMP句柄 | |
0x0020 | Read LMP Handle command | 建立SCO | |
0x002B | Setup Synchronous Connection command | 接受对方SCO建立请求 | |
0x002C | Accept Synchronous Connection Request command | 拒绝对方SCO建立请求 | |
0x002D | Reject Synchronous Connection Request command | 当在SSP配对模式下,响应芯片IO capability的请求 | |
0x002E | IO Capability Request Reply command | 当在SSP配对模式下,响应芯片IO User Confirmation的请求 | |
0x002F | User Confirmation Request Reply command | 当在SSP配对模式下,拒绝芯片IO User Confirmation的请求 | |
0x0030 | User Confirmation Request Negative Reply command | 当在SSP配对模式下,拒绝芯片IO User Confirmation的请求 | |
0x0031 | IO Capability Request Negative Reply command | ||
Link Policy Commands (0x02) | 0x0001 | Hold Mode command | 用于改变链接的行为,并让它将指定的Connection_Handle关联的ACL基带连接置于Hold模式 |
0x0002 | Sniff Mode command | 进入Sniff模式 | |
0x0003 | Exit Sniff Mode command | 离开Sniff模式 | |
0x0004 | QoS Setup command | 用于为Connection_Handle指定服务质量参数 | |
0x0007 | Role Discovery command | 查询当前的连接芯片处于什么角色 | |
0x0008 | Switch Role command | 切换角色 | |
0x000B | Read Link Policy Settings command | 读取当前连接的策略 | |
0x000C | Write Link Policy Settings command | 改变当前连接的策略 | |
0x000D | Read Default Link Policy Settings command | 读取默认的连接策略 | |
0x000E | Write Default Link Policy Settings command | 用于指定通过Connection_Handle标识的ACL Connection_Handle传输的流量的流参数 | |
0x000F | Flow Specification command | 用于指定通过Connection_Handle标识的ACL Connection_Handle传输的流量的流参数 | |
0x0010 | Sniff Subrating command | 给定链路指定用于嗅探子例程的参数 | |
0x0011 | Sniff Subrating command | ||
Control and Baseband commands (0x03) | 0x0001 | Set Event Mask command | 用于控制HCI为主机生成哪些事件 |
0x0003 | Reset command | 复位 (软复位) | |
0x0005 | Set Event Filter command | 设置事件过滤 | |
0x0009 | Flush command | 丢弃芯片中正在传输的数据 | |
0x000A | Read PIN Type command | 读取PIN类型 | |
0x000B | Write PIN Type command | 写PIN类型 | |
0x000D | Read Stored Link Key command | 读取芯片中存储的Link key | |
0x000E | Write Stored Link Key command | 把link key写入芯片 | |
0x0011 | Delete Stored Link Key command | 删除芯片中的Link key | |
0x0012 | Write Local Name command | 写入本地名称到芯片中 | |
0x0013 | Read Local Name command | 读取芯片的蓝牙名称 | |
0x0014 | Write Connection Accept Timeout command | 写入蓝牙连接接收的超时时间 | |
0x0015 | Read Connection Accept Timeout command | 读取蓝牙连接接收的超时时间 | |
0x0016 | Write Page Timeout command | 写入page的超时时间 | |
0x0017 | Read Page Timeout command | 读取page的超时时间 | |
0x0019 | Write Scan Enable command | 写入scan enable | |
0x001A | Read Scan Enable command | 读取scan enable | |
0x001B | Write Page Scan Activity command | 写入Page Scan Activity | |
0x001D | Read Page Scan Activity command | 读取Page Scan Activity | |
0x0023 | Write Class of Device command | 写入芯片的cod | |
0x0024 | Read Class of Device command | 读取cod写人cod | |
0x0025 | Write Voice Setting command | 写入voice setting | |
0x0026 | Read Voice Setting command | 读取voice setting | |
0x0031 | Set Controller To Host Flow Control command | 启动HCI流程 | |
0x0032 | Host Buffer Size command | 把buffer size写入到芯片中 | |
0x0033 | Read Buffer Size command | 读取buffer size | |
0x0036 | Read Link Supervision Timeout command | 读取Link Supervision timeout时间 (也就是Link lost时间) | |
0x0037 | Write Link Supervision Timeout command | 写入Link Supervision timeout时间 (也就是Link lost时间) | |
0x0044 | Read Inquiry Mode command | 读取芯片的Inquiry模式 | |
0x0045 | Write Inquiry Mode command | 把搜索模式写入到芯片中 | |
0x0051 | Read Extended Inquiry Response command | 读取芯片的Extended inquiry response | |
0x0052 | Write Extended Inquiry Response command | 把Extended inquiry response写入到芯片 | |
0x0055 | Read Simple Pairing Mode command | 读取芯片是否支持SSP | |
0x0056 | Write Simple Pairing Mode command | 把是否支持SSP写入到蓝牙芯片 | |
Informational Parameters commands (0x04) | 0x0001 | Read Local Version information command | 读取本地芯片的LMP version |
0x0002 | Read Local Supported Commands command | 读取本地芯片支持的command | |
0x0003 | Read Local Supported Features command | 读取本地芯片支持的feature | |
0x0004 | Read Local Extended Features command | 读取本地芯片支持的扩展feature | |
0x0005 | Read Buffer Size command | 读取芯片的buffer size | |
0x0009 | Read BD_ADDR command | 读取本地芯片的蓝牙地址 | |
0x000A | Read Data Block Size command | 读取芯片的block size | |
0x000B | Read Local Supported Codecs command | 读取本地芯片支持的编码格式 | |
0x000C | Read Local Simple Pairing Options command | 读取本地芯片SSP选项 | |
0x000E | Read Local Supported Codec Capabilities command | 读取本地芯片支持的codec capabilities | |
Status Parameters commands (0x05) | 0x0003 | Read Link Quality command | 读取连接质量 |
0x0005 | Read RSSI command | 读取RSSI信号强度 | |
0x0007 | Read Clock command | 读取clock | |
Testing commands (0x06) | 0x0001 | Read Loopback Mode command | 去读取loopback模式 |
0x0002 | Write Loopback Mode command | 写loopback模式 | |
0x0003 | Enable Device Under Test Mode command | 使设备进入测试模式 |
蓝牙事件部分
下面为列出的蓝牙 HCI 事件 (部分):
序号 (Event Code) | EVENT (事件名称) | 描述 |
---|---|---|
0x01 | Inquiry Complete Event | 搜索完成 |
0x02 | Inquiry Result Event | 搜索结果 |
0x03 | Connection Complete Event | 连接完成 |
0x04 | Connection Request Event | 连接请求 |
0x05 | Disconnection Complete | 断开完成 |
0x06 | Authentication Complete event | 授权完成 |
0x07 | Remote Name Request Complete event | 获取远端蓝牙名称完成 |
0x08 | Encryption Change event | 加密模式改变完成 |
0x09 | Change Connection Link Key Complete event | 改变连接的link key完成 |
0x0A | Master Link Key Complete event | 管理Link key完成 |
0x0B | Read Remote Supported Features Complete event | 读取远端设备feature完成 |
0x0C | Read Remote Version Information Complete event | 读取远端版本完成 |
0x0D | QoS Setup Complete event | Qos setup完成 |
0x0E | Command Complete event | 命令完成 |
0x0F | Command Status event | 命令状态消息 |
0x10 | Hardware Error event | 蓝牙芯片硬件错误 |
0x12 | Role Change Event | 角色切换事件 |
0x13 | Number Of Completed Packets event | 完成封包个数 |
0x14 | Mode Change event | 模式改变 |
0x15 | Return Link Keys event | 返回link key |
0x16 | PIN Code Request event | PIN code请求 |
0x17 | Link Key Request event | Link key请求 |
0x18 | Link Key Notification event | Link key通知 |
0x19 | Loopback Command event | Loopback模式返回的事件 |
0x1A | Data Buffer Overflow event | 芯片buffer爆掉 |
0x1B | Max Slots Change event | 最大slot变化 |
0x1C | Read Clock Offset Complete event | 读取时钟偏移完成 |
0x1D | Connection PacketType Changed event | 连接包类型变化 |
0x1E | QoS Violation event | QoS违规 |
0x22 | Inquiry Result with RSSI event | 带RSSI的搜索结果 |
0x2C | Synchronous Connection Complete event | SCO连接完成 |
0x2F | Extended Inquiry Result event | 带EIR的搜索结果 |
0x31 | IO Capability Request event | IO capability请求 |
0x32 | IO Capability Response event | IO capability回复 |
0x33 | User Confirmation Request event | SSP配对方式用户确认请求 |
0x36 | Simple Pairing Complete event | SSP配对完成 |
控制器错误码
在蓝牙 HCI (Host Controller Interface) 协议中,Controller Error Code (或通常称为 Status) 是蓝牙控制器(通常是蓝牙芯片)向主机(运行蓝牙协议栈的处理器)报告操作结果或当前状态的一种机制。它们用于指示一个请求的操作是否成功完成,或者如果失败了,失败的具体原因是什么。
Error Code | Name (名称) | Description (描述) |
---|---|---|
0x00 | Success | 操作成功完成。 |
0x01 | Unknown HCI Command | 控制器不识别主机发送的HCI命令。 |
0x02 | Unknown Connection Identifier | 命令中指定的连接句柄无效或不存在。 |
0x03 | Hardware Failure | 控制器(蓝牙芯片)发生硬件故障。 |
0x04 | Page Timeout | 尝试连接(Paging)远端设备时,在规定时间内未收到响应。 |
0x05 | Authentication Failure | 认证失败,通常在配对过程中因为PIN码或密钥不匹配导致。 |
0x06 | PIN or Key Missing | 需要PIN码或链路密钥,但本地设备没有存储。 |
0x07 | Memory Capacity Exceeded | 控制器内存不足,无法完成请求的操作。 |
0x08 | Connection Timeout | 现有连接的链路监管超时(Link Supervision Timeout)已过期,连接已断开。 |
0x09 | Connection Limit Exceeded | 控制器已达到其支持的最大连接数,无法建立新连接。 |
0x0A | Synchronous Connection Limit To A Device Exceeded | 尝试与一个设备建立的同步连接(SCO/eSCO)数量超出了限制。 |
0x0B | ACL Connection Already Exists | 尝试与一个已经存在ACL连接的设备再次建立ACL连接。 |
0x0C | Command Disallowed | 由于控制器当前的状态,该命令不被允许执行。 |
0x0D | Connection Rejected due to Limited Resources | 连接被远端设备拒绝,因为其资源有限(如内存、连接数已满)。 |
0x0E | Connection Rejected Due To Security Reasons | 连接被远端设备拒绝,因为安全原因(如认证/加密要求未满足)。 |
0x0F | Connection Rejected due to Unacceptable BD_ADDR | 连接被远端设备拒绝,因为它不接受来自本设备蓝牙地址(BD_ADDR)的连接。 |
0x10 | Connection Accept Timeout Exceeded | 主机接受连接的超时时间已过,连接自动失败。 |
0x11 | Unsupported Feature or Parameter Value | 主机请求的功能或参数值不被控制器支持。 |
0x12 | Invalid HCI Command Parameters | HCI命令的参数无效(如长度错误、范围超限)。 |
0x13 | Remote User Terminated Connection | 远端用户主动终止了连接。 |
0x14 | Remote Device Terminated Connection due to Low Resources | 远端设备因资源不足而终止了连接。 |
0x15 | Remote Device Terminated Connection due to Power Off | 远端设备关机导致连接终止。 |
0x16 | Connection Terminated By Local Host | 连接由本地主机主动终止。 |
0x17 | Repeated Attempts | 由于重复尝试,操作失败(例如在认证过程中)。 |
0x18 | Pairing Not Allowed | 设备不允许配对。 |
0x19 | Unknown LMP PDU | 收到了一个未知的或格式不正确的LMP(链路管理协议)数据包。 |
0x1A | Unsupported Remote Feature / Unsupported LMP Feature | 远端设备不支持请求的功能。 |
0x1B | SCO Offset Rejected | 请求的SCO偏移量被拒绝。 |
0x1C | SCO Interval Rejected | 请求的SCO间隔被拒绝。 |
0x1D | SCO Air Mode Rejected | 请求的SCO空中模式(Air Mode)被拒绝。 |
0x1E | Invalid LMP Parameters | LMP数据包中的参数无效。 |
0x1F | Unspecified Error | 未指定的通用错误。 |
0x20 | Unsupported LMP Parameter Value | LMP数据包中的参数值不被支持。 |
0x21 | Role Change Not Allowed | 不允许进行主从角色切换。 |
0x22 | LMP Response Timeout | 等待远端设备的LMP响应超时。 |
0x23 | LMP Error Transaction Collision | 发生了LMP事务冲突。 |
0x24 | LMP PDU Not Allowed | 在当前状态下不允许发送该LMP PDU。 |
0x25 | Encryption Mode Not Acceptable | 请求的加密模式不可接受。 |
0x26 | Link Key Can Not be Changed | 链路密钥无法被更改。 |
0x27 | Requested QoS Not Supported | 请求的服务质量(QoS)不被支持。 |
0x28 | Instant Passed | 一个即时(Instant)已经过去,无法在指定的时间点执行操作。 |
0x29 | Pairing With Unit Key Not Supported | 不支持使用单元密钥(Unit Key)进行配对。 |
0x2A | Different Transaction Collision | 两个不同的LMP事务发生冲突。 |
0x2B | Reserved | 保留值,未使用。 |
0x2C | QoS Unacceptable Parameter | QoS参数不可接受。 |
0x2D | QoS Rejected | QoS请求被拒绝。 |
0x2E | Channel Classification Not Supported | 不支持信道分类。 |
0x2F | Insufficient Security | 当前链路的安全级别不足以执行请求的操作。 |
0x30 | Parameter Out Of Mandatory Range | 参数超出了强制要求的范围。 |
0x31 | Reserved | 保留值,未使用。 |