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