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 *******************************************************************************/ 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 *******************************************************************************/ 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 *******************************************************************************/ 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 *******************************************************************************/ 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; 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 *******************************************************************************/ 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 *******************************************************************************/ 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 *******************************************************************************/ 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 *******************************************************************************/ 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 *******************************************************************************/ 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 *******************************************************************************/ 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 *******************************************************************************/ 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 *******************************************************************************/ 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 *******************************************************************************/ 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 *******************************************************************************/ 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 *******************************************************************************/ 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 *******************************************************************************/ 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 *******************************************************************************/ 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 *******************************************************************************/ 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