藍牙BLE設備斷線回連分析

在 文章中分析了Hogp的鏈接的流程 ,這裏分析一下回連的流程.html

在使用ble設備的過程當中,咱們發現當設備和主機配對以後,若是沒有解除配對,那麼即使設備和主機斷開,那麼也是能夠從新鏈接而不須要從新走配對的流程,這裏的分析的源代碼是Android7.0 .api

回連的大概的流程是:hogp 鏈接完成以後,會把當前的device 加入到whitelist裏面.,標記爲能夠回連的設備.當設備和主機斷開的時候,主機會根據whitelist裏面的設備來進行回連.安全

這裏咱們從hogp鏈接流程中將device加入到 whitelist的流程來開始分析.app

/*******************************************************************************
**
** 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 的實現:ide

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); 

 這裏的重點是第一個步驟,咱們依次分析:ui

bta_gattc_api.cthis

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 咱們直接看實際處理的函數 spa

bta_gattc_act.ccode

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 設備的回連,暫且分析到這裏.

相關文章
相關標籤/搜索