From ec488aae55126703a1512d29e0f3383e49fc0069 Mon Sep 17 00:00:00 2001 From: h2zero Date: Mon, 18 Nov 2024 13:41:49 -0700 Subject: [PATCH] Set a time for scan responses so that callbacks are triggered. --- src/NimBLEAdvertisedDevice.cpp | 2 ++ src/NimBLEAdvertisedDevice.h | 1 + src/NimBLEScan.cpp | 62 ++++++++++++++++++++++++++++++++-- src/NimBLEScan.h | 6 ++-- 4 files changed, 66 insertions(+), 5 deletions(-) diff --git a/src/NimBLEAdvertisedDevice.cpp b/src/NimBLEAdvertisedDevice.cpp index fed8bf6..c84692f 100644 --- a/src/NimBLEAdvertisedDevice.cpp +++ b/src/NimBLEAdvertisedDevice.cpp @@ -35,6 +35,7 @@ NimBLEAdvertisedDevice::NimBLEAdvertisedDevice(const ble_gap_event* event, uint8 m_rssi{event->ext_disc.rssi}, m_callbackSent{0}, m_advLength{event->ext_disc.length_data}, + m_srTimeout{0}, m_isLegacyAdv{!!(event->ext_disc.props & BLE_HCI_ADV_LEGACY_MASK)}, m_sid{event->ext_disc.sid}, m_primPhy{event->ext_disc.prim_phy}, @@ -47,6 +48,7 @@ NimBLEAdvertisedDevice::NimBLEAdvertisedDevice(const ble_gap_event* event, uint8 m_rssi{event->disc.rssi}, m_callbackSent{0}, m_advLength{event->disc.length_data}, + m_srTimeout{0}, m_payload(event->disc.data, event->disc.data + event->disc.length_data) { # endif } // NimBLEAdvertisedDevice diff --git a/src/NimBLEAdvertisedDevice.h b/src/NimBLEAdvertisedDevice.h index e5563e0..3e76383 100644 --- a/src/NimBLEAdvertisedDevice.h +++ b/src/NimBLEAdvertisedDevice.h @@ -157,6 +157,7 @@ class NimBLEAdvertisedDevice { int8_t m_rssi{}; uint8_t m_callbackSent{}; uint8_t m_advLength{}; + uint32_t m_srTimeout{}; # if CONFIG_BT_NIMBLE_EXT_ADV bool m_isLegacyAdv{}; diff --git a/src/NimBLEScan.cpp b/src/NimBLEScan.cpp index fa9f90a..b3c505d 100644 --- a/src/NimBLEScan.cpp +++ b/src/NimBLEScan.cpp @@ -19,6 +19,12 @@ # include "NimBLEDevice.h" # include "NimBLELog.h" +# if defined(CONFIG_NIMBLE_CPP_IDF) +# include "nimble/nimble_port.h" +# else +# include "nimble/porting/nimble/include/nimble/nimble_port.h" +# endif + # include # include @@ -33,13 +39,16 @@ NimBLEScan::NimBLEScan() .itvl{0}, .window{0}, .filter_policy{BLE_HCI_SCAN_FILT_NO_WL}, .limited{0}, .passive{1}, .filter_duplicates{1}}, m_duration{BLE_HS_FOREVER}, m_pTaskData{nullptr}, - m_maxResults{0xFF} {} + m_maxResults{0xFF} { + ble_npl_callout_init(&m_srTimer, nimble_port_get_dflt_eventq(), NimBLEScan::srTimerCb, nullptr); +} /** * @brief Scan destructor, release any allocated resources. */ NimBLEScan::~NimBLEScan() { clearResults(); + ble_npl_callout_deinit(&m_srTimer); } /** @@ -133,7 +142,15 @@ int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) { } else if (isLegacyAdv && event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) { advertisedDevice->m_callbackSent = 2; pScan->m_pScanCallbacks->onResult(advertisedDevice); + } else if (isLegacyAdv) { + ble_npl_time_t ticks; + ble_npl_time_ms_to_ticks(500, &ticks); // more than 500ms for scan response = not coming + advertisedDevice->m_srTimeout = ble_npl_time_get() + ticks; + if (!ble_npl_callout_is_active(&pScan->m_srTimer)) { + ble_npl_callout_reset(&pScan->m_srTimer, ticks); + } } + // If not storing results and we have invoked the callback, delete the device. if (pScan->m_maxResults == 0 && advertisedDevice->m_callbackSent >= 2) { pScan->erase(advertisedAddress); @@ -166,6 +183,41 @@ int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) { } } // handleGapEvent +/** + * @brief This will call the scan result callback when a scan response is not received + * and will delete the device from the vector when maxResults is 0. + */ +void NimBLEScan::srTimerCb(ble_npl_event* event) { + NimBLEScan* pScan = NimBLEDevice::getScan(); + ble_npl_time_t now = ble_npl_time_get(); + ble_npl_time_t nextTimeout = BLE_NPL_TIME_FOREVER; + + for (auto& ad : pScan->m_scanResults.m_deviceVec) { + if (!ad->m_srTimeout) { + continue; + } + + if (ad->m_callbackSent == 1 && now > ad->m_srTimeout) { + ad->m_callbackSent = 2; + pScan->m_pScanCallbacks->onResult(ad); + + if (pScan->m_maxResults == 0) { + pScan->erase(ad->getAddress()); + } + + continue; + } + + if (ad->m_callbackSent == 1 && ad->m_srTimeout < nextTimeout) { + nextTimeout = ad->m_srTimeout; + } + } + + if (nextTimeout != BLE_NPL_TIME_FOREVER) { + ble_npl_callout_reset(&pScan->m_srTimer, nextTimeout); + } +} // srTimerCb + /** * @brief Should we perform an active or passive scan? * The default is a passive scan. An active scan means that we will request a scan response. @@ -277,8 +329,8 @@ bool NimBLEScan::start(uint32_t duration, bool is_continue, bool restart) { } if (isScanning()) { - if(restart) { - //NIMBLE_LOGI(LOG_TAG, "Scan already in progress, stopping it"); + if (restart) { + // NIMBLE_LOGI(LOG_TAG, "Scan already in progress, stopping it"); if (!stop()) { return false; } @@ -357,6 +409,10 @@ bool NimBLEScan::stop() { return false; } + if (m_pScanCallbacks) { + ble_npl_callout_stop(&m_srTimer); + } + if (m_maxResults == 0) { clearResults(); } diff --git a/src/NimBLEScan.h b/src/NimBLEScan.h index 090eb0b..f643f02 100644 --- a/src/NimBLEScan.h +++ b/src/NimBLEScan.h @@ -83,8 +83,9 @@ class NimBLEScan { NimBLEScan(); ~NimBLEScan(); - static int handleGapEvent(ble_gap_event* event, void* arg); - void onHostSync(); + static int handleGapEvent(ble_gap_event* event, void* arg); + static void srTimerCb(ble_npl_event* event); + void onHostSync(); NimBLEScanCallbacks* m_pScanCallbacks; ble_gap_disc_params m_scanParams; @@ -92,6 +93,7 @@ class NimBLEScan { uint32_t m_duration; NimBLETaskData* m_pTaskData; uint8_t m_maxResults; + ble_npl_callout m_srTimer; }; /**