• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
37 tBTM_BLE_MULTI_ADV_CB  btm_multi_adv_cb;
38 tBTM_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 *******************************************************************************/
btm_ble_multi_adv_enq_op_q(UINT8 opcode,UINT8 inst_id,UINT8 cb_evt)53 void 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 *******************************************************************************/
btm_ble_multi_adv_deq_op_q(UINT8 * p_opcode,UINT8 * p_inst_id,UINT8 * p_cb_evt)74 void 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 *******************************************************************************/
btm_ble_multi_adv_vsc_cmpl_cback(tBTM_VSC_CMPL * p_params)96 void 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 *******************************************************************************/
btm_ble_enable_multi_adv(BOOLEAN enable,UINT8 inst_id,UINT8 cb_evt)182 tBTM_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 *******************************************************************************/
218 int btm_ble_tx_power[BTM_BLE_ADV_TX_POWER_MAX + 1] = BTM_BLE_ADV_TX_POWER;
btm_ble_map_adv_tx_power(int tx_power_index)219 char 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 *******************************************************************************/
btm_ble_multi_adv_set_params(tBTM_BLE_MULTI_ADV_INST * p_inst,tBTM_BLE_ADV_PARAMS * p_params,UINT8 cb_evt)236 tBTM_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 *******************************************************************************/
btm_ble_multi_adv_write_rpa(tBTM_BLE_MULTI_ADV_INST * p_inst,BD_ADDR random_addr)323 tBTM_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 *******************************************************************************/
btm_ble_multi_adv_gen_rpa_cmpl(tBTM_RAND_ENC * p)362 void 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 *******************************************************************************/
btm_ble_multi_adv_configure_rpa(tBTM_BLE_MULTI_ADV_INST * p_inst)434 void 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 *******************************************************************************/
btm_ble_multi_adv_reenable(UINT8 inst_id)468 void 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 *******************************************************************************/
btm_ble_multi_adv_enb_privacy(BOOLEAN enable)496 void 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 *******************************************************************************/
BTM_BleEnableAdvInstance(tBTM_BLE_ADV_PARAMS * p_params,tBTM_BLE_MULTI_ADV_CBACK * p_cback,void * p_ref)525 tBTM_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 *******************************************************************************/
BTM_BleUpdateAdvInstParam(UINT8 inst_id,tBTM_BLE_ADV_PARAMS * p_params)596 tBTM_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 *******************************************************************************/
BTM_BleCfgAdvInstData(UINT8 inst_id,BOOLEAN is_scan_rsp,tBTM_BLE_AD_MASK data_mask,tBTM_BLE_ADV_DATA * p_data)642 tBTM_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 *******************************************************************************/
BTM_BleDisableAdvInstance(UINT8 inst_id)696 tBTM_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 *******************************************************************************/
btm_ble_multi_adv_vse_cback(UINT8 len,UINT8 * p)733 void 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 *******************************************************************************/
btm_ble_multi_adv_init()788 void 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 *******************************************************************************/
btm_ble_multi_adv_cleanup(void)830 void 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 *******************************************************************************/
btm_ble_multi_adv_get_ref(UINT8 inst_id)854 void* 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