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