Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions src/NimBLEDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -728,7 +728,7 @@ bool NimBLEDevice::onWhiteList(const NimBLEAddress& address) {
bool NimBLEDevice::whiteListAdd(const NimBLEAddress& address) {
if (!NimBLEDevice::onWhiteList(address)) {
m_whiteList.push_back(address);
int rc = ble_gap_wl_set(reinterpret_cast<ble_addr_t*>(&m_whiteList[0]), m_whiteList.size());
int rc = ble_gap_wl_set(reinterpret_cast<ble_addr_t*>(m_whiteList.data()), m_whiteList.size());
if (rc != 0) {
NIMBLE_LOGE(LOG_TAG, "Failed adding to whitelist rc=%d", rc);
m_whiteList.pop_back();
Expand All @@ -748,14 +748,18 @@ bool NimBLEDevice::whiteListRemove(const NimBLEAddress& address) {
for (auto it = m_whiteList.begin(); it < m_whiteList.end(); ++it) {
if (*it == address) {
m_whiteList.erase(it);
int rc = ble_gap_wl_set(reinterpret_cast<ble_addr_t*>(&m_whiteList[0]), m_whiteList.size());
int rc = ble_gap_wl_set(reinterpret_cast<ble_addr_t*>(m_whiteList.data()), m_whiteList.size());
if (rc != 0) {
m_whiteList.push_back(address);
NIMBLE_LOGE(LOG_TAG, "Failed removing from whitelist rc=%d", rc);
return false;
}

std::vector<NimBLEAddress>(m_whiteList).swap(m_whiteList);
break; // `it` was invalidated by erase() and its buffer freed by the
// swap above; continuing would iterate a dangling iterator.
// Duplicates are impossible (whiteListAdd checks onWhiteList),
// so a single match is total.
}
}

Expand Down Expand Up @@ -1027,6 +1031,11 @@ bool NimBLEDevice::deinit(bool clearAll) {
if (m_initialized) {
rc = nimble_port_stop();
if (rc == 0) {
# if MYNEWT_VAL(BLE_ROLE_OBSERVER)
if (NimBLEDevice::m_pScan != nullptr) {
NimBLEDevice::m_pScan->onHostDeinit();
}
# endif
nimble_port_deinit();
# ifndef USING_NIMBLE_ARDUINO_HEADERS
# if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
Expand All @@ -1038,6 +1047,9 @@ bool NimBLEDevice::deinit(bool clearAll) {
# endif
m_initialized = false;
m_synced = false;
} else {
NIMBLE_LOGE(LOG_TAG, "nimble_port_stop() failed with error: %d", rc);
return false;
}
}

Expand Down
41 changes: 35 additions & 6 deletions src/NimBLEScan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,15 +84,17 @@ NimBLEScan::NimBLEScan()
},
m_pTaskData{nullptr},
m_maxResults{0xFF} {
ble_npl_callout_init(&m_srTimer, nimble_port_get_dflt_eventq(), NimBLEScan::srTimerCb, nullptr);
ble_npl_time_ms_to_ticks(DEFAULT_SCAN_RESP_TIMEOUT_MS, &m_srTimeoutTicks);
} // NimBLEScan::NimBLEScan

/**
* @brief Scan destructor, release any allocated resources.
*/
NimBLEScan::~NimBLEScan() {
ble_npl_callout_deinit(&m_srTimer);
if (m_srTimerInitialized) {
ble_npl_callout_deinit(&m_srTimer);
m_srTimerInitialized = false;
}

for (const auto& dev : m_scanResults.m_deviceVec) {
delete dev;
Expand Down Expand Up @@ -178,7 +180,9 @@ void NimBLEScan::removeWaitingDevice(NimBLEAdvertisedDevice* pDev) {
void NimBLEScan::clearWaitingList() {
// Stop the timer and remove any pending timeout events since we're clearing
// the list and won't be processing any more timeouts for these devices
ble_npl_callout_stop(&m_srTimer);
if (m_srTimerInitialized) {
ble_npl_callout_stop(&m_srTimer);
}
ble_npl_hw_enter_critical();
NimBLEAdvertisedDevice* current = m_pWaitingListHead;
while (current != nullptr) {
Expand All @@ -196,10 +200,19 @@ void NimBLEScan::clearWaitingList() {
*/
void NimBLEScan::resetWaitingTimer() {
if (m_srTimeoutTicks == 0 || m_pWaitingListHead == nullptr) {
ble_npl_callout_stop(&m_srTimer);
if (m_srTimerInitialized) {
ble_npl_callout_stop(&m_srTimer);
}
return;
}

if (!m_srTimerInitialized) {
m_srTimerInitialized = ble_npl_callout_init(&m_srTimer, nimble_port_get_dflt_eventq(), NimBLEScan::srTimerCb, nullptr) == 0;
if (!m_srTimerInitialized) {
return;
}
}

ble_npl_time_t now = ble_npl_time_get();
ble_npl_time_t elapsed = now - m_pWaitingListHead->m_time;
ble_npl_time_t nextTime = elapsed >= m_srTimeoutTicks ? 1 : m_srTimeoutTicks - elapsed;
Expand Down Expand Up @@ -346,7 +359,9 @@ int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) {
}

case BLE_GAP_EVENT_DISC_COMPLETE: {
ble_npl_callout_stop(&pScan->m_srTimer);
if (pScan->m_srTimerInitialized) {
ble_npl_callout_stop(&pScan->m_srTimer);
}

// If we have any scannable devices that haven't received a scan response,
// we should trigger the callback with whatever data we have since the scan is complete
Expand Down Expand Up @@ -392,7 +407,9 @@ int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) {
*/
void NimBLEScan::setScanResponseTimeout(uint32_t timeoutMs) {
if (timeoutMs == 0) {
ble_npl_callout_stop(&m_srTimer);
if (m_srTimerInitialized) {
ble_npl_callout_stop(&m_srTimer);
}
m_srTimeoutTicks = 0;
return;
}
Expand Down Expand Up @@ -673,6 +690,18 @@ void NimBLEScan::onHostSync() {
m_pScanCallbacks->onScanEnd(m_scanResults, BLE_HS_ENOTSYNCED);
}

/**
* @brief Called before host deinit so callouts don't outlive the default event queue.
*/
void NimBLEScan::onHostDeinit() {
clearWaitingList();

if (m_srTimerInitialized) {
ble_npl_callout_deinit(&m_srTimer);
m_srTimerInitialized = false;
}
Comment thread
h2zero marked this conversation as resolved.
}

/**
* @brief Start scanning and block until scanning has been completed.
* @param [in] duration The duration in milliseconds for which to scan.
Expand Down
2 changes: 2 additions & 0 deletions src/NimBLEScan.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ class NimBLEScan {
~NimBLEScan();
static int handleGapEvent(ble_gap_event* event, void* arg);
void onHostSync();
void onHostDeinit();
static void srTimerCb(ble_npl_event* event);

// Linked list helpers for devices awaiting scan responses
Expand All @@ -194,6 +195,7 @@ class NimBLEScan {
NimBLEScanResults m_scanResults;
NimBLEUtils::TaskData* m_pTaskData;
ble_npl_callout m_srTimer{};
bool m_srTimerInitialized{false};
ble_npl_time_t m_srTimeoutTicks{};
uint8_t m_maxResults;
NimBLEAdvertisedDevice* m_pWaitingListHead{}; // head of linked list for devices awaiting scan responses
Expand Down