Suspend MediaTek boards only while discharging - #118
Open
abhishek-anand wants to merge 15 commits into
Open
Conversation
Nickel is stopped for the session, so the button had no owner. A short press now sleeps without handing the panel back; a hold of two seconds powers off. MediaTek boards skip kernel suspend while charging. Co-authored-by: Cursor <cursoragent@cursor.com>
A missed battery read must not write mem on boards that hang when suspended on a charger. Kernel power writes stay behind device-write. Co-authored-by: Cursor <cursoragent@cursor.com>
Both the device build and the packaging step hard-coded a relative "target/" prefix when locating the cross-compiled artifact to verify. Anyone building with CARGO_TARGET_DIR pointed somewhere else — a shared cache, or a worktree on a different volume — got a missing-file error from verify_arm_elf instead of a verified binary, even though cargo had just built it successfully. Resolve the prefix from the environment the same way cargo does, and fall back to "target" only when nothing is set. Co-authored-by: Cursor <cursoragent@cursor.com>
Battery::charging answers a two-state question by treating everything that is not "Charging" as not charging. That is the right answer for a status band, and the wrong one for suspend: a MediaTek kernel hangs on "Full" and on "Not charging" just as readily as on "Charging", and an unreadable status has to count as unsafe rather than safe. Add discharging()/discharging_from() alongside it, returning None when the status cannot be read so the caller can decide, and cover every status string the sysfs node is known to produce. Co-authored-by: Cursor <cursoragent@cursor.com>
charger_blocks_mem asked Battery::charging, so "Full" and "Not charging" both read as safe to suspend and both hang the kernel. Ask the stricter question instead, and re-check it inside try_mem: the gap between flagging subsystems and writing mem is two seconds, which is long enough for a charger to be plugged in after the decision was made. A cancelled attempt unflags the subsystems it already flagged. Wake was also handing the panel to the wrong owner. Some firmware restarts Nickel during resume even though Cobalt stopped it before taking the panel; yielding to it left Cobalt's sleep screen painted over Nickel, so wake looked like it had returned to the wrong program. Stop that second owner and repaint instead of bailing out. Finally, drop resleep_at and UNEXPECTED_WAKE. The power-key edge that wakes the kernel is not reliably replayed to userspace, so the loop was waiting fifteen seconds for an event that never arrived and then going back to sleep on a reader somebody was holding. Treat the completed resume as the wake signal and lean on WAKE_GRACE to swallow the late release edge. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
🟡 Changes recommended
The sleep UI/docs currently describe wake and sleep-screen behavior that doesn’t match the implemented runtime behavior, which can mislead users.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR extends the device runtime’s in-session sleep/wake behavior (including MediaTek charging constraints), adds an owner-visible “Sleep after idle” setting, and improves post-suspend recovery (panel ownership + Wi‑Fi) while aligning the protocol/SDK/simulator surfaces to support the new capability.
Changes:
- Add an
IdleSleeppreference end-to-end (protocol wire tags + SDK API + Settings UI + device runtime persistence). - Implement in-session sleep/wake handling (power button + cover), including MediaTek “suspend only when explicitly discharging” gating and panel invalidation after resume.
- Improve network recovery/robustness around sleep/wake and session hand-off (Wi‑Fi bring-up hooks, link/lease handling, and reader ownership detection).
File summaries
| File | Description |
|---|---|
| examples/settings/src/main.rs | Adds “Sleep after idle” screen and device request plumbing for idle-sleep preference. |
| docs/PORTING.md | Tightens required evidence to include short power-button sleep/wake into the same app. |
| docs/DEVICES.md | Documents in-session sleep behavior and MediaTek charging suspend limitations. |
| crates/kobod/src/main.rs | Updates KOBO_IDLE_SECONDS handling to support “never/from settings” modes. |
| crates/kobod/src/device.rs | Implements sleep overlay, idle-sleep enforcement, suspend gating, Wi‑Fi/session restoration, and reader-ownership-aware handoff. |
| crates/kobod/src/app_link.rs | Ensures relay path runs network-prepare hook before opening sockets. |
| crates/kobo-ui/src/lib.rs | Adds FramePlanner::invalidate() to force full refresh after untrusted framebuffer restore. |
| crates/kobo-sim/src/lib.rs | Restricts idle-sleep requests to Settings in the simulator authority model. |
| crates/kobo-sdk/src/lib.rs | Exposes IdleSleep plus read_idle_sleep/set_idle_sleep on Device. |
| crates/kobo-protocol/src/lib.rs | Defines IdleSleep, adds device requests/results, and encodes/decodes new wire tags. |
| crates/kobo-profile/src/lib.rs | Adds MediaTek charging-suspend predicate; enables supplicant reaping for Clara BW profiles. |
| crates/kobo-policy/src/services.rs | Tracks idle-sleep in services and marks idle-sleep requests as capability-free. |
| crates/kobo-net/src/lib.rs | Adds on_prepare hook and calls prepare() before opening sockets; adds idle-connection reset helper. |
| crates/kobo-hal/src/wifi.rs | Adds wake/keep/restore logic for saved Wi‑Fi with route/lease handling and sleep staleness tracking. |
| crates/kobo-hal/src/reader.rs | Adds “any reader running” detection and safer restart behavior to avoid double-Nickel ownership. |
| crates/kobo-hal/src/power.rs | New module for power-button action classification and kernel suspend sysfs access (device-write gated). |
| crates/kobo-hal/src/network.rs | Adds non-owning DHCP renew helper and makes wait_until_online public for reuse. |
| crates/kobo-hal/src/lib.rs | Exposes the new power module. |
| crates/kobo-hal/src/gpio.rs | Detects MediaTek pwrkey node separately from gpio-keys; updates discovery and validation. |
| crates/kobo-hal/src/battery.rs | Adds strict “explicitly discharging” check for safe suspend gating on MediaTek boards. |
| crates/kobo-cli/src/main.rs | Resolves ARM binary paths via CARGO_TARGET_DIR instead of assuming target/. |
Review details
- Files reviewed: 21/21 changed files
- Comments generated: 2
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+944
to
+945
| title: "Sleeping".to_owned(), | ||
| summary: "Press the power button or open the cover to wake.".to_owned(), |
Comment on lines
+38
to
+40
| the default. Sleep keeps the current screen and writes "Sleeping" in the | ||
| status strip; it does not replace the panel with a splash. The radio is | ||
| powered down for sleep and brought back on wake when it was up. If it is |
Keep MediaTek suspend-while-discharging and fold later radio, protocol, and settings work.
…wake # Conflicts: # crates/kobo-profile/src/lib.rs # crates/kobod/src/device.rs # tools/check-app-versions.mjs
…wake # Conflicts: # crates/kobo-cli/src/main.rs # crates/kobod/src/device.rs # docs/DEVICES.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Test plan
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.