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