HCI 功能规范【5. HCI data formats】(3/5)

这部分内容属于HCI data formats → IDs and Handles,主要讲的是:

HCI 中的 ID 和 Handle 是什么、有什么区别、由谁分配、用于什么范围,以及常见 Controller Handle 的编号空间规则。

这部分可以分成三层理解:

第一层:HCI 里有两类标识符:ID 和 Handle 第二层:Controller Handle 包括 Connection_Handle、Sync_Handle、Advertising_Handle、BIG_Handle 第三层:Broadcast Connection_Handle 是 BR/EDR 里的一个特殊情况

一、5.3 IDs and Handles:ID 和 Handle 的基本区别

这一节首先说明:

HCI commands 和 events 中使用两类 identifiers: 1. ID 2. Handle

它们都可以理解为“标识符”,也就是用一个数字代表某个对象。

但是ID 和 Handle 的作用范围不同


关键信息 1:ID 是 Host 分配的,用于两个设备之间,并且会出现在空口 PDU 中

原文说:

IDs, assigned by the Host, are identifiers used between two peer devices and sent over the air in PDUs.

意思是:

ID 由 Host 分配,用于两个 peer devices 之间,并且会通过 PDU 发到空口。

也就是说,ID 不只是本机 Host 和 Controller 内部使用,它会参与两个蓝牙设备之间的协议交互。

可以理解为:

Host 分配 ID ↓ Controller 在空口 PDU 中带上这个 ID ↓ 对端设备也能看到这个 ID ↓ 双方通过这个 ID 识别某个对象

这里的 “over the air” 就是指通过蓝牙无线链路发送出去。


关键信息 2:不同类型的 ID 有不同编号空间

原文说:

Each different type of ID has a separate number space.

意思是:

不同类型的 ID 有各自独立的编号空间。

也就是说:

A 类型 ID = 0x01 B 类型 ID = 0x01

它们不一定冲突,因为它们属于不同 ID 类型。

可以类比为:

一班的 1 号学生 二班的 1 号学生

两个都是 1 号,但因为班级不同,所以不会混淆。


关键信息 3:CIS_ID 在每个 CIG_ID 下都有独立编号空间

原文特别举例:

The CIS_ID has a separate number space for each CIG_ID.

意思是:

每个 CIG_ID 下面,都有自己独立的一套 CIS_ID 编号空间。

这里涉及 LE Isochronous / LE Audio 相关概念:

CIG:Connected Isochronous Group CIS:Connected Isochronous Stream

一个 CIG 中可以包含多个 CIS。

所以可以出现:

CIG_ID = 1 ├── CIS_ID = 0 └── CIS_ID = 1 CIG_ID = 2 ├── CIS_ID = 0 └── CIS_ID = 1

这里两个CIS_ID = 0不冲突,因为它们属于不同的CIG_ID


二、Handle 的含义:用于 Host 和 Controller 之间,不发到空口

原文说:

Handles, assigned by either the Host in a command or by the Controller in an event, are identifiers used between the Host and the Controller but not sent over the air.

意思是:

Handle 可以由 Host 在 command 中分配,也可以由 Controller 在 event 中分配。Handle 用于 Host 和 Controller 之间,不会发送到空口。

这是 ID 和 Handle 最重要的区别。

可以总结为:

ID:设备和设备之间使用,会出现在空口 PDU 中 Handle:Host 和 Controller 之间使用,不会出现在空口 PDU 中

关键信息 4:Handle 是本机 Host 和 Controller 之间的对象编号

例如 BLE 中最常见的是:

Connection_Handle

当手机连接一个 BLE 外设后,Controller 会分配一个Connection_Handle,然后通过 HCI Event 告诉 Host。

之后 Host 要操作这条连接,就通过Connection_Handle指定目标连接。

例如:

Host -> Controller: HCI_Disconnect Connection_Handle = 0x000B

意思是:

请断开 Connection_Handle 为 0x000B 的这条连接

但是这个0x000B只是本机 Host 和 Controller 之间使用的编号。

它不是对端设备地址,也不会直接发到空口让对端设备知道。


关键信息 5:Handle 有些共享编号空间,有些有独立编号空间

原文说:

Some handles share the same number spaces and others have separate number spaces.

意思是:

有些 Handle 共享同一个编号空间,有些 Handle 使用不同编号空间。

所以不能简单认为:

只要两个 Handle 数值一样,就一定冲突

要看它们是不是同一种 Handle,或者是不是处在同一个 number space。

例如:

Connection_Handle = 0x0001 Advertising_Handle = 0x01

它们数值看起来一样,但不一定冲突,因为它们属于不同 Handle 类型。


三、ID / Handle 分配时不能和当前对象冲突

原文说:

When a device allocates an ID or Handle for a new object ... it shall not use a handle that is currently allocated to another object in the same number space.

意思是:

当设备为一个新对象分配 ID 或 Handle 时,在同一个编号空间中,不能使用已经被其他对象占用的值。

例如 Controller 已经有一条连接:

连接 A:Connection_Handle = 0x000B

如果又建立一条新的 ACL 连接,就不能再分配:

连接 B:Connection_Handle = 0x000B

因为这两个连接属于同一个 Connection_Handle 编号空间。

否则 Host 后续发送命令时就无法区分:

Connection_Handle = 0x000B 到底表示连接 A 还是连接 B?

正确做法应该是:

连接 A:Connection_Handle = 0x000B 连接 B:Connection_Handle = 0x000C

四、ID / Handle 删除后可以复用

原文说:

After a device deletes an ID or Handle ... it may reuse the ID or Handle.

意思是:

当某个 ID 或 Handle 对应的对象被删除后,这个 ID 或 Handle 可以被重新使用。

例如:

10:00:00 建立连接 A,Connection_Handle = 0x000B 10:00:10 连接 A 断开,Connection_Handle = 0x000B 被释放 10:00:20 建立连接 B,Connection_Handle = 0x000B

这是允许的。

所以Connection_Handle不是永久唯一的。

它只在当前对象存在期间有效。

分析 HCI 日志时要特别注意:

同一个 Connection_Handle 在不同时间段,可能代表不同连接。

不能只看到相同的 Handle,就判断它一定是同一条连接。


五、5.3.1 Controller handles:常见 Controller Handle

这一节列出了几类 Controller Handle:

Connection_Handle Sync_Handle Advertising_Handle BIG_Handle

它们都用于标识 Host 和 Controller 之间的 logical channel。

这里的 logical channel 可以理解为 Host 和 Controller 之间为了管理某个对象而使用的逻辑编号。


六、Connection_Handle:连接或逻辑传输的 Handle

原文说:

Connection_Handles are assigned by the Controller when a new logical transport is created or reserved...

意思是:

Connection_Handle 通常由 Controller 分配。

当新的 logical transport 被创建或预留时,Controller 会分配一个Connection_Handle,然后通过相应的 HCI Event 上报给 Host。

常见事件包括:

HCI_Connection_Complete HCI_Synchronous_Connection_Complete HCI_LE_Connection_Complete HCI_LE_Enhanced_Connection_Complete HCI_LE_CIS_Request HCI_LE_Create_BIG_Complete HCI_LE_BIG_Sync_Established HCI_Command_Complete

对于你当前学习 BLE 来说,最常见的是:

HCI_LE_Connection_Complete HCI_LE_Enhanced_Connection_Complete

当 BLE 连接建立完成后,Controller 会通过这些 event 告诉 Host:

连接建立结果是什么 Connection_Handle 是多少 对端设备地址是什么 连接间隔是多少 连接延迟是多少 监督超时时间是多少

之后 Host 再对这条连接发送 ACL Data、断开连接、更新连接参数,都需要使用这个Connection_Handle


七、Sync_Handle:周期广播同步对象的 Handle

原文说:

Sync_Handles are assigned by the Controller when a new logical transport is created and reported to the Host in the HCI_LE_Periodic_Advertising_Sync_Established event.

意思是:

Sync_Handle 由 Controller 分配,用于 Periodic Advertising Sync。

流程可以理解为:

Host 让 Controller 去同步某个周期广播 ↓ Controller 成功同步 ↓ Controller 分配 Sync_Handle ↓ 通过 HCI_LE_Periodic_Advertising_Sync_Established event 告诉 Host ↓ Host 后续通过 Sync_Handle 管理这个同步对象

它主要和 BLE Extended Advertising / Periodic Advertising 有关。

如果你现在重点学习 Legacy Advertising,可以先知道它是周期广播同步对象的编号,不必深挖。


八、Advertising_Handle:扩展广播集的 Handle

原文说:

Advertising_Handles are assigned by the Host when a new advertising set is created by using the HCI_LE_Set_Extended_Advertising_Parameters command.

意思是:

Advertising_Handle 由 Host 分配,用于标识一个 extended advertising set。

这个概念主要出现在 Extended Advertising 中。

Legacy Advertising 时代,一般只有一组广播配置:

LE Set Advertising Parameters LE Set Advertising Data LE Set Scan Response Data LE Set Advertising Enable

这些常见 Legacy Advertising 命令通常不需要Advertising_Handle

但是 Extended Advertising 支持多个 advertising sets,所以需要用Advertising_Handle区分不同广播集。

例如:

Advertising_Handle = 0x00:普通广播集 Advertising_Handle = 0x01:周期广播相关广播集 Advertising_Handle = 0x02:厂商自定义数据广播集

之后 Host 设置扩展广播参数、扩展广播数据、扩展扫描响应数据、使能扩展广播时,都可以通过Advertising_Handle指定操作哪一组广播。


九、BIG_Handle:BIG 广播等时组的 Handle

原文说:

BIG_Handles are assigned by the Host when a new BIG is created...

意思是:

BIG_Handle 由 Host 分配,用于标识一个 BIG。

BIG 是:

Broadcast Isochronous Group

主要和 LE Audio 的广播音频有关。

Host 创建 BIG 时,会通过相关命令指定BIG_Handle,例如:

HCI_LE_Create_BIG HCI_LE_Create_BIG_Test LE_BIG_Create_Sync

对当前 BLE 基础学习来说,BIG_Handle 可以先作为了解项。


十、Controller Handle 的编号空间规则

原文说:

All connection handles that are assigned by the Controller shall be derived from the same number space. Sync handles shall be assigned by the Controller from a separate number space. Advertising handles and BIG handles are assigned by the Host from separate number spaces.

意思是:

不同 Controller Handle 的编号空间规则如下:

Connection_Handle:Controller 分配,来自同一个 Connection_Handle 编号空间 Sync_Handle:Controller 分配,但使用单独的编号空间 Advertising_Handle:Host 分配,使用单独编号空间 BIG_Handle:Host 分配,使用单独编号空间

所以可以出现:

Connection_Handle = 0x0001 Sync_Handle = 0x0001 Advertising_Handle = 0x01 BIG_Handle = 0x01

它们数值相同,但不一定冲突,因为它们属于不同编号空间。

真正不能重复的是:

同一个编号空间内,当前正在使用的 Handle 不能重复。

例如两个当前存在的连接不能使用同一个Connection_Handle


十一、5.3.1.1 Broadcast Connection_Handles:广播连接句柄

这一节是一个特殊内容,主要针对BR/EDR broadcast场景,不是 BLE Legacy Advertising 的核心内容。

这里一定要注意:

Broadcast Connection_Handle 不是 BLE 广播包里的 AdvA,也不是 BLE 广播地址,也不是 Advertising_Handle。

它讲的是 HCI ACL Data packet 中带 Broadcast_Flag 的情况。


关键信息 1:Host 第一次发送 active Peripheral broadcast 时,要选择一个未被 Controller 使用的 Connection_Handle

原文说:

The first time the Host sends an HCI ACL Data packet with Broadcast_Flag set to 0b01 ... the value of the Connection_Handle parameter shall be a value which is not currently assigned by the Controller.

意思是:

上电或 reset 后,Host 第一次发送带Broadcast_Flag = 0b01的 HCI ACL Data packet 时,里面的Connection_Handle必须选择一个当前 Controller 没有使用的值。

也就是说,这个广播用的 Connection_Handle 不能和当前已有连接冲突。


关键信息 2:BR/EDR Controller 会持续使用这个 Connection_Handle 做 broadcast,直到 reset

原文说:

The BR/EDR Controller shall then continue to use the same Connection_Handle for broadcast until a reset is made.

意思是:

BR/EDR Controller 后续会继续使用这个相同的Connection_Handle做 broadcast,直到发生 reset。

并且:

Controller 不应把这个已经用于 broadcast 的 Connection_Handle 重新分配给其他连接。

否则就可能出现歧义:

这个 Connection_Handle 到底表示 broadcast? 还是表示某条新的 ACL connection?

关键信息 3:规范考虑了极少见的冲突场景

原文说,有些情况下 Controller 可能还没来得及解释 Host 发来的 Broadcast packet,就先发出了 Connection Complete event。

这样可能出现:

Broadcast packet 中的 Connection_Handle 和 Connection Complete event 中的新连接 Connection_Handle 相同

也就是同一个 Handle 临时同时指向了 broadcast 和新连接。

规范说这种冲突要这样处理:

如果 Host 收到 Connection Complete event, 发现其中的 Connection_Handle 正好是 broadcast 正在使用的 handle, 那么 Host 不能马上给新连接发送数据。

Host 要先等待:

Number Of Completed Packets event

这个事件表明该Connection_Handle下已经没有 pending broadcast packets。

然后 Host 要把 broadcast 使用的Connection_Handle改成另一个当前没有被 Controller 分配的值。

之后,Connection Complete event 中的那个Connection_Handle才用于新连接。


关键信息 4:这样做是为了区分 broadcast message 和新连接

这个处理流程的目的,是让 Controller 能够区分:

Host 之前发出的 broadcast message

和:

新建立的 connection

即使它们一度使用了相同的Connection_Handle,也可以通过等待旧 broadcast 数据处理完、然后更换 broadcast handle 的方式,避免混淆。

可以理解为:

旧 broadcast 数据还没处理完 ↓ 新连接碰巧使用了同一个 Connection_Handle ↓ Host 先不要马上用这个 Handle 给新连接发数据 ↓ 等 Number Of Completed Packets 表明旧 broadcast 数据处理完 ↓ Host 更换 broadcast 使用的 Connection_Handle ↓ 这个 Handle 才正式归新连接使用

关键信息 5:Controller 发给 Host 的 Broadcast_Flag = 01 的 ACL Data,Connection_Handle 应该填发送 broadcast 的 Central 对应 ACL connection handle

原文说:

For an HCI ACL Data packet sent from the Controller to the Host where the Broadcast_Flag is 01, the Connection_Handle parameter should contain the Connection_Handle for the ACL connection to the Central that sent the broadcast.

意思是:

如果 Controller 向 Host 发送 HCI ACL Data packet,并且Broadcast_Flag = 01,那么其中的Connection_Handle应该填写发送该 broadcast 的 Central 对应的 ACL connection handle。

这仍然是 BR/EDR broadcast 语境下的规则,不要和 BLE 广播扫描结果混在一起。


关键信息 6:Connectionless Peripheral Broadcast 不分配 Connection_Handle

原文最后说:

For Connectionless Peripheral Broadcast, no Connection_Handle is assigned.

意思是:

对于Connectionless Peripheral Broadcast,不分配Connection_Handle

也就是说,不是所有 broadcast 都会有 Connection_Handle。是否有 Handle,取决于具体 broadcast 类型。


十二、这部分最重要的学习重点

如果你的目标是掌握 BLE,尤其是 BLE 的 HCI Command、HCI Event、连接、广播、扫描,那么这部分最应该抓住的是:

1. ID 和 Handle 不是一回事。 2. ID 会用于两个 peer device 之间,并可能出现在空口 PDU 中。 3. Handle 用于 Host 和 Controller 之间,不会发送到空口。 4. Connection_Handle 是最重要的 Handle,用于标识一条连接。 5. Advertising_Handle 主要用于 Extended Advertising,用来标识一个 advertising set。 6. Sync_Handle 主要用于 Periodic Advertising Sync。 7. BIG_Handle 主要用于 LE Audio / BIG。 8. 同一个编号空间内,正在使用的 Handle 不能重复。 9. 对象删除后,Handle 可以复用。 10. Broadcast Connection_Handle 主要是 BR/EDR 特殊规则,学习 BLE 时可以先了解,不必作为重点。

十三、容易混淆的点

1. Connection_Handle 不是蓝牙地址

Connection_Handle只是 Host 和 Controller 之间标识某条连接的本地编号。

它不是:

Public Device Address Random Device Address Resolvable Private Address Identity Address

例如:

外设地址:DC:0D:30:00:06:F6 Connection_Handle:0x000B

这两个不是一类东西。


2. Advertising_Handle 不是广播地址

Advertising_Handle是 Extended Advertising 中 Host 给 advertising set 分配的编号。

它不是:

AdvA 广播设备地址 蓝牙 MAC 地址

它只是用来区分多个广播集。


3. BLE Legacy Advertising 通常不用 Advertising_Handle

你之前看的这些命令:

LE Set Advertising Parameters LE Set Advertising Data LE Set Scan Response Data LE Set Advertising Enable

属于 Legacy Advertising 常见命令,它们通常没有Advertising_Handle

Advertising_Handle主要出现在:

HCI_LE_Set_Extended_Advertising_Parameters HCI_LE_Set_Extended_Advertising_Data HCI_LE_Set_Extended_Scan_Response_Data HCI_LE_Set_Extended_Advertising_Enable

4. Broadcast Connection_Handle 不是 BLE 广播中的 “广播句柄”

看到Broadcast Connection_Handles这个标题,不要理解成 BLE Advertising 里面有一个广播连接句柄。

这部分讲的是 BR/EDR 的 broadcast 相关规则,和 BLE Legacy Advertising 的ADV_INDADV_NONCONN_INDSCAN_REQSCAN_RSP不是一回事。


十四、这部分可以总结为

这部分内容讲的是HCI 中 ID 和 Handle 的概念、区别、分配规则和编号空间规则

核心结论是:

ID: - 由 Host 分配 - 用于两个 peer devices 之间 - 会出现在空口 PDU 中 - 不同类型 ID 有各自独立编号空间 Handle: - 可由 Host 分配,也可由 Controller 分配 - 用于 Host 和 Controller 之间 - 不会发送到空口 - 不同 Handle 可能共享编号空间,也可能使用独立编号空间 - 同一编号空间内,当前使用的值不能重复 - 对象删除后,Handle 可以复用

对 BLE 学习来说,最重要的是理解:

Connection_Handle 是 Host 和 Controller 之间标识某条连接的本地编号; Advertising_Handle 是 Extended Advertising 中标识某个 advertising set 的编号; Sync_Handle 是 Periodic Advertising Sync 的编号; BIG_Handle 是 Broadcast Isochronous Group 的编号; 它们都不是蓝牙设备地址,也不是永久唯一标识。

所以后面看 HCI 日志时,只要看到Connection_Handle,就要把它理解成:

当前本机 Host 和 Controller 之间,用来操作某条连接的临时编号。

而不是把它理解成设备地址、蓝牙 MAC,或者空口里的永久身份标识。