此篇文章簡單分析一下藍牙解除配對在協議棧中的工作流程。分析的協議棧版本是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; }
這個解除綁定的流程 暫時是分析到這里。