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 ************************************************************************************/ 48 tBTM_BLE_MULTI_ADV_CB btm_multi_adv_cb; 49 tBTM_BLE_MULTI_ADV_INST_IDX_Q btm_multi_adv_idx_q; 50 51 /************************************************************************************ 52 ** Externs 53 ************************************************************************************/ 54 extern 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 *******************************************************************************/ 67 void 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 *******************************************************************************/ 88 void 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 *******************************************************************************/ 110 void 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 *******************************************************************************/ 198 tBTM_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 *******************************************************************************/ 234 int btm_ble_tx_power[BTM_BLE_ADV_TX_POWER_MAX + 1] = BTM_BLE_ADV_TX_POWER; 235 char 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 *******************************************************************************/ 252 tBTM_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 *******************************************************************************/ 339 tBTM_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 *******************************************************************************/ 380 void 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 *******************************************************************************/ 452 void 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 *******************************************************************************/ 486 void 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 *******************************************************************************/ 514 void 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 *******************************************************************************/ 544 tBTM_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 *******************************************************************************/ 614 tBTM_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 *******************************************************************************/ 660 tBTM_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 *******************************************************************************/ 716 tBTM_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 *******************************************************************************/ 753 void 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 *******************************************************************************/ 811 void 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 *******************************************************************************/ 856 void 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 *******************************************************************************/ 880 void* 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