/******************************************************************************* ** ** 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; }
/******************************************************************************* ** ** 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; }
/******************************************************************************* ** ** 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 }
/******************************************************************************* ** ** 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; }
/******************************************************************************* ** ** 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); }
/******************************************************************************* ** ** 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; }
/******************************************************************************* ** ** 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; } }
/******************************************************************************* ** ** 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; }