Home | History | Annotate | Download | only in btm
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 2014  Broadcom Corporation
      4  *
      5  *  Licensed under the Apache License, Version 2.0 (the "License");
      6  *  you may not use this file except in compliance with the License.
      7  *  You may obtain a copy of the License at:
      8  *
      9  *  http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  *
     17  ******************************************************************************/
     18 
     19 #include <string.h>
     20 
     21 #include "bt_target.h"
     22 #include "device/include/controller.h"
     23 
     24 #if (BLE_INCLUDED == TRUE)
     25 #include "bt_types.h"
     26 #include "hcimsgs.h"
     27 #include "btu.h"
     28 #include "btm_int.h"
     29 #include "bt_utils.h"
     30 #include "hcidefs.h"
     31 #include "btm_ble_api.h"
     32 
     33 /************************************************************************************
     34 **  Constants & Macros
     35 ************************************************************************************/
     36 /* length of each multi adv sub command */
     37 #define BTM_BLE_MULTI_ADV_ENB_LEN                       3
     38 #define BTM_BLE_MULTI_ADV_SET_PARAM_LEN                 24
     39 #define BTM_BLE_MULTI_ADV_WRITE_DATA_LEN                (BTM_BLE_AD_DATA_LEN + 3)
     40 #define BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN           8
     41 
     42 #define BTM_BLE_MULTI_ADV_CB_EVT_MASK   0xF0
     43 #define BTM_BLE_MULTI_ADV_SUBCODE_MASK  0x0F
     44 
     45 /************************************************************************************
     46 **  Static variables
     47 ************************************************************************************/
     48 tBTM_BLE_MULTI_ADV_CB  btm_multi_adv_cb;
     49 tBTM_BLE_MULTI_ADV_INST_IDX_Q btm_multi_adv_idx_q;
     50 
     51 /************************************************************************************
     52 **  Externs
     53 ************************************************************************************/
     54 extern fixed_queue_t *btu_general_alarm_queue;
     55 extern void btm_ble_update_dmt_flag_bits(UINT8 *flag_value,
     56                                                const UINT16 connect_mode, const UINT16 disc_mode);
     57 
     58 /*******************************************************************************
     59 **
     60 ** Function         btm_ble_multi_adv_enq_op_q
     61 **
     62 ** Description      enqueue a multi adv operation in q to check command complete
     63 **                  status.
     64 **
     65 ** Returns          void
     66 **
     67 *******************************************************************************/
     68 void btm_ble_multi_adv_enq_op_q(UINT8 opcode, UINT8 inst_id, UINT8 cb_evt)
     69 {
     70     tBTM_BLE_MULTI_ADV_OPQ  *p_op_q = &btm_multi_adv_cb.op_q;
     71 
     72     p_op_q->p_inst_id[p_op_q->next_idx] = inst_id;
     73 
     74     p_op_q->p_sub_code[p_op_q->next_idx] = (opcode |(cb_evt << 4));
     75 
     76     p_op_q->next_idx = (p_op_q->next_idx + 1) %  BTM_BleMaxMultiAdvInstanceCount();
     77 }
     78 
     79 /*******************************************************************************
     80 **
     81 ** Function         btm_ble_multi_adv_deq_op_q
     82 **
     83 ** Description      dequeue a multi adv operation from q when command complete
     84 **                  is received.
     85 **
     86 ** Returns          void
     87 **
     88 *******************************************************************************/
     89 void btm_ble_multi_adv_deq_op_q(UINT8 *p_opcode, UINT8 *p_inst_id, UINT8 *p_cb_evt)
     90 {
     91     tBTM_BLE_MULTI_ADV_OPQ  *p_op_q = &btm_multi_adv_cb.op_q;
     92 
     93     *p_inst_id = p_op_q->p_inst_id[p_op_q->pending_idx] & 0x7F;
     94     *p_cb_evt = (p_op_q->p_sub_code[p_op_q->pending_idx] >> 4);
     95     *p_opcode = (p_op_q->p_sub_code[p_op_q->pending_idx] & BTM_BLE_MULTI_ADV_SUBCODE_MASK);
     96 
     97     p_op_q->pending_idx = (p_op_q->pending_idx + 1) %  BTM_BleMaxMultiAdvInstanceCount();
     98 }
     99 
    100 /*******************************************************************************
    101 **
    102 ** Function         btm_ble_multi_adv_vsc_cmpl_cback
    103 **
    104 ** Description      Multi adv VSC complete callback
    105 **
    106 ** Parameters
    107 **
    108 ** Returns          void
    109 **
    110 *******************************************************************************/
    111 void btm_ble_multi_adv_vsc_cmpl_cback (tBTM_VSC_CMPL *p_params)
    112 {
    113     UINT8  status, subcode;
    114     UINT8  *p = p_params->p_param_buf, inst_id;
    115     UINT16  len = p_params->param_len;
    116     tBTM_BLE_MULTI_ADV_INST *p_inst ;
    117     UINT8   cb_evt = 0, opcode;
    118 
    119     if (len  < 2)
    120     {
    121         BTM_TRACE_ERROR("wrong length for btm_ble_multi_adv_vsc_cmpl_cback");
    122         return;
    123     }
    124 
    125     STREAM_TO_UINT8(status, p);
    126     STREAM_TO_UINT8(subcode, p);
    127 
    128     btm_ble_multi_adv_deq_op_q(&opcode, &inst_id, &cb_evt);
    129 
    130     BTM_TRACE_DEBUG("op_code = %02x inst_id = %d cb_evt = %02x", opcode, inst_id, cb_evt);
    131 
    132     if (opcode != subcode || inst_id == 0)
    133     {
    134         BTM_TRACE_ERROR("get unexpected VSC cmpl, expect: %d get: %d",subcode,opcode);
    135         return;
    136     }
    137 
    138     p_inst = &btm_multi_adv_cb.p_adv_inst[inst_id - 1];
    139 
    140     switch (subcode)
    141     {
    142         case BTM_BLE_MULTI_ADV_ENB:
    143         {
    144             BTM_TRACE_DEBUG("BTM_BLE_MULTI_ADV_ENB status = %d", status);
    145 
    146             /* Mark as not in use here, if instance cannot be enabled */
    147             if (HCI_SUCCESS != status && BTM_BLE_MULTI_ADV_ENB_EVT == cb_evt)
    148                 btm_multi_adv_cb.p_adv_inst[inst_id-1].in_use = FALSE;
    149             break;
    150         }
    151 
    152         case BTM_BLE_MULTI_ADV_SET_PARAM:
    153         {
    154             BTM_TRACE_DEBUG("BTM_BLE_MULTI_ADV_SET_PARAM status = %d", status);
    155             break;
    156         }
    157 
    158         case BTM_BLE_MULTI_ADV_WRITE_ADV_DATA:
    159         {
    160             BTM_TRACE_DEBUG("BTM_BLE_MULTI_ADV_WRITE_ADV_DATA status = %d", status);
    161             break;
    162         }
    163 
    164         case BTM_BLE_MULTI_ADV_WRITE_SCAN_RSP_DATA:
    165         {
    166             BTM_TRACE_DEBUG("BTM_BLE_MULTI_ADV_WRITE_SCAN_RSP_DATA status = %d", status);
    167             break;
    168         }
    169 
    170         case BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR:
    171         {
    172             BTM_TRACE_DEBUG("BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR status = %d", status);
    173             break;
    174         }
    175 
    176         default:
    177             break;
    178     }
    179 
    180     if (cb_evt != 0 && p_inst->p_cback != NULL)
    181     {
    182         (p_inst->p_cback)(cb_evt, inst_id, p_inst->p_ref, status);
    183     }
    184     return;
    185 }
    186 
    187 /*******************************************************************************
    188 **
    189 ** Function         btm_ble_enable_multi_adv
    190 **
    191 ** Description      This function enable the customer specific feature in controller
    192 **
    193 ** Parameters       enable: enable or disable
    194 **                  inst_id:    adv instance ID, can not be 0
    195 **
    196 ** Returns          status
    197 **
    198 *******************************************************************************/
    199 tBTM_STATUS btm_ble_enable_multi_adv (BOOLEAN enable, UINT8 inst_id, UINT8 cb_evt)
    200 {
    201     UINT8           param[BTM_BLE_MULTI_ADV_ENB_LEN], *pp;
    202     UINT8           enb = enable ? 1: 0;
    203     tBTM_STATUS     rt;
    204 
    205     pp = param;
    206     memset(param, 0, BTM_BLE_MULTI_ADV_ENB_LEN);
    207 
    208     UINT8_TO_STREAM (pp, BTM_BLE_MULTI_ADV_ENB);
    209     UINT8_TO_STREAM (pp, enb);
    210     UINT8_TO_STREAM (pp, inst_id);
    211 
    212     BTM_TRACE_EVENT (" btm_ble_enable_multi_adv: enb %d, Inst ID %d",enb,inst_id);
    213 
    214     if ((rt = BTM_VendorSpecificCommand (HCI_BLE_MULTI_ADV_OCF,
    215                                     BTM_BLE_MULTI_ADV_ENB_LEN,
    216                                     param,
    217                                     btm_ble_multi_adv_vsc_cmpl_cback))
    218                                      == BTM_CMD_STARTED)
    219     {
    220         btm_ble_multi_adv_enq_op_q(BTM_BLE_MULTI_ADV_ENB, inst_id, cb_evt);
    221     }
    222     return rt;
    223 }
    224 /*******************************************************************************
    225 **
    226 ** Function         btm_ble_map_adv_tx_power
    227 **
    228 ** Description      return the actual power in dBm based on the mapping in config file
    229 **
    230 ** Parameters       advertise parameters used for this instance.
    231 **
    232 ** Returns          tx power in dBm
    233 **
    234 *******************************************************************************/
    235 int btm_ble_tx_power[BTM_BLE_ADV_TX_POWER_MAX + 1] = BTM_BLE_ADV_TX_POWER;
    236 char btm_ble_map_adv_tx_power(int tx_power_index)
    237 {
    238     if(0 <= tx_power_index && tx_power_index < BTM_BLE_ADV_TX_POWER_MAX)
    239         return (char)btm_ble_tx_power[tx_power_index];
    240     return 0;
    241 }
    242 /*******************************************************************************
    243 **
    244 ** Function         btm_ble_multi_adv_set_params
    245 **
    246 ** Description      This function enable the customer specific feature in controller
    247 **
    248 ** Parameters       advertise parameters used for this instance.
    249 **
    250 ** Returns          status
    251 **
    252 *******************************************************************************/
    253 tBTM_STATUS btm_ble_multi_adv_set_params (tBTM_BLE_MULTI_ADV_INST *p_inst,
    254                                           tBTM_BLE_ADV_PARAMS *p_params,
    255                                           UINT8 cb_evt)
    256 {
    257     UINT8           param[BTM_BLE_MULTI_ADV_SET_PARAM_LEN], *pp;
    258     tBTM_STATUS     rt;
    259     BD_ADDR         dummy ={0,0,0,0,0,0};
    260 
    261     pp = param;
    262     memset(param, 0, BTM_BLE_MULTI_ADV_SET_PARAM_LEN);
    263 
    264     UINT8_TO_STREAM(pp, BTM_BLE_MULTI_ADV_SET_PARAM);
    265 
    266     UINT16_TO_STREAM (pp, p_params->adv_int_min);
    267     UINT16_TO_STREAM (pp, p_params->adv_int_max);
    268     UINT8_TO_STREAM  (pp, p_params->adv_type);
    269 
    270 #if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
    271     if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE)
    272     {
    273         UINT8_TO_STREAM  (pp, BLE_ADDR_RANDOM);
    274         BDADDR_TO_STREAM (pp, p_inst->rpa);
    275     }
    276     else
    277 #endif
    278     {
    279         UINT8_TO_STREAM  (pp, BLE_ADDR_PUBLIC);
    280         BDADDR_TO_STREAM (pp, controller_get_interface()->get_address()->address);
    281     }
    282 
    283     BTM_TRACE_EVENT (" btm_ble_multi_adv_set_params,Min %d, Max %d,adv_type %d",
    284         p_params->adv_int_min,p_params->adv_int_max,p_params->adv_type);
    285 
    286     UINT8_TO_STREAM  (pp, 0);
    287     BDADDR_TO_STREAM (pp, dummy);
    288 
    289     if (p_params->channel_map == 0 || p_params->channel_map > BTM_BLE_DEFAULT_ADV_CHNL_MAP)
    290         p_params->channel_map = BTM_BLE_DEFAULT_ADV_CHNL_MAP;
    291     UINT8_TO_STREAM (pp, p_params->channel_map);
    292 
    293     if (p_params->adv_filter_policy >= AP_SCAN_CONN_POLICY_MAX)
    294         p_params->adv_filter_policy = AP_SCAN_CONN_ALL;
    295     UINT8_TO_STREAM (pp, p_params->adv_filter_policy);
    296 
    297     UINT8_TO_STREAM (pp, p_inst->inst_id);
    298 
    299     if (p_params->tx_power > BTM_BLE_ADV_TX_POWER_MAX)
    300         p_params->tx_power = BTM_BLE_ADV_TX_POWER_MAX;
    301     UINT8_TO_STREAM (pp, btm_ble_map_adv_tx_power(p_params->tx_power));
    302 
    303     BTM_TRACE_EVENT("set_params:Chnl Map %d,adv_fltr policy %d,ID:%d, TX Power%d",
    304         p_params->channel_map,p_params->adv_filter_policy,p_inst->inst_id,p_params->tx_power);
    305 
    306     if ((rt = BTM_VendorSpecificCommand (HCI_BLE_MULTI_ADV_OCF,
    307                                     BTM_BLE_MULTI_ADV_SET_PARAM_LEN,
    308                                     param,
    309                                     btm_ble_multi_adv_vsc_cmpl_cback))
    310            == BTM_CMD_STARTED)
    311     {
    312         p_inst->adv_evt = p_params->adv_type;
    313 
    314 #if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
    315         if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE) {
    316             alarm_set_on_queue(p_inst->adv_raddr_timer,
    317                                BTM_BLE_PRIVATE_ADDR_INT_MS,
    318                                btm_ble_adv_raddr_timer_timeout, p_inst,
    319                                btu_general_alarm_queue);
    320         }
    321 #endif
    322         btm_ble_multi_adv_enq_op_q(BTM_BLE_MULTI_ADV_SET_PARAM, p_inst->inst_id, cb_evt);
    323     }
    324     return rt;
    325 }
    326 
    327 /*******************************************************************************
    328 **
    329 ** Function         btm_ble_multi_adv_write_rpa
    330 **
    331 ** Description      This function write the random address for the adv instance into
    332 **                  controller
    333 **
    334 ** Parameters
    335 **
    336 ** Returns          status
    337 **
    338 *******************************************************************************/
    339 tBTM_STATUS btm_ble_multi_adv_write_rpa (tBTM_BLE_MULTI_ADV_INST *p_inst, BD_ADDR random_addr)
    340 {
    341     UINT8           param[BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN], *pp = param;
    342     tBTM_STATUS     rt;
    343 
    344     BTM_TRACE_EVENT ("%s-BD_ADDR:%02x-%02x-%02x-%02x-%02x-%02x,inst_id:%d",
    345                       __FUNCTION__, random_addr[5], random_addr[4], random_addr[3], random_addr[2],
    346                       random_addr[1], random_addr[0], p_inst->inst_id);
    347 
    348     memset(param, 0, BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN);
    349 
    350     UINT8_TO_STREAM (pp, BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR);
    351     BDADDR_TO_STREAM(pp, random_addr);
    352     UINT8_TO_STREAM(pp,  p_inst->inst_id);
    353 
    354     if ((rt = BTM_VendorSpecificCommand (HCI_BLE_MULTI_ADV_OCF,
    355                                     BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN,
    356                                     param,
    357                                     btm_ble_multi_adv_vsc_cmpl_cback)) == BTM_CMD_STARTED)
    358     {
    359         /* start a periodical timer to refresh random addr */
    360         /* TODO: is the above comment correct - is the timer periodical? */
    361         alarm_set_on_queue(p_inst->adv_raddr_timer,
    362                            BTM_BLE_PRIVATE_ADDR_INT_MS,
    363                            btm_ble_adv_raddr_timer_timeout, p_inst,
    364                            btu_general_alarm_queue);
    365         btm_ble_multi_adv_enq_op_q(BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR,
    366                                    p_inst->inst_id, 0);
    367     }
    368     return rt;
    369 }
    370 
    371 /*******************************************************************************
    372 **
    373 ** Function         btm_ble_multi_adv_gen_rpa_cmpl
    374 **
    375 ** Description      RPA generation completion callback for each adv instance. Will
    376 **                  continue write the new RPA into controller.
    377 **
    378 ** Returns          none.
    379 **
    380 *******************************************************************************/
    381 void btm_ble_multi_adv_gen_rpa_cmpl(tBTM_RAND_ENC *p)
    382 {
    383 #if (SMP_INCLUDED == TRUE)
    384     tSMP_ENC    output;
    385     UINT8 index = 0;
    386     tBTM_BLE_MULTI_ADV_INST *p_inst = NULL;
    387 
    388      /* Retrieve the index of adv instance from stored Q */
    389     if (btm_multi_adv_idx_q.front == -1)
    390     {
    391         BTM_TRACE_ERROR(" %s can't locate advertise instance", __FUNCTION__);
    392         return;
    393     }
    394     else
    395     {
    396         index = btm_multi_adv_idx_q.inst_index_queue[btm_multi_adv_idx_q.front];
    397         if (btm_multi_adv_idx_q.front == btm_multi_adv_idx_q.rear)
    398         {
    399             btm_multi_adv_idx_q.front = -1;
    400             btm_multi_adv_idx_q.rear = -1;
    401         }
    402         else
    403         {
    404             btm_multi_adv_idx_q.front = (btm_multi_adv_idx_q.front + 1) % BTM_BLE_MULTI_ADV_MAX;
    405         }
    406     }
    407 
    408     p_inst = &(btm_multi_adv_cb.p_adv_inst[index]);
    409 
    410     BTM_TRACE_EVENT ("btm_ble_multi_adv_gen_rpa_cmpl inst_id = %d", p_inst->inst_id);
    411     if (p)
    412     {
    413         p->param_buf[2] &= (~BLE_RESOLVE_ADDR_MASK);
    414         p->param_buf[2] |= BLE_RESOLVE_ADDR_MSB;
    415 
    416         p_inst->rpa[2] = p->param_buf[0];
    417         p_inst->rpa[1] = p->param_buf[1];
    418         p_inst->rpa[0] = p->param_buf[2];
    419 
    420         if (!SMP_Encrypt(btm_cb.devcb.id_keys.irk, BT_OCTET16_LEN, p->param_buf, 3, &output))
    421         {
    422             BTM_TRACE_DEBUG("generate random address failed");
    423         }
    424         else
    425         {
    426             /* set hash to be LSB of rpAddress */
    427             p_inst->rpa[5] = output.param_buf[0];
    428             p_inst->rpa[4] = output.param_buf[1];
    429             p_inst->rpa[3] = output.param_buf[2];
    430         }
    431 
    432         if (p_inst->inst_id != BTM_BLE_MULTI_ADV_DEFAULT_STD &&
    433             p_inst->inst_id < BTM_BleMaxMultiAdvInstanceCount())
    434         {
    435             /* set it to controller */
    436             btm_ble_multi_adv_write_rpa(p_inst, p_inst->rpa);
    437         }
    438     }
    439 #endif
    440 }
    441 
    442 /*******************************************************************************
    443 **
    444 ** Function         btm_ble_multi_adv_configure_rpa
    445 **
    446 ** Description      This function set the random address for the adv instance
    447 **
    448 ** Parameters       advertise parameters used for this instance.
    449 **
    450 ** Returns          none
    451 **
    452 *******************************************************************************/
    453 void btm_ble_multi_adv_configure_rpa (tBTM_BLE_MULTI_ADV_INST *p_inst)
    454 {
    455     if (btm_multi_adv_idx_q.front == (btm_multi_adv_idx_q.rear + 1) % BTM_BLE_MULTI_ADV_MAX)
    456     {
    457         BTM_TRACE_ERROR("outstanding rand generation exceeded max allowed ");
    458         return;
    459     }
    460     else
    461     {
    462         if (btm_multi_adv_idx_q.front == -1)
    463         {
    464             btm_multi_adv_idx_q.front = 0;
    465             btm_multi_adv_idx_q.rear = 0;
    466         }
    467         else
    468         {
    469             btm_multi_adv_idx_q.rear = (btm_multi_adv_idx_q.rear + 1) % BTM_BLE_MULTI_ADV_MAX;
    470         }
    471         btm_multi_adv_idx_q.inst_index_queue[btm_multi_adv_idx_q.rear] = p_inst->index;
    472     }
    473     btm_gen_resolvable_private_addr((void *)btm_ble_multi_adv_gen_rpa_cmpl);
    474 }
    475 
    476 /*******************************************************************************
    477 **
    478 ** Function         btm_ble_multi_adv_reenable
    479 **
    480 ** Description      This function re-enable adv instance upon a connection establishment.
    481 **
    482 ** Parameters       advertise parameters used for this instance.
    483 **
    484 ** Returns          none.
    485 **
    486 *******************************************************************************/
    487 void btm_ble_multi_adv_reenable(UINT8 inst_id)
    488 {
    489     tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.p_adv_inst[inst_id - 1];
    490 
    491     if (TRUE == p_inst->in_use)
    492     {
    493         if (p_inst->adv_evt != BTM_BLE_CONNECT_DIR_EVT)
    494             btm_ble_enable_multi_adv (TRUE, p_inst->inst_id, 0);
    495         else
    496           /* mark directed adv as disabled if adv has been stopped */
    497         {
    498             (p_inst->p_cback)(BTM_BLE_MULTI_ADV_DISABLE_EVT,p_inst->inst_id,p_inst->p_ref,0);
    499              p_inst->in_use = FALSE;
    500         }
    501      }
    502 }
    503 
    504 /*******************************************************************************
    505 **
    506 ** Function         btm_ble_multi_adv_enb_privacy
    507 **
    508 ** Description      This function enable/disable privacy setting in multi adv
    509 **
    510 ** Parameters       enable: enable or disable the adv instance.
    511 **
    512 ** Returns          none.
    513 **
    514 *******************************************************************************/
    515 void btm_ble_multi_adv_enb_privacy(BOOLEAN enable)
    516 {
    517     UINT8 i;
    518     tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.p_adv_inst[0];
    519 
    520     for (i = 0; i <  BTM_BleMaxMultiAdvInstanceCount() - 1; i ++, p_inst++)
    521     {
    522         p_inst->in_use = FALSE;
    523         if (enable)
    524             btm_ble_multi_adv_configure_rpa(p_inst);
    525         else
    526             alarm_cancel(p_inst->adv_raddr_timer);
    527     }
    528 }
    529 
    530 /*******************************************************************************
    531 **
    532 ** Function         BTM_BleEnableAdvInstance
    533 **
    534 ** Description      This function enable a Multi-ADV instance with the specified
    535 **                  adv parameters
    536 **
    537 ** Parameters       p_params: pointer to the adv parameter structure, set as default
    538 **                            adv parameter when the instance is enabled.
    539 **                  p_cback: callback function for the adv instance.
    540 **                  p_ref:  reference data attach to the adv instance to be enabled.
    541 **
    542 ** Returns          status
    543 **
    544 *******************************************************************************/
    545 tBTM_STATUS BTM_BleEnableAdvInstance (tBTM_BLE_ADV_PARAMS *p_params,
    546                                       tBTM_BLE_MULTI_ADV_CBACK *p_cback,void *p_ref)
    547 {
    548     UINT8 i;
    549     tBTM_STATUS rt = BTM_NO_RESOURCES;
    550     tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.p_adv_inst[0];
    551 
    552     BTM_TRACE_EVENT("BTM_BleEnableAdvInstance called");
    553 
    554     if (0 == btm_cb.cmn_ble_vsc_cb.adv_inst_max)
    555     {
    556         BTM_TRACE_ERROR("Controller does not support Multi ADV");
    557         return BTM_ERR_PROCESSING;
    558     }
    559 
    560     if (NULL == p_inst)
    561     {
    562         BTM_TRACE_ERROR("Invalid instance in BTM_BleEnableAdvInstance");
    563         return BTM_ERR_PROCESSING;
    564     }
    565 
    566     for (i = 0; i <  BTM_BleMaxMultiAdvInstanceCount() - 1; i ++, p_inst++)
    567     {
    568         if (FALSE == p_inst->in_use)
    569         {
    570             p_inst->in_use = TRUE;
    571             /* configure adv parameter */
    572             if (p_params)
    573                 rt = btm_ble_multi_adv_set_params(p_inst, p_params, 0);
    574             else
    575                 rt = BTM_CMD_STARTED;
    576 
    577             /* enable adv */
    578             BTM_TRACE_EVENT("btm_ble_enable_multi_adv being called with inst_id:%d",
    579                 p_inst->inst_id);
    580 
    581             if (BTM_CMD_STARTED == rt)
    582             {
    583                 if ((rt = btm_ble_enable_multi_adv (TRUE, p_inst->inst_id,
    584                           BTM_BLE_MULTI_ADV_ENB_EVT)) == BTM_CMD_STARTED)
    585                 {
    586                     p_inst->p_cback = p_cback;
    587                     p_inst->p_ref   = p_ref;
    588                 }
    589             }
    590 
    591             if (BTM_CMD_STARTED != rt)
    592             {
    593                 p_inst->in_use = FALSE;
    594                 BTM_TRACE_ERROR("BTM_BleEnableAdvInstance failed");
    595             }
    596             break;
    597         }
    598     }
    599     return rt;
    600 }
    601 
    602 /*******************************************************************************
    603 **
    604 ** Function         BTM_BleUpdateAdvInstParam
    605 **
    606 ** Description      This function update a Multi-ADV instance with the specified
    607 **                  adv parameters.
    608 **
    609 ** Parameters       inst_id: adv instance ID
    610 **                  p_params: pointer to the adv parameter structure.
    611 **
    612 ** Returns          status
    613 **
    614 *******************************************************************************/
    615 tBTM_STATUS BTM_BleUpdateAdvInstParam (UINT8 inst_id, tBTM_BLE_ADV_PARAMS *p_params)
    616 {
    617     tBTM_STATUS rt = BTM_ILLEGAL_VALUE;
    618     tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.p_adv_inst[inst_id - 1];
    619 
    620     BTM_TRACE_EVENT("BTM_BleUpdateAdvInstParam called with inst_id:%d", inst_id);
    621 
    622     if (0 == btm_cb.cmn_ble_vsc_cb.adv_inst_max)
    623     {
    624         BTM_TRACE_ERROR("Controller does not support Multi ADV");
    625         return BTM_ERR_PROCESSING;
    626     }
    627 
    628     if (inst_id <  BTM_BleMaxMultiAdvInstanceCount() &&
    629         inst_id != BTM_BLE_MULTI_ADV_DEFAULT_STD &&
    630         p_params != NULL)
    631     {
    632         if (FALSE == p_inst->in_use)
    633         {
    634             BTM_TRACE_DEBUG("adv instance %d is not active", inst_id);
    635             return BTM_WRONG_MODE;
    636         }
    637         else
    638             btm_ble_enable_multi_adv(FALSE, inst_id, 0);
    639 
    640         if (BTM_CMD_STARTED == btm_ble_multi_adv_set_params(p_inst, p_params, 0))
    641             rt = btm_ble_enable_multi_adv(TRUE, inst_id, BTM_BLE_MULTI_ADV_PARAM_EVT);
    642     }
    643     return rt;
    644 }
    645 
    646 /*******************************************************************************
    647 **
    648 ** Function         BTM_BleCfgAdvInstData
    649 **
    650 ** Description      This function configure a Multi-ADV instance with the specified
    651 **                  adv data or scan response data.
    652 **
    653 ** Parameters       inst_id: adv instance ID
    654 **                  is_scan_rsp: is this scan response. if no, set as adv data.
    655 **                  data_mask: adv data mask.
    656 **                  p_data: pointer to the adv data structure.
    657 **
    658 ** Returns          status
    659 **
    660 *******************************************************************************/
    661 tBTM_STATUS BTM_BleCfgAdvInstData (UINT8 inst_id, BOOLEAN is_scan_rsp,
    662                                     tBTM_BLE_AD_MASK data_mask,
    663                                     tBTM_BLE_ADV_DATA *p_data)
    664 {
    665     UINT8       param[BTM_BLE_MULTI_ADV_WRITE_DATA_LEN], *pp = param;
    666     UINT8       sub_code = (is_scan_rsp) ?
    667                            BTM_BLE_MULTI_ADV_WRITE_SCAN_RSP_DATA : BTM_BLE_MULTI_ADV_WRITE_ADV_DATA;
    668     UINT8       *p_len;
    669     tBTM_STATUS rt;
    670     UINT8 *pp_temp = (UINT8*)(param + BTM_BLE_MULTI_ADV_WRITE_DATA_LEN -1);
    671     tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
    672 
    673     BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
    674     if (0 == cmn_ble_vsc_cb.adv_inst_max)
    675     {
    676         BTM_TRACE_ERROR("Controller does not support Multi ADV");
    677         return BTM_ERR_PROCESSING;
    678     }
    679 
    680     btm_ble_update_dmt_flag_bits(&p_data->flag, btm_cb.btm_inq_vars.connectable_mode,
    681                                         btm_cb.btm_inq_vars.discoverable_mode);
    682 
    683     BTM_TRACE_EVENT("BTM_BleCfgAdvInstData called with inst_id:%d", inst_id);
    684     if (inst_id > BTM_BLE_MULTI_ADV_MAX || inst_id == BTM_BLE_MULTI_ADV_DEFAULT_STD)
    685         return BTM_ILLEGAL_VALUE;
    686 
    687     memset(param, 0, BTM_BLE_MULTI_ADV_WRITE_DATA_LEN);
    688 
    689     UINT8_TO_STREAM(pp, sub_code);
    690     p_len = pp ++;
    691     btm_ble_build_adv_data(&data_mask, &pp, p_data);
    692     *p_len = (UINT8)(pp - param - 2);
    693     UINT8_TO_STREAM(pp_temp, inst_id);
    694 
    695     if ((rt = BTM_VendorSpecificCommand (HCI_BLE_MULTI_ADV_OCF,
    696                                     (UINT8)BTM_BLE_MULTI_ADV_WRITE_DATA_LEN,
    697                                     param,
    698                                     btm_ble_multi_adv_vsc_cmpl_cback))
    699                                      == BTM_CMD_STARTED)
    700     {
    701         btm_ble_multi_adv_enq_op_q(sub_code, inst_id, BTM_BLE_MULTI_ADV_DATA_EVT);
    702     }
    703     return rt;
    704 }
    705 
    706 /*******************************************************************************
    707 **
    708 ** Function         BTM_BleDisableAdvInstance
    709 **
    710 ** Description      This function disables a Multi-ADV instance.
    711 **
    712 ** Parameters       inst_id: adv instance ID
    713 **
    714 ** Returns          status
    715 **
    716 *******************************************************************************/
    717 tBTM_STATUS BTM_BleDisableAdvInstance (UINT8 inst_id)
    718 {
    719      tBTM_STATUS rt = BTM_ILLEGAL_VALUE;
    720      tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
    721 
    722      BTM_TRACE_EVENT("BTM_BleDisableAdvInstance with inst_id:%d", inst_id);
    723 
    724      BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
    725 
    726      if (0 == cmn_ble_vsc_cb.adv_inst_max)
    727      {
    728          BTM_TRACE_ERROR("Controller does not support Multi ADV");
    729          return BTM_ERR_PROCESSING;
    730      }
    731 
    732      if (inst_id < BTM_BleMaxMultiAdvInstanceCount() &&
    733          inst_id != BTM_BLE_MULTI_ADV_DEFAULT_STD)
    734      {
    735          if ((rt = btm_ble_enable_multi_adv(FALSE, inst_id, BTM_BLE_MULTI_ADV_DISABLE_EVT))
    736             == BTM_CMD_STARTED)
    737          {
    738             btm_ble_multi_adv_configure_rpa(&btm_multi_adv_cb.p_adv_inst[inst_id - 1]);
    739             alarm_cancel(btm_multi_adv_cb.p_adv_inst[inst_id - 1].adv_raddr_timer);
    740             btm_multi_adv_cb.p_adv_inst[inst_id - 1].in_use = FALSE;
    741          }
    742      }
    743     return rt;
    744 }
    745 /*******************************************************************************
    746 **
    747 ** Function         btm_ble_multi_adv_vse_cback
    748 **
    749 ** Description      VSE callback for multi adv events.
    750 **
    751 ** Returns
    752 **
    753 *******************************************************************************/
    754 void btm_ble_multi_adv_vse_cback(UINT8 len, UINT8 *p)
    755 {
    756     UINT8   sub_event;
    757     UINT8   adv_inst, idx;
    758     UINT16  conn_handle;
    759 
    760     /* Check if this is a BLE RSSI vendor specific event */
    761     STREAM_TO_UINT8(sub_event, p);
    762     len--;
    763 
    764     BTM_TRACE_EVENT("btm_ble_multi_adv_vse_cback called with event:%d", sub_event);
    765     if ((sub_event == HCI_VSE_SUBCODE_BLE_MULTI_ADV_ST_CHG) && (len >= 4))
    766     {
    767         STREAM_TO_UINT8(adv_inst, p);
    768         ++p;
    769         STREAM_TO_UINT16(conn_handle, p);
    770 
    771         if ((idx = btm_handle_to_acl_index(conn_handle)) != MAX_L2CAP_LINKS)
    772         {
    773 #if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
    774             if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE &&
    775                 adv_inst <= BTM_BLE_MULTI_ADV_MAX && adv_inst !=  BTM_BLE_MULTI_ADV_DEFAULT_STD)
    776             {
    777                 memcpy(btm_cb.acl_db[idx].conn_addr, btm_multi_adv_cb.p_adv_inst[adv_inst - 1].rpa,
    778                                 BD_ADDR_LEN);
    779             }
    780 #endif
    781         }
    782 
    783         if (adv_inst < BTM_BleMaxMultiAdvInstanceCount() &&
    784             adv_inst !=  BTM_BLE_MULTI_ADV_DEFAULT_STD)
    785         {
    786             BTM_TRACE_EVENT("btm_ble_multi_adv_reenable called");
    787             btm_ble_multi_adv_reenable(adv_inst);
    788         }
    789         /* re-enable connectibility */
    790         else if (adv_inst == BTM_BLE_MULTI_ADV_DEFAULT_STD)
    791         {
    792             if (btm_cb.ble_ctr_cb.inq_var.connectable_mode == BTM_BLE_CONNECTABLE)
    793             {
    794                 btm_ble_set_connectability ( btm_cb.ble_ctr_cb.inq_var.connectable_mode );
    795             }
    796         }
    797 
    798     }
    799 
    800 }
    801 /*******************************************************************************
    802 **
    803 ** Function         btm_ble_multi_adv_init
    804 **
    805 ** Description      This function initialize the multi adv control block.
    806 **
    807 ** Parameters       None
    808 **
    809 ** Returns          void
    810 **
    811 *******************************************************************************/
    812 void btm_ble_multi_adv_init()
    813 {
    814     UINT8 i = 0;
    815     memset(&btm_multi_adv_cb, 0, sizeof(tBTM_BLE_MULTI_ADV_CB));
    816     memset (&btm_multi_adv_idx_q,0, sizeof (tBTM_BLE_MULTI_ADV_INST_IDX_Q));
    817     btm_multi_adv_idx_q.front = -1;
    818     btm_multi_adv_idx_q.rear = -1;
    819 
    820     if (btm_cb.cmn_ble_vsc_cb.adv_inst_max > 0) {
    821         btm_multi_adv_cb.p_adv_inst = osi_calloc(sizeof(tBTM_BLE_MULTI_ADV_INST) *
    822                                                  (btm_cb.cmn_ble_vsc_cb.adv_inst_max));
    823 
    824         btm_multi_adv_cb.op_q.p_sub_code = osi_calloc(sizeof(UINT8) *
    825                                                       (btm_cb.cmn_ble_vsc_cb.adv_inst_max));
    826 
    827         btm_multi_adv_cb.op_q.p_inst_id = osi_calloc(sizeof(UINT8) *
    828                                                      (btm_cb.cmn_ble_vsc_cb.adv_inst_max));
    829     }
    830 
    831     /* Initialize adv instance indices and IDs. */
    832     for (i = 0; i < btm_cb.cmn_ble_vsc_cb.adv_inst_max; i++) {
    833         btm_multi_adv_cb.p_adv_inst[i].index = i;
    834         btm_multi_adv_cb.p_adv_inst[i].inst_id = i + 1;
    835         btm_multi_adv_cb.p_adv_inst[i].adv_raddr_timer =
    836             alarm_new("btm_ble.adv_raddr_timer");
    837     }
    838 
    839     BTM_RegisterForVSEvents(btm_ble_multi_adv_vse_cback, TRUE);
    840 }
    841 
    842 /*******************************************************************************
    843 **
    844 ** Function         btm_ble_multi_adv_cleanup
    845 **
    846 ** Description      This function cleans up multi adv control block.
    847 **
    848 ** Parameters
    849 ** Returns          void
    850 **
    851 *******************************************************************************/
    852 void btm_ble_multi_adv_cleanup(void)
    853 {
    854     if (btm_multi_adv_cb.p_adv_inst) {
    855         for (size_t i = 0; i < btm_cb.cmn_ble_vsc_cb.adv_inst_max; i++) {
    856             alarm_free(btm_multi_adv_cb.p_adv_inst[i].adv_raddr_timer);
    857         }
    858         osi_free_and_reset((void **)&btm_multi_adv_cb.p_adv_inst);
    859     }
    860 
    861     osi_free_and_reset((void **)&btm_multi_adv_cb.op_q.p_sub_code);
    862     osi_free_and_reset((void **)&btm_multi_adv_cb.op_q.p_inst_id);
    863 }
    864 
    865 /*******************************************************************************
    866 **
    867 ** Function         btm_ble_multi_adv_get_ref
    868 **
    869 ** Description      This function obtains the reference pointer for the instance ID provided
    870 **
    871 ** Parameters       inst_id - Instance ID
    872 **
    873 ** Returns          void*
    874 **
    875 *******************************************************************************/
    876 void* btm_ble_multi_adv_get_ref(UINT8 inst_id)
    877 {
    878     tBTM_BLE_MULTI_ADV_INST *p_inst = NULL;
    879 
    880     if (inst_id < BTM_BleMaxMultiAdvInstanceCount())
    881     {
    882         p_inst = &btm_multi_adv_cb.p_adv_inst[inst_id - 1];
    883         if (NULL != p_inst)
    884             return p_inst->p_ref;
    885     }
    886 
    887     return NULL;
    888 }
    889 #endif
    890 
    891