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