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