Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a8aff6dd authored by Andre Eisenbach's avatar Andre Eisenbach Committed by android-build-merger
Browse files

Fix 100 LE device connection limitation

am: aa4d762b

Change-Id: I64d57c1a19e41bcf35569eb707f58d31c9a54d63
parents d9b63d2b aa4d762b
Loading
Loading
Loading
Loading
+5 −9
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ extern void smp_link_encrypted(BD_ADDR bda, UINT8 encr_enable);
extern BOOLEAN smp_proc_ltk_request(BD_ADDR bda);
#endif
extern void gatt_notify_enc_cmpl(BD_ADDR bd_addr);

/*******************************************************************************/
/* External Function to be called by other modules                             */
/*******************************************************************************/
@@ -73,16 +74,11 @@ BOOLEAN BTM_SecAddBleDevice (BD_ADDR bd_addr, BD_NAME bd_name, tBT_DEVICE_TYPE d
                             tBLE_ADDR_TYPE addr_type)
{
    BTM_TRACE_DEBUG ("%s: dev_type=0x%x", __func__, dev_type);
    tBTM_SEC_DEV_REC  *p_dev_rec = btm_find_dev(bd_addr);

    if (!p_dev_rec) {
        if (list_length(btm_cb.sec_dev_rec) > BTM_SEC_MAX_DEVICE_RECORDS) {
            BTM_TRACE_ERROR("%s: %d max devices reached!", __func__, BTM_SEC_MAX_DEVICE_RECORDS);
            return FALSE;
        }

        p_dev_rec = osi_calloc(sizeof(tBTM_SEC_DEV_REC));
        list_append(btm_cb.sec_dev_rec, p_dev_rec);
    tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev(bd_addr);
    if (!p_dev_rec)
    {
        p_dev_rec = btm_sec_allocate_dev_rec();

        memcpy(p_dev_rec->bd_addr, bd_addr, BD_ADDR_LEN);
        p_dev_rec->hci_handle = BTM_GetHCIConnHandle(bd_addr, BT_TRANSPORT_BR_EDR);
+75 −73
Original line number Diff line number Diff line
@@ -37,8 +37,6 @@
#include "hcidefs.h"
#include "l2c_api.h"

static tBTM_SEC_DEV_REC *btm_find_oldest_dev (void);

/*******************************************************************************
**
** Function         BTM_SecAddDevice
@@ -63,22 +61,12 @@ BOOLEAN BTM_SecAddDevice (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name,
                          LINK_KEY link_key, UINT8 key_type, tBTM_IO_CAP io_cap,
                          UINT8 pin_length)
{
    tBTM_SEC_DEV_REC  *p_dev_rec;
    int               i, j;
    BOOLEAN           found = FALSE;

    BTM_TRACE_API("%s: link key type:%x", __func__, key_type);
    p_dev_rec = btm_find_dev (bd_addr);

    tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr);
    if (!p_dev_rec)
    {
        if (list_length(btm_cb.sec_dev_rec) > BTM_SEC_MAX_DEVICE_RECORDS) {
            BTM_TRACE_DEBUG("%s: Max devices reached!", __func__);
            return FALSE;
        }

        BTM_TRACE_DEBUG ("%s: allocate a new dev rec", __func__);
        p_dev_rec = osi_calloc(sizeof(tBTM_SEC_DEV_REC));
        list_append(btm_cb.sec_dev_rec, p_dev_rec);
        p_dev_rec = btm_sec_allocate_dev_rec();

        memcpy (p_dev_rec->bd_addr, bd_addr, BD_ADDR_LEN);
        p_dev_rec->hci_handle = BTM_GetHCIConnHandle (bd_addr, BT_TRANSPORT_BR_EDR);
@@ -88,11 +76,19 @@ BOOLEAN BTM_SecAddDevice (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name,
        /* update conn params, use default value for background connection params */
        memset(&p_dev_rec->conn_params, 0xff, sizeof(tBTM_LE_CONN_PRAMS));
#endif
    }

    p_dev_rec->bond_type = BOND_TYPE_UNKNOWN;           /* Default value */
    } else {
        /* "Bump" timestamp for existing record */
        p_dev_rec->timestamp = btm_cb.dev_rec_count++;

        /* TODO(eisenbach):
         * Small refactor, but leaving original logic for now.
         * On the surface, this does not make any sense at all. Why change the
         * bond state for an existing device here? This logic should be verified
         * as part of a larger refactor.
         */
        p_dev_rec->bond_type = BOND_TYPE_UNKNOWN;
    }

    if (dev_class)
        memcpy (p_dev_rec->dev_class, dev_class, DEV_CLASS_LEN);

@@ -108,26 +104,23 @@ BOOLEAN BTM_SecAddDevice (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name,
    p_dev_rec->num_read_pages = 0;
    if (features)
    {
        BOOLEAN found = FALSE;
        memcpy (p_dev_rec->features, features, sizeof (p_dev_rec->features));
        for (i = HCI_EXT_FEATURES_PAGE_MAX; i >= 0; i--)
        for (int i = HCI_EXT_FEATURES_PAGE_MAX; !found && i >= 0; i--)
        {
            for (j = 0; j < HCI_FEATURE_BYTES_PER_PAGE; j++)
            for (int j = 0; j < HCI_FEATURE_BYTES_PER_PAGE; j++)
            {
                if (p_dev_rec->features[i][j] != 0)
                {
                    found = TRUE;
                    break;
                }
            }
            if (found)
            {
                    p_dev_rec->num_read_pages = i + 1;
                    break;
                }
            }
        }
    else
    } else {
        memset (p_dev_rec->features, 0, sizeof (p_dev_rec->features));
    }

    BTM_SEC_COPY_TRUSTED_DEVICE(trusted_mask, p_dev_rec->trusted_mask);

@@ -177,8 +170,6 @@ BOOLEAN BTM_SecAddDevice (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name,
*******************************************************************************/
BOOLEAN BTM_SecDeleteDevice (BD_ADDR bd_addr)
{
    tBTM_SEC_DEV_REC *p_dev_rec;

    if (BTM_IsAclConnectionUp(bd_addr, BT_TRANSPORT_LE) ||
        BTM_IsAclConnectionUp(bd_addr, BT_TRANSPORT_BR_EDR))
    {
@@ -186,7 +177,8 @@ BOOLEAN BTM_SecDeleteDevice (BD_ADDR bd_addr)
        return FALSE;
    }

    if ((p_dev_rec = btm_find_dev(bd_addr)) != NULL)
    tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev(bd_addr);
    if (p_dev_rec != NULL)
    {
        btm_sec_free_dev(p_dev_rec);
        /* Tell controller to get rid of the link key, if it has one stored */
@@ -240,20 +232,10 @@ bool is_bd_addr_equal(void *data, void *context)
*******************************************************************************/
tBTM_SEC_DEV_REC *btm_sec_alloc_dev (BD_ADDR bd_addr)
{
    tBTM_SEC_DEV_REC *p_dev_rec = NULL;
    tBTM_INQ_INFO    *p_inq_info;
    BTM_TRACE_EVENT ("btm_sec_alloc_dev");

    if (list_length(btm_cb.sec_dev_rec) > BTM_SEC_MAX_DEVICE_RECORDS) {
        p_dev_rec = btm_find_oldest_dev();
    } else {
        BTM_TRACE_DEBUG ("allocate a new dev rec");
        p_dev_rec = osi_calloc(sizeof(tBTM_SEC_DEV_REC));
        list_append(btm_cb.sec_dev_rec, p_dev_rec);
    }

    p_dev_rec->bond_type = BOND_TYPE_UNKNOWN;           /* Default value */
    p_dev_rec->sec_flags = BTM_SEC_IN_USE;
    tBTM_SEC_DEV_REC *p_dev_rec = btm_sec_allocate_dev_rec();

    /* Check with the BT manager if details about remote device are known */
    /* outgoing connection */
@@ -280,7 +262,6 @@ tBTM_SEC_DEV_REC *btm_sec_alloc_dev (BD_ADDR bd_addr)
    p_dev_rec->ble_hci_handle = BTM_GetHCIConnHandle (bd_addr, BT_TRANSPORT_LE);
#endif
    p_dev_rec->hci_handle = BTM_GetHCIConnHandle (bd_addr, BT_TRANSPORT_BR_EDR);
    p_dev_rec->timestamp = btm_cb.dev_rec_count++;

    return(p_dev_rec);
}
@@ -295,17 +276,11 @@ tBTM_SEC_DEV_REC *btm_sec_alloc_dev (BD_ADDR bd_addr)
*******************************************************************************/
void btm_sec_free_dev (tBTM_SEC_DEV_REC *p_dev_rec)
{
    p_dev_rec->bond_type = BOND_TYPE_UNKNOWN;
    p_dev_rec->sec_flags = 0;

#if BLE_INCLUDED == TRUE
    /* Clear out any saved BLE keys */
    btm_sec_clear_ble_keys (p_dev_rec);
    /* clear the ble block */
    memset(&p_dev_rec->ble, 0, sizeof(tBTM_SEC_BLE));
#endif


    list_remove(btm_cb.sec_dev_rec, p_dev_rec);
}

/*******************************************************************************
@@ -475,8 +450,6 @@ void btm_consolidate_dev(tBTM_SEC_DEV_REC *p_target_rec)

            /* remove the combined record */
            list_remove(btm_cb.sec_dev_rec, p_dev_rec);

            p_dev_rec->bond_type = BOND_TYPE_UNKNOWN;
            break;
        }

@@ -490,8 +463,6 @@ void btm_consolidate_dev(tBTM_SEC_DEV_REC *p_target_rec)

                /* remove the combined record */
                list_remove(btm_cb.sec_dev_rec, p_dev_rec);

                p_dev_rec->bond_type = BOND_TYPE_UNKNOWN;
            }
            break;
        }
@@ -524,48 +495,79 @@ tBTM_SEC_DEV_REC *btm_find_or_alloc_dev (BD_ADDR bd_addr)

/*******************************************************************************
**
** Function         btm_find_oldest_dev
** Function         btm_find_oldest_dev_rec
**
** Description      Locates the oldest device in use. It first looks for
**                  the oldest non-paired device.  If all devices are paired it
**                  deletes the oldest paired device.
**                  returns the oldest paired device.
**
** Returns          Pointer to the record or NULL
**
*******************************************************************************/
tBTM_SEC_DEV_REC *btm_find_oldest_dev (void)
static tBTM_SEC_DEV_REC* btm_find_oldest_dev_rec (void)
{
    tBTM_SEC_DEV_REC *p_oldest = NULL;
    UINT32       ot = 0xFFFFFFFF;
    UINT32       ts_oldest = 0xFFFFFFFF;
    tBTM_SEC_DEV_REC *p_oldest_paired = NULL;
    UINT32       ot_paired = 0xFFFFFFFF;
    UINT32       ts_oldest_paired = 0xFFFFFFFF;

    /* First look for the non-paired devices for the oldest entry */
    list_node_t *end = list_end(btm_cb.sec_dev_rec);
    for (list_node_t *node = list_begin(btm_cb.sec_dev_rec); node != end; node = list_next(node)) {
        tBTM_SEC_DEV_REC *p_dev_rec = list_node(node);
        /* Device is not paired */

        if ((p_dev_rec->sec_flags & (BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_LE_LINK_KEY_KNOWN)) == 0) {
            if (p_dev_rec->timestamp < ot) {
            // Device is not paired
            if (p_dev_rec->timestamp < ts_oldest) {
                p_oldest = p_dev_rec;
                ot       = p_dev_rec->timestamp;
                ts_oldest = p_dev_rec->timestamp;
            }
        } else {
            // Paired device
            if (p_dev_rec->timestamp < ts_oldest_paired) {
                p_oldest_paired = p_dev_rec;
                ts_oldest_paired = p_dev_rec->timestamp;
            }
        }
            continue;
    }

        if (p_dev_rec->timestamp < ot_paired) {
            p_oldest_paired = p_dev_rec;
            ot_paired       = p_dev_rec->timestamp;
    // If we did not find any non-paired devices, use the oldest paired one...
    if (ts_oldest == 0xFFFFFFFF)
        p_oldest = p_oldest_paired;

    return p_oldest;
}

/*******************************************************************************
**
** Function         btm_sec_allocate_dev_rec
**
** Description      Attempts to allocate a new device record. If we have
**                  exceeded the maximum number of allowable records to
**                  allocate, the oldest record will be deleted to make room
**                  for the new record.
**
** Returns          Pointer to the newly allocated record
**
*******************************************************************************/
tBTM_SEC_DEV_REC* btm_sec_allocate_dev_rec(void)
{
    tBTM_SEC_DEV_REC *p_dev_rec = NULL;

    if (list_length(btm_cb.sec_dev_rec) > BTM_SEC_MAX_DEVICE_RECORDS)
    {
        p_dev_rec = btm_find_oldest_dev_rec();
        list_remove(btm_cb.sec_dev_rec, p_dev_rec);
    }

    /* if non-paired device return oldest */
    if (ot != 0xFFFFFFFF)
        return(p_oldest);
    p_dev_rec = osi_calloc(sizeof(tBTM_SEC_DEV_REC));
    list_append(btm_cb.sec_dev_rec, p_dev_rec);

    // Initialize defaults
    p_dev_rec->sec_flags = BTM_SEC_IN_USE;
    p_dev_rec->bond_type = BOND_TYPE_UNKNOWN;
    p_dev_rec->timestamp = btm_cb.dev_rec_count++;

    /* only paired devices present, return oldest */
    return p_oldest_paired;
    return p_dev_rec;
}

/*******************************************************************************
+1 −0
Original line number Diff line number Diff line
@@ -1057,6 +1057,7 @@ extern void btm_report_device_status (tBTM_DEV_STATUS status);
*/
extern BOOLEAN btm_dev_support_switch (BD_ADDR bd_addr);

extern tBTM_SEC_DEV_REC  *btm_sec_allocate_dev_rec(void);
extern tBTM_SEC_DEV_REC  *btm_sec_alloc_dev (BD_ADDR bd_addr);
extern void               btm_sec_free_dev (tBTM_SEC_DEV_REC *p_dev_rec);
extern tBTM_SEC_DEV_REC  *btm_find_dev (BD_ADDR bd_addr);