那个网站可以做软件出售的,双鸭山建设网站,服装设计公司属于什么行业类型,做网站用vps还是虚拟主机本文基于 Android 蓝牙 HID#xff08;Human Interface Device#xff09;Host 模块的源码#xff0c;深入解析 HID 设备断开连接的完整流程。重点覆盖从应用层触发断开请求#xff0c;到 BTIF 层#xff08;接口适配层#xff09;状态校验与异步传递、BTA 层#xff08…本文基于 Android 蓝牙 HIDHuman Interface DeviceHost 模块的源码深入解析 HID 设备断开连接的完整流程。重点覆盖从应用层触发断开请求到 BTIF 层接口适配层状态校验与异步传递、BTA 层协议栈适配层状态机驱动、HID 协议栈执行物理断连最终通过 BTA/BTIF 层回调通知应用层的全链路逻辑。揭示各层级如何通过状态校验、事件传递、资源清理和状态同步确保断开操作的健壮性、可诊断性和用户体验的一致性。
一、流程概述
蓝牙 HID Host 模块的断开连接流程可分为6 大核心环节贯穿应用层、BTIF 层、BTA 层和 HID 协议栈各层级协作完成状态校验、物理断连和状态通知
1.1 应用层触发断开请求BTIF 层disconnect 函数 状态校验BTIF 层首先校验模块状态是否已禁用 / 禁用中和设备状态是否存在、是否已连接 / 连接中避免无效操作。 异步传递通过btif_transfer_context将断开请求BTIF_HH_DISCONNECT_REQ_EVT异步传递至 BTIF 线程确保操作在统一上下文执行。
1.2 BTIF 层发起断开BTIF 层btif_hh_handle_evt/btif_hh_disconnect 事件处理BTIF 线程接收BTIF_HH_DISCONNECT_REQ_EVT后调用btif_hh_disconnect触发断开。 底层接口调用通过BTA_HhClose通知 BTA 层执行断开传递设备句柄dev_handle。
1.3 BTA 层状态机驱动BTA 层BTA_HhClose→状态机→bta_hh_api_disc_act 事件封装BTA 层将断开请求封装为BTA_HH_API_CLOSE_EVT事件通过消息队列传递至状态机。 设备类型分发根据设备类型LE / 传统蓝牙调用bta_hh_le_api_disc_act或直接调用 HID 协议栈接口HID_HostCloseDev执行物理断连。
1.4 HID 协议栈执行物理断开HID 协议栈HID_HostCloseDev→hidh_conn_disconnect 多级校验校验模块注册状态、设备句柄有效性、连接状态确保断开操作仅作用于合法已连接设备。 物理断连关闭 L2CAP 控制 / 中断通道优先断开中断通道设置 ACL 链路空闲超时为 0 触发立即断开清理定时器并重试标志。
1.5 BTA 层处理断开完成事件BTA 层bta_hh_cback→状态机→bta_hh_close_act 事件转换HID 协议栈通过HID_HDEV_EVT_CLOSE通知断开完成BTA 层将其转换为状态机事件BTA_HH_INT_CLOSE_EVT。 资源清理与通知解析断开原因L2CAP 层 / 协议层错误码更新连接计数通知角色管理器协同清理触发上层回调BTA_HH_CLOSE_EVT。
1.6 BTIF 层同步状态并通知应用层BTIF 层bte_hh_evt→btif_hh_upstreams_evt 上下文转移BTA 层通过bte_hh_evt将BTA_HH_CLOSE_EVT事件异步传递至 BTIF 线程。 应用层通知BTIF 层查找目标设备更新本地状态BTHH_CONN_STATE_DISCONNECTED通过HAL_CBACK触发应用层回调通知设备已断开预通知→最终通知。
二、源码解析
disconnect
packages/modules/Bluetooth/system/btif/src/btif_hh.cc
/********************************************************************************* Function disconnect** Description disconnect from hid device** Returns bt_status_t*******************************************************************************/
static bt_status_t disconnect(RawAddress* bd_addr) {CHECK_BTHH_INIT();log::verbose(BTHH);btif_hh_device_t* p_dev;tAclLinkSpec link_spec;// 1. 状态校验模块级if (btif_hh_cb.status BTIF_HH_DISABLED ||btif_hh_cb.status BTIF_HH_DISABLING) {log::warn(Error, HH status {}, btif_hh_cb.status);return BT_STATUS_UNHANDLED;}// 2. 设备存在性检查link_spec.addrt.bda *bd_addr;// Todo: fill with params receivedlink_spec.addrt.type BLE_ADDR_PUBLIC;link_spec.transport BT_TRANSPORT_AUTO;p_dev btif_hh_find_connected_dev_by_bda(link_spec);if (!p_dev) {log::error(Error, device {} not opened.,ADDRESS_TO_LOGGABLE_CSTR(*bd_addr));return BT_STATUS_UNHANDLED;}// 3. 设备状态校验设备级if (p_dev-dev_status BTHH_CONN_STATE_DISCONNECTED ||p_dev-dev_status BTHH_CONN_STATE_DISCONNECTING) {log::error(Error, device {} already disconnected.,ADDRESS_TO_LOGGABLE_CSTR(*bd_addr));return BT_STATUS_DONE; // 已断开或断开中无需操作} else if (p_dev-dev_status BTHH_CONN_STATE_CONNECTING) {log::error(Error, device {} is busy with (dis)connecting.,ADDRESS_TO_LOGGABLE_CSTR(*bd_addr));return BT_STATUS_BUSY; // 设备正忙连接中无法断开}// 4. 异步传递断开请求return btif_transfer_context(btif_hh_handle_evt, BTIF_HH_DISCONNECT_REQ_EVT,(char*)link_spec, sizeof(tAclLinkSpec), NULL);
}
蓝牙 HID Host 模块中断开 HID 设备连接的核心接口主要负责连接状态校验、设备存在性检查并通过异步机制触发后续断开操作。核心流程: btif_transfer_context(BTIF_HH_DISCONNECT_REQ_EVT)
packages/modules/Bluetooth/system/btif/src/btif_hh.cc
/********************************************************************************* Function btif_hh_handle_evt** Description Switches context for immediate callback** Returns void*******************************************************************************/static void btif_hh_handle_evt(uint16_t event, char* p_param) {CHECK(p_param ! nullptr);tAclLinkSpec* p_link_spec (tAclLinkSpec*)p_param;switch (event) {...case BTIF_HH_DISCONNECT_REQ_EVT: {log::debug(Disconnect request received remote:{},ADDRESS_TO_LOGGABLE_CSTR((*p_link_spec)));btif_hh_disconnect(p_link_spec);HAL_CBACK(bt_hh_callbacks, connection_state_cb, p_link_spec-addrt.bda,BTHH_CONN_STATE_DISCONNECTING);} break;...
btif_hh_disconnect
packages/modules/Bluetooth/system/btif/src/btif_hh.cc
/********************************************************************************* Function btif_hh_disconnect** Description disconnection initiated from the BTIF thread context** Returns void*******************************************************************************/
void btif_hh_disconnect(tAclLinkSpec* link_spec) {CHECK(link_spec ! nullptr);const btif_hh_device_t* p_dev btif_hh_find_connected_dev_by_bda(*link_spec);if (p_dev nullptr) {log::debug(Unable to disconnect unknown HID device:{},ADDRESS_TO_LOGGABLE_CSTR((*link_spec)));return;}log::debug(Disconnect and close request for HID device:{},ADDRESS_TO_LOGGABLE_CSTR((*link_spec)));BTA_HhClose(p_dev-dev_handle);
}校验设备存在性并调用底层接口BTA_HhClose触发物理层断开确保断开操作的合法性和有序性。
BTA_HhClose
/packages/modules/Bluetooth/system/bta/hh/bta_hh_api.cc
/********************************************************************************* Function BTA_HhClose** Description Disconnect a connection.** Returns void*******************************************************************************/
void BTA_HhClose(uint8_t dev_handle) {BT_HDR* p_buf (BT_HDR*)osi_calloc(sizeof(BT_HDR));p_buf-event BTA_HH_API_CLOSE_EVT; // 事件类型API 层断开请求p_buf-layer_specific (uint16_t)dev_handle;bta_sys_sendmsg(p_buf);
}
蓝牙 HID Host 模块中BTA 层的断开连接接口其核心作用是将上层如 BTIF 模块的断开请求封装为事件消息并通过系统消息队列异步传递给 HID 状态机触发实际的断开逻辑。
bta_hh_better_state_machine(BTA_HH_API_CLOSE_EVT) ...case BTA_HH_CONN_ST:switch (event) {case BTA_HH_API_CLOSE_EVT:bta_hh_api_disc_act(p_cb, p_data);break;...
bta_hh_api_disc_act
packages/modules/Bluetooth/system/bta/hh/bta_hh_act.cc
/********************************************************************************* Function bta_hh_api_disc_act** Description HID Host initiate a disconnection.*** Returns void*******************************************************************************/
void btif_hh_remove_device(tAclLinkSpec link_spec);
void bta_hh_api_disc_act(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) {CHECK(p_cb ! nullptr);// 设备类型判断LE vs 传统蓝牙if (p_cb-is_le_device) {log::debug(Host initiating close to le device:{},ADDRESS_TO_LOGGABLE_CSTR(p_cb-link_spec));bta_hh_le_api_disc_act(p_cb);} else { // 传统蓝牙设备断开逻辑const uint8_t hid_handle (p_data ! nullptr) ? static_castuint8_t(p_data-hdr.layer_specific): p_cb-hid_handle;tHID_STATUS status HID_HostCloseDev(hid_handle); // 关闭指定设备的连接// 结果处理与上层回调if (status ! HID_SUCCESS) {log::warn(Failed closing classic device:{} status:{},ADDRESS_TO_LOGGABLE_CSTR(p_cb-link_spec),hid_status_text(status));} else {log::debug(Host initiated close to classic device:{},ADDRESS_TO_LOGGABLE_CSTR(p_cb-link_spec));}tBTA_HH bta_hh {.dev_status {.status (status HID_SUCCESS) ? BTA_HH_OK : BTA_HH_ERR,.handle hid_handle},};(*bta_hh_cb.p_cback)(BTA_HH_CLOSE_EVT, bta_hh);}
}
根据设备类型LE 或传统蓝牙分发断开请求调用底层协议栈接口关闭连接并通过回调通知上层断开结果。
HID_HostCloseDev
packages/modules/Bluetooth/system/stack/hid/hidh_api.cc
/********************************************************************************* Function HID_HostCloseDev** Description This function disconnects the device.** Returns void*******************************************************************************/
tHID_STATUS HID_HostCloseDev(uint8_t dev_handle) {// 1. 模块注册状态校验if (!hh_cb.reg_flag) return (HID_ERR_NOT_REGISTERED);// 2. 设备句柄有效性校验if ((dev_handle HID_HOST_MAX_DEVICES) ||(!hh_cb.devices[dev_handle].in_use)) {log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::HIDH_ERR_INVALID_PARAM_AT_HOST_CLOSE_DEV,1);return HID_ERR_INVALID_PARAM;}// 3. 设备连接状态校验if (hh_cb.devices[dev_handle].state ! HID_DEV_CONNECTED) {log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::HIDH_ERR_NO_CONNECTION_AT_HOST_CLOSE_DEV,1);return HID_ERR_NO_CONNECTION;}// 4. 清理准备取消定时器与禁止重连alarm_cancel(hh_cb.devices[dev_handle].conn.process_repage_timer);hh_cb.devices[dev_handle].conn_tries HID_HOST_MAX_CONN_RETRY 1;// 5. 执行底层断开操作return hidh_conn_disconnect(dev_handle);
}负责多级状态校验和连接资源清理确保断开操作仅作用于合法、已连接的设备。
核心逻辑可概括为校验模块状态 → 校验设备句柄 → 校验连接状态 → 清理准备 → 执行断开。
hidh_conn_disconnect
packages/modules/Bluetooth/system/stack/hid/hidh_conn.cc
/********************************************************************************* Function hidh_conn_disconnect** Description This function disconnects a connection.** Returns true if disconnect started, false if already disconnected*******************************************************************************/
tHID_STATUS hidh_conn_disconnect(uint8_t dhandle) {// 1. 获取连接结构体tHID_CONN* p_hcon hh_cb.devices[dhandle].conn;// 2. 通道存在性检查if ((p_hcon-ctrl_cid ! 0) || (p_hcon-intr_cid ! 0)) { // 存在有效通道执行断开逻辑// 3. 标记断开中状态p_hcon-conn_state HID_CONN_STATE_DISCONNECTING;// 4. 设置 ACL 链路立即断开/* Set l2cap idle timeout to 0 (so ACL link is disconnected* immediately after last channel is closed) */L2CA_SetIdleTimeoutByBdAddr(hh_cb.devices[dhandle].addr, 0,BT_TRANSPORT_BR_EDR);// 5. 断开 L2CAP 通道中断→控制/* Disconnect both interrupt and control channels */if (p_hcon-intr_cid)hidh_l2cif_disconnect(p_hcon-intr_cid);else if (p_hcon-ctrl_cid)hidh_l2cif_disconnect(p_hcon-ctrl_cid);BTM_LogHistory(kBtmLogTag, hh_cb.devices[dhandle].addr, Disconnecting,local initiated);} else { // 无通道标记为未使用p_hcon-conn_state HID_CONN_STATE_UNUSED;}return HID_SUCCESS;
}负责关闭控制 / 中断通道、释放 ACL 链路并更新连接状态。
调用 L2CAP 接口 L2CA_SetIdleTimeoutByBdAddr将目标设备的 ACL 链路空闲超时时间设为 0。
作用ACL 链路是 L2CAP 通道的物理承载当最后一个 L2CAP 通道关闭后空闲超时时间为 0 可触发 ACL 链路立即断开避免残留的物理连接占用资源。
优先断开中断通道HID 设备通常使用两个 L2CAP 通道 控制通道ctrl_cid用于传输 HID 协议命令如设备配置。 中断通道intr_cid用于实时数据上报如键盘按键、鼠标移动。
中断通道的实时性要求更高优先断开可减少数据残留避免断开过程中仍有数据上报导致的状态混乱。
hidh_l2cif_disconnect
packages/modules/Bluetooth/system/stack/hid/hidh_conn.cc
static void hidh_l2cif_disconnect(uint16_t l2cap_cid) {// 1. 触发 L2CAP 层断开请求L2CA_DisconnectReq(l2cap_cid);// 2. 查找设备句柄dhandle/* Find CCB based on CID */const uint8_t dhandle find_conn_by_cid(l2cap_cid);if (dhandle kHID_HOST_MAX_DEVICES) {log::warn(HID-Host Rcvd L2CAP disc cfm, unknown CID: 0x{:x}, l2cap_cid);return;}// 3. 清理通道状态控制 / 中断通道tHID_CONN* p_hcon hh_cb.devices[dhandle].conn;if (l2cap_cid p_hcon-ctrl_cid) {p_hcon-ctrl_cid 0; // 控制通道断开清除 CID} else {p_hcon-intr_cid 0; // 中断通道断开清除 CIDif (p_hcon-ctrl_cid) { // 若控制通道仍存在主动断开log::verbose(HID-Host Initiating L2CAP Ctrl disconnection);L2CA_DisconnectReq(p_hcon-ctrl_cid);p_hcon-ctrl_cid 0;}}// 4. 所有通道断开后的状态更新与通知if ((p_hcon-ctrl_cid 0) (p_hcon-intr_cid 0)) {hh_cb.devices[dhandle].state HID_DEV_NO_CONN;p_hcon-conn_state HID_CONN_STATE_UNUSED;BTM_LogHistory(kBtmLogTag, hh_cb.devices[dhandle].addr, Disconnected);hh_cb.callback(dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE,p_hcon-disc_reason, NULL); // 通知上层断开完成}
}
负责触发 L2CAP 层断开请求、清理通道状态并在所有通道断开后通知上层完成断开。
核心逻辑概括为触发 L2CAP 断开 → 查找设备 → 清理通道状态 → 同步断开关联通道 → 更新状态并通知上层。 bta_hh_cback(HID_HDEV_EVT_CLOSE)
packages/modules/Bluetooth/system/bta/hh/bta_hh_act.cc
/********************************************************************************* Function bta_hh_cback** Description BTA HH callback function.*** Returns void*******************************************************************************/
static void bta_hh_cback(uint8_t dev_handle, const RawAddress addr,uint8_t event, uint32_t data, BT_HDR* pdata) {uint16_t sm_event BTA_HH_INVALID_EVT;uint8_t xx 0;log::verbose(HID_event [{}], bta_hh_hid_event_name(event));switch (event) {case HID_HDEV_EVT_OPEN:sm_event BTA_HH_INT_OPEN_EVT;break;case HID_HDEV_EVT_CLOSE:sm_event BTA_HH_INT_CLOSE_EVT;break;case HID_HDEV_EVT_INTR_DATA:sm_event BTA_HH_INT_DATA_EVT;break;case HID_HDEV_EVT_HANDSHAKE:sm_event BTA_HH_INT_HANDSK_EVT;break;case HID_HDEV_EVT_CTRL_DATA:sm_event BTA_HH_INT_CTRL_DATA;break;case HID_HDEV_EVT_RETRYING:break;case HID_HDEV_EVT_INTR_DATC:case HID_HDEV_EVT_CTRL_DATC:/* Unhandled events: Free buffer for DATAC */osi_free_and_reset((void**)pdata);break;case HID_HDEV_EVT_VC_UNPLUG:for (xx 0; xx BTA_HH_MAX_DEVICE; xx) {if (bta_hh_cb.kdev[xx].hid_handle dev_handle) {bta_hh_cb.kdev[xx].vp true;break;}}break;}if (sm_event ! BTA_HH_INVALID_EVT) {tBTA_HH_CBACK_DATA* p_buf (tBTA_HH_CBACK_DATA*)osi_malloc(sizeof(tBTA_HH_CBACK_DATA) sizeof(BT_HDR));p_buf-hdr.event sm_event;p_buf-hdr.layer_specific (uint16_t)dev_handle;p_buf-data data;p_buf-link_spec.addrt.bda addr;p_buf-link_spec.addrt.type BLE_ADDR_PUBLIC;p_buf-link_spec.transport BT_TRANSPORT_BR_EDR;p_buf-p_data pdata;bta_sys_sendmsg(p_buf);}
}
HID_HDEV_EVT_CLOSE 事件的处理是蓝牙 HID Host 断开流程中底层协议栈向 BTA 层传递断开完成信号的关键环节。其核心作用是将 HID 协议栈的断开完成事件HID_HDEV_EVT_CLOSE转换为 BTA 层状态机可识别的内部事件BTA_HH_INT_CLOSE_EVT并通过消息机制触发 BTA 层的状态更新和上层通知。
bta_hh_better_state_machineBTA_HH_INT_CLOSE_EVT ...case BTA_HH_CONN_ST:switch (event) {...case BTA_HH_INT_CLOSE_EVT:p_cb-state BTA_HH_IDLE_ST;bta_hh_close_act(p_cb, p_data);break;...
bta_hh_close_act
packages/modules/Bluetooth/system/bta/hh/bta_hh_act.cc
/********************************************************************************* Function bta_hh_close_act** Description HID Host process a close event*** Returns void*******************************************************************************/
void bta_hh_close_act(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) {tBTA_HH_CBDATA disc_dat {BTA_HH_OK, 0};// 1. 解析断开原因核心诊断信息uint32_t reason p_data-hid_cback.data; /* Reason for closing (32-bit) */const bool l2cap_conn_fail reason HID_L2CAP_CONN_FAIL;const bool l2cap_req_fail reason HID_L2CAP_REQ_FAIL;const bool l2cap_cfg_fail reason HID_L2CAP_CFG_FAIL;const tHID_STATUS hid_status static_casttHID_STATUS(reason 0xff); // HID状态码低8位// 2. 确定事件类型虚拟拔插 vs 正常断开/* if HID_HDEV_EVT_VC_UNPLUG was received, report BTA_HH_VC_UNPLUG_EVT */uint16_t event p_cb-vp ? BTA_HH_VC_UNPLUG_EVT : BTA_HH_CLOSE_EVT;// 3. 准备上层回调数据disc_dat.handle p_cb-hid_handle;disc_dat.status to_bta_hh_status(p_data-hid_cback.data);std::string overlay_fail base::StringPrintf(%s %s %s, (l2cap_conn_fail) ? l2cap_conn_fail : ,(l2cap_req_fail) ? l2cap_req_fail : ,(l2cap_cfg_fail) ? l2cap_cfg_fail : );BTM_LogHistory(kBtmLogTag, p_cb-link_spec.addrt.bda, Closed,base::StringPrintf(%s reason %s %s,(p_cb-is_le_device) ? le : classic,hid_status_text(hid_status).c_str(),overlay_fail.c_str()));// 5. 通知角色管理器资源协同清理/* inform role manager */bta_sys_conn_close(BTA_ID_HH, p_cb-app_id, p_cb-link_spec.addrt.bda);// 6. 更新连接计数系统状态跟踪/* update total conn number */bta_hh_cb.cnt_num--;if (disc_dat.status) disc_dat.status BTA_HH_ERR; // 非零状态标记为错误// 7. 触发上层回调状态同步关键(*bta_hh_cb.p_cback)(event, (tBTA_HH*)disc_dat);// 8. 虚拟拔插处理彻底移除设备/* if virtually unplug, remove device */if (p_cb-vp) {HID_HostRemoveDev(p_cb-hid_handle); // 从HID协议栈移除设备bta_hh_clean_up_kdev(p_cb); // 清理BTA层的设备控制块}bta_hh_trace_dev_db();// 9. 清理控制块保留重连可能/* clean up control block, but retain SDP info and device handle */p_cb-vp false; // 重置虚拟拔插标志p_cb-w4_evt 0; // 重置“等待事件”标志避免后续误触发// 10. 检查是否禁用服务资源回收/* if no connection is active and HH disable is signaled, disable service */if (bta_hh_cb.cnt_num 0 bta_hh_cb.w4_disable) {bta_hh_disc_cmpl(); // 完成服务禁用}return;
}
解析断开原因、通知上层状态变化并清理连接资源确保断开操作的完整闭环和系统资源的有效管理。
核心逻辑可概括为解析原因→分类事件→记录日志→协同清理→通知上层→资源回收。
核心流程: bta_sys_conn_close处理逻辑见【Bluedroid】蓝牙HID Device disconnect流程源码分析-CSDN博客
bta_hh_disc_cmpl处理流程见【Bluedroid】 蓝牙HID Device register_app流程源码解析_human interface device可以禁用吗-CSDN博客
(*bta_hh_cb.p_cback)(BTA_HH_CLOSE_EVT) bte_hh_evtBTA_HH_CLOSE_EVT
packages/modules/Bluetooth/system/btif/src/btif_hh.cc
/********************************************************************************* Function bte_hh_evt** Description Switches context from BTE to BTIF for all HH events** Returns void*******************************************************************************/static void bte_hh_evt(tBTA_HH_EVT event, tBTA_HH* p_data) {bt_status_t status;int param_len 0;tBTIF_COPY_CBACK* p_copy_cback NULL;if (BTA_HH_ENABLE_EVT event)param_len sizeof(tBTA_HH_STATUS);else if (BTA_HH_OPEN_EVT event)param_len sizeof(tBTA_HH_CONN);else if (BTA_HH_DISABLE_EVT event)param_len sizeof(tBTA_HH_STATUS);else if (BTA_HH_CLOSE_EVT event)param_len sizeof(tBTA_HH_CBDATA);else if (BTA_HH_GET_DSCP_EVT event)param_len sizeof(tBTA_HH_DEV_DSCP_INFO);else if ((BTA_HH_GET_PROTO_EVT event) || (BTA_HH_GET_IDLE_EVT event))param_len sizeof(tBTA_HH_HSDATA);else if (BTA_HH_GET_RPT_EVT event) {BT_HDR* hdr p_data-hs_data.rsp_data.p_rpt_data;param_len sizeof(tBTA_HH_HSDATA);if (hdr ! NULL) {p_copy_cback btif_hh_hsdata_rpt_copy_cb;param_len BT_HDR_SIZE hdr-offset hdr-len;}} else if ((BTA_HH_SET_PROTO_EVT event) || (BTA_HH_SET_RPT_EVT event) ||(BTA_HH_VC_UNPLUG_EVT event) || (BTA_HH_SET_IDLE_EVT event))param_len sizeof(tBTA_HH_CBDATA);else if ((BTA_HH_ADD_DEV_EVT event) || (BTA_HH_RMV_DEV_EVT event))param_len sizeof(tBTA_HH_DEV_INFO);else if (BTA_HH_API_ERR_EVT event)param_len 0;/* switch context to btif task context (copy full union size for convenience)*/// 上下文转移BTA → BTIF 线程status btif_transfer_context(btif_hh_upstreams_evt, (uint16_t)event,(char*)p_data, param_len, p_copy_cback);/* catch any failed context transfers */ASSERTC(status BT_STATUS_SUCCESS, context transfer failed, status);
}
BTA_HH_CLOSE_EVT 事件的处理是蓝牙 HID 断开流程中BTA 层向 BTIF 层接口层传递断开事件的关键环节。其核心作用是将 BTA 层的断开完成事件BTA_HH_CLOSE_EVT转换为 BTIF 层可处理的上下文并通过线程切换确保事件在 BTIF 任务上下文中执行最终通知应用层设备已断开。
btif_hh_upstreams_evt(BTA_HH_CLOSE_EVT)
/********************************************************************************* Function btif_hh_upstreams_evt** Description Executes HH UPSTREAMS events in btif context** Returns void*******************************************************************************/
static void btif_hh_upstreams_evt(uint16_t event, char* p_param) {tBTA_HH* p_data (tBTA_HH*)p_param;btif_hh_device_t* p_dev NULL;int i;int len, tmplen;log::verbose(event{} dereg {}, dump_hh_event(event),btif_hh_cb.service_dereg_active);switch (event) {...case BTA_HH_CLOSE_EVT:log::verbose(BTA_HH_CLOSE_EVT: status {}, handle {},p_data-dev_status.status, p_data-dev_status.handle);// 1. 查找设备对象定位目标设备p_dev btif_hh_find_connected_dev_by_handle(p_data-dev_status.handle);if (p_dev ! NULL) {// 2. 触发 “断开中” HAL 回调应用层预通知HAL_CBACK(bt_hh_callbacks, connection_state_cb,(p_dev-link_spec.addrt.bda), BTHH_CONN_STATE_DISCONNECTING);log::verbose(uhid fd{} local_vup{}, p_dev-fd, p_dev-local_vup);// 3. 停止虚拟拔插定时器避免残留事件btif_hh_stop_vup_timer((p_dev-link_spec));// 4. 处理本地虚拟拔插或服务变更特殊场景清理/* If this is a locally initiated VUP, remove the bond as ACL got* disconnected while VUP being processed.*/if (p_dev-local_vup) {p_dev-local_vup false;BTA_DmRemoveDevice(p_dev-link_spec.addrt.bda); // 移除设备绑定} else if (p_data-dev_status.status BTA_HH_HS_SERVICE_CHANGED) {// 断开原因是 HID 设备的服务变更BTA_HH_HS_SERVICE_CHANGED如设备固件升级后服务配置变化/* Local disconnection due to service change in the HOGP device.HID descriptor would be read again, so remove it from cache. */log::warn(Removing cached descriptor due to service change, handle {},p_data-dev_status.handle);btif_storage_remove_hid_info(p_dev-link_spec.addrt.bda); // 清除HID描述符缓存}// 5. 更新 BTIF 层设备状态内部状态同步btif_hh_cb.status (BTIF_HH_STATUS)BTIF_HH_DEV_DISCONNECTED;p_dev-dev_status BTHH_CONN_STATE_DISCONNECTED;// 6. 关闭协同连接多协议清理bta_hh_co_close(p_dev);//7. 触发 “已断开” HAL 回调应用层最终通知HAL_CBACK(bt_hh_callbacks, connection_state_cb,(p_dev-link_spec.addrt.bda), p_dev-dev_status);} else {log::warn(Error: cannot find device with handle {},p_data-dev_status.handle);}break;...
BTA_HH_CLOSE_EVT 事件的处理是蓝牙 HID 断开流程的最终环节负责同步 BTIF 层设备状态并通知应用层设备已断开。核心作用是将 BTA 层传递的断开事件转换为应用层可感知的状态变化确保整个系统状态的一致性。
其核心逻辑可概括为定位设备→预通知应用层→清理特殊场景资源→同步内部状态→关闭协同连接→最终通知应用层。BTIF 层实现了从协议栈到应用层的状态同步确保断开操作的完整性和用户体验的一致性。
三、时序图 四、总结
蓝牙 HID Host 模块的断开流程是多层级协作、状态同步和资源管理的典型案例核心设计特点如下 多层校验机制从 BTIF 层的设备存在性检查到 HID 协议栈的句柄 / 状态校验确保断开操作的合法性。 异步事件传递通过btif_transfer_context和消息队列避免跨线程并发问题保证操作原子性。 资源高效清理关闭 L2CAP 通道、设置 ACL 链路立即断开、清理虚拟拔插定时器避免资源残留。 状态同步闭环通过两次应用层回调断开中→已断开确保用户及时感知状态变化提升体验一致性。
流程通过严格的状态管理和层级协作为蓝牙 HID 设备的稳定断开提供了关键保障。