Skip to content

Commit 040e398

Browse files
committed
pbio/drv/bluetooth_btstack: Make peripheral scan/connect robust.
This replaces the state machine logic of the scan and connect task with placing logic synchronously in a protothread. At every stage, we can detect, report and return errors, and handle cancellation correctly. This fixes a longstanding issue where the Xbox Controller would sometimes not pair to a SPIKE Prime Hub, even though a second attempt usually worked. Now we can catch the return codes from the security manager and re-try pairing within the task, or retry the whole task a second time. We also allow re-encryption now rather than disconnecting when this is attempted. Extensive USB logging is added to catch issues and flow of the connection process.
1 parent 3f714f5 commit 040e398

File tree

5 files changed

+335
-216
lines changed

5 files changed

+335
-216
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@
3333
- Fixed Powered Up remote and Xbox Controller working only after the first
3434
connection. All of the above Remote and Xbox Controller were introduced in
3535
the previous beta release, so did not affect any stable release ([support#2521]).
36+
- Fixed Xbox Controller sometimes not working the first time ([support#1509]).
3637

38+
[support#1509]: https://github.com/pybricks/support/issues/1509
3739
[support#1962]: https://github.com/pybricks/support/issues/1962
3840
[support#2468]: https://github.com/pybricks/support/issues/2468
3941
[support#2497]: https://github.com/pybricks/support/issues/2497

lib/pbio/drv/bluetooth/bluetooth.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: MIT
2-
// Copyright (c) 2018-2025 The Pybricks Authors
2+
// Copyright (c) 2018-2026 The Pybricks Authors
33

44
// Common Bluetooth driver code
55

@@ -195,6 +195,11 @@ pbio_error_t pbdrv_bluetooth_peripheral_scan_and_connect(pbdrv_bluetooth_periphe
195195
return PBIO_ERROR_BUSY;
196196
}
197197

198+
// Must provide matchers.
199+
if (!config || !config->match_adv || !config->match_adv_rsp) {
200+
return PBIO_ERROR_INVALID_ARG;
201+
}
202+
198203
// Used to compare subsequent advertisements, so we should reset it.
199204
memset(peri->bdaddr, 0, sizeof(peri->bdaddr));
200205

@@ -311,6 +316,7 @@ pbio_error_t pbdrv_bluetooth_await_peripheral_command(pbio_os_state_t *state, vo
311316

312317
void pbdrv_bluetooth_cancel_operation_request(void) {
313318
// Only some peripheral actions support cancellation.
319+
DEBUG_PRINT("Bluetooth operation cancel requested.\n");
314320
peripheral_singleton.cancel = true;
315321
}
316322

@@ -645,6 +651,7 @@ void pbdrv_bluetooth_deinit(void) {
645651
// is, a task got stuck, so exit forcefully.
646652
if (advertising_or_scan_err == PBIO_ERROR_AGAIN || peripheral_singleton.err == PBIO_ERROR_AGAIN) {
647653
// Hard reset without waiting on completion of any process.
654+
DEBUG_PRINT("Bluetooth deinit: forcing hard reset due to busy tasks.\n");
648655
pbdrv_bluetooth_controller_reset_hard();
649656
return;
650657
}

0 commit comments

Comments
 (0)