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