@@ -373,6 +373,11 @@ Gap::Gap(
373
373
, _scan_parameters_set(false )
374
374
#endif // BLE_ROLE_OBSERVER
375
375
{
376
+ #if BLE_FEATURE_EXTENDED_ADVERTISING
377
+ _advertising_enable_queue.handle = ble::INVALID_ADVERTISING_HANDLE;
378
+ _advertising_enable_queue.next = nullptr ;
379
+ _advertising_enable_pending = false ;
380
+ #endif // BLE_FEATURE_EXTENDED_ADVERTISING
376
381
_pal_gap.initialize ();
377
382
378
383
_pal_gap.when_gap_event_received (
@@ -1214,6 +1219,21 @@ ble_error_t Gap::reset()
1214
1219
_initiating = false ;
1215
1220
set_scan_state (ScanState::idle);
1216
1221
_scan_requested = false ;
1222
+
1223
+ #if BLE_FEATURE_EXTENDED_ADVERTISING
1224
+ /* reset pending advertising sets */
1225
+ AdvertisingEnableStackNode_t* next = _advertising_enable_queue.next ;
1226
+ _advertising_enable_queue.next = nullptr ;
1227
+ _advertising_enable_queue.handle = ble::INVALID_ADVERTISING_HANDLE;
1228
+ _advertising_enable_pending = false ;
1229
+ /* free any allocated nodes */
1230
+ while (next) {
1231
+ AdvertisingEnableStackNode_t* node_to_free = next;
1232
+ AdvertisingEnableStackNode_t* next = next->next ;
1233
+ delete node_to_free;
1234
+ }
1235
+ #endif // BLE_FEATURE_EXTENDED_ADVERTISING
1236
+
1217
1237
#if BLE_FEATURE_PRIVACY
1218
1238
_privacy_initialization_pending = false ;
1219
1239
#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
@@ -1268,6 +1288,7 @@ ble_error_t Gap::reset()
1268
1288
#endif // BLE_FEATURE_EXTENDED_ADVERTISING
1269
1289
1270
1290
_active_sets.clear ();
1291
+ _pending_stop_sets.clear ();
1271
1292
_pending_sets.clear ();
1272
1293
_address_refresh_sets.clear ();
1273
1294
_interruptible_sets.clear ();
@@ -2413,23 +2434,10 @@ ble_error_t Gap::startAdvertising(
2413
2434
_pal_gap.set_advertising_set_random_address (handle, *random_address);
2414
2435
}
2415
2436
2416
- error = _pal_gap.extended_advertising_enable (
2417
- /* enable */ true ,
2418
- /* number of advertising sets */ 1 ,
2419
- &handle,
2420
- maxDuration.storage (),
2421
- &maxEvents
2422
- );
2423
-
2424
- if (error) {
2425
- return error;
2426
- }
2427
-
2428
- if (maxDuration.value () || maxEvents) {
2429
- _interruptible_sets.clear (handle);
2430
- } else {
2431
- _interruptible_sets.set (handle);
2432
- }
2437
+ _event_queue.post ([this , handle, maxDuration, maxEvents] {
2438
+ start_advertising_enable (handle, maxDuration, maxEvents);
2439
+ evaluate_advertising_enable_queue ();
2440
+ });
2433
2441
2434
2442
} else
2435
2443
#endif // BLE_FEATURE_EXTENDED_ADVERTISING
@@ -2469,6 +2477,93 @@ ble_error_t Gap::startAdvertising(
2469
2477
}
2470
2478
#endif
2471
2479
2480
+ #if BLE_FEATURE_EXTENDED_ADVERTISING
2481
+ void Gap::start_advertising_enable (
2482
+ advertising_handle_t handle,
2483
+ adv_duration_t maxDuration,
2484
+ uint8_t maxEvents
2485
+ )
2486
+ {
2487
+ /* remember the parameters that will be enabled when the last command completes */
2488
+ if (_advertising_enable_queue.handle == ble::INVALID_ADVERTISING_HANDLE) {
2489
+ /* special case when there is only one pending */
2490
+ _advertising_enable_queue.handle = handle;
2491
+ _advertising_enable_queue.max_duration = maxDuration;
2492
+ _advertising_enable_queue.max_events = maxEvents;
2493
+ _advertising_enable_queue.next = nullptr ;
2494
+ } else {
2495
+ AdvertisingEnableStackNode_t** next = &_advertising_enable_queue.next ;
2496
+ /* move down the queue until we're over a nullptr */
2497
+ if (*next) {
2498
+ while ((*next)->next ) {
2499
+ next = &((*next)->next );
2500
+ }
2501
+ next = &(*next)->next ;
2502
+ }
2503
+ *next = new AdvertisingEnableStackNode_t ();
2504
+ if (!*next) {
2505
+ tr_error (" Out of memory creating pending advertising enable node for handle %d" , handle);
2506
+ return ;
2507
+ }
2508
+ (*next)->handle = handle;
2509
+ (*next)->max_duration = maxDuration;
2510
+ (*next)->max_events = maxEvents;
2511
+ (*next)->next = nullptr ;
2512
+ }
2513
+ }
2514
+
2515
+ void Gap::evaluate_advertising_enable_queue ()
2516
+ {
2517
+ tr_info (" Evaluating pending advertising sets to be started" );
2518
+ if (_advertising_enable_pending) {
2519
+ return ;
2520
+ }
2521
+
2522
+ if (_advertising_enable_queue.handle == ble::INVALID_ADVERTISING_HANDLE) {
2523
+ /* no set pending to be enabled*/
2524
+ return ;
2525
+ }
2526
+
2527
+ ble_error_t error = _pal_gap.extended_advertising_enable (
2528
+ /* enable */ true ,
2529
+ /* number of advertising sets */ 1 ,
2530
+ &_advertising_enable_queue.handle ,
2531
+ _advertising_enable_queue.max_duration .storage (),
2532
+ &_advertising_enable_queue.max_events
2533
+ );
2534
+
2535
+ if (error) {
2536
+ tr_error (" Failed to start advertising set with error: %s" , to_string (error));
2537
+ if (_event_handler) {
2538
+ _event_handler->onAdvertisingCommandFailed (
2539
+ AdvertisingCommandFailedEvent (
2540
+ _advertising_enable_queue.handle ,
2541
+ error
2542
+ )
2543
+ );
2544
+ }
2545
+ } else {
2546
+ _advertising_enable_pending = true ;
2547
+ if (_advertising_enable_queue.max_duration .value () || _advertising_enable_queue.max_events ) {
2548
+ _interruptible_sets.clear (_advertising_enable_queue.handle );
2549
+ } else {
2550
+ _interruptible_sets.set (_advertising_enable_queue.handle );
2551
+ }
2552
+ }
2553
+
2554
+ /* if there's anything else waiting, queue it up, otherwise mark the head node handle as invalid */
2555
+ if (_advertising_enable_queue.next ) {
2556
+ AdvertisingEnableStackNode_t* next = _advertising_enable_queue.next ;
2557
+ _advertising_enable_queue.handle = next->handle ;
2558
+ _advertising_enable_queue.max_duration = next->max_duration ;
2559
+ _advertising_enable_queue.max_events = next->max_events ;
2560
+ _advertising_enable_queue.next = next->next ;
2561
+ delete next;
2562
+ } else {
2563
+ _advertising_enable_queue.handle = ble::INVALID_ADVERTISING_HANDLE;
2564
+ }
2565
+ }
2566
+ #endif // BLE_FEATURE_EXTENDED_ADVERTISING
2472
2567
2473
2568
#if BLE_ROLE_BROADCASTER
2474
2569
ble_error_t Gap::stopAdvertising (advertising_handle_t handle)
@@ -2499,17 +2594,23 @@ ble_error_t Gap::stopAdvertising(advertising_handle_t handle)
2499
2594
2500
2595
#if BLE_FEATURE_EXTENDED_ADVERTISING
2501
2596
if (is_extended_advertising_available ()) {
2502
- status = _pal_gap.extended_advertising_enable (
2503
- /* enable ? */ false ,
2504
- /* number of advertising sets */ 1 ,
2505
- &handle,
2506
- nullptr ,
2507
- nullptr
2508
- );
2597
+ _event_queue.post ([this , handle] {
2598
+ /* if any already pending to stop delay the command execution */
2599
+ bool delay = false ;
2600
+ for (size_t i = 0 ; i < BLE_GAP_MAX_ADVERTISING_SETS; ++i) {
2601
+ if (_pending_stop_sets.get (i)) {
2602
+ delay = true ;
2603
+ break ;
2604
+ }
2605
+ }
2606
+ _pending_stop_sets.set (handle);
2607
+ if (!delay) {
2608
+ evaluate_advertising_stop ();
2609
+ }
2610
+ });
2611
+
2612
+ return BLE_ERROR_NONE;
2509
2613
2510
- if (status) {
2511
- return status;
2512
- }
2513
2614
} else
2514
2615
#endif // BLE_FEATURE_EXTENDED_ADVERTISING
2515
2616
{
@@ -2531,6 +2632,36 @@ ble_error_t Gap::stopAdvertising(advertising_handle_t handle)
2531
2632
2532
2633
return status;
2533
2634
}
2635
+
2636
+ #if BLE_FEATURE_EXTENDED_ADVERTISING
2637
+ void Gap::evaluate_advertising_stop ()
2638
+ {
2639
+ // refresh for address for all connectable advertising sets
2640
+ for (size_t i = 0 ; i < BLE_GAP_MAX_ADVERTISING_SETS; ++i) {
2641
+ if (_pending_stop_sets.get (i)) {
2642
+ ble_error_t status = _pal_gap.extended_advertising_enable (
2643
+ /* enable */ false ,
2644
+ /* number of advertising sets */ 1 ,
2645
+ (advertising_handle_t *)&i,
2646
+ nullptr ,
2647
+ nullptr
2648
+ );
2649
+ if (status) {
2650
+ _event_handler->onAdvertisingCommandFailed (
2651
+ AdvertisingCommandFailedEvent (
2652
+ (advertising_handle_t )i,
2653
+ status
2654
+ )
2655
+ );
2656
+ tr_error (" Could not stop advertising set %u, error: %s" , i, to_string (status));
2657
+ }
2658
+ break ;
2659
+ }
2660
+ }
2661
+
2662
+ }
2663
+ #endif // BLE_FEATURE_EXTENDED_ADVERTISING
2664
+
2534
2665
#endif
2535
2666
2536
2667
@@ -3354,6 +3485,11 @@ void Gap::on_advertising_set_started(const mbed::Span<const uint8_t>& handles)
3354
3485
{
3355
3486
tr_info (" Advertising set started - handles=%s" , mbed_trace_array (handles.data (), handles.size ()));
3356
3487
3488
+ _event_queue.post ([this ] {
3489
+ _advertising_enable_pending = false ;
3490
+ evaluate_advertising_enable_queue ();
3491
+ });
3492
+
3357
3493
for (const auto &handle : handles) {
3358
3494
_active_sets.set (handle);
3359
3495
_pending_sets.clear (handle);
@@ -3394,6 +3530,11 @@ void Gap::on_advertising_set_terminated(
3394
3530
return ;
3395
3531
}
3396
3532
3533
+ _event_queue.post ([this , advertising_handle] {
3534
+ _pending_stop_sets.clear (advertising_handle);
3535
+ evaluate_advertising_stop ();
3536
+ });
3537
+
3397
3538
if (!_event_handler) {
3398
3539
return ;
3399
3540
}
0 commit comments