diff --git a/components/bt/host/bluedroid/btc/core/btc_main.c b/components/bt/host/bluedroid/btc/core/btc_main.c index bbcb17b670b..f42d37771de 100644 --- a/components/bt/host/bluedroid/btc/core/btc_main.c +++ b/components/bt/host/bluedroid/btc/core/btc_main.c @@ -183,7 +183,6 @@ uint32_t btc_get_ble_status(void) } #endif // #if ((SMP_INCLUDED == TRUE) || (BLE_PRIVACY_SPT == TRUE)) -#if (SMP_INCLUDED == TRUE) // Number of recorded devices extern uint8_t btm_ble_sec_dev_record_count(void); uint8_t sec_dev_cnt = btm_ble_sec_dev_record_count(); @@ -191,14 +190,14 @@ uint32_t btc_get_ble_status(void) BTC_TRACE_WARNING("%s security device record count %d", __func__, sec_dev_cnt); status |= BIT(BTC_BLE_STATUS_DEVICE_REC); } - +#if SMP_INCLUDED == TRUE // Number of saved bonded devices int bond_cnt = btc_storage_get_num_ble_bond_devices(); if (bond_cnt) { BTC_TRACE_WARNING("%s bonded devices count %d", __func__, bond_cnt); status |= BIT(BTC_BLE_STATUS_BOND); } -#endif // SMP_INCLUDED +#endif // SMP_INCLUDED == TRUE #if (BLE_PRIVACY_SPT == TRUE) // Privacy enabled diff --git a/components/bt/host/bluedroid/stack/btm/btm_ble.c b/components/bt/host/bluedroid/stack/btm/btm_ble.c index 23ddc7b99d5..4e0b630db35 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_ble.c +++ b/components/bt/host/bluedroid/stack/btm/btm_ble.c @@ -2903,26 +2903,47 @@ uint8_t btm_ble_scan_active_count(void) return count; } +#if (BLE_INCLUDED == TRUE) #if (SMP_INCLUDED == TRUE) +extern bool btc_config_has_section(const char *section); +#endif + uint8_t btm_ble_sec_dev_record_count(void) { tBTM_SEC_DEV_REC *p_dev_rec = NULL; list_node_t *p_node = NULL; uint8_t count = 0; - /* First look for the non-paired devices for the oldest entry */ for (p_node = list_begin(btm_cb.p_sec_dev_rec_list); p_node; p_node = list_next(p_node)) { p_dev_rec = list_node(p_node); +#if (SMP_INCLUDED == TRUE) if (p_dev_rec && (p_dev_rec->sec_flags & BTM_SEC_IN_USE) && (p_dev_rec->ble.key_type != BTM_LE_KEY_NONE)) { - BTM_TRACE_DEBUG("%s BLE security device #%d: bd_addr=%02X:%02X:%02X:%02X:%02X:%02X", +#else + if (p_dev_rec && (p_dev_rec->sec_flags & BTM_SEC_IN_USE)) { +#endif +#if (SMP_INCLUDED == TRUE) + /* Check if device exists in NVS */ + char bdstr[18] = {0}; + bdaddr_to_string((bt_bdaddr_t *)p_dev_rec->bd_addr, bdstr, sizeof(bdstr)); + + BTM_TRACE_WARNING("%s device #%d: "MACSTR", key_type=0x%02x (PENC:%d PID:%d PCSRK:%d LENC:%d LID:%d LCSRK:%d), in_nvs=%d", __func__, count, - p_dev_rec->bd_addr[0], - p_dev_rec->bd_addr[1], - p_dev_rec->bd_addr[2], - p_dev_rec->bd_addr[3], - p_dev_rec->bd_addr[4], - p_dev_rec->bd_addr[5]); + MAC2STR(p_dev_rec->bd_addr), + p_dev_rec->ble.key_type, + (p_dev_rec->ble.key_type & BTM_LE_KEY_PENC) ? 1 : 0, + (p_dev_rec->ble.key_type & BTM_LE_KEY_PID) ? 1 : 0, + (p_dev_rec->ble.key_type & BTM_LE_KEY_PCSRK) ? 1 : 0, + (p_dev_rec->ble.key_type & BTM_LE_KEY_LENC) ? 1 : 0, + (p_dev_rec->ble.key_type & BTM_LE_KEY_LID) ? 1 : 0, + (p_dev_rec->ble.key_type & BTM_LE_KEY_LCSRK) ? 1 : 0, + btc_config_has_section(bdstr)); +#else + BTM_TRACE_WARNING("%s device #%d: "MACSTR, + __func__, + count, + MAC2STR(p_dev_rec->bd_addr)); +#endif count++; } } diff --git a/components/bt/host/bluedroid/stack/btu/btu_hcif.c b/components/bt/host/bluedroid/stack/btu/btu_hcif.c index cce65d887fb..2ca2f182f76 100644 --- a/components/bt/host/bluedroid/stack/btu/btu_hcif.c +++ b/components/bt/host/bluedroid/stack/btu/btu_hcif.c @@ -951,6 +951,20 @@ static void btu_hcif_disconnection_comp_evt (UINT8 *p) handle = HCID_GET_HANDLE (handle); +#if BLE_INCLUDED == TRUE + /* Capture the disconnecting device's address before btm_acl_disconnected() + * clears the matched connection handle. The record itself is re-looked-up + * afterwards (by address) because callbacks fired during disconnection may + * have already freed it. */ + BD_ADDR disc_bda; + BOOLEAN have_disc_bda = FALSE; + tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev_by_handle(handle); + if (p_dev_rec) { + memcpy(disc_bda, p_dev_rec->bd_addr, BD_ADDR_LEN); + have_disc_bda = TRUE; + } +#endif + dev_find = btm_acl_disconnected(handle, reason); #if (BLE_FEAT_ISO_CIG_EN == TRUE) @@ -963,6 +977,48 @@ static void btu_hcif_disconnection_comp_evt (UINT8 *p) HCI_TRACE_WARNING("hcif disc complete: hdl 0x%x, rsn 0x%x dev_find %d", handle, reason, dev_find); UNUSED(dev_find); + +#if BLE_INCLUDED == TRUE + /* Delete unpaired device records to free memory (~356B per device). + * + * Re-find the record by address: callbacks invoked during + * btm_acl_disconnected() may already have freed it, so the pointer captured + * before the call cannot be trusted. + * + * Only delete when the device is fully idle and unpaired: + * 1. No active BR/EDR connection (hci_handle invalid) + * 2. No active LE connection (ble_hci_handle invalid) - protects the still + * connected transport of a dual-mode device when the other one drops + * 3. No BLE security keys (unpaired) - when SMP is enabled + * + * BT_TRANSPORT_LE is used so that any retained BR/EDR link key keeps a + * BR/EDR-bonded record alive; an LE-unpaired record that has no BR/EDR key + * collapses to BTM_SEC_IN_USE only and is removed from the list. + * + * Skip deletion on HCI_ERR_CONN_FAILED_ESTABLISHMENT when connect + * retry is enabled. + */ + if (have_disc_bda +#if (GATTC_CONNECT_RETRY_EN == TRUE) + && reason != HCI_ERR_CONN_FAILED_ESTABLISHMENT +#endif + ) { + p_dev_rec = btm_find_dev(disc_bda); + if (p_dev_rec + && p_dev_rec->hci_handle == BTM_SEC_INVALID_HANDLE /* No active BR/EDR connection */ + && p_dev_rec->ble_hci_handle == BTM_SEC_INVALID_HANDLE /* No active LE connection */ +#if SMP_INCLUDED == TRUE + && !p_dev_rec->ble.key_type /* No BLE security keys */ +#endif + ) { + BTM_TRACE_WARNING( + "Deleting unpaired device %02X:%02X:%02X:%02X:%02X:%02X", + p_dev_rec->bd_addr[0], p_dev_rec->bd_addr[1], p_dev_rec->bd_addr[2], + p_dev_rec->bd_addr[3], p_dev_rec->bd_addr[4], p_dev_rec->bd_addr[5]); + btm_sec_free_dev(p_dev_rec, BT_TRANSPORT_LE); + } + } +#endif // BLE_INCLUDED == TRUE } /*******************************************************************************