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