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