/******************************************************************************* ** ** 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_update_bg_conn_list ** ** Description This function update the local background connection device list. *******************************************************************************/ BOOLEAN btm_update_bg_conn_list(BOOLEAN to_add, BD_ADDR bd_addr) { tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb; tBTM_LE_BG_CONN_DEV *p_bg_dev = &p_cb->bg_dev_list[0], *p_next, *p_cur; UINT8 i, j; BOOLEAN ret = FALSE; BTM_TRACE_EVENT ("btm_update_bg_conn_list"); if ((to_add && (p_cb->bg_dev_num == BTM_BLE_MAX_BG_CONN_DEV_NUM || p_cb->num_empty_filter == 0))) { BTM_TRACE_DEBUG("num_empty_filter = %d", p_cb->num_empty_filter); return ret; } for (i = 0; i < BTM_BLE_MAX_BG_CONN_DEV_NUM; i ++, p_bg_dev ++) { if (p_bg_dev->in_use && memcmp(p_bg_dev->bd_addr, bd_addr, BD_ADDR_LEN) == 0) { if (!to_add) { memset(p_bg_dev, 0, sizeof(tBTM_LE_BG_CONN_DEV)); p_cb->bg_dev_num --; p_cur = p_bg_dev; p_next = p_bg_dev + 1; for (j = i + 1; j < BTM_BLE_MAX_BG_CONN_DEV_NUM && p_next->in_use; j ++, p_cur ++, p_next ++) { memcpy(p_cur, p_next, sizeof(tBTM_LE_BG_CONN_DEV)); memset(p_next, 0, sizeof(tBTM_LE_BG_CONN_DEV)); } } ret = TRUE; break; } else if (!p_bg_dev->in_use && to_add) { BTM_TRACE_DEBUG("add new WL entry in bg_dev_list"); memcpy(p_bg_dev->bd_addr, bd_addr, BD_ADDR_LEN); p_bg_dev->in_use = TRUE; p_cb->bg_dev_num ++; ret = TRUE; break; } } return ret; }
/******************************************************************************* ** ** Function btm_gen_resolve_paddr_cmpl ** ** Description This is callback functioin when resolvable private address ** generation is complete. ** ** Returns void ** *******************************************************************************/ static void btm_gen_resolve_paddr_cmpl(tSMP_ENC *p) { tBTM_LE_RANDOM_CB *p_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb; BTM_TRACE_EVENT ("btm_gen_resolve_paddr_cmpl"); if (p) { /* set hash to be LSB of rpAddress */ p_cb->private_addr[5] = p->param_buf[0]; p_cb->private_addr[4] = p->param_buf[1]; p_cb->private_addr[3] = p->param_buf[2]; /* set it to controller */ btsnd_hcic_ble_set_random_addr(p_cb->private_addr); p_cb->own_addr_type = BLE_ADDR_RANDOM; /* start a periodical timer to refresh random addr */ btu_stop_timer_oneshot(&p_cb->raddr_timer_ent); #if (BTM_BLE_CONFORMANCE_TESTING == TRUE) btu_start_timer_oneshot(&p_cb->raddr_timer_ent, BTU_TTYPE_BLE_RANDOM_ADDR, btm_cb.ble_ctr_cb.rpa_tout); #else btu_start_timer_oneshot(&p_cb->raddr_timer_ent, BTU_TTYPE_BLE_RANDOM_ADDR, BTM_BLE_PRIVATE_ADDR_INT); #endif } else { /* random address set failure */ BTM_TRACE_DEBUG("set random address failed"); } }
/******************************************************************************* ** ** Function btm_gen_non_resolve_paddr_cmpl ** ** Description This is the callback function when non-resolvable private ** function is generated and write to controller. ** ** Returns void ** *******************************************************************************/ static void btm_gen_non_resolve_paddr_cmpl(tBTM_RAND_ENC *p) { tBTM_LE_RANDOM_CB *p_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb; tBTM_BLE_ADDR_CBACK *p_cback = p_cb->p_generate_cback; void *p_data = p_cb->p; UINT8 *pp; BD_ADDR static_random; BTM_TRACE_EVENT ("btm_gen_non_resolve_paddr_cmpl"); p_cb->p_generate_cback = NULL; if (p) { pp = p->param_buf; STREAM_TO_BDADDR(static_random, pp); /* mask off the 2 MSB */ static_random[0] &= BLE_STATIC_PRIVATE_MSB_MASK; /* report complete */ if (p_cback) (* p_cback)(static_random, p_data); } else { BTM_TRACE_DEBUG("btm_gen_non_resolvable_private_addr failed"); if (p_cback) (* p_cback)(NULL, p_data); } }
/******************************************************************************* ** ** Function btm_ble_match_random_bda ** ** Description This function match the random address to the appointed device ** record, starting from calculating IRK. If record index exceed ** the maximum record number, matching failed and send callback. ** ** Returns None. ** *******************************************************************************/ static BOOLEAN btm_ble_match_random_bda(UINT16 rec_index) { /* use the 3 MSB of bd address as prand */ tBTM_LE_RANDOM_CB *p_mgnt_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb; UINT8 rand[3]; rand[0] = p_mgnt_cb->random_bda[2]; rand[1] = p_mgnt_cb->random_bda[1]; rand[2] = p_mgnt_cb->random_bda[0]; BTM_TRACE_EVENT("%s rec_index = %d", __func__, rec_index); if (rec_index < BTM_SEC_MAX_DEVICE_RECORDS) { tSMP_ENC output; tBTM_SEC_DEV_REC *p_dev_rec; p_dev_rec = &btm_cb.sec_dev_rec[rec_index]; BTM_TRACE_DEBUG("sec_flags = %02x device_type = %d", p_dev_rec->sec_flags, p_dev_rec->device_type); if ((p_dev_rec->device_type & BT_DEVICE_TYPE_BLE) && (p_dev_rec->ble.key_type & BTM_LE_KEY_PID)) { /* generate X = E irk(R0, R1, R2) and R is random address 3 LSO */ SMP_Encrypt(p_dev_rec->ble.keys.irk, BT_OCTET16_LEN, &rand[0], 3, &output); return btm_ble_proc_resolve_x(&output); } else { // not completed return FALSE; } } else { /* no match found */ btm_ble_resolve_address_cmpl(); return TRUE; } }
/******************************************************************************* ** ** Function btm_ble_addr_resolvable ** ** Description This function checks if a RPA is resolvable by the device key. ** ** Returns TRUE is resolvable; FALSE otherwise. ** *******************************************************************************/ BOOLEAN btm_ble_addr_resolvable (BD_ADDR rpa, tBTM_SEC_DEV_REC *p_dev_rec) { BOOLEAN rt = FALSE; #if (SMP_INCLUDED == TRUE) if (!BTM_BLE_IS_RESOLVE_BDA(rpa)) { return rt; } UINT8 rand[3]; tSMP_ENC output; if ((p_dev_rec->device_type & BT_DEVICE_TYPE_BLE) && (p_dev_rec->ble.key_type & BTM_LE_KEY_PID)) { BTM_TRACE_DEBUG("%s try to resolve", __func__); /* use the 3 MSB of bd address as prand */ rand[0] = rpa[2]; rand[1] = rpa[1]; rand[2] = rpa[0]; /* generate X = E irk(R0, R1, R2) and R is random address 3 LSO */ SMP_Encrypt(p_dev_rec->ble.keys.irk, BT_OCTET16_LEN, &rand[0], 3, &output); rand[0] = rpa[5]; rand[1] = rpa[4]; rand[2] = rpa[3]; if (!memcmp(output.param_buf, &rand[0], 3)) { btm_ble_init_pseudo_addr (p_dev_rec, rpa); rt = TRUE; } } #endif ///SMP_INCLUDED == TRUE return rt; }
/******************************************************************************* ** ** 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 smp_process_confirm ** ** Description This function is called when SConfirm/MConfirm is generated ** proceed to send the Confirm request/response to peer device. ** ** Returns void ** *******************************************************************************/ static void smp_process_confirm(tSMP_CB *p_cb, tSMP_ENC *p) { tSMP_KEY key; SMP_TRACE_DEBUG ("smp_process_confirm "); #if SMP_CONFORMANCE_TESTING == TRUE if (p_cb->enable_test_confirm_val) { BTM_TRACE_DEBUG ("Use confirm value from script"); memcpy(p_cb->confirm, p_cb->test_confirm, BT_OCTET16_LEN); } else memcpy(p_cb->confirm, p->param_buf, BT_OCTET16_LEN); #else memcpy(p_cb->confirm, p->param_buf, BT_OCTET16_LEN); #endif #if (SMP_DEBUG == TRUE) SMP_TRACE_DEBUG("Confirm Generated"); smp_debug_print_nbyte_little_endian ((UINT8 *)p_cb->confirm, (const UINT8 *)"Confirm", 16); #endif key.key_type = SMP_KEY_TYPE_CFM; key.p_data = p->param_buf; smp_sm_event(p_cb, SMP_KEY_READY_EVT, &key); }
/******************************************************************************* ** ** Function btm_vendor_specific_evt ** ** Description Process event HCI_VENDOR_SPECIFIC_EVT ** ** Note: Some controllers do not send command complete, so ** the callback and busy flag are cleared here also. ** ** Returns void ** *******************************************************************************/ void btm_vendor_specific_evt (UINT8 *p, UINT8 evt_len) { UINT8 i; BTM_TRACE_DEBUG ("BTM Event: Vendor Specific event from controller"); for (i=0; i<BTM_MAX_VSE_CALLBACKS; i++) { if (btm_cb.devcb.p_vend_spec_cb[i]) (*btm_cb.devcb.p_vend_spec_cb[i])(evt_len, p); } }
/******************************************************************************* ** ** Function btm_ble_batchscan_enq_op_q ** ** Description enqueue a batchscan operation in q to check command complete ** status ** ** Returns void ** *******************************************************************************/ void btm_ble_batchscan_enq_op_q(UINT8 opcode, tBTM_BLE_BATCH_SCAN_STATE cur_state, UINT8 cb_evt, tBTM_BLE_REF_VALUE ref_value) { ble_batchscan_cb.op_q.sub_code[ble_batchscan_cb.op_q.next_idx] = (opcode |(cb_evt << 4)); ble_batchscan_cb.op_q.cur_state[ble_batchscan_cb.op_q.next_idx] = cur_state; ble_batchscan_cb.op_q.ref_value[ble_batchscan_cb.op_q.next_idx] = ref_value; BTM_TRACE_DEBUG("btm_ble_batchscan_enq_op_q: subcode:%d, Cur_state:%d, ref_value:%d", ble_batchscan_cb.op_q.sub_code[ble_batchscan_cb.op_q.next_idx], ble_batchscan_cb.op_q.cur_state[ble_batchscan_cb.op_q.next_idx], ble_batchscan_cb.op_q.ref_value[ble_batchscan_cb.op_q.next_idx]); ble_batchscan_cb.op_q.next_idx = (ble_batchscan_cb.op_q.next_idx + 1) % BTM_BLE_BATCH_SCAN_MAX; }
/******************************************************************************* ** ** Function btm_ble_advfilt_enq_op_q ** ** Description enqueue an adv filter operation in q to check command complete ** status ** ** Returns void ** *******************************************************************************/ void btm_ble_advfilt_enq_op_q(UINT8 action, UINT8 ocf, tBTM_BLE_FILT_CB_EVT cb_evt, tBTM_BLE_REF_VALUE ref, tBTM_BLE_PF_CFG_CBACK *p_cmpl_cback, tBTM_BLE_PF_PARAM_CBACK *p_filt_param_cback) { btm_ble_adv_filt_cb.op_q.action_ocf[btm_ble_adv_filt_cb.op_q.next_idx] = (action |(ocf << 4)); btm_ble_adv_filt_cb.op_q.ref_value[btm_ble_adv_filt_cb.op_q.next_idx] = ref; btm_ble_adv_filt_cb.op_q.cb_evt[btm_ble_adv_filt_cb.op_q.next_idx] = cb_evt; btm_ble_adv_filt_cb.op_q.p_scan_cfg_cback[btm_ble_adv_filt_cb.op_q.next_idx] = p_cmpl_cback; btm_ble_adv_filt_cb.op_q.p_filt_param_cback[btm_ble_adv_filt_cb.op_q.next_idx] = p_filt_param_cback; BTM_TRACE_DEBUG("btm_ble_advfilt_enq_op_q: act_ocf:%d, action:%d, ocf:%d,cb_evt;%d, cback:%x", btm_ble_adv_filt_cb.op_q.action_ocf[btm_ble_adv_filt_cb.op_q.next_idx], action, ocf, cb_evt, p_cmpl_cback); btm_ble_adv_filt_cb.op_q.next_idx = (btm_ble_adv_filt_cb.op_q.next_idx + 1) % BTM_BLE_PF_TYPE_MAX; }
/******************************************************************************* ** ** Function btm_ble_batchscan_enq_rep_q ** ** Description enqueue a batchscan report operation in q to check command complete ** status ** ** Returns void ** *******************************************************************************/ tBTM_STATUS btm_ble_batchscan_enq_rep_q(UINT8 report_format, tBTM_BLE_REF_VALUE ref_value) { int i = 0; for (i = 0; i < BTM_BLE_BATCH_REP_MAIN_Q_SIZE; i++) { if (report_format == ble_batchscan_cb.main_rep_q.rep_mode[i]) return BTM_ILLEGAL_VALUE; } ble_batchscan_cb.main_rep_q.rep_mode[ble_batchscan_cb.main_rep_q.next_idx] = report_format; ble_batchscan_cb.main_rep_q.ref_value[ble_batchscan_cb.main_rep_q.next_idx] = ref_value; ble_batchscan_cb.main_rep_q.num_records[ble_batchscan_cb.main_rep_q.next_idx] = 0; ble_batchscan_cb.main_rep_q.data_len[ble_batchscan_cb.main_rep_q.next_idx] = 0; ble_batchscan_cb.main_rep_q.p_data[ble_batchscan_cb.main_rep_q.next_idx] = NULL; BTM_TRACE_DEBUG("btm_ble_batchscan_enq_rep_q: index:%d, rep %d, ref %d", ble_batchscan_cb.main_rep_q.next_idx, report_format, ref_value); ble_batchscan_cb.main_rep_q.next_idx = (ble_batchscan_cb.main_rep_q.next_idx + 1) % BTM_BLE_BATCH_REP_MAIN_Q_SIZE; return BTM_SUCCESS; }
/******************************************************************************* ** ** Function btm_ble_batchscan_enq_rep_data ** ** Description setup the data in the main report queue ** ** Returns void ** *******************************************************************************/ void btm_ble_batchscan_enq_rep_data(UINT8 report_format, UINT8 num_records, UINT8 *p_data, UINT8 data_len) { int index = 0, len = 0; UINT8 *p_orig_data = NULL, *p_app_data = NULL; 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; } BTM_TRACE_DEBUG("btm_ble_batchscan_enq_rep_data: index:%d, rep %d, num %d len : %d", index, report_format, num_records, data_len); if (index < BTM_BLE_BATCH_REP_MAIN_Q_SIZE && data_len > 0 && num_records > 0) { len = ble_batchscan_cb.main_rep_q.data_len[index]; p_orig_data = ble_batchscan_cb.main_rep_q.p_data[index]; if (NULL != p_orig_data) { p_app_data = GKI_getbuf(len + data_len); memcpy(p_app_data, p_orig_data, len); memcpy(p_app_data+len, p_data, data_len); GKI_freebuf(p_orig_data); ble_batchscan_cb.main_rep_q.p_data[index] = p_app_data; ble_batchscan_cb.main_rep_q.num_records[index] += num_records; ble_batchscan_cb.main_rep_q.data_len[index] += data_len; } else { p_app_data = GKI_getbuf(data_len); memcpy(p_app_data, p_data, data_len); ble_batchscan_cb.main_rep_q.p_data[index] = p_app_data; ble_batchscan_cb.main_rep_q.num_records[index] = num_records; ble_batchscan_cb.main_rep_q.data_len[index] = data_len; } } }
/******************************************************************************* ** ** 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_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) { 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; btm_execute_wl_dev_operation(); #if BLE_PRIVACY_SPT == TRUE btm_ble_enable_resolving_list_for_platform(BTM_BLE_RL_INIT); #endif 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 BLE_PRIVACY_SPT == TRUE if (btm_cb.ble_ctr_cb.rl_state != BTM_BLE_RL_IDLE) { own_addr_type |= BLE_ADDR_TYPE_ID_BIT; peer_addr_type |= BLE_ADDR_TYPE_ID_BIT; } #endif 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_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; 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; }
/******************************************************************************* ** ** Function btm_ble_white_list_init ** ** Description Initialize white list size ** *******************************************************************************/ void btm_ble_white_list_init(UINT8 white_list_size) { BTM_TRACE_DEBUG("%s white_list_size = %d", __func__, white_list_size); btm_cb.ble_ctr_cb.white_list_avail_size = white_list_size; }