
这部分内容属于HCI data formats下面的IDs and Handles主要讲的是HCI 里面有两类“标识符”ID 和 Handle。它们都用来标识某个对象但使用范围不同。简单说ID主要用于两个蓝牙设备之间会出现在空口 PDU 中 Handle主要用于 Host 和 Controller 之间不会直接发到空口一、这部分整体想表达什么这部分主要说明 HCI 中的ID和Handle的区别。在 HCI Command 和 HCI Event 中经常会看到类似下面的字段Connection_Handle Advertising_Handle Sync_Handle CIS_ID CIG_ID这些字段看起来都是“编号”但它们不是同一种东西。规范在这里先建立一个基础概念ID 和 Handle 都是 identifier也就是标识符。 但是它们的作用范围、分配者、是否会出现在空口数据包中是不同的。二、关键信息 1HCI 中有两类标识符原文说Two types of identifiers are used in HCI commands and events.意思是HCI Command 和 HCI Event 中使用两类标识符1. ID 2. Handle它们都可以理解为“用一个数字代表某个对象”。例如某一个连接 某一个广播集 某一个同步对象 某一个 CIS 某一个 CIG但是这些数字到底是给谁看的要看它是 ID 还是 Handle。三、关键信息 2ID 是 Host 分配的并且用于两个对等设备之间原文说IDs, assigned by the Host, are identifiers used between two peer devices and sent over the air in PDUs.意思是ID 是由 Host 分配的。它的使用范围是两个 peer device 之间也就是两个蓝牙设备之间。并且 ID 会被放进空口 PDU 中发送。这里的 “over the air” 就是指通过无线链路传出去也就是实际出现在蓝牙空口包里。可以理解为Host 分配一个 ID ↓ Controller 在发送空口 PDU 时使用这个 ID ↓ 对端设备收到 PDU 后也能看到这个 ID ↓ 双方用这个 ID 来识别某个对象所以 ID 不是只在本机 Host 和 Controller 内部使用它会影响两个设备之间的协议交互。四、关键信息 3不同类型的 ID 有各自独立的编号空间原文说Each different type of ID has a separate number space. The CIS_ID has a separate number space for each CIG_ID.意思是不同类型的 ID 使用不同的编号空间。所谓number space可以理解为“编号范围”或者“编号池”。例如A 类型 ID 可以从 0 开始编号 B 类型 ID 也可以从 0 开始编号这两个0不冲突因为它们属于不同类型的 ID。可以类比为班级 1 的 1 号学生 班级 2 的 1 号学生两个都是 1 号但因为班级不同所以不会混淆。五、关键信息 4CIS_ID 在每个 CIG_ID 下都有独立编号空间原文特别举了一个例子The CIS_ID has a separate number space for each CIG_ID.意思是每个 CIG_ID 下面CIS_ID 都有自己独立的编号空间。这里涉及 LE Audio / Isochronous 相关概念CIGConnected Isochronous Group CISConnected Isochronous Stream可以简单理解为一个 CIG 里面可以包含多个 CIS因此CIG_ID 1 下面可以有 CIS_ID 0 CIG_ID 2 下面也可以有 CIS_ID 0这两个CIS_ID 0不冲突因为它们属于不同的 CIG。可以理解成CIG_ID 1 ├── CIS_ID 0 └── CIS_ID 1 CIG_ID 2 ├── CIS_ID 0 └── CIS_ID 1这里的CIS_ID不是全局唯一而是在对应的CIG_ID范围内唯一。六、关键信息 5Handle 可以由 Host 或 Controller 分配原文说Handles, assigned by either the Host in a command or by the Controller in an event...意思是Handle 可以由 Host 分配也可以由 Controller 分配。具体由谁分配要看具体的对象类型和具体的 HCI Command / Event。例如有些 Handle 是 Host 在 HCI Command 中指定的Host - Controller: 创建某个对象并指定它的 Handle有些 Handle 是 Controller 在 HCI Event 中返回的Controller - Host: 某个对象创建完成这是我分配给它的 Handle最典型的就是Connection_Handle连接建立完成后Controller 会通过事件告诉 Host这个连接对应的 Connection_Handle 是多少之后 Host 再操作这个连接时就通过这个Connection_Handle指定目标连接。七、关键信息 6Handle 用于 Host 和 Controller 之间不会发到空口原文说handles ... are identifiers used between the Host and the Controller but not sent over the air.意思是Handle 是 Host 和 Controller 之间使用的标识符不会直接出现在空口 PDU 中。这点非常关键。例如Connection_HandleHost 想让 Controller 对某个连接发送数据、断开连接、读取连接信息时会在 HCI Command 中带上Connection_Handle。例如Host - Controller: HCI_Disconnect Connection_Handle 0x000B意思是请断开 Connection_Handle 为 0x000B 的连接但是这个0x000B只是本机 Host 和 Controller 之间识别连接用的编号。它不会原封不动地发到空口里让对端设备看到。对端设备并不知道你本地 Host 和 Controller 之间把这个连接叫做0x000B。八、关键信息 7有些 Handle 共享编号空间有些 Handle 有独立编号空间原文说Some handles share the same number spaces and others have separate number spaces.意思是有些 Handle 使用同一个编号空间有些 Handle 使用不同的编号空间。也就是说某些 Handle 类型之间编号不能重复 某些 Handle 类型之间编号可以重复因为它们属于不同编号空间。这个具体要看规范对某个 Handle 的定义。例如某些连接相关 handle 可能在同一个范围内管理而某些广播相关 handle、同步相关 handle 则可能有自己的编号范围。这里暂时不需要记所有 Handle 的编号空间只需要先理解原则Handle 不是全部都在一个全局编号池里。 不同 Handle 是否冲突要看它们是否属于同一个 number space。九、关键信息 8新分配 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 为一个新的 ACL 连接分配Connection_Handle时不能分配一个当前已经被别的连接使用的Connection_Handle。错误示例ACL Connection A - Connection_Handle 0x000B ACL Connection B - Connection_Handle 0x000B如果 A 和 B 属于同一个编号空间这就是错误的。正确示例ACL Connection A - Connection_Handle 0x000B ACL Connection B - Connection_Handle 0x000C这样 Host 才能明确知道0x000B 对应连接 A 0x000C 对应连接 B否则 Host 后续发送命令时就无法区分到底操作哪条连接。十、关键信息 9对象删除后ID 或 Handle 可以被复用原文说After a device deletes an ID or Handle ... it may reuse the ID or Handle.意思是当某个对象被删除后它对应的 ID 或 Handle 可以被重新使用。例如连接 A 建立 Connection_Handle 0x000B 连接 A 断开 Connection_Handle 0x000B 被释放 后面连接 B 建立 Controller 可以再次使用 Connection_Handle 0x000B所以Connection_Handle不是永久唯一的。它只是在当前对象存在期间有效。这点在分析日志时非常重要同一个 Connection_Handle 在不同时间段可能代表不同连接。例如你在 btsnoop 里看到10:00:00 Connection_Handle 0x000B 10:00:10 Disconnection Complete, Handle 0x000B 10:00:20 Connection Complete, Handle 0x000B不能简单认为 10:00:00 和 10:00:20 的0x000B一定是同一条连接。中间已经断开过所以后面的0x000B可能是新的连接复用了旧 handle。十一、ID 和 Handle 的核心区别可以这样理解ID - 由 Host 分配 - 用于两个 peer device 之间 - 会出现在空口 PDU 中 - 不同类型 ID 有独立编号空间 Handle - 可由 Host 或 Controller 分配 - 用于 Host 和 Controller 之间 - 不会直接出现在空口 PDU 中 - 有些 Handle 共享编号空间有些有独立编号空间更直观地说ID 是“设备与设备之间”的标识符 Handle 是“Host 与 Controller 之间”的标识符十二、结合 BLE 学习时怎么理解在 BLE 学习中最常见、最需要先掌握的是Connection_Handle它是一个典型的 Handle。连接建立之后Controller 会分配一个Connection_Handle并通过 HCI Event 告诉 Host。之后 Host 想对这条连接做操作都要带上这个 Handle。例如断开连接 更新连接参数 读取远端版本信息 发送 ACL Data 处理 Number Of Completed Packets这些场景都会用到Connection_Handle。但是要记住Connection_Handle 只是本机 Host 和 Controller 之间使用的连接编号。 它不是对端设备地址。 它不是蓝牙 MAC 地址。 它也不是空口连接标识。十三、一个简单例子假设手机作为 Central 连接了两个 BLE 外设外设 ADC:0D:30:00:06:F6 外设 BAA:BB:CC:DD:EE:FFController 可能分配外设 A 的连接Connection_Handle 0x000B 外设 B 的连接Connection_Handle 0x000C之后 Host 要断开外设 A就发HCI_Disconnect Connection_Handle 0x000BHost 要给外设 B 发 ACL Data就在 ACL Data packet 里带Connection_Handle 0x000C这里的0x000B、0x000C只是本机内部 HCI 层使用的编号。外设 A 和外设 B 并不知道手机本地给这两条连接分配了什么Connection_Handle。十四、这部分可以总结为这部分内容讲的是 HCI 中ID 和 Handle 的基本概念与使用规则。核心结论是1. HCI 中有两类标识符ID 和 Handle。 2. ID 由 Host 分配用于两个 peer device 之间会出现在空口 PDU 中。 3. Handle 由 Host 或 Controller 分配用于 Host 和 Controller 之间不会出现在空口 PDU 中。 4. 不同 ID / Handle 可能有不同的编号空间。 5. 同一个编号空间中正在使用的 ID 或 Handle 不能重复。 6. 当对象被删除后它的 ID 或 Handle 可以被重新使用。对 BLE 学习来说最重要的是先理解Connection_Handle 是 Host 和 Controller 之间用来标识某条连接的本地编号。 它不是设备地址也不是永久唯一 ID。 连接断开后这个 handle 可以被释放并在后续连接中复用。这部分内容属于HCI data formats → IDs and Handles → Controller handles主要讲的是HCI 中有哪些 Controller Handle这些 Handle 由谁分配、用于标识什么对象、编号空间如何划分以及一个特殊的 Broadcast Connection_Handle 如何处理。这一节比较偏“规则说明”核心是在告诉你不同类型的 Handle 虽然都叫 Handle但它们不一定由同一方分配也不一定处在同一个编号空间中。一、这部分整体想表达什么HCI 中存在多种 Controller Handle主要包括Connection_Handle Sync_Handle Advertising_Handle BIG_Handle这些 Handle 都是 Host 和 Controller 之间使用的标识符用来标识某些逻辑对象或逻辑通道。其中最重要的是Connection_Handle标识连接或逻辑传输 Sync_Handle标识周期广播同步相关逻辑传输 Advertising_Handle标识一个 advertising set BIG_Handle标识一个 BIG这部分的重点不是讲这些对象的完整工作流程而是讲这些 Handle 是谁分配的 什么时候分配 通过什么 HCI Command 或 HCI Event 告诉对方 它们是否共享编号空间二、关键信息 1Controller Handle 用于标识 Host 和 Controller 之间的逻辑通道原文说Connection_Handles, Sync_Handles, Advertising_Handles, and BIG_Handles are Controller Handles used to identify logical channels between the Host and the Controller.意思是这些 Handle 都属于Controller Handle用于标识 Host 和 Controller 之间的 logical channel。这里的logical channel不一定是一个真实的物理链路而是 Host 和 Controller 之间为了管理某个蓝牙对象而使用的逻辑编号。例如一条 ACL 连接 一个同步对象 一个扩展广播集 一个 BIG 广播等时组Host 后续要操作这些对象时就通过对应的 Handle 告诉 Controller我要操作哪一个连接 我要操作哪一个广播集 我要操作哪一个周期广播同步 我要操作哪一个 BIG所以 Handle 的作用就是“定位对象”。三、关键信息 2Connection_Handle 通常由 Controller 分配原文说Connection_Handles are assigned by the Controller when a new logical transport is created or reserved...意思是当新的 logical transport 被创建或预留时Connection_Handle通常由 Controller 分配。然后 Controller 会通过相关 HCI Event 把这个 Handle 上报给 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不用一开始把这些事件都背下来先抓住本质连接或逻辑传输创建完成后Controller 会分配 Connection_Handle并通过事件告诉 Host。例如 BLE 中最常见的是HCI_LE_Connection_Complete event或者新版本中更常见的是HCI_LE_Enhanced_Connection_Complete event它们会告诉 Host连接建立成功 这个连接的 Connection_Handle 是多少 对端地址是什么 连接间隔是多少 连接延迟是多少 监督超时时间是多少之后 Host 再发送 ACL Data 或连接管理命令时就通过这个Connection_Handle指定这条连接。四、关键信息 3Sync_Handle 由 Controller 分配原文说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 在创建新的同步逻辑传输时分配的。它会通过下面这个事件报告给 HostHCI_LE_Periodic_Advertising_Sync_Established event这个主要和Periodic Advertising有关。可以简单理解为Host 让 Controller 去同步某个周期广播 ↓ Controller 成功同步后 ↓ Controller 分配一个 Sync_Handle ↓ 之后 Host 用这个 Sync_Handle 管理这个周期广播同步对象例如后续要终止同步、接收周期广播报告、处理同步状态时就会用到这个Sync_Handle。五、关键信息 4Advertising_Handle 由 Host 分配原文说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 分配的。当 Host 使用下面这个命令创建一个新的 advertising set 时会指定一个Advertising_HandleHCI_LE_Set_Extended_Advertising_Parameters command这个主要和Extended Advertising有关。在 Legacy Advertising 时代通常只有一组广播参数所以不需要用Advertising_Handle区分多个广播集。但 Extended Advertising 支持多个 advertising sets因此需要一个编号来区分Advertising_Handle 0x00 Advertising_Handle 0x01 Advertising_Handle 0x02每个 handle 可以对应一组不同的广播配置例如Advertising_Handle 0x00普通可连接广播 Advertising_Handle 0x01周期广播相关广播集 Advertising_Handle 0x02厂商数据广播之后 Host 设置广播数据、扫描响应数据、使能广播时都可以通过Advertising_Handle指定操作哪一个 advertising set。六、关键信息 5BIG_Handle 由 Host 分配原文说BIG_Handles are assigned by the Host when a new BIG is created...意思是BIG_Handle也是由 Host 分配的。BIG 是Broadcast Isochronous Group也就是广播等时组主要和 LE Audio 的广播音频相关。Host 创建 BIG 时会通过相关命令指定BIG_Handle例如HCI_LE_Create_BIG HCI_LE_Create_BIG_Test LE_BIG_Create_Sync这里不需要一开始深入 LE Audio只要先理解BIG_Handle 用来标识一个 BIG 对象。 Host 创建 BIG 时指定这个 Handle。 后续 Controller 和 Host 通过这个 Handle 管理这个 BIG。七、关键信息 6不同 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.这几句话非常重要。它们说明了编号空间的划分Connection_HandleController 分配来自同一个 Connection_Handle 编号空间 Sync_HandleController 分配但使用单独的编号空间 Advertising_HandleHost 分配使用单独的编号空间 BIG_HandleHost 分配使用单独的编号空间也就是说Connection_Handle 0x0001 Sync_Handle 0x0001 Advertising_Handle 0x0001 BIG_Handle 0x0001这些数值即使一样也不一定冲突因为它们属于不同类型、不同编号空间。但是在同一个编号空间中正在使用的 Handle 不能重复。例如两个当前存在的 ACL 连接不能同时使用同一个Connection_Handle连接 AConnection_Handle 0x000B 连接 BConnection_Handle 0x000B // 不允许但是下面这种情况可能是允许的Connection_Handle 0x000B Advertising_Handle 0x0B因为它们不是同一个编号空间。八、关键信息 7Broadcast Connection_Handle 是一个特殊情况下面的5.3.1.1 Broadcast Connection_Handles讲的是一个特殊规则Broadcast Connection_Handle这部分主要是 BR/EDR 里的广播相关内容不是你当前学习 BLE Legacy 广播时最核心的内容。但是可以先理解它的规则当 Host 第一次发送一个 HCI ACL Data packet并且其中Broadcast_Flag 0b01也就是active Peripheral broadcast时如果是在上电或 reset 之后第一次这样发送那么Connection_Handle 的值必须是当前 Controller 没有使用的 handle。随后 BR/EDR Controller 会继续使用这个相同的Connection_Handle做 broadcast直到下一次 reset。九、关键信息 8Broadcast Connection_Handle 一旦用于 broadcastController 不应重新分配给别的连接原文说The Controller shall not re-allocate a Connection_Handle that it knows is used for broadcast.意思是Controller 如果知道某个Connection_Handle已经被用于 broadcast就不应该再把这个Connection_Handle分配给其他连接。因为如果同一个Connection_Handle同时用于 broadcast 和新连接Host 和 Controller 之间就会产生歧义这个 ACL Data 到底是 broadcast 数据 还是某条新连接的数据所以原则上要避免这种冲突。十、关键信息 9规范考虑了极少见的冲突情况原文提到一种特殊情况Controller 可能还没有来得及解析 Host 发送的 Broadcast packet就先发送了 Connection Complete event。这样就可能出现Connection Complete event 中的 Connection_Handle 和 Host 发送的 broadcast ACL Data packet 中的 Connection_Handle 相同也就是新连接的 Connection_Handle 和 broadcast 使用的 Connection_Handle 冲突了规范说这种冲突是可以避免并处理的。处理方式是如果 Host 收到 Connection Complete event里面的 Connection_Handle 正好是 broadcast 用过的 handle Host 应该先等待不要马上给这条新连接发送数据。要等到Number Of Completed Packets event表明该 Connection_Handle 对应的 pending broadcast packets 已经没有了。然后 Host 还要把 broadcast 使用的 Connection_Handle 改成另一个当前没有被 Controller 分配使用的值。之后Connection Complete event 中那个Connection_Handle才能用于新连接。十一、为什么要这样处理这个规则的目的是让 Controller 可以区分Host 之前发送的 broadcast message和后来新建立的 connection即使它们一度使用了相同的Connection_Handle也能通过等待 pending packet 清空和更换 broadcast handle 的方式避免数据归属混乱。可以简单理解为旧的 broadcast 数据还没处理完 ↓ 新连接碰巧也用了同一个 Connection_Handle ↓ Host 不能马上用这个 Handle 给新连接发数据 ↓ 先等旧 broadcast 数据处理完 ↓ 再把 broadcast 改用别的 Handle ↓ 这个 Handle 才正式归新连接使用十二、关键信息 10从 Controller 发给 Host 的 broadcast ACL DataConnection_Handle 应该填 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 广播包里那种 Advertising Data。所以这里千万不要和 BLE Advertising 混在一起。十三、关键信息 11Connectionless 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尤其是BLE Legacy Advertising BLE Scanning BLE Connection HCI Command / Event ACL Data那么这一节里最重要的是前半部分也就是Connection_Handle Sync_Handle Advertising_Handle BIG_Handle其中你最应该优先掌握的是Connection_Handle Advertising_Handle Sync_Handle优先级可以这样排第一优先级Connection_Handle 第二优先级Advertising_Handle 第三优先级Sync_Handle 第四优先级BIG_Handle至于Broadcast Connection_Handles这一小节主要是 BR/EDR broadcast 相关内容。如果你的目标是 BLE可以先了解概念不需要现在深挖。十五、几个容易混淆的点1. Advertising_Handle 不是 BLE 设备地址Advertising_Handle只是 Host 创建 extended advertising set 时指定的本地编号。它不是Public Device Address Random Device Address Resolvable Private Address它只是用来区分多个 advertising sets。2. Connection_Handle 不是对端设备地址Connection_Handle是 Controller 分配给某条连接的本地编号。它不是对端 MAC 地址 Identity Address Random Address同一个外设断开后重新连接可能得到新的Connection_Handle。不同外设连接时也会有不同的Connection_Handle。3. Handle 可以复用连接断开、同步删除、广播集删除之后对应的 Handle 值可能被再次使用。所以分析日志时要结合时间线Connection Complete ACL Data Disconnection Complete Connection Complete不能只看到相同 Handle 就认为一定是同一个对象。4. Legacy Advertising 通常不用 Advertising_Handle你之前重点看的LE Set Advertising Parameters LE Set Advertising Data LE Set Scan Response Data LE Set Advertising Enable这些是 Legacy Advertising 常用命令。Legacy Advertising 通常没有Advertising_Handle这个概念。Advertising_Handle主要出现在 Extended Advertising 相关命令中例如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十六、可以这样总结这部分内容讲的是Controller Handles 的分类、分配者、使用场景和编号空间规则。核心结论是1. Connection_Handle、Sync_Handle、Advertising_Handle、BIG_Handle 都是 Controller Handle。 2. 它们用于 Host 和 Controller 之间标识逻辑对象或逻辑通道。 3. Connection_Handle 通常由 Controller 分配并通过连接完成类事件上报给 Host。 4. Sync_Handle 由 Controller 分配用于 Periodic Advertising Sync。 5. Advertising_Handle 由 Host 分配用于 Extended Advertising 中区分多个 advertising sets。 6. BIG_Handle 由 Host 分配用于 BIG 广播等时组。 7. Connection_Handle、Sync_Handle、Advertising_Handle、BIG_Handle 处在不同的编号空间中。 8. 同一个编号空间内正在使用的 Handle 不能重复对象释放后 Handle 可以复用。 9. Broadcast Connection_Handle 是 BR/EDR broadcast 相关的特殊规则学习 BLE 时可以先了解不必作为重点深挖。对你当前学习 BLE 来说这一节最实用的理解是Connection_Handle 用来标识一条已经建立的连接 Advertising_Handle 用来标识一个扩展广播集 Sync_Handle 用来标识一个周期广播同步对象 这些 Handle 都不是蓝牙设备地址而是 Host 和 Controller 之间管理对象用的编号。