Skip to content

Commit a71d6bc

Browse files
committed
pbio/drv/bluetooth: Maintain advertising state.
We used to maintain an advertising state in pbsys/bluetooth and now in pbsys/hmi, handling things such as _not_ advertising if it was already in the connected state. This works, but becomes even more cumbersome when we add a USB state in the next commits. It is simpler for the higher level code to be able to just say stop_advertising, and letting the Bluetooth driver treat it as a no-op if it not advertising to begin with.
1 parent fb73270 commit a71d6bc

File tree

6 files changed

+54
-28
lines changed

6 files changed

+54
-28
lines changed

lib/pbio/drv/bluetooth/bluetooth.c

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -317,8 +317,18 @@ void pbdrv_bluetooth_cancel_operation_request(void) {
317317
static pbio_os_process_func_t advertising_or_scan_func;
318318
static pbio_error_t advertising_or_scan_err;
319319

320+
pbdrv_bluetooth_advertising_state_t pbdrv_bluetooth_advertising_state;
321+
320322
pbio_error_t pbdrv_bluetooth_start_advertising(bool start) {
321323

324+
bool is_advertising = pbdrv_bluetooth_advertising_state == PBDRV_BLUETOOTH_ADVERTISING_STATE_ADVERTISING_PYBRICKS;
325+
326+
// Already in requested state. This makes it safe to call stop advertising
327+
// even if it already stopped on becoming connected;
328+
if (start == is_advertising) {
329+
return PBIO_SUCCESS;
330+
}
331+
322332
if (advertising_or_scan_func) {
323333
return PBIO_ERROR_BUSY;
324334
}
@@ -349,9 +359,13 @@ pbio_error_t pbdrv_bluetooth_start_broadcasting(const uint8_t *data, size_t size
349359
return PBIO_ERROR_INVALID_ARG;
350360
}
351361

362+
bool is_broadcasting = pbdrv_bluetooth_advertising_state == PBDRV_BLUETOOTH_ADVERTISING_STATE_BROADCASTING;
363+
352364
// This means stop broadcasting.
353365
if (!data || !size) {
354-
if (!pbdrv_bluetooth_is_broadcasting) {
366+
367+
if (!is_broadcasting) {
368+
// Already stopped.
355369
return PBIO_SUCCESS;
356370
}
357371
advertising_or_scan_err = PBIO_ERROR_AGAIN;
@@ -362,7 +376,7 @@ pbio_error_t pbdrv_bluetooth_start_broadcasting(const uint8_t *data, size_t size
362376

363377
// Avoid I/O operations if the user tries to broadcast the same data
364378
// over and over in a tight loop.
365-
if (pbdrv_bluetooth_is_broadcasting && pbdrv_bluetooth_broadcast_data_size == size && !memcmp(pbdrv_bluetooth_broadcast_data, data, size)) {
379+
if (is_broadcasting && pbdrv_bluetooth_broadcast_data_size == size && !memcmp(pbdrv_bluetooth_broadcast_data, data, size)) {
366380
return PBIO_SUCCESS;
367381
}
368382
pbdrv_bluetooth_broadcast_data_size = size;
@@ -376,7 +390,6 @@ pbio_error_t pbdrv_bluetooth_start_broadcasting(const uint8_t *data, size_t size
376390
return PBIO_SUCCESS;
377391
}
378392

379-
bool pbdrv_bluetooth_is_broadcasting;
380393
bool pbdrv_bluetooth_is_observing;
381394
pbdrv_bluetooth_start_observing_callback_t pbdrv_bluetooth_observe_callback;
382395

@@ -441,7 +454,7 @@ pbio_error_t pbdrv_bluetooth_process_thread(pbio_os_state_t *state, void *contex
441454

442455
DEBUG_PRINT("Bluetooth disable requested.\n");
443456

444-
pbdrv_bluetooth_is_broadcasting = false;
457+
pbdrv_bluetooth_advertising_state = PBDRV_BLUETOOTH_ADVERTISING_STATE_NONE;
445458
pbdrv_bluetooth_is_observing = false;
446459
observe_restart_requested = false;
447460

lib/pbio/drv/bluetooth/bluetooth.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,14 @@ extern size_t pbdrv_bluetooth_char_write_size;
5252
extern uint8_t pbdrv_bluetooth_broadcast_data[PBDRV_BLUETOOTH_MAX_ADV_SIZE];
5353
extern uint8_t pbdrv_bluetooth_broadcast_data_size;
5454

55-
extern bool pbdrv_bluetooth_is_broadcasting;
55+
typedef enum {
56+
PBDRV_BLUETOOTH_ADVERTISING_STATE_NONE,
57+
PBDRV_BLUETOOTH_ADVERTISING_STATE_ADVERTISING_PYBRICKS,
58+
PBDRV_BLUETOOTH_ADVERTISING_STATE_BROADCASTING,
59+
} pbdrv_bluetooth_advertising_state_t;
60+
61+
extern pbdrv_bluetooth_advertising_state_t pbdrv_bluetooth_advertising_state;
62+
5663
extern bool pbdrv_bluetooth_is_observing;
5764
extern pbdrv_bluetooth_start_observing_callback_t pbdrv_bluetooth_observe_callback;
5865

lib/pbio/drv/bluetooth/bluetooth_btstack.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
281281

282282
// don't start advertising again on disconnect
283283
gap_advertisements_enable(false);
284+
pbdrv_bluetooth_advertising_state = PBDRV_BLUETOOTH_ADVERTISING_STATE_NONE;
284285
} else {
285286
// If we aren't waiting for a peripheral connection, this must be a different connection.
286287
if (handset.con_state != CON_STATE_WAIT_CONNECT) {
@@ -548,6 +549,8 @@ pbio_error_t pbdrv_bluetooth_start_advertising_func(pbio_os_state_t *state, void
548549

549550
PBIO_OS_AWAIT_UNTIL(state, event_packet && HCI_EVENT_IS_COMMAND_COMPLETE(event_packet, hci_le_set_advertising_data));
550551

552+
pbdrv_bluetooth_advertising_state = PBDRV_BLUETOOTH_ADVERTISING_STATE_ADVERTISING_PYBRICKS;
553+
551554
PBIO_OS_ASYNC_END(PBIO_SUCCESS);
552555
}
553556

@@ -556,9 +559,11 @@ pbio_error_t pbdrv_bluetooth_stop_advertising_func(pbio_os_state_t *state, void
556559
PBIO_OS_ASYNC_BEGIN(state);
557560

558561
gap_advertisements_enable(false);
559-
pbdrv_bluetooth_is_broadcasting = false;
562+
560563
// REVISIT: use callback to await operation
561564

565+
pbdrv_bluetooth_advertising_state = PBDRV_BLUETOOTH_ADVERTISING_STATE_NONE;
566+
562567
PBIO_OS_ASYNC_END(PBIO_SUCCESS);
563568
}
564569

@@ -797,18 +802,19 @@ pbio_error_t pbdrv_bluetooth_start_broadcasting_func(pbio_os_state_t *state, voi
797802
gap_advertisements_set_data(pbdrv_bluetooth_broadcast_data_size, pbdrv_bluetooth_broadcast_data);
798803

799804
// If already broadcasting, await set data and return.
800-
if (pbdrv_bluetooth_is_broadcasting) {
805+
if (pbdrv_bluetooth_advertising_state == PBDRV_BLUETOOTH_ADVERTISING_STATE_BROADCASTING) {
801806
PBIO_OS_AWAIT_UNTIL(state, event_packet && HCI_EVENT_IS_COMMAND_COMPLETE(event_packet, hci_le_set_advertising_data));
802807
return PBIO_SUCCESS;
803808
}
804809

805-
pbdrv_bluetooth_is_broadcasting = true;
806810
bd_addr_t null_addr = { };
807811
gap_advertisements_set_params(0xA0, 0xA0, PBDRV_BLUETOOTH_AD_TYPE_ADV_NONCONN_IND, 0, null_addr, 0x7, 0);
808812
gap_advertisements_enable(true);
809813

810814
PBIO_OS_AWAIT_UNTIL(state, event_packet && HCI_EVENT_IS_COMMAND_COMPLETE(event_packet, hci_le_set_advertise_enable));
811815

816+
pbdrv_bluetooth_advertising_state = PBDRV_BLUETOOTH_ADVERTISING_STATE_BROADCASTING;
817+
812818
PBIO_OS_ASYNC_END(PBIO_SUCCESS);
813819
}
814820

lib/pbio/drv/bluetooth/bluetooth_stm32_bluenrg.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,8 @@ pbio_error_t pbdrv_bluetooth_start_advertising_func(pbio_os_state_t *state, void
265265
PBIO_OS_AWAIT_UNTIL(state, hci_command_complete);
266266
// aci_gap_set_discoverable_end();
267267

268+
pbdrv_bluetooth_advertising_state = PBDRV_BLUETOOTH_ADVERTISING_STATE_ADVERTISING_PYBRICKS;
269+
268270
PBIO_OS_ASYNC_END(PBIO_SUCCESS);
269271
}
270272

@@ -281,10 +283,9 @@ pbio_error_t pbdrv_bluetooth_stop_advertising_func(pbio_os_state_t *state, void
281283
// This protothread is also shared with stop broadcasting. Either way,
282284
// nothing is advertising or broadcasting after this, so reset that state.
283285
// even if it wasn't active.
284-
pbdrv_bluetooth_is_broadcasting = false;
286+
pbdrv_bluetooth_advertising_state = PBDRV_BLUETOOTH_ADVERTISING_STATE_NONE;
285287

286288
PBIO_OS_ASYNC_END(PBIO_SUCCESS);
287-
;
288289
}
289290

290291

@@ -588,7 +589,7 @@ pbio_error_t pbdrv_bluetooth_start_broadcasting_func(pbio_os_state_t *state, voi
588589

589590
PBIO_OS_ASYNC_BEGIN(state);
590591

591-
if (!pbdrv_bluetooth_is_broadcasting) {
592+
if (pbdrv_bluetooth_advertising_state != PBDRV_BLUETOOTH_ADVERTISING_STATE_BROADCASTING) {
592593
PBIO_OS_AWAIT_WHILE(state, write_xfer_size);
593594
aci_gap_set_non_connectable_begin(ADV_NONCONN_IND, STATIC_RANDOM_ADDR);
594595
PBIO_OS_AWAIT_UNTIL(state, hci_command_complete);
@@ -620,7 +621,7 @@ pbio_error_t pbdrv_bluetooth_start_broadcasting_func(pbio_os_state_t *state, voi
620621
// Errors from deleting are ignored since we should only get an error
621622
// if the AD does not exist, which is OK.
622623

623-
pbdrv_bluetooth_is_broadcasting = true;
624+
pbdrv_bluetooth_advertising_state = PBDRV_BLUETOOTH_ADVERTISING_STATE_BROADCASTING;
624625
}
625626

626627
// This has to be done _after_ other data is delete to make sure it fits.
@@ -898,6 +899,7 @@ static void handle_event(hci_event_pckt *event) {
898899
evt_le_connection_complete *subevt = (evt_le_connection_complete *)evt->data;
899900
if (subevt->role == GAP_PERIPHERAL_ROLE) {
900901
conn_handle = subevt->handle;
902+
pbdrv_bluetooth_advertising_state = PBDRV_BLUETOOTH_ADVERTISING_STATE_NONE;
901903
} else {
902904
peri->con_handle = subevt->handle;
903905
}

lib/pbio/drv/bluetooth/bluetooth_stm32_cc2640.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,8 @@ pbio_error_t pbdrv_bluetooth_start_advertising_func(pbio_os_state_t *state, void
296296
PBIO_OS_AWAIT_UNTIL(state, hci_command_complete);
297297
// ignoring response data
298298

299+
pbdrv_bluetooth_advertising_state = PBDRV_BLUETOOTH_ADVERTISING_STATE_ADVERTISING_PYBRICKS;
300+
299301
PBIO_OS_ASYNC_END(PBIO_SUCCESS);
300302
}
301303

@@ -315,10 +317,8 @@ pbio_error_t pbdrv_bluetooth_stop_advertising_func(pbio_os_state_t *state, void
315317
// Status could also be bleIncorrectMode which means "Not advertising".
316318
// This is not expected, but should be safe to ignore.
317319

318-
// This protothread is also shared with stop broadcasting. Either way,
319-
// nothing is advertising or broadcasting after this, so reset that state.
320-
// even if it wasn't active.
321-
pbdrv_bluetooth_is_broadcasting = false;
320+
// This protothread is also shared with stop broadcasting.
321+
pbdrv_bluetooth_advertising_state = PBDRV_BLUETOOTH_ADVERTISING_STATE_NONE;
322322

323323
PBIO_OS_ASYNC_END(PBIO_SUCCESS);
324324
}
@@ -804,7 +804,7 @@ pbio_error_t pbdrv_bluetooth_start_broadcasting_func(pbio_os_state_t *state, voi
804804
HCI_LE_setAdvertisingData(pbdrv_bluetooth_broadcast_data_size, pbdrv_bluetooth_broadcast_data);
805805
PBIO_OS_AWAIT_UNTIL(state, hci_command_complete);
806806

807-
if (pbdrv_bluetooth_is_broadcasting) {
807+
if (pbdrv_bluetooth_advertising_state == PBDRV_BLUETOOTH_ADVERTISING_STATE_BROADCASTING) {
808808
// Already broadcasting, so just updating the data as above is enough.
809809
return PBIO_SUCCESS;
810810
}
@@ -823,7 +823,7 @@ pbio_error_t pbdrv_bluetooth_start_broadcasting_func(pbio_os_state_t *state, voi
823823
// wait for make discoverable done event
824824
PBIO_OS_AWAIT_UNTIL(state, hci_command_complete);
825825

826-
pbdrv_bluetooth_is_broadcasting = true;
826+
pbdrv_bluetooth_advertising_state = PBDRV_BLUETOOTH_ADVERTISING_STATE_BROADCASTING;
827827

828828
PBIO_OS_ASYNC_END(PBIO_SUCCESS);
829829
}
@@ -1319,6 +1319,9 @@ static void handle_event(uint8_t *packet) {
13191319
// assume minimum MTU until we get an exchange MTU request
13201320
conn_mtu = ATT_MTU_SIZE;
13211321

1322+
// Establishing the link implicitly stops advertising.
1323+
pbdrv_bluetooth_advertising_state = PBDRV_BLUETOOTH_ADVERTISING_STATE_NONE;
1324+
13221325
// On 2019 and newer MacBooks, the default interval was
13231326
// measured to be 15 ms. This caused advertisement to
13241327
// not be received by the local Bluetooth chip when

lib/pbio/sys/hmi_pup.c

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -203,19 +203,14 @@ static pbio_error_t run_ui(pbio_os_state_t *state, pbio_os_timer_t *timer) {
203203
PBIO_OS_AWAIT(state, &sub, pbdrv_bluetooth_power_on(&sub, pbsys_storage_settings_bluetooth_enabled_get()));
204204

205205
// Update advertising state.
206-
if (pbsys_storage_settings_bluetooth_enabled_get()) {
207-
// Start advertising if we aren't already.
208-
if (!pbsys_status_test(PBIO_PYBRICKS_STATUS_BLE_ADVERTISING)) {
209-
pbsys_status_set(PBIO_PYBRICKS_STATUS_BLE_ADVERTISING);
210-
DEBUG_PRINT("Start advertising.\n");
211-
pbdrv_bluetooth_start_advertising(true);
212-
PBIO_OS_AWAIT(state, &sub, pbdrv_bluetooth_await_advertise_or_scan_command(&sub, NULL));
213-
}
206+
bool do_advertise = pbsys_storage_settings_bluetooth_enabled_get();
207+
if (do_advertise) {
208+
pbsys_status_set(PBIO_PYBRICKS_STATUS_BLE_ADVERTISING);
214209
} else {
215-
// Not advertising if Bluetooth is disabled. The physical state
216-
// is already off, but we need the blinking to stop too.
217210
pbsys_status_clear(PBIO_PYBRICKS_STATUS_BLE_ADVERTISING);
218211
}
212+
pbdrv_bluetooth_start_advertising(do_advertise);
213+
PBIO_OS_AWAIT(state, &sub, pbdrv_bluetooth_await_advertise_or_scan_command(&sub, NULL));
219214
}
220215

221216
// Buttons could be pressed at the end of the user program, so wait for

0 commit comments

Comments
 (0)