starnix_core/power/
state.rs1use crate::task::CurrentTask;
6use crate::vfs::FsNodeOps;
7use crate::vfs::pseudo::simple_file::{BytesFile, BytesFileOps};
8use fidl_fuchsia_power_broker::PowerLevel;
9use starnix_logging::{log_info, log_warn};
10use starnix_sync::{FileOpsCore, Locked};
11use starnix_uapi::errors::Errno;
12use starnix_uapi::{errno, error};
13use std::borrow::Cow;
14
15#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
16pub enum SuspendState {
17 Disk,
21 Ram,
26 Standby,
32 Idle,
36}
37
38impl std::fmt::Display for SuspendState {
39 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
40 match self {
41 SuspendState::Disk => write!(f, "disk"),
42 SuspendState::Ram => write!(f, "ram"),
43 SuspendState::Standby => write!(f, "standby"),
44 SuspendState::Idle => write!(f, "freeze"),
45 }
46 }
47}
48
49impl From<SuspendState> for PowerLevel {
50 fn from(value: SuspendState) -> Self {
51 match value {
52 SuspendState::Disk => 0,
53 SuspendState::Ram => 1,
54 SuspendState::Standby => 2,
55 SuspendState::Idle => 3,
56 }
57 }
58}
59
60pub struct PowerStateFile;
61
62impl PowerStateFile {
63 pub fn new_node() -> impl FsNodeOps {
64 BytesFile::new_node(Self {})
65 }
66}
67
68impl BytesFileOps for PowerStateFile {
69 fn write_locked(
70 &self,
71 locked: &mut Locked<FileOpsCore>,
72 current_task: &CurrentTask,
73 data: Vec<u8>,
74 ) -> Result<(), Errno> {
75 let state_str = std::str::from_utf8(&data).map_err(|_| errno!(EINVAL))?;
76 let clean_state_str = state_str.split('\n').next().unwrap_or("");
77 let state = match clean_state_str {
78 "disk" => SuspendState::Disk,
79 "standby" => SuspendState::Standby,
80 "freeze" | "mem" => SuspendState::Idle,
83 _ => return error!(EINVAL),
84 };
85 let power_manager = ¤t_task.kernel().suspend_resume_manager;
86 let supported_states = power_manager.suspend_states();
87 if !supported_states.contains(&state) {
88 return error!(EINVAL);
89 }
90 log_info!(state:?; "Received write to power state file.");
91 fuchsia_trace::duration!("power", "starnix-sysfs:suspend");
93 power_manager.suspend(locked, state).inspect_err(|e| log_warn!("Suspend failed: {e}"))?;
95
96 Ok(())
97 }
98
99 fn read(&self, current_task: &CurrentTask) -> Result<Cow<'_, [u8]>, Errno> {
100 let states = current_task.kernel().suspend_resume_manager.suspend_states();
101 let mut states_array: Vec<String> = states.iter().map(SuspendState::to_string).collect();
102 states_array.push("mem".to_string());
105 states_array.sort();
106 let content = states_array.join(" ") + "\n";
107 Ok(content.as_bytes().to_owned().into())
108 }
109}