nRF52 BLE: restore pairing passkey callback on re-enable (#11027)

shutdown() installs onUnwantedPairing to actively refuse pairing (used on
the factory-reset / BT-disable teardown path), but the correct callback
(onPairingPasskey) is installed only in setup(). Re-enabling BLE on an
already-constructed nrf52Bluetooth goes through resumeAdvertising(), not
setup() (main-nrf52.cpp), which only re-armed advertising and never
restored the pairing callback. So a shutdown()->resumeAdvertising() cycle
without a reboot left the device silently refusing all pairing until the
next reboot.

Restore the correct pairing passkey callback in resumeAdvertising(),
guarded by the same config.bluetooth.mode check setup() uses. Only PIN
modes drive a passkey-display callback; NO_PIN (Just Works) never invokes
it, so no restore is needed there.

Reachable today only via the PowerStress module's BT_OFF/BT_ON opcodes
(normal runtime BT-disable paths reboot), so low severity, but a real
teardown-latches / re-enable-doesn't-restore asymmetry.
This commit is contained in:
Ben Meadors
2026-07-16 13:02:43 -05:00
committed by GitHub
co-authored by GitHub
parent 53a6b5e01f
commit 43084873a6
+9
View File
@@ -369,6 +369,15 @@ void NRF52Bluetooth::setup()
}
void NRF52Bluetooth::resumeAdvertising()
{
// shutdown() latches onUnwantedPairing to actively refuse pairing (used on the factory-reset /
// BT-disable teardown path). The real pairing passkey callback is installed only in setup(), but a
// shutdown()->resumeAdvertising() re-enable cycle skips setup() entirely (see setBluetoothEnable() in
// main-nrf52.cpp), so restore the correct callback here - otherwise the device silently refuses all
// pairing until the next reboot. Mirror the mode check in setup(): only PIN modes drive a passkey-
// display callback, so NO_PIN (Just Works) needs no restore.
if (config.bluetooth.mode != meshtastic_Config_BluetoothConfig_PairingMode_NO_PIN)
Bluefruit.Security.setPairPasskeyCallback(NRF52Bluetooth::onPairingPasskey);
Bluefruit.Advertising.restartOnDisconnect(true);
Bluefruit.Advertising.setInterval(32, 668); // in unit of 0.625 ms
Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode