feat(core): swap charging efect phases to start 800ms in OFF.
What changed, and why it matters
This commit changes the visual pattern of the RGB LED charging indicator on Trezor hardware wallets. It swaps the order of the charging animation phases so the LED stays off for the first 800 milliseconds, then fades to yellow, holds yellow, fades off, and repeats. There is no security-relevant change here—only the timing and visual appearance of a status light.
No security action required. This is a cosmetic/user-experience change to the charging LED animation.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch modifies core/embed/io/rgb_led/stm32u5/rgb_led_effects.c, which drives the RGB LED effects on STM32U5-based Trezor devices. It reorders the EF_CHG_PHASEn_MS constants for the charging effect and rewrites rgb_led_effect_charging() so that phase 1 is an 800 ms OFF hold (previously 300 ms fade-in), phase 2 is a 300 ms fade-in to yellow (previously 800 ms hold), phase 3 is an 800 ms yellow hold (previously 300 ms fade-out), and phase 4 is a 300 ms fade-out (previously 800 ms OFF hold). Total cycle time remains 2200 ms. No logic affecting firmware security, cryptography, memory safety, or user confirmation flows is changed.
Changed components
core/embed/io/rgb_led/stm32u5/rgb_led_effects.cInspect captured patch +19 / −17
diff --git a/core/embed/io/rgb_led/stm32u5/rgb_led_effects.c b/core/embed/io/rgb_led/stm32u5/rgb_led_effects.c
index c3b1c2e24..bbad8c9b0 100644
--- a/core/embed/io/rgb_led/stm32u5/rgb_led_effects.c
+++ b/core/embed/io/rgb_led/stm32u5/rgb_led_effects.c
@@ -33,10 +33,10 @@
(EF_BB_PHASE1_MS + EF_BB_PHASE2_MS + EF_BB_PHASE3_MS + EF_BB_PHASE4_MS)
// RGB_LED_EFFECT_CHARGING constants
-#define EF_CHG_PHASE1_MS 300
-#define EF_CHG_PHASE2_MS 800
-#define EF_CHG_PHASE3_MS 300
-#define EF_CHG_PHASE4_MS 800
+#define EF_CHG_PHASE1_MS 800
+#define EF_CHG_PHASE2_MS 300
+#define EF_CHG_PHASE3_MS 800
+#define EF_CHG_PHASE4_MS 300
#define EF_CHG_CYCLE_MS \
(EF_CHG_PHASE1_MS + EF_CHG_PHASE2_MS + EF_CHG_PHASE3_MS + EF_CHG_PHASE4_MS)
@@ -170,27 +170,29 @@ static void rgb_led_effect_charging(uint32_t elapsed_ms,
uint32_t ef_time = elapsed_ms % EF_CHG_CYCLE_MS;
if (ef_time < EF_CHG_PHASE1_MS) {
- // PHASE 1: linear transition to RGBLED_YELLOW
- rgb_led_linear_gc_effect(RGBLED_OFF, RGBLED_YELLOW, ef_time,
- EF_CHG_PHASE1_MS, ef_color);
+ // PHASE 1: hold the off state
+ ef_color->red = 0;
+ ef_color->green = 0;
+ ef_color->blue = 0;
} else if (ef_time < EF_CHG_PHASE1_MS + EF_CHG_PHASE2_MS) {
- // PHASE 2: hold RGBLED_YELLOW color
+ // PHASE 2: linear transition to RGBLED_YELLOW
+ rgb_led_linear_gc_effect(RGBLED_OFF, RGBLED_YELLOW,
+ ef_time - EF_CHG_PHASE1_MS, EF_CHG_PHASE2_MS,
+ ef_color);
+ } else if (ef_time < EF_CHG_PHASE1_MS + EF_CHG_PHASE2_MS + EF_CHG_PHASE3_MS) {
+ // PHASE 3: hold RGBLED_YELLOW color
ef_color->red =
(RGB_EXTRACT_RED(RGBLED_YELLOW) * RGB_LED_TIMER_PERIOD) / 255;
ef_color->green =
(RGB_EXTRACT_GREEN(RGBLED_YELLOW) * RGB_LED_TIMER_PERIOD) / 255;
ef_color->blue =
(RGB_EXTRACT_BLUE(RGBLED_YELLOW) * RGB_LED_TIMER_PERIOD) / 255;
- } else if (ef_time < EF_CHG_PHASE1_MS + EF_CHG_PHASE2_MS + EF_CHG_PHASE3_MS) {
- // PHASE 3: linear transition to RGBLED_OFF
- rgb_led_linear_gc_effect(RGBLED_YELLOW, RGBLED_OFF,
- ef_time - EF_CHG_PHASE1_MS - EF_CHG_PHASE2_MS,
- EF_CHG_PHASE3_MS, ef_color);
} else if (ef_time < EF_CHG_CYCLE_MS) {
- // PHASE 4: hold the off state
- ef_color->red = 0;
- ef_color->green = 0;
- ef_color->blue = 0;
+ // PHASE 4: linear transition to RGBLED_OFF
+ rgb_led_linear_gc_effect(
+ RGBLED_YELLOW, RGBLED_OFF,
+ ef_time - EF_CHG_PHASE1_MS - EF_CHG_PHASE2_MS - EF_CHG_PHASE3_MS,
+ EF_CHG_PHASE4_MS, ef_color);
} else {
// Should not happen
ef_color->red = 0;
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.