蓝牙HID(Human Interface Device) 的断开连接流程涉及从应用层到协议栈的多层交互。本文通过剖析Android Bluetooth协议栈代码,梳理从上层调用disconnect()
到最终物理链路断开的完整流程,涵盖状态检查、消息传递、L2CAP通道关闭、资源清理及回调通知等关键环节。流程中通过事件驱动机制协调各模块,确保安全断开并通知应用层状态变化。
一、流程概述
1.1 应用层触发断开
-
入口函数 :
btif_hd.cc
中的disconnect()
首先检查应用注册和设备状态。-
若条件不满足(如未注册或未启用),直接返回错误状态。
-
条件满足时调用
BTA_HdDisconnect()
发起断开请求。
-
1.2 BTA层消息传递
- BTA_HdDisconnect 通过
bta_sys_sendmsg()
发送BTA_HD_API_DISCONNECT_EVT
事件,触发状态机处理,而非直接操作硬件。
1.3 状态机处理断开事件
- 状态机
bta_hd_better_state_machine
根据当前状态(如BTA_HD_CONN_ST
)处理BTA_HD_API_DISCONNECT_EVT
,调用bta_hd_disconnect_act()
执行实际断开操作。
1.4 HID协议栈断开操作
-
HID_DevDisconnect() 验证设备状态后,调用
hidd_conn_disconnect()
关闭L2CAP通道:-
清理待发送数据(
osi_free(hd_cb.pending_data)
)。 -
通过
L2CA_DisconnectReq()
依次断开控制通道(ctrl_cid
)和中断通道(intr_cid
)。 -
更新连接状态为
HID_CONN_STATE_DISCONNECTING
。
-
1.5 底层通道关闭与资源释放
-
**hidd_l2cif_disconnect()**处理L2CAP断开:
- 若所有通道关闭(
ctrl_cid
和intr_cid
均为0),更新设备状态为HIDD_DEV_NO_CONN
,并通过回调通知上层(HID_DHOST_EVT_CLOSE
或HID_DHOST_EVT_VC_UNPLUG
)。
- 若所有通道关闭(
1.6 回调通知与资源清理
-
BTA层回调 :
bta_hd_cback()
根据事件类型(如HID_DHOST_EVT_CLOSE
)转发至btif_hd_upstreams_evt()
。 -
应用层处理:
-
正常断开:通知
BTHD_CONN_STATE_DISCONNECTED
,移除设备绑定信息(BTA_DmRemoveDevice()
或btif_hd_remove_device()
)。 -
虚拟线缆拔出:触发
vc_unplug_cb
,强制清理设备数据。
-
二、源码分析
disconnect
cpp
/packages/modules/Bluetooth/system/btif/src/btif_hd.cc
/*******************************************************************************
*
* Function disconnect
*
* Description Disconnects from host
*
* Returns bt_status_t
*
******************************************************************************/
static bt_status_t disconnect(void) {
log::verbose("");
if (!btif_hd_cb.app_registered) {
log::warn("application not yet registered");
return BT_STATUS_NOT_READY;
}
if (btif_hd_cb.status != BTIF_HD_ENABLED) {
log::warn("BT-HD not enabled, status={}", btif_hd_cb.status);
return BT_STATUS_NOT_READY;
}
BTA_HdDisconnect();
return BT_STATUS_SUCCESS;
}
断开与蓝牙主机的连接。在执行断开连接操作之前,先检查应用程序是否已经注册以及蓝牙 HID 设备(BT - HD)是否已经启用。若这两个条件都满足,会调用 BTA_HdDisconnect
函数来发起断开连接的请求;
BTA_HdDisconnect
cpp
/packages/modules/Bluetooth/system/bta/hd/bta_hd_api.cc
/*******************************************************************************
*
* Function BTA_HdDisconnect
*
* Description This function is called when host shall be disconnected
*
* Returns void
*
******************************************************************************/
void BTA_HdDisconnect(void) {
log::verbose("");
BT_HDR_RIGID* p_buf = (BT_HDR_RIGID*)osi_malloc(sizeof(BT_HDR_RIGID));
p_buf->event = BTA_HD_API_DISCONNECT_EVT;
bta_sys_sendmsg(p_buf);
}
该函数本身并不直接执行断开连接的实际动作,而是通过消息机制通知系统进行相应处理。
bta_hd_better_state_machine(BTA_HD_API_DISCONNECT_EVT)
cpp
packages/modules/Bluetooth/system/bta/hd/bta_hd_main.cc
static void bta_hd_better_state_machine(uint16_t event, tBTA_HD_DATA* p_data) {
switch (get_state()) {
case BTA_HD_INIT_ST:
...
break;
case BTA_HD_IDLE_ST:
switch (event) {
case BTA_HD_API_UNREGISTER_APP_EVT:
set_state(BTA_HD_INIT_ST);
bta_hd_unregister_act();
break;
case BTA_HD_API_CONNECT_EVT:
bta_hd_connect_act(p_data);
break;
...
case BTA_HD_CONN_ST:
switch (event) {
case BTA_HD_API_UNREGISTER_APP_EVT:
set_state(BTA_HD_TRANSIENT_TO_INIT_ST);
bta_hd_disconnect_act();
break;
case BTA_HD_API_DISCONNECT_EVT:
bta_hd_disconnect_act();
break;
...
bta_hd_disconnect_act
cpp
packages/modules/Bluetooth/system/bta/hd/bta_hd_act.cc
/*******************************************************************************
*
* Function bta_hd_disconnect_act
*
* Description Disconnect from device
*
* Returns void
*
******************************************************************************/
void bta_hd_disconnect_act() {
tHID_STATUS ret;
tBTA_HD cback_data;
log::verbose("");
ret = HID_DevDisconnect();
if (ret != HID_SUCCESS) {
log::warn("HID_DevDisconnect returned {}", ret);
return;
}
if (HID_DevGetDevice(&cback_data.conn.bda) == HID_SUCCESS) {
cback_data.conn.status = BTHD_CONN_STATE_DISCONNECTING;
bta_hd_cb.p_cback(BTA_HD_CONN_STATE_EVT, &cback_data);
}
}
执行与蓝牙设备断开连接的操作。首先调用 HID_DevDisconnect
函数尝试断开连接,然后检查断开连接的结果。如果断开连接成功,会获取设备地址并设置连接状态为 "正在断开连接",最后调用回调函数 bta_hd_cb.p_cback
通知上层连接状态的变化。
bta_hd_cb.p_cback(BTA_HD_CONN_STATE_EVT, &cback_data)

btif_hd_upstreams_evt(BTA_HD_CONN_STATE_EVT)
cpp
packages/modules/Bluetooth/system/btif/src/btif_hd.cc
/*******************************************************************************
*
* Function btif_hd_upstreams_evt
*
* Description Executes events in btif context
*
* Returns void
*
******************************************************************************/
static void btif_hd_upstreams_evt(uint16_t event, char* p_param) {
tBTA_HD* p_data = (tBTA_HD*)p_param;
log::verbose("event={}", dump_hd_event(event));
switch (event) {
...
case BTA_HD_CONN_STATE_EVT:
HAL_CBACK(bt_hd_callbacks, connection_state_cb,
(RawAddress*)&p_data->conn.bda,
(bthd_connection_state_t)p_data->conn.status);
break;
...
当接收到 BTA_HD_CONN_STATE_EVT
事件时,会调用回调函数来通知上层应用设备的连接状态发生了变化(BTHD_CONN_STATE_DISCONNECTING)。
HID_DevDisconnect
cpp
/packages/modules/Bluetooth/system/stack/hid/hidd_api.cc
/*******************************************************************************
*
* Function HID_DevDisconnect
*
* Description Disconnects from device
*
* Returns tHID_STATUS
*
******************************************************************************/
tHID_STATUS HID_DevDisconnect(void) {
if (!hd_cb.reg_flag) {
log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::
HIDD_ERR_NOT_REGISTERED_AT_DISCONNECT,
1);
return HID_ERR_NOT_REGISTERED;
}
if (!hd_cb.device.in_use) {
log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::
HIDD_ERR_DEVICE_NOT_IN_USE_AT_DISCONNECT,
1);
return HID_ERR_INVALID_PARAM;
}
if (hd_cb.device.state == HIDD_DEV_NO_CONN) {
/* If we are still trying to connect, just close the connection. */
if (hd_cb.device.conn.conn_state != HID_CONN_STATE_UNUSED) { // 说明设备正在尝试连接
tHID_STATUS ret = hidd_conn_disconnect();
hd_cb.device.conn.conn_state = HID_CONN_STATE_UNUSED;
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE,
HID_ERR_DISCONNECTING, NULL);
log_counter_metrics(
android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_DISCONNECTING,
1);
return ret;
}
// 确实没有连接
log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::
HIDD_ERR_NO_CONNECTION_AT_DISCONNECT,
1);
return HID_ERR_NO_CONNECTION;
}
return hidd_conn_disconnect();
}
在执行断开连接操作之前,会对设备的注册状态、使用状态和连接状态 进行检查。若检查通过,则调用 hidd_conn_disconnect
来实际执行断开连接操作。
hidd_conn_disconnect
cpp
packages/modules/Bluetooth/system/stack/hid/hidd_conn.cc
/*******************************************************************************
*
* Function hidd_conn_disconnect
*
* Description Disconnects existing HID connection
*
* Returns HID_SUCCESS
*
******************************************************************************/
tHID_STATUS hidd_conn_disconnect(void) {
log::verbose("");
// clean any outstanding data on intr
if (hd_cb.pending_data) {
osi_free(hd_cb.pending_data);
hd_cb.pending_data = NULL;
}
// 获取连接信息指针
tHID_CONN* p_hcon = &hd_cb.device.conn;
// 判断连接状态并执行断开操作
if ((p_hcon->ctrl_cid != 0) || (p_hcon->intr_cid != 0)) {
p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING;
/* Set l2cap idle timeout to 0 (so ACL link is disconnected
* immediately after last channel is closed) */
// 将 L2CAP 空闲超时时间设置为0,这样在最后一个通道关闭后,ACL 链路会立即断开
L2CA_SetIdleTimeoutByBdAddr(hd_cb.device.addr, 0, BT_TRANSPORT_BR_EDR);
if (p_hcon->intr_cid) {
hidd_l2cif_disconnect(p_hcon->intr_cid);
} else if (p_hcon->ctrl_cid) {
hidd_l2cif_disconnect(p_hcon->ctrl_cid);
}
} else {
log::warn("already disconnected");
p_hcon->conn_state = HID_CONN_STATE_UNUSED;
}
return (HID_SUCCESS);
}
在执行断开操作前,会清理可能存在的待处理数据,然后根据连接的控制通道 ID(ctrl_cid
)和中断通道 ID(intr_cid
)的情况,执行相应的断开连接步骤,并更新连接状态。若连接已经断开,则更新状态。
hidd_l2cif_disconnect
cpp
packages/modules/Bluetooth/system/stack/hid/hidd_conn.cc
static void hidd_l2cif_disconnect(uint16_t cid) {
L2CA_DisconnectReq(cid);
log::verbose("cid={:04x}", cid);
tHID_CONN* p_hcon = &hd_cb.device.conn;
if (p_hcon->conn_state == HID_CONN_STATE_UNUSED ||
(p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) {
log::warn("unknown cid");
return;
}
if (cid == p_hcon->ctrl_cid) {
p_hcon->ctrl_cid = 0;
} else {
p_hcon->intr_cid = 0;
// now disconnect CTRL
L2CA_DisconnectReq(p_hcon->ctrl_cid);
if (bluetooth::common::init_flags::
clear_hidd_interrupt_cid_on_disconnect_is_enabled()) {
p_hcon->ctrl_cid = 0;
}
}
// 更新连接状态与回调通知
if ((p_hcon->ctrl_cid == 0) && (p_hcon->intr_cid == 0)) {
log::verbose("INTR and CTRL disconnected");
hd_cb.device.state = HIDD_DEV_NO_CONN;
p_hcon->conn_state = HID_CONN_STATE_UNUSED;
if (hd_cb.pending_vc_unplug) {
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_VC_UNPLUG,
p_hcon->disc_reason, NULL);
hd_cb.pending_vc_unplug = FALSE;
} else {
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE,
p_hcon->disc_reason, NULL);
}
}
}
断开指定的 L2CAP通道连接。先调用 L2CA_DisconnectReq
尝试断开连接,然后根据连接状态判断是否为未知通道 ID。若通道 ID 有效,根据通道类型(控制通道或中断通道)断开相应通道连接,并在两个通道都断开时更新设备连接状态,调用回调函数通知上层连接已断开。
情况1:hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_VC_UNPLUG,p_hcon->disc_reason, NULL)
bta_hd_cback(HID_DHOST_EVT_VC_UNPLUG)
cpp
/*******************************************************************************
*
* Function bta_hd_cback
*
* Description BTA HD callback function
*
* Returns void
*
******************************************************************************/
static void bta_hd_cback(const RawAddress& bd_addr, uint8_t event,
uint32_t data, BT_HDR* pdata) {
tBTA_HD_CBACK_DATA* p_buf = NULL;
uint16_t sm_event = BTA_HD_INVALID_EVT;
log::verbose("event={}", event);
switch (event) {
...
case HID_DHOST_EVT_CLOSE:
sm_event = BTA_HD_INT_CLOSE_EVT;
break;
...
case HID_DHOST_EVT_VC_UNPLUG:
sm_event = BTA_HD_INT_VC_UNPLUG_EVT;
break;
...
}
if (sm_event != BTA_HD_INVALID_EVT &&
(p_buf = (tBTA_HD_CBACK_DATA*)osi_malloc(sizeof(tBTA_HD_CBACK_DATA) +
sizeof(BT_HDR))) != NULL) {
p_buf->hdr.event = sm_event;
p_buf->addr = bd_addr;
p_buf->data = data;
p_buf->p_data = pdata;
bta_sys_sendmsg(p_buf);
}
}
bta_hd_better_state_machine(BTA_HD_INT_VC_UNPLUG_EVT)
cpp
case BTA_HD_INT_VC_UNPLUG_EVT:
set_state(BTA_HD_IDLE_ST);
bta_hd_vc_unplug_done_act(p_data);
break;
bta_hd_vc_unplug_done_act
cpp
packages/modules/Bluetooth/system/bta/hd/bta_hd_act.cc
/*******************************************************************************
*
* Function bta_hd_vc_unplug_done_act
*
* Description
*
* Returns void
*
******************************************************************************/
void bta_hd_vc_unplug_done_act(tBTA_HD_DATA* p_data) {
tBTA_HD_CBACK_DATA* p_cback = (tBTA_HD_CBACK_DATA*)p_data;
tBTA_HD cback_data;
log::verbose("");
bta_sys_conn_close(BTA_ID_HD, 1, p_cback->addr); // 关闭系统连接
HID_DevUnplugDevice(p_cback->addr); // 设备拔出操作
// 设置回调数据并调用回调函数
cback_data.conn.bda = p_cback->addr;
bta_hd_cb.bd_addr = p_cback->addr;
(*bta_hd_cb.p_cback)(BTA_HD_VC_UNPLUG_EVT, &cback_data);
}
处理 HID 设备虚拟线缆(VC)拔出完成后的操作。完成关闭系统连接、执行设备拔出操作,并通过回调函数通知上层设备虚拟线缆已拔出。
bta_sys_conn_close
cpp
packages/modules/Bluetooth/system/bta/sys/bta_sys_conn.cc
/*******************************************************************************
*
* Function bta_sys_conn_close
*
* Description Called by BTA subsystems when a connection to the service
* is closed
*
*
* Returns void
*
******************************************************************************/
void bta_sys_conn_close(tBTA_SYS_ID id, uint8_t app_id,
const RawAddress& peer_addr) {
if (bta_sys_cb.prm_cb) {
bta_sys_cb.prm_cb(BTA_SYS_CONN_CLOSE, id, app_id, peer_addr);
}
if (bta_sys_cb.ppm_cb) {
bta_sys_cb.ppm_cb(BTA_SYS_CONN_CLOSE, id, app_id, peer_addr);
}
}
根据配置情况调用两个回调函数 bta_sys_cb.prm_cb
和 bta_sys_cb.ppm_cb
,向这些回调函数传递连接关闭的事件信息以及相关的参数,如系统 ID、应用 ID 和对端设备地址。
HID_DevUnplugDevice
cpp
packages/modules/Bluetooth/system/stack/hid/hidd_api.cc
/*******************************************************************************
*
* Function HID_DevUnplugDevice
*
* Description Unplugs virtual cable from given host
*
* Returns tHID_STATUS
*
******************************************************************************/
tHID_STATUS HID_DevUnplugDevice(const RawAddress& addr) {
if (hd_cb.device.addr == addr) {
hd_cb.device.in_use = FALSE;
hd_cb.device.conn.conn_state = HID_CONN_STATE_UNUSED;
hd_cb.device.conn.ctrl_cid = 0;
hd_cb.device.conn.intr_cid = 0;
}
return HID_SUCCESS;
}
从给定的主机上拔出虚拟线缆,通过检查设备地址,将设备的使用状态设置为未使用,并将连接状态相关的控制通道 ID 和中断通道 ID 设置为 0。
(*bta_hd_cb.p_cback)(BTA_HD_VC_UNPLUG_EVT, &cback_data)
cpp
/*******************************************************************************
*
* Function btif_hd_upstreams_evt
*
* Description Executes events in btif context
*
* Returns void
*
******************************************************************************/
static void btif_hd_upstreams_evt(uint16_t event, char* p_param) {
tBTA_HD* p_data = (tBTA_HD*)p_param;
log::verbose("event={}", dump_hd_event(event));
switch (event) {
...
case BTA_HD_VC_UNPLUG_EVT:
// 检查连接情况并执行清理操作
HAL_CBACK(bt_hd_callbacks, connection_state_cb,
(RawAddress*)&p_data->conn.bda, BTHD_CONN_STATE_DISCONNECTED);
// 检查连接情况并执行清理操作
if (bta_dm_check_if_only_hd_connected(p_data->conn.bda)) { // 检查指定地址的设备是否仅连接了 HID 配置文件
log::verbose("Removing bonding as only HID profile connected");
BTA_DmRemoveDevice(p_data->conn.bda);
} else {
RawAddress* bd_addr = (RawAddress*)&p_data->conn.bda;
log::verbose("Only removing HID data as some other profiles connected");
btif_hd_remove_device(*bd_addr);
}
// 调用虚拟线缆拔出回调函数
HAL_CBACK(bt_hd_callbacks, vc_unplug_cb);
break;
...
BTA_HD_VC_UNPLUG_EVT
事件表示蓝牙 HID 设备的虚拟线缆(VC)已拔出。此事件处理主要包括更新连接状态、根据连接情况执行不同的清理操作,以及调用相应的回调函数通知上层。
btif_hd_remove_device
cpp
packages/modules/Bluetooth/system/btif/src/btif_hd.cc
/*******************************************************************************
*
* Function btif_hd_remove_device
*
* Description Removes plugged device
*
* Returns void
*
******************************************************************************/
void btif_hd_remove_device(RawAddress bd_addr) {
BTA_HdRemoveDevice(bd_addr);
btif_storage_remove_hidd(&bd_addr);
}
BTA_HdRemoveDevice
cpp
packages/modules/Bluetooth/system/bta/hd/bta_hd_api.cc
/*******************************************************************************
*
* Function BTA_HdRemoveDevice
*
* Description This function is called when a device is virtually uncabled
*
* Returns void
*
******************************************************************************/
void BTA_HdRemoveDevice(const RawAddress& addr) {
log::verbose("");
tBTA_HD_DEVICE_CTRL* p_buf =
(tBTA_HD_DEVICE_CTRL*)osi_malloc(sizeof(tBTA_HD_DEVICE_CTRL));
p_buf->hdr.event = BTA_HD_API_REMOVE_DEVICE_EVT;
p_buf->addr = addr;
bta_sys_sendmsg(p_buf);
}
在设备的虚拟线缆断开(即设备被视为移除)时被调用。将该消息发送出去,以触发后续的设备移除操作。
bta_hd_better_state_machine(BTA_HD_API_REMOVE_DEVICE_EVT)
cpp
packages/modules/Bluetooth/system/bta/hd/bta_hd_main.cc
case BTA_HD_CONN_ST:
switch (event) {
case BTA_HD_API_UNREGISTER_APP_EVT:
set_state(BTA_HD_TRANSIENT_TO_INIT_ST);
bta_hd_disconnect_act();
break;
case BTA_HD_API_DISCONNECT_EVT:
bta_hd_disconnect_act();
break;
case BTA_HD_API_ADD_DEVICE_EVT:
bta_hd_add_device_act(p_data);
break;
case BTA_HD_API_REMOVE_DEVICE_EVT:
bta_hd_remove_device_act(p_data);
break;
bta_hd_remove_device_act
cpp
packages/modules/Bluetooth/system/bta/hd/bta_hd_act.cc
/*******************************************************************************
*
* Function bta_hd_remove_device_act
*
* Description
*
* Returns void
*
******************************************************************************/
void bta_hd_remove_device_act(tBTA_HD_DATA* p_data) {
tBTA_HD_DEVICE_CTRL* p_ctrl = (tBTA_HD_DEVICE_CTRL*)p_data;
log::verbose("");
HID_DevUnplugDevice(p_ctrl->addr);
}
处理移除蓝牙 HID 设备的操作。调用 HID_DevUnplugDevice
函数来执行设备的虚拟线缆拔出操作。HID_DevUnplugDevice前文有分析。
btif_storage_remove_hidd
cpp
packages/modules/Bluetooth/system/btif/src/btif_profile_storage.cc
/*******************************************************************************
*
* Function btif_storage_remove_hidd
*
* Description Removes hidd bonded device info from nvram
*
* Returns BT_STATUS_SUCCESS
*
******************************************************************************/
bt_status_t btif_storage_remove_hidd(RawAddress* remote_bd_addr) {
btif_config_remove(remote_bd_addr->ToString(),
BTIF_STORAGE_KEY_HID_DEVICE_CABLED);
return BT_STATUS_SUCCESS;
}
从非易失性随机访问存储器(NVRAM)中移除与 HID已配对设备相关的信息。
情况2:hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, p_hcon->disc_reason, NULL)
bta_hd_better_state_machine(BTA_HD_INT_CLOSE_EVT)
cpp
case BTA_HD_CONN_ST:
switch (event) {
...
case BTA_HD_INT_CLOSE_EVT:
set_state(BTA_HD_IDLE_ST);
bta_hd_close_act(p_data);
break;
...
bta_hd_close_act
cpp
packages/modules/Bluetooth/system/bta/hd/bta_hd_act.cc
/*******************************************************************************
*
* Function bta_hd_close_act
*
* Description
*
* Returns void
*
******************************************************************************/
void bta_hd_close_act(tBTA_HD_DATA* p_data) {
tBTA_HD_CBACK_DATA* p_cback = (tBTA_HD_CBACK_DATA*)p_data;
tBTA_HD cback_data;
tBTA_HD_EVT cback_event = BTA_HD_CLOSE_EVT;
log::verbose("");
// 关闭系统连接
bta_sys_conn_close(BTA_ID_HD, 1, p_cback->addr);
// 检查虚拟线缆拔出标志并执行相应操作
if (bta_hd_cb.vc_unplug) {
bta_hd_cb.vc_unplug = FALSE;
HID_DevUnplugDevice(p_cback->addr);
cback_event = BTA_HD_VC_UNPLUG_EVT;
}
// 设置回调数据并调用回调函数
cback_data.conn.bda = p_cback->addr;
bta_hd_cb.bd_addr = RawAddress::kEmpty;
bta_hd_cb.p_cback(cback_event, &cback_data);
}
处理蓝牙 HID 设备的关闭操作。关闭系统连接,根据 bta_hd_cb.vc_unplug
标志决定是否执行设备的虚拟线缆拔出操作,最后调用回调函数通知上层设备关闭或虚拟线缆拔出事件。
bta_hd_cb.p_cback(BTA_HD_CLOSE_EVT)
cpp
packages/modules/Bluetooth/system/btif/src/btif_hd.cc
case BTA_HD_CLOSE_EVT:
if (btif_hd_cb.forced_disc) { // 意味着设备是被强制断开连接的
RawAddress* addr = (RawAddress*)&p_data->conn.bda;
log::warn("remote device was forcefully disconnected");
btif_hd_remove_device(*addr);
btif_hd_cb.forced_disc = FALSE;
break;
}
// 正常断开情况处理
HAL_CBACK(bt_hd_callbacks, connection_state_cb,
(RawAddress*)&p_data->conn.bda, BTHD_CONN_STATE_DISCONNECTED);
break;
BTA_HD_CLOSE_EVT
事件代表蓝牙 HID 设备关闭连接的事件。代码根据 btif_hd_cb.forced_disc
标志的状态,执行不同的操作,要么强制移除设备,要么通知上层设备连接已断开。
正常断开的情况会将设备地址和断开连接的状态 BTHD_CONN_STATE_DISCONNECTED
传递给该回调函数,从而通知上层设备连接已断开。
三、时序图
