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************************************************************************************/
48tBTM_BLE_MULTI_ADV_CB  btm_multi_adv_cb;
49tBTM_BLE_MULTI_ADV_INST_IDX_Q btm_multi_adv_idx_q;
50
51/************************************************************************************
52**  Externs
53************************************************************************************/
54extern fixed_queue_t *btu_general_alarm_queue;
55extern 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*******************************************************************************/
68void 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*******************************************************************************/
89void 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*******************************************************************************/
111void 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*******************************************************************************/
199tBTM_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*******************************************************************************/
235int btm_ble_tx_power[BTM_BLE_ADV_TX_POWER_MAX + 1] = BTM_BLE_ADV_TX_POWER;
236char 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*******************************************************************************/
253tBTM_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*******************************************************************************/
339tBTM_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*******************************************************************************/
381void 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*******************************************************************************/
453void 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*******************************************************************************/
487void 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*******************************************************************************/
515void 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*******************************************************************************/
545tBTM_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*******************************************************************************/
615tBTM_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*******************************************************************************/
661tBTM_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*******************************************************************************/
717tBTM_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*******************************************************************************/
754void 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*******************************************************************************/
812void 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*******************************************************************************/
852void 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*******************************************************************************/
876void* 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