fix(core): fix wireless charging in suspend.
What changed, and why it matters
This commit fixes a bug in the Trezor hardware wallet's low-power suspend routine for STM32U5 devices. Previously, when the device was placed on a wireless charger and not connected by USB cable, it would not stay suspended with the charging LED effect active; it could drop out of suspend unexpectedly. The fix tracks whether charging is active and keeps the device in the suspend loop while charging, even without a USB connection. There is no indication this is a security vulnerability or exploitable by an attacker.
No security action required. Treat as a normal firmware bug fix. If reviewing for release notes, note it as a fix for wireless charging LED/suspend behavior.
Security signals we found
No security-relevant signals detected in the diff
Change is a functional bug fix for LED/suspend behavior during wireless charging
No input validation, memory safety, cryptographic, or privilege changes
Evidence from the diff
In core/embed/sys/suspend/stm32u5/suspend.c, the suspend loop condition was pm_usb_is_connected() && (wakeup_flags == 0). This meant that if a wireless charger was providing power but no USB cable was connected, pm_usb_is_connected() would be false and the loop would exit, stopping the charging LED effect and leaving suspend early. The patch introduces a local boolean charging_in_suspend that is set whenever pm_is_charging() is true, and changes the loop condition to (pm_usb_is_connected() || charging_in_suspend) && (wakeup_flags == 0). This keeps the device suspended and the charging LED active while wireless charging continues.
Changed components
core/embed/sys/suspend/stm32u5/suspend.cTrezor Safe firmware suspend/charging state machine (STM32U5 models)Inspect captured patch +6 / −1
diff --git a/core/embed/sys/suspend/stm32u5/suspend.c b/core/embed/sys/suspend/stm32u5/suspend.c
index 7165c8049..0e9eb5f7a 100644
--- a/core/embed/sys/suspend/stm32u5/suspend.c
+++ b/core/embed/sys/suspend/stm32u5/suspend.c
@@ -75,13 +75,17 @@ wakeup_flags_t system_suspend(void) {
// Keep in this loop until the external power got disconnected or the
// device is waked up. Also, if the battery is charging, the state is signaled
// with RGB LED charging effect.
+
+ bool charging_in_suspend = false;
do {
#ifdef USE_RGB_LED
if (pm_is_charging()) {
+ charging_in_suspend = true;
if (!rgb_led_effect_ongoing()) {
rgb_led_effect_start(RGB_LED_EFFECT_CHARGING, 0);
}
} else {
+ charging_in_suspend = false;
rgb_led_effect_stop();
}
#endif
@@ -90,7 +94,8 @@ wakeup_flags_t system_suspend(void) {
wakeup_flags_get(&wakeup_flags);
- } while (pm_usb_is_connected() && (wakeup_flags == 0));
+ } while ((pm_usb_is_connected() || charging_in_suspend) &&
+ (wakeup_flags == 0));
if (wakeup_flags == 0) {
// Deinitialize rest of the drivers before entering low-power mode
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.