蓝牙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; 
    }
}

 

这里 分为两个步骤:

  1.  BTA_GATTC_Open(bta_hh_cb.gatt_if, p_cb->addr, FALSE, BTA_GATT_TRANSPORT_LE);
  2. 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 设备的回连,暂且分析到这里.

 

 


 

posted @ 2018-12-18 20:35  雪山飞燕  阅读(6365)  评论(0编辑  收藏  举报