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