蓝牙Remove Bond的流程分析

此篇文章简单分析一下蓝牙解除配对在协议栈中的工作流程。分析的协议栈版本是Android8.0

协议栈的接口都定义在bluetooth.cc这个文件中:

static int remove_bond(const bt_bdaddr_t* bd_addr) {
if (is_restricted_mode() && !btif_storage_is_restricted_device(bd_addr))
return BT_STATUS_SUCCESS;
/* sanity check */
if (interface_ready() == false) return BT_STATUS_NOT_READY;
return btif_dm_remove_bond(bd_addr);
}

这里需要注意一下bt_bdaddr_t 是一个结构体,内部一个元素是数组。

 /** Bluetooth Address */
typedef struct {
uint8_t address[];
} __attribute__((packed))bt_bdaddr_t;

进入btif_dm_remove_bond:

bt_status_t btif_dm_remove_bond(const bt_bdaddr_t* bd_addr) {
bdstr_t bdstr;
btif_transfer_context(btif_dm_generic_evt, BTIF_DM_CB_REMOVE_BOND,
(char*)bd_addr, sizeof(bt_bdaddr_t), NULL);
return BT_STATUS_SUCCESS;
}

这个函数btif_transfer_context 是将remove bond这件事情交给bt_jni_workqueue_thread来处理。在该线程中执行的函数就是btif_dm_generic_evt

static void btif_dm_generic_evt(uint16_t event, char* p_param) {
BTIF_TRACE_EVENT("%s: event=%d", __func__, event);
switch (event) {
case BTIF_DM_CB_REMOVE_BOND: {
btif_dm_cb_remove_bond((bt_bdaddr_t*)p_param);
} break;
}
}

执行的函数:btif_dm_cb_remove_bond

void btif_dm_cb_remove_bond(bt_bdaddr_t* bd_addr) {
BTA_DmRemoveDevice((uint8_t*)bd_addr->address);
}

函数执行到了BTA层面。

tBTA_STATUS BTA_DmRemoveDevice(BD_ADDR bd_addr) {
tBTA_DM_API_REMOVE_DEVICE* p_msg =
(tBTA_DM_API_REMOVE_DEVICE*)osi_calloc(sizeof(tBTA_DM_API_REMOVE_DEVICE));
p_msg->hdr.event = BTA_DM_API_REMOVE_DEVICE_EVT;
bdcpy(p_msg->bd_addr, bd_addr);
bta_sys_sendmsg(p_msg);
return BTA_SUCCESS;
}

这边是发送了一个BTA_DM_API_REMOVE_DEVICE_EVT到另一个线程:bt_workqueue_thread,这个线程是专门处理bt里面的队列的,当队列里面有数据都会在这个线程里面处理。

通过bta_sys_sendmsg发送的信号都会经过bta_sys_event来处理,bta_sys_event会根据相应的事件路由到相应的处理函数。这里处理这个事件的函数是:

/*******************************************************************************
*
* Function bta_dm_remove_device
*
* Description Removes device, disconnects ACL link if required.
***
******************************************************************************/
void bta_dm_remove_device(tBTA_DM_MSG* p_data) {
tBTA_DM_API_REMOVE_DEVICE* p_dev = &p_data->remove_dev;//获取消息
bool continue_delete_other_dev = false;/* If ACL exists for the device in the remove_bond message*/
bool continue_delete_dev = false;
uint8_t other_transport = BT_TRANSPORT_INVALID;
/*首先判断该address 是否存有link*/
if (BTM_IsAclConnectionUp(p_dev->bd_addr, BT_TRANSPORT_LE) ||
BTM_IsAclConnectionUp(p_dev->bd_addr, BT_TRANSPORT_BR_EDR)) {
APPL_TRACE_DEBUG("%s: ACL Up count %d", __func__,
bta_dm_cb.device_list.count);
continue_delete_dev = false;
/* Take the link down first, and mark the device for removal when
* disconnected */
for (int i = ; i < bta_dm_cb.device_list.count; i++) {
if (!bdcmp(bta_dm_cb.device_list.peer_device[i].peer_bdaddr,
p_dev->bd_addr)) {
uint8_t transport = BT_TRANSPORT_BR_EDR;
transport = bta_dm_cb.device_list.peer_device[i].transport;
bta_dm_cb.device_list.peer_device[i].conn_state = BTA_DM_UNPAIRING;//设置标志位,在acl link状态改变的函数中会去删除link key
btm_remove_acl(p_dev->bd_addr, transport);//已经存在link,那么要先删除这条linkbreak;
}
}
} else {
continue_delete_dev = true;
}
...
/* Delete the device mentioned in the msg */
if (continue_delete_dev) bta_dm_process_remove_device(p_dev->bd_addr);//解配的设备没有处于连接状态则执行
}

从上面的代码可以看出,核心的地方就两处:

  1. bta_dm_cb.device_list.peer_device[i].conn_state = BTA_DM_UNPAIRING; 标记该设备是要解除配对的,后续会删除其link key
  2. btm_remove_acl 做实际的断开连接的操作。

现在简单看看btm_remove_acl 的实现:

tBTM_STATUS btm_remove_acl(BD_ADDR bd_addr, tBT_TRANSPORT transport) {
uint16_t hci_handle = BTM_GetHCIConnHandle(bd_addr, transport);
tBTM_STATUS status = BTM_SUCCESS;
...
{
if (hci_handle != 0xFFFF && p_dev_rec &&
p_dev_rec->sec_state != BTM_SEC_STATE_DISCONNECTING) {
btsnd_hcic_disconnect(hci_handle, HCI_ERR_PEER_USER);
} else
status = BTM_UNKNOWN_ADDR;
}
return status;
}

先搜索btm_cb.acl_db 找到该地址对应的ACL link 的控制体,获取该link 的handle,该handle用于标志是哪一条link,然后调用btsnd_hcic_disconnect(hci_handle, HCI_ERR_PEER_USER); 向controller发送断开的命令。

到这里,在bt_workqueue_thread 线程中发送断开link 的消息是结束了,controller收到信息处理之后,会有断开完成事件上来,这个时候处理该事件的线程依然是bt_workqueue_thread,我们看看具体的处理过程:处理底层的事件的接口实现在btu_hcif.cc中:

/*******************************************************************************
*
* Function btu_hcif_disconnection_comp_evt
*
* Description Process event HCI_DISCONNECTION_COMP_EVT
*
* Returns void
*
******************************************************************************/
static void btu_hcif_disconnection_comp_evt(uint8_t* p) {
uint16_t handle;
uint8_t reason;
++p;
STREAM_TO_UINT16(handle, p);
STREAM_TO_UINT8(reason, p);
handle = HCID_GET_HANDLE(handle);
l2c_link_hci_disc_comp(handle, reason);
/* Notify security manager */
btm_sec_disconnected(handle, reason);
}

从函数的注释我们也能看出其是处理HCI_DISCONNECTION_COMP_EVT 这个事件的。从代码流程中,我们能看到代码主要做了两件事:

  1. l2c_link_hci_disc_comp
  2. btm_sec_disconnected,这个函数是用来通知security manager的。

下面依次看看这两个函数的实现:

bool l2c_link_hci_disc_comp(uint16_t handle, uint8_t reason) {
L2CAP_TRACE_EVENT("entry l2c_link_hci_disc_comp libs_liu");
tL2C_LCB* p_lcb;
tL2C_CCB* p_ccb;
bool status = true;
bool lcb_is_free = true;
tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR;
/* See if we have a link control block for the connection */
p_lcb = l2cu_find_lcb_by_handle(handle);
...
{
/* Just in case app decides to try again in the callback context */
p_lcb->link_state = LST_DISCONNECTING; /* Check for BLE and handle that differently */
if (p_lcb->transport == BT_TRANSPORT_LE)
btm_ble_update_link_topology_mask(p_lcb->link_role, false);
/* Link is disconnected. For all channels, send the event through */
/* their FSMs. The CCBs should remove themselves from the LCB */
for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb;) {
tL2C_CCB* pn = p_ccb->p_next_ccb;
/* Keep connect pending control block (if exists)
* Possible Race condition when a reconnect occurs
* on the channel during a disconnect of link. This
* ccb will be automatically retried after link disconnect
* arrives
*/
if (p_ccb != p_lcb->p_pending_ccb) {
l2c_csm_execute(p_ccb, L2CEVT_LP_DISCONNECT_IND, &reason);
}
p_ccb = pn;
}
p_lcb->p_pending_ccb = NULL; /* Release the LCB */
if (lcb_is_free){
l2cu_release_lcb(p_lcb);}
}
...
return status;
}

上面函数核心的地方 是释放link 相关的结构体l2cu_release_lcb,这个函数主要就是释放一些定时器,内存以及channel结构释放,另外还做一些通知的事情:

      /* If anyone cares, tell him database changed */
if (btm_cb.p_bl_changed_cb) {
evt_data.event = BTM_BL_DISCN_EVT;
evt_data.discn.p_bda = bda;
evt_data.discn.handle = p->hci_handle;
evt_data.discn.transport = p->transport;
(*btm_cb.p_bl_changed_cb)(&evt_data);
}

这里需要思考一下,这个btm_cb.p_bl_changed_cb 回调函数是哪里注册。这个函数其实在bta_dm_sys_hw_cback 函数中注册的:

BTM_RegBusyLevelNotif(bta_dm_bl_change_cback, NULL,
BTM_BL_UPDATE_MASK | BTM_BL_ROLE_CHG_MASK);
//那其实是
btm_cb.p_bl_changed_cb  = bta_dm_bl_change_cback

那我们现在看看这个busy level change的实现:从上面也可以看出是把BTM_BL_DISCN_EVT 传入到 bta_dm_bl_change_cback 来执行:

static void bta_dm_bl_change_cback(tBTM_BL_EVENT_DATA* p_data) {
tBTA_DM_ACL_CHANGE* p_msg =
(tBTA_DM_ACL_CHANGE*)osi_malloc(sizeof(tBTA_DM_ACL_CHANGE)); p_msg->event = p_data->event;
p_msg->is_new = false; switch (p_msg->event) {
case BTM_BL_CONN_EVT:
p_msg->is_new = true;
bdcpy(p_msg->bd_addr, p_data->conn.p_bda);
p_msg->transport = p_data->conn.transport;
p_msg->handle = p_data->conn.handle;
break;
case BTM_BL_DISCN_EVT:
bdcpy(p_msg->bd_addr, p_data->discn.p_bda);
p_msg->transport = p_data->discn.transport;
p_msg->handle = p_data->discn.handle;
break;
case BTM_BL_UPDATE_EVT:
p_msg->busy_level = p_data->update.busy_level;
p_msg->busy_level_flags = p_data->update.busy_level_flags;
break;
case BTM_BL_ROLE_CHG_EVT:
p_msg->new_role = p_data->role_chg.new_role;
p_msg->hci_status = p_data->role_chg.hci_status;
bdcpy(p_msg->bd_addr, p_data->role_chg.p_bda);
break;
case BTM_BL_COLLISION_EVT:
bdcpy(p_msg->bd_addr, p_data->conn.p_bda);
break;
} p_msg->hdr.event = BTA_DM_ACL_CHANGE_EVT;
bta_sys_sendmsg(p_msg);
}

从这个函数的实现来看,他是可以处理很多的event的。然后统一发送给bt_workqueue_thread中的另外一个队列中,看看具体的处理流程:

其实现的函数是在bta_dm_act.cc中,

void bta_dm_acl_change(tBTA_DM_MSG* p_data) {
uint8_t i;
uint8_t* p;
tBTA_DM_SEC conn;
bool is_new = p_data->acl_change.is_new;
BD_ADDR_PTR p_bda = p_data->acl_change.bd_addr;
bool need_policy_change = false;
bool issue_unpair_cb = false; tBTA_DM_PEER_DEVICE* p_dev;
memset(&conn, , sizeof(tBTA_DM_SEC));
...
for (i = ; i < bta_dm_cb.device_list.count; i++) {
if (bdcmp(bta_dm_cb.device_list.peer_device[i].peer_bdaddr, p_bda) ||
bta_dm_cb.device_list.peer_device[i].transport !=
p_data->acl_change.transport)
continue;
/*找到之后*/
if (bta_dm_cb.device_list.peer_device[i].conn_state == BTA_DM_UNPAIRING) {//之前已经标记过
if (BTM_SecDeleteDevice(bta_dm_cb.device_list.peer_device[i].peer_bdaddr))
      BTA_GATTC_Refresh(p_bda);//remove all gatt information
issue_unpair_cb = true;
}
conn.link_down.is_removed =
bta_dm_cb.device_list.peer_device[i].remove_dev_pending; break;
}
...
conn.link_down.link_type = p_data->acl_change.transport;
...
bdcpy(conn.link_down.bd_addr, p_bda);
conn.link_down.status = (uint8_t)btm_get_acl_disc_reason_code();
if (bta_dm_cb.p_sec_cback) { //执行这里的函数
bta_dm_cb.p_sec_cback(BTA_DM_LINK_DOWN_EVT, &conn);
if (issue_unpair_cb)
bta_dm_cb.p_sec_cback(BTA_DM_DEV_UNPAIRED_EVT, &conn);
}
bta_dm_adjust_roles(true);
}

上面的回调函数主要执行如下:

  1. 从bta_dm_cb 查找到该地址的结构。
  2. 找到之后判断bta_dm_cb.device_list.peer_device[i].conn_state的状态,如果是BTA_DM_UNPAIRING,则开始删除link key:BTM_SecDeleteDevice
  3. 回调bta_dm_cb.p_sec_cback :BTA_DM_LINK_DOWN_EVT以及BTA_DM_DEV_UNPAIRED_EVT

前两个容易理解,看看第三点:

第三点的回调函数在enable 的时候就已经注册好了:bta_dm_cb.p_sec_cback = bte_dm_evt ,我们进一步看看:

void bte_dm_evt(tBTA_DM_SEC_EVT event, tBTA_DM_SEC* p_data) {
bt_status_t status = btif_transfer_context(
btif_dm_upstreams_evt, (uint16_t)event, (char*)p_data,
sizeof(tBTA_DM_SEC), btif_dm_data_copy);
}

发现其实 他实质执行的函数是btif_dm_upstreams_evt ,这个函数处理的event非常的多,这里就列出相关的代码:

static void btif_dm_upstreams_evt(uint16_t event, char* p_param) {
tBTA_DM_SEC* p_data = (tBTA_DM_SEC*)p_param;
tBTA_SERVICE_MASK service_mask;
uint32_t i;
bt_bdaddr_t bd_addr; switch (event) {
...
case BTA_DM_DEV_UNPAIRED_EVT:
bdcpy(bd_addr.address, p_data->link_down.bd_addr);
btm_set_bond_type_dev(p_data->link_down.bd_addr, BOND_TYPE_UNKNOWN); /*special handling for HID devices */
#if (defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == true))
btif_hh_remove_device(bd_addr);
#endif
#if (defined(BTA_HD_INCLUDED) && (BTA_HD_INCLUDED == TRUE))
btif_hd_remove_device(bd_addr);
#endif
btif_storage_remove_bonded_device(&bd_addr);
bond_state_changed(BT_STATUS_SUCCESS, &bd_addr, BT_BOND_STATE_NONE);
break; case BTA_DM_LINK_DOWN_EVT:
bdcpy(bd_addr.address, p_data->link_down.bd_addr);
btm_set_bond_type_dev(p_data->link_down.bd_addr, BOND_TYPE_UNKNOWN);
btif_av_move_idle(bd_addr);
BTIF_TRACE_DEBUG(
"BTA_DM_LINK_DOWN_EVT. Sending BT_ACL_STATE_DISCONNECTED");
HAL_CBACK(bt_hal_cbacks, acl_state_changed_cb, BT_STATUS_SUCCESS,
&bd_addr, BT_ACL_STATE_DISCONNECTED);
break;
} btif_dm_data_free(event, p_data);
}

处理的两个事件是BTA_DM_LINK_DOWN_EVT和BTA_DM_DEV_UNPAIRED_EVT

其中BTA_DM_LINK_DOWN_EVT 主要是执行acl_state_changed_cb,向上层传导BT_ACL_STATE_DISCONNECTED

这里主要看一下BTA_DM_DEV_UNPAIRED_EVT  的处理:

  1. btif_hh_remove_device
  2. btif_storage_remove_bonded_device  删除config中的key 的信息。

下面看看btif_hh_remove_device

void btif_hh_remove_device(bt_bdaddr_t bd_addr) {
int i;
btif_hh_device_t* p_dev;
btif_hh_added_device_t* p_added_dev;for (i = ; i < BTIF_HH_MAX_ADDED_DEV; i++) {
p_added_dev = &btif_hh_cb.added_devices[i];
if (memcmp(&(p_added_dev->bd_addr), &bd_addr, ) == ) {
BTA_HhRemoveDev(p_added_dev->dev_handle);//remove dev
btif_storage_remove_hid_info(&(p_added_dev->bd_addr));//删除config中的hid信息
memset(&(p_added_dev->bd_addr), , );
p_added_dev->dev_handle = BTA_HH_INVALID_HANDLE;
break;
}
}
...
p_dev = btif_hh_find_dev_by_bda(&bd_addr);/* need to notify up-layer device is disconnected to avoid state out of sync
* with up-layer */
HAL_CBACK(bt_hh_callbacks, connection_state_cb, &(p_dev->bd_addr),//向上层汇报状态
BTHH_CONN_STATE_DISCONNECTED); p_dev->dev_status = BTHH_CONN_STATE_UNKNOWN;
p_dev->dev_handle = BTA_HH_INVALID_HANDLE;
p_dev->ready_for_data = false;
...if (p_dev->fd >= ) {
bta_hh_co_destroy(p_dev->fd);//销毁相关的结构
p_dev->fd = -;
}
}

上面代码很简单,主要做清理工作:下面具体看看BTA_HhRemoveDev

void BTA_HhRemoveDev(uint8_t dev_handle) {
tBTA_HH_MAINT_DEV* p_buf =
(tBTA_HH_MAINT_DEV*)osi_calloc(sizeof(tBTA_HH_MAINT_DEV));
p_buf->hdr.event = BTA_HH_API_MAINT_DEV_EVT;
p_buf->sub_event = BTA_HH_RMV_DEV_EVT;
p_buf->hdr.layer_specific = (uint16_t)dev_handle;
bta_sys_sendmsg(p_buf);
}

发送了一个BTA_HH_API_MAINT_DEV_EVT的事件到达BTU task,

void bta_hh_maint_dev_act(tBTA_HH_DEV_CB* p_cb, tBTA_HH_DATA* p_data) {
tBTA_HH_MAINT_DEV* p_dev_info = &p_data->api_maintdev;
tBTA_HH_DEV_INFO dev_info;
uint8_t dev_handle; dev_info.status = BTA_HH_ERR;
dev_info.handle = BTA_HH_INVALID_HANDLE; switch (p_dev_info->sub_event) {
...
case BTA_HH_RMV_DEV_EVT: /* remove device */
dev_info.handle = (uint8_t)p_dev_info->hdr.layer_specific;
bdcpy(dev_info.bda, p_cb->addr); if (p_cb->is_le_device) {//le 设备
bta_hh_le_remove_dev_bg_conn(p_cb);//移除background 里面的list,让其不要回连
bta_hh_sm_execute(p_cb, BTA_HH_API_CLOSE_EVT, NULL);
bta_hh_clean_up_kdev(p_cb);
} else//bredr 设备
{
if (HID_HostRemoveDev(dev_info.handle) == HID_SUCCESS) {
dev_info.status = BTA_HH_OK;
/* remove from known device list in BTA */
bta_hh_clean_up_kdev(p_cb);
}
}
break;
}
(*bta_hh_cb.p_cback)(p_dev_info->sub_event, (tBTA_HH*)&dev_info);
}

这里先讲一下bta_hh_cb.p_cback,也是在 BTA_HhEnable(BTUI_HH_SECURITY, bte_hh_evt); 时候注册的,那么也就是说bta_hh_cb.p_cback = bte_hh_evt

void bte_hh_evt(tBTA_HH_EVT event, tBTA_HH* p_data) {
bt_status_t status;
int param_len = ; 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_RPT_EVT == event) ||
(BTA_HH_GET_IDLE_EVT == event))
param_len = sizeof(tBTA_HH_HSDATA);
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 = ;
/* switch context to btif task context (copy full union size for convenience)
*/
status = btif_transfer_context(btif_hh_upstreams_evt, (uint16_t)event,
(char*)p_data, param_len, NULL); /* catch any failed context transfers */
ASSERTC(status == BT_STATUS_SUCCESS, "context transfer failed", status);
}

其本质还是transfer 到btif 线程,执行btif_hh_upstreams_evt 函数,这边追踪了一下该事件的处理,只是打印了一些log:

    case BTA_HH_RMV_DEV_EVT:
BTIF_TRACE_DEBUG("BTA_HH_RMV_DEV_EVT: status = %d, handle = %d",
p_data->dev_info.status, p_data->dev_info.handle);
BTIF_TRACE_DEBUG("BTA_HH_RMV_DEV_EVT:bda = %02x:%02x:%02x:%02x:%02x:%02x",
p_data->dev_info.bda[], p_data->dev_info.bda[],
p_data->dev_info.bda[], p_data->dev_info.bda[],
p_data->dev_info.bda[], p_data->dev_info.bda[]);
break;

现在着重看一下bta_hh_le_remove_dev_bg_conn(p_cb) 的处理

void bta_hh_le_remove_dev_bg_conn(tBTA_HH_DEV_CB* p_dev_cb) {
if (p_dev_cb->in_bg_conn) {
p_dev_cb->in_bg_conn = false;
BTA_GATTC_CancelOpen(bta_hh_cb.gatt_if, p_dev_cb->addr, false);
} /* deregister all notifications */
bta_hh_le_deregister_input_notif(p_dev_cb);
}
void BTA_GATTC_CancelOpen(tBTA_GATTC_IF client_if, BD_ADDR remote_bda,
bool is_direct) {
tBTA_GATTC_API_CANCEL_OPEN* p_buf = (tBTA_GATTC_API_CANCEL_OPEN*)osi_malloc(
sizeof(tBTA_GATTC_API_CANCEL_OPEN)); p_buf->hdr.event = BTA_GATTC_API_CANCEL_OPEN_EVT;
p_buf->client_if = client_if;
p_buf->is_direct = is_direct;
memcpy(p_buf->remote_bda, remote_bda, BD_ADDR_LEN); bta_sys_sendmsg(p_buf);
}
void bta_gattc_process_api_open_cancel(tBTA_GATTC_DATA* p_msg) {
uint16_t event = ((BT_HDR*)p_msg)->event;
tBTA_GATTC_CLCB* p_clcb = NULL;
tBTA_GATTC_RCB* p_clreg;
tBTA_GATTC cb_data; if (p_msg->api_cancel_conn.is_direct) {
...
} else {
bta_gattc_cancel_bk_conn(&p_msg->api_cancel_conn);
}
}
void bta_gattc_cancel_bk_conn(tBTA_GATTC_API_CANCEL_OPEN* p_data) {
tBTA_GATTC_RCB* p_clreg;
tBTA_GATTC cb_data;
cb_data.status = BTA_GATT_ERROR; /* remove the device from the bg connection mask */
if (bta_gattc_mark_bg_conn(p_data->client_if, p_data->remote_bda, false)) {
if (GATT_CancelConnect(p_data->client_if, p_data->remote_bda, false)) {
cb_data.status = BTA_GATT_OK;
} else {
APPL_TRACE_ERROR("bta_gattc_cancel_bk_conn failed");
}
}
p_clreg = bta_gattc_cl_get_regcb(p_data->client_if); if (p_clreg && p_clreg->p_cback) {
(*p_clreg->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, &cb_data);
}
}
bool GATT_CancelConnect(tGATT_IF gatt_if, BD_ADDR bd_addr, bool is_direct) {
tGATT_REG* p_reg;
tGATT_TCB* p_tcb;
bool status = true;
tGATT_IF temp_gatt_if;
uint8_t start_idx, found_idx; if (!gatt_if)
...
else {
status = gatt_remove_bg_dev_for_app(gatt_if, bd_addr);
}
return status;
}
bool gatt_remove_bg_dev_for_app(tGATT_IF gatt_if, BD_ADDR bd_addr) {
tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bd_addr, BT_TRANSPORT_LE);
bool status; if (p_tcb) gatt_update_app_use_link_flag(gatt_if, p_tcb, false, false);
status = gatt_update_auto_connect_dev(gatt_if, false, bd_addr);
return status;
}
bool gatt_update_auto_connect_dev(tGATT_IF gatt_if, bool add, BD_ADDR bd_addr) {
...
if (add) {
ret = gatt_add_bg_dev_list(p_reg, bd_addr);
if (ret && p_tcb != NULL) {
/* if a connected device, update the link holding number */
gatt_update_app_use_link_flag(gatt_if, p_tcb, true, true);
}
} else {
ret = gatt_remove_bg_dev_from_list(p_reg, bd_addr);
}
return ret;
}
bool gatt_remove_bg_dev_from_list(tGATT_REG* p_reg, BD_ADDR bd_addr) {
tGATT_IF gatt_if = p_reg->gatt_if;
tGATT_BG_CONN_DEV* p_dev = NULL;
uint8_t i, j;
bool ret = false; p_dev = gatt_find_bg_dev(bd_addr);
if (p_dev == NULL) {
return ret;
} for (i = ; i < GATT_MAX_APPS && (p_dev->gatt_if[i] > ); i++) {
if (p_dev->gatt_if[i] == gatt_if) {
p_dev->gatt_if[i] = ;
/* move all element behind one forward */
for (j = i + ; j < GATT_MAX_APPS; j++)
p_dev->gatt_if[j - ] = p_dev->gatt_if[j]; if (p_dev->gatt_if[] == ){//只有设备全部都断开了才会去做BTM_BleUpdateBgConnDev
ret = BTM_BleUpdateBgConnDev(false, p_dev->remote_bda);
}
else
ret = true; break;
}
} if (i != GATT_MAX_APPS && p_dev->gatt_if[] == ) {
memset(p_dev, , sizeof(tGATT_BG_CONN_DEV));
} return ret;
}
bool BTM_BleUpdateBgConnDev(bool add_remove, BD_ADDR remote_bda) {
return btm_update_dev_to_white_list(add_remove, remote_bda);
}
bool btm_update_dev_to_white_list(bool to_add, BD_ADDR bd_addr) {
tBTM_BLE_CB* p_cb = &btm_cb.ble_ctr_cb; if (to_add && p_cb->white_list_avail_size == ) {
BTM_TRACE_ERROR("%s Whitelist full, unable to add device", __func__);
return false;
}
if (to_add)
background_connection_add((bt_bdaddr_t*)bd_addr);
else{
background_connection_remove((bt_bdaddr_t*)bd_addr);
}
btm_suspend_wl_activity(p_cb->wl_state);
btm_enq_wl_dev_operation(to_add, bd_addr);
btm_resume_wl_activity(p_cb->wl_state);
return true;
}

删除 里面的值: background_connection_remove

static void btm_resume_wl_activity(tBTM_BLE_WL_STATE wl_state) {
btm_ble_resume_bg_conn();
if (wl_state & BTM_BLE_WL_ADV) {
btm_ble_start_adv();
}
}
bool btm_ble_resume_bg_conn(void) {
tBTM_BLE_CB* p_cb = &btm_cb.ble_ctr_cb;
if (p_cb->bg_conn_type == BTM_BLE_CONN_AUTO) {
return btm_ble_start_auto_conn(true);//如果background 里面还存在设备,那么就会回连
}
return false;
}

这个解除绑定的流程 暂时是分析到这里。

蓝牙Remove Bond的流程分析

上一篇:suricate学习笔记1--初步认识(转)


下一篇:Ubuntu 14.04 LTS 火狐浏览器中,鼠标选择文字被删除的解决办法