diff --git a/src/NimBLEAdvertising.cpp b/src/NimBLEAdvertising.cpp index 5e27131..31a1a4f 100644 --- a/src/NimBLEAdvertising.cpp +++ b/src/NimBLEAdvertising.cpp @@ -312,6 +312,9 @@ void NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv return; } + // Save the duration incase of host reset so we can restart with the same params + m_duration = duration; + if(duration == 0){ duration = BLE_HS_FOREVER; } @@ -495,6 +498,7 @@ void NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv */ void NimBLEAdvertising::stop() { NIMBLE_LOGD(LOG_TAG, ">> stop"); + int rc = ble_gap_adv_stop(); if (rc != 0 && rc != BLE_HS_EALREADY) { NIMBLE_LOGE(LOG_TAG, "ble_gap_adv_stop rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc)); @@ -528,8 +532,14 @@ bool NimBLEAdvertising::isAdvertising() { * Host reset seems to clear advertising data, * we need clear the flag so it reloads it. */ -void NimBLEAdvertising::onHostReset() { +void NimBLEAdvertising::onHostSync() { + NIMBLE_LOGD(LOG_TAG, "Host re-synced"); + m_advDataSet = false; + // If we were advertising forever, restart it now + if(m_duration == 0) { + start(m_duration, m_advCompCB); + } } @@ -543,6 +553,19 @@ int NimBLEAdvertising::handleGapEvent(struct ble_gap_event *event, void *arg) { NimBLEAdvertising *pAdv = (NimBLEAdvertising*)arg; if(event->type == BLE_GAP_EVENT_ADV_COMPLETE) { + switch(event->adv_complete.reason) { + // Don't call the callback if host reset, we want to + // preserve the active flag until re-sync to restart advertising. + case BLE_HS_ETIMEOUT_HCI: + case BLE_HS_EOS: + case BLE_HS_ECONTROLLER: + case BLE_HS_ENOTSYNCED: + NIMBLE_LOGC(LOG_TAG, "host reset, rc=%d", event->adv_complete.reason); + NimBLEDevice::onReset(event->adv_complete.reason); + return 0; + default: + break; + } pAdv->advCompleteCB(); } return 0; diff --git a/src/NimBLEAdvertising.h b/src/NimBLEAdvertising.h index 1018bd0..60e5982 100644 --- a/src/NimBLEAdvertising.h +++ b/src/NimBLEAdvertising.h @@ -95,7 +95,7 @@ public: private: friend class NimBLEDevice; - void onHostReset(); + void onHostSync(); static int handleGapEvent(struct ble_gap_event *event, void *arg); ble_hs_adv_fields m_advData; @@ -108,7 +108,7 @@ private: bool m_advDataSet; void (*m_advCompCB)(NimBLEAdvertising *pAdv); uint8_t m_slaveItvl[4]; - + uint32_t m_duration; }; #endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) diff --git a/src/NimBLEDevice.cpp b/src/NimBLEDevice.cpp index b1a0f7b..9ac9e16 100644 --- a/src/NimBLEDevice.cpp +++ b/src/NimBLEDevice.cpp @@ -410,30 +410,16 @@ void NimBLEDevice::stopAdvertising() { m_synced = false; -#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) - if(m_pScan != nullptr) { - m_pScan->onHostReset(); - } -#endif - -/* Not needed - if(m_pServer != nullptr) { - m_pServer->onHostReset(); - } - - for(auto it = m_cList.cbegin(); it != m_cList.cend(); ++it) { - (*it)->onHostReset(); - } -*/ - -#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) - if(m_bleAdvertising != nullptr) { - m_bleAdvertising->onHostReset(); - } -#endif - NIMBLE_LOGC(LOG_TAG, "Resetting state; reason=%d, %s", reason, NimBLEUtils::returnCodeToString(reason)); + +#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) + if(initialized) { + if(m_pScan != nullptr) { + m_pScan->onHostReset(); + } + } +#endif } // onReset @@ -462,15 +448,13 @@ void NimBLEDevice::stopAdvertising() { if(initialized) { #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) if(m_pScan != nullptr) { - // Restart scanning with the last values sent, allow to clear results. - m_pScan->start(m_pScan->m_duration, m_pScan->m_scanCompleteCB); + m_pScan->onHostSync(); } #endif #if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) if(m_bleAdvertising != nullptr) { - // Restart advertisng, parameters should already be set. - m_bleAdvertising->start(); + m_bleAdvertising->onHostSync(); } #endif } diff --git a/src/NimBLEScan.cpp b/src/NimBLEScan.cpp index d3ea532..63b8680 100644 --- a/src/NimBLEScan.cpp +++ b/src/NimBLEScan.cpp @@ -41,6 +41,7 @@ NimBLEScan::NimBLEScan() { m_ignoreResults = false; m_wantDuplicates = false; m_pTaskData = nullptr; + m_duration = BLE_HS_FOREVER; // make sure this is non-zero in the event of a host reset } @@ -378,12 +379,25 @@ void NimBLEScan::erase(const NimBLEAddress &address) { /** - * @brief If the host reset the scan will have stopped so we should set the flag as stopped. + * @brief Called when host reset, we set a flag to stop scanning until synced. */ void NimBLEScan::onHostReset() { + m_ignoreResults = true; } +/** + * @brief If the host reset and re-synced this is called. + * If the application was scanning indefinitely with a callback, restart it. + */ +void NimBLEScan::onHostSync() { + m_ignoreResults = false; + + if(m_duration == 0 && m_pAdvertisedDeviceCallbacks != nullptr) { + start(m_duration, m_scanCompleteCB); + } +} + /** * @brief Get the results of the scan. * @return NimBLEScanResults object. diff --git a/src/NimBLEScan.h b/src/NimBLEScan.h index b55cdf8..1f837a3 100644 --- a/src/NimBLEScan.h +++ b/src/NimBLEScan.h @@ -83,6 +83,7 @@ private: ~NimBLEScan(); static int handleGapEvent(ble_gap_event* event, void* arg); void onHostReset(); + void onHostSync(); NimBLEAdvertisedDeviceCallbacks* m_pAdvertisedDeviceCallbacks = nullptr; void (*m_scanCompleteCB)(NimBLEScanResults scanResults);