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