From 9dd9baf278ae408a8f8c0b26619c42e2e3e7a759 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Tue, 23 Dec 2025 13:34:02 -0600 Subject: [PATCH] If incompatible NimBLE bonds exist in the NVS, delete them for fresh pairing --- src/nimble/NimbleBluetooth.cpp | 75 ++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/src/nimble/NimbleBluetooth.cpp b/src/nimble/NimbleBluetooth.cpp index b6533fc6a..52a415363 100644 --- a/src/nimble/NimbleBluetooth.cpp +++ b/src/nimble/NimbleBluetooth.cpp @@ -26,6 +26,16 @@ #include "nimble/nimble/host/include/host/ble_gap.h" #endif +#ifdef ARCH_ESP32 +#if defined(CONFIG_NIMBLE_CPP_IDF) +#include "host/ble_store.h" +#else +#include "nimble/nimble/host/include/host/ble_store.h" +#endif +#include +#include +#endif + namespace { constexpr uint16_t kPreferredBleMtu = 517; @@ -33,6 +43,67 @@ constexpr uint16_t kPreferredBleTxOctets = 251; constexpr uint16_t kPreferredBleTxTimeUs = (kPreferredBleTxOctets + 14) * 8; } // namespace +#ifdef ARCH_ESP32 +static void deleteBondsIfNimBLEVersionChanged() +{ + esp_err_t err = nvs_flash_init(); + if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { + err = nvs_flash_erase(); + if (err != ESP_OK) { + LOG_ERROR("Failed to erase NVS for NimBLE migration, err=%d", err); + return; + } + err = nvs_flash_init(); + if (err != ESP_OK) { + LOG_ERROR("Failed to re-init NVS after erase, err=%d", err); + return; + } + } else if (err != ESP_OK) { + LOG_ERROR("nvs_flash_init failed, err=%d", err); + return; + } + + nvs_handle_t nimbleHandle = 0; + err = nvs_open("nimble_bond", NVS_READWRITE, &nimbleHandle); + if (err == ESP_ERR_NVS_NOT_FOUND) { + return; + } + if (err != ESP_OK) { + LOG_ERROR("Failed to open nimble_bond namespace, err=%d", err); + return; + } + + size_t requiredSize = 0; + bool bondExists = nvs_get_blob(nimbleHandle, "peer_sec_1", nullptr, &requiredSize) == ESP_OK; + bool rpaExists = nvs_get_blob(nimbleHandle, "rpa_rec_1", nullptr, &requiredSize) == ESP_OK; + bool irkExists = nvs_get_blob(nimbleHandle, "local_irk_1", nullptr, &requiredSize) == ESP_OK; + + bool erasePartition = false; +#if defined(BLE_STORE_OBJ_TYPE_LOCAL_IRK) + erasePartition = bondExists && !rpaExists; +#else + erasePartition = rpaExists || irkExists; +#endif + + bool restartRequired = false; + if (erasePartition) { + LOG_WARN("Clearing NimBLE bonds due to version migration"); + if (nvs_erase_all(nimbleHandle) != ESP_OK || nvs_commit(nimbleHandle) != ESP_OK) { + LOG_ERROR("Failed to erase nimble_bond namespace"); + } else { + restartRequired = true; + } + } + + nvs_close(nimbleHandle); + + if (restartRequired) { + LOG_INFO("Restarting after NimBLE bond cleanup"); + ESP.restart(); + } +} +#endif + // Debugging options: careful, they slow things down quite a bit! // #define DEBUG_NIMBLE_ON_READ_TIMING // uncomment to time onRead duration // #define DEBUG_NIMBLE_ON_WRITE_TIMING // uncomment to time onWrite duration @@ -800,6 +871,10 @@ void NimbleBluetooth::setup() // Uncomment for testing // NimbleBluetooth::clearBonds(); +#ifdef ARCH_ESP32 + deleteBondsIfNimBLEVersionChanged(); +#endif + LOG_INFO("Init the NimBLE bluetooth module"); NimBLEDevice::init(getDeviceName());