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