| /****************************************************************************** |
| * |
| * Copyright (C) 2014 Broadcom Corporation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at: |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| ******************************************************************************/ |
| |
| #include <string.h> |
| #include <pthread.h> |
| |
| #include "bt_target.h" |
| #include "device/include/controller.h" |
| #include "stack_config.h" |
| |
| #if (BLE_INCLUDED == TRUE) |
| #include "bt_types.h" |
| #include "hcimsgs.h" |
| #include "btu.h" |
| #include "btm_int.h" |
| #include "bt_utils.h" |
| #include "hcidefs.h" |
| #include "btm_ble_api.h" |
| |
| /************************************************************************************ |
| ** Constants & Macros |
| ************************************************************************************/ |
| /* length of each multi adv sub command */ |
| #define BTM_BLE_MULTI_ADV_ENB_LEN 3 |
| #define BTM_BLE_MULTI_ADV_SET_PARAM_LEN 24 |
| #define BTM_BLE_MULTI_ADV_WRITE_DATA_LEN (BTM_BLE_AD_DATA_LEN + 3) |
| #define BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN 8 |
| #define BTM_BLE_EXTENDED_ADV_TIMEOUT 0x3C |
| |
| #define BTM_BLE_MULTI_ADV_CB_EVT_MASK 0xF0 |
| #define BTM_BLE_MULTI_ADV_SUBCODE_MASK 0x0F |
| |
| #ifdef WIPOWER_SUPPORTED |
| #define WIPOWER_16_UUID_LSB 0xFE |
| #define WIPOWER_16_UUID_MSB 0xFF |
| static bool is_wipower_adv = false; |
| #endif |
| |
| #define BTM_BLE_EXTENDED_LEGACY_MASK 0x10 |
| |
| /************************************************************************************ |
| ** Static variables |
| ************************************************************************************/ |
| tBTM_BLE_MULTI_ADV_CB btm_multi_adv_cb; |
| tBTM_BLE_MULTI_ADV_INST_IDX_Q btm_multi_adv_idx_q; |
| pthread_mutex_t btm_multi_adv_lock = PTHREAD_MUTEX_INITIALIZER; |
| tBTM_BLE_EXT_ADV_ENABLE_CB btm_ble_ext_enable_cb; |
| |
| #ifdef WIPOWER_SUPPORTED |
| UINT8 wipower_inst_id = BTM_BLE_MULTI_ADV_DEFAULT_STD; |
| #endif |
| |
| /************************************************************************************ |
| ** Externs |
| ************************************************************************************/ |
| extern fixed_queue_t *btu_general_alarm_queue; |
| extern void btm_ble_update_dmt_flag_bits(UINT8 *flag_value, |
| const UINT16 connect_mode, const UINT16 disc_mode); |
| |
| static inline BOOLEAN is_btm_multi_adv_cb_valid() |
| { |
| if (!btm_multi_adv_cb.p_adv_inst || |
| !btm_multi_adv_cb.op_q.p_sub_code || |
| !btm_multi_adv_cb.op_q.p_inst_id) |
| return FALSE; |
| else |
| return TRUE; |
| } |
| #if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE)) |
| /************************************************************************************ |
| ** Local declaration |
| ************************************************************************************/ |
| static tBTM_STATUS btm_ble_extended_adv_set_params (tBTM_BLE_MULTI_ADV_INST *p_inst, |
| tBTM_BLE_ADV_PARAMS *p_params, |
| UINT8 cb_evt); |
| static tBTM_STATUS btm_ble_enable_extended_adv (BOOLEAN enable, UINT8 inst_id, UINT16 duration, UINT8 max_ext_adv_evts, UINT8 cb_evt); |
| #endif |
| |
| /******************************************************************************* |
| ** |
| ** Function btm_ble_multi_adv_enq_op_q |
| ** |
| ** Description enqueue a multi adv operation in q to check command complete |
| ** status. |
| ** |
| ** Returns void |
| ** |
| *******************************************************************************/ |
| void btm_ble_multi_adv_enq_op_q(UINT8 opcode, UINT8 inst_id, UINT8 cb_evt) |
| { |
| UINT8 max_adv_instance = BTM_BleMaxMultiAdvInstanceCount(); |
| tBTM_BLE_MULTI_ADV_OPQ *p_op_q = &btm_multi_adv_cb.op_q; |
| |
| p_op_q->p_inst_id[p_op_q->next_idx] = inst_id; |
| |
| p_op_q->p_sub_code[p_op_q->next_idx] = (opcode |(cb_evt << 4)); |
| |
| if (max_adv_instance > 0) |
| p_op_q->next_idx = (p_op_q->next_idx + 1) % max_adv_instance; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function btm_ble_multi_adv_deq_op_q |
| ** |
| ** Description dequeue a multi adv operation from q when command complete |
| ** is received. |
| ** |
| ** Returns void |
| ** |
| *******************************************************************************/ |
| void btm_ble_multi_adv_deq_op_q(UINT8 *p_opcode, UINT8 *p_inst_id, UINT8 *p_cb_evt) |
| { |
| UINT8 max_adv_instance = BTM_BleMaxMultiAdvInstanceCount(); |
| tBTM_BLE_MULTI_ADV_OPQ *p_op_q = &btm_multi_adv_cb.op_q; |
| |
| *p_inst_id = p_op_q->p_inst_id[p_op_q->pending_idx] & 0x7F; |
| *p_cb_evt = (p_op_q->p_sub_code[p_op_q->pending_idx] >> 4); |
| *p_opcode = (p_op_q->p_sub_code[p_op_q->pending_idx] & BTM_BLE_MULTI_ADV_SUBCODE_MASK); |
| |
| if (max_adv_instance > 0) |
| p_op_q->pending_idx = (p_op_q->pending_idx + 1) % max_adv_instance; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function btm_ble_multi_adv_vsc_cmpl_cback |
| ** |
| ** Description Multi adv VSC complete callback |
| ** |
| ** Parameters |
| ** |
| ** Returns void |
| ** |
| *******************************************************************************/ |
| void btm_ble_multi_adv_vsc_cmpl_cback (tBTM_VSC_CMPL *p_params) |
| { |
| UINT8 status, subcode; |
| UINT8 *p = p_params->p_param_buf, inst_id; |
| UINT16 len = p_params->param_len; |
| tBTM_BLE_MULTI_ADV_INST *p_inst ; |
| UINT8 cb_evt = 0, opcode; |
| |
| if (!controller_get_interface()->get_is_ready()) |
| { |
| BTM_TRACE_ERROR("btm_ble_multi_adv_vsc_cmpl_cback controller not ready. returning!"); |
| return; |
| } |
| |
| if (len < 2) |
| { |
| BTM_TRACE_ERROR("wrong length for btm_ble_multi_adv_vsc_cmpl_cback"); |
| return; |
| } |
| |
| STREAM_TO_UINT8(status, p); |
| STREAM_TO_UINT8(subcode, p); |
| |
| pthread_mutex_lock(&btm_multi_adv_lock); |
| if (!is_btm_multi_adv_cb_valid()) |
| goto error; |
| btm_ble_multi_adv_deq_op_q(&opcode, &inst_id, &cb_evt); |
| |
| BTM_TRACE_DEBUG("op_code = %02x inst_id = %d cb_evt = %02x", opcode, inst_id, cb_evt); |
| |
| if (opcode != subcode || inst_id == 0) |
| { |
| BTM_TRACE_ERROR("get unexpected VSC cmpl, expect: %d get: %d",subcode,opcode); |
| goto error; |
| } |
| |
| p_inst = &btm_multi_adv_cb.p_adv_inst[inst_id - 1]; |
| |
| switch (subcode) |
| { |
| case BTM_BLE_MULTI_ADV_ENB: |
| { |
| BTM_TRACE_DEBUG("BTM_BLE_MULTI_ADV_ENB status = %d", status); |
| |
| /* Mark as not in use here, if instance cannot be enabled */ |
| if (HCI_SUCCESS != status && BTM_BLE_MULTI_ADV_ENB_EVT == cb_evt) |
| btm_multi_adv_cb.p_adv_inst[inst_id-1].in_use = FALSE; |
| break; |
| } |
| |
| case BTM_BLE_MULTI_ADV_SET_PARAM: |
| { |
| BTM_TRACE_DEBUG("BTM_BLE_MULTI_ADV_SET_PARAM status = %d", status); |
| break; |
| } |
| |
| case BTM_BLE_MULTI_ADV_WRITE_ADV_DATA: |
| { |
| BTM_TRACE_DEBUG("BTM_BLE_MULTI_ADV_WRITE_ADV_DATA status = %d", status); |
| break; |
| } |
| |
| case BTM_BLE_MULTI_ADV_WRITE_SCAN_RSP_DATA: |
| { |
| BTM_TRACE_DEBUG("BTM_BLE_MULTI_ADV_WRITE_SCAN_RSP_DATA status = %d", status); |
| break; |
| } |
| |
| case BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR: |
| { |
| BTM_TRACE_DEBUG("BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR status = %d", status); |
| break; |
| } |
| |
| default: |
| break; |
| } |
| |
| if (cb_evt != 0 && p_inst->p_cback != NULL) |
| { |
| (p_inst->p_cback)(cb_evt, inst_id, p_inst->p_ref, status); |
| } |
| |
| error: |
| pthread_mutex_unlock(&btm_multi_adv_lock); |
| return; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function btm_ble_enable_multi_adv |
| ** |
| ** Description This function enable the customer specific feature in controller |
| ** |
| ** Parameters enable: enable or disable |
| ** inst_id: adv instance ID, can not be 0 |
| ** |
| ** Returns status |
| ** |
| *******************************************************************************/ |
| tBTM_STATUS btm_ble_enable_multi_adv (BOOLEAN enable, UINT8 inst_id, UINT8 cb_evt) |
| { |
| UINT8 param[BTM_BLE_MULTI_ADV_ENB_LEN], *pp; |
| UINT8 enb = enable ? 1: 0; |
| tBTM_STATUS rt; |
| |
| pp = param; |
| memset(param, 0, BTM_BLE_MULTI_ADV_ENB_LEN); |
| |
| UINT8_TO_STREAM (pp, BTM_BLE_MULTI_ADV_ENB); |
| UINT8_TO_STREAM (pp, enb); |
| UINT8_TO_STREAM (pp, inst_id); |
| |
| BTM_TRACE_EVENT (" btm_ble_enable_multi_adv: enb %d, Inst ID %d",enb,inst_id); |
| |
| if ((rt = BTM_VendorSpecificCommand (HCI_BLE_MULTI_ADV_OCF, |
| BTM_BLE_MULTI_ADV_ENB_LEN, |
| param, |
| btm_ble_multi_adv_vsc_cmpl_cback)) |
| == BTM_CMD_STARTED) |
| { |
| btm_ble_multi_adv_enq_op_q(BTM_BLE_MULTI_ADV_ENB, inst_id, cb_evt); |
| } |
| return rt; |
| } |
| /******************************************************************************* |
| ** |
| ** Function btm_ble_map_adv_tx_power |
| ** |
| ** Description return the actual power in dBm based on the mapping in config file |
| ** |
| ** Parameters advertise parameters used for this instance. |
| ** |
| ** Returns tx power in dBm |
| ** |
| *******************************************************************************/ |
| int btm_ble_tx_power[BTM_BLE_ADV_TX_POWER_MAX + 1] = BTM_BLE_ADV_TX_POWER; |
| char btm_ble_map_adv_tx_power(int tx_power_index) |
| { |
| if(0 <= tx_power_index && tx_power_index < BTM_BLE_ADV_TX_POWER_MAX) |
| return (char)btm_ble_tx_power[tx_power_index]; |
| return 0; |
| } |
| /******************************************************************************* |
| ** |
| ** Function btm_ble_multi_adv_set_params |
| ** |
| ** Description This function enable the customer specific feature in controller |
| ** |
| ** Parameters advertise parameters used for this instance. |
| ** |
| ** Returns status |
| ** |
| *******************************************************************************/ |
| tBTM_STATUS btm_ble_multi_adv_set_params (tBTM_BLE_MULTI_ADV_INST *p_inst, |
| tBTM_BLE_ADV_PARAMS *p_params, |
| UINT8 cb_evt) |
| { |
| UINT8 param[BTM_BLE_MULTI_ADV_SET_PARAM_LEN], *pp; |
| tBTM_STATUS rt; |
| BD_ADDR dummy ={0,0,0,0,0,0}; |
| |
| pp = param; |
| memset(param, 0, BTM_BLE_MULTI_ADV_SET_PARAM_LEN); |
| |
| UINT8_TO_STREAM(pp, BTM_BLE_MULTI_ADV_SET_PARAM); |
| |
| UINT16_TO_STREAM (pp, p_params->adv_int_min); |
| UINT16_TO_STREAM (pp, p_params->adv_int_max); |
| UINT8_TO_STREAM (pp, p_params->adv_type); |
| |
| #if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE) |
| if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE) |
| { |
| UINT8_TO_STREAM (pp, BLE_ADDR_RANDOM); |
| BDADDR_TO_STREAM (pp, p_inst->rpa); |
| } |
| else |
| #endif |
| { |
| UINT8_TO_STREAM (pp, BLE_ADDR_PUBLIC); |
| BDADDR_TO_STREAM (pp, controller_get_interface()->get_address()->address); |
| } |
| |
| BTM_TRACE_EVENT (" btm_ble_multi_adv_set_params,Min %d, Max %d,adv_type %d", |
| p_params->adv_int_min,p_params->adv_int_max,p_params->adv_type); |
| |
| UINT8_TO_STREAM (pp, 0); |
| BDADDR_TO_STREAM (pp, dummy); |
| |
| if (p_params->channel_map == 0 || p_params->channel_map > BTM_BLE_DEFAULT_ADV_CHNL_MAP) |
| p_params->channel_map = BTM_BLE_DEFAULT_ADV_CHNL_MAP; |
| UINT8_TO_STREAM (pp, p_params->channel_map); |
| |
| if (p_params->adv_filter_policy >= AP_SCAN_CONN_POLICY_MAX) |
| p_params->adv_filter_policy = AP_SCAN_CONN_ALL; |
| UINT8_TO_STREAM (pp, p_params->adv_filter_policy); |
| |
| UINT8_TO_STREAM (pp, p_inst->inst_id); |
| |
| if (p_params->tx_power > BTM_BLE_ADV_TX_POWER_MAX) |
| p_params->tx_power = BTM_BLE_ADV_TX_POWER_MAX; |
| UINT8_TO_STREAM (pp, btm_ble_map_adv_tx_power(p_params->tx_power)); |
| |
| BTM_TRACE_EVENT("set_params:Chnl Map %d,adv_fltr policy %d,ID:%d, TX Power%d", |
| p_params->channel_map,p_params->adv_filter_policy,p_inst->inst_id,p_params->tx_power); |
| |
| if ((rt = BTM_VendorSpecificCommand (HCI_BLE_MULTI_ADV_OCF, |
| BTM_BLE_MULTI_ADV_SET_PARAM_LEN, |
| param, |
| btm_ble_multi_adv_vsc_cmpl_cback)) |
| == BTM_CMD_STARTED) |
| { |
| p_inst->adv_evt = p_params->adv_type; |
| |
| #if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE) |
| if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE) { |
| alarm_set_on_queue(p_inst->adv_raddr_timer, |
| BTM_BLE_PRIVATE_ADDR_INT_MS, |
| btm_ble_adv_raddr_timer_timeout, p_inst, |
| btu_general_alarm_queue); |
| } |
| #endif |
| btm_ble_multi_adv_enq_op_q(BTM_BLE_MULTI_ADV_SET_PARAM, p_inst->inst_id, cb_evt); |
| } |
| return rt; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function btm_ble_multi_adv_write_rpa |
| ** |
| ** Description This function write the random address for the adv instance into |
| ** controller |
| ** |
| ** Parameters |
| ** |
| ** Returns status |
| ** |
| *******************************************************************************/ |
| tBTM_STATUS btm_ble_multi_adv_write_rpa (tBTM_BLE_MULTI_ADV_INST *p_inst, BD_ADDR random_addr) |
| { |
| UINT8 param[BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN], *pp = param; |
| tBTM_STATUS rt = BTM_NO_RESOURCES; |
| |
| BTM_TRACE_EVENT ("%s-BD_ADDR:%02x-%02x-%02x-%02x-%02x-%02x,inst_id:%d", |
| __FUNCTION__, random_addr[5], random_addr[4], random_addr[3], random_addr[2], |
| random_addr[1], random_addr[0], p_inst->inst_id); |
| |
| #if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE)) |
| if (controller_get_interface()->supports_ble_extended_advertisements()) |
| { |
| rt = btm_ble_add_multi_adv_rpa(random_addr, BLE_ADDR_RANDOM); |
| return rt; |
| } |
| else |
| #endif |
| { |
| memset(param, 0, BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN); |
| |
| UINT8_TO_STREAM (pp, BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR); |
| BDADDR_TO_STREAM(pp, random_addr); |
| UINT8_TO_STREAM(pp, p_inst->inst_id); |
| rt = BTM_VendorSpecificCommand (HCI_BLE_MULTI_ADV_OCF, |
| BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN, |
| param, |
| btm_ble_multi_adv_vsc_cmpl_cback); |
| } |
| |
| |
| if (rt == BTM_CMD_STARTED) |
| { |
| /* start a periodical timer to refresh random addr */ |
| /* TODO: is the above comment correct - is the timer periodical? */ |
| alarm_set_on_queue(p_inst->adv_raddr_timer, |
| BTM_BLE_PRIVATE_ADDR_INT_MS, |
| btm_ble_adv_raddr_timer_timeout, p_inst, |
| btu_general_alarm_queue); |
| btm_ble_multi_adv_enq_op_q(BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR, |
| p_inst->inst_id, 0); |
| } |
| return rt; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function btm_ble_multi_adv_gen_rpa_cmpl |
| ** |
| ** Description RPA generation completion callback for each adv instance. Will |
| ** continue write the new RPA into controller. |
| ** |
| ** Returns none. |
| ** |
| *******************************************************************************/ |
| void btm_ble_multi_adv_gen_rpa_cmpl(tBTM_RAND_ENC *p) |
| { |
| if (!controller_get_interface()->get_is_ready()) |
| { |
| BTM_TRACE_ERROR("btm_ble_multi_adv_gen_rpa_cmpl controller module is not ready!"); |
| return; |
| } |
| |
| #if (SMP_INCLUDED == TRUE) |
| tSMP_ENC output; |
| UINT8 index = 0; |
| tBTM_BLE_MULTI_ADV_INST *p_inst = NULL; |
| |
| /* Retrieve the index of adv instance from stored Q */ |
| if (btm_multi_adv_idx_q.front == -1) |
| { |
| BTM_TRACE_ERROR(" %s can't locate advertise instance", __FUNCTION__); |
| return; |
| } |
| else |
| { |
| index = btm_multi_adv_idx_q.inst_index_queue[btm_multi_adv_idx_q.front]; |
| if (btm_multi_adv_idx_q.front == btm_multi_adv_idx_q.rear) |
| { |
| btm_multi_adv_idx_q.front = -1; |
| btm_multi_adv_idx_q.rear = -1; |
| } |
| else |
| { |
| btm_multi_adv_idx_q.front = (btm_multi_adv_idx_q.front + 1) % BTM_BLE_MULTI_ADV_MAX; |
| } |
| } |
| |
| pthread_mutex_lock(&btm_multi_adv_lock); |
| if (!is_btm_multi_adv_cb_valid()) |
| goto error; |
| p_inst = &(btm_multi_adv_cb.p_adv_inst[index]); |
| |
| BTM_TRACE_EVENT ("btm_ble_multi_adv_gen_rpa_cmpl inst_id = %d", p_inst->inst_id); |
| if (p) |
| { |
| p->param_buf[2] &= (~BLE_RESOLVE_ADDR_MASK); |
| p->param_buf[2] |= BLE_RESOLVE_ADDR_MSB; |
| |
| p_inst->rpa[2] = p->param_buf[0]; |
| p_inst->rpa[1] = p->param_buf[1]; |
| p_inst->rpa[0] = p->param_buf[2]; |
| |
| if (!SMP_Encrypt(btm_cb.devcb.id_keys.irk, BT_OCTET16_LEN, p->param_buf, 3, &output)) |
| { |
| BTM_TRACE_DEBUG("generate random address failed"); |
| } |
| else |
| { |
| /* set hash to be LSB of rpAddress */ |
| p_inst->rpa[5] = output.param_buf[0]; |
| p_inst->rpa[4] = output.param_buf[1]; |
| p_inst->rpa[3] = output.param_buf[2]; |
| } |
| |
| if (p_inst->inst_id != BTM_BLE_MULTI_ADV_DEFAULT_STD && |
| p_inst->inst_id < BTM_BleMaxMultiAdvInstanceCount()) |
| { |
| /* set it to controller */ |
| btm_ble_multi_adv_write_rpa(p_inst, p_inst->rpa); |
| } |
| } |
| error: |
| pthread_mutex_unlock(&btm_multi_adv_lock); |
| #endif |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function btm_ble_multi_adv_configure_rpa |
| ** |
| ** Description This function set the random address for the adv instance |
| ** |
| ** Parameters advertise parameters used for this instance. |
| ** |
| ** Returns none |
| ** |
| *******************************************************************************/ |
| void btm_ble_multi_adv_configure_rpa (tBTM_BLE_MULTI_ADV_INST *p_inst) |
| { |
| if (btm_multi_adv_idx_q.front == (btm_multi_adv_idx_q.rear + 1) % BTM_BLE_MULTI_ADV_MAX) |
| { |
| BTM_TRACE_ERROR("outstanding rand generation exceeded max allowed "); |
| return; |
| } |
| else |
| { |
| if (btm_multi_adv_idx_q.front == -1) |
| { |
| btm_multi_adv_idx_q.front = 0; |
| btm_multi_adv_idx_q.rear = 0; |
| } |
| else |
| { |
| btm_multi_adv_idx_q.rear = (btm_multi_adv_idx_q.rear + 1) % BTM_BLE_MULTI_ADV_MAX; |
| } |
| btm_multi_adv_idx_q.inst_index_queue[btm_multi_adv_idx_q.rear] = p_inst->index; |
| } |
| btm_gen_resolvable_private_addr((void *)btm_ble_multi_adv_gen_rpa_cmpl); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function btm_ble_update_multi_adv_inst_data_length |
| ** |
| ** Description This function set the random address for the adv instance |
| ** |
| ** Parameters advertise parameters used for this instance. |
| ** |
| ** Returns none |
| ** |
| *******************************************************************************/ |
| void btm_ble_update_multi_adv_inst_data_length (UINT16 inst_len) |
| { |
| int index; |
| tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.p_adv_inst[0]; |
| BTM_TRACE_ERROR("btm_ble_update_multi_adv_inst_data_length inst_len:%d",inst_len); |
| |
| for (index = 0; index < BTM_BleMaxMultiAdvInstanceCount() - 1; index++, p_inst++) |
| { |
| p_inst->len = inst_len; |
| } |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function btm_ble_multi_adv_reenable |
| ** |
| ** Description This function re-enable adv instance upon a connection establishment. |
| ** |
| ** Parameters advertise parameters used for this instance. |
| ** |
| ** Returns none. |
| ** |
| *******************************************************************************/ |
| void btm_ble_multi_adv_reenable(UINT8 inst_id) |
| { |
| tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.p_adv_inst[inst_id - 1]; |
| |
| if (TRUE == p_inst->in_use) |
| { |
| if (p_inst->adv_evt != BTM_BLE_CONNECT_DIR_EVT) |
| btm_ble_enable_multi_adv (TRUE, p_inst->inst_id, 0); |
| else |
| /* mark directed adv as disabled if adv has been stopped */ |
| { |
| (p_inst->p_cback)(BTM_BLE_MULTI_ADV_DISABLE_EVT,p_inst->inst_id,p_inst->p_ref,0); |
| p_inst->in_use = FALSE; |
| } |
| } |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function btm_ble_multi_adv_enb_privacy |
| ** |
| ** Description This function enable/disable privacy setting in multi adv |
| ** |
| ** Parameters enable: enable or disable the adv instance. |
| ** |
| ** Returns none. |
| ** |
| *******************************************************************************/ |
| void btm_ble_multi_adv_enb_privacy(BOOLEAN enable) |
| { |
| int i; |
| tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.p_adv_inst[0]; |
| |
| for (i = 0; i < BTM_BleMaxMultiAdvInstanceCount() - 1; i ++, p_inst++) |
| { |
| p_inst->in_use = FALSE; |
| if (enable) |
| btm_ble_multi_adv_configure_rpa(p_inst); |
| else |
| alarm_cancel(p_inst->adv_raddr_timer); |
| } |
| } |
| |
| #if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE)) |
| /******************************************************************************* |
| ** |
| ** Function btm_ble_extended_configure_inst_size |
| ** |
| ** Description This function gathers max length of advertiement sets |
| ** |
| ** Parameters none. |
| ** |
| ** Returns none. |
| ** |
| *******************************************************************************/ |
| void btm_ble_extended_configure_inst_size() |
| { |
| BTM_TRACE_DEBUG ("%s", __func__); |
| btsnd_hcic_ble_read_extended_max_adv_len(); |
| } |
| #endif |
| |
| /******************************************************************************* |
| ** |
| ** Function BTM_BleEnableAdvInstance |
| ** |
| ** Description This function enable a Multi-ADV instance with the specified |
| ** adv parameters |
| ** |
| ** Parameters p_params: pointer to the adv parameter structure, set as default |
| ** adv parameter when the instance is enabled. |
| ** p_cback: callback function for the adv instance. |
| ** p_ref: reference data attach to the adv instance to be enabled. |
| ** |
| ** Returns status |
| ** |
| *******************************************************************************/ |
| tBTM_STATUS BTM_BleEnableAdvInstance (tBTM_BLE_ADV_PARAMS *p_params, |
| tBTM_BLE_MULTI_ADV_CBACK *p_cback,void *p_ref) |
| { |
| int i; |
| tBTM_STATUS rt = BTM_NO_RESOURCES; |
| tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.p_adv_inst[0]; |
| |
| BTM_TRACE_EVENT("BTM_BleEnableAdvInstance called"); |
| |
| if (0 == BTM_BleMaxMultiAdvInstanceCount()) |
| { |
| BTM_TRACE_ERROR("Controller does not support Multi ADV"); |
| return BTM_ERR_PROCESSING; |
| } |
| |
| if (NULL == p_inst) |
| { |
| BTM_TRACE_ERROR("Invalid instance in BTM_BleEnableAdvInstance"); |
| return BTM_ERR_PROCESSING; |
| } |
| |
| for (i = 0; i < BTM_BleMaxMultiAdvInstanceCount() - 1; i ++, p_inst++) |
| { |
| if (FALSE == p_inst->in_use) |
| { |
| p_inst->in_use = TRUE; |
| /* configure adv parameter */ |
| if (p_params) { |
| #if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE)) |
| if (controller_get_interface()->supports_ble_extended_advertisements()) |
| { |
| rt = btm_ble_extended_adv_set_params(p_inst, p_params, 0); |
| } |
| else |
| #endif |
| { |
| rt = btm_ble_multi_adv_set_params(p_inst, p_params, 0); |
| } |
| } |
| else |
| rt = BTM_CMD_STARTED; |
| |
| /* enable adv */ |
| BTM_TRACE_EVENT("btm_ble_enable_multi_adv being called with inst_id:%d", |
| p_inst->inst_id); |
| |
| if (BTM_CMD_STARTED == rt) |
| { |
| #if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE)) |
| if (controller_get_interface()->supports_ble_extended_advertisements()) { |
| p_inst->in_use = FALSE; |
| btm_ble_enable_resolving_list (BTM_BLE_RL_EXT_ADV); |
| p_inst->in_use = TRUE; |
| rt = btm_ble_enable_extended_adv (TRUE, p_inst->inst_id, |
| p_inst->duration, p_params->max_ext_adv_evts, BTM_BLE_EXTENDED_ADV_ENB_EVT); |
| } |
| else |
| #endif |
| { |
| rt = btm_ble_enable_multi_adv (TRUE, p_inst->inst_id, |
| BTM_BLE_MULTI_ADV_ENB_EVT); |
| } |
| |
| if (rt == BTM_CMD_STARTED) |
| { |
| p_inst->p_cback = p_cback; |
| p_inst->p_ref = p_ref; |
| } |
| } |
| |
| if (BTM_CMD_STARTED != rt) |
| { |
| p_inst->in_use = FALSE; |
| BTM_TRACE_ERROR("BTM_BleEnableAdvInstance failed"); |
| } |
| break; |
| } |
| } |
| return rt; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function BTM_BleUpdateAdvInstParam |
| ** |
| ** Description This function update a Multi-ADV instance with the specified |
| ** adv parameters. |
| ** |
| ** Parameters inst_id: adv instance ID |
| ** p_params: pointer to the adv parameter structure. |
| ** |
| ** Returns status |
| ** |
| *******************************************************************************/ |
| tBTM_STATUS BTM_BleUpdateAdvInstParam (UINT8 inst_id, tBTM_BLE_ADV_PARAMS *p_params) |
| { |
| tBTM_STATUS rt = BTM_ILLEGAL_VALUE; |
| tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.p_adv_inst[inst_id - 1]; |
| UINT8 cb_evt = BTM_BLE_MULTI_ADV_PARAM_EVT; |
| |
| BTM_TRACE_EVENT("BTM_BleUpdateAdvInstParam called with inst_id:%d", inst_id); |
| |
| if (0 == BTM_BleMaxMultiAdvInstanceCount()) |
| { |
| BTM_TRACE_ERROR("Controller does not support Multi ADV"); |
| return BTM_ERR_PROCESSING; |
| } |
| |
| if (inst_id < BTM_BleMaxMultiAdvInstanceCount() && |
| inst_id != BTM_BLE_MULTI_ADV_DEFAULT_STD && |
| p_params != NULL) |
| { |
| if (FALSE == p_inst->in_use) |
| { |
| BTM_TRACE_DEBUG("adv instance %d is not active", inst_id); |
| return BTM_WRONG_MODE; |
| } |
| else { |
| #if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE)) |
| if (controller_get_interface()->supports_ble_extended_advertisements()) |
| btm_ble_enable_extended_adv(FALSE, inst_id, 0, 0/*p_params->max_ext_adv_evts*/, 0); |
| else |
| #endif |
| { |
| btm_ble_enable_multi_adv(FALSE, inst_id, 0); |
| } |
| } |
| |
| #if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE)) |
| if (controller_get_interface()->supports_ble_extended_advertisements()) |
| { |
| rt = btm_ble_extended_adv_set_params(p_inst, p_params, 0); |
| cb_evt = BTM_BLE_EXTENDED_ADV_PARAM_EVT; |
| } |
| else |
| #endif |
| { |
| rt = btm_ble_multi_adv_set_params(p_inst, p_params, 0); |
| } |
| |
| if (BTM_CMD_STARTED == rt) { |
| #if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE)) |
| if (controller_get_interface()->supports_ble_extended_advertisements()) |
| rt = btm_ble_enable_extended_adv(TRUE, inst_id, p_inst->duration, p_params->max_ext_adv_evts, cb_evt); |
| else |
| #endif |
| { |
| rt = btm_ble_enable_multi_adv(TRUE, inst_id, cb_evt); |
| } |
| } |
| } |
| return rt; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function BTM_BleCfgAdvInstData |
| ** |
| ** Description This function configure a Multi-ADV instance with the specified |
| ** adv data or scan response data. |
| ** |
| ** Parameters inst_id: adv instance ID |
| ** is_scan_rsp: is this scan response. if no, set as adv data. |
| ** data_mask: adv data mask. |
| ** p_data: pointer to the adv data structure. |
| ** |
| ** Returns status |
| ** |
| *******************************************************************************/ |
| tBTM_STATUS BTM_BleCfgAdvInstData (UINT8 inst_id, BOOLEAN is_scan_rsp, |
| tBTM_BLE_AD_MASK data_mask, UINT8 frag_pref, |
| tBTM_BLE_ADV_DATA *p_data) |
| { |
| UINT8 param[BTM_BLE_MULTI_ADV_WRITE_DATA_LEN], *pp = param; |
| UINT8 sub_code = (is_scan_rsp) ? |
| BTM_BLE_MULTI_ADV_WRITE_SCAN_RSP_DATA : BTM_BLE_MULTI_ADV_WRITE_ADV_DATA; |
| UINT8 *p_len; |
| tBTM_STATUS rt; |
| UINT8 *pp_temp = (UINT8*)(param + BTM_BLE_MULTI_ADV_WRITE_DATA_LEN -1); |
| tBTM_BLE_VSC_CB cmn_ble_vsc_cb; |
| |
| #if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE)) |
| if (controller_get_interface()->supports_ble_extended_advertisements()) |
| { |
| return BTM_BleWriteExtendedAdvData (inst_id, is_scan_rsp, data_mask, |
| BTM_BLE_EXT_ADV_COMPLETE ,frag_pref, p_data); |
| } |
| #endif |
| |
| BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb); |
| if (0 == BTM_BleMaxMultiAdvInstanceCount()) |
| { |
| BTM_TRACE_ERROR("Controller does not support Multi ADV"); |
| return BTM_ERR_PROCESSING; |
| } |
| |
| btm_ble_update_dmt_flag_bits(&p_data->flag, btm_cb.btm_inq_vars.connectable_mode, |
| btm_cb.btm_inq_vars.discoverable_mode); |
| |
| BTM_TRACE_EVENT("BTM_BleCfgAdvInstData called with inst_id:%d", inst_id); |
| if (inst_id > BTM_BLE_MULTI_ADV_MAX || inst_id == BTM_BLE_MULTI_ADV_DEFAULT_STD) |
| return BTM_ILLEGAL_VALUE; |
| |
| memset(param, 0, BTM_BLE_MULTI_ADV_WRITE_DATA_LEN); |
| |
| UINT8_TO_STREAM(pp, sub_code); |
| p_len = pp ++; |
| btm_ble_build_adv_data(&data_mask, &pp, p_data, BTM_BLE_AD_DATA_LEN); |
| *p_len = (UINT8)(pp - param - 2); |
| UINT8_TO_STREAM(pp_temp, inst_id); |
| #ifdef WIPOWER_SUPPORTED |
| if (param[7] == WIPOWER_16_UUID_LSB && param[8] == WIPOWER_16_UUID_MSB) |
| { |
| is_wipower_adv = true; |
| wipower_inst_id = inst_id; |
| } |
| #endif |
| |
| if ((rt = BTM_VendorSpecificCommand (HCI_BLE_MULTI_ADV_OCF, |
| (UINT8)BTM_BLE_MULTI_ADV_WRITE_DATA_LEN, |
| param, |
| btm_ble_multi_adv_vsc_cmpl_cback)) |
| == BTM_CMD_STARTED) |
| { |
| btm_ble_multi_adv_enq_op_q(sub_code, inst_id, BTM_BLE_MULTI_ADV_DATA_EVT); |
| } |
| return rt; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function BTM_BleDisableAdvInstance |
| ** |
| ** Description This function disables a Multi-ADV instance. |
| ** |
| ** Parameters inst_id: adv instance ID |
| ** |
| ** Returns status |
| ** |
| *******************************************************************************/ |
| tBTM_STATUS BTM_BleDisableAdvInstance (UINT8 inst_id) |
| { |
| tBTM_STATUS rt = BTM_ILLEGAL_VALUE; |
| tBTM_BLE_VSC_CB cmn_ble_vsc_cb; |
| |
| BTM_TRACE_EVENT("BTM_BleDisableAdvInstance with inst_id:%d", inst_id); |
| |
| BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb); |
| |
| if (0 == BTM_BleMaxMultiAdvInstanceCount()) |
| { |
| BTM_TRACE_ERROR("Controller does not support Multi ADV"); |
| return BTM_ERR_PROCESSING; |
| } |
| |
| if (inst_id < BTM_BleMaxMultiAdvInstanceCount() && |
| inst_id != BTM_BLE_MULTI_ADV_DEFAULT_STD) |
| { |
| #if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE)) |
| tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.p_adv_inst[inst_id - 1]; |
| if (controller_get_interface()->supports_ble_extended_advertisements()) { |
| rt = btm_ble_enable_extended_adv (FALSE, inst_id, |
| p_inst->duration, 0/*p_params->max_ext_adv_evts*/, |
| BTM_BLE_MULTI_ADV_DISABLE_EVT); |
| } |
| else |
| #endif |
| { |
| rt = btm_ble_enable_multi_adv(FALSE, inst_id, BTM_BLE_MULTI_ADV_DISABLE_EVT); |
| } |
| |
| if (rt == BTM_CMD_STARTED |
| #if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE)) |
| && !controller_get_interface()->supports_ble_extended_advertisements() |
| #endif |
| ) |
| { |
| btm_ble_multi_adv_configure_rpa(&btm_multi_adv_cb.p_adv_inst[inst_id - 1]); |
| alarm_cancel(btm_multi_adv_cb.p_adv_inst[inst_id - 1].adv_raddr_timer); |
| } |
| btm_multi_adv_cb.p_adv_inst[inst_id - 1].in_use = FALSE; |
| } |
| return rt; |
| } |
| /******************************************************************************* |
| ** |
| ** Function btm_ble_multi_adv_vse_cback |
| ** |
| ** Description VSE callback for multi adv events. |
| ** |
| ** Returns |
| ** |
| *******************************************************************************/ |
| void btm_ble_multi_adv_vse_cback(UINT8 len, UINT8 *p) |
| { |
| UINT8 sub_event; |
| UINT8 adv_inst, idx; |
| UINT16 conn_handle; |
| |
| /* Check if this is a BLE RSSI vendor specific event */ |
| STREAM_TO_UINT8(sub_event, p); |
| len--; |
| |
| BTM_TRACE_EVENT("btm_ble_multi_adv_vse_cback called with event:%d", sub_event); |
| if ((sub_event == HCI_VSE_SUBCODE_BLE_MULTI_ADV_ST_CHG) && (len >= 4)) |
| { |
| STREAM_TO_UINT8(adv_inst, p); |
| ++p; |
| STREAM_TO_UINT16(conn_handle, p); |
| |
| if ((idx = btm_handle_to_acl_index(conn_handle)) != MAX_L2CAP_LINKS) |
| { |
| #if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE) |
| if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE && |
| adv_inst <= BTM_BLE_MULTI_ADV_MAX && adv_inst != BTM_BLE_MULTI_ADV_DEFAULT_STD) |
| { |
| memcpy(btm_cb.acl_db[idx].conn_addr, btm_multi_adv_cb.p_adv_inst[adv_inst - 1].rpa, |
| BD_ADDR_LEN); |
| } |
| #endif |
| } |
| |
| if (adv_inst < BTM_BleMaxMultiAdvInstanceCount() && |
| adv_inst != BTM_BLE_MULTI_ADV_DEFAULT_STD) |
| { |
| BTM_TRACE_EVENT("btm_ble_multi_adv_reenable called"); |
| #ifdef WIPOWER_SUPPORTED |
| if (!(is_wipower_adv && (adv_inst == wipower_inst_id))) { |
| btm_ble_multi_adv_reenable(adv_inst); |
| } |
| #else |
| btm_ble_multi_adv_reenable(adv_inst); |
| #endif |
| } |
| /* re-enable connectibility */ |
| else if (adv_inst == BTM_BLE_MULTI_ADV_DEFAULT_STD) |
| { |
| if (btm_cb.ble_ctr_cb.inq_var.connectable_mode == BTM_BLE_CONNECTABLE) |
| { |
| btm_ble_set_connectability ( btm_cb.ble_ctr_cb.inq_var.connectable_mode ); |
| } |
| } |
| |
| } |
| |
| } |
| /******************************************************************************* |
| ** |
| ** Function btm_ble_multi_adv_init |
| ** |
| ** Description This function initialize the multi adv control block. |
| ** |
| ** Parameters UINT8 max_adv_inst |
| ** |
| ** Returns void |
| ** |
| *******************************************************************************/ |
| void btm_ble_multi_adv_init(UINT8 max_adv_inst) |
| { |
| BTM_TRACE_ERROR("%s: max adv instances: %d", __func__, max_adv_inst); |
| UINT8 i = 0; |
| memset(&btm_multi_adv_cb, 0, sizeof(tBTM_BLE_MULTI_ADV_CB)); |
| memset (&btm_multi_adv_idx_q,0, sizeof (tBTM_BLE_MULTI_ADV_INST_IDX_Q)); |
| |
| btm_multi_adv_idx_q.front = -1; |
| btm_multi_adv_idx_q.rear = -1; |
| |
| if (max_adv_inst > 0) |
| { |
| btm_multi_adv_cb.p_adv_inst = osi_calloc(sizeof(tBTM_BLE_MULTI_ADV_INST) * |
| (max_adv_inst)); |
| |
| btm_multi_adv_cb.op_q.p_sub_code = osi_calloc(sizeof(UINT8) * |
| (max_adv_inst)); |
| |
| btm_multi_adv_cb.op_q.p_inst_id = osi_calloc(sizeof(UINT8) * |
| (max_adv_inst)); |
| |
| btm_ble_ext_enable_cb.set_ids = osi_calloc(sizeof(UINT8) * max_adv_inst); |
| |
| btm_ble_ext_enable_cb.durations = osi_calloc(sizeof(UINT16) * max_adv_inst); |
| |
| btm_ble_ext_enable_cb.max_adv_events = osi_calloc(sizeof(UINT8) * max_adv_inst); |
| } |
| |
| /* Initialize adv instance indices and IDs. */ |
| for (i = 0; i < max_adv_inst; i++) { |
| btm_multi_adv_cb.p_adv_inst[i].index = i; |
| btm_multi_adv_cb.p_adv_inst[i].inst_id = i + 1; |
| btm_multi_adv_cb.p_adv_inst[i].adv_raddr_timer = |
| alarm_new("btm_ble.adv_raddr_timer"); |
| } |
| controller_get_interface()->set_ble_adv_ext_size(max_adv_inst); |
| |
| #if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE)) |
| if(!controller_get_interface()->supports_ble_extended_advertisements()) |
| #endif |
| { |
| BTM_RegisterForVSEvents(btm_ble_multi_adv_vse_cback, TRUE); |
| } |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function btm_ble_multi_adv_cleanup |
| ** |
| ** Description This function cleans up multi adv control block. |
| ** |
| ** Parameters |
| ** Returns void |
| ** |
| *******************************************************************************/ |
| void btm_ble_multi_adv_cleanup(void) |
| { |
| #ifdef WIPOWER_SUPPORTED |
| is_wipower_adv = false; |
| wipower_inst_id = BTM_BLE_MULTI_ADV_DEFAULT_STD; |
| #endif |
| |
| pthread_mutex_lock(&btm_multi_adv_lock); |
| if (btm_multi_adv_cb.p_adv_inst) { |
| for (size_t i = 0; i < btm_cb.cmn_ble_vsc_cb.adv_inst_max; i++) { |
| alarm_free(btm_multi_adv_cb.p_adv_inst[i].adv_raddr_timer); |
| } |
| osi_free_and_reset((void **)&btm_multi_adv_cb.p_adv_inst); |
| } |
| |
| osi_free_and_reset((void **)&btm_multi_adv_cb.op_q.p_sub_code); |
| osi_free_and_reset((void **)&btm_multi_adv_cb.op_q.p_inst_id); |
| osi_free_and_reset((void **)&btm_multi_adv_cb.op_q.p_inst_id); |
| osi_free_and_reset((void **)&btm_ble_ext_enable_cb.set_ids); |
| osi_free_and_reset((void **)&btm_ble_ext_enable_cb.durations); |
| osi_free_and_reset((void **)&btm_ble_ext_enable_cb.max_adv_events); |
| pthread_mutex_unlock(&btm_multi_adv_lock); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function btm_ble_multi_adv_get_ref |
| ** |
| ** Description This function obtains the reference pointer for the instance ID provided |
| ** |
| ** Parameters inst_id - Instance ID |
| ** |
| ** Returns void* |
| ** |
| *******************************************************************************/ |
| void* btm_ble_multi_adv_get_ref(UINT8 inst_id) |
| { |
| tBTM_BLE_MULTI_ADV_INST *p_inst = NULL; |
| |
| if (inst_id < BTM_BleMaxMultiAdvInstanceCount()) |
| { |
| p_inst = &btm_multi_adv_cb.p_adv_inst[inst_id - 1]; |
| if (NULL != p_inst) |
| return p_inst->p_ref; |
| } |
| |
| return NULL; |
| } |
| |
| #if (defined BLE_EXTENDED_ADV_SUPPORT && (BLE_EXTENDED_ADV_SUPPORT == TRUE)) |
| |
| /******************************************************************************* |
| ** |
| ** Function btm_ble_enable_extended_adv |
| ** |
| ** Description This function enables the extended adv |
| ** |
| ** Parameters enable: enable or disable |
| ** inst_id: adv instance ID, can not be 0 |
| ** duration: duration of the adv |
| ** |
| ** Returns status |
| ** |
| *******************************************************************************/ |
| tBTM_STATUS btm_ble_enable_extended_adv (BOOLEAN enable, UINT8 inst_id, UINT16 duration, UINT8 max_ext_adv_evts, UINT8 cb_evt) |
| { |
| UINT8 enb = enable ? 1: 0; |
| tBTM_STATUS rt; |
| |
| BTM_TRACE_EVENT ("%s: enb %d, Inst ID %d, dur = %d(s)",__func__, enb,inst_id, duration); |
| inst_id = inst_id - 1; |
| duration = duration * 100; //duration is interpreted as t*10msec |
| |
| if ((rt = btsnd_hcic_ble_set_extended_adv_enable (enb, |
| 1, //Num of sets |
| &inst_id, |
| &duration, |
| &max_ext_adv_evts)) |
| == BTM_CMD_STARTED) |
| { |
| btm_ble_multi_adv_enq_op_q(BTM_BLE_MULTI_ADV_ENB, inst_id + 1, cb_evt); |
| } |
| return rt; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function btm_ble_save_extended_adv_params |
| ** |
| ** Description This function sets the extended adv params |
| ** |
| ** Parameters p_inst: pointer to instance variable |
| ** p_params: adv parameters |
| ** cb_evt: callback event |
| ** |
| ** Returns status |
| ** |
| *******************************************************************************/ |
| void btm_ble_save_extended_adv_params (tBTM_BLE_MULTI_ADV_INST *p_inst,UINT32 adv_int_min, UINT32 adv_int_max, |
| UINT8 own_addr_type, UINT8 pri_phy, UINT8 adv_sid ,UINT8 sec_adv_max_skip, UINT8 sec_adv_phy, |
| UINT8 scan_req_notf_enb, UINT8 channel_map, UINT8 adv_filter_policy, UINT8 tx_power) |
| { |
| if(p_inst != NULL) |
| { |
| p_inst->adv_int_min = adv_int_min; |
| p_inst->adv_int_max = adv_int_max; |
| p_inst->own_addr_type = own_addr_type; |
| p_inst->pri_phy = pri_phy; |
| p_inst->adv_sid = adv_sid; |
| p_inst->sec_adv_max_skip = sec_adv_max_skip; |
| p_inst->sec_adv_phy = sec_adv_phy; |
| p_inst->scan_req_notf_enb = scan_req_notf_enb; |
| p_inst->channel_map = channel_map; |
| p_inst->adv_filter_policy = adv_filter_policy; |
| p_inst->tx_power = tx_power; |
| } |
| } |
| |
| |
| /******************************************************************************* |
| ** |
| ** Function btm_ble_extended_adv_set_params |
| ** |
| ** Description This function sets the extended adv params |
| ** |
| ** Parameters p_inst: pointer to instance variable |
| ** p_params: adv parameters |
| ** cb_evt: callback event |
| ** |
| ** Returns status |
| ** |
| *******************************************************************************/ |
| tBTM_STATUS btm_ble_extended_adv_set_params (tBTM_BLE_MULTI_ADV_INST *p_inst, |
| tBTM_BLE_ADV_PARAMS *p_params, |
| UINT8 cb_evt) |
| { |
| UINT8 set_id; |
| tBTM_BLE_EXT_EVT evt_prop = BTM_BLE_EXT_CONNECT_EVT; |
| tBTM_STATUS rt; |
| tBLE_ADDR_TYPE own_addr_type; |
| tBLE_ADDR_TYPE dir_addr_type = BLE_ADDR_RANDOM; |
| UINT32 adv_int_min = 0, adv_int_max =0; |
| UINT8 adv_filter_policy = 0, tx_power =0, channel_map = 0; |
| UINT8 pri_phy = 0,sec_adv_max_skip=0, sec_adv_phy=0, adv_sid=1, scan_req_notf_enb=0; |
| |
| if (!p_inst) |
| { |
| BTM_TRACE_ERROR ("%s: instance variable is null", __func__); |
| return BTM_ERR_PROCESSING; |
| } |
| |
| if (0 == BTM_BleMaxMultiAdvInstanceCount()) |
| { |
| BTM_TRACE_ERROR ("%s: Controller does not support extended Multi ADV", __func__); |
| return BTM_ERR_PROCESSING; |
| } |
| |
| set_id = p_inst->inst_id; |
| #if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE) |
| if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE) |
| { |
| own_addr_type = BLE_ADDR_RANDOM_ID; |
| } |
| else |
| #endif |
| { |
| own_addr_type = BLE_ADDR_PUBLIC; |
| } |
| |
| if(p_params != NULL) |
| { |
| p_inst->duration = p_params->duration; |
| p_inst->adv_evt = p_params->adv_type; |
| |
| adv_int_min = p_params->adv_int_min; |
| adv_int_max = p_params->adv_int_max; |
| //To identify that event type(adv type) parameter was read from bt_stack.conf and not sent from fwks |
| if(p_params->sec_adv_phy > 0) |
| { |
| evt_prop = p_params->adv_type; |
| pri_phy = p_params->pri_phy; |
| adv_sid = p_params->adv_sid; |
| scan_req_notf_enb =p_params->scan_req_notf_enb; |
| sec_adv_phy = p_params->sec_adv_phy; |
| sec_adv_max_skip = p_params->sec_adv_max_skip; |
| } |
| else |
| { |
| switch (p_params->adv_type) |
| { |
| case BTM_BLE_CONNECT_EVT: |
| evt_prop = BTM_BLE_EXT_CONNECT_EVT; |
| break; |
| case BTM_BLE_CONNECT_DIR_EVT: |
| evt_prop = BTM_BLE_EXT_CONNECT_DIR_EVT; |
| break; |
| case BTM_BLE_DISCOVER_EVT: |
| evt_prop = BTM_BLE_EXT_DISCOVER_EVT; |
| break; |
| case BTM_BLE_NON_CONNECT_EVT: |
| evt_prop = BTM_BLE_EXT_NON_CONNECT_EVT; |
| break; |
| case BTM_BLE_CONNECT_LO_DUTY_DIR_EVT: |
| evt_prop = BTM_BLE_EXT_CONNECT_LO_DUTY_DIR_EVT; |
| break; |
| } |
| pri_phy = BTM_DATA_RATE_ONE; |
| adv_sid = 0x01; |
| |
| } |
| p_inst->evt_prop = evt_prop; |
| |
| if (p_params->channel_map == 0 || p_params->channel_map > BTM_BLE_DEFAULT_ADV_CHNL_MAP) |
| channel_map = BTM_BLE_DEFAULT_ADV_CHNL_MAP; |
| else |
| channel_map = p_params->channel_map; |
| |
| if (p_params->adv_filter_policy >= AP_SCAN_CONN_POLICY_MAX) |
| adv_filter_policy = AP_SCAN_CONN_ALL; |
| else |
| adv_filter_policy = p_params->adv_filter_policy; |
| |
| if (p_params->tx_power > BTM_BLE_ADV_TX_POWER_MAX) |
| tx_power = BTM_BLE_ADV_TX_POWER_MAX; |
| else |
| tx_power = p_params->tx_power; |
| |
| //save ext adv params in p_inst for reenabling adv for chained ext advs |
| btm_ble_save_extended_adv_params(p_inst, adv_int_min, adv_int_max, own_addr_type, pri_phy, adv_sid ,sec_adv_max_skip, |
| sec_adv_phy, scan_req_notf_enb, channel_map, adv_filter_policy,tx_power); |
| } |
| //else case is reached when adv is disabled and re enabled again for chained advs |
| else |
| { |
| evt_prop = p_inst->evt_prop; |
| adv_int_min = p_inst->adv_int_min; |
| adv_int_max =p_inst->adv_int_max; |
| channel_map =p_inst->channel_map; |
| adv_filter_policy =p_inst->adv_filter_policy; |
| tx_power=p_inst->tx_power; |
| pri_phy=p_inst->pri_phy; |
| sec_adv_max_skip=p_inst->sec_adv_max_skip; |
| sec_adv_phy =p_inst->sec_adv_phy; |
| adv_sid =p_inst->adv_sid; |
| scan_req_notf_enb=p_inst->scan_req_notf_enb; |
| } |
| |
| BTM_TRACE_ERROR ("%s: evt_prop::%d, primary_phy=%d,p_params->sec_adv_max_skip=%d, p_params->sec_adv_phy=%d, p_params->adv_sid=%d, p_params->scan_req_notf_enb=%d", __func__, |
| evt_prop, pri_phy, sec_adv_max_skip, sec_adv_phy, adv_sid, scan_req_notf_enb); |
| |
| rt = btsnd_hcic_ble_set_extended_adv_params (set_id - 1, evt_prop, |
| adv_int_min, adv_int_max, |
| channel_map, own_addr_type, |
| dir_addr_type, p_inst->rpa, |
| adv_filter_policy, btm_ble_map_adv_tx_power(tx_power), |
| pri_phy, sec_adv_max_skip, |
| sec_adv_phy, adv_sid, scan_req_notf_enb); |
| |
| if (rt == BTM_CMD_STARTED) |
| { |
| btm_ble_multi_adv_enq_op_q(BTM_BLE_MULTI_ADV_SET_PARAM, set_id, cb_evt); |
| } |
| |
| return rt; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function btm_ble_send_ext_adv_data |
| ** |
| ** Description This function configure a Multi-ADV instance with the specified |
| ** adv data or scan response data. |
| ** |
| ** Parameters inst_id: adv instance ID |
| ** is_scan_rsp: is this scan response. if no, set as adv data. |
| ** data_mask: adv data mask. |
| ** p_data: pointer to the adv data structure. |
| ** operation: |
| ** 0x00: Intermediate fragment |
| ** 0x01: first fragment |
| ** 0x02: Last fragment |
| ** 0x03: complete data, ctrlr fragmentation permitted |
| ** 0x04: complete data, ctrlr fragmentation not permitted |
| ** |
| ** Returns status |
| ** |
| *******************************************************************************/ |
| tBTM_STATUS btm_ble_send_ext_adv_data (BOOLEAN is_scan_rsp, UINT8 inst_id, UINT8 operation, UINT8 frag_pref, UINT8 data_len, UINT8 *param) |
| { |
| tBTM_STATUS rt; |
| UINT8 sub_code; |
| if (!is_scan_rsp) |
| { |
| rt = btsnd_hcic_ble_set_extended_adv_data(inst_id - 1, |
| operation, |
| frag_pref, |
| data_len, |
| param); |
| sub_code = BTM_BLE_MULTI_ADV_WRITE_ADV_DATA; |
| } |
| else |
| { |
| rt = btsnd_hcic_ble_set_extended_scan_rsp_data(inst_id - 1, |
| operation, |
| frag_pref, |
| data_len, |
| param); |
| sub_code = BTM_BLE_MULTI_ADV_WRITE_SCAN_RSP_DATA; |
| } |
| |
| if (rt == BTM_CMD_STARTED) |
| { |
| btm_ble_multi_adv_enq_op_q(sub_code, inst_id, BTM_BLE_MULTI_ADV_DATA_EVT); |
| } |
| return rt; |
| } |
| |
| |
| /******************************************************************************* |
| ** |
| ** Function btm_ble_compute_frag_lens |
| ** |
| ** Description This function configure a Multi-ADV instance with the specified |
| ** adv data or scan response data. |
| ** |
| ** Parameters inst_id: adv instance ID |
| ** is_scan_rsp: is this scan response. if no, set as adv data. |
| ** data_mask: adv data mask. |
| ** p_data: pointer to the adv data structure. |
| ** operation: |
| ** 0x00: Intermediate fragment |
| ** 0x01: first fragment |
| ** 0x02: Last fragment |
| ** 0x03: complete data, ctrlr fragmentation permitted |
| ** 0x04: complete data, ctrlr fragmentation not permitted |
| ** |
| ** Returns status |
| ** |
| *******************************************************************************/ |
| void btm_ble_compute_frag_lens (UINT16 data_len, UINT8* num_hci_cmds, UINT8 *pp_data_len) |
| { |
| UINT8 index = 0; |
| *num_hci_cmds = (data_len/(HCI_COMMAND_SIZE-4)); |
| for(index=0; index < *num_hci_cmds; index++) |
| pp_data_len[index] = (HCI_COMMAND_SIZE -4); |
| |
| if(data_len % (HCI_COMMAND_SIZE-4)) |
| { |
| pp_data_len[index] = (data_len % (HCI_COMMAND_SIZE-4)); |
| (*num_hci_cmds)++; |
| } |
| BTM_TRACE_EVENT("btm_ble_compute_frag_lens::Final num_hci_cmds=%d",*num_hci_cmds); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function btm_ble_get_operation |
| ** |
| ** Description This function configure a Multi-ADV instance with the specified |
| ** adv data or scan response data. |
| ** |
| ** Parameters inst_id: adv instance ID |
| ** is_scan_rsp: is this scan response. if no, set as adv data. |
| ** data_mask: adv data mask. |
| ** p_data: pointer to the adv data structure. |
| ** operation: |
| ** 0x00: Intermediate fragment |
| ** 0x01: first fragment |
| ** 0x02: Last fragment |
| ** 0x03: complete data, ctrlr fragmentation permitted |
| ** 0x04: complete data, ctrlr fragmentation not permitted |
| ** |
| ** Returns status |
| ** |
| *******************************************************************************/ |
| UINT8 btm_ble_get_operation (UINT8 num_hci_cmds_copy, UINT8 num_hci_cmds) |
| { |
| UINT8 op = 0; |
| if(num_hci_cmds_copy == num_hci_cmds) |
| op = BTM_BLE_EXT_ADV_FIRST_FRAG; |
| else if(num_hci_cmds != 1) |
| op = BTM_BLE_EXT_ADV_INT_FRAG; |
| else |
| op = BTM_BLE_EXT_ADV_LAST_FRAG; |
| return op; |
| } |
| |
| |
| /******************************************************************************* |
| ** |
| ** Function BTM_BleWriteExtendedAdvData |
| ** |
| ** Description This function configure a Multi-ADV instance with the specified |
| ** adv data or scan response data. |
| ** |
| ** Parameters inst_id: adv instance ID |
| ** is_scan_rsp: is this scan response. if no, set as adv data. |
| ** data_mask: adv data mask. |
| ** p_data: pointer to the adv data structure. |
| ** operation: |
| ** 0x00: Intermediate fragment |
| ** 0x01: first fragment |
| ** 0x02: Last fragment |
| ** 0x03: complete data, ctrlr fragmentation permitted |
| ** 0x04: complete data, ctrlr fragmentation not permitted |
| ** |
| ** Returns status |
| ** |
| *******************************************************************************/ |
| tBTM_STATUS BTM_BleWriteExtendedAdvData (UINT8 inst_id, BOOLEAN is_scan_rsp, |
| tBTM_BLE_AD_MASK data_mask, |
| UINT8 operation, UINT8 frag_pref, |
| tBTM_BLE_ADV_DATA *p_data) |
| { |
| UINT8 param[BTM_BLE_EXTENDED_AD_DATA_LEN], *pp = param, frag_data[HCI_COMMAND_SIZE-4]; |
| UINT8 frag_data_len[BTM_BLE_EXT_ADV_MAX_FRAG_NUM], index=0; |
| UINT16 data_len, offset =0, j=0; |
| tBTM_STATUS rt; |
| UINT8 num_hci_cmds = 0, num_hci_cmds_copy = 0; |
| tBTM_BLE_MULTI_ADV_INST *p_inst; |
| tBTM_BLE_LOCAL_ADV_DATA *p_adv_data = &btm_cb.ble_ctr_cb.inq_var.adv_data; |
| |
| if (0 == BTM_BleMaxMultiAdvInstanceCount()) |
| { |
| BTM_TRACE_ERROR ("%s: Controller does not support extended Multi ADV", __func__); |
| return BTM_ERR_PROCESSING; |
| } |
| BTM_TRACE_EVENT("BTM_BleWriteExtendedAdvData"); |
| if (stack_config_get_interface()->get_pts_le_nonconn_adv_enabled()) |
| { |
| if (p_adv_data->p_flags != NULL) |
| { |
| p_data->flag = *(p_adv_data->p_flags); |
| } |
| } |
| |
| btm_ble_update_dmt_flag_bits(&p_data->flag, btm_cb.btm_inq_vars.connectable_mode, |
| btm_cb.btm_inq_vars.discoverable_mode); |
| |
| BTM_TRACE_EVENT("%s called with inst_id:%d", __func__, inst_id); |
| // inst_id will range from 1 to 16 max, so the below should ideally fail |
| if (inst_id > BTM_BLE_MULTI_ADV_MAX || inst_id == BTM_BLE_MULTI_ADV_DEFAULT_STD) |
| return BTM_ILLEGAL_VALUE; |
| |
| p_inst = &btm_multi_adv_cb.p_adv_inst[inst_id - 1]; |
| |
| /* check if adv is not enabled for operations 0 to 3 */ |
| if (p_inst->in_use && (operation < BTM_BLE_EXT_ADV_COMPLETE)) |
| { |
| BTM_TRACE_ERROR ("%s: Illegal operation: %d while adv is enabled", __func__, operation); |
| return BTM_ILLEGAL_VALUE; |
| } |
| |
| memset(param, 0, BTM_BLE_EXTENDED_AD_DATA_LEN); |
| |
| if (p_inst->len == 0 || (p_inst->evt_prop & BTM_BLE_EXTENDED_LEGACY_MASK)) { |
| BTM_TRACE_ERROR("%s: using default length 31 bytes", __func__); |
| p_inst->len = BTM_BLE_AD_DATA_LEN; |
| } |
| |
| btm_ble_build_adv_data(&data_mask, &pp, p_data, p_inst->len); |
| data_len = (UINT16) (pp - param); |
| BTM_TRACE_ERROR("%s: data len is %d", __func__, data_len); |
| |
| if(data_len > HCI_COMMAND_SIZE) |
| btm_ble_compute_frag_lens(data_len, &num_hci_cmds, frag_data_len); |
| |
| num_hci_cmds_copy = num_hci_cmds; |
| |
| if(num_hci_cmds > 0) |
| { |
| //Disable advertisement |
| rt = btm_ble_enable_extended_adv (FALSE, inst_id, |
| p_inst->duration, 0/*p_params->max_ext_adv_evts*/, |
| 0/*instead of BTM_BLE_MULTI_ADV_DISABLE_EVT*/); |
| p_inst->in_use = FALSE; |
| |
| //set ext adv params |
| if (rt == BTM_CMD_STARTED) |
| { |
| p_inst->in_use = TRUE; |
| rt = btm_ble_extended_adv_set_params(p_inst, NULL, 0); |
| } |
| |
| //set ext adv data |
| if (rt == BTM_CMD_STARTED) |
| { |
| while(num_hci_cmds) |
| { |
| memset(frag_data, 0, frag_data_len[index]); |
| BTM_TRACE_ERROR("offset =%d , index =%d ,frag_data_len[index] ::%d",offset, index, frag_data_len[index]); |
| for(j=0; j< frag_data_len[index]; j++) |
| { |
| BTM_TRACE_ERROR("Adv data ::%02x",param[offset+j]); |
| } |
| memcpy(frag_data, (param+offset), frag_data_len[index]); |
| operation = btm_ble_get_operation(num_hci_cmds_copy, num_hci_cmds); |
| offset += frag_data_len[index]; |
| rt = btm_ble_send_ext_adv_data(is_scan_rsp, inst_id, operation, frag_pref, frag_data_len[index++], frag_data); |
| num_hci_cmds--; |
| } |
| } |
| //enable ext adv |
| if (rt == BTM_CMD_STARTED) |
| { |
| rt = btm_ble_enable_extended_adv (TRUE, p_inst->inst_id, p_inst->duration, 0, 0/*instead of BTM_BLE_EXTENDED_ADV_ENB_EVT*/); |
| } |
| } |
| else |
| rt = btm_ble_send_ext_adv_data(is_scan_rsp, inst_id, operation, frag_pref, data_len, param); |
| |
| return rt; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function btm_ble_ext_adv_reenable |
| ** |
| ** Description This function re-enable adv instance upon a connection establishment. |
| ** |
| ** Parameters instance id |
| ** |
| ** Returns none. |
| ** |
| *******************************************************************************/ |
| void btm_ble_ext_adv_reenable(UINT8 inst_id) |
| { |
| BTM_TRACE_DEBUG("%s, instance id: %d", __func__, inst_id); |
| tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.p_adv_inst[inst_id - 1]; |
| //TODO: Use expired ticks instead. GKI_get_os_tick_count |
| // provides time in msec. Diff between current and start time |
| // to figure out remaining duration |
| UINT16 duration = p_inst->duration; |
| |
| if (TRUE == p_inst->in_use) |
| { |
| // Verify the evt prop directed adv bit is 0 |
| if (!(p_inst->evt_prop & 0x04)) |
| btm_ble_enable_extended_adv (TRUE, p_inst->inst_id, duration, 0, 0); |
| else |
| { |
| //mark directed adv as disabled if adv has been stopped |
| (p_inst->p_cback)(BTM_BLE_MULTI_ADV_DISABLE_EVT,p_inst->inst_id,p_inst->p_ref,0); |
| p_inst->in_use = FALSE; |
| } |
| } |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function btm_ble_multi_adv_enable_all |
| ** |
| ** Description This function enables/disables all adv instances at once |
| ** |
| ** Parameters enable/disable |
| ** |
| ** Returns none. |
| ** |
| *******************************************************************************/ |
| void btm_ble_multi_adv_enable_all(UINT8 enable) |
| { |
| BTM_TRACE_DEBUG("%s, enable = %d", __func__, enable); |
| int i; |
| tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.p_adv_inst[0]; |
| UINT8 enb = enable? 1:0; |
| UINT8 num_instances = 0; |
| |
| for (i = 0; i < BTM_BleMaxMultiAdvInstanceCount() - 1; i++, p_inst++) |
| { |
| if (p_inst->in_use) { |
| btm_ble_ext_enable_cb.set_ids[num_instances] = p_inst->inst_id - 1; |
| btm_ble_ext_enable_cb.durations[num_instances] = p_inst->duration * 100; |
| btm_ble_ext_enable_cb.max_adv_events[num_instances] = 0x00; |
| num_instances++; |
| } |
| } |
| |
| if (num_instances == 0) return; |
| |
| if (!enable) |
| { |
| if (btsnd_hcic_ble_set_extended_adv_enable(enb, 0, NULL, NULL, NULL) |
| == BTM_CMD_STARTED) |
| { |
| btm_ble_multi_adv_enq_op_q(BTM_BLE_MULTI_ADV_ENB, 1, 0); |
| } |
| } |
| else |
| { |
| if ((btsnd_hcic_ble_set_extended_adv_enable (enb, |
| num_instances, |
| btm_ble_ext_enable_cb.set_ids, |
| btm_ble_ext_enable_cb.durations, |
| btm_ble_ext_enable_cb.max_adv_events)) |
| == BTM_CMD_STARTED) |
| { |
| btm_ble_multi_adv_enq_op_q(BTM_BLE_MULTI_ADV_ENB, 1, 0); |
| } |
| } |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function btm_ble_adv_set_terminated_evt |
| ** |
| ** Description This function is a callback event when an adv set is |
| ** terminiated due to connection complete or due to duration |
| ** timeout |
| ** |
| ** Returns void |
| ** |
| *******************************************************************************/ |
| |
| void btm_ble_adv_set_terminated_evt (UINT8* p) |
| { |
| BTM_TRACE_EVENT("%s", __func__); |
| UINT8 status; |
| UINT8 inst_id; |
| UINT16 handle; |
| tBTM_BLE_MULTI_ADV_INST *p_inst; |
| |
| STREAM_TO_UINT8(status,p); |
| STREAM_TO_UINT8(inst_id, p); |
| |
| //Adjust inst_id to base 1 |
| inst_id++; |
| |
| STREAM_TO_UINT16(handle, p); |
| BTM_TRACE_DEBUG("%s, status = %d, inst_id = %d, handle = %x", |
| __func__, status, inst_id, handle); |
| |
| if (inst_id > BTM_BleMaxMultiAdvInstanceCount() || |
| inst_id == BTM_BLE_MULTI_ADV_DEFAULT_STD) |
| { |
| BTM_TRACE_ERROR("%s:Invalid instance received", __func__); |
| return; |
| } |
| |
| p_inst = &btm_multi_adv_cb.p_adv_inst[inst_id - 1]; |
| |
| if (status == BTM_BLE_EXTENDED_ADV_TIMEOUT) |
| { |
| p_inst->in_use = FALSE; |
| if (p_inst->p_cback) |
| (p_inst->p_cback)(BTM_BLE_MULTI_ADV_DISABLE_EVT,p_inst->inst_id, p_inst->p_ref, 0); |
| } |
| |
| else if (status == HCI_SUCCESS) |
| { |
| btm_ble_ext_adv_reenable(inst_id); |
| } |
| } |
| |
| |
| /******************************************************************************* |
| ** |
| ** Function btm_ble_adv_extension_operation_complete |
| ** |
| ** Description This function is a callback event of adv extension operation |
| ** including write rpa, set adv data/scan rsp data |
| ** |
| ** Returns void |
| ** |
| *******************************************************************************/ |
| |
| void btm_ble_adv_extension_operation_complete(UINT8* p, UINT16 hcicmd) |
| { |
| UINT8 status; |
| UINT8 cb_evt = 0, opcode; |
| UINT8 subcode = 0; |
| UINT8 inst_id; |
| tBTM_BLE_MULTI_ADV_INST *p_inst ; |
| STREAM_TO_UINT8 (status, p); |
| |
| BTM_TRACE_EVENT ("%s, status: %d, opcode = %d", __func__, status, hcicmd); |
| |
| if (status != HCI_SUCCESS) |
| { |
| BTM_TRACE_ERROR ("%s, HCI command failure", __func__); |
| return; |
| } |
| |
| btm_ble_multi_adv_deq_op_q(&opcode, &inst_id, &cb_evt); |
| |
| switch (hcicmd) |
| { |
| case HCI_BLE_WRITE_EXTENDED_ADV_RPA: |
| subcode = BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR; |
| break; |
| case HCI_BLE_WRITE_EXTENDED_ADV_DATA: |
| subcode = BTM_BLE_MULTI_ADV_WRITE_ADV_DATA; |
| break; |
| case HCI_BLE_WRITE_EXTENDED_SCAN_RSP_DATA: |
| subcode = BTM_BLE_MULTI_ADV_WRITE_SCAN_RSP_DATA; |
| break; |
| case HCI_BLE_WRITE_EXTENDED_ADV_PARAMS: |
| subcode = BTM_BLE_MULTI_ADV_SET_PARAM; |
| break; |
| case HCI_BLE_WRITE_EXTENDED_ADV_ENABLE: |
| subcode = BTM_BLE_MULTI_ADV_ENB; |
| break; |
| } |
| |
| if (opcode != subcode) |
| { |
| BTM_TRACE_ERROR("got unexpected Event, expected: %d got: %d", opcode, subcode); |
| return; |
| } |
| p_inst = &btm_multi_adv_cb.p_adv_inst[inst_id - 1]; |
| |
| if (cb_evt != 0 && p_inst->p_cback != NULL) |
| { |
| (p_inst->p_cback)(cb_evt, inst_id, p_inst->p_ref, status); |
| } |
| return; |
| } |
| |
| UINT8 BTM_BleGetAvailableMAInstance () |
| { |
| int index = 0; |
| tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.p_adv_inst[0]; |
| |
| BTM_TRACE_EVENT("BTM_BleGetAvailableMAInstance"); |
| |
| for (index = 0; index < BTM_BleMaxMultiAdvInstanceCount() - 1; index++, p_inst++) |
| { |
| if (FALSE == p_inst->in_use) |
| break; |
| } |
| return index; |
| } |
| |
| #endif |
| #endif |
| |