@@ -362,7 +362,6 @@ Gap::Gap(
362
362
_central_privacy_configuration (default_central_privacy_configuration),
363
363
#endif // BLE_ROLE_OBSERVER
364
364
#endif // BLE_FEATURE_PRIVACY
365
- _scan_enabled (false ),
366
365
_advertising_timeout (),
367
366
_scan_timeout(),
368
367
_user_manage_connection_parameter_requests(false )
@@ -483,34 +482,36 @@ ble_error_t Gap::getRandomAddressType(
483
482
}
484
483
}
485
484
486
-
487
485
#if BLE_ROLE_OBSERVER
488
486
ble_error_t Gap::stopScan ()
489
487
{
490
488
ble_error_t err;
491
489
492
- if ((!_scan_enabled && !_scan_pending) || _scan_pending || _initiating) {
490
+ if (_initiating) {
493
491
return BLE_STACK_BUSY;
494
492
}
495
493
496
- if (is_extended_advertising_available ()) {
497
- err = _pal_gap.extended_scan_enable (false , duplicates_filter_t ::DISABLE, 0 , 0 );
498
- } else {
499
- err = _pal_gap.scan_enable (false , false );
500
- }
494
+ _scan_requested = false ;
501
495
502
- if (err) {
503
- return err;
496
+ if (_scan_state == ScanState::scan) {
497
+ if (is_extended_advertising_available ()) {
498
+ err = _pal_gap.extended_scan_enable (false , duplicates_filter_t ::DISABLE, 0 , 0 );
499
+ } else {
500
+ err = _pal_gap.scan_enable (false , false );
501
+ }
502
+
503
+ if (err) {
504
+ return err;
505
+ }
506
+ _scan_state = ScanState::pending_stop_scan;
504
507
}
505
508
506
- _scan_pending = true ;
507
509
_scan_timeout.detach ();
508
510
509
511
return BLE_ERROR_NONE;
510
512
}
511
513
#endif
512
514
513
-
514
515
#if BLE_ROLE_CENTRAL
515
516
ble_error_t Gap::connect (
516
517
peer_address_type_t peerAddressType,
@@ -582,7 +583,7 @@ ble_error_t Gap::connect(
582
583
return BLE_ERROR_INVALID_PARAM;
583
584
}
584
585
585
- if (!_scan_enabled ) {
586
+ if (_scan_state == ScanState::idle ) {
586
587
if (!_active_sets.get (LEGACY_ADVERTISING_HANDLE) &&
587
588
!_pending_sets.get (LEGACY_ADVERTISING_HANDLE)
588
589
) {
@@ -593,11 +594,7 @@ ble_error_t Gap::connect(
593
594
}
594
595
#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
595
596
if (_connect_to_host_resolved_address_state == ConnectionToHostResolvedAddressState::scan) {
596
- ret = startScan (
597
- scan_duration_t::forever (),
598
- duplicates_filter_t ::ENABLE,
599
- (scan_period_t )0
600
- );
597
+ ret = startScan (scan_duration_t::forever (), duplicates_filter_t ::ENABLE, scan_period_t (0 ));
601
598
if (ret != BLE_ERROR_NONE) {
602
599
_connect_to_host_resolved_address_state = ConnectionToHostResolvedAddressState::idle;
603
600
}
@@ -621,7 +618,7 @@ ble_error_t Gap::connect(
621
618
}
622
619
} else {
623
620
// set the correct mac address before starting scanning.
624
- if (!_scan_enabled ) {
621
+ if (_scan_state == ScanState::idle ) {
625
622
_pal_gap.set_random_address (*address);
626
623
} else {
627
624
// ensure scan is stopped.
@@ -1065,6 +1062,8 @@ ble_error_t Gap::reset()
1065
1062
1066
1063
_event_handler = nullptr ;
1067
1064
_initiating = false ;
1065
+ _scan_state = ScanState::idle;
1066
+ _scan_requested = false ;
1068
1067
#if BLE_FEATURE_PRIVACY
1069
1068
_privacy_initialization_pending = false ;
1070
1069
#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
@@ -1148,51 +1147,56 @@ Gap::GapShutdownCallbackChain_t &Gap::onShutdown()
1148
1147
#if BLE_ROLE_OBSERVER
1149
1148
void Gap::on_scan_started (bool success)
1150
1149
{
1151
- _scan_pending = false ;
1152
- _scan_enabled = success;
1150
+ MBED_ASSERT (_scan_state == ScanState::pending_scan);
1151
+
1152
+ if (success) {
1153
+ _scan_state = ScanState::scan;
1154
+ /* if no longer want the scan */
1155
+ if (!_scan_requested) {
1156
+ stopScan ();
1157
+ }
1158
+ } else {
1159
+ _scan_state = ScanState::idle;
1160
+ }
1153
1161
}
1154
1162
1155
1163
void Gap::on_scan_stopped (bool success)
1156
1164
{
1157
- _scan_pending = false ;
1158
- _scan_enabled = false ;
1159
-
1160
1165
if (!success) {
1161
- _scan_address_refresh = false ;
1162
1166
return ;
1163
1167
}
1164
1168
1165
- // The address is refreshed only if there's no other pending request to refresh
1166
- // the main address
1167
-
1168
- bool wait_for_advertising_stop =
1169
- _address_refresh_sets.get (LEGACY_ADVERTISING_HANDLE) &&
1170
- _active_sets.get (LEGACY_ADVERTISING_HANDLE) &&
1171
- _pending_sets.get (LEGACY_ADVERTISING_HANDLE);
1169
+ _scan_state = ScanState::idle;
1172
1170
1173
- bool restart_advertising =
1174
- !_active_sets.get (LEGACY_ADVERTISING_HANDLE) &&
1175
- !_pending_sets.get (LEGACY_ADVERTISING_HANDLE) &&
1176
- _address_refresh_sets.get (LEGACY_ADVERTISING_HANDLE);
1171
+ #if BLE_ROLE_BROADCASTER
1172
+ /* with legacy advertising we might need to wait for scanning and advertising to both stop */
1173
+ if (!is_extended_advertising_available ()) {
1174
+ bool wait_for_advertising_stop =
1175
+ _address_refresh_sets.get (LEGACY_ADVERTISING_HANDLE) &&
1176
+ _active_sets.get (LEGACY_ADVERTISING_HANDLE) &&
1177
+ _pending_sets.get (LEGACY_ADVERTISING_HANDLE);
1178
+
1179
+ if (wait_for_advertising_stop) {
1180
+ /* return early if we're waiting for advertising to stop and do not restart scan even if requested */
1181
+ return ;
1182
+ }
1177
1183
1178
- #ifdef BLE_FEATURE_EXTENDED_ADVERTISING
1179
- if (is_extended_advertising_available ()) {
1180
- wait_for_advertising_stop = false ;
1181
- restart_advertising = false ;
1182
- }
1183
- #endif // BLE_FEATURE_EXTENDED_ADVERTISING
1184
+ bool restart_advertising =
1185
+ !_active_sets.get (LEGACY_ADVERTISING_HANDLE) &&
1186
+ !_pending_sets.get (LEGACY_ADVERTISING_HANDLE) &&
1187
+ _address_refresh_sets.get (LEGACY_ADVERTISING_HANDLE);
1184
1188
1185
- if (_scan_address_refresh && !wait_for_advertising_stop) {
1186
- #if BLE_ROLE_BROADCASTER
1187
1189
if (restart_advertising) {
1190
+ /* this will refresh the address and we can continue scan if we want as well */
1188
1191
_address_refresh_sets.clear (LEGACY_ADVERTISING_HANDLE);
1189
1192
startAdvertising (LEGACY_ADVERTISING_HANDLE);
1190
1193
_adv_started_from_refresh.set (LEGACY_ADVERTISING_HANDLE);
1191
1194
}
1195
+ }
1192
1196
#endif // BLE_ROLE_BROADCASTER
1193
1197
1194
- _scan_address_refresh = false ;
1195
- startScan ();
1198
+ if (_scan_requested) {
1199
+ initiate_scan ();
1196
1200
}
1197
1201
}
1198
1202
#endif // BLE_ROLE_OBSERVER
@@ -1227,13 +1231,12 @@ void Gap::connecting_to_host_resolved_address_failed(bool inform_user)
1227
1231
#if BLE_ROLE_OBSERVER
1228
1232
void Gap::on_scan_timeout ()
1229
1233
{
1230
- if (!_scan_enabled ) {
1234
+ if (_scan_state == ScanState::idle ) {
1231
1235
return ;
1232
1236
}
1233
1237
1234
- _scan_address_refresh = false ;
1235
- _scan_enabled = false ;
1236
- _scan_pending = false ;
1238
+ _scan_state = ScanState::idle;
1239
+ _scan_requested = false ;
1237
1240
1238
1241
if (_event_handler) {
1239
1242
_event_handler->onScanTimeout (ScanTimeoutEvent ());
@@ -1244,12 +1247,11 @@ void Gap::on_scan_timeout()
1244
1247
#if BLE_ROLE_OBSERVER
1245
1248
void Gap::process_legacy_scan_timeout ()
1246
1249
{
1247
- if (!_scan_enabled ) {
1250
+ if (_scan_state == ScanState::idle ) {
1248
1251
return ;
1249
1252
}
1250
1253
1251
- /* legacy scanning timed out is based on timer so we need to stop the scan manually */
1252
- _pal_gap.scan_enable (false , false );
1254
+ stopScan ();
1253
1255
1254
1256
if (_event_handler) {
1255
1257
_event_handler->onScanTimeout (ScanTimeoutEvent ());
@@ -2064,7 +2066,7 @@ ble_error_t Gap::startAdvertising(
2064
2066
}
2065
2067
2066
2068
// Address can be updated if the device is not scanning or advertising
2067
- if (!_scan_enabled && !_scan_pending && !_active_sets.get (LEGACY_ADVERTISING_HANDLE)) {
2069
+ if ((_scan_state == ScanState::idle) && !_active_sets.get (LEGACY_ADVERTISING_HANDLE)) {
2068
2070
_pal_gap.set_random_address (*random_address);
2069
2071
}
2070
2072
@@ -2824,18 +2826,15 @@ void Gap::on_legacy_advertising_stopped()
2824
2826
_active_sets.clear (LEGACY_ADVERTISING_HANDLE);
2825
2827
_pending_sets.clear (LEGACY_ADVERTISING_HANDLE);
2826
2828
2827
- bool wait_for_scan_stop = _scan_enabled && _scan_pending && _scan_address_refresh;
2828
- bool restart_scan = _scan_address_refresh && !_scan_enabled && !_scan_pending;
2829
-
2830
2829
// restart advertising if it was stopped to refresh the address
2831
- if (_address_refresh_sets.get (LEGACY_ADVERTISING_HANDLE) && !wait_for_scan_stop ) {
2830
+ if (_address_refresh_sets.get (LEGACY_ADVERTISING_HANDLE) && (_scan_state == ScanState::idle) ) {
2832
2831
_address_refresh_sets.clear (LEGACY_ADVERTISING_HANDLE);
2833
2832
startAdvertising (LEGACY_ADVERTISING_HANDLE);
2834
2833
_adv_started_from_refresh.set (LEGACY_ADVERTISING_HANDLE);
2835
2834
#if BLE_ROLE_OBSERVER
2836
- if (restart_scan) {
2837
- _scan_address_refresh = false ;
2838
- startScan ();
2835
+ /* scan is idle but we might still want to be scan since this could've been caused be address refresh */
2836
+ if (_scan_requested) {
2837
+ initiate_scan ();
2839
2838
}
2840
2839
#endif // BLE_ROLE_OBSERVER
2841
2840
} else if (_event_handler) {
@@ -3025,26 +3024,46 @@ ble_error_t Gap::startScan(
3025
3024
scan_period_t period
3026
3025
)
3027
3026
{
3028
- if (_scan_pending || _scan_address_refresh || _initiating) {
3027
+ if (_initiating) {
3029
3028
return BLE_STACK_BUSY;
3030
3029
}
3031
3030
3031
+ _scan_requested_duration = duration;
3032
+ _scan_requested_filtering = filtering;
3033
+ _scan_requested_period = period;
3034
+
3035
+ /* only initiate scan if we're not already busy */
3036
+ if (_scan_state == ScanState::idle) {
3037
+ ble_error_t ret = initiate_scan ();
3038
+ if (ret != BLE_ERROR_NONE) {
3039
+ return ret;
3040
+ }
3041
+ }
3042
+
3043
+ _scan_requested = true ;
3044
+
3045
+ return BLE_ERROR_NONE;
3046
+ }
3047
+
3048
+ ble_error_t Gap::initiate_scan ()
3049
+ {
3032
3050
const address_t *address = get_random_address (controller_operation_t ::scanning);
3033
3051
if (!address) {
3034
3052
return BLE_ERROR_INVALID_STATE;
3035
3053
}
3054
+
3036
3055
#if BLE_FEATURE_EXTENDED_ADVERTISING
3037
3056
if (is_extended_advertising_available ()) {
3038
3057
// set the correct mac address before starting scanning.
3039
- if (!_scan_enabled ) {
3058
+ if (_scan_state == ScanState::idle ) {
3040
3059
_pal_gap.set_random_address (*address);
3041
3060
}
3042
3061
3043
3062
ble_error_t err = _pal_gap.extended_scan_enable (
3044
3063
/* enable */ true ,
3045
- filtering ,
3046
- duration .value (),
3047
- period .value ()
3064
+ _scan_requested_filtering ,
3065
+ _scan_requested_duration .value (),
3066
+ _scan_requested_period .value ()
3048
3067
);
3049
3068
3050
3069
if (err) {
@@ -3053,49 +3072,40 @@ ble_error_t Gap::startScan(
3053
3072
} else
3054
3073
#endif // BLE_FEATURE_EXTENDED_ADVERTISING
3055
3074
{
3056
- if (period .value () != 0 ) {
3075
+ if (_scan_requested_period .value () != 0 ) {
3057
3076
return BLE_ERROR_INVALID_PARAM;
3058
3077
}
3059
3078
3060
3079
// update the address if no scan or advertising is running
3061
3080
auto adv_handle = LEGACY_ADVERTISING_HANDLE;
3062
- if (!_scan_enabled && !_active_sets.get (adv_handle) && !_pending_sets.get (adv_handle)) {
3081
+ if ((_scan_state == ScanState::idle) && !_active_sets.get (adv_handle) && !_pending_sets.get (adv_handle)) {
3063
3082
_pal_gap.set_random_address (*address);
3064
3083
}
3065
3084
3066
3085
ble_error_t err = _pal_gap.scan_enable (
3067
3086
true ,
3068
- filtering == duplicates_filter_t ::DISABLE ? false : true
3087
+ _scan_requested_filtering == duplicates_filter_t ::DISABLE ? false : true
3069
3088
);
3070
3089
3071
3090
if (err) {
3072
3091
return err;
3073
3092
}
3074
3093
3075
3094
_scan_timeout.detach ();
3076
- if (duration.value ()) {
3077
- _scan_timeout.attach ([this ]() {
3078
- _event_queue.post ([this ] { process_legacy_scan_timeout (); });
3079
- },
3080
- duration.valueChrono ()
3095
+ if (_scan_requested_duration.value ()) {
3096
+ _scan_timeout.attach (
3097
+ [this ]() { _event_queue.post ([this ] { process_legacy_scan_timeout (); }); },
3098
+ _scan_requested_duration.valueChrono ()
3081
3099
);
3082
3100
}
3083
3101
}
3084
3102
3085
- if (!_scan_enabled) {
3086
- _scan_pending = true ;
3087
- }
3088
- if (duration == scan_duration_t::forever () && period == scan_period_t (0 )) {
3089
- _scan_interruptible = true ;
3090
- } else {
3091
- _scan_interruptible = false ;
3092
- }
3103
+ _scan_state = ScanState::pending_scan;
3093
3104
3094
3105
return BLE_ERROR_NONE;
3095
3106
}
3096
3107
#endif
3097
3108
3098
-
3099
3109
#if BLE_ROLE_OBSERVER
3100
3110
#if BLE_FEATURE_PERIODIC_ADVERTISING
3101
3111
ble_error_t Gap::createSync (
@@ -3358,15 +3368,18 @@ void Gap::on_private_address_generated(bool connectable)
3358
3368
#endif // BLE_ROLE_BROADCASTER
3359
3369
3360
3370
#if BLE_ROLE_OBSERVER
3361
- // refresh scanning address
3362
- if (_scan_enabled && !_scan_pending && _scan_interruptible &&
3363
- !_central_privacy_configuration.use_non_resolvable_random_address == connectable
3364
- ) {
3365
- ble_error_t err = stopScan ();
3366
- if (err) {
3367
- return ;
3371
+ /* if we are connectable and we want to use a resolvable address we want to refresh it */
3372
+ if (!_central_privacy_configuration.use_non_resolvable_random_address == connectable) {
3373
+ /* if we're scanning we need to stop */
3374
+ if (_scan_state == ScanState::scan) {
3375
+ /* but we can only stop if we're scanning forever */
3376
+ if (_scan_requested_duration == scan_duration_t::forever () && _scan_requested_period == scan_period_t (0 )) {
3377
+ /* when the scan stops it will refresh the address and restart scan */
3378
+ ble_error_t err = stopScan ();
3379
+ /* but after we stop we actually want to continue */
3380
+ _scan_requested = true ;
3381
+ }
3368
3382
}
3369
- _scan_address_refresh = true ;
3370
3383
}
3371
3384
#endif // BLE_ROLE_OBSERVER
3372
3385
}
@@ -3449,7 +3462,7 @@ bool Gap::is_advertising() const
3449
3462
}
3450
3463
3451
3464
bool Gap::is_radio_active () const {
3452
- return _initiating || _scan_enabled || _scan_pending || is_advertising ();
3465
+ return _initiating || (_scan_state != ScanState::idle) || is_advertising ();
3453
3466
}
3454
3467
3455
3468
void Gap::update_advertising_set_connectable_attribute (
@@ -3514,7 +3527,7 @@ const address_t *Gap::get_random_address(controller_operation_t operation, size_
3514
3527
// it to the address to use to determine if the address is correct or not.
3515
3528
if (_initiating) {
3516
3529
address_in_use = &resolvable_address;
3517
- } else if (_scan_enabled || _scan_pending ) {
3530
+ } else if (_scan_state != ScanState::idle ) {
3518
3531
if (central_non_resolvable) {
3519
3532
address_in_use = &non_resolvable_address;
3520
3533
} else {
0 commit comments