22
22
# include " NimBLEDevice.h"
23
23
# include " NimBLELog.h"
24
24
25
+ # if defined(CONFIG_NIMBLE_CPP_IDF)
26
+ # include " nimble/nimble_port.h"
27
+ # else
28
+ # include " nimble/porting/nimble/include/nimble/nimble_port.h"
29
+ # endif
30
+
25
31
# include < string>
26
32
# include < climits>
27
33
34
+ # define SR_TIMEOUT CONFIG_NIMBLE_CPP_SCAN_RSP_TIMEOUT
35
+
28
36
static const char * LOG_TAG = " NimBLEScan" ;
29
37
static NimBLEScanCallbacks defaultScanCallbacks;
30
38
39
+ # if SR_TIMEOUT
40
+ static ble_npl_event dummySrTimerEvent;
41
+ static ble_gap_disc_desc dummyDesc{
42
+ .event_type = BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP, .length_data = 0 , .addr {0 }, .rssi = 127 , .data = nullptr , .direct_addr {0 }};
43
+
44
+ extern " C" void ble_gap_rx_adv_report (ble_gap_disc_desc* desc);
45
+
46
+ static void sendDummyScanResponse (ble_npl_event* ev) {
47
+ (void )ev;
48
+ ble_gap_rx_adv_report (&dummyDesc);
49
+ }
50
+
51
+ /* *
52
+ * @brief This will call the scan result callback when a scan response is not received
53
+ * and will delete the device from the vector when maxResults is 0.
54
+ */
55
+ void NimBLEScan::srTimerCb (ble_npl_event* event) {
56
+ NimBLEScan* pScan = (NimBLEScan*)ble_npl_event_get_arg (event);
57
+ ble_npl_time_t now = ble_npl_time_get ();
58
+ NimBLEAdvertisedDevice* curDev = nullptr ;
59
+ NimBLEAdvertisedDevice* nextDev = nullptr ;
60
+
61
+ for (auto & dev : pScan->m_scanResults .m_deviceVec ) {
62
+ if (dev->m_callbackSent < 2 && dev->isScannable ()) {
63
+ if (!curDev || (now - dev->m_time > now - curDev->m_time )) {
64
+ nextDev = curDev;
65
+ curDev = dev;
66
+ continue ;
67
+ }
68
+
69
+ if (!nextDev || now - dev->m_time > now - nextDev->m_time ) {
70
+ nextDev = dev;
71
+ }
72
+ }
73
+ }
74
+
75
+ if (curDev) {
76
+ memcpy (&dummyDesc.addr , curDev->getAddress ().getBase (), sizeof (dummyDesc.addr ));
77
+ NIMBLE_LOGI (LOG_TAG, " Scan response timeout for: %s" , curDev->getAddress ().toString ().c_str ());
78
+ ble_npl_eventq_put (nimble_port_get_dflt_eventq (), &dummySrTimerEvent);
79
+ }
80
+
81
+ // Restart timer if there are more devices waiting for scan responses.
82
+ if (nextDev) {
83
+ auto nextTime = now - nextDev->m_time ;
84
+ if (nextTime >= SR_TIMEOUT) {
85
+ nextTime = 1 ;
86
+ } else {
87
+ nextTime = SR_TIMEOUT - nextTime;
88
+ }
89
+ ble_npl_time_t ticks;
90
+ ble_npl_time_ms_to_ticks (nextTime, &ticks);
91
+ ble_npl_callout_reset (&pScan->m_srTimer , ticks);
92
+ }
93
+ }
94
+ # endif
95
+
31
96
/* *
32
97
* @brief Scan constructor.
33
98
*/
@@ -36,13 +101,22 @@ NimBLEScan::NimBLEScan()
36
101
// default interval + window, no whitelist scan filter,not limited scan, no scan response, filter_duplicates
37
102
m_scanParams{0 , 0 , BLE_HCI_SCAN_FILT_NO_WL, 0 , 1 , 1 },
38
103
m_pTaskData{nullptr },
39
- m_maxResults{0xFF } {}
104
+ m_maxResults{0xFF } {
105
+ # if SR_TIMEOUT
106
+ ble_npl_callout_init (&m_srTimer, nimble_port_get_dflt_eventq (), NimBLEScan::srTimerCb, this );
107
+ ble_npl_event_init (&dummySrTimerEvent, sendDummyScanResponse, NULL );
108
+ # endif
109
+ }
40
110
41
111
/* *
42
112
* @brief Scan destructor, release any allocated resources.
43
113
*/
44
114
NimBLEScan::~NimBLEScan () {
45
115
clearResults ();
116
+ # if SR_TIMEOUT
117
+ ble_npl_callout_deinit (&m_srTimer);
118
+ ble_npl_event_deinit (&dummySrTimerEvent);
119
+ # endif
46
120
}
47
121
48
122
/* *
@@ -109,6 +183,9 @@ int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) {
109
183
advertisedDevice = new NimBLEAdvertisedDevice (event, event_type);
110
184
pScan->m_scanResults .m_deviceVec .push_back (advertisedDevice);
111
185
NIMBLE_LOGI (LOG_TAG, " New advertiser: %s" , advertisedAddress.toString ().c_str ());
186
+ # if SR_TIMEOUT
187
+ advertisedDevice->m_time = ble_npl_time_get ();
188
+ # endif
112
189
} else {
113
190
advertisedDevice->update (event, event_type);
114
191
if (isLegacyAdv && event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) {
@@ -132,6 +209,13 @@ int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) {
132
209
advertisedDevice->m_callbackSent ++;
133
210
// got the scan response report the full data.
134
211
pScan->m_pScanCallbacks ->onResult (advertisedDevice);
212
+ # if SR_TIMEOUT
213
+ } else if (isLegacyAdv && !ble_npl_callout_is_active (&pScan->m_srTimer )) {
214
+ // Start the timer to wait for the scan response.
215
+ ble_npl_time_t ticks;
216
+ ble_npl_time_ms_to_ticks (SR_TIMEOUT, &ticks);
217
+ ble_npl_callout_reset (&pScan->m_srTimer , ticks);
218
+ # endif
135
219
}
136
220
137
221
// If not storing results and we have invoked the callback, delete the device.
@@ -144,13 +228,15 @@ int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) {
144
228
145
229
case BLE_GAP_EVENT_DISC_COMPLETE: {
146
230
NIMBLE_LOGD (LOG_TAG, " discovery complete; reason=%d" , event->disc_complete .reason );
231
+ # if SR_TIMEOUT
232
+ ble_npl_callout_stop (&pScan->m_srTimer );
233
+ # endif
234
+ pScan->m_pScanCallbacks ->onScanEnd (pScan->m_scanResults , event->disc_complete .reason );
147
235
148
236
if (pScan->m_maxResults == 0 ) {
149
237
pScan->clearResults ();
150
238
}
151
239
152
- pScan->m_pScanCallbacks ->onScanEnd (pScan->m_scanResults , event->disc_complete .reason );
153
-
154
240
if (pScan->m_pTaskData != nullptr ) {
155
241
NimBLEUtils::taskRelease (*pScan->m_pTaskData , event->disc_complete .reason );
156
242
}
@@ -379,6 +465,10 @@ bool NimBLEScan::stop() {
379
465
return false ;
380
466
}
381
467
468
+ # if SR_TIMEOUT
469
+ ble_npl_callout_stop (&m_srTimer);
470
+ # endif
471
+
382
472
if (m_maxResults == 0 ) {
383
473
clearResults ();
384
474
}
@@ -483,11 +573,11 @@ void NimBLEScan::clearResults() {
483
573
* @brief Dump the scan results to the log.
484
574
*/
485
575
void NimBLEScanResults::dump () const {
486
- #if CONFIG_NIMBLE_CPP_LOG_LEVEL >=3
576
+ # if CONFIG_NIMBLE_CPP_LOG_LEVEL >= 3
487
577
for (const auto & dev : m_deviceVec) {
488
578
NIMBLE_LOGI (LOG_TAG, " - %s" , dev->toString ().c_str ());
489
579
}
490
- #endif
580
+ # endif
491
581
} // dump
492
582
493
583
/* *
0 commit comments