From 724e1a7083c27167d72c718892b8ea78268cc0cf Mon Sep 17 00:00:00 2001 From: h2zero Date: Sun, 10 Nov 2024 08:28:14 -0700 Subject: [PATCH] Fix endless loop when calling scan start from scan end callback. When attempting to connect and the scanner is running `NimBLEScan::stop` is called to stop it which then calls the `onScanEnded` callback. If the app then starts the scan again in this callback an endless loop will be created. This change prevents the endless loop by setting a flag in `NimBLEDevice` that is checked before starting a scan while a client is trying to connect. * Adds `NimBLEDevice::setConnectionInProgress` and `NimBLEDevice::isConnectionInProgress` functions. --- src/NimBLEClient.cpp | 7 +++++-- src/NimBLEDevice.cpp | 21 +++++++++++++++++++++ src/NimBLEDevice.h | 6 ++++++ src/NimBLEScan.cpp | 5 +++++ 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/NimBLEClient.cpp b/src/NimBLEClient.cpp index a127996..1de4a63 100644 --- a/src/NimBLEClient.cpp +++ b/src/NimBLEClient.cpp @@ -182,6 +182,9 @@ bool NimBLEClient::connect(const NimBLEAddress& address, bool deleteAttributes) m_pTaskData = &taskData; int rc = 0; + // Set the connection in progress flag to prevent a scan from starting while connecting. + NimBLEDevice::setConnectionInProgress(true); + do { # if CONFIG_BT_NIMBLE_EXT_ADV rc = ble_gap_ext_connect(NimBLEDevice::m_ownAddrType, @@ -207,7 +210,7 @@ bool NimBLEClient::connect(const NimBLEAddress& address, bool deleteAttributes) break; case BLE_HS_EBUSY: - // Scan was still running, stop it and try again + // Scan was active, stop it through the NimBLEScan API to release any tasks and call the callback. if (!NimBLEDevice::getScan()->stop()) { rc = BLE_HS_EUNKNOWN; } @@ -236,8 +239,8 @@ bool NimBLEClient::connect(const NimBLEAddress& address, bool deleteAttributes) } while (rc == BLE_HS_EBUSY); + NimBLEDevice::setConnectionInProgress(false); m_lastErr = rc; - if (rc != 0) { m_pTaskData = nullptr; return false; diff --git a/src/NimBLEDevice.cpp b/src/NimBLEDevice.cpp index 514004d..784514e 100644 --- a/src/NimBLEDevice.cpp +++ b/src/NimBLEDevice.cpp @@ -101,6 +101,10 @@ std::vector NimBLEDevice::m_ignoreList{}; std::vector NimBLEDevice::m_whiteList{}; uint8_t NimBLEDevice::m_ownAddrType{BLE_OWN_ADDR_PUBLIC}; +# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) || defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +bool NimBLEDevice::m_connectionInProgress{false}; +# endif + # ifdef ESP_PLATFORM # ifdef CONFIG_BTDM_BLE_SCAN_DUPL uint16_t NimBLEDevice::m_scanDuplicateSize{CONFIG_BTDM_SCAN_DUPL_CACHE_SIZE}; @@ -1232,6 +1236,23 @@ bool NimBLEDevice::setCustomGapHandler(gap_event_handler handler) { return rc == 0; } // setCustomGapHandler +/** + * @brief Set the connection in progress flag. + * @param [in] inProgress The connection in progress flag. + * @details This is used to prevent a scan from starting while a connection is in progress. + */ +void NimBLEDevice::setConnectionInProgress(bool inProgress) { + m_connectionInProgress = inProgress; +} // setConnectionInProgress + +/** + * @brief Check if a connection is in progress. + * @return True if a connection is in progress. + */ +bool NimBLEDevice::isConnectionInProgress() { + return m_connectionInProgress; +} // isConnectionInProgress + /** * @brief Return a string representation of the address of this device. * @return A string representation of this device address. diff --git a/src/NimBLEDevice.h b/src/NimBLEDevice.h index 507b5ad..e6c1144 100644 --- a/src/NimBLEDevice.h +++ b/src/NimBLEDevice.h @@ -183,6 +183,8 @@ class NimBLEDevice { static bool isBonded(const NimBLEAddress& address); static bool deleteAllBonds(); static NimBLEAddress getBondedAddress(int index); + static void setConnectionInProgress(bool inProgress); + static bool isConnectionInProgress(); # endif private: @@ -194,6 +196,10 @@ class NimBLEDevice { static uint8_t m_ownAddrType; static std::vector m_whiteList; +# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) || defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) + static bool m_connectionInProgress; +# endif + # if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) static NimBLEScan* m_pScan; # endif diff --git a/src/NimBLEScan.cpp b/src/NimBLEScan.cpp index 6546634..56d49a0 100644 --- a/src/NimBLEScan.cpp +++ b/src/NimBLEScan.cpp @@ -292,6 +292,11 @@ bool NimBLEScan::isScanning() { bool NimBLEScan::start(uint32_t duration, bool is_continue) { NIMBLE_LOGD(LOG_TAG, ">> start: duration=%" PRIu32, duration); + if (NimBLEDevice::isConnectionInProgress()) { + NIMBLE_LOGE(LOG_TAG, "Connection in progress, cannot start scan"); + return false; + } + // Save the duration in the case that the host is reset so we can reuse it. m_duration = duration;