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