Home | History | Annotate | Download | only in btm
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 1999-2012 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  *  This file contains functions for the Bluetooth Device Manager
     22  *
     23  ******************************************************************************/
     24 
     25 #include <stdlib.h>
     26 #include <string.h>
     27 #include <stdio.h>
     28 #include <stddef.h>
     29 
     30 #include "bt_types.h"
     31 #include "gki.h"
     32 #include "hcimsgs.h"
     33 #include "btu.h"
     34 #include "btm_api.h"
     35 #include "btm_int.h"
     36 #include "hcidefs.h"
     37 #include "l2c_api.h"
     38 static tBTM_SEC_DEV_REC *btm_find_oldest_dev (void);
     39 
     40 /*******************************************************************************
     41 **
     42 ** Function         BTM_SecAddDevice
     43 **
     44 ** Description      Add/modify device.  This function will be normally called
     45 **                  during host startup to restore all required information
     46 **                  stored in the NVRAM.
     47 **
     48 ** Parameters:      bd_addr          - BD address of the peer
     49 **                  dev_class        - Device Class
     50 **                  bd_name          - Name of the peer device.  NULL if unknown.
     51 **                  features         - Remote device's supported features. NULL if not known
     52 **                  trusted_mask     - Bitwise OR of services that do not
     53 **                                     require authorization. (array of UINT32)
     54 **                  link_key         - Connection link key. NULL if unknown.
     55 **
     56 ** Returns          TRUE if added OK, else FALSE
     57 **
     58 *******************************************************************************/
     59 BOOLEAN BTM_SecAddDevice (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name,
     60                           BD_FEATURES features, UINT32 trusted_mask[],
     61                           LINK_KEY link_key, UINT8 key_type, tBTM_IO_CAP io_cap)
     62 {
     63     tBTM_SEC_DEV_REC  *p_dev_rec;
     64     int               i;
     65 
     66     p_dev_rec = btm_find_dev (bd_addr);
     67     if (!p_dev_rec)
     68     {
     69         /* There is no device record, allocate one.
     70          * If we can not find an empty spot for this one, let it fail. */
     71         for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++)
     72         {
     73             if (!(btm_cb.sec_dev_rec[i].sec_flags & BTM_SEC_IN_USE))
     74             {
     75                 p_dev_rec = &btm_cb.sec_dev_rec[i];
     76 
     77                 /* Mark this record as in use and initialize */
     78                 memset (p_dev_rec, 0, sizeof (tBTM_SEC_DEV_REC));
     79                 p_dev_rec->sec_flags = BTM_SEC_IN_USE;
     80                 memcpy (p_dev_rec->bd_addr, bd_addr, BD_ADDR_LEN);
     81                 p_dev_rec->hci_handle = BTM_GetHCIConnHandle (bd_addr);
     82 
     83 #if BLE_INCLUDED == TRUE
     84                 /* use default value for background connection params */
     85                 /* update conn params, use default value for background connection params */
     86                 memset(&p_dev_rec->conn_params, 0xff, sizeof(tBTM_LE_CONN_PRAMS));
     87 #endif
     88                 break;
     89             }
     90         }
     91 
     92         if (!p_dev_rec)
     93             return(FALSE);
     94     }
     95 
     96     p_dev_rec->timestamp = btm_cb.dev_rec_count++;
     97 
     98     if (dev_class)
     99         memcpy (p_dev_rec->dev_class, dev_class, DEV_CLASS_LEN);
    100 
    101     memset(p_dev_rec->sec_bd_name, 0, sizeof(tBTM_BD_NAME));
    102 
    103     if (bd_name && bd_name[0])
    104     {
    105         p_dev_rec->sec_flags |= BTM_SEC_NAME_KNOWN;
    106         BCM_STRNCPY_S ((char *)p_dev_rec->sec_bd_name, sizeof (p_dev_rec->sec_bd_name),
    107             (char *)bd_name, BTM_MAX_REM_BD_NAME_LEN);
    108     }
    109 
    110     if (features)
    111         memcpy (p_dev_rec->features, features, sizeof (BD_FEATURES));
    112     else
    113         memset (p_dev_rec->features, 0, sizeof (BD_FEATURES));
    114 
    115     BTM_SEC_COPY_TRUSTED_DEVICE(trusted_mask, p_dev_rec->trusted_mask);
    116 
    117     if (link_key)
    118     {
    119         BTM_TRACE_EVENT6 ("BTM_SecAddDevice()  BDA: %02x:%02x:%02x:%02x:%02x:%02x",
    120                           bd_addr[0], bd_addr[1], bd_addr[2],
    121                           bd_addr[3], bd_addr[4], bd_addr[5]);
    122         p_dev_rec->sec_flags |= BTM_SEC_LINK_KEY_KNOWN;
    123         memcpy (p_dev_rec->link_key, link_key, LINK_KEY_LEN);
    124         p_dev_rec->link_key_type = key_type;
    125     }
    126 
    127 #if defined(BTIF_MIXED_MODE_INCLUDED) && (BTIF_MIXED_MODE_INCLUDED == TRUE)
    128     p_dev_rec->sm4 = BTM_SM4_KNOWN;
    129 #endif
    130 
    131     p_dev_rec->rmt_io_caps = io_cap;
    132 
    133     return(TRUE);
    134 }
    135 
    136 
    137 /*******************************************************************************
    138 **
    139 ** Function         BTM_SecDeleteDevice
    140 **
    141 ** Description      Free resources associated with the device.
    142 **
    143 ** Parameters:      bd_addr          - BD address of the peer
    144 **
    145 ** Returns          TRUE if removed OK, FALSE if not found or ACL link is active
    146 **
    147 *******************************************************************************/
    148 BOOLEAN BTM_SecDeleteDevice (BD_ADDR bd_addr)
    149 {
    150     tBTM_SEC_DEV_REC  *p_dev_rec;
    151 
    152     if (BTM_IsAclConnectionUp(bd_addr))
    153     {
    154         BTM_TRACE_WARNING0("BTM_SecDeleteDevice FAILED: Cannot Delete when connection is active");
    155         return(FALSE);
    156     }
    157 
    158     if ((p_dev_rec = btm_find_dev (bd_addr)) == NULL)
    159         return(FALSE);
    160 
    161     btm_sec_free_dev (p_dev_rec);
    162 
    163     /* Tell controller to get rid of the link key if it has one stored */
    164     BTM_DeleteStoredLinkKey (bd_addr, NULL);
    165 
    166     return(TRUE);
    167 }
    168 
    169 /*******************************************************************************
    170 **
    171 ** Function         BTM_SecReadDevName
    172 **
    173 ** Description      Looks for the device name in the security database for the
    174 **                  specified BD address.
    175 **
    176 ** Returns          Pointer to the name or NULL
    177 **
    178 *******************************************************************************/
    179 char *BTM_SecReadDevName (BD_ADDR bd_addr)
    180 {
    181     char *p_name = NULL;
    182     tBTM_SEC_DEV_REC *p_srec;
    183 
    184     if ((p_srec = btm_find_dev(bd_addr)) != NULL)
    185         p_name = (char *)p_srec->sec_bd_name;
    186 
    187     return(p_name);
    188 }
    189 
    190 /*******************************************************************************
    191 **
    192 ** Function         btm_sec_alloc_dev
    193 **
    194 ** Description      Look for the record in the device database for the record
    195 **                  with specified handle
    196 **
    197 ** Returns          Pointer to the record or NULL
    198 **
    199 *******************************************************************************/
    200 tBTM_SEC_DEV_REC *btm_sec_alloc_dev (BD_ADDR bd_addr)
    201 {
    202     tBTM_SEC_DEV_REC *p_dev_rec = NULL;
    203     tBTM_INQ_INFO    *p_inq_info;
    204     int               i;
    205     BTM_TRACE_EVENT0 ("btm_sec_alloc_dev");
    206     for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++)
    207     {
    208         if (!(btm_cb.sec_dev_rec[i].sec_flags & BTM_SEC_IN_USE))
    209         {
    210             p_dev_rec = &btm_cb.sec_dev_rec[i];
    211             break;
    212         }
    213     }
    214 
    215     if (!p_dev_rec)
    216         p_dev_rec = btm_find_oldest_dev();
    217 
    218     memset (p_dev_rec, 0, sizeof (tBTM_SEC_DEV_REC));
    219 
    220     p_dev_rec->sec_flags = BTM_SEC_IN_USE;
    221 
    222     /* Check with the BT manager if details about remote device are known */
    223     /* outgoing connection */
    224     if ((p_inq_info = BTM_InqDbRead(bd_addr)) != NULL)
    225     {
    226         memcpy (p_dev_rec->dev_class, p_inq_info->results.dev_class, DEV_CLASS_LEN);
    227 
    228 #if BLE_INCLUDED == TRUE
    229         p_dev_rec->device_type = p_inq_info->results.device_type;
    230         p_dev_rec->ble.ble_addr_type = p_inq_info->results.ble_addr_type;
    231 
    232         /* update conn params, use default value for background connection params */
    233         memset(&p_dev_rec->conn_params, 0xff, sizeof(tBTM_LE_CONN_PRAMS));
    234 #endif
    235 
    236 #if BTM_INQ_GET_REMOTE_NAME == TRUE
    237         if (p_inq_info->remote_name_state == BTM_INQ_RMT_NAME_DONE)
    238         {
    239             BCM_STRNCPY_S ((char *)p_dev_rec->sec_bd_name, sizeof (p_dev_rec->sec_bd_name),
    240                      (char *)p_inq_info->remote_name, BTM_MAX_REM_BD_NAME_LEN);
    241             p_dev_rec->sec_flags |= BTM_SEC_NAME_KNOWN;
    242         }
    243 #endif
    244     }
    245     else
    246     {
    247 #if BLE_INCLUDED == TRUE
    248         p_dev_rec->device_type = BT_DEVICE_TYPE_BREDR;  /* initialize it as BR/EDR device */
    249         /* update conn params, use default value for background connection params */
    250         memset(&p_dev_rec->conn_params, 0xff, sizeof(tBTM_LE_CONN_PRAMS));
    251 #endif
    252 
    253         if (!memcmp (bd_addr, btm_cb.connecting_bda, BD_ADDR_LEN))
    254             memcpy (p_dev_rec->dev_class, btm_cb.connecting_dc, DEV_CLASS_LEN);
    255     }
    256 
    257     memcpy (p_dev_rec->bd_addr, bd_addr, BD_ADDR_LEN);
    258 
    259     p_dev_rec->hci_handle = BTM_GetHCIConnHandle (bd_addr);
    260     p_dev_rec->timestamp = btm_cb.dev_rec_count++;
    261 
    262     return(p_dev_rec);
    263 }
    264 
    265 
    266 /*******************************************************************************
    267 **
    268 ** Function         btm_sec_free_dev
    269 **
    270 ** Description      Mark device record as not used
    271 **
    272 *******************************************************************************/
    273 void btm_sec_free_dev (tBTM_SEC_DEV_REC *p_dev_rec)
    274 {
    275     p_dev_rec->sec_flags = 0;
    276 
    277 #if BLE_INCLUDED == TRUE
    278     /* Clear out any saved BLE keys */
    279     btm_sec_clear_ble_keys (p_dev_rec);
    280 #endif
    281 
    282 
    283 }
    284 
    285 /*******************************************************************************
    286 **
    287 ** Function         btm_dev_support_switch
    288 **
    289 ** Description      This function is called by the L2CAP to check if remote
    290 **                  device supports role switch
    291 **
    292 ** Parameters:      bd_addr       - Address of the peer device
    293 **
    294 ** Returns          TRUE if device is known and role switch is supported
    295 **
    296 *******************************************************************************/
    297 BOOLEAN btm_dev_support_switch (BD_ADDR bd_addr)
    298 {
    299     tBTM_SEC_DEV_REC  *p_dev_rec;
    300     UINT8   xx;
    301     BOOLEAN feature_empty = TRUE;
    302 
    303 #if BTM_SCO_INCLUDED == TRUE
    304     /* Role switch is not allowed if a SCO is up */
    305     if (btm_is_sco_active_by_bdaddr(bd_addr))
    306         return(FALSE);
    307 #endif
    308     p_dev_rec = btm_find_dev (bd_addr);
    309     if (p_dev_rec && HCI_SWITCH_SUPPORTED(btm_cb.devcb.local_features))
    310     {
    311         if (HCI_SWITCH_SUPPORTED(p_dev_rec->features))
    312         {
    313             BTM_TRACE_DEBUG0("btm_dev_support_switch return TRUE (feature found)");
    314             return (TRUE);
    315         }
    316 
    317         /* If the feature field is all zero, we never received them */
    318         for (xx = 0 ; xx < BD_FEATURES_LEN ; xx++)
    319         {
    320             if (p_dev_rec->features[xx] != 0x00)
    321             {
    322                 feature_empty = FALSE; /* at least one is != 0 */
    323                 break;
    324             }
    325         }
    326 
    327         /* If we don't know peer's capabilities, assume it supports Role-switch */
    328         if (feature_empty)
    329         {
    330             BTM_TRACE_DEBUG0("btm_dev_support_switch return TRUE (feature empty)");
    331             return (TRUE);
    332         }
    333     }
    334 
    335     BTM_TRACE_DEBUG0("btm_dev_support_switch return FALSE");
    336     return(FALSE);
    337 }
    338 
    339 /*******************************************************************************
    340 **
    341 ** Function         btm_find_dev_by_handle
    342 **
    343 ** Description      Look for the record in the device database for the record
    344 **                  with specified handle
    345 **
    346 ** Returns          Pointer to the record or NULL
    347 **
    348 *******************************************************************************/
    349 tBTM_SEC_DEV_REC *btm_find_dev_by_handle (UINT16 handle)
    350 {
    351     tBTM_SEC_DEV_REC *p_dev_rec = &btm_cb.sec_dev_rec[0];
    352     int i;
    353 
    354     for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++, p_dev_rec++)
    355     {
    356         if ((p_dev_rec->sec_flags & BTM_SEC_IN_USE)
    357             && (p_dev_rec->hci_handle == handle))
    358             return(p_dev_rec);
    359     }
    360     return(NULL);
    361 }
    362 
    363 /*******************************************************************************
    364 **
    365 ** Function         btm_find_dev
    366 **
    367 ** Description      Look for the record in the device database for the record
    368 **                  with specified BD address
    369 **
    370 ** Returns          Pointer to the record or NULL
    371 **
    372 *******************************************************************************/
    373 tBTM_SEC_DEV_REC *btm_find_dev (BD_ADDR bd_addr)
    374 {
    375     tBTM_SEC_DEV_REC *p_dev_rec = &btm_cb.sec_dev_rec[0];
    376     int i;
    377 
    378     if (bd_addr)
    379     {
    380         for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++, p_dev_rec++)
    381         {
    382             if ((p_dev_rec->sec_flags & BTM_SEC_IN_USE)
    383                 && (!memcmp (p_dev_rec->bd_addr, bd_addr, BD_ADDR_LEN)))
    384                 return(p_dev_rec);
    385         }
    386     }
    387     return(NULL);
    388 }
    389 
    390 /*******************************************************************************
    391 **
    392 ** Function         btm_find_or_alloc_dev
    393 **
    394 ** Description      Look for the record in the device database for the record
    395 **                  with specified BD address
    396 **
    397 ** Returns          Pointer to the record or NULL
    398 **
    399 *******************************************************************************/
    400 tBTM_SEC_DEV_REC *btm_find_or_alloc_dev (BD_ADDR bd_addr)
    401 {
    402     tBTM_SEC_DEV_REC *p_dev_rec;
    403     BTM_TRACE_EVENT0 ("btm_find_or_alloc_dev");
    404     if ((p_dev_rec = btm_find_dev (bd_addr)) == NULL)
    405     {
    406 
    407         /* Allocate a new device record or reuse the oldest one */
    408         p_dev_rec = btm_sec_alloc_dev (bd_addr);
    409     }
    410     return(p_dev_rec);
    411 }
    412 
    413 /*******************************************************************************
    414 **
    415 ** Function         btm_find_oldest_dev
    416 **
    417 ** Description      Locates the oldest device in use. It first looks for
    418 **                  the oldest non-paired device.  If all devices are paired it
    419 **                  deletes the oldest paired device.
    420 **
    421 ** Returns          Pointer to the record or NULL
    422 **
    423 *******************************************************************************/
    424 tBTM_SEC_DEV_REC *btm_find_oldest_dev (void)
    425 {
    426     tBTM_SEC_DEV_REC *p_dev_rec = &btm_cb.sec_dev_rec[0];
    427     tBTM_SEC_DEV_REC *p_oldest = p_dev_rec;
    428     UINT32       ot = 0xFFFFFFFF;
    429     int i;
    430 
    431     /* First look for the non-paired devices for the oldest entry */
    432     for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++, p_dev_rec++)
    433     {
    434         if (((p_dev_rec->sec_flags & BTM_SEC_IN_USE) == 0)
    435             || ((p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN) != 0))
    436             continue; /* Device is paired so skip it */
    437 
    438         if (p_dev_rec->timestamp < ot)
    439         {
    440             p_oldest = p_dev_rec;
    441             ot       = p_dev_rec->timestamp;
    442         }
    443     }
    444 
    445     if (ot != 0xFFFFFFFF)
    446         return(p_oldest);
    447 
    448     /* All devices are paired; find the oldest */
    449     p_dev_rec = &btm_cb.sec_dev_rec[0];
    450     for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++, p_dev_rec++)
    451     {
    452         if ((p_dev_rec->sec_flags & BTM_SEC_IN_USE) == 0)
    453             continue;
    454 
    455         if (p_dev_rec->timestamp < ot)
    456         {
    457             p_oldest = p_dev_rec;
    458             ot       = p_dev_rec->timestamp;
    459         }
    460     }
    461     return(p_oldest);
    462 }
    463 
    464 
    465