@@ -374,9 +374,7 @@ Gap::Gap(
374
374
#endif // BLE_ROLE_OBSERVER
375
375
{
376
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 ;
377
+ _advertising_enable_command_params.number_of_handles = 0 ;
380
378
#endif // BLE_FEATURE_EXTENDED_ADVERTISING
381
379
_pal_gap.initialize ();
382
380
@@ -1214,7 +1212,6 @@ ble_error_t Gap::reset()
1214
1212
/* Notify that the instance is about to shut down */
1215
1213
// shutdownCallChain.call(this);
1216
1214
shutdownCallChain.clear ();
1217
- _event_queue.clear ();
1218
1215
1219
1216
_event_handler = nullptr ;
1220
1217
_initiating = false ;
@@ -1240,16 +1237,9 @@ ble_error_t Gap::reset()
1240
1237
_pal_gap.clear_advertising_sets ();
1241
1238
#if BLE_FEATURE_EXTENDED_ADVERTISING
1242
1239
/* reset pending advertising sets */
1243
- AdvertisingEnableStackNode_t* next = _advertising_enable_queue.next ;
1244
- _advertising_enable_queue.next = nullptr ;
1245
- _advertising_enable_queue.handle = ble::INVALID_ADVERTISING_HANDLE;
1246
- _advertising_enable_pending = false ;
1247
- /* free any allocated nodes */
1248
- while (next) {
1249
- AdvertisingEnableStackNode_t* node_to_free = next;
1250
- AdvertisingEnableStackNode_t* next = next->next ;
1251
- delete node_to_free;
1252
- }
1240
+ _advertising_enable_command_params.number_of_handles = 0 ;
1241
+ _process_enable_queue_pending = false ;
1242
+ _process_disable_queue_pending = false ;
1253
1243
_existing_sets.clear ();
1254
1244
#if BLE_FEATURE_PERIODIC_ADVERTISING
1255
1245
_active_periodic_sets.clear ();
@@ -2402,10 +2392,23 @@ ble_error_t Gap::startAdvertising(
2402
2392
_pal_gap.set_advertising_set_random_address (handle, *random_address);
2403
2393
}
2404
2394
2405
- _event_queue.post ([this , handle, maxDuration, maxEvents] {
2406
- queue_advertising_start (handle, maxDuration, maxEvents);
2407
- process_enable_queue ();
2408
- });
2395
+ /* remember the parameters that will be enabled when the last command completes */
2396
+ if (_advertising_enable_command_params.number_of_handles == BLE_GAP_HOST_MAX_OUTSTANDING_ADVERTISING_START_COMMANDS) {
2397
+ return BLE_ERROR_NO_MEM;
2398
+ }
2399
+
2400
+ const uint8_t i = _advertising_enable_command_params.number_of_handles ;
2401
+ _advertising_enable_command_params.handles [i] = handle;
2402
+ _advertising_enable_command_params.max_durations [i] = maxDuration;
2403
+ _advertising_enable_command_params.max_events [i] = maxEvents;
2404
+ _advertising_enable_command_params.number_of_handles ++;
2405
+
2406
+ /* we delay the processing to gather as many calls as we can in one go */
2407
+ if (!_process_enable_queue_pending) {
2408
+ _process_enable_queue_pending = _event_queue.post ([this ] {
2409
+ process_enable_queue ();
2410
+ });
2411
+ }
2409
2412
2410
2413
} else
2411
2414
#endif // BLE_FEATURE_EXTENDED_ADVERTISING
@@ -2448,90 +2451,51 @@ ble_error_t Gap::startAdvertising(
2448
2451
#endif
2449
2452
2450
2453
#if BLE_FEATURE_EXTENDED_ADVERTISING
2451
- void Gap::queue_advertising_start (
2452
- advertising_handle_t handle,
2453
- adv_duration_t maxDuration,
2454
- uint8_t maxEvents
2455
- )
2456
- {
2457
- /* remember the parameters that will be enabled when the last command completes */
2458
- if (_advertising_enable_queue.handle == ble::INVALID_ADVERTISING_HANDLE) {
2459
- /* special case when there is only one pending */
2460
- _advertising_enable_queue.handle = handle;
2461
- _advertising_enable_queue.max_duration = maxDuration;
2462
- _advertising_enable_queue.max_events = maxEvents;
2463
- _advertising_enable_queue.next = nullptr ;
2464
- } else {
2465
- AdvertisingEnableStackNode_t** next = &_advertising_enable_queue.next ;
2466
- /* move down the queue until we're over a nullptr */
2467
- if (*next) {
2468
- while ((*next)->next ) {
2469
- next = &((*next)->next );
2470
- }
2471
- next = &(*next)->next ;
2472
- }
2473
- *next = new (std::nothrow) AdvertisingEnableStackNode_t ();
2474
- if (!*next) {
2475
- tr_error (" Out of memory creating pending advertising enable node for handle %d" , handle);
2476
- return ;
2477
- }
2478
- (*next)->handle = handle;
2479
- (*next)->max_duration = maxDuration;
2480
- (*next)->max_events = maxEvents;
2481
- (*next)->next = nullptr ;
2482
- }
2483
- }
2484
-
2485
2454
void Gap::process_enable_queue ()
2486
2455
{
2487
2456
tr_info (" Evaluating pending advertising sets to be started" );
2488
- if (_advertising_enable_pending) {
2457
+ if (!_advertising_enable_command_params.number_of_handles ) {
2458
+ /* no set pending to be enabled */
2489
2459
return ;
2490
2460
}
2491
2461
2492
- if (_advertising_enable_queue.handle == ble::INVALID_ADVERTISING_HANDLE) {
2493
- /* no set pending to be enabled*/
2494
- return ;
2462
+ for (size_t i = 0 ; i < BLE_GAP_MAX_ADVERTISING_SETS; ++i) {
2463
+ if (_pending_sets.get (i)) {
2464
+ /* we have to wait until nothing is pending */
2465
+ return ;
2466
+ }
2495
2467
}
2496
2468
2497
2469
ble_error_t error = _pal_gap.extended_advertising_enable (
2498
2470
/* enable */ true ,
2499
- /* number of advertising sets */ 1 ,
2500
- &_advertising_enable_queue. handle ,
2501
- _advertising_enable_queue. max_duration . storage () ,
2502
- &_advertising_enable_queue .max_events
2471
+ _advertising_enable_command_params. number_of_handles ,
2472
+ _advertising_enable_command_params. handles ,
2473
+ ( uint16_t *)&_advertising_enable_command_params. max_durations ,
2474
+ _advertising_enable_command_params .max_events
2503
2475
);
2504
2476
2505
2477
if (error) {
2506
2478
tr_error (" Failed to start advertising set with error: %s" , to_string (error));
2507
2479
if (_event_handler) {
2508
- _event_handler-> onAdvertisingCommandFailed (
2509
- AdvertisingCommandFailedEvent (
2510
- _advertising_enable_queue. handle ,
2511
- error
2512
- )
2513
- );
2480
+ for ( size_t i = 0 ; i < _advertising_enable_command_params. number_of_handles ; ++i) {
2481
+ _pending_sets. clear (_advertising_enable_command_params. handles [i]);
2482
+ _event_handler-> onAdvertisingStart (
2483
+ AdvertisingStartEvent (_advertising_enable_command_params. handles [i], error)
2484
+ );
2485
+ }
2514
2486
}
2515
2487
} else {
2516
- _advertising_enable_pending = true ;
2517
- if (_advertising_enable_queue.max_duration .value () || _advertising_enable_queue.max_events ) {
2518
- _interruptible_sets.clear (_advertising_enable_queue.handle );
2519
- } else {
2520
- _interruptible_sets.set (_advertising_enable_queue.handle );
2488
+ for (size_t i = 0 ; i < _advertising_enable_command_params.number_of_handles ; ++i) {
2489
+ if (_advertising_enable_command_params.max_durations [i].value () || _advertising_enable_command_params.max_events [i]) {
2490
+ _interruptible_sets.clear (_advertising_enable_command_params.handles [i]);
2491
+ } else {
2492
+ _interruptible_sets.set (_advertising_enable_command_params.handles [i]);
2493
+ }
2521
2494
}
2522
2495
}
2523
2496
2524
- /* if there's anything else waiting, queue it up, otherwise mark the head node handle as invalid */
2525
- if (_advertising_enable_queue.next ) {
2526
- AdvertisingEnableStackNode_t* next = _advertising_enable_queue.next ;
2527
- _advertising_enable_queue.handle = next->handle ;
2528
- _advertising_enable_queue.max_duration = next->max_duration ;
2529
- _advertising_enable_queue.max_events = next->max_events ;
2530
- _advertising_enable_queue.next = next->next ;
2531
- delete next;
2532
- } else {
2533
- _advertising_enable_queue.handle = ble::INVALID_ADVERTISING_HANDLE;
2534
- }
2497
+ _advertising_enable_command_params.number_of_handles = 0 ;
2498
+ _process_enable_queue_pending = false ;
2535
2499
}
2536
2500
#endif // BLE_FEATURE_EXTENDED_ADVERTISING
2537
2501
@@ -2564,22 +2528,15 @@ ble_error_t Gap::stopAdvertising(advertising_handle_t handle)
2564
2528
2565
2529
#if BLE_FEATURE_EXTENDED_ADVERTISING
2566
2530
if (is_extended_advertising_available ()) {
2567
- _event_queue.post ([this , handle] {
2568
- /* if any already pending to stop delay the command execution */
2569
- bool delay = false ;
2570
- for (size_t i = 0 ; i < BLE_GAP_MAX_ADVERTISING_SETS; ++i) {
2571
- if (_pending_stop_sets.get (i)) {
2572
- delay = true ;
2573
- break ;
2574
- }
2575
- }
2576
- _pending_stop_sets.set (handle);
2577
- if (!delay) {
2578
- process_stop ();
2579
- }
2580
- });
2531
+ _pending_stop_sets.set (handle);
2532
+ /* delay execution of command to accumulate multiple sets */
2533
+ if (!_process_disable_queue_pending) {
2534
+ _process_disable_queue_pending = _event_queue.post ([this ] {
2535
+ process_disable_queue ();
2536
+ });
2537
+ }
2581
2538
2582
- return BLE_ERROR_NONE;
2539
+ status = BLE_ERROR_NONE;
2583
2540
2584
2541
} else
2585
2542
#endif // BLE_FEATURE_EXTENDED_ADVERTISING
@@ -2604,31 +2561,44 @@ ble_error_t Gap::stopAdvertising(advertising_handle_t handle)
2604
2561
}
2605
2562
2606
2563
#if BLE_FEATURE_EXTENDED_ADVERTISING
2607
- void Gap::process_stop ()
2564
+ void Gap::process_disable_queue ()
2608
2565
{
2566
+ advertising_handle_t sets[BLE_GAP_MAX_ADVERTISING_SETS];
2567
+ uint8_t number_of_handles = 0 ;
2609
2568
// refresh for address for all connectable advertising sets
2610
2569
for (size_t i = 0 ; i < BLE_GAP_MAX_ADVERTISING_SETS; ++i) {
2611
2570
if (_pending_stop_sets.get (i)) {
2612
- ble_error_t status = _pal_gap.extended_advertising_enable (
2613
- /* enable */ false ,
2614
- /* number of advertising sets */ 1 ,
2615
- (advertising_handle_t *)&i,
2616
- nullptr ,
2617
- nullptr
2618
- );
2619
- if (status) {
2620
- _event_handler->onAdvertisingCommandFailed (
2621
- AdvertisingCommandFailedEvent (
2622
- (advertising_handle_t )i,
2571
+ sets[number_of_handles] = i;
2572
+ number_of_handles++;
2573
+ _pending_stop_sets.clear (i);
2574
+ }
2575
+ }
2576
+
2577
+ if (number_of_handles) {
2578
+ ble_error_t status = _pal_gap.extended_advertising_enable (
2579
+ /* enable */ false ,
2580
+ number_of_handles,
2581
+ (advertising_handle_t *)&sets,
2582
+ nullptr ,
2583
+ nullptr
2584
+ );
2585
+ if (status) {
2586
+ for (size_t i = 0 ; i < number_of_handles; ++i) {
2587
+ _event_handler->onAdvertisingEnd (
2588
+ AdvertisingEndEvent (
2589
+ (advertising_handle_t )sets[i],
2590
+ 0 /* connection*/ ,
2591
+ 0 /* completed_events*/ ,
2592
+ false /* connected*/ ,
2623
2593
status
2624
2594
)
2625
2595
);
2626
2596
tr_error (" Could not stop advertising set %u, error: %s" , i, to_string (status));
2627
2597
}
2628
- break ;
2629
2598
}
2630
2599
}
2631
2600
2601
+ _process_disable_queue_pending = false ;
2632
2602
}
2633
2603
#endif // BLE_FEATURE_EXTENDED_ADVERTISING
2634
2604
@@ -3459,11 +3429,6 @@ void Gap::on_advertising_set_started(const mbed::Span<const uint8_t>& handles)
3459
3429
{
3460
3430
tr_info (" Advertising set started - handles=%s" , mbed_trace_array (handles.data (), handles.size ()));
3461
3431
3462
- _event_queue.post ([this ] {
3463
- _advertising_enable_pending = false ;
3464
- process_enable_queue ();
3465
- });
3466
-
3467
3432
for (const auto &handle : handles) {
3468
3433
_active_sets.set (handle);
3469
3434
_pending_sets.clear (handle);
@@ -3475,6 +3440,13 @@ void Gap::on_advertising_set_started(const mbed::Span<const uint8_t>& handles)
3475
3440
);
3476
3441
}
3477
3442
}
3443
+
3444
+ /* delay processing to minimise churn (if multiple events are pending that would trigger it) */
3445
+ if (!_process_enable_queue_pending) {
3446
+ _process_enable_queue_pending = _event_queue.post ([this ] {
3447
+ process_enable_queue ();
3448
+ });
3449
+ }
3478
3450
}
3479
3451
3480
3452
void Gap::on_advertising_set_terminated (
@@ -3504,10 +3476,12 @@ void Gap::on_advertising_set_terminated(
3504
3476
return ;
3505
3477
}
3506
3478
3507
- _event_queue.post ([this , advertising_handle] {
3508
- _pending_stop_sets.clear (advertising_handle);
3509
- process_stop ();
3510
- });
3479
+ /* postpone as other events may still be pending */
3480
+ if (!_process_disable_queue_pending) {
3481
+ _process_disable_queue_pending = _event_queue.post ([this ] {
3482
+ process_disable_queue ();
3483
+ });
3484
+ }
3511
3485
3512
3486
if (!_event_handler) {
3513
3487
return ;
0 commit comments