/*******************************************************************************
**
** Function         smp_encrypt_data
**
** Description      This function is called to generate passkey.
**
** Returns          void
**
*******************************************************************************/
BOOLEAN smp_encrypt_data (UINT8 *key, UINT8 key_len,
                          UINT8 *plain_text, UINT8 pt_len,
                          tSMP_ENC *p_out)
{
    aes_context     ctx;
    UINT8           *p_start = NULL;
    UINT8           *p = NULL;
    UINT8           *p_rev_data = NULL;    /* input data in big endilan format */
    UINT8           *p_rev_key = NULL;     /* input key in big endilan format */
    UINT8           *p_rev_output = NULL;  /* encrypted output in big endilan format */

    SMP_TRACE_DEBUG ("smp_encrypt_data");
    if ( (p_out == NULL ) || (key_len != SMP_ENCRYT_KEY_SIZE) )
    {
        BTM_TRACE_ERROR ("smp_encrypt_data Failed");
        return(FALSE);
    }

    if ((p_start = (UINT8 *)GKI_getbuf((SMP_ENCRYT_DATA_SIZE*4))) == NULL)
    {
        BTM_TRACE_ERROR ("smp_encrypt_data Failed unable to allocate buffer");
        return(FALSE);
    }

    if (pt_len > SMP_ENCRYT_DATA_SIZE)
        pt_len = SMP_ENCRYT_DATA_SIZE;

    memset(p_start, 0, SMP_ENCRYT_DATA_SIZE * 4);
    p = p_start;
    ARRAY_TO_STREAM (p, plain_text, pt_len); /* byte 0 to byte 15 */
    p_rev_data = p = p_start + SMP_ENCRYT_DATA_SIZE; /* start at byte 16 */
    REVERSE_ARRAY_TO_STREAM (p, p_start, SMP_ENCRYT_DATA_SIZE);  /* byte 16 to byte 31 */
    p_rev_key = p; /* start at byte 32 */
    REVERSE_ARRAY_TO_STREAM (p, key, SMP_ENCRYT_KEY_SIZE); /* byte 32 to byte 47 */

    smp_debug_print_nbyte_little_endian(key, (const UINT8 *)"Key", SMP_ENCRYT_KEY_SIZE);
    smp_debug_print_nbyte_little_endian(p_start, (const UINT8 *)"Plain text", SMP_ENCRYT_DATA_SIZE);
    p_rev_output = p;
    aes_set_key(p_rev_key, SMP_ENCRYT_KEY_SIZE, &ctx);
    aes_encrypt(p_rev_data, p, &ctx);  /* outputs in byte 48 to byte 63 */

    p = p_out->param_buf;
    REVERSE_ARRAY_TO_STREAM (p, p_rev_output, SMP_ENCRYT_DATA_SIZE);
    smp_debug_print_nbyte_little_endian(p_out->param_buf, (const UINT8 *)"Encrypted text", SMP_ENCRYT_KEY_SIZE);

    p_out->param_len = SMP_ENCRYT_KEY_SIZE;
    p_out->status = HCI_SUCCESS;
    p_out->opcode =  HCI_BLE_ENCRYPT;

    GKI_freebuf(p_start);

    return(TRUE);
}
/*******************************************************************************
**
** Function         btm_public_addr_to_random_pseudo
**
** Description      This function map a static BD address to a pseudo random address
**                  in security database.
**
*******************************************************************************/
BOOLEAN btm_public_addr_to_random_pseudo(BD_ADDR bd_addr, UINT8 *p_addr_type, BOOLEAN read_irk)
{
#if BLE_PRIVACY_SPT == TRUE
    tBTM_SEC_DEV_REC    *p_dev_rec = btm_find_dev_by_public_static_addr(bd_addr);

    BTM_TRACE_EVENT ("btm_public_addr_to_random_pseudo");

    /* evt reported on static address, map static address to random pseudo */
    if (p_dev_rec  != NULL && read_irk &&
        /* static address is not static address */
        memcmp(p_dev_rec->bd_addr, bd_addr, BD_ADDR_LEN) != 0)
        /* update current random */
        btm_ble_read_irk_entry(p_dev_rec->ble.static_addr);
    if (p_dev_rec != NULL)
    {
        /* assign the orginal random to be the current report address */
        memcpy(bd_addr, p_dev_rec->bd_addr, BD_ADDR_LEN);
        /* always be a resolvable random if a match is found */
        *p_addr_type = BLE_ADDR_RANDOM;

        BTM_TRACE_ERROR("matched a public/reconnect address and map to random pseudo");

        return TRUE;
    }
#endif
    return FALSE;
}
/*******************************************************************************
**
** Function         btm_ble_batchscan_deq_rep_q
**
** Description      dequeue a batchscan report  in q when command complete
**                  is received
**
** Returns          void
**
*******************************************************************************/
void btm_ble_batchscan_deq_rep_data(UINT8 report_format, tBTM_BLE_REF_VALUE *p_ref_value,
                                 UINT8 *p_num_records, UINT8 **p_data, UINT16 *p_data_len)
{
    int index = 0;

    for (index = 0; index < BTM_BLE_BATCH_REP_MAIN_Q_SIZE; index++)
    {
        if (report_format == ble_batchscan_cb.main_rep_q.rep_mode[index])
            break;
    }

    if (BTM_BLE_BATCH_REP_MAIN_Q_SIZE == index)
    {
        BTM_TRACE_ERROR("btm_ble_batchscan_deq_rep_data: rep_format:%d not found", report_format);
        return;
    }

    *p_num_records = ble_batchscan_cb.main_rep_q.num_records[index];
    *p_ref_value = ble_batchscan_cb.main_rep_q.ref_value[index];
    *p_data = ble_batchscan_cb.main_rep_q.p_data[index];
    *p_data_len = ble_batchscan_cb.main_rep_q.data_len[index];

    ble_batchscan_cb.main_rep_q.p_data[index] = NULL;
    ble_batchscan_cb.main_rep_q.data_len[index] = 0;
    ble_batchscan_cb.main_rep_q.rep_mode[index] = 0;
    ble_batchscan_cb.main_rep_q.ref_value[index] = 0;
    ble_batchscan_cb.main_rep_q.num_records[index] = 0;

    BTM_TRACE_DEBUG("btm_ble_batchscan_deq_rep_data: index:%d, rep %d, num %d, data_len %d",
        index, report_format, *p_num_records, *p_data_len);

    ble_batchscan_cb.main_rep_q.pending_idx = (ble_batchscan_cb.main_rep_q.pending_idx + 1)
                                            % BTM_BLE_BATCH_SCAN_MAX;
}
Ejemplo n.º 4
0
/*******************************************************************************
**
** Function         btm_enq_wl_dev_operation
**
** Description      enqueue the pending whitelist device operation(loading or removing).
*******************************************************************************/
void btm_enq_wl_dev_operation(BOOLEAN to_add, BD_ADDR bd_addr)
{
    tBTM_BLE_WL_OP *p_dev_op = btm_cb.ble_ctr_cb.wl_op_q;
    UINT8   i = 0;

    for (i = 0; i < BTM_BLE_MAX_BG_CONN_DEV_NUM; i ++, p_dev_op ++)
    {
        if (p_dev_op->in_use && !memcmp(p_dev_op->bd_addr, bd_addr, BD_ADDR_LEN))
        {
            p_dev_op->to_add = to_add;
            return;
        }
        else if (!p_dev_op->in_use)
            break;
    }
    if (i != BTM_BLE_MAX_BG_CONN_DEV_NUM)
    {
        p_dev_op->in_use = TRUE;
        p_dev_op->to_add = to_add;
        memcpy(p_dev_op->bd_addr, bd_addr, BD_ADDR_LEN);
    }
    else
    {
        BTM_TRACE_ERROR("max pending WL operation reached, discard");
    }
    return;
}
Ejemplo n.º 5
0
/*******************************************************************************
**
** Function         btm_ble_refresh_peer_resolvable_private_addr
**
** Description      This function refresh the currently used resolvable remote private address into security
**                  database and set active connection address.
**
*******************************************************************************/
void btm_ble_refresh_peer_resolvable_private_addr(BD_ADDR pseudo_bda, BD_ADDR rpa,
        UINT8 rra_type)
{
#if BLE_PRIVACY_SPT == TRUE
    UINT8 rra_dummy = FALSE;
    BD_ADDR dummy_bda = {0};

    if (memcmp(dummy_bda, rpa, BD_ADDR_LEN) == 0) {
        rra_dummy = TRUE;
    }

    /* update security record here, in adv event or connection complete process */
    tBTM_SEC_DEV_REC *p_sec_rec = btm_find_dev(pseudo_bda);
    if (p_sec_rec != NULL) {
        memcpy(p_sec_rec->ble.cur_rand_addr, rpa, BD_ADDR_LEN);

        /* unknown, if dummy address, set to static */
        if (rra_type == BTM_BLE_ADDR_PSEUDO) {
            p_sec_rec->ble.active_addr_type = rra_dummy ? BTM_BLE_ADDR_STATIC : BTM_BLE_ADDR_RRA;
        } else {
            p_sec_rec->ble.active_addr_type = rra_type;
        }
    } else {
        BTM_TRACE_ERROR("No matching known device in record");
        return;
    }

    BTM_TRACE_DEBUG("%s: active_addr_type: %d ",
                    __func__, p_sec_rec->ble.active_addr_type);

    /* connection refresh remote address */
    tACL_CONN *p_acl = btm_bda_to_acl(p_sec_rec->bd_addr, BT_TRANSPORT_LE);
    if (p_acl == NULL) {
        p_acl = btm_bda_to_acl(p_sec_rec->ble.pseudo_addr, BT_TRANSPORT_LE);
    }

    if (p_acl != NULL) {
        if (rra_type == BTM_BLE_ADDR_PSEUDO) {
            /* use static address, resolvable_private_addr is empty */
            if (rra_dummy) {
                p_acl->active_remote_addr_type = p_sec_rec->ble.static_addr_type;
                memcpy(p_acl->active_remote_addr, p_sec_rec->ble.static_addr, BD_ADDR_LEN);
            } else {
                p_acl->active_remote_addr_type = BLE_ADDR_RANDOM;
                memcpy(p_acl->active_remote_addr, rpa, BD_ADDR_LEN);
            }
        } else {
            p_acl->active_remote_addr_type = rra_type;
            memcpy(p_acl->active_remote_addr, rpa, BD_ADDR_LEN);
        }

        BTM_TRACE_DEBUG("p_acl->active_remote_addr_type: %d ", p_acl->active_remote_addr_type);
        BTM_TRACE_DEBUG("%s conn_addr: %02x:%02x:%02x:%02x:%02x:%02x",
                        __func__, p_acl->active_remote_addr[0], p_acl->active_remote_addr[1],
                        p_acl->active_remote_addr[2], p_acl->active_remote_addr[3],
                        p_acl->active_remote_addr[4], p_acl->active_remote_addr[5]);
    }
#endif
}
Ejemplo n.º 6
0
/*******************************************************************************
**
** Function         btm_ble_initiate_select_conn
**
** Description      This function is to start/stop selective connection procedure.
**
** Parameters       start: TRUE to start; FALSE to stop.
**                  p_select_cback: callback function to return application
**                                  selection.
**
** Returns          BOOLEAN: selective connectino procedure is started.
**
*******************************************************************************/
void btm_ble_initiate_select_conn(BD_ADDR bda)
{
    BTM_TRACE_EVENT ("btm_ble_initiate_select_conn");

    /* use direct connection procedure to initiate connection */
    if (!L2CA_ConnectFixedChnl(L2CAP_ATT_CID, bda))
    {
        BTM_TRACE_ERROR("btm_ble_initiate_select_conn failed");
    }
}
/*******************************************************************************
**
** Function         btm_ble_enqueue_direct_conn_req
**
** Description      This function enqueue the direct connection request
**
** Returns          None.
**
*******************************************************************************/
void btm_ble_enqueue_direct_conn_req(void *p_param)
{
    tBTM_BLE_CONN_REQ   *p = (tBTM_BLE_CONN_REQ *)GKI_getbuf(sizeof(tBTM_BLE_CONN_REQ));

    if (NULL != p)
    {
        p->p_param = p_param;
        GKI_enqueue (&btm_cb.ble_ctr_cb.conn_pending_q, p);
    } else {
        BTM_TRACE_ERROR ("%s: Failed to get memory", __FUNCTION__);
    }
}
/*******************************************************************************
**
** Function         btm_ble_refresh_rra
**
** Description      This function refresh the currently used RRA into security
**                  database and set active connection address.
**
*******************************************************************************/
void btm_ble_refresh_rra(BD_ADDR static_bda, BD_ADDR rra)
{
#if BLE_PRIVACY_SPT == TRUE
    tBTM_SEC_DEV_REC    *p_sec_rec = btm_find_dev_by_public_static_addr(static_bda);
    tACL_CONN           *p_acl = btm_bda_to_acl (p_sec_rec->bd_addr, BT_TRANSPORT_LE);
    UINT8               rra_dummy = FALSE;
    BD_ADDR             dummy_bda = {0};

    BTM_TRACE_ERROR("btm_ble_refresh_rra");

    if (memcmp(dummy_bda, rra, BD_ADDR_LEN) == 0)
        rra_dummy = TRUE;

    /* connection refresh RRA */
    if (p_acl != NULL /* && memcmp(p_acl->active_remote_addr, dummy_bda, BD_ADDR_LEN) == 0 */)
    {
        /* use static address, rra is empty */
        if (rra_dummy && p_sec_rec != NULL)
        {
            p_acl->active_remote_addr_type = p_sec_rec->ble.static_addr_type;
            memcpy(p_acl->active_remote_addr, p_sec_rec->ble.static_addr, BD_ADDR_LEN);
        }
        else
        {
            p_acl->active_remote_addr_type = BLE_ADDR_RANDOM;
            memcpy(p_acl->active_remote_addr, rra, BD_ADDR_LEN);
        }
    }
    /* update security record here, in adv event or connection complete process */
    if (p_sec_rec != NULL)
    {
        memcpy(p_sec_rec->ble.cur_rand_addr, rra, BD_ADDR_LEN);
        p_sec_rec->ble.active_addr_type = rra_dummy ? BTM_BLE_ADDR_STATIC: BTM_BLE_ADDR_RRA;
    }
    else
    {
        BTM_TRACE_ERROR("No matching known device in record");
    }
#endif
}
/*******************************************************************************
**
** Function         btm_send_pending_direct_conn
**
** Description      This function send the pending direct connection request in queue
**
** Returns          TRUE if started, FALSE otherwise
**
*******************************************************************************/
BOOLEAN btm_send_pending_direct_conn(void )
{
    tBTM_BLE_CONN_REQ *p_req;
    BOOLEAN     rt = FALSE;

    if ( btm_cb.ble_ctr_cb.conn_pending_q.count )
    {
        if (NULL != (p_req = (tBTM_BLE_CONN_REQ*)GKI_dequeue (&btm_cb.ble_ctr_cb.conn_pending_q)))
        {
            rt = l2cble_init_direct_conn((tL2C_LCB *)(p_req->p_param));
            GKI_freebuf((void *)p_req);
        } else {
            BTM_TRACE_ERROR ("%s: Failed to get pending connection", __FUNCTION__);
        }
    }

    return rt;
}
Ejemplo n.º 10
0
/*******************************************************************************
**
** Function         BTM_RegisterForVSEvents
**
** Description      This function is called to register/deregister for vendor
**                  specific HCI events.
**
**                  If is_register=TRUE, then the function will be registered;
**                  if is_register=FALSE, then the function will be deregistered.
**
** Returns          BTM_SUCCESS if successful,
**                  BTM_BUSY if maximum number of callbacks have already been
**                           registered.
**
*******************************************************************************/
tBTM_STATUS BTM_RegisterForVSEvents (tBTM_VS_EVT_CB *p_cb, BOOLEAN is_register)
{
    tBTM_STATUS retval = BTM_SUCCESS;
    UINT8 i, free_idx = BTM_MAX_VSE_CALLBACKS;

    /* See if callback is already registered */
    for (i=0; i<BTM_MAX_VSE_CALLBACKS; i++)
    {
        if (btm_cb.devcb.p_vend_spec_cb[i] == NULL)
        {
            /* Found a free slot. Store index */
            free_idx = i;
        }
        else if (btm_cb.devcb.p_vend_spec_cb[i] == p_cb)
        {
            /* Found callback in lookup table. If deregistering, clear the entry. */
            if (is_register == FALSE)
            {
                btm_cb.devcb.p_vend_spec_cb[i] = NULL;
                BTM_TRACE_EVENT("BTM Deregister For VSEvents is successfully");
            }
            return (BTM_SUCCESS);
        }
    }

    /* Didn't find callback. Add callback to free slot if registering */
    if (is_register)
    {
        if (free_idx < BTM_MAX_VSE_CALLBACKS)
        {
            btm_cb.devcb.p_vend_spec_cb[free_idx] = p_cb;
            BTM_TRACE_EVENT("BTM Register For VSEvents is successfully");
        }
        else
        {
            /* No free entries available */
            BTM_TRACE_ERROR ("BTM_RegisterForVSEvents: too many callbacks registered");

            retval = BTM_NO_RESOURCES;
        }
    }

    return (retval);
}
Ejemplo n.º 11
0
/*******************************************************************************
**
** 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)
    {
        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;
}
/*******************************************************************************
**
** Function         btm_update_dev_to_white_list
**
** Description      This function adds a device into white list.
*******************************************************************************/
BOOLEAN btm_update_dev_to_white_list(BOOLEAN to_add, BD_ADDR bd_addr)
{
    /* look up the sec device record, and find the address */
    tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
    UINT8       wl_state = BTM_BLE_WL_INIT;

    if ((to_add && p_cb->num_empty_filter == 0) ||
        (!to_add && p_cb->num_empty_filter == p_cb->max_filter_entries))
    {
        BTM_TRACE_ERROR("WL full or empty, unable to update to WL. num_entry available: %d",
                          p_cb->num_empty_filter);
        return FALSE;
    }

    btm_suspend_wl_activity(wl_state);

    /* enq pending WL device operation */
    btm_enq_wl_dev_operation(to_add, bd_addr);

    btm_resume_wl_activity(wl_state);

    return TRUE;
}
Ejemplo n.º 13
0
/*******************************************************************************
**
** Function         btm_decode_ext_features_page
**
** Description      This function is decodes a features page.
**
** Returns          void
**
*******************************************************************************/
static void btm_decode_ext_features_page (UINT8 page_number, const UINT8 *p_features)
{
    BTM_TRACE_DEBUG ("btm_decode_ext_features_page page: %d", page_number);
    switch (page_number)
    {
    /* Extended (Legacy) Page 0 */
    case HCI_EXT_FEATURES_PAGE_0:

        /* Create ACL supported packet types mask */
        btm_cb.btm_acl_pkt_types_supported = (BTM_ACL_PKT_TYPES_MASK_DH1 +
                                              BTM_ACL_PKT_TYPES_MASK_DM1);

        if (HCI_3_SLOT_PACKETS_SUPPORTED(p_features))
            btm_cb.btm_acl_pkt_types_supported |= (BTM_ACL_PKT_TYPES_MASK_DH3 +
                                                   BTM_ACL_PKT_TYPES_MASK_DM3);

        if (HCI_5_SLOT_PACKETS_SUPPORTED(p_features))
            btm_cb.btm_acl_pkt_types_supported |= (BTM_ACL_PKT_TYPES_MASK_DH5 +
                                                   BTM_ACL_PKT_TYPES_MASK_DM5);

        /* Add in EDR related ACL types */
        if (!HCI_EDR_ACL_2MPS_SUPPORTED(p_features))
        {
            btm_cb.btm_acl_pkt_types_supported |= (BTM_ACL_PKT_TYPES_MASK_NO_2_DH1 +
                                                   BTM_ACL_PKT_TYPES_MASK_NO_2_DH3 +
                                                   BTM_ACL_PKT_TYPES_MASK_NO_2_DH5);
        }

        if (!HCI_EDR_ACL_3MPS_SUPPORTED(p_features))
        {
            btm_cb.btm_acl_pkt_types_supported |= (BTM_ACL_PKT_TYPES_MASK_NO_3_DH1 +
                                                   BTM_ACL_PKT_TYPES_MASK_NO_3_DH3 +
                                                   BTM_ACL_PKT_TYPES_MASK_NO_3_DH5);
        }

        /* Check to see if 3 and 5 slot packets are available */
        if (HCI_EDR_ACL_2MPS_SUPPORTED(p_features) ||
            HCI_EDR_ACL_3MPS_SUPPORTED(p_features))
        {
            if (!HCI_3_SLOT_EDR_ACL_SUPPORTED(p_features))
                btm_cb.btm_acl_pkt_types_supported |= (BTM_ACL_PKT_TYPES_MASK_NO_2_DH3 +
                                                       BTM_ACL_PKT_TYPES_MASK_NO_3_DH3);

            if (!HCI_5_SLOT_EDR_ACL_SUPPORTED(p_features))
                btm_cb.btm_acl_pkt_types_supported |= (BTM_ACL_PKT_TYPES_MASK_NO_2_DH5 +
                                                       BTM_ACL_PKT_TYPES_MASK_NO_3_DH5);
        }

        BTM_TRACE_DEBUG("Local supported ACL packet types: 0x%04x",
                         btm_cb.btm_acl_pkt_types_supported);

        /* Create (e)SCO supported packet types mask */
        btm_cb.btm_sco_pkt_types_supported = 0;
#if BTM_SCO_INCLUDED == TRUE
        btm_cb.sco_cb.esco_supported = FALSE;
#endif
        if (HCI_SCO_LINK_SUPPORTED(p_features))
        {
            btm_cb.btm_sco_pkt_types_supported = BTM_SCO_PKT_TYPES_MASK_HV1;

            if (HCI_HV2_PACKETS_SUPPORTED(p_features))
                btm_cb.btm_sco_pkt_types_supported |= BTM_SCO_PKT_TYPES_MASK_HV2;

            if (HCI_HV3_PACKETS_SUPPORTED(p_features))
                btm_cb.btm_sco_pkt_types_supported |= BTM_SCO_PKT_TYPES_MASK_HV3;
        }

        if (HCI_ESCO_EV3_SUPPORTED(p_features))
            btm_cb.btm_sco_pkt_types_supported |= BTM_SCO_PKT_TYPES_MASK_EV3;

        if (HCI_ESCO_EV4_SUPPORTED(p_features))
            btm_cb.btm_sco_pkt_types_supported |= BTM_SCO_PKT_TYPES_MASK_EV4;

        if (HCI_ESCO_EV5_SUPPORTED(p_features))
            btm_cb.btm_sco_pkt_types_supported |= BTM_SCO_PKT_TYPES_MASK_EV5;
#if BTM_SCO_INCLUDED == TRUE
        if (btm_cb.btm_sco_pkt_types_supported & BTM_ESCO_LINK_ONLY_MASK)
        {
            btm_cb.sco_cb.esco_supported = TRUE;

            /* Add in EDR related eSCO types */
            if (HCI_EDR_ESCO_2MPS_SUPPORTED(p_features))
            {
                if (!HCI_3_SLOT_EDR_ESCO_SUPPORTED(p_features))
                    btm_cb.btm_sco_pkt_types_supported |= BTM_SCO_PKT_TYPES_MASK_NO_2_EV5;
            }
            else
            {
                btm_cb.btm_sco_pkt_types_supported |= (BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 +
                                                       BTM_SCO_PKT_TYPES_MASK_NO_2_EV5);
            }

            if (HCI_EDR_ESCO_3MPS_SUPPORTED(p_features))
            {
                if (!HCI_3_SLOT_EDR_ESCO_SUPPORTED(p_features))
                    btm_cb.btm_sco_pkt_types_supported |= BTM_SCO_PKT_TYPES_MASK_NO_3_EV5;
            }
            else
            {
                btm_cb.btm_sco_pkt_types_supported |= (BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 +
                                                       BTM_SCO_PKT_TYPES_MASK_NO_3_EV5);
            }
        }
#endif

        BTM_TRACE_DEBUG("Local supported SCO packet types: 0x%04x",
                         btm_cb.btm_sco_pkt_types_supported);

        /* Create Default Policy Settings */
        if (HCI_SWITCH_SUPPORTED(p_features))
            btm_cb.btm_def_link_policy |= HCI_ENABLE_MASTER_SLAVE_SWITCH;
        else
            btm_cb.btm_def_link_policy &= ~HCI_ENABLE_MASTER_SLAVE_SWITCH;

        if (HCI_HOLD_MODE_SUPPORTED(p_features))
            btm_cb.btm_def_link_policy |= HCI_ENABLE_HOLD_MODE;
        else
            btm_cb.btm_def_link_policy &= ~HCI_ENABLE_HOLD_MODE;

        if (HCI_SNIFF_MODE_SUPPORTED(p_features))
            btm_cb.btm_def_link_policy |= HCI_ENABLE_SNIFF_MODE;
        else
            btm_cb.btm_def_link_policy &= ~HCI_ENABLE_SNIFF_MODE;

        if (HCI_PARK_MODE_SUPPORTED(p_features))
            btm_cb.btm_def_link_policy |= HCI_ENABLE_PARK_MODE;
        else
            btm_cb.btm_def_link_policy &= ~HCI_ENABLE_PARK_MODE;

        btm_sec_dev_reset ();

        if (HCI_LMP_INQ_RSSI_SUPPORTED(p_features))
        {
            if (HCI_EXT_INQ_RSP_SUPPORTED(p_features))
                BTM_SetInquiryMode (BTM_INQ_RESULT_EXTENDED);
            else
                BTM_SetInquiryMode (BTM_INQ_RESULT_WITH_RSSI);
        }

#if L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE
        if( HCI_NON_FLUSHABLE_PB_SUPPORTED(p_features))
            l2cu_set_non_flushable_pbf(TRUE);
        else
            l2cu_set_non_flushable_pbf(FALSE);
#endif
        BTM_SetPageScanType (BTM_DEFAULT_SCAN_TYPE);
        BTM_SetInquiryScanType (BTM_DEFAULT_SCAN_TYPE);

        break;

    /* Extended Page 1 */
    case HCI_EXT_FEATURES_PAGE_1:
        /* Nothing to do for page 1 */
        break;

    /* Extended Page 2 */
    case HCI_EXT_FEATURES_PAGE_2:
        /* Nothing to do for page 2 */
        break;

    default:
        BTM_TRACE_ERROR("btm_decode_ext_features_page page=%d unknown", page_number);
        break;
    }
}
Ejemplo n.º 14
0
/*******************************************************************************
**
** Function         btm_ble_start_select_conn
**
** Description      This function is to start/stop selective connection procedure.
**
** Parameters       start: TRUE to start; FALSE to stop.
**                  p_select_cback: callback function to return application
**                                  selection.
**
** Returns          BOOLEAN: selective connectino procedure is started.
**
*******************************************************************************/
BOOLEAN btm_ble_start_select_conn(BOOLEAN start, tBTM_BLE_SEL_CBACK *p_select_cback)
{
    tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
    UINT32 scan_int = p_cb->scan_int == BTM_BLE_SCAN_PARAM_UNDEF ? BTM_BLE_SCAN_FAST_INT : p_cb->scan_int;
    UINT32 scan_win = p_cb->scan_win == BTM_BLE_SCAN_PARAM_UNDEF ? BTM_BLE_SCAN_FAST_WIN : p_cb->scan_win;

    BTM_TRACE_EVENT ("%s", __func__);

    if (start)
    {
        if (!BTM_BLE_IS_SCAN_ACTIVE(p_cb->scan_activity))
        {
            if (p_select_cback != NULL)
                btm_cb.ble_ctr_cb.p_select_cback = p_select_cback;

            btm_execute_wl_dev_operation();

            btm_update_scanner_filter_policy(SP_ADV_WL);
            btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_PASS;

            /* Process advertising packets only from devices in the white list */
            if (btm_cb.cmn_ble_vsc_cb.extended_scan_support == 0)
            {
                /* use passive scan by default */
                if (!btsnd_hcic_ble_set_scan_params(BTM_BLE_SCAN_MODE_PASS,
                                                    scan_int,
                                                    scan_win,
                                                    p_cb->addr_mgnt_cb.own_addr_type,
                                                    SP_ADV_WL))
                {
                    return FALSE;
                }
            }
            else
            {
                if (!btm_ble_send_extended_scan_params(BTM_BLE_SCAN_MODE_PASS,
                                                       scan_int,
                                                       scan_win,
                                                       p_cb->addr_mgnt_cb.own_addr_type,
                                                       SP_ADV_WL))
                {
                    return FALSE;
                }
            }

            if (!btm_ble_topology_check(BTM_BLE_STATE_PASSIVE_SCAN))
            {
                BTM_TRACE_ERROR("peripheral device cannot initiate passive scan for a selective connection");
                return FALSE;
            }
            else if (background_connections_pending())
            {
#if BLE_PRIVACY_SPT == TRUE
                btm_ble_enable_resolving_list_for_platform(BTM_BLE_RL_SCAN);
#endif
                if (!btsnd_hcic_ble_set_scan_enable(TRUE, TRUE)) /* duplicate filtering enabled */
                     return FALSE;
                 /* mark up inquiry status flag */
                 p_cb->scan_activity |= BTM_LE_SELECT_CONN_ACTIVE;
                 p_cb->wl_state |= BTM_BLE_WL_SCAN;
            }
        }
        else
        {
            BTM_TRACE_ERROR("scan active, can not start selective connection procedure");
            return FALSE;
        }
    }
    else /* disable selective connection mode */
    {
        p_cb->scan_activity &= ~BTM_LE_SELECT_CONN_ACTIVE;
        p_cb->p_select_cback = NULL;
        p_cb->wl_state &= ~BTM_BLE_WL_SCAN;

        /* stop scanning */
        if (!BTM_BLE_IS_SCAN_ACTIVE(p_cb->scan_activity))
            btm_ble_stop_scan(); /* duplicate filtering enabled */
    }
    return TRUE;
}
/*******************************************************************************
**
** Function         btm_ble_start_select_conn
**
** Description      This function is to start/stop selective connection procedure.
**
** Parameters       start: TRUE to start; FALSE to stop.
**                  p_select_cback: callback function to return application
**                                  selection.
**
** Returns          BOOLEAN: selective connectino procedure is started.
**
*******************************************************************************/
BOOLEAN btm_ble_start_select_conn(BOOLEAN start,tBTM_BLE_SEL_CBACK   *p_select_cback)
{
    tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
    UINT16 scan_int, scan_win;

    BTM_TRACE_EVENT ("btm_ble_start_select_conn");

    scan_int = (p_cb->scan_int == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_INT : p_cb->scan_int;
    scan_win = (p_cb->scan_win == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_WIN : p_cb->scan_win;

    if (start)
    {
        if (!BTM_BLE_IS_SCAN_ACTIVE(p_cb->scan_activity))
        {
            if (p_select_cback != NULL)
                btm_cb.ble_ctr_cb.p_select_cback = p_select_cback;

            btm_execute_wl_dev_operation();

            btm_update_scanner_filter_policy(SP_ADV_WL);
            btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_PASS;

            if (!btsnd_hcic_ble_set_scan_params(BTM_BLE_SCAN_MODE_PASS,  /* use passive scan by default */
                                                scan_int, /* scan interval */
                                                scan_win,    /* scan window */
                                                p_cb->addr_mgnt_cb.own_addr_type,
                                                SP_ADV_WL)              /* process advertising packets only from devices in the White List */
                )
                return FALSE;

            if (!btm_ble_topology_check(BTM_BLE_STATE_PASSIVE_SCAN))
            {
                BTM_TRACE_ERROR("peripheral device cannot initiate passive scan for a selective connection");
                return FALSE;
            }
            else if (p_cb->bg_dev_num > 0 && btm_ble_count_unconn_dev_in_whitelist() > 0 )
            {

                if (!btsnd_hcic_ble_set_scan_enable(TRUE, TRUE)) /* duplicate filtering enabled */
                    return FALSE;

                /* mark up inquiry status flag */
                p_cb->scan_activity |= BTM_LE_SELECT_CONN_ACTIVE;
                p_cb->wl_state |= BTM_BLE_WL_SCAN;
            }
        }
        else
        {
            BTM_TRACE_ERROR("scan active, can not start selective connection procedure");
            return FALSE;
        }
    }
    else /* disable selective connection mode */
    {
        p_cb->scan_activity &= ~BTM_LE_SELECT_CONN_ACTIVE;
        p_cb->p_select_cback = NULL;

#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
        if (btm_cb.cmn_ble_vsc_cb.rpa_offloading == TRUE)
            btm_ble_vendor_disable_irk_list();
#endif
        p_cb->wl_state |= BTM_BLE_WL_SCAN;

        /* stop scanning */
        if (!BTM_BLE_IS_SCAN_ACTIVE(p_cb->scan_activity))
            btm_ble_stop_scan(); /* duplicate filtering enabled */
        btm_update_scanner_filter_policy(SP_ADV_ALL);
    }
    return TRUE;
}
/*******************************************************************************
**
** 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, scan_win;

    if (start)
    {
        if ( p_cb->conn_state == BLE_CONN_IDLE )
        {
            exec = btm_execute_wl_dev_operation();
        }
        if ((p_cb->conn_state == BLE_CONN_IDLE && btm_ble_count_unconn_dev_in_whitelist() > 0)
            && btm_ble_topology_check(BTM_BLE_STATE_INIT))
        {
#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
            /*enable offload if any unconn dev in WL are in IRK list*/
            if (btm_cb.cmn_ble_vsc_cb.rpa_offloading == TRUE && btm_ble_count_unconn_dev_in_wl_irk() > 0)
                btm_ble_vendor_enable_irk_feature(TRUE);
#endif
            scan_int = (p_cb->scan_int == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_SLOW_INT_1 : p_cb->scan_int;
            scan_win = (p_cb->scan_win == BTM_BLE_CONN_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     */
                                                BLE_ADDR_PUBLIC,        /* UINT8 addr_type_peer */
                                                dummy_bda,              /* BD_ADDR bda_peer     */
                                                p_cb->addr_mgnt_cb.own_addr_type,
                                                   /* UINT8 addr_type_own,
                                                   not allow random address for central  */
                                                BTM_BLE_CONN_INT_MIN_DEF,   /* UINT16 conn_int_min  */
                                                BTM_BLE_CONN_INT_MAX_DEF,   /* UINT16 conn_int_max  */
                                                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;
            }
            else
            {
                btm_ble_set_conn_st (BLE_BG_CONN);
                p_cb->wl_state |= BTM_BLE_WL_INIT;
            }
        }
        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
        {
#if 0
            BTM_TRACE_ERROR("conn_st = %d, not in auto conn state, can not stop.", p_cb->conn_state);
            exec = FALSE;
#endif
        }
    }
    return exec;
}