Home | History | Annotate | Download | only in ble
      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