蓝牙BLE设备断线回连分析
在 文章中分析了Hogp的连接的流程 ,这里分析一下回连的流程.
在使用ble设备的过程中,我们发现当设备和主机配对之后,如果没有解除配对,那么即便设备和主机断开,那么也是可以重新连接而不需要重新走配对的流程,这里的分析的源代码是Android7.0 .
回连的大概的流程是:hogp 连接完成之后,会把当前的device 加入到whitelist里面.,标记为可以回连的设备.当设备和主机断开的时候,主机会根据whitelist里面的设备来进行回连.
这里我们从hogp连接流程中将device加入到 whitelist的流程来开始分析.
/******************************************************************************* ** ** Function bta_hh_le_open_cmpl ** ** Description HID over GATT connection sucessfully opened ** *******************************************************************************/ void bta_hh_le_open_cmpl(tBTA_HH_DEV_CB *p_cb) { if ( p_cb->disc_active == BTA_HH_LE_DISC_NONE) { bta_hh_le_register_input_notif(p_cb, p_cb->mode, TRUE); bta_hh_sm_execute(p_cb, BTA_HH_OPEN_CMPL_EVT, NULL); #if (BTA_HH_LE_RECONN == TRUE) if (p_cb->status == BTA_HH_OK) { bta_hh_le_add_dev_bg_conn(p_cb, TRUE);//加入到bg connection 中 } #endif } }
继续看bta_hh_le_add_dev_bg_conn 的实现:
static void bta_hh_le_add_dev_bg_conn(tBTA_HH_DEV_CB *p_cb, BOOLEAN check_bond) { UINT8 sec_flag=0; BOOLEAN to_add = TRUE; if (check_bond) { /* start reconnection if remote is a bonded device */ /* verify bond */ BTM_GetSecurityFlagsByTransport(p_cb->addr, &sec_flag, BT_TRANSPORT_LE); if ((sec_flag & BTM_SEC_FLAG_LKEY_KNOWN) == 0) to_add = FALSE;//如果没有完成安全认证,那么不会加入到whitelist里面 } if (!p_cb->in_bg_conn && to_add) { /* add device into BG connection to accept remote initiated connection */ BTA_GATTC_Open(bta_hh_cb.gatt_if, p_cb->addr, FALSE, BTA_GATT_TRANSPORT_LE); p_cb->in_bg_conn = TRUE;//标记为in_bg_conn 为true BTA_DmBleSetBgConnType(BTA_DM_BLE_CONN_AUTO, NULL); } return; } }
这里 分为两个步骤:
- BTA_GATTC_Open(bta_hh_cb.gatt_if, p_cb->addr, FALSE, BTA_GATT_TRANSPORT_LE);
- BTA_DmBleSetBgConnType(BTA_DM_BLE_CONN_AUTO, NULL);
这里的重点是第一个步骤,我们依次分析:
bta_gattc_api.c
void BTA_GATTC_Open(tBTA_GATTC_IF client_if, BD_ADDR remote_bda, BOOLEAN is_direct, tBTA_GATT_TRANSPORT transport) { tBTA_GATTC_API_OPEN *p_buf = (tBTA_GATTC_API_OPEN *) osi_malloc(sizeof(tBTA_GATTC_API_OPEN)); p_buf->hdr.event = BTA_GATTC_API_OPEN_EVT; p_buf->client_if = client_if; p_buf->is_direct = is_direct; p_buf->transport = transport; memcpy(p_buf->remote_bda, remote_bda, BD_ADDR_LEN); bta_sys_sendmsg(p_buf); }
这里不多说, bta_gattc_hdl_event -->BTA_GATTC_API_OPEN_EVT ->bta_gattc_process_api_open 我们直接看实际处理的函数
bta_gattc_act.c
void bta_gattc_process_api_open (tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg) { UINT16 event = ((BT_HDR *)p_msg)->event; tBTA_GATTC_CLCB *p_clcb = NULL; tBTA_GATTC_RCB *p_clreg = bta_gattc_cl_get_regcb(p_msg->api_conn.client_if); UNUSED(p_cb); if (p_clreg != NULL) { if (p_msg->api_conn.is_direct)//is_direct是false { if ((p_clcb = bta_gattc_find_alloc_clcb(p_msg->api_conn.client_if, p_msg->api_conn.remote_bda, p_msg->api_conn.transport)) != NULL) { bta_gattc_sm_execute(p_clcb, event, p_msg); } else { APPL_TRACE_ERROR("No resources to open a new connection."); bta_gattc_send_open_cback(p_clreg, BTA_GATT_NO_RESOURCES, p_msg->api_conn.remote_bda, BTA_GATT_INVALID_CONN_ID, p_msg->api_conn.transport, 0); } } else { bta_gattc_init_bk_conn(&p_msg->api_conn, p_clreg);//init bg conn } } }
继续看bta_gattc_init_bk_conn
/******************************************************************************* ** ** Function bta_gattc_init_bk_conn ** ** Description Process API Open for a background connection ** ** Returns void ** *******************************************************************************/ void bta_gattc_init_bk_conn(tBTA_GATTC_API_OPEN *p_data, tBTA_GATTC_RCB *p_clreg) { tBTA_GATT_STATUS status = BTA_GATT_NO_RESOURCES; UINT16 conn_id; tBTA_GATTC_CLCB *p_clcb; tBTA_GATTC_DATA gattc_data; if (bta_gattc_mark_bg_conn(p_data->client_if, p_data->remote_bda, TRUE, FALSE))//标记p_bg_tck->cif_mask ,暂时没看出来用处 { /* always call open to hold a connection */ if (!GATT_Connect(p_data->client_if, p_data->remote_bda, false, p_data->transport, false))//执行gatt_connect,注意这里的参数是no_direct { /*出错处理*/ } else { status = BTA_GATT_OK; /* if is a connected remote device */ if (GATT_GetConnIdIfConnected(p_data->client_if, p_data->remote_bda, &conn_id, p_data->transport)) { if ((p_clcb = bta_gattc_find_alloc_clcb(p_data->client_if, p_data->remote_bda, BTA_GATT_TRANSPORT_LE)) != NULL) { gattc_data.hdr.layer_specific = p_clcb->bta_conn_id = conn_id; /* open connection */ bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_CONN_EVT, &gattc_data);//当前就是connection状态,BTA_GATTC_IGNORE status = BTA_GATT_OK; } } } } ... }
上面的重点是 GATT_Connect,下面重点看:
/******************************************************************************* ** ** Function GATT_Connect ** ** Description This function initiate a connecttion to a remote device on GATT ** channel. ** ** Parameters gatt_if: applicaiton interface ** bd_addr: peer device address. ** is_direct: is a direct conenection or a background auto connection ** ** Returns TRUE if connection started; FALSE if connection start failure. ** *******************************************************************************/ BOOLEAN GATT_Connect (tGATT_IF gatt_if, BD_ADDR bd_addr, BOOLEAN is_direct, tBT_TRANSPORT transport, BOOLEAN opportunistic) { tGATT_REG *p_reg; BOOLEAN status = FALSE; /* Make sure app is registered */ if ((p_reg = gatt_get_regcb(gatt_if)) == NULL) { GATT_TRACE_ERROR("GATT_Connect - gatt_if =%d is not registered", gatt_if); return(FALSE); } if (is_direct)//定向是直接建立连接,否则加入whitelist status = gatt_act_connect (p_reg, bd_addr, transport, opportunistic); else { if (transport == BT_TRANSPORT_LE) status = gatt_update_auto_connect_dev(gatt_if,TRUE, bd_addr, TRUE); else { GATT_TRACE_ERROR("Unsupported transport for background connection"); } } return status; }
我们这里执行的是gatt_update_auto_connect_dev
/******************************************************************************* ** ** Function gatt_update_auto_connect_dev ** ** Description This function add or remove a device for background connection ** procedure. ** ** Parameters gatt_if: Application ID. ** add: add peer device ** bd_addr: peer device address. ** ** Returns TRUE if connection started; FALSE if connection start failure. ** *******************************************************************************/ BOOLEAN gatt_update_auto_connect_dev (tGATT_IF gatt_if, BOOLEAN add, BD_ADDR bd_addr, BOOLEAN is_initator) { BOOLEAN ret = FALSE; tGATT_REG *p_reg; tGATT_TCB *p_tcb = gatt_find_tcb_by_addr(bd_addr, BT_TRANSPORT_LE); if (add) { ret = gatt_add_bg_dev_list(p_reg, bd_addr, is_initator);//添加到whitelist 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, is_initator);//否则移除 } return ret; }
这里我们先简单分析一下 gatt_update_app_use_link_flag(gatt_if, p_tcb, TRUE, TRUE);
/******************************************************************************* ** ** Function gatt_update_app_use_link_flag ** ** Description Update the application use link flag and optional to check the acl link ** if the link is up then set the idle time out accordingly ** ** Returns void. ** *******************************************************************************/ void gatt_update_app_use_link_flag(tGATT_IF gatt_if, tGATT_TCB *p_tcb, BOOLEAN is_add, BOOLEAN check_acl_link) { // If we make no modification, i.e. kill app that was never connected to a device, // skip updating the device state. if (!gatt_update_app_hold_link_status(gatt_if, p_tcb, is_add))//gatt_cb->p_tcb->app_hold_link[i] == gatt_if return; if (!check_acl_link || p_tcb->att_lcid != L2CAP_ATT_CID || /* only update link idle timer for fixed channel */ (BTM_GetHCIConnHandle(p_tcb->peer_bda, p_tcb->transport) == GATT_INVALID_ACL_HANDLE)) { return; } if (is_add) { /* acl link is connected disable the idle timeout */ GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_NO_IDLE_TIMEOUT, p_tcb->transport);//设置timeout为无限长 } else { if (!gatt_num_apps_hold_link(p_tcb)) { /* acl link is connected but no application needs to use the link so set the timeout value to GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP seconds */ GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP, p_tcb->transport);//如果是remove,那么设置timeout为1s } } }
下面继续看gatt_add_bg_dev_list 的实现:
/******************************************************************************* ** ** Function gatt_add_bg_dev_list ** ** Description add/remove device from the back ground connection device list ** ** Returns TRUE if device added to the list; FALSE failed ** *******************************************************************************/ BOOLEAN gatt_add_bg_dev_list(tGATT_REG *p_reg, BD_ADDR bd_addr, BOOLEAN is_initator) { tGATT_IF gatt_if = p_reg->gatt_if; tGATT_BG_CONN_DEV *p_dev = NULL; UINT8 i; BOOLEAN ret = FALSE; if ((p_dev = gatt_find_bg_dev(bd_addr)) == NULL) { p_dev = gatt_alloc_bg_dev(bd_addr);//未找到则分配,此结构为gatt_cb.bgconn_dev } if (p_dev) { for (i = 0; i < GATT_MAX_APPS; i ++) { if (is_initator)//主机端一般都是initator { if (p_dev->gatt_if[i] == gatt_if) { GATT_TRACE_ERROR("device already in iniator white list"); return TRUE; } else if (p_dev->gatt_if[i] == 0) { p_dev->gatt_if[i] = gatt_if; ret = BTM_BleUpdateBgConnDev(TRUE, bd_addr);//update background connection break; } } } } return ret; }
继续看:
/******************************************************************************* ** ** Function BTM_BleUpdateBgConnDev ** ** Description This function is called to add or remove a device into/from ** background connection procedure. The background connection * procedure is decided by the background connection type, it can be * auto connection, or selective connection. ** ** Parameters add_remove: TRUE to add; FALSE to remove. ** remote_bda: device address to add/remove. ** ** Returns void ** *******************************************************************************/ BOOLEAN BTM_BleUpdateBgConnDev(BOOLEAN add_remove, BD_ADDR remote_bda) { BTM_TRACE_EVENT("%s() add=%d", __func__, add_remove); return btm_update_dev_to_white_list(add_remove, remote_bda); }
/******************************************************************************* ** ** Function btm_update_dev_to_white_list ** ** Description This function adds or removes a device into/from ** the white list. ** *******************************************************************************/ BOOLEAN btm_update_dev_to_white_list(BOOLEAN 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)//判断whitelist容量 { BTM_TRACE_ERROR("%s Whitelist full, unable to add device", __func__); return FALSE; } if (to_add) background_connection_add((bt_bdaddr_t*)bd_addr);//添加到background_connections 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_cb.ble_ctr_cb.wl_op_q 更新 btm_resume_wl_activity(p_cb->wl_state); return TRUE; }
这里简单看下bg connection的管理:用hash map 来实现的,
static void background_connection_add(bt_bdaddr_t *address) { assert(address); background_connections_lazy_init(); background_connection_t *connection = hash_map_get(background_connections, address); if (!connection) { connection = osi_calloc(sizeof(background_connection_t)); connection->address = *address; hash_map_set(background_connections, &(connection->address), connection); } }
到这里 已经将设备添加到bg connection里面了,
下面继续看
2.BTA_DmBleSetBgConnType(BTA_DM_BLE_CONN_AUTO, NULL);
void BTA_DmBleSetBgConnType(tBTA_DM_BLE_CONN_TYPE bg_conn_type, tBTA_DM_BLE_SEL_CBACK *p_select_cback) { #if BLE_INCLUDED == TRUE tBTA_DM_API_BLE_SET_BG_CONN_TYPE *p_msg = (tBTA_DM_API_BLE_SET_BG_CONN_TYPE *)osi_calloc(sizeof(tBTA_DM_API_BLE_SET_BG_CONN_TYPE)); p_msg->hdr.event = BTA_DM_API_BLE_SET_BG_CONN_TYPE; p_msg->bg_conn_type = bg_conn_type; p_msg->p_select_cback = p_select_cback; bta_sys_sendmsg(p_msg); #endif }
发出BTA_DM_API_BLE_SET_BG_CONN_TYPE 信息.
相应的处理函数:
/******************************************************************************* ** ** Function BTM_BleSetBgConnType ** ** Description This function is called to set BLE connectable mode for a ** peripheral device. ** ** Parameters bg_conn_type: it can be auto connection, or selective connection. ** p_select_cback: callback function when selective connection procedure ** is being used. ** ** Returns void ** *******************************************************************************/ BOOLEAN BTM_BleSetBgConnType(tBTM_BLE_CONN_TYPE bg_conn_type, tBTM_BLE_SEL_CBACK *p_select_cback) { BOOLEAN started = TRUE; if (btm_cb.ble_ctr_cb.bg_conn_type != bg_conn_type) { switch (bg_conn_type) { case BTM_BLE_CONN_AUTO: btm_ble_start_auto_conn(TRUE); break; ...
if (started)
btm_cb.ble_ctr_cb.bg_conn_type = bg_conn_type; //更新 bg_conn_type = BTM_BLE_CONN_AUTO = 1
我们继续看btm_ble_start_auto_conn 的实现:
/******************************************************************************* ** ** Function btm_ble_start_auto_conn ** ** Description This function is to start/stop auto connection procedure. ** ** Parameters start: TRUE to start; FALSE to stop. ** ** Returns void ** *******************************************************************************/ BOOLEAN btm_ble_start_auto_conn(BOOLEAN start) { tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb; BD_ADDR dummy_bda = {0}; BOOLEAN exec = TRUE; UINT16 scan_int; UINT16 scan_win; UINT8 own_addr_type = p_cb->addr_mgnt_cb.own_addr_type; UINT8 peer_addr_type = BLE_ADDR_PUBLIC; if (start)//true { if ( p_cb->conn_state == BLE_CONN_IDLE )//未 正在连接状态,当前状态是 BLE_CONN_IDLE { exec = btm_execute_wl_dev_operation();//add to whitelist } /*background_connections_pending 此条件判断不符,因为当前ble 设备和主机已经连接,故不会去下0x200d*/ if (p_cb->conn_state == BLE_CONN_IDLE && background_connections_pending() && btm_ble_topology_check(BTM_BLE_STATE_INIT)) { p_cb->wl_state |= BTM_BLE_WL_INIT; scan_int = (p_cb->scan_int == BTM_BLE_SCAN_PARAM_UNDEF) ? BTM_BLE_SCAN_SLOW_INT_1 : p_cb->scan_int; scan_win = (p_cb->scan_win == BTM_BLE_SCAN_PARAM_UNDEF) ? BTM_BLE_SCAN_SLOW_WIN_1 : p_cb->scan_win; if (!btsnd_hcic_ble_create_ll_conn (scan_int, /* UINT16 scan_int */ scan_win, /* UINT16 scan_win */ 0x01, /* UINT8 white_list */ peer_addr_type, /* UINT8 addr_type_peer */ dummy_bda, /* BD_ADDR bda_peer */ own_addr_type, /* UINT8 addr_type_own */ BTM_BLE_CONN_INT_MIN_DEF, /* UINT16 conn_int_min */ #ifdef BLUETOOTH_RTK BTM_BLE_CONN_INT_MIN_DEF, #else BTM_BLE_CONN_INT_MAX_DEF, /* UINT16 conn_int_max */ #endif BTM_BLE_CONN_SLAVE_LATENCY_DEF, /* UINT16 conn_latency */ BTM_BLE_CONN_TIMEOUT_DEF, /* UINT16 conn_timeout */ 0, /* UINT16 min_len */ 0)) /* UINT16 max_len */ { /* start auto connection failed */ exec = FALSE; p_cb->wl_state &= ~BTM_BLE_WL_INIT; } else { btm_ble_set_conn_st (BLE_BG_CONN); } } else { exec = FALSE; } } else //false 状态 { if (p_cb->conn_state == BLE_BG_CONN) { btsnd_hcic_ble_create_conn_cancel(); btm_ble_set_conn_st (BLE_CONN_CANCEL); p_cb->wl_state &= ~BTM_BLE_WL_INIT; } else { exec = FALSE; } } return exec; }
在上面的 btm_execute_wl_dev_operation 流程中,会将设备加入到whitelist里面去,对应的HCI 命令是Command: HCI_LE_Add_Device_To_White_List
到目前为止,已经将设备加入到bg connection里面以及contrller的 whitelist里面了.
当设备与主机端断开连接,那么主机端应该主动发起,回连,.
下面我们简单看一下,当设备与主机端断开的时候,主机端的行为.
/******************************************************************************* ** ** Function btu_hcif_disconnection_comp_evt ** ** Description Process event HCI_DISCONNECTION_COMP_EVT ** ** Returns void ** *******************************************************************************/ static void btu_hcif_disconnection_comp_evt (UINT8 *p) { UINT16 handle; UINT8 reason; ++p; STREAM_TO_UINT16 (handle, p); STREAM_TO_UINT8 (reason, p); handle = HCID_GET_HANDLE (handle); l2c_link_hci_disc_comp (handle, reason);//L2cap 相关的链接处理 /* Notify security manager */ btm_sec_disconnected (handle, reason);//security manager的处理 }
我们主要看一下btm_sec_disconnected的处理:
这里挑重点;
void btm_sec_disconnected (UINT16 handle, UINT8 reason) { tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev_by_handle (handle); UINT8 old_pairing_flags = btm_cb.pairing_flags; int result = HCI_ERR_AUTH_FAILURE; tBTM_SEC_CALLBACK *p_callback = NULL; tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR; btm_acl_resubmit_page();//如果有挂起的连接请求,那么继续 transport = (handle == p_dev_rec->hci_handle) ? BT_TRANSPORT_BR_EDR: BT_TRANSPORT_LE; p_dev_rec->rs_disc_pending = BTM_SEC_RS_NOT_PENDING; /* reset flag */ /* clear unused flags */ p_dev_rec->sm4 &= BTM_SM4_TRUE; uint8_t *bd_addr = (uint8_t *)p_dev_rec->bd_addr; /* If we are in the process of bonding we need to tell client that auth failed */ if ( (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE) && (memcmp (btm_cb.pairing_bda, p_dev_rec->bd_addr, BD_ADDR_LEN) == 0)) { ... } #if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE btm_ble_update_mode_operation(HCI_ROLE_UNKNOWN, p_dev_rec->bd_addr, HCI_SUCCESS);//当link状态改变时更新le设备应该做的行为 /* see sec_flags processing in btm_acl_removed */ if (transport == BT_TRANSPORT_LE)/*清掉各种flag*/ { p_dev_rec->ble_hci_handle = BTM_SEC_INVALID_HANDLE; p_dev_rec->sec_flags &= ~(BTM_SEC_LE_AUTHENTICATED|BTM_SEC_LE_ENCRYPTED); p_dev_rec->enc_key_size = 0; } else #endif { ... } ... p_dev_rec->sec_state = BTM_SEC_STATE_IDLE; p_dev_rec->security_required = BTM_SEC_NONE; p_callback = p_dev_rec->p_callback; /* if security is pending, send callback to clean up the security state */ if(p_callback) { p_dev_rec->p_callback = NULL; /* when the peer device time out the authentication before we do, this call back must be reset here */ (*p_callback) (p_dev_rec->bd_addr, transport, p_dev_rec->p_ref_data, BTM_ERR_PROCESSING); } BTM_TRACE_EVENT("%s after update sec_flags=0x%x", __func__, p_dev_rec->sec_flags); }
这里我们只要专注于 btm_ble_update_mode_operation 就好.
/******************************************************************************* ** ** Function btm_ble_update_mode_operation ** ** Description This function update the GAP role operation when a link status ** is updated. ** ** Returns void ** *******************************************************************************/ void btm_ble_update_mode_operation(UINT8 link_role, BD_ADDR bd_addr, UINT8 status) { if (status == HCI_ERR_DIRECTED_ADVERTISING_TIMEOUT) { ... } if (btm_cb.ble_ctr_cb.inq_var.connectable_mode == BTM_BLE_CONNECTABLE) { ... } /* when no connection is attempted, and controller is not rejecting last request due to resource limitation, start next direct connection or background connection now in order */ if (btm_ble_get_conn_st() == BLE_CONN_IDLE && status != HCI_ERR_HOST_REJECT_RESOURCES && !btm_send_pending_direct_conn())//当没有direct请求的时候 { btm_ble_resume_bg_conn();//开始回连 } }
/******************************************************************************* ** ** Function btm_ble_resume_bg_conn ** ** Description This function is to resume a background auto connection ** procedure. ** ** Parameters none. ** ** Returns none. ** *******************************************************************************/ BOOLEAN btm_ble_resume_bg_conn(void) { tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb; BOOLEAN ret = FALSE; if (p_cb->bg_conn_type != BTM_BLE_CONN_NONE) { if (p_cb->bg_conn_type == BTM_BLE_CONN_AUTO)//BTM_BLE_CONN_AUTO前面已经设置过了 ret = btm_ble_start_auto_conn(TRUE); if (p_cb->bg_conn_type == BTM_BLE_CONN_SELECTIVE) ret = btm_ble_start_select_conn(TRUE, btm_cb.ble_ctr_cb.p_select_cback); } return ret; }
接下来又来到了这个函数:btm_ble_start_auto_conn,上面分析了当设备仍然和主机有连接的情况,当前设备已经断开,是真正需要回连的时候,
BOOLEAN btm_ble_start_auto_conn(BOOLEAN start) { tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb; BD_ADDR dummy_bda = {0}; BOOLEAN exec = TRUE; UINT16 scan_int; UINT16 scan_win; UINT8 own_addr_type = p_cb->addr_mgnt_cb.own_addr_type; UINT8 peer_addr_type = BLE_ADDR_PUBLIC; if (start) { if ( p_cb->conn_state == BLE_CONN_IDLE ) { exec = btm_execute_wl_dev_operation();//这里不会重复添加whitelist, memset. } /*这里会发现 bg connection 里面还有 设备需要回连*/ if (p_cb->conn_state == BLE_CONN_IDLE && background_connections_pending() && btm_ble_topology_check(BTM_BLE_STATE_INIT)) { p_cb->wl_state |= BTM_BLE_WL_INIT;//设置状态 scan_int = (p_cb->scan_int == BTM_BLE_SCAN_PARAM_UNDEF) ? BTM_BLE_SCAN_SLOW_INT_1 : p_cb->scan_int; scan_win = (p_cb->scan_win == BTM_BLE_SCAN_PARAM_UNDEF) ? BTM_BLE_SCAN_SLOW_WIN_1 : p_cb->scan_win; /*发送0x200d到controller*/ if (!btsnd_hcic_ble_create_ll_conn (scan_int, /* UINT16 scan_int */ scan_win, /* UINT16 scan_win */ 0x01, /* UINT8 white_list */ peer_addr_type, /* UINT8 addr_type_peer */ dummy_bda, /* BD_ADDR bda_peer */ own_addr_type, /* UINT8 addr_type_own */ BTM_BLE_CONN_INT_MIN_DEF, /* UINT16 conn_int_min */ BTM_BLE_CONN_INT_MIN_DEF, BTM_BLE_CONN_SLAVE_LATENCY_DEF, /* UINT16 conn_latency */ BTM_BLE_CONN_TIMEOUT_DEF, /* UINT16 conn_timeout */ 0, /* UINT16 min_len */ 0)) /* UINT16 max_len */ { /* start auto connection failed */ exec = FALSE; p_cb->wl_state &= ~BTM_BLE_WL_INIT; } else { btm_ble_set_conn_st (BLE_BG_CONN);//设置连的状态 } } else { exec = FALSE; } } else { if (p_cb->conn_state == BLE_BG_CONN) { btsnd_hcic_ble_create_conn_cancel(); btm_ble_set_conn_st (BLE_CONN_CANCEL); p_cb->wl_state &= ~BTM_BLE_WL_INIT; } else { BTM_TRACE_DEBUG("conn_st = %d, not in auto conn state, cannot stop", p_cb->conn_state); exec = FALSE; } } return exec; }
host端向controller端发起了连接的请求,也即回连请求,.
对于Le 设备的回连,暂且分析到这里.