@@ -362,7 +362,6 @@ Gap::Gap(
362362 _central_privacy_configuration (default_central_privacy_configuration),
363363#endif // BLE_ROLE_OBSERVER
364364#endif // BLE_FEATURE_PRIVACY
365- _scan_enabled (false ),
366365 _advertising_timeout (),
367366 _scan_timeout(),
368367 _user_manage_connection_parameter_requests(false )
@@ -483,34 +482,36 @@ ble_error_t Gap::getRandomAddressType(
483482 }
484483}
485484
486-
487485#if BLE_ROLE_OBSERVER
488486ble_error_t Gap::stopScan ()
489487{
490488 ble_error_t err;
491489
492- if ((!_scan_enabled && !_scan_pending) || _scan_pending || _initiating) {
490+ if (_initiating) {
493491 return BLE_STACK_BUSY;
494492 }
495493
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 ;
501495
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;
504507 }
505508
506- _scan_pending = true ;
507509 _scan_timeout.detach ();
508510
509511 return BLE_ERROR_NONE;
510512}
511513#endif
512514
513-
514515#if BLE_ROLE_CENTRAL
515516ble_error_t Gap::connect (
516517 peer_address_type_t peerAddressType,
@@ -582,7 +583,7 @@ ble_error_t Gap::connect(
582583 return BLE_ERROR_INVALID_PARAM;
583584 }
584585
585- if (!_scan_enabled ) {
586+ if (_scan_state == ScanState::idle ) {
586587 if (!_active_sets.get (LEGACY_ADVERTISING_HANDLE) &&
587588 !_pending_sets.get (LEGACY_ADVERTISING_HANDLE)
588589 ) {
@@ -593,11 +594,7 @@ ble_error_t Gap::connect(
593594 }
594595#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
595596 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 ));
601598 if (ret != BLE_ERROR_NONE) {
602599 _connect_to_host_resolved_address_state = ConnectionToHostResolvedAddressState::idle;
603600 }
@@ -621,7 +618,7 @@ ble_error_t Gap::connect(
621618 }
622619 } else {
623620 // set the correct mac address before starting scanning.
624- if (!_scan_enabled ) {
621+ if (_scan_state == ScanState::idle ) {
625622 _pal_gap.set_random_address (*address);
626623 } else {
627624 // ensure scan is stopped.
@@ -1065,6 +1062,8 @@ ble_error_t Gap::reset()
10651062
10661063 _event_handler = nullptr ;
10671064 _initiating = false ;
1065+ _scan_state = ScanState::idle;
1066+ _scan_requested = false ;
10681067#if BLE_FEATURE_PRIVACY
10691068 _privacy_initialization_pending = false ;
10701069#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
@@ -1148,51 +1147,56 @@ Gap::GapShutdownCallbackChain_t &Gap::onShutdown()
11481147#if BLE_ROLE_OBSERVER
11491148void Gap::on_scan_started (bool success)
11501149{
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+ }
11531161}
11541162
11551163void Gap::on_scan_stopped (bool success)
11561164{
1157- _scan_pending = false ;
1158- _scan_enabled = false ;
1159-
11601165 if (!success) {
1161- _scan_address_refresh = false ;
11621166 return ;
11631167 }
11641168
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;
11721170
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+ }
11771183
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);
11841188
1185- if (_scan_address_refresh && !wait_for_advertising_stop) {
1186- #if BLE_ROLE_BROADCASTER
11871189 if (restart_advertising) {
1190+ /* this will refresh the address and we can continue scan if we want as well */
11881191 _address_refresh_sets.clear (LEGACY_ADVERTISING_HANDLE);
11891192 startAdvertising (LEGACY_ADVERTISING_HANDLE);
11901193 _adv_started_from_refresh.set (LEGACY_ADVERTISING_HANDLE);
11911194 }
1195+ }
11921196#endif // BLE_ROLE_BROADCASTER
11931197
1194- _scan_address_refresh = false ;
1195- startScan ();
1198+ if (_scan_requested) {
1199+ initiate_scan ();
11961200 }
11971201}
11981202#endif // BLE_ROLE_OBSERVER
@@ -1227,13 +1231,12 @@ void Gap::connecting_to_host_resolved_address_failed(bool inform_user)
12271231#if BLE_ROLE_OBSERVER
12281232void Gap::on_scan_timeout ()
12291233{
1230- if (!_scan_enabled ) {
1234+ if (_scan_state == ScanState::idle ) {
12311235 return ;
12321236 }
12331237
1234- _scan_address_refresh = false ;
1235- _scan_enabled = false ;
1236- _scan_pending = false ;
1238+ _scan_state = ScanState::idle;
1239+ _scan_requested = false ;
12371240
12381241 if (_event_handler) {
12391242 _event_handler->onScanTimeout (ScanTimeoutEvent ());
@@ -1244,12 +1247,11 @@ void Gap::on_scan_timeout()
12441247#if BLE_ROLE_OBSERVER
12451248void Gap::process_legacy_scan_timeout ()
12461249{
1247- if (!_scan_enabled ) {
1250+ if (_scan_state == ScanState::idle ) {
12481251 return ;
12491252 }
12501253
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 ();
12531255
12541256 if (_event_handler) {
12551257 _event_handler->onScanTimeout (ScanTimeoutEvent ());
@@ -2064,7 +2066,7 @@ ble_error_t Gap::startAdvertising(
20642066 }
20652067
20662068 // 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)) {
20682070 _pal_gap.set_random_address (*random_address);
20692071 }
20702072
@@ -2824,18 +2826,15 @@ void Gap::on_legacy_advertising_stopped()
28242826 _active_sets.clear (LEGACY_ADVERTISING_HANDLE);
28252827 _pending_sets.clear (LEGACY_ADVERTISING_HANDLE);
28262828
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-
28302829 // 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) ) {
28322831 _address_refresh_sets.clear (LEGACY_ADVERTISING_HANDLE);
28332832 startAdvertising (LEGACY_ADVERTISING_HANDLE);
28342833 _adv_started_from_refresh.set (LEGACY_ADVERTISING_HANDLE);
28352834#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 ();
28392838 }
28402839#endif // BLE_ROLE_OBSERVER
28412840 } else if (_event_handler) {
@@ -3025,26 +3024,46 @@ ble_error_t Gap::startScan(
30253024 scan_period_t period
30263025)
30273026{
3028- if (_scan_pending || _scan_address_refresh || _initiating) {
3027+ if (_initiating) {
30293028 return BLE_STACK_BUSY;
30303029 }
30313030
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+ {
30323050 const address_t *address = get_random_address (controller_operation_t ::scanning);
30333051 if (!address) {
30343052 return BLE_ERROR_INVALID_STATE;
30353053 }
3054+
30363055#if BLE_FEATURE_EXTENDED_ADVERTISING
30373056 if (is_extended_advertising_available ()) {
30383057 // set the correct mac address before starting scanning.
3039- if (!_scan_enabled ) {
3058+ if (_scan_state == ScanState::idle ) {
30403059 _pal_gap.set_random_address (*address);
30413060 }
30423061
30433062 ble_error_t err = _pal_gap.extended_scan_enable (
30443063 /* enable */ true ,
3045- filtering ,
3046- duration .value (),
3047- period .value ()
3064+ _scan_requested_filtering ,
3065+ _scan_requested_duration .value (),
3066+ _scan_requested_period .value ()
30483067 );
30493068
30503069 if (err) {
@@ -3053,49 +3072,40 @@ ble_error_t Gap::startScan(
30533072 } else
30543073#endif // BLE_FEATURE_EXTENDED_ADVERTISING
30553074 {
3056- if (period .value () != 0 ) {
3075+ if (_scan_requested_period .value () != 0 ) {
30573076 return BLE_ERROR_INVALID_PARAM;
30583077 }
30593078
30603079 // update the address if no scan or advertising is running
30613080 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)) {
30633082 _pal_gap.set_random_address (*address);
30643083 }
30653084
30663085 ble_error_t err = _pal_gap.scan_enable (
30673086 true ,
3068- filtering == duplicates_filter_t ::DISABLE ? false : true
3087+ _scan_requested_filtering == duplicates_filter_t ::DISABLE ? false : true
30693088 );
30703089
30713090 if (err) {
30723091 return err;
30733092 }
30743093
30753094 _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 ()
30813099 );
30823100 }
30833101 }
30843102
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;
30933104
30943105 return BLE_ERROR_NONE;
30953106}
30963107#endif
30973108
3098-
30993109#if BLE_ROLE_OBSERVER
31003110#if BLE_FEATURE_PERIODIC_ADVERTISING
31013111ble_error_t Gap::createSync (
@@ -3358,15 +3368,18 @@ void Gap::on_private_address_generated(bool connectable)
33583368#endif // BLE_ROLE_BROADCASTER
33593369
33603370#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+ }
33683382 }
3369- _scan_address_refresh = true ;
33703383 }
33713384#endif // BLE_ROLE_OBSERVER
33723385}
@@ -3449,7 +3462,7 @@ bool Gap::is_advertising() const
34493462}
34503463
34513464bool Gap::is_radio_active () const {
3452- return _initiating || _scan_enabled || _scan_pending || is_advertising ();
3465+ return _initiating || (_scan_state != ScanState::idle) || is_advertising ();
34533466}
34543467
34553468void Gap::update_advertising_set_connectable_attribute (
@@ -3514,7 +3527,7 @@ const address_t *Gap::get_random_address(controller_operation_t operation, size_
35143527 // it to the address to use to determine if the address is correct or not.
35153528 if (_initiating) {
35163529 address_in_use = &resolvable_address;
3517- } else if (_scan_enabled || _scan_pending ) {
3530+ } else if (_scan_state != ScanState::idle ) {
35183531 if (central_non_resolvable) {
35193532 address_in_use = &non_resolvable_address;
35203533 } else {
0 commit comments