mirror of
https://github.com/meshtastic/firmware.git
synced 2026-09-16 16:41:24 -04:00
fix(ble): stop BLE from coming back up during the pre-reboot window (#11650)
* fix(ble): stop BLE from coming back up during the pre-reboot window Saving a reboot-requiring config over BLE (e.g. screen timeout) made the node disconnect, re-advertise, let the phone reconnect, and then drop it again at the reset. Two causes: nRF52: admin messages from the phone run synchronously on Bluefruit's BLE event task, so the BLE_GAP_EVT_DISCONNECTED caused by shutdown() is only processed after we return - and that handler restarts advertising because restartOnDisconnect(true) was never cleared. Stopping advertising first is a no-op while a connection is live (the SoftDevice isn't advertising), so the deferred event brought it straight back. Clear the restart flag and stop advertising before dropping the link, mirroring nRF54L15's ble_enabled gate. This also closes a main-thread race on the shutdown path where Advertising.stop() could land between connection teardown and Bluefruit's auto-restart within the same event dispatch. PowerFSM (all platforms): darkEnter/onEnter/powerEnter/powerExit/serialExit unconditionally re-enable BLE, so any state transition inside the reboot window - a button press while the banner is up, the screen timeout, USB plug/unplug - turned BLE back on after AdminModule had deliberately torn it down. Route them through a helper that skips the re-enable while rebootAtMsec/shutdownAtMsec is armed; every writer of those deadlines is an imminent restart. * style: trim rationale comments to house 1-2 line limit The full mechanism is in the original commit message and PR description.
This commit is contained in:
1 parent
db84bdf3b4
commit
f8a8d12477
2 files changed
+21
-6
No files matched your search
+16
-5
@@ -195,6 +195,17 @@ static void lsExit()
|
||||
t5BacklightWakeFromSleep();
|
||||
}
|
||||
|
||||
/// Skip the BLE re-enable while a reboot/shutdown is armed: AdminModule tears BLE down before
|
||||
/// scheduling the restart, and a state transition in that window would otherwise bring it back up.
|
||||
static void setBluetoothEnableUnlessRestarting()
|
||||
{
|
||||
if (rebootAtMsec || shutdownAtMsec) {
|
||||
LOG_POWERFSM("Skip BLE enable, restart pending");
|
||||
return;
|
||||
}
|
||||
setBluetoothEnable(true);
|
||||
}
|
||||
|
||||
static void nbEnter()
|
||||
{
|
||||
LOG_POWERFSM("State: nbEnter");
|
||||
@@ -211,7 +222,7 @@ static void nbEnter()
|
||||
static void darkEnter()
|
||||
{
|
||||
LOG_POWERFSM("State: darkEnter");
|
||||
setBluetoothEnable(true);
|
||||
setBluetoothEnableUnlessRestarting();
|
||||
if (screen)
|
||||
screen->setOn(false);
|
||||
// Screen timeout enters DARK; ensure backlight also turns off.
|
||||
@@ -235,7 +246,7 @@ static void serialExit()
|
||||
{
|
||||
LOG_POWERFSM("State: serialExit");
|
||||
// Turn bluetooth back on when we leave serial stream API
|
||||
setBluetoothEnable(true);
|
||||
setBluetoothEnableUnlessRestarting();
|
||||
}
|
||||
|
||||
static void powerEnter()
|
||||
@@ -248,7 +259,7 @@ static void powerEnter()
|
||||
} else {
|
||||
if (screen)
|
||||
screen->setOn(true);
|
||||
setBluetoothEnable(true);
|
||||
setBluetoothEnableUnlessRestarting();
|
||||
// within enter() the function getState() returns the state we came from
|
||||
}
|
||||
}
|
||||
@@ -266,7 +277,7 @@ static void powerIdle()
|
||||
static void powerExit()
|
||||
{
|
||||
LOG_POWERFSM("State: powerExit");
|
||||
setBluetoothEnable(true);
|
||||
setBluetoothEnableUnlessRestarting();
|
||||
}
|
||||
|
||||
static void onEnter()
|
||||
@@ -274,7 +285,7 @@ static void onEnter()
|
||||
LOG_POWERFSM("State: onEnter");
|
||||
if (screen)
|
||||
screen->setOn(true);
|
||||
setBluetoothEnable(true);
|
||||
setBluetoothEnableUnlessRestarting();
|
||||
}
|
||||
|
||||
static void onIdle()
|
||||
|
||||
@@ -245,8 +245,12 @@ void NRF52Bluetooth::shutdown()
|
||||
// Shutdown bluetooth for minimum power draw
|
||||
LOG_INFO("Disable NRF52 bluetooth");
|
||||
Bluefruit.Security.setPairPasskeyCallback(NRF52Bluetooth::onUnwantedPairing); // Actively refuse (during factory reset)
|
||||
disconnect();
|
||||
|
||||
// Clear the auto-restart flag before dropping the link: our DISCONNECTED event is only processed
|
||||
// after this callback returns and would re-start advertising. startAdv()/resumeAdvertising() re-set it.
|
||||
Bluefruit.Advertising.restartOnDisconnect(false);
|
||||
Bluefruit.Advertising.stop();
|
||||
disconnect();
|
||||
}
|
||||
void NRF52Bluetooth::startDisabled()
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user