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 fixed_queue_t *btu_general_alarm_queue; 55 extern 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 *******************************************************************************/ 68 void 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 *******************************************************************************/ 89 void 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 *******************************************************************************/ 111 void 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 *******************************************************************************/ 199 tBTM_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 *******************************************************************************/ 235 int btm_ble_tx_power[BTM_BLE_ADV_TX_POWER_MAX + 1] = BTM_BLE_ADV_TX_POWER; 236 char 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 *******************************************************************************/ 253 tBTM_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 *******************************************************************************/ 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 /* 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 *******************************************************************************/ 381 void 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 *******************************************************************************/ 453 void 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 *******************************************************************************/ 487 void 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 *******************************************************************************/ 515 void 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 *******************************************************************************/ 545 tBTM_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 *******************************************************************************/ 615 tBTM_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 *******************************************************************************/ 661 tBTM_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 *******************************************************************************/ 717 tBTM_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 *******************************************************************************/ 754 void 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 *******************************************************************************/ 812 void 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 *******************************************************************************/ 852 void 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 *******************************************************************************/ 876 void* 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