feat(core/debuglink): set battery handler
What changed, and why it matters
This commit adds a debug-only feature that lets developers or automated tests tell the Trezor emulator what battery state to report (charge level, charging, temperature, etc.). It only works when the device is compiled in debug mode and is running in the software emulator, not on a real hardware wallet. There is no indication this is a security fix or that it exposes real user funds to risk.
No urgent action. If reviewing for defense in depth, verify that `io.pm.set_emu_battery_state()` enforces sane value ranges and that the debug link is disabled in production firmware builds. Treat as normal feature code.
Security signals we found
New debug-link message handler added
Gated by __debug__ compile-time flag and emulator-only runtime checks
No validation or bounds checking on battery-state integer/boolean inputs
Touches power-manager emulator state, not real hardware
No changelog entry; commit is labeled as a feature
Evidence from the diff
The change registers a new debug-link message handler, DebugLinkSetBatteryState, gated by if __debug__: and further restricted to utils.USE_POWER_MANAGER and utils.EMULATOR. The handler forwards protobuf fields to io.pm.set_emu_battery_state(), an emulator-specific power-manager hook. It does not alter production code paths, real battery hardware, or wallet security logic.
Changed components
core/src/apps/debug/__init__.pyDebugLink debug interfaceTrezor emulator power-manager battery stateInspect captured patch +36 / −0
diff --git a/core/src/apps/debug/__init__.py b/core/src/apps/debug/__init__.py
index fc31fabe..7c6ecb23 100644
--- a/core/src/apps/debug/__init__.py
+++ b/core/src/apps/debug/__init__.py
@@ -32,6 +32,7 @@ if __debug__:
DebugLinkPairingInfo,
DebugLinkRecordScreen,
DebugLinkReseedRandom,
+ DebugLinkSetBatteryState,
DebugLinkSetLogFilter,
DebugLinkState,
DebugLinkStop,
@@ -399,6 +400,36 @@ if __debug__:
sdcard.power_off()
return Success()
+ if utils.USE_POWER_MANAGER and utils.EMULATOR:
+
+ async def dispatch_DebugLinkSetBatteryState(
+ msg: DebugLinkSetBatteryState,
+ ) -> Success:
+ from trezor import io
+
+ log.debug(
+ __name__,
+ "setting battery state: soc=%s, usb=%s, wireless=%s, ntc=%s, "
+ "limited=%s, temp_ctrl=%s, bat_conn=%s",
+ msg.soc,
+ msg.usb_connected,
+ msg.wireless_connected,
+ msg.ntc_connected,
+ msg.charging_limited,
+ msg.temp_control_active,
+ msg.battery_connected,
+ )
+ io.pm.set_emu_battery_state(
+ soc=msg.soc,
+ usb_connected=msg.usb_connected,
+ wireless_connected=msg.wireless_connected,
+ ntc_connected=msg.ntc_connected,
+ charging_limited=msg.charging_limited,
+ temp_control_active=msg.temp_control_active,
+ battery_connected=msg.battery_connected,
+ )
+ return Success()
+
async def dispatch_DebugLinkOptigaSetSecMax(
msg: DebugLinkOptigaSetSecMax,
) -> Success:
@@ -582,6 +613,11 @@ if __debug__:
dispatch_DebugLinkConnected
)
+ if utils.USE_POWER_MANAGER and utils.EMULATOR:
+ WORKFLOW_HANDLERS[MessageType.DebugLinkSetBatteryState] = (
+ dispatch_DebugLinkSetBatteryState
+ )
+
def boot() -> None:
import usb
Why this scored 21/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.