uconsole_sleep/
power_mode.rs1use crate::hardware::{backlight, drm_panel, framebuffer};
4use crate::{CpuFreqConfig, WifiConfig};
5use log::{debug, info, warn};
6use std::fs;
7
8fn toggle_display(dry_run: bool) -> Result<(), String> {
9 let backlight_path = match backlight::find_backlight() {
10 Ok(Some(p)) => p,
11 Ok(None) => return Err("backlight not found".to_string()),
12 Err(e) => return Err(format!("failed to find backlight: {}", e)),
13 };
14
15 let framebuffer_path = framebuffer::find_framebuffer().ok().flatten();
16 let drm_path = drm_panel::find_drm_panel().ok().flatten();
17
18 let bl_state =
19 fs::read_to_string(backlight_path.join("bl_power")).unwrap_or_else(|_| "4".to_string());
20 let bl_state_trim = bl_state.trim();
21
22 if bl_state_trim == "4" {
23 info!("Turning display ON");
25 if !dry_run {
26 if let Some(fb) = framebuffer_path {
27 let _ = fs::write(fb.join("blank"), "0");
28 }
29 let _ = fs::write(backlight_path.join("bl_power"), "0");
30 if let Some(drm) = drm_path {
31 let _ = fs::write(drm.join("status"), "detect");
32 }
33 } else {
34 debug!("DRY-RUN: toggle_display ON skipped");
35 }
36 } else {
37 info!("Turning display OFF");
39 if !dry_run {
40 if let Some(drm) = drm_path {
41 let _ = fs::write(drm.join("status"), "off");
42 }
43 if let Some(fb) = framebuffer_path {
44 let _ = fs::write(fb.join("blank"), "1");
45 }
46 let _ = fs::write(backlight_path.join("bl_power"), "4");
47 } else {
48 debug!("DRY-RUN: toggle_display OFF skipped");
49 }
50 }
51 Ok(())
52}
53
54#[derive(Clone, Debug, PartialEq)]
56pub enum PowerMode {
57 Normal,
58 Saving,
59}
60
61pub fn enter_saving_mode(cpu_config: &CpuFreqConfig, dry_run: bool, wifi: Option<&WifiConfig>) {
62 info!("Entering power-saving mode");
63 if let Err(e) = toggle_display(dry_run) {
64 warn!("toggle_display failed: {}", e);
65 }
66 cpu_config.apply_saving_mode(dry_run);
67 if let Some(w) = wifi {
68 w.block(dry_run);
69 }
70}
71
72pub fn exit_saving_mode(cpu_config: &CpuFreqConfig, dry_run: bool, wifi: Option<&WifiConfig>) {
74 info!("Exiting power-saving mode");
75 cpu_config.apply_normal_mode(dry_run);
76 if let Err(e) = toggle_display(dry_run) {
77 warn!("toggle_display failed: {}", e);
78 }
79 if let Some(w) = wifi {
80 w.unblock(dry_run);
81 }
82}
83
84#[cfg(test)]
85mod tests {
86 use super::*;
87 use std::env;
88 use std::fs;
89
90 #[test]
91 fn test_enter_exit_saving_mode_dryrun() {
92 let tmp = env::temp_dir().join(format!(
93 "uconsole_pm_test_{}",
94 std::time::SystemTime::now()
95 .duration_since(std::time::UNIX_EPOCH)
96 .unwrap()
97 .as_millis()
98 ));
99 let _ = fs::create_dir_all(&tmp);
100 let cpu = CpuFreqConfig::with_policy_path(tmp.clone(), Some(String::from("100,200")));
101 enter_saving_mode(&cpu, true, None);
103 assert!(!tmp.join("scaling_min_freq").exists());
104 assert!(!tmp.join("scaling_max_freq").exists());
105
106 enter_saving_mode(&cpu, false, None);
108 assert!(tmp.join("scaling_min_freq").exists());
109 assert!(tmp.join("scaling_max_freq").exists());
110
111 exit_saving_mode(&cpu, false, None);
113 }
114}