Skip to main content

cadmus_core/device/power/
mod.rs

1//! Power management submodule.
2
3mod error;
4mod manager;
5
6cfg_select! {
7    feature = "kobo" => {
8        mod kobo;
9        pub(crate) use kobo::create_power_manager;
10    }
11    _ => {
12        mod stub;
13        pub(crate) use stub::create_power_manager;
14    }
15}
16
17pub use error::PowerError;
18pub use manager::PowerManager;
19
20pub(crate) fn discover_cores(
21    cpu_dir: &std::path::Path,
22) -> Result<Vec<(std::path::PathBuf, String)>, std::io::Error> {
23    let mut discovered = Vec::new();
24    if !cpu_dir.is_dir() {
25        return Ok(discovered);
26    }
27
28    for entry in std::fs::read_dir(cpu_dir)? {
29        let entry = entry?;
30        let path = entry.path();
31        if !path.is_dir() {
32            continue;
33        }
34
35        let file_name = match path.file_name().and_then(|s| s.to_str()) {
36            Some(name) => name,
37            None => continue,
38        };
39
40        if !file_name.starts_with("cpu") {
41            continue;
42        }
43        let core_id_str = &file_name[3..];
44        if !core_id_str.chars().all(|c| c.is_ascii_digit()) {
45            continue;
46        }
47
48        let online_path = path.join("online");
49        if !online_path.is_file() {
50            continue;
51        }
52
53        if let Ok(state_str) = std::fs::read_to_string(&online_path) {
54            let trimmed = state_str.trim().to_string();
55            discovered.push((online_path, trimmed));
56        }
57    }
58
59    Ok(discovered)
60}
61
62#[cfg(test)]
63mod tests {
64    use super::*;
65    #[cfg(not(feature = "kobo"))]
66    use crate::device::Model;
67
68    #[cfg(not(feature = "kobo"))]
69    #[test]
70    #[should_panic(expected = "There is no implementation for suspending on this build.")]
71    fn test_power_manager_stub_suspend_panics() {
72        let manager = create_power_manager(Model::Sage).expect("failed to create power manager");
73
74        let _ = manager.suspend();
75    }
76
77    #[cfg(not(feature = "kobo"))]
78    #[test]
79    #[should_panic(expected = "There is no implementation for resuming on this build.")]
80    fn test_power_manager_stub_resume_panics() {
81        let manager = create_power_manager(Model::Sage).expect("failed to create power manager");
82
83        let _ = manager.resume();
84    }
85
86    #[test]
87    fn test_discover_cores() {
88        let temp_dir = tempfile::tempdir().expect("failed to create temp dir");
89        let cpu_dir = temp_dir.path();
90
91        let cpu0_dir = cpu_dir.join("cpu0");
92        std::fs::create_dir(&cpu0_dir).expect("failed to create cpu0 dir");
93
94        let cpu1_dir = cpu_dir.join("cpu1");
95        std::fs::create_dir(&cpu1_dir).expect("failed to create cpu1 dir");
96        let cpu1_online = cpu1_dir.join("online");
97        std::fs::write(&cpu1_online, "0\n").expect("failed to write cpu1 online");
98
99        let cpu2_dir = cpu_dir.join("cpu2");
100        std::fs::create_dir(&cpu2_dir).expect("failed to create cpu2 dir");
101        let cpu2_online = cpu2_dir.join("online");
102        std::fs::write(&cpu2_online, "1").expect("failed to write cpu2 online");
103
104        let not_cpu_dir = cpu_dir.join("not_cpu");
105        std::fs::create_dir(&not_cpu_dir).expect("failed to create not_cpu dir");
106        let not_cpu_online = not_cpu_dir.join("online");
107        std::fs::write(&not_cpu_online, "1").expect("failed to write not_cpu online");
108
109        let mut cores = discover_cores(cpu_dir).expect("failed to discover cores");
110        cores.sort_by(|a, b| a.0.cmp(&b.0));
111
112        assert_eq!(cores.len(), 2);
113        assert_eq!(cores[0].0, cpu1_online);
114        assert_eq!(cores[0].1, "0");
115        assert_eq!(cores[1].0, cpu2_online);
116        assert_eq!(cores[1].1, "1");
117    }
118}