蓝牙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[6]; } __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 = 0; 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);//解配的设备没有处于连接状态则执行 }
从上面的代码可以看出,核心的地方就两处:
- bta_dm_cb.device_list.peer_device[i].conn_state = BTA_DM_UNPAIRING; 标记该设备是要解除配对的,后续会删除其link key
- 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 这个事件的。从代码流程中,我们能看到代码主要做了两件事:
- l2c_link_hci_disc_comp
- 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, 0, sizeof(tBTA_DM_SEC)); ... for (i = 0; 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); }
上面的回调函数主要执行如下:
- 从bta_dm_cb 查找到该地址的结构。
- 找到之后判断bta_dm_cb.device_list.peer_device[i].conn_state的状态,如果是BTA_DM_UNPAIRING,则开始删除link key:BTM_SecDeleteDevice
- 回调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 的处理:
- btif_hh_remove_device
- 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 = 0; 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, 6) == 0) { 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), 0, 6); 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 >= 0) { bta_hh_co_destroy(p_dev->fd);//销毁相关的结构 p_dev->fd = -1; } }
上面代码很简单,主要做清理工作:下面具体看看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 = 0; 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 = 0; /* 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[0], p_data->dev_info.bda[1], p_data->dev_info.bda[2], p_data->dev_info.bda[3], p_data->dev_info.bda[4], p_data->dev_info.bda[5]); 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 = 0; i < GATT_MAX_APPS && (p_dev->gatt_if[i] > 0); i++) { if (p_dev->gatt_if[i] == gatt_if) { p_dev->gatt_if[i] = 0; /* move all element behind one forward */ for (j = i + 1; j < GATT_MAX_APPS; j++) p_dev->gatt_if[j - 1] = p_dev->gatt_if[j]; if (p_dev->gatt_if[0] == 0){//只有设备全部都断开了才会去做BTM_BleUpdateBgConnDev ret = BTM_BleUpdateBgConnDev(false, p_dev->remote_bda); } else ret = true; break; } } if (i != GATT_MAX_APPS && p_dev->gatt_if[0] == 0) { memset(p_dev, 0, 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 == 0) { 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; }
这个解除绑定的流程 暂时是分析到这里。