
这部分是 4.3 Disconnection behavior,讲的是:
当连接断开以后,Host 和 Controller 之间与这个连接相关的 HCI 数据包、buffer、flow control 计数应该如何处理。
它不是在讲断开连接的原因,也不是在讲 HCI_Disconnect command 的参数,而是在讲:
连接已经断开以后,之前还没有完成的数据包和 buffer 怎么算?
1. 这部分整体表达了哪些知识
这一节主要表达两个方向的处理规则:
1. Host → Controller 方向:
连接断开后,Host 应认为之前发给 Controller、但还没确认完成的数据包已经被 flush,
Controller 对应 buffer 已经释放。
2. Controller → Host 方向:
如果 Controller → Host 方向也启用了流控,
连接断开后,Controller 可以认为 Host 会释放这个连接相关的接收 buffer,
Host 不需要再专门发送 completed packets command 通知 Controller。
也就是说,断开连接以后,这条连接上的未完成 HCI 数据包不会继续等待完成通知,而是直接按"清掉了"处理。
2. HCI_Disconnection_Complete event 是关键事件
原文第一句说:
When the Host receives an HCI_Disconnection_Complete event...
意思是:
当 Host 收到 HCI_Disconnection_Complete event 时,Host 就知道某个连接已经断开完成。
HCI_Disconnection_Complete event 是 Controller 通知 Host:
某个 Connection_Handle 对应的连接已经断开
这个事件里通常会带有:
Status
Connection_Handle
Reason
其中 Connection_Handle 很重要,因为它告诉 Host:
是哪一条连接断开了
如果 Host 同时连接多个设备,就要根据这个 handle 清理对应连接的数据状态。
3. Host 应认为未确认的 HCI Data packets 已经被 flush
原文说:
the Host shall assume that all unacknowledged HCI Data packets that have been sent to the Controller for the returned Handle have been flushed
意思是:
Host 应当认为,所有已经发送给 Controller、但还没有收到完成通知的 HCI Data Packet,都已经被 flush 掉了。
这里的 unacknowledged HCI Data packets 指的是:
Host 已经发给 Controller
但是 Controller 还没有通过 HCI_Number_Of_Completed_Packets event 告诉 Host completed 的数据包
例如 Host 给某个 BLE 连接发送了 10 个 HCI ACL Data Packet:
Host → Controller:Packet 1
Host → Controller:Packet 2
Host → Controller:Packet 3
...
Host → Controller:Packet 10
Controller 已经通过 HCI_Number_Of_Completed_Packets event 报告完成了 6 个:
Num_Completed_Packets = 6
还有 4 个没有完成通知。
这时连接断开,Host 收到:
HCI_Disconnection_Complete event
Connection_Handle = 0x0001
那么 Host 应该认为剩下那 4 个未完成的数据包已经被 flush,不需要再等它们的 completed 通知。
4. flushed 是什么意思
这里的 flushed 可以理解为:
被清除
被丢弃
不会继续发送
不再占用 Controller buffer
它不表示这些数据已经成功送到对端设备。
恰恰相反,连接都已经断开了,未完成的数据通常应该视为没有可靠送达。
所以这里要特别注意:
flush ≠ 成功发送到对端
flush ≠ 对端应用层收到
flush ≠ GATT 写入成功
它只是说:
Controller 不再保留这些数据,对应 buffer 已经释放。
5. 对应 Controller buffer 已经释放
原文接着说:
and that the corresponding data buffers have been freed.
意思是:
Host 还应认为这些数据包对应的 Controller buffer 已经释放。
这句话是为了和前面 4.1 的 Host → Controller flow control 对上。
在 4.1 中,Host 每发送一个 HCI Data Packet,就会把 Controller 可用 buffer 计数减 1。
例如:
Controller 总共有 8 个 LE ACL buffer
Host 发出 8 个包后,free_buffer = 0
如果其中 4 个包还没 completed,正常情况下 Host 要等:
HCI_Number_Of_Completed_Packets event
才能把 free buffer 加回来。
但是如果连接断开了,Host 不需要再等这个事件。
Host 收到:
HCI_Disconnection_Complete event
后,就可以认为这条连接上未完成数据包对应的 Controller buffer 已经释放。
6. Controller 不需要再通过 completed 事件通知这些包
原文说:
A Controller does not have to notify the Host about this in an HCI_Number_Of_Completed_Packets or an HCI_Number_Of_Completed_Data_Blocks event before the disconnection event.
意思是:
Controller 不需要在断开事件之前,再专门通过 HCI_Number_Of_Completed_Packets 或 HCI_Number_Of_Completed_Data_Blocks event 通知 Host 这些数据包已经完成。
也就是说,Controller 不需要这样做:
先上报 HCI_Number_Of_Completed_Packets
告诉 Host 剩余未完成包都完成了
然后再上报 HCI_Disconnection_Complete
规范允许它直接上报:
HCI_Disconnection_Complete
Host 收到后自己清理这条连接上的 pending 数据和 buffer 计数。
这避免了断开连接时还要额外补很多 completed packets 事件。
7. Controller → Host 方向启用流控时的处理
第二段讲的是反方向:
Controller → Host
也就是 4.2 中提到的 Controller 到 Host 的 flow control。
原文说:
If flow control is also enabled in the direction from the Controller to the Host...
意思是:
如果 Controller → Host 方向也启用了流控,那么断开连接后也有类似处理。
前面 4.2 说过,Controller 向 Host 发送数据时,会消耗 Host buffer。Host 处理完成后,要用:
HCI_Host_Number_Of_Completed_Packets command
通知 Controller:
我这边某个 Connection_Handle 上的多少个 packet 已经处理完了,Host buffer 可以释放。
但是连接断开后,不需要再这样通知。
8. Controller 可以认为 Host 会释放这个 Handle 对应的 buffer
原文说:
the Controller may, after it has sent an HCI_Disconnection_Complete event, assume that the Host will flush its data buffers for the sent Handle
意思是:
Controller 发送 HCI_Disconnection_Complete event 后,可以认为 Host 会清理这个 Connection_Handle 对应的数据 buffer。
也就是说,Controller 不需要继续等待 Host 对这个 handle 发送:
HCI_Host_Number_Of_Completed_Packets command
因为这条连接已经没了,这个 handle 对应的数据包和 buffer 状态都应该被清理。
9. Host 不需要再发 HCI_Host_Number_Of_Completed_Packets command
原文最后说:
The Host does not have to notify the Controller about this in an HCI_Host_Number_Of_Completed_Packets command.
意思是:
Host 不需要再通过 HCI_Host_Number_Of_Completed_Packets command 告诉 Controller:我已经释放了这个连接相关的 Host buffer。
这和第一段是对称的。
可以这样理解:
Host → Controller 方向:
连接断开后,Controller 不需要再发 completed packets event。
Host 自己认为 Controller buffer 已释放。
Controller → Host 方向:
连接断开后,Host 不需要再发 host completed packets command。
Controller 自己认为 Host buffer 会释放。
10. 两个方向的断开行为对比
可以整理成这样:
| 方向 | 断开前谁发数据 | 谁的 buffer 被占用 | 断开后谁不用再通知 | Host/Controller 应怎么认为 |
|---|---|---|---|---|
| Host → Controller | Host 发给 Controller | Controller buffer | Controller 不必再发 HCI_Number_Of_Completed_Packets |
Host 认为未完成包已 flush,Controller buffer 已释放 |
| Controller → Host | Controller 发给 Host | Host buffer | Host 不必再发 HCI_Host_Number_Of_Completed_Packets |
Controller 认为 Host 会清理该 handle 的 buffer |
核心逻辑就是:
连接断开后,这个 Connection_Handle 相关的 pending data 和 buffer 计数都要清掉。
11. 为什么需要这个规则
因为连接断开时,很多数据可能还在排队。
例如 BLE OTA 发送中:
Host 已经往 Controller 塞了很多 ACL Data Packet
Controller 还没来得及通过空口全部发出去
连接突然断开
如果没有这个规则,Host 可能还在等:
HCI_Number_Of_Completed_Packets event
来释放 buffer 额度。
但是连接已经断开了,剩余数据不可能继续按原连接发送。
所以规范直接规定:
收到 HCI_Disconnection_Complete 后,Host 应当认为该连接未完成包已经 flush,buffer 已释放。
这样 Host 可以清理状态,避免 flow control 计数卡死。
12. completed 和 disconnection 的关系
前面 4.1 说:
packet completed = Controller 不再需要该 packet 对应的 buffer,并释放 buffer
通常 completed 会通过:
HCI_Number_Of_Completed_Packets event
通知 Host。
但是 4.3 补充了一个特殊场景:
连接断开时,不需要逐个 completed。
断开事件本身就隐含了:
这个 Connection_Handle 上未完成的数据包已经不再保留
对应 buffer 已经释放
所以可以理解为:
正常发送完成:通过 completed packets event 归还 buffer
连接断开:通过 disconnection complete 隐含清理 pending buffer
13. 对 BLE App 开发的实际意义
在 iOS / Android BLE 开发中,这部分能解释一些现象:
App 正在大量写入数据
突然收到断开连接回调
之前已经调用 write 的数据,不代表都已经到达对端
底层还没完成的数据可能已经被 flush
断开以后,不应该继续等待这些数据的底层完成
应该清理发送队列和连接状态
例如 BLE OTA 时:
App 已经发送到第 500 包
系统底层可能还有若干 HCI ACL Data Packet 排队
此时连接断开
这时不能认为:
第 500 包之前的数据都已经被对端成功处理
更严谨的理解是:
已经被应用层确认 / 协议层确认的数据才可靠
未确认的数据可能只是进入了本地 Host/Controller 队列
连接断开后,未完成的数据会被 flush
所以做 OTA 或大数据传输时,需要自己的业务确认机制,例如:
分包序号
ACK
CRC
断点续传
失败重传
最终校验
不能只依赖"App 调用了 write 成功"来判断对端已经收到。
14. 这部分的关键信息总结
14.1 HCI_Disconnection_Complete event 是清理连接状态的关键事件
Host 收到这个事件后,就知道某个 Connection_Handle 对应的连接已经断开。
14.2 Host → Controller 方向,未完成数据包视为 flushed
对于这个断开的 handle:
Host 已发给 Controller
但还没收到 completed 通知的数据包
Host 应认为它们已经被 flush。
14.3 flush 不等于发送成功
flushed 表示数据被清理、不再占用 buffer,不代表对端已经收到。
14.4 Controller buffer 视为已释放
Host 不需要继续等待这个 handle 的:
HCI_Number_Of_Completed_Packets event
或:
HCI_Number_Of_Completed_Data_Blocks event
来归还 buffer。
14.5 Controller 不需要在断开事件前补发 completed packets event
Controller 可以直接上报:
HCI_Disconnection_Complete event
Host 自己根据这个事件清理相关 pending 数据。
14.6 Controller → Host 方向也类似
如果 Controller → Host 方向启用了 flow control,Controller 发送断开事件后,可以认为 Host 会清理该 handle 的 buffer。
Host 不需要再发送:
HCI_Host_Number_Of_Completed_Packets command
15. 最核心的一句话
这一节可以总结为:
连接断开后,Connection_Handle 对应的未完成 HCI Data Packet 都应被视为已经清理;Host 不需要继续等待 Controller 的 completed packets event,Controller 也不需要继续等待 Host 的 host completed packets command,双方都应基于 HCI_Disconnection_Complete event 清理该连接相关的 buffer 和 flow control 状态。
对 BLE 数据传输来说,最重要的理解是:
断开连接时,底层未完成的数据会被 flush;flush 只是释放 buffer,不代表数据已经成功到达对端。