1 /******************************************************************************
3 * Copyright (C) 2014 Broadcom Corporation
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:
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 ******************************************************************************/
21 #include "common/bt_target.h"
22 #include "device/controller.h"
24 #if (BLE_INCLUDED == TRUE)
25 #include "stack/bt_types.h"
26 #include "stack/hcimsgs.h"
27 #include "stack/btu.h"
29 //#include "bt_utils.h"
30 #include "stack/hcidefs.h"
31 #include "stack/btm_ble_api.h"
33 /************************************************************************************
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
42 #define BTM_BLE_MULTI_ADV_CB_EVT_MASK 0xF0
43 #define BTM_BLE_MULTI_ADV_SUBCODE_MASK 0x0F
45 /************************************************************************************
47 ************************************************************************************/
48 tBTM_BLE_MULTI_ADV_CB btm_multi_adv_cb;
49 tBTM_BLE_MULTI_ADV_INST_IDX_Q btm_multi_adv_idx_q;
51 /************************************************************************************
53 ************************************************************************************/
54 extern void btm_ble_update_dmt_flag_bits(UINT8 *flag_value,
55 const UINT16 connect_mode, const UINT16 disc_mode);
57 /*******************************************************************************
59 ** Function btm_ble_multi_adv_enq_op_q
61 ** Description enqueue a multi adv operation in q to check command complete
66 *******************************************************************************/
67 void btm_ble_multi_adv_enq_op_q(UINT8 opcode, UINT8 inst_id, UINT8 cb_evt)
69 tBTM_BLE_MULTI_ADV_OPQ *p_op_q = &btm_multi_adv_cb.op_q;
71 p_op_q->p_inst_id[p_op_q->next_idx] = inst_id;
73 p_op_q->p_sub_code[p_op_q->next_idx] = (opcode | (cb_evt << 4));
75 p_op_q->next_idx = (p_op_q->next_idx + 1) % BTM_BleMaxMultiAdvInstanceCount();
78 /*******************************************************************************
80 ** Function btm_ble_multi_adv_deq_op_q
82 ** Description dequeue a multi adv operation from q when command complete
87 *******************************************************************************/
88 void btm_ble_multi_adv_deq_op_q(UINT8 *p_opcode, UINT8 *p_inst_id, UINT8 *p_cb_evt)
90 tBTM_BLE_MULTI_ADV_OPQ *p_op_q = &btm_multi_adv_cb.op_q;
92 *p_inst_id = p_op_q->p_inst_id[p_op_q->pending_idx] & 0x7F;
93 *p_cb_evt = (p_op_q->p_sub_code[p_op_q->pending_idx] >> 4);
94 *p_opcode = (p_op_q->p_sub_code[p_op_q->pending_idx] & BTM_BLE_MULTI_ADV_SUBCODE_MASK);
96 p_op_q->pending_idx = (p_op_q->pending_idx + 1) % BTM_BleMaxMultiAdvInstanceCount();
99 /*******************************************************************************
101 ** Function btm_ble_multi_adv_vsc_cmpl_cback
103 ** Description Multi adv VSC complete callback
109 *******************************************************************************/
110 void btm_ble_multi_adv_vsc_cmpl_cback (tBTM_VSC_CMPL *p_params)
112 UINT8 status, subcode;
113 UINT8 *p = p_params->p_param_buf, inst_id;
114 UINT16 len = p_params->param_len;
115 tBTM_BLE_MULTI_ADV_INST *p_inst ;
116 UINT8 cb_evt = 0, opcode;
119 BTM_TRACE_ERROR("wrong length for btm_ble_multi_adv_vsc_cmpl_cback");
123 STREAM_TO_UINT8(status, p);
124 STREAM_TO_UINT8(subcode, p);
126 btm_ble_multi_adv_deq_op_q(&opcode, &inst_id, &cb_evt);
128 BTM_TRACE_DEBUG("op_code = %02x inst_id = %d cb_evt = %02x", opcode, inst_id, cb_evt);
130 if (opcode != subcode || inst_id == 0) {
131 BTM_TRACE_ERROR("get unexpected VSC cmpl, expect: %d get: %d", subcode, opcode);
135 p_inst = &btm_multi_adv_cb.p_adv_inst[inst_id - 1];
138 case BTM_BLE_MULTI_ADV_ENB: {
139 BTM_TRACE_DEBUG("BTM_BLE_MULTI_ADV_ENB status = %d", status);
141 /* Mark as not in use here, if instance cannot be enabled */
142 if (HCI_SUCCESS != status && BTM_BLE_MULTI_ADV_ENB_EVT == cb_evt) {
143 btm_multi_adv_cb.p_adv_inst[inst_id - 1].in_use = FALSE;
148 case BTM_BLE_MULTI_ADV_SET_PARAM: {
149 BTM_TRACE_DEBUG("BTM_BLE_MULTI_ADV_SET_PARAM status = %d", status);
153 case BTM_BLE_MULTI_ADV_WRITE_ADV_DATA: {
154 BTM_TRACE_DEBUG("BTM_BLE_MULTI_ADV_WRITE_ADV_DATA status = %d", status);
158 case BTM_BLE_MULTI_ADV_WRITE_SCAN_RSP_DATA: {
159 BTM_TRACE_DEBUG("BTM_BLE_MULTI_ADV_WRITE_SCAN_RSP_DATA status = %d", status);
163 case BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR: {
164 BTM_TRACE_DEBUG("BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR status = %d", status);
172 if (cb_evt != 0 && p_inst->p_cback != NULL) {
173 (p_inst->p_cback)(cb_evt, inst_id, p_inst->p_ref, status);
178 /*******************************************************************************
180 ** Function btm_ble_enable_multi_adv
182 ** Description This function enable the customer specific feature in controller
184 ** Parameters enable: enable or disable
185 ** inst_id: adv instance ID, can not be 0
189 *******************************************************************************/
190 tBTM_STATUS btm_ble_enable_multi_adv (BOOLEAN enable, UINT8 inst_id, UINT8 cb_evt)
192 UINT8 param[BTM_BLE_MULTI_ADV_ENB_LEN], *pp;
193 UINT8 enb = enable ? 1 : 0;
197 memset(param, 0, BTM_BLE_MULTI_ADV_ENB_LEN);
199 UINT8_TO_STREAM (pp, BTM_BLE_MULTI_ADV_ENB);
200 UINT8_TO_STREAM (pp, enb);
201 UINT8_TO_STREAM (pp, inst_id);
203 BTM_TRACE_EVENT (" btm_ble_enable_multi_adv: enb %d, Inst ID %d", enb, inst_id);
205 if ((rt = BTM_VendorSpecificCommand (HCI_BLE_MULTI_ADV_OCF,
206 BTM_BLE_MULTI_ADV_ENB_LEN,
208 btm_ble_multi_adv_vsc_cmpl_cback))
209 == BTM_CMD_STARTED) {
210 btm_ble_multi_adv_enq_op_q(BTM_BLE_MULTI_ADV_ENB, inst_id, cb_evt);
214 /*******************************************************************************
216 ** Function btm_ble_map_adv_tx_power
218 ** Description return the actual power in dBm based on the mapping in config file
220 ** Parameters advertise parameters used for this instance.
222 ** Returns tx power in dBm
224 *******************************************************************************/
225 int btm_ble_tx_power[BTM_BLE_ADV_TX_POWER_MAX + 1] = BTM_BLE_ADV_TX_POWER;
226 char btm_ble_map_adv_tx_power(int tx_power_index)
228 if (0 <= tx_power_index && tx_power_index < BTM_BLE_ADV_TX_POWER_MAX) {
229 return (char)btm_ble_tx_power[tx_power_index];
233 /*******************************************************************************
235 ** Function btm_ble_multi_adv_set_params
237 ** Description This function enable the customer specific feature in controller
239 ** Parameters advertise parameters used for this instance.
243 *******************************************************************************/
244 tBTM_STATUS btm_ble_multi_adv_set_params (tBTM_BLE_MULTI_ADV_INST *p_inst,
245 tBTM_BLE_ADV_PARAMS *p_params,
248 UINT8 param[BTM_BLE_MULTI_ADV_SET_PARAM_LEN], *pp;
250 BD_ADDR dummy = {0, 0, 0, 0, 0, 0};
253 memset(param, 0, BTM_BLE_MULTI_ADV_SET_PARAM_LEN);
255 UINT8_TO_STREAM(pp, BTM_BLE_MULTI_ADV_SET_PARAM);
257 UINT16_TO_STREAM (pp, p_params->adv_int_min);
258 UINT16_TO_STREAM (pp, p_params->adv_int_max);
259 UINT8_TO_STREAM (pp, p_params->adv_type);
261 #if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
262 if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE) {
263 UINT8_TO_STREAM (pp, BLE_ADDR_RANDOM);
264 BDADDR_TO_STREAM (pp, p_inst->rpa);
268 UINT8_TO_STREAM (pp, BLE_ADDR_PUBLIC);
269 BDADDR_TO_STREAM (pp, controller_get_interface()->get_address()->address);
272 BTM_TRACE_EVENT (" btm_ble_multi_adv_set_params,Min %d, Max %d,adv_type %d",
273 p_params->adv_int_min, p_params->adv_int_max, p_params->adv_type);
275 UINT8_TO_STREAM (pp, 0);
276 BDADDR_TO_STREAM (pp, dummy);
278 if (p_params->channel_map == 0 || p_params->channel_map > BTM_BLE_DEFAULT_ADV_CHNL_MAP) {
279 p_params->channel_map = BTM_BLE_DEFAULT_ADV_CHNL_MAP;
281 UINT8_TO_STREAM (pp, p_params->channel_map);
283 if (p_params->adv_filter_policy >= AP_SCAN_CONN_POLICY_MAX) {
284 p_params->adv_filter_policy = AP_SCAN_CONN_ALL;
286 UINT8_TO_STREAM (pp, p_params->adv_filter_policy);
288 UINT8_TO_STREAM (pp, p_inst->inst_id);
290 if (p_params->tx_power > BTM_BLE_ADV_TX_POWER_MAX) {
291 p_params->tx_power = BTM_BLE_ADV_TX_POWER_MAX;
293 UINT8_TO_STREAM (pp, btm_ble_map_adv_tx_power(p_params->tx_power));
295 BTM_TRACE_EVENT("set_params:Chnl Map %d,adv_fltr policy %d,ID:%d, TX Power%d",
296 p_params->channel_map, p_params->adv_filter_policy, p_inst->inst_id, p_params->tx_power);
298 if ((rt = BTM_VendorSpecificCommand (HCI_BLE_MULTI_ADV_OCF,
299 BTM_BLE_MULTI_ADV_SET_PARAM_LEN,
301 btm_ble_multi_adv_vsc_cmpl_cback))
302 == BTM_CMD_STARTED) {
303 p_inst->adv_evt = p_params->adv_type;
305 #if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
306 if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE) {
308 p_inst->raddr_timer_ent.param = (TIMER_PARAM_TYPE) p_inst;
309 btu_start_timer_oneshot(&p_inst->raddr_timer_ent, BTU_TTYPE_BLE_RANDOM_ADDR,
310 BTM_BLE_PRIVATE_ADDR_INT);
313 btm_ble_multi_adv_enq_op_q(BTM_BLE_MULTI_ADV_SET_PARAM, p_inst->inst_id, cb_evt);
318 /*******************************************************************************
320 ** Function btm_ble_multi_adv_write_rpa
322 ** Description This function write the random address for the adv instance into
329 *******************************************************************************/
330 tBTM_STATUS btm_ble_multi_adv_write_rpa (tBTM_BLE_MULTI_ADV_INST *p_inst, BD_ADDR random_addr)
332 UINT8 param[BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN], *pp = param;
335 BTM_TRACE_EVENT ("%s-BD_ADDR:%02x-%02x-%02x-%02x-%02x-%02x,inst_id:%d",
336 __FUNCTION__, random_addr[5], random_addr[4], random_addr[3], random_addr[2],
337 random_addr[1], random_addr[0], p_inst->inst_id);
339 memset(param, 0, BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN);
341 UINT8_TO_STREAM (pp, BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR);
342 BDADDR_TO_STREAM(pp, random_addr);
343 UINT8_TO_STREAM(pp, p_inst->inst_id);
345 if ((rt = BTM_VendorSpecificCommand (HCI_BLE_MULTI_ADV_OCF,
346 BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN,
348 btm_ble_multi_adv_vsc_cmpl_cback)) == BTM_CMD_STARTED) {
349 /* start a periodical timer to refresh random addr */
350 btu_stop_timer_oneshot(&p_inst->raddr_timer_ent);
351 p_inst->raddr_timer_ent.param = (TIMER_PARAM_TYPE) p_inst;
352 btu_start_timer_oneshot(&p_inst->raddr_timer_ent, BTU_TTYPE_BLE_RANDOM_ADDR,
353 BTM_BLE_PRIVATE_ADDR_INT);
355 btm_ble_multi_adv_enq_op_q(BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR, p_inst->inst_id, 0);
360 /*******************************************************************************
362 ** Function btm_ble_multi_adv_gen_rpa_cmpl
364 ** Description RPA generation completion callback for each adv instance. Will
365 ** continue write the new RPA into controller.
369 *******************************************************************************/
370 void btm_ble_multi_adv_gen_rpa_cmpl(tBTM_RAND_ENC *p)
372 #if (SMP_INCLUDED == TRUE)
375 tBTM_BLE_MULTI_ADV_INST *p_inst = NULL;
377 /* Retrieve the index of adv instance from stored Q */
378 if (btm_multi_adv_idx_q.front == -1) {
379 BTM_TRACE_ERROR(" %s can't locate advertise instance", __FUNCTION__);
382 index = btm_multi_adv_idx_q.inst_index_queue[btm_multi_adv_idx_q.front];
383 if (btm_multi_adv_idx_q.front == btm_multi_adv_idx_q.rear) {
384 btm_multi_adv_idx_q.front = -1;
385 btm_multi_adv_idx_q.rear = -1;
387 btm_multi_adv_idx_q.front = (btm_multi_adv_idx_q.front + 1) % BTM_BLE_MULTI_ADV_MAX;
391 p_inst = &(btm_multi_adv_cb.p_adv_inst[index]);
393 BTM_TRACE_EVENT ("btm_ble_multi_adv_gen_rpa_cmpl inst_id = %d", p_inst->inst_id);
395 p->param_buf[2] &= (~BLE_RESOLVE_ADDR_MASK);
396 p->param_buf[2] |= BLE_RESOLVE_ADDR_MSB;
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];
402 if (!SMP_Encrypt(btm_cb.devcb.id_keys.irk, BT_OCTET16_LEN, p->param_buf, 3, &output)) {
403 BTM_TRACE_DEBUG("generate random address failed");
405 /* set hash to be LSB of rpAddress */
406 p_inst->rpa[5] = output.param_buf[0];
407 p_inst->rpa[4] = output.param_buf[1];
408 p_inst->rpa[3] = output.param_buf[2];
411 if (p_inst->inst_id != BTM_BLE_MULTI_ADV_DEFAULT_STD &&
412 p_inst->inst_id < BTM_BleMaxMultiAdvInstanceCount()) {
413 /* set it to controller */
414 btm_ble_multi_adv_write_rpa(p_inst, p_inst->rpa);
420 /*******************************************************************************
422 ** Function btm_ble_multi_adv_configure_rpa
424 ** Description This function set the random address for the adv instance
426 ** Parameters advertise parameters used for this instance.
430 *******************************************************************************/
431 void btm_ble_multi_adv_configure_rpa (tBTM_BLE_MULTI_ADV_INST *p_inst)
433 if (btm_multi_adv_idx_q.front == (btm_multi_adv_idx_q.rear + 1) % BTM_BLE_MULTI_ADV_MAX) {
434 BTM_TRACE_ERROR("outstanding rand generation exceeded max allowed ");
437 if (btm_multi_adv_idx_q.front == -1) {
438 btm_multi_adv_idx_q.front = 0;
439 btm_multi_adv_idx_q.rear = 0;
441 btm_multi_adv_idx_q.rear = (btm_multi_adv_idx_q.rear + 1) % BTM_BLE_MULTI_ADV_MAX;
443 btm_multi_adv_idx_q.inst_index_queue[btm_multi_adv_idx_q.rear] = p_inst->index;
445 btm_gen_resolvable_private_addr((void *)btm_ble_multi_adv_gen_rpa_cmpl);
448 /*******************************************************************************
450 ** Function btm_ble_multi_adv_reenable
452 ** Description This function re-enable adv instance upon a connection establishment.
454 ** Parameters advertise parameters used for this instance.
458 *******************************************************************************/
459 void btm_ble_multi_adv_reenable(UINT8 inst_id)
461 tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.p_adv_inst[inst_id - 1];
463 if (TRUE == p_inst->in_use) {
464 if (p_inst->adv_evt != BTM_BLE_CONNECT_DIR_EVT) {
465 btm_ble_enable_multi_adv (TRUE, p_inst->inst_id, 0);
467 /* mark directed adv as disabled if adv has been stopped */
469 (p_inst->p_cback)(BTM_BLE_MULTI_ADV_DISABLE_EVT, p_inst->inst_id, p_inst->p_ref, 0);
470 p_inst->in_use = FALSE;
475 /*******************************************************************************
477 ** Function btm_ble_multi_adv_enb_privacy
479 ** Description This function enable/disable privacy setting in multi adv
481 ** Parameters enable: enable or disable the adv instance.
485 *******************************************************************************/
486 void btm_ble_multi_adv_enb_privacy(BOOLEAN enable)
489 tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.p_adv_inst[0];
491 for (i = 0; i < BTM_BleMaxMultiAdvInstanceCount() - 1; i ++, p_inst++) {
492 p_inst->in_use = FALSE;
494 btm_ble_multi_adv_configure_rpa (p_inst);
496 btu_stop_timer_oneshot(&p_inst->raddr_timer_ent);
501 /*******************************************************************************
503 ** Function BTM_BleEnableAdvInstance
505 ** Description This function enable a Multi-ADV instance with the specified
508 ** Parameters p_params: pointer to the adv parameter structure, set as default
509 ** adv parameter when the instance is enabled.
510 ** p_cback: callback function for the adv instance.
511 ** p_ref: reference data attach to the adv instance to be enabled.
515 *******************************************************************************/
516 tBTM_STATUS BTM_BleEnableAdvInstance (tBTM_BLE_ADV_PARAMS *p_params,
517 tBTM_BLE_MULTI_ADV_CBACK *p_cback, void *p_ref)
520 tBTM_STATUS rt = BTM_NO_RESOURCES;
521 tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.p_adv_inst[0];
523 BTM_TRACE_EVENT("BTM_BleEnableAdvInstance called");
525 if (0 == btm_cb.cmn_ble_vsc_cb.adv_inst_max) {
526 BTM_TRACE_ERROR("Controller does not support Multi ADV");
527 return BTM_ERR_PROCESSING;
530 if (NULL == p_inst) {
531 BTM_TRACE_ERROR("Invalid instance in BTM_BleEnableAdvInstance");
532 return BTM_ERR_PROCESSING;
535 for (i = 0; i < BTM_BleMaxMultiAdvInstanceCount() - 1; i ++, p_inst++) {
536 if (FALSE == p_inst->in_use) {
537 p_inst->in_use = TRUE;
538 /* configure adv parameter */
540 rt = btm_ble_multi_adv_set_params(p_inst, p_params, 0);
542 rt = BTM_CMD_STARTED;
546 BTM_TRACE_EVENT("btm_ble_enable_multi_adv being called with inst_id:%d",
549 if (BTM_CMD_STARTED == rt) {
550 if ((rt = btm_ble_enable_multi_adv (TRUE, p_inst->inst_id,
551 BTM_BLE_MULTI_ADV_ENB_EVT)) == BTM_CMD_STARTED) {
552 p_inst->p_cback = p_cback;
553 p_inst->p_ref = p_ref;
557 if (BTM_CMD_STARTED != rt) {
558 p_inst->in_use = FALSE;
559 BTM_TRACE_ERROR("BTM_BleEnableAdvInstance failed");
567 /*******************************************************************************
569 ** Function BTM_BleUpdateAdvInstParam
571 ** Description This function update a Multi-ADV instance with the specified
574 ** Parameters inst_id: adv instance ID
575 ** p_params: pointer to the adv parameter structure.
579 *******************************************************************************/
580 tBTM_STATUS BTM_BleUpdateAdvInstParam (UINT8 inst_id, tBTM_BLE_ADV_PARAMS *p_params)
582 tBTM_STATUS rt = BTM_ILLEGAL_VALUE;
583 tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.p_adv_inst[inst_id - 1];
585 BTM_TRACE_EVENT("BTM_BleUpdateAdvInstParam called with inst_id:%d", inst_id);
587 if (0 == btm_cb.cmn_ble_vsc_cb.adv_inst_max) {
588 BTM_TRACE_ERROR("Controller does not support Multi ADV");
589 return BTM_ERR_PROCESSING;
592 if (inst_id < BTM_BleMaxMultiAdvInstanceCount() &&
593 inst_id != BTM_BLE_MULTI_ADV_DEFAULT_STD &&
595 if (FALSE == p_inst->in_use) {
596 BTM_TRACE_DEBUG("adv instance %d is not active", inst_id);
597 return BTM_WRONG_MODE;
599 btm_ble_enable_multi_adv(FALSE, inst_id, 0);
602 if (BTM_CMD_STARTED == btm_ble_multi_adv_set_params(p_inst, p_params, 0)) {
603 rt = btm_ble_enable_multi_adv(TRUE, inst_id, BTM_BLE_MULTI_ADV_PARAM_EVT);
609 /*******************************************************************************
611 ** Function BTM_BleCfgAdvInstData
613 ** Description This function configure a Multi-ADV instance with the specified
614 ** adv data or scan response data.
616 ** Parameters inst_id: adv instance ID
617 ** is_scan_rsp: is this scan response. if no, set as adv data.
618 ** data_mask: adv data mask.
619 ** p_data: pointer to the adv data structure.
623 *******************************************************************************/
624 tBTM_STATUS BTM_BleCfgAdvInstData (UINT8 inst_id, BOOLEAN is_scan_rsp,
625 tBTM_BLE_AD_MASK data_mask,
626 tBTM_BLE_ADV_DATA *p_data)
628 UINT8 param[BTM_BLE_MULTI_ADV_WRITE_DATA_LEN], *pp = param;
629 UINT8 sub_code = (is_scan_rsp) ?
630 BTM_BLE_MULTI_ADV_WRITE_SCAN_RSP_DATA : BTM_BLE_MULTI_ADV_WRITE_ADV_DATA;
633 UINT8 *pp_temp = (UINT8 *)(param + BTM_BLE_MULTI_ADV_WRITE_DATA_LEN - 1);
634 tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
636 BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
637 if (0 == cmn_ble_vsc_cb.adv_inst_max) {
638 BTM_TRACE_ERROR("Controller does not support Multi ADV");
639 return BTM_ERR_PROCESSING;
642 btm_ble_update_dmt_flag_bits(&p_data->flag, btm_cb.btm_inq_vars.connectable_mode,
643 btm_cb.btm_inq_vars.discoverable_mode);
645 BTM_TRACE_EVENT("BTM_BleCfgAdvInstData called with inst_id:%d", inst_id);
646 if (inst_id > BTM_BLE_MULTI_ADV_MAX || inst_id == BTM_BLE_MULTI_ADV_DEFAULT_STD) {
647 return BTM_ILLEGAL_VALUE;
650 memset(param, 0, BTM_BLE_MULTI_ADV_WRITE_DATA_LEN);
652 UINT8_TO_STREAM(pp, sub_code);
654 btm_ble_build_adv_data(&data_mask, &pp, p_data);
655 *p_len = (UINT8)(pp - param - 2);
656 UINT8_TO_STREAM(pp_temp, inst_id);
658 if ((rt = BTM_VendorSpecificCommand (HCI_BLE_MULTI_ADV_OCF,
659 (UINT8)BTM_BLE_MULTI_ADV_WRITE_DATA_LEN,
661 btm_ble_multi_adv_vsc_cmpl_cback))
662 == BTM_CMD_STARTED) {
663 btm_ble_multi_adv_enq_op_q(sub_code, inst_id, BTM_BLE_MULTI_ADV_DATA_EVT);
668 /*******************************************************************************
670 ** Function BTM_BleDisableAdvInstance
672 ** Description This function disables a Multi-ADV instance.
674 ** Parameters inst_id: adv instance ID
678 *******************************************************************************/
679 tBTM_STATUS BTM_BleDisableAdvInstance (UINT8 inst_id)
681 tBTM_STATUS rt = BTM_ILLEGAL_VALUE;
682 tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
684 BTM_TRACE_EVENT("BTM_BleDisableAdvInstance with inst_id:%d", inst_id);
686 BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
688 if (0 == cmn_ble_vsc_cb.adv_inst_max) {
689 BTM_TRACE_ERROR("Controller does not support Multi ADV");
690 return BTM_ERR_PROCESSING;
693 if (inst_id < BTM_BleMaxMultiAdvInstanceCount() &&
694 inst_id != BTM_BLE_MULTI_ADV_DEFAULT_STD) {
695 if ((rt = btm_ble_enable_multi_adv(FALSE, inst_id, BTM_BLE_MULTI_ADV_DISABLE_EVT))
696 == BTM_CMD_STARTED) {
697 btm_ble_multi_adv_configure_rpa(&btm_multi_adv_cb.p_adv_inst[inst_id - 1]);
698 btu_stop_timer_oneshot(&btm_multi_adv_cb.p_adv_inst[inst_id - 1].raddr_timer_ent);
699 btm_multi_adv_cb.p_adv_inst[inst_id - 1].in_use = FALSE;
704 /*******************************************************************************
706 ** Function btm_ble_multi_adv_vse_cback
708 ** Description VSE callback for multi adv events.
712 *******************************************************************************/
713 void btm_ble_multi_adv_vse_cback(UINT8 len, UINT8 *p)
719 /* Check if this is a BLE RSSI vendor specific event */
720 STREAM_TO_UINT8(sub_event, p);
723 BTM_TRACE_EVENT("btm_ble_multi_adv_vse_cback called with event:%d", sub_event);
724 if ((sub_event == HCI_VSE_SUBCODE_BLE_MULTI_ADV_ST_CHG) && (len >= 4)) {
725 STREAM_TO_UINT8(adv_inst, p);
727 STREAM_TO_UINT16(conn_handle, p);
729 if ((idx = btm_handle_to_acl_index(conn_handle)) != MAX_L2CAP_LINKS) {
730 #if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
731 if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE &&
732 adv_inst <= BTM_BLE_MULTI_ADV_MAX && adv_inst != BTM_BLE_MULTI_ADV_DEFAULT_STD) {
733 memcpy(btm_cb.acl_db[idx].conn_addr, btm_multi_adv_cb.p_adv_inst[adv_inst - 1].rpa,
739 if (adv_inst < BTM_BleMaxMultiAdvInstanceCount() &&
740 adv_inst != BTM_BLE_MULTI_ADV_DEFAULT_STD) {
741 BTM_TRACE_EVENT("btm_ble_multi_adv_reenable called");
742 btm_ble_multi_adv_reenable(adv_inst);
744 /* re-enable connectibility */
745 else if (adv_inst == BTM_BLE_MULTI_ADV_DEFAULT_STD) {
746 if (btm_cb.ble_ctr_cb.inq_var.connectable_mode == BTM_BLE_CONNECTABLE) {
747 btm_ble_set_connectability ( btm_cb.ble_ctr_cb.inq_var.connectable_mode );
754 /*******************************************************************************
756 ** Function btm_ble_multi_adv_init
758 ** Description This function initialize the multi adv control block.
764 *******************************************************************************/
765 void btm_ble_multi_adv_init()
768 memset(&btm_multi_adv_cb, 0, sizeof(tBTM_BLE_MULTI_ADV_CB));
769 memset (&btm_multi_adv_idx_q, 0, sizeof (tBTM_BLE_MULTI_ADV_INST_IDX_Q));
770 btm_multi_adv_idx_q.front = -1;
771 btm_multi_adv_idx_q.rear = -1;
773 if (btm_cb.cmn_ble_vsc_cb.adv_inst_max > 0) {
774 btm_multi_adv_cb.p_adv_inst = osi_malloc( sizeof(tBTM_BLE_MULTI_ADV_INST) *
775 (btm_cb.cmn_ble_vsc_cb.adv_inst_max));
776 memset(btm_multi_adv_cb.p_adv_inst, 0, sizeof(tBTM_BLE_MULTI_ADV_INST) *
777 (btm_cb.cmn_ble_vsc_cb.adv_inst_max));
779 btm_multi_adv_cb.op_q.p_sub_code = osi_malloc( sizeof(UINT8) *
780 (btm_cb.cmn_ble_vsc_cb.adv_inst_max));
781 memset(btm_multi_adv_cb.op_q.p_sub_code, 0,
782 sizeof(UINT8) * (btm_cb.cmn_ble_vsc_cb.adv_inst_max));
784 btm_multi_adv_cb.op_q.p_inst_id = osi_malloc( sizeof(UINT8) *
785 (btm_cb.cmn_ble_vsc_cb.adv_inst_max));
786 memset(btm_multi_adv_cb.op_q.p_inst_id, 0,
787 sizeof(UINT8) * (btm_cb.cmn_ble_vsc_cb.adv_inst_max));
790 /* Initialize adv instance indices and IDs. */
791 for (i = 0; i < btm_cb.cmn_ble_vsc_cb.adv_inst_max; i++) {
792 btm_multi_adv_cb.p_adv_inst[i].index = i;
793 btm_multi_adv_cb.p_adv_inst[i].inst_id = i + 1;
796 BTM_RegisterForVSEvents(btm_ble_multi_adv_vse_cback, TRUE);
799 /*******************************************************************************
801 ** Function btm_ble_multi_adv_cleanup
803 ** Description This function cleans up multi adv control block.
808 *******************************************************************************/
809 void btm_ble_multi_adv_cleanup(void)
811 if (btm_multi_adv_cb.p_adv_inst) {
812 osi_free(btm_multi_adv_cb.p_adv_inst);
813 btm_multi_adv_cb.p_adv_inst = NULL;
816 if (btm_multi_adv_cb.op_q.p_sub_code) {
817 osi_free(btm_multi_adv_cb.op_q.p_sub_code);
818 btm_multi_adv_cb.op_q.p_sub_code = NULL;
821 if (btm_multi_adv_cb.op_q.p_inst_id) {
822 osi_free(btm_multi_adv_cb.op_q.p_inst_id);
823 btm_multi_adv_cb.op_q.p_inst_id = NULL;
828 /*******************************************************************************
830 ** Function btm_ble_multi_adv_get_ref
832 ** Description This function obtains the reference pointer for the instance ID provided
834 ** Parameters inst_id - Instance ID
838 *******************************************************************************/
839 void *btm_ble_multi_adv_get_ref(UINT8 inst_id)
841 tBTM_BLE_MULTI_ADV_INST *p_inst = NULL;
843 if (inst_id < BTM_BleMaxMultiAdvInstanceCount()) {
844 p_inst = &btm_multi_adv_cb.p_adv_inst[inst_id - 1];
845 if (NULL != p_inst) {
846 return p_inst->p_ref;