在 文章中分析了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