1 /****************************************************************************** 2 * 3 * Copyright (C) 2003-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 /***************************************************************************** 20 ** 21 ** Name: vendor_ble.c 22 ** 23 ** Description: This file contains vendor specific feature for BLE 24 ** 25 ******************************************************************************/ 26 #include <string.h> 27 #include "bt_target.h" 28 29 #if (BLE_INCLUDED == TRUE) 30 #include "bt_types.h" 31 #include "hcimsgs.h" 32 #include "btu.h" 33 #include "vendor_ble.h" 34 #include "vendor_hcidefs.h" 35 #include "gatt_int.h" 36 37 /*** This needs to be moved to a VSC control block eventually per coding conventions ***/ 38 #if VENDOR_DYNAMIC_MEMORY == FALSE 39 tBTM_BLE_VENDOR_CB btm_ble_vendor_cb; 40 #endif 41 42 static const BD_ADDR na_bda= {0}; 43 44 /******************************************************************************* 45 ** Resolve Address Using IRK List functions 46 *******************************************************************************/ 47 48 49 /******************************************************************************* 50 ** 51 ** Function btm_ble_vendor_enq_irk_pending 52 ** 53 ** Description add target address into IRK pending operation queue 54 ** 55 ** Parameters target_bda: target device address 56 ** add_entry: TRUE for add entry, FALSE for remove entry 57 ** 58 ** Returns void 59 ** 60 *******************************************************************************/ 61 void btm_ble_vendor_enq_irk_pending(BD_ADDR target_bda, BD_ADDR psuedo_bda, UINT8 to_add) 62 { 63 #if BLE_PRIVACY_SPT == TRUE 64 tBTM_BLE_IRK_Q *p_q = &btm_ble_vendor_cb.irk_pend_q; 65 66 memcpy(p_q->irk_q[p_q->q_next], target_bda, BD_ADDR_LEN); 67 memcpy(p_q->irk_q_random_pseudo[p_q->q_next], psuedo_bda, BD_ADDR_LEN); 68 p_q->irk_q_action[p_q->q_next] = to_add; 69 70 p_q->q_next ++; 71 p_q->q_next %= btm_cb.cmn_ble_vsc_cb.max_irk_list_sz; 72 #endif 73 return ; 74 } 75 /******************************************************************************* 76 ** 77 ** Function btm_ble_vendor_find_irk_pending_entry 78 ** 79 ** Description check to see if the action is in pending list 80 ** 81 ** Parameters TRUE: action pending; 82 ** FALSE: new action 83 ** 84 ** Returns void 85 ** 86 *******************************************************************************/ 87 BOOLEAN btm_ble_vendor_find_irk_pending_entry(BD_ADDR psuedo_addr, UINT8 action) 88 { 89 #if BLE_PRIVACY_SPT == TRUE 90 tBTM_BLE_IRK_Q *p_q = &btm_ble_vendor_cb.irk_pend_q; 91 UINT8 i; 92 93 for (i = p_q->q_pending; i != p_q->q_next; ) 94 { 95 if (memcmp(p_q->irk_q_random_pseudo[i], psuedo_addr, BD_ADDR_LEN) == 0 && 96 action == p_q->irk_q_action[i]) 97 return TRUE; 98 99 i ++; 100 i %= btm_cb.cmn_ble_vsc_cb.max_irk_list_sz; 101 } 102 #endif 103 return FALSE; 104 } 105 /******************************************************************************* 106 ** 107 ** Function btm_ble_vendor_deq_irk_pending 108 ** 109 ** Description add target address into IRK pending operation queue 110 ** 111 ** Parameters target_bda: target device address 112 ** add_entry: TRUE for add entry, FALSE for remove entry 113 ** 114 ** Returns void 115 ** 116 *******************************************************************************/ 117 BOOLEAN btm_ble_vendor_deq_irk_pending(BD_ADDR target_bda, BD_ADDR psuedo_addr) 118 { 119 #if BLE_PRIVACY_SPT == TRUE 120 tBTM_BLE_IRK_Q *p_q = &btm_ble_vendor_cb.irk_pend_q; 121 122 if (p_q->q_next != p_q->q_pending) 123 { 124 memcpy(target_bda, p_q->irk_q[p_q->q_pending], BD_ADDR_LEN); 125 memcpy(psuedo_addr, p_q->irk_q_random_pseudo[p_q->q_pending], BD_ADDR_LEN); 126 127 p_q->q_pending ++; 128 p_q->q_pending %= btm_cb.cmn_ble_vsc_cb.max_irk_list_sz; 129 130 return TRUE; 131 } 132 #endif 133 return FALSE; 134 135 } 136 /******************************************************************************* 137 ** 138 ** Function btm_ble_vendor_find_irk_entry 139 ** 140 ** Description find IRK entry in local host IRK list by static address 141 ** 142 ** Returns IRK list entry pointer 143 ** 144 *******************************************************************************/ 145 tBTM_BLE_IRK_ENTRY * btm_ble_vendor_find_irk_entry(BD_ADDR target_bda) 146 { 147 #if BLE_PRIVACY_SPT == TRUE 148 tBTM_BLE_IRK_ENTRY *p_irk_entry = &btm_ble_vendor_cb.irk_list[0]; 149 UINT8 i; 150 151 for (i = 0; i < btm_cb.cmn_ble_vsc_cb.max_irk_list_sz; i ++, p_irk_entry++) 152 { 153 if (p_irk_entry->in_use && memcmp(p_irk_entry->bd_addr, target_bda, BD_ADDR_LEN) == 0) 154 { 155 return p_irk_entry ; 156 } 157 } 158 #endif 159 return NULL; 160 } 161 /******************************************************************************* 162 ** 163 ** Function btm_ble_vendor_find_irk_entry_by_psuedo_addr 164 ** 165 ** Description find IRK entry in local host IRK list by psuedo address 166 ** 167 ** Returns IRK list entry pointer 168 ** 169 *******************************************************************************/ 170 tBTM_BLE_IRK_ENTRY * btm_ble_vendor_find_irk_entry_by_psuedo_addr (BD_ADDR psuedo_bda) 171 { 172 #if BLE_PRIVACY_SPT == TRUE 173 tBTM_BLE_IRK_ENTRY *p_irk_entry = &btm_ble_vendor_cb.irk_list[0]; 174 UINT8 i; 175 176 if(p_irk_entry == NULL) 177 return NULL; 178 179 for (i = 0; i < btm_cb.cmn_ble_vsc_cb.max_irk_list_sz; i ++, p_irk_entry++) 180 { 181 if (p_irk_entry->in_use && memcmp(p_irk_entry->psuedo_bda, psuedo_bda, BD_ADDR_LEN) == 0) 182 { 183 return p_irk_entry ; 184 } 185 } 186 #endif 187 return NULL; 188 } 189 /******************************************************************************* 190 ** 191 ** Function btm_ble_vendor_alloc_irk_entry 192 ** 193 ** Description allocate IRK entry in local host IRK list 194 ** 195 ** Returns IRK list index 196 ** 197 *******************************************************************************/ 198 UINT8 btm_ble_vendor_alloc_irk_entry(BD_ADDR target_bda, BD_ADDR pseudo_bda) 199 { 200 #if BLE_PRIVACY_SPT == TRUE 201 tBTM_BLE_IRK_ENTRY *p_irk_entry = &btm_ble_vendor_cb.irk_list[0]; 202 UINT8 i; 203 204 for (i = 0; i < btm_cb.cmn_ble_vsc_cb.max_irk_list_sz; i ++, p_irk_entry++) 205 { 206 if (!p_irk_entry->in_use) 207 { 208 memcpy(p_irk_entry->bd_addr, target_bda, BD_ADDR_LEN); 209 memcpy(p_irk_entry->psuedo_bda, pseudo_bda, BD_ADDR_LEN); 210 211 p_irk_entry->index = i; 212 p_irk_entry->in_use = TRUE; 213 214 return i; 215 } 216 } 217 #endif 218 return BTM_CS_IRK_LIST_INVALID; 219 } 220 221 /******************************************************************************* 222 ** 223 ** Function btm_ble_vendor_update_irk_list 224 ** 225 ** Description update IRK entry in local host IRK list 226 ** 227 ** Returns void 228 ** 229 *******************************************************************************/ 230 void btm_ble_vendor_update_irk_list(BD_ADDR target_bda, BD_ADDR pseudo_bda, BOOLEAN add) 231 { 232 #if BLE_PRIVACY_SPT == TRUE 233 tBTM_BLE_IRK_ENTRY *p_irk_entry = btm_ble_vendor_find_irk_entry(target_bda); 234 UINT8 i; 235 236 if (add) 237 { 238 if (p_irk_entry == NULL) 239 { 240 if ((i = btm_ble_vendor_alloc_irk_entry(target_bda, pseudo_bda)) == BTM_CS_IRK_LIST_INVALID) 241 { 242 BTM_TRACE_ERROR("max IRK capacity reached"); 243 } 244 } 245 else 246 { 247 BTM_TRACE_WARNING(" IRK already in queue"); 248 } 249 } 250 else 251 { 252 if (p_irk_entry != NULL) 253 { 254 memset(p_irk_entry, 0, sizeof(tBTM_BLE_IRK_ENTRY)); 255 } 256 else 257 { 258 BTM_TRACE_ERROR("No IRK exist in list, can not remove"); 259 } 260 } 261 #endif 262 return ; 263 } 264 /******************************************************************************* 265 ** 266 ** Function btm_ble_vendor_irk_vsc_op_cmpl 267 ** 268 ** Description IRK operation VSC complete handler 269 ** 270 ** Parameters 271 ** 272 ** Returns void 273 ** 274 *******************************************************************************/ 275 void btm_ble_vendor_irk_vsc_op_cmpl (tBTM_VSC_CMPL *p_params) 276 { 277 UINT8 status; 278 UINT8 *p = p_params->p_param_buf, op_subcode; 279 UINT16 evt_len = p_params->param_len; 280 UINT8 i; 281 tBTM_BLE_VENDOR_CB *p_cb = &btm_ble_vendor_cb; 282 BD_ADDR target_bda, pseudo_bda, rra; 283 284 285 STREAM_TO_UINT8(status, p); 286 287 evt_len--; 288 289 op_subcode = *p ++; 290 BTM_TRACE_DEBUG("btm_ble_vendor_irk_vsc_op_cmpl op_subcode = %d", op_subcode); 291 if (evt_len < 1) 292 { 293 BTM_TRACE_ERROR("cannot interpret IRK VSC cmpl callback"); 294 return; 295 } 296 297 if (BTM_BLE_META_IRK_ENABLE == op_subcode) 298 { 299 BTM_TRACE_DEBUG("IRK enable: %d, %d", status, op_subcode); 300 return; 301 } 302 else 303 if (op_subcode == BTM_BLE_META_CLEAR_IRK_LIST) 304 { 305 if (status == HCI_SUCCESS) 306 { 307 STREAM_TO_UINT8(p_cb->irk_avail_size, p); 308 p_cb->irk_list_size = 0; 309 310 BTM_TRACE_DEBUG("p_cb->irk_list_size = %d", p_cb->irk_avail_size); 311 312 for (i = 0; i < btm_cb.cmn_ble_vsc_cb.max_irk_list_sz; i ++) 313 memset(&p_cb->irk_list[i], 0, sizeof(tBTM_BLE_IRK_ENTRY)); 314 } 315 } 316 else if (op_subcode == BTM_BLE_META_ADD_IRK_ENTRY) 317 { 318 if (!btm_ble_vendor_deq_irk_pending(target_bda, pseudo_bda)) 319 { 320 BTM_TRACE_ERROR("no pending IRK operation"); 321 return; 322 } 323 324 if (status == HCI_SUCCESS) 325 { 326 STREAM_TO_UINT8(p_cb->irk_avail_size, p); 327 btm_ble_vendor_update_irk_list(target_bda, pseudo_bda, TRUE); 328 } 329 else if (status == 0x07) /* BT_ERROR_CODE_MEMORY_CAPACITY_EXCEEDED */ 330 { 331 p_cb->irk_avail_size = 0; 332 BTM_TRACE_ERROR("IRK Full "); 333 } 334 else 335 { 336 /* give the credit back if invalid parameter failed the operation */ 337 p_cb->irk_list_size ++; 338 } 339 } 340 else if (op_subcode == BTM_BLE_META_REMOVE_IRK_ENTRY) 341 { 342 if (!btm_ble_vendor_deq_irk_pending(target_bda, pseudo_bda)) 343 { 344 BTM_TRACE_ERROR("no pending IRK operation"); 345 return; 346 } 347 if (status == HCI_SUCCESS) 348 { 349 STREAM_TO_UINT8(p_cb->irk_avail_size, p); 350 btm_ble_vendor_update_irk_list(target_bda, pseudo_bda, FALSE); 351 } 352 else 353 { 354 /* give the credit back if invalid parameter failed the operation */ 355 if (p_cb->irk_avail_size > 0) 356 p_cb->irk_list_size --; 357 } 358 359 } 360 else if (op_subcode == BTM_BLE_META_READ_IRK_ENTRY) 361 { 362 if (status == HCI_SUCCESS) 363 { 364 //STREAM_TO_UINT8(index, p); 365 p += (1 + 16 + 1); /* skip index, IRK value, address type */ 366 STREAM_TO_BDADDR(target_bda, p); 367 STREAM_TO_BDADDR(rra, p); 368 btm_ble_refresh_rra(target_bda, rra); 369 } 370 } 371 372 } 373 /******************************************************************************* 374 ** 375 ** Function btm_ble_remove_irk_entry 376 ** 377 ** Description This function to remove an IRK entry from the list 378 ** 379 ** Parameters ble_addr_type: address type 380 ** ble_addr: LE adddress 381 ** 382 ** Returns status 383 ** 384 *******************************************************************************/ 385 tBTM_STATUS btm_ble_remove_irk_entry(tBTM_SEC_DEV_REC *p_dev_rec) 386 { 387 #if BLE_PRIVACY_SPT == TRUE 388 UINT8 param[20], *p; 389 tBTM_STATUS st; 390 tBTM_BLE_VENDOR_CB *p_cb = &btm_ble_vendor_cb; 391 392 if (btm_cb.cmn_ble_vsc_cb.max_irk_list_sz == 0) 393 return BTM_MODE_UNSUPPORTED; 394 395 p = param; 396 memset(param, 0, 20); 397 398 UINT8_TO_STREAM(p, BTM_BLE_META_REMOVE_IRK_ENTRY); 399 UINT8_TO_STREAM(p, p_dev_rec->ble.static_addr_type); 400 BDADDR_TO_STREAM(p, p_dev_rec->ble.static_addr); 401 402 if ((st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_RPA_VSC, 403 BTM_BLE_META_REMOVE_IRK_LEN, 404 param, 405 btm_ble_vendor_irk_vsc_op_cmpl)) 406 != BTM_NO_RESOURCES) 407 { 408 btm_ble_vendor_enq_irk_pending(p_dev_rec->ble.static_addr, p_dev_rec->bd_addr, FALSE); 409 p_cb->irk_list_size --; 410 } 411 412 return st; 413 #endif 414 return BTM_MODE_UNSUPPORTED; 415 } 416 /******************************************************************************* 417 ** 418 ** Function btm_ble_vendor_clear_irk_list 419 ** 420 ** Description This function clears the IRK entry list 421 ** 422 ** Parameters None. 423 ** 424 ** Returns status 425 ** 426 *******************************************************************************/ 427 tBTM_STATUS btm_ble_vendor_clear_irk_list(void) 428 { 429 #if BLE_PRIVACY_SPT == TRUE 430 UINT8 param[20], *p; 431 tBTM_STATUS st; 432 433 if (btm_cb.cmn_ble_vsc_cb.max_irk_list_sz == 0) 434 return BTM_MODE_UNSUPPORTED; 435 436 p = param; 437 memset(param, 0, 20); 438 439 UINT8_TO_STREAM(p, BTM_BLE_META_CLEAR_IRK_LIST); 440 441 st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_RPA_VSC, 442 BTM_BLE_META_CLEAR_IRK_LEN, 443 param, 444 btm_ble_vendor_irk_vsc_op_cmpl); 445 446 return st; 447 #endif 448 return BTM_MODE_UNSUPPORTED; 449 } 450 /******************************************************************************* 451 ** 452 ** Function btm_ble_read_irk_entry 453 ** 454 ** Description This function read an IRK entry by index 455 ** 456 ** Parameters entry index. 457 ** 458 ** Returns status 459 ** 460 *******************************************************************************/ 461 tBTM_STATUS btm_ble_read_irk_entry(BD_ADDR target_bda) 462 { 463 #if BLE_PRIVACY_SPT == TRUE 464 UINT8 param[20], *p; 465 tBTM_STATUS st = BTM_UNKNOWN_ADDR; 466 tBTM_BLE_IRK_ENTRY *p_entry; 467 468 if (btm_cb.cmn_ble_vsc_cb.max_irk_list_sz == 0) 469 return BTM_MODE_UNSUPPORTED; 470 471 if ((p_entry = btm_ble_vendor_find_irk_entry(target_bda)) == NULL) 472 return st; 473 474 p = param; 475 memset(param, 0, 20); 476 477 UINT8_TO_STREAM(p, BTM_BLE_META_READ_IRK_ENTRY); 478 UINT8_TO_STREAM(p, p_entry->index); 479 480 st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_RPA_VSC, 481 BTM_BLE_META_READ_IRK_LEN, 482 param, 483 btm_ble_vendor_irk_vsc_op_cmpl); 484 485 return st; 486 #endif 487 return BTM_MODE_UNSUPPORTED; 488 } 489 490 491 /******************************************************************************* 492 ** 493 ** Function btm_ble_vendor_enable_irk_list_known_dev 494 ** 495 ** Description This function add all known device with random address into 496 ** IRK list. 497 ** 498 ** Parameters enable: enable IRK list with known device, or disable it 499 ** 500 ** Returns status 501 ** 502 *******************************************************************************/ 503 void btm_ble_vendor_irk_list_known_dev(BOOLEAN enable) 504 { 505 #if BLE_PRIVACY_SPT == TRUE 506 UINT8 i; 507 UINT8 count = 0; 508 tBTM_SEC_DEV_REC *p_dev_rec = &btm_cb.sec_dev_rec[0]; 509 510 if (btm_cb.cmn_ble_vsc_cb.max_irk_list_sz == 0) 511 return; 512 513 /* add all known device with random address into IRK list */ 514 for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i ++, p_dev_rec ++) 515 { 516 if (p_dev_rec->sec_flags & BTM_SEC_IN_USE) 517 { 518 if (btm_ble_vendor_irk_list_load_dev(p_dev_rec)) 519 count ++; 520 } 521 } 522 523 if ((count > 0 && enable) || !enable) 524 btm_ble_vendor_enable_irk_feature(enable); 525 #endif 526 return ; 527 } 528 /******************************************************************************* 529 ** 530 ** Function btm_ble_vendor_irk_list_load_dev 531 ** 532 ** Description This function add a device which is using RPA into white list 533 ** 534 ** Parameters 535 ** 536 ** Returns status 537 ** 538 *******************************************************************************/ 539 BOOLEAN btm_ble_vendor_irk_list_load_dev(tBTM_SEC_DEV_REC *p_dev_rec) 540 { 541 #if BLE_PRIVACY_SPT == TRUE 542 UINT8 param[40], *p; 543 tBTM_BLE_VENDOR_CB *p_cb = &btm_ble_vendor_cb; 544 BOOLEAN rt = FALSE; 545 tBTM_BLE_IRK_ENTRY *p_irk_entry = NULL; 546 BTM_TRACE_DEBUG ("btm_ble_vendor_irk_list_load_dev:max_irk_size=%d", p_cb->irk_avail_size); 547 memset(param, 0, 40); 548 549 if (btm_cb.cmn_ble_vsc_cb.max_irk_list_sz == 0) 550 return FALSE; 551 552 if (p_dev_rec != NULL && /* RPA is being used and PID is known */ 553 (p_dev_rec->ble.key_type & BTM_LE_KEY_PID) != 0) 554 { 555 556 if ((p_irk_entry = btm_ble_vendor_find_irk_entry_by_psuedo_addr(p_dev_rec->bd_addr)) == NULL && 557 btm_ble_vendor_find_irk_pending_entry(p_dev_rec->bd_addr, TRUE) == FALSE) 558 { 559 560 if (p_cb->irk_avail_size > 0) 561 { 562 p = param; 563 564 UINT8_TO_STREAM(p, BTM_BLE_META_ADD_IRK_ENTRY); 565 ARRAY_TO_STREAM(p, p_dev_rec->ble.keys.irk, BT_OCTET16_LEN); 566 UINT8_TO_STREAM(p, p_dev_rec->ble.static_addr_type); 567 BDADDR_TO_STREAM(p,p_dev_rec->ble.static_addr); 568 569 if (BTM_VendorSpecificCommand (HCI_VENDOR_BLE_RPA_VSC, 570 BTM_BLE_META_ADD_IRK_LEN, 571 param, 572 btm_ble_vendor_irk_vsc_op_cmpl) 573 != BTM_NO_RESOURCES) 574 { 575 btm_ble_vendor_enq_irk_pending(p_dev_rec->ble.static_addr, p_dev_rec->bd_addr, TRUE); 576 p_cb->irk_list_size ++; 577 rt = TRUE; 578 579 btm_ble_vendor_enable_irk_feature(TRUE); 580 } 581 } 582 } 583 else 584 { 585 BTM_TRACE_ERROR("Device already in IRK list"); 586 rt = TRUE; 587 } 588 } 589 else 590 { 591 BTM_TRACE_DEBUG("Device not a RPA enabled device"); 592 } 593 return rt; 594 #endif 595 return FALSE; 596 } 597 /******************************************************************************* 598 ** 599 ** Function btm_ble_vendor_irk_list_remove_dev 600 ** 601 ** Description This function remove the device from IRK list 602 ** 603 ** Parameters 604 ** 605 ** Returns status 606 ** 607 *******************************************************************************/ 608 void btm_ble_vendor_irk_list_remove_dev(tBTM_SEC_DEV_REC *p_dev_rec) 609 { 610 #if BLE_PRIVACY_SPT == TRUE 611 tBTM_BLE_VENDOR_CB *p_cs_cb = &btm_ble_vendor_cb; 612 tBTM_BLE_IRK_ENTRY *p_irk_entry; 613 614 if (btm_cb.cmn_ble_vsc_cb.max_irk_list_sz == 0) 615 return; 616 617 if ((p_irk_entry = btm_ble_vendor_find_irk_entry_by_psuedo_addr(p_dev_rec->bd_addr)) != NULL && 618 btm_ble_vendor_find_irk_pending_entry(p_dev_rec->bd_addr, FALSE) == FALSE) 619 { 620 btm_ble_remove_irk_entry(p_dev_rec); 621 } 622 else 623 { 624 BTM_TRACE_ERROR("Device not in IRK list"); 625 } 626 627 if (p_cs_cb->irk_list_size == 0) 628 btm_ble_vendor_enable_irk_feature(FALSE); 629 #endif 630 } 631 /******************************************************************************* 632 ** 633 ** Function btm_ble_vendor_disable_irk_list 634 ** 635 ** Description disable LE resolve address feature 636 ** 637 ** Parameters 638 ** 639 ** Returns status 640 ** 641 *******************************************************************************/ 642 void btm_ble_vendor_disable_irk_list(void) 643 { 644 #if BLE_PRIVACY_SPT == TRUE 645 btm_ble_vendor_enable_irk_feature(FALSE); 646 #endif 647 } 648 649 /******************************************************************************* 650 ** 651 ** Function btm_ble_vendor_enable_irk_feature 652 ** 653 ** Description This function is called to enable or disable the RRA 654 ** offloading feature. 655 ** 656 ** Parameters enable: enable or disable the RRA offloading feature 657 ** 658 ** Returns BTM_SUCCESS if successful 659 ** 660 *******************************************************************************/ 661 tBTM_STATUS btm_ble_vendor_enable_irk_feature(BOOLEAN enable) 662 { 663 #if BLE_PRIVACY_SPT == TRUE 664 UINT8 param[20], *p; 665 tBTM_STATUS st = BTM_WRONG_MODE; 666 tBTM_BLE_PF_COUNT *p_bda_filter; 667 668 if (btm_cb.cmn_ble_vsc_cb.max_irk_list_sz == 0) 669 return BTM_MODE_UNSUPPORTED; 670 671 if (btm_ble_vendor_cb.enable != enable) 672 { 673 p = param; 674 memset(param, 0, 20); 675 676 /* select feature based on control block settings */ 677 UINT8_TO_STREAM(p, BTM_BLE_META_IRK_ENABLE); 678 UINT8_TO_STREAM(p, enable ? 0x01 : 0x00); 679 680 st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_RPA_VSC, BTM_BLE_IRK_ENABLE_LEN, 681 param, btm_ble_vendor_irk_vsc_op_cmpl); 682 683 btm_ble_vendor_cb.enable = enable; 684 } 685 686 return st; 687 #endif 688 return BTM_MODE_UNSUPPORTED; 689 } 690 691 692 /******************************************************************************* 693 ** 694 ** Function btm_ble_vendor_init 695 ** 696 ** Description Initialize customer specific feature information in host stack 697 ** 698 ** Parameters Max IRK list size 699 ** Max filter supported 700 ** 701 ** Returns void 702 ** 703 *******************************************************************************/ 704 void btm_ble_vendor_init(UINT8 max_irk_list_sz) 705 { 706 memset(&btm_ble_vendor_cb, 0, sizeof(tBTM_BLE_VENDOR_CB)); 707 708 #if BLE_PRIVACY_SPT == TRUE 709 if (max_irk_list_sz > 0) 710 { 711 btm_ble_vendor_cb.irk_list = (tBTM_BLE_IRK_ENTRY*)GKI_getbuf (sizeof (tBTM_BLE_IRK_ENTRY) 712 * max_irk_list_sz); 713 btm_ble_vendor_cb.irk_pend_q.irk_q = (BD_ADDR*) GKI_getbuf (sizeof (BD_ADDR) * 714 max_irk_list_sz); 715 btm_ble_vendor_cb.irk_pend_q.irk_q_random_pseudo = (BD_ADDR*)GKI_getbuf (sizeof (BD_ADDR) * 716 max_irk_list_sz); 717 btm_ble_vendor_cb.irk_pend_q.irk_q_action = (UINT8*) GKI_getbuf (max_irk_list_sz); 718 } 719 720 btm_ble_vendor_cb.irk_avail_size = max_irk_list_sz; 721 722 if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1])) 723 return; 724 #endif 725 } 726 727 /******************************************************************************* 728 ** 729 ** Function btm_ble_vendor_cleanup 730 ** 731 ** Description Cleanup VSC specific dynamic memory 732 ** 733 ** Parameters 734 ** 735 ** Returns void 736 ** 737 *******************************************************************************/ 738 void btm_ble_vendor_cleanup(void) 739 { 740 #if BLE_PRIVACY_SPT == TRUE 741 if (btm_ble_vendor_cb.irk_list) 742 GKI_freebuf(btm_ble_vendor_cb.irk_list); 743 744 if (btm_ble_vendor_cb.irk_pend_q.irk_q) 745 GKI_freebuf(btm_ble_vendor_cb.irk_pend_q.irk_q); 746 747 if (btm_ble_vendor_cb.irk_pend_q.irk_q_random_pseudo) 748 GKI_freebuf(btm_ble_vendor_cb.irk_pend_q.irk_q_random_pseudo); 749 750 if (btm_ble_vendor_cb.irk_pend_q.irk_q_action) 751 GKI_freebuf(btm_ble_vendor_cb.irk_pend_q.irk_q_action); 752 #endif 753 memset(&btm_ble_vendor_cb, 0, sizeof(tBTM_BLE_VENDOR_CB)); 754 } 755 756 #endif 757 758