【Bluedroid】蓝牙HID DEVICE断开连接流程源码分析

蓝牙HID(Human Interface Device) 的断开连接流程涉及从应用层到协议栈的多层交互。本文通过剖析Android Bluetooth协议栈代码,梳理从上层调用disconnect()到最终物理链路断开的完整流程,涵盖状态检查、消息传递、L2CAP通道关闭、资源清理及回调通知等关键环节。流程中通过事件驱动机制协调各模块,确保安全断开并通知应用层状态变化。

一、流程概述

1.1 应用层触发断开

  • 入口函数btif_hd.cc中的disconnect()首先检查应用注册和设备状态。

    • 若条件不满足(如未注册或未启用),直接返回错误状态。

    • 条件满足时调用BTA_HdDisconnect()发起断开请求。

1.2 BTA层消息传递

  1. 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_cidintr_cid均为0),更新设备状态为HIDD_DEV_NO_CONN,并通过回调通知上层(HID_DHOST_EVT_CLOSEHID_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_cbbta_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 传递给该回调函数,从而通知上层设备连接已断开。

三、时序图

相关推荐
Darkwanderor43 分钟前
c++STL-string的模拟实现
c++·string
南风与鱼1 小时前
【数据结构】红黑树(C++)
c++·红黑树
李匠20241 小时前
C++GO语言微服务和服务发现②
开发语言·c++·golang·服务发现
每次的天空1 小时前
Kotlin 内联函数深度解析:从源码到实践优化
android·开发语言·kotlin
练习本1 小时前
Android MVC架构的现代化改造:构建清晰单向数据流
android·架构·mvc
早上好啊! 树哥2 小时前
android studio开发:设置屏幕朝向为竖屏,强制应用的包体始终以竖屏(纵向)展示
android·ide·android studio
虾球xz2 小时前
游戏引擎学习第271天:生成可行走的点
c++·学习·游戏引擎
qq_433554542 小时前
C++ STL编程 vector空间预留、vector高效删除、vector数据排序、vector代码练习
开发语言·c++
XiaoCCCcCCccCcccC2 小时前
Linux网络基础 -- 局域网,广域网,网络协议,网络传输的基本流程,端口号,网络字节序
linux·c语言·网络·c++·网络协议
YY_pdd2 小时前
使用go开发安卓程序
android·golang