
这部分是 HCI flow control 的开头,主要讲的是:
Host 和 Controller 之间传输数据时,需要有流控机制,避免 Controller 的数据缓冲区被 Host 发来的数据撑爆。
这里的 flow control 不是蓝牙空口上的流控,而是 Host 和 Controller 之间 HCI 层的数据流控。
1. 这部分整体想表达什么
HCI 数据传输不是 Host 想发多少就发多少。
因为 Controller 内部有数据 buffer,例如用于暂存:
HCI ACL Data Packet
HCI ISO Data Packet
BR/EDR 数据
LE 数据
如果 Host 连续向 Controller 发送大量数据,而 Controller 来不及通过无线链路发出去,就会导致 Controller buffer 溢出。
所以 HCI 需要 flow control。
可以理解为:
Host
↓ 发送 HCI Data Packet
Controller
↓ 暂存在 Controller buffer
↓ 再通过无线链路发给 remote device
如果远端设备没有及时响应、连接间隔较长、空口吞吐受限、Controller buffer 很小,Host 还一直往 Controller 塞数据,就会出问题。
2. 这里讲的是 Host → Controller 方向的数据流控
原文第一句说:
Flow control for data shall be used in the direction from the Host to the Controller...
意思是:
数据流控必须用于 Host 到 Controller 这个方向。
也就是:
Host → Controller
为什么这个方向必须做流控?
因为 Host 发送数据给 Controller 后,Controller 需要先把数据放进自己的 buffer,再等待合适的连接事件、空口时机、链路资源,把数据发给对端设备。
如果 Controller buffer 满了,Host 还继续发,Controller 就处理不过来。
所以 Host 必须知道:
Controller 现在还有多少 buffer 可以用?
我还能不能继续发 ACL Data?
哪些数据包已经发送完成并释放 buffer?
3. Flow control 主要是为了避免 Controller data buffers 溢出
原文说:
to avoid overflowing the Controller data buffers
意思是:
为了避免 Controller 的数据缓冲区溢出。
这里的 Controller data buffers 可以理解为 Controller 内部用于暂存 HCI 数据包的队列。
例如 BLE GATT 写数据时,Host 最终可能通过 HCI ACL Data Packet 把 ATT 数据交给 Controller。
流程大概是:
App 写入数据
↓
GATT / ATT
↓
L2CAP
↓
HCI ACL Data
↓
Controller buffer
↓
Link Layer 在连接事件中发出去
↓
对端设备
如果 App 或 Host 层发得太快,而空口发送能力有限,Controller buffer 就可能被填满。
这就是为什么 HCI flow control 很重要。
4. 什么是 "data destined for a remote device"
原文说:
with data destined for a remote device
意思是:
这些数据最终是要发给远端设备的。
也就是说,Host 发给 Controller 的数据不是停在 Controller 里,而是要通过 Controller 发给另一个蓝牙设备。
例如:
手机 Host → 手机 Controller → 空口 → 蓝牙模块
或者:
MCU Host → 蓝牙芯片 Controller → 空口 → 手机
这里的 remote device 就是对端蓝牙设备。
所以 HCI flow control 管的是:
Host 交给 Controller、准备发往对端设备的数据
典型就是 ACL 数据。
5. using a Connection_Handle 是什么意思
原文中提到:
using a Connection_Handle
意思是:
这些数据是和某一条连接关联的,通常会带有 Connection_Handle。
在 HCI ACL Data Packet 中,会有一个连接句柄,用来表示这包数据属于哪一条连接。
例如一个 Central 同时连接了多个 BLE 外设:
Connection_Handle = 0x0001 → 设备 A
Connection_Handle = 0x0002 → 设备 B
Connection_Handle = 0x0003 → 设备 C
Host 向 Controller 发送 ACL Data 时,需要告诉 Controller:
这包数据要发到哪一条连接上
Controller 才知道应该把数据放到哪条链路对应的队列里。
所以 flow control 通常也和连接句柄有关,因为 Controller 需要知道哪些连接上的数据包已经处理完成。
6. Packet based flow control 是默认机制
原文说:
Packet based flow control is the default for BR/EDR traffic and the only option for LE traffic.
意思是:
基于 Packet 数量的流控,是 BR/EDR 流量的默认方式,也是 LE 流量的唯一方式。
这句话非常关键。
6.1 什么是 Packet based flow control
Packet based flow control 可以理解为:
按"包的数量"来进行流控。
Controller 会告诉 Host:
我最多能接收多少个 HCI Data Packet
Host 发送数据包后,要减少可用额度。
Controller 处理完一部分数据后,会通过事件告诉 Host:
哪些连接上的多少个包已经完成了
你可以继续发送新的包了
典型相关事件是:
HCI_Number_Of_Completed_Packets event
这个事件的作用就是告诉 Host:
某个 Connection_Handle 上,Controller 已经完成了多少个 HCI Data Packet
对应 buffer 已经释放
Host 可以继续发新的数据包
6.2 为什么 LE 只能用 Packet based flow control
对于 BLE 来说,规范明确说:
Packet based flow control is the only option for LE traffic.
也就是说,LE 数据流控只能按包数量来做。
这就意味着,Host 不能无限制地往 Controller 发送 LE ACL Data Packet。
Host 必须根据 Controller 的 buffer 能力和完成事件来控制发送节奏。
7. 这部分不是在讲 GATT 层流控
这里容易和 GATT/ATT 的流控混淆。
HCI flow control 是:
Host ↔ Controller 之间的流控
不是:
App ↔ GATT 之间的流控
也不是:
ATT Write Request / Write Command 的应用层确认机制
例如 BLE 发送数据时,可能有多层"限速":
App 层:一次发送多少业务数据
GATT/ATT 层:Write Request 还是 Write Without Response
L2CAP 层:分片、重组
HCI 层:Controller buffer 流控
Link Layer 层:连接事件里能发多少个空口包
这一节讲的是其中的 HCI 层。
8. Controller → Host 方向的流控
原文说:
Flow control for data moving from the Controller to the Host may be in accordance with Section 4.2.
意思是:
Controller 到 Host 方向的数据流控,可以按照 4.2 节的规则来处理。
也就是说:
Controller → Host
这个方向也可能需要流控,但这里的语气是 may,不像 Host → Controller 那样强调必须使用。
为什么?
因为 Controller 向 Host 上报数据时,Host 侧通常资源更充足,或者由系统驱动处理接收队列。但在某些传输方式或实现中,也需要避免 Host 接收不过来,所以可以使用 Controller 到 Host 方向的流控机制。
9. Command flow control 是另一件事
最后一句说:
Command flow control is covered in Section 4.4 and Section 4.5.
意思是:
命令流控在 4.4 和 4.5 节中讲。
这里要区分两种流控:
Data flow control
Command flow control
9.1 Data flow control
Data flow control 管的是 HCI 数据包,比如:
HCI ACL Data Packet
HCI ISO Data Packet
例如 BLE GATT 通信最终会走 HCI ACL Data Packet。
所以这里关心的是:
Host 能不能继续往 Controller 发数据包
Controller buffer 有没有空位
已经完成了多少个数据包
9.2 Command flow control
Command flow control 管的是 HCI Command。
例如:
LE Set Advertising Parameters
LE Set Advertising Data
LE Set Scan Enable
LE Create Connection
Disconnect
Read RSSI
HCI Command 也不能无限制乱发。
Controller 通常会通过:
Num_HCI_Command_Packets
告诉 Host 当前还能接收多少个 HCI Command。
这个字段经常出现在:
HCI_Command_Complete event
HCI_Command_Status event
所以命令流控和数据流控不是一回事。
10. 结合 BLE 数据发送理解
以 BLE 发送 GATT 数据为例。
假设手机要向蓝牙模块写入大量数据:
App
↓
CoreBluetooth / Android Bluetooth API
↓
GATT
↓
ATT
↓
L2CAP
↓
HCI ACL Data
↓
Controller
↓
Link Layer
↓
空口
↓
蓝牙模块
当 Host 把 ATT 数据封装成 HCI ACL Data Packet 后,并不是随便往 Controller 发。
Host 要考虑:
Controller 支持的 ACL buffer 数量
每个 ACL buffer 的最大长度
当前还剩多少可用 buffer
Controller 已经完成了多少包
Controller 完成发送后,会通过事件释放额度:
HCI_Number_Of_Completed_Packets event
Host 收到这个事件后,才知道可以继续往 Controller 发更多 ACL 数据。
所以 HCI flow control 直接影响 BLE 大数据传输的吞吐和稳定性。
11. 这部分的关键信息总结
11.1 HCI flow control 是 Host 和 Controller 之间的流控
它不是空口流控,也不是 GATT 应用层流控。
它解决的是:
Host 发给 Controller 的数据太快,Controller buffer 被塞满
11.2 Host → Controller 方向必须使用数据流控
因为 Controller buffer 有限,Host 不能无限制发送 HCI Data Packet。
11.3 LE 流量只能使用 Packet based flow control
对于 BLE 来说,HCI 数据流控就是基于包数量的流控。
核心思路是:
Controller 告诉 Host:我能接收多少包
Host 发包时消耗额度
Controller 完成包后通过事件释放额度
Host 根据释放额度继续发送
11.4 Connection_Handle 用来区分数据属于哪条连接
HCI 数据包通常带有 Connection_Handle。
它告诉 Controller:
这包数据属于哪一个蓝牙连接
多连接场景下,这一点非常重要。
11.5 Data flow control 和 Command flow control 要区分
Data flow control:管 HCI ACL / ISO 数据包
Command flow control:管 HCI Command 命令包
不要把它们混在一起理解。
12. 对这部分的学习建议
这部分现在只需要先建立一个核心理解:
HCI flow control 的本质,是 Host 根据 Controller 的 buffer 能力和完成事件,控制 HCI 数据包发送节奏。
后面继续看 4.x 小节时,可以重点关注:
4.1 Host to Controller data flow control
4.2 Controller to Host data flow control
4.4 Command flow control
4.5 Command Status / Command Complete 相关机制
HCI_Number_Of_Completed_Packets event
尤其对于 BLE 数据透传、OTA、大文件发送、吞吐测试来说,HCI flow control 很关键。
因为你在 App 层看到的现象可能是:
写太快丢包
写太快失败
吞吐上不去
连接容易断
不同手机表现不同
但底层原因之一可能就是:
Host、Controller、Link Layer、对端设备之间的数据缓存和流控能力不同。



这部分是 4.1 Host to Controller data flow control,讲的是:
Host 向 Controller 发送 HCI Data Packet 时,Host 应该如何根据 Controller 的 buffer 情况控制发送节奏,避免 Controller 缓冲区溢出。
这部分比 4. HCI flow control 更具体,开始真正讲 Host → Controller 方向的数据流控规则。
1. 这部分整体想表达什么
Host 发给 Controller 的数据,主要是:
HCI ACL Data Packet
HCI ISO Data Packet
这些数据最终会通过 Controller 发给对端蓝牙设备。
但是 Controller 内部 buffer 是有限的,所以 Host 不能无限制地往 Controller 发数据。
因此 Host 必须知道:
Controller 一共有多少 buffer
每个 buffer 最大能放多大的 HCI Data Packet
当前还有多少 buffer 可用
哪些已经发送完成,可以释放 buffer
这就是 Host to Controller data flow control 要解决的问题。
它的核心逻辑是:
初始化时,Host 读取 Controller 的 buffer 能力
↓
Host 根据 buffer 数量发送 HCI Data Packet
↓
Host 每发送一个包,就认为 Controller 可用 buffer 减 1
↓
Controller 完成若干包后,通过事件通知 Host
↓
Host 根据完成事件恢复可用 buffer 数量
↓
Host 继续发送后续数据
2. Host → Controller 数据流控有两种方式
规范中说定义了两种数据流控方式:
packet-based flow control
data-block-based flow control
也就是:
基于包的流控
基于数据块的流控
选择哪种流控模式,通过这个命令设置:
HCI_Write_Flow_Control_Mode command
2.1 Packet-based flow control
这是 BLE 最重要的流控方式。
它的核心是:
按 HCI Data Packet 的数量来计算 buffer 使用情况
例如 Controller 告诉 Host:
我最多可以缓存 10 个 HCI ACL Data Packet
那么 Host 最多只能连续发 10 个包。
每发 1 个包,可用数量减 1。
Controller 完成 1 个包后,通过事件告诉 Host:
某个 Connection_Handle 上完成了 1 个包
Host 再把可用数量加 1。
2.2 Data-block-based flow control
这是另一种流控方式,也称为:
buffer management
它不是简单按包数量管理,而是按 Controller 内部的数据块 buffer 来管理。
这部分对普通 BLE 学习不是最核心。对于 LE 来说,前面规范已经说了:
Packet based flow control is the only option for LE traffic.
所以你现在重点掌握 packet-based flow control 就够了。
3. BR/EDR/LE Controller 是否有独立 ACL buffer
截图开头讲了两种情况:
Controller 为 BR/EDR 和 LE 实现了独立 ACL buffer
Controller 没有为 BR/EDR 和 LE 实现独立 ACL buffer
这主要是针对 双模 Controller。
双模 Controller 同时支持:
BR/EDR
LE
也就是既支持经典蓝牙,也支持 BLE。
那么 Controller 内部的 ACL buffer 可能有两种设计。
3.1 情况一:BR/EDR 和 LE 使用独立 buffer
如果 Controller 为 ACL Data 实现了独立 buffer,那么 Host 要分别管理。
规范要求:
1. Host 使用 HCI_LE_Read_Buffer_Size command 读取 LE-U logical link 使用的 buffer。
2. Host 对每一组 buffer 使用独立的 packet-based flow control。
3. Controller 根据 ACL Data packet 里的 Connection_Handle 判断这包数据应该使用哪一组 buffer。
可以理解为:
BR/EDR ACL buffer:一套
LE ACL buffer:一套
Host 不能把它们混在一起算。
例如:
BR/EDR buffer 剩余 5 个
LE buffer 剩余 3 个
那么发送 LE 数据时,只能消耗 LE buffer。
发送 BR/EDR 数据时,只能消耗 BR/EDR buffer。
3.2 情况二:BR/EDR 和 LE 没有独立 buffer
如果 Controller 没有实现独立 buffer,那么所有 ACL Data 使用同一套 BR/EDR buffer management。
规范说:
all ACL Data shall use the BR/EDR buffer management
也就是说:
BR/EDR ACL Data
LE ACL Data
都从同一个 buffer 池里消耗。
这时 Controller 根据 Connection_Handle 来判断这包数据属于哪个 logical link。
4. Connection_Handle 在流控中有什么作用
这一节多次提到:
Connection_Handle
Handle
原因是 HCI Data Packet 是和具体连接相关的。
例如一个 Host 同时连接多个 BLE 设备:
Connection_Handle = 0x0001 → 设备 A
Connection_Handle = 0x0002 → 设备 B
Connection_Handle = 0x0003 → 设备 C
Host 发 HCI ACL Data Packet 时,里面会带 Connection_Handle。
Controller 根据这个 handle 知道:
这包数据属于哪条连接
这包数据应该走哪个 logical link
这包数据应该消耗哪一组 buffer
在多连接场景下,这一点非常重要。
5. 什么叫一个 packet "completed"
截图中有一段非常关键:
A packet is said to have completed when the Controller no longer needs the buffer space to store the data from the packet and has freed the corresponding buffer for re-use.
意思是:
当 Controller 不再需要用 buffer 保存这个 packet 的数据,并且已经释放对应 buffer 供后续复用时,这个 packet 才算 completed。
注意,这里的 completed 不一定等同于:
对端应用层已经收到数据
也不一定等同于:
ATT 层已经确认
它表示的是:
Controller 侧的 HCI buffer 已经可以释放
通常发生在:
数据已经发送出去
数据被 flush 掉
Controller 内部已经把数据转移到其他存储位置
所以这里的 completed 是 Controller buffer 管理意义上的完成。
6. 同一个 Connection_Handle 上的数据顺序要求
规范最后一句说:
For each individual Connection_Handle, the data shall be sent to the Controller in HCI Data packets in the order in which it was provided by the Host and shall arrive at the Controller in that order.
意思是:
对于每一个单独的 Connection_Handle,Host 提供的数据应该按照原始顺序发送到 Controller,并且到达 Controller 时也应该保持这个顺序。
也就是说,同一条连接上的 HCI Data Packet 不能乱序。
例如 Host 对同一个 BLE 连接发送:
Packet 1
Packet 2
Packet 3
Controller 应该按这个顺序收到:
Packet 1 → Packet 2 → Packet 3
不能变成:
Packet 2 → Packet 1 → Packet 3
这对 L2CAP、ATT、GATT 层的数据重组和语义很重要。
但是不同 Connection_Handle 之间,规范这里强调的是"每个 individual Connection_Handle",也就是说,不同连接之间的数据调度可以由 Host/Controller 根据 buffer 和链路情况处理。
7. 4.1.1 Packet-based data flow control 具体讲什么
这一小节是重点。
它讲的是:
当使用 packet-based flow control 时,Host 和 Controller 怎么通过 buffer size 命令和 completed packets 事件来管理发送额度。
8. 初始化时,Host 要读取 Controller buffer size
对于支持 LE 的 Host,初始化时应发送:
HCI_LE_Read_Buffer_Size command
这个命令用于读取 LE 传输使用的 HCI ACL Data buffer 信息。
它返回的重要参数包括:
LE_ACL_Data_Packet_Length
Total_Num_LE_ACL_Data_Packets
可以理解为:
LE_ACL_Data_Packet_Length:
每个 LE ACL Data Packet 最大能放多少字节数据,不包括 HCI ACL header。
Total_Num_LE_ACL_Data_Packets:
Controller 最多能同时缓存多少个 LE ACL Data Packet。
例如假设返回:
LE_ACL_Data_Packet_Length = 251
Total_Num_LE_ACL_Data_Packets = 10
可以理解为:
Controller 最多可以同时排队 10 个 LE ACL Data Packet
每个包最大数据长度是 251 字节
那么 Host 发送 LE ACL Data 时,就要按照这个能力控制发送。
9. 如果 Total_Num_LE_ACL_Data_Packets 返回 0 怎么办
规范里有一个特殊情况:
如果 Controller 同时支持 BR/EDR 和 LE,那么它可能在 HCI_LE_Read_Buffer_Size 里返回:
Total_Num_LE_ACL_Data_Packets = 0
这表示:
LE 不使用单独的 LE ACL buffer
Host 应该使用 BR/EDR 的 ACL buffer 信息来管理 LE ACL Data
这时 Host 应该再使用:
HCI_Read_Buffer_Size command
来读取 BR/EDR buffer 相关信息。
不过规范也说:
不支持 BR/EDR 的 Controller,不应在 Total_Num_LE_ACL_Data_Packets 返回 0。
也就是说,如果是纯 LE Controller,它不能告诉 Host:
LE ACL buffer 数量为 0
因为纯 LE Controller 没有 BR/EDR buffer 可借用。
10. ISO 数据的 buffer size
截图里还讲到了 HCI ISO Data Packet。
如果 Host 支持通过 HCI 传输 isochronous data,那么初始化时也应发送:
HCI_LE_Read_Buffer_Size command
这个命令的某些版本会返回 ISO 相关参数:
ISO_Data_Packet_Length
Total_Num_ISO_Data_Packets
它们表示:
ISO_Data_Packet_Length:
每个 HCI ISO Data Packet 的最大 buffer 大小。
Total_Num_ISO_Data_Packets:
Controller 最多可以同时缓存多少个 HCI ISO Data Packet。
注意截图中的 Note:
ISO_Data_Packet_Length 和 Total_Num_ISO_Data_Packets 只有在使用 v2 或以上版本的 HCI_LE_Read_Buffer_Size command 时才可用。
对普通 BLE GATT 通信来说,ISO 不是重点。ISO 主要和 LE Audio、CIS/BIS 等等时数据有关。
11. BR/EDR Controller 初始化时读取 buffer size
对于 BR/EDR Controller,当启用 packet-based flow control 时,初始化时 Host 应发送:
HCI_Read_Buffer_Size command
这个命令返回 BR/EDR 相关 buffer 信息,例如:
HCI ACL Data Packet 最大长度
HCI Synchronous Data Packet 最大长度
Controller 可缓存的 ACL Data Packet 总数
Controller 可缓存的 Synchronous Data Packet 总数
这主要是经典蓝牙相关。
你如果主要研究 BLE,可以先知道它和 LE 的区别即可:
LE:重点看 HCI_LE_Read_Buffer_Size
BR/EDR:重点看 HCI_Read_Buffer_Size
12. HCI_Number_Of_Completed_Packets event 的作用
这是这一节最重要的事件。
当至少存在一个连接时,Controller 使用:
HCI_Number_Of_Completed_Packets event
来控制 Host 到 Controller 的数据流。
这个事件会告诉 Host:
每个 Connection_Handle 上,自上一次事件以来,有多少个 HCI Data Packet 已经 completed
也就是告诉 Host:
哪些连接上的多少个 packet 对应的 Controller buffer 已经释放
例如 Controller 上报:
Connection_Handle = 0x0001
Num_Completed_Packets = 3
意思是:
连接 0x0001 上有 3 个 HCI Data Packet 已经完成
Host 可以把对应 buffer 额度加回 3
如果事件中有多个 handle,则可能是:
Connection_Handle = 0x0001,完成 3 个包
Connection_Handle = 0x0002,完成 2 个包
Connection_Handle = 0x0003,完成 1 个包
Host 根据这个事件更新自己的 buffer 计数。
13. Host 如何选择后续发往哪些 Connection_Handle
规范说:
The Host chooses the Connection_Handles for the following HCI Data packets...
意思是:
Host 根据以下信息选择接下来要给哪些连接发送 HCI Data Packet:
HCI_Number_Of_Completed_Packets event 返回的信息
HCI_LE_Read_Buffer_Size command 返回的信息
HCI_Read_Buffer_Size command 返回的信息
也就是说,Host 自己要做调度。
例如有三个 BLE 连接:
设备 A 有很多数据要发
设备 B 有少量数据要发
设备 C 暂时没数据
Host 要根据各连接的数据队列、Controller buffer 空间、完成事件,决定后续先发哪个连接的数据。
14. Host 每发送一个 HCI Data Packet,就要减少可用 buffer 计数
规范中说:
Every time it has sent an HCI Data packet, the Host shall reduce its count of the free buffer space...
意思是:
Host 每发送一个 HCI Data Packet,都必须把对应类型的 Controller 可用 buffer 计数减 1。
例如初始化时知道:
Total_Num_LE_ACL_Data_Packets = 10
Host 当前认为可用 LE ACL buffer 是 10。
发送一个 LE ACL Data Packet 后:
free_buffer = 9
再发一个:
free_buffer = 8
直到:
free_buffer = 0
此时不能继续发。
必须等待 Controller 通过 HCI_Number_Of_Completed_Packets event 释放额度。
15. Host 每发送一个 HCI ISO Data Packet,也要减少 ISO buffer 计数
对于 ISO 数据也是类似。
Host 每发送一个 HCI ISO Data Packet,就要把对应 logical link type 的 free buffer 计数减 1。
这里提到的 logical link type:
LE-S
LE-F
这是 ISO 相关的逻辑链路类型。
普通 BLE GATT 通信可以先不深入。
16. Host 不能在 free buffer 为 0 时继续发送
这是非常关键的一条规则:
The Host shall not send an HCI Data packet or HCI ISO Data packet to the Controller when its count of the free buffer space for the corresponding link type is zero.
意思是:
当对应链路类型的可用 buffer 数量为 0 时,Host 不得继续向 Controller 发送 HCI Data Packet 或 HCI ISO Data Packet。
这就是 flow control 的硬规则。
可以简化成:
free_buffer > 0:可以发
free_buffer = 0:不能发,必须等 completed event
17. Controller 完成 packet 后,要发送 completed packets event
当 Controller 完成一个或多个 HCI Data Packet 或 HCI ISO Data Packet 后,应发送:
HCI_Number_Of_Completed_Packets event
通知 Host。
并且要一直发送,直到最终报告所有 pending 的 HCI Data Packet 都已经完成。
不过发送频率是厂商自定义的:
The frequency at which this event is sent is manufacturer specific.
也就是说,不同 Controller 可能上报频率不同。
有的可能很频繁上报,有的可能批量上报。
这会影响 Host 侧发送节奏和吞吐表现。
18. 4.1.2 Data-block-based data flow control 讲什么
这一节讲另一种流控模式:
data-block-based data flow control
当启用这种模式时,初始化时 Host 要发送:
HCI_Read_Data_Block_Size command
这个命令返回:
最大 HCI ACL Data Packet 长度
Controller 可缓存的 HCI ACL Data Packet 总数
Controller 使用另一个事件来通知 Host:
HCI_Number_Of_Completed_Data_Blocks event
它的作用类似于 packet-based 中的 HCI_Number_Of_Completed_Packets event,只是它按 data block 管理。
Host 同样要根据这个事件计算当前 buffer 使用情况。
规则也类似:
Host 每发送一个 HCI Data Packet,可用 buffer 减 1
Host 收到 completed data blocks 事件,可用 buffer 增加
free buffer 为 0 时,Host 不能继续发送
19. Packet-based 和 Data-block-based 的区别
可以这样理解:
Packet-based:
按 HCI Data Packet 数量进行流控。
Data-block-based:
按 Controller 内部 data block buffer 进行流控。
对于你的 BLE 学习重点来说,主要记住:
LE traffic 只能使用 packet-based flow control。
所以 BLE GATT 数据、BLE L2CAP 数据,重点看:
HCI_LE_Read_Buffer_Size
HCI_Number_Of_Completed_Packets
free buffer count
Connection_Handle
20. 用一个 BLE GATT 大数据发送例子理解
假设手机 Host 要给 BLE 模块发送 OTA 数据。
上层流程是:
App
↓
GATT Write Without Response
↓
ATT
↓
L2CAP
↓
HCI ACL Data Packet
↓
Controller buffer
↓
Link Layer 空口发送
↓
对端 BLE 模块
Controller 初始化时告诉 Host:
LE_ACL_Data_Packet_Length = 251
Total_Num_LE_ACL_Data_Packets = 8
Host 内部维护:
free_buffer = 8
然后 Host 开始发送:
发送第 1 个 HCI ACL Data Packet:free_buffer = 7
发送第 2 个 HCI ACL Data Packet:free_buffer = 6
发送第 3 个 HCI ACL Data Packet:free_buffer = 5
...
发送第 8 个 HCI ACL Data Packet:free_buffer = 0
此时 Host 不能继续往 Controller 发。
等 Controller 在某几个连接事件中把部分数据发出去后,上报:
HCI_Number_Of_Completed_Packets event
Connection_Handle = 0x0001
Num_Completed_Packets = 4
Host 更新:
free_buffer = 4
然后 Host 可以继续发送 4 个包。
这就是 Host → Controller 数据流控的基本逻辑。
21. 和 App 层现象的关系
在 iOS / Android App 开发中,一般直接看不到 HCI buffer 计数,但它会影响你看到的现象。
例如 BLE 透传、OTA、大文件发送中:
writeWithoutResponse 不能无限制调用
发送太快可能失败
系统会限制写入节奏
不同手机吞吐不同
不同蓝牙芯片吞吐不同
连接间隔影响吞吐
MTU / Data Length / PHY 影响吞吐
背后除了 GATT/ATT、L2CAP、Link Layer 之外,也和 HCI flow control 有关系。
App 层虽然不能直接操作 HCI_Number_Of_Completed_Packets event,但系统蓝牙协议栈会在底层根据这些事件控制发送节奏。
22. 这部分最关键的信息总结
22.1 Host 不能无限制向 Controller 发 HCI Data Packet
Controller buffer 有限,Host 必须根据 buffer 状态发送。
22.2 Host 初始化时要读取 Controller buffer 能力
BLE 主要看:
HCI_LE_Read_Buffer_Size
BR/EDR 主要看:
HCI_Read_Buffer_Size
22.3 Host 每发送一个包,可用 buffer 计数减 1
Host 内部需要维护类似这样的计数:
free_buffer_count
发送一个 HCI Data Packet 后:
free_buffer_count -= 1
22.4 Controller 完成包后,通过事件告诉 Host
主要事件是:
HCI_Number_Of_Completed_Packets event
它告诉 Host:
某个 Connection_Handle 上完成了多少个 HCI Data Packet
Host 收到后增加可用 buffer 计数。
22.5 free buffer 为 0 时,Host 不得继续发送
这是流控的硬规则:
free_buffer_count == 0
时,Host 不能继续发对应类型的 HCI Data Packet。
22.6 completed 表示 Controller buffer 可以释放,不等于对端应用层处理完成
这个 completed 是 Controller buffer 管理意义上的完成。
它不是 GATT 层确认,也不是业务层确认。
22.7 同一个 Connection_Handle 上的数据要保持顺序
同一条连接上的 HCI Data Packet 必须按 Host 提供的顺序到达 Controller。
这对上层 L2CAP / ATT 数据的正确性很重要。
22.8 BLE 重点关注 packet-based flow control
因为 LE traffic 只能使用 packet-based flow control。
所以你现在重点掌握:
HCI_LE_Read_Buffer_Size
HCI_Number_Of_Completed_Packets
Connection_Handle
free buffer count
packet completed
23. 可以形成的核心理解
这一节可以总结成一句话:
Host to Controller data flow control 的本质,是 Host 先读取 Controller 的数据 buffer 能力,然后每发送一个 HCI Data Packet 就消耗一个 buffer 额度,Controller 完成数据包后通过 HCI_Number_Of_Completed_Packets event 归还额度;当可用额度为 0 时,Host 不能继续发送。
对 BLE 来说,重点是:
LE 数据走 packet-based flow control。
HCI_LE_Read_Buffer_Size 用来读取 LE buffer 能力。
HCI_Number_Of_Completed_Packets event 用来通知哪些连接上的 packet 已经完成。
Connection_Handle 用来区分数据属于哪条连接。