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 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*******************************************************************************/
67void 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*******************************************************************************/
88void 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*******************************************************************************/
110void 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*******************************************************************************/
198tBTM_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*******************************************************************************/
234int btm_ble_tx_power[BTM_BLE_ADV_TX_POWER_MAX + 1] = BTM_BLE_ADV_TX_POWER;
235char 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*******************************************************************************/
252tBTM_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*******************************************************************************/
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        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*******************************************************************************/
380void 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*******************************************************************************/
452void 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*******************************************************************************/
486void 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*******************************************************************************/
514void 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*******************************************************************************/
544tBTM_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*******************************************************************************/
614tBTM_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*******************************************************************************/
660tBTM_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*******************************************************************************/
716tBTM_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*******************************************************************************/
753void 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*******************************************************************************/
811void 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*******************************************************************************/
856void 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*******************************************************************************/
880void* 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