@@ -73,15 +73,17 @@ NimBLEScan::NimBLEScan()
7373 m_scanParams{0 , 0 , BLE_HCI_SCAN_FILT_NO_WL , 0 , 1 , 1 },
7474 m_pTaskData{nullptr },
7575 m_maxResults{0xFF } {
76- ble_npl_callout_init (&m_srTimer, nimble_port_get_dflt_eventq (), NimBLEScan::srTimerCb, nullptr );
7776 ble_npl_time_ms_to_ticks (DEFAULT_SCAN_RESP_TIMEOUT_MS , &m_srTimeoutTicks);
7877} // NimBLEScan::NimBLEScan
7978
8079/* *
8180 * @brief Scan destructor, release any allocated resources.
8281 */
8382NimBLEScan::~NimBLEScan () {
84- ble_npl_callout_deinit (&m_srTimer);
83+ if (m_srTimerInitialized) {
84+ ble_npl_callout_deinit (&m_srTimer);
85+ m_srTimerInitialized = false ;
86+ }
8587
8688 for (const auto & dev : m_scanResults.m_deviceVec ) {
8789 delete dev;
@@ -167,7 +169,9 @@ void NimBLEScan::removeWaitingDevice(NimBLEAdvertisedDevice* pDev) {
167169void NimBLEScan::clearWaitingList () {
168170 // Stop the timer and remove any pending timeout events since we're clearing
169171 // the list and won't be processing any more timeouts for these devices
170- ble_npl_callout_stop (&m_srTimer);
172+ if (m_srTimerInitialized) {
173+ ble_npl_callout_stop (&m_srTimer);
174+ }
171175 ble_npl_hw_enter_critical ();
172176 NimBLEAdvertisedDevice* current = m_pWaitingListHead;
173177 while (current != nullptr ) {
@@ -185,10 +189,19 @@ void NimBLEScan::clearWaitingList() {
185189 */
186190void NimBLEScan::resetWaitingTimer () {
187191 if (m_srTimeoutTicks == 0 || m_pWaitingListHead == nullptr ) {
188- ble_npl_callout_stop (&m_srTimer);
192+ if (m_srTimerInitialized) {
193+ ble_npl_callout_stop (&m_srTimer);
194+ }
189195 return ;
190196 }
191197
198+ if (!m_srTimerInitialized) {
199+ m_srTimerInitialized = ble_npl_callout_init (&m_srTimer, nimble_port_get_dflt_eventq (), NimBLEScan::srTimerCb, nullptr ) == 0 ;
200+ if (!m_srTimerInitialized) {
201+ return ;
202+ }
203+ }
204+
192205 ble_npl_time_t now = ble_npl_time_get ();
193206 ble_npl_time_t elapsed = now - m_pWaitingListHead->m_time ;
194207 ble_npl_time_t nextTime = elapsed >= m_srTimeoutTicks ? 1 : m_srTimeoutTicks - elapsed;
@@ -335,7 +348,9 @@ int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) {
335348 }
336349
337350 case BLE_GAP_EVENT_DISC_COMPLETE : {
338- ble_npl_callout_stop (&pScan->m_srTimer );
351+ if (pScan->m_srTimerInitialized ) {
352+ ble_npl_callout_stop (&pScan->m_srTimer );
353+ }
339354
340355 // If we have any scannable devices that haven't received a scan response,
341356 // we should trigger the callback with whatever data we have since the scan is complete
@@ -381,7 +396,9 @@ int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) {
381396 */
382397void NimBLEScan::setScanResponseTimeout (uint32_t timeoutMs) {
383398 if (timeoutMs == 0 ) {
384- ble_npl_callout_stop (&m_srTimer);
399+ if (m_srTimerInitialized) {
400+ ble_npl_callout_stop (&m_srTimer);
401+ }
385402 m_srTimeoutTicks = 0 ;
386403 return ;
387404 }
@@ -662,6 +679,18 @@ void NimBLEScan::onHostSync() {
662679 m_pScanCallbacks->onScanEnd (m_scanResults, BLE_HS_ENOTSYNCED );
663680}
664681
682+ /* *
683+ * @brief Called before host deinit so callouts don't outlive the default event queue.
684+ */
685+ void NimBLEScan::onHostDeinit () {
686+ clearWaitingList ();
687+
688+ if (m_srTimerInitialized) {
689+ ble_npl_callout_deinit (&m_srTimer);
690+ m_srTimerInitialized = false ;
691+ }
692+ }
693+
665694/* *
666695 * @brief Start scanning and block until scanning has been completed.
667696 * @param [in] duration The duration in milliseconds for which to scan.
0 commit comments