power_manager/
lib.rs

1// SPDX-FileCopyrightText: 2024 Foundation Devices, Inc. <hello@foundation.xyz>
2// SPDX-License-Identifier: GPL-3.0-or-later
3pub mod error;
4pub mod messages;
5
6pub use error::PowerManagerError;
7use messages::*;
8use server::{CheckedConn, CheckedPermissions, MessageAllowed};
9
10#[macro_export]
11macro_rules! use_api {
12    () => {
13        mod power_manager_permissions {
14            use power_manager::messages::*;
15            #[derive(Clone, Default, server::Permissions)]
16            #[server_name = "os/power-manager"]
17            pub struct PowerManagerPermissions;
18        }
19        type PowerManagerApi =
20            power_manager::PowerManagerApi<power_manager_permissions::PowerManagerPermissions>;
21    };
22}
23
24#[macro_export]
25macro_rules! use_ext_api {
26    () => {
27        mod power_manager_ext_permissions {
28            use power_manager::messages::*;
29            #[derive(Clone, Default, server::Permissions)]
30            #[server_name = "os/power-manager-ext"]
31            pub struct PowerManagerExtPermissions;
32        }
33        type PowerManagerExtApi =
34            power_manager::PowerManagerExtApi<power_manager_ext_permissions::PowerManagerExtPermissions>;
35    };
36}
37
38#[derive(Clone, Default)]
39pub struct PowerManagerApi<P: CheckedPermissions> {
40    conn: CheckedConn<P>,
41}
42
43impl<P: CheckedPermissions> PowerManagerApi<P> {
44    pub fn reboot(&self)
45    where
46        P: MessageAllowed<Reboot>,
47    {
48        self.conn.send_blocking_scalar(Reboot)
49    }
50
51    pub fn shutdown(&self)
52    where
53        P: MessageAllowed<Shutdown>,
54    {
55        self.conn.send_blocking_scalar(Shutdown)
56    }
57
58    #[cfg(keyos)]
59    pub fn enable_peripheral(&self, peripheral: atsama5d27::pmc::PeripheralId) -> Result<(), xous::Error>
60    where
61        P: MessageAllowed<SetPeripheralEnabled>,
62    {
63        self.conn.try_send_blocking_scalar(SetPeripheralEnabled { peripheral, enabled: true })
64    }
65
66    #[cfg(keyos)]
67    pub fn disable_peripheral(&self, peripheral: atsama5d27::pmc::PeripheralId) -> Result<(), xous::Error>
68    where
69        P: MessageAllowed<SetPeripheralEnabled>,
70    {
71        self.conn.try_send_blocking_scalar(SetPeripheralEnabled { peripheral, enabled: false })
72    }
73}
74
75#[derive(Clone, Default)]
76pub struct PowerManagerExtApi<P: CheckedPermissions> {
77    conn: CheckedConn<P>,
78}
79
80impl<P: CheckedPermissions> PowerManagerExtApi<P> {
81    pub fn status(&self) -> Result<Status, xous::Error>
82    where
83        P: MessageAllowed<GetStatus>,
84    {
85        self.conn.try_send_blocking_scalar(GetStatus)
86    }
87
88    pub fn extended_status(&self) -> Option<ExtendedStatus>
89    where
90        P: MessageAllowed<GetExtendedStatus>,
91    {
92        self.conn.send_blocking_archive(GetExtendedStatus)
93    }
94
95    pub fn set_usb_boost(&self, enabled: bool) -> Result<SetUsbBoostResponse, xous::Error>
96    where
97        P: MessageAllowed<SetUsbBoost>,
98    {
99        self.conn.try_send_blocking_scalar(SetUsbBoost { enabled })
100    }
101
102    #[cfg(not(keyos))]
103    pub fn set_battery_percent(&self, level: u8) -> Result<(), xous::Error>
104    where
105        P: MessageAllowed<SetBatteryPercent>,
106    {
107        self.conn.try_send_scalar(SetBatteryPercent(level))?;
108        Ok(())
109    }
110
111    #[cfg(keyos)]
112    pub fn set_otg_priority(&self, priority: OtgPriority) -> Result<(), xous::Error>
113    where
114        P: MessageAllowed<SetOtgPriority>,
115    {
116        self.conn.try_send_scalar(SetOtgPriority(priority))?;
117        Ok(())
118    }
119
120    #[cfg(keyos)]
121    pub fn clear_charger_fault(&self) -> Result<(), xous::Error>
122    where
123        P: MessageAllowed<ClearChargeFault>,
124    {
125        self.conn.try_send_scalar(ClearChargeFault)?;
126        Ok(())
127    }
128
129    pub fn subscribe_status<S>(&self, context: &mut server::ServerContext<S>)
130    where
131        S: server::Server + server::ScalarEventHandler<Status>,
132        P: MessageAllowed<StatusSubscribe>,
133    {
134        self.conn.subscribe_scalar_infallible(StatusSubscribe, context)
135    }
136}
137
138#[derive(Debug, Copy, Clone, Eq, PartialEq)]
139pub struct Status {
140    pub charge_status: ChargeStatus,
141    pub attached_state: AttachedState,
142    pub battery_percent: u8,
143}
144
145#[derive(num_derive::FromPrimitive, num_derive::ToPrimitive, Debug, Clone, Copy, PartialEq, Eq)]
146pub enum ChargeStatus {
147    Idle = 0,
148    Charging = 1,
149    ChargeDone = 2,
150    Boosting = 3,
151    Fault = 4,
152}
153
154/// Priority of the USB OTG mode.
155#[derive(num_derive::FromPrimitive, num_derive::ToPrimitive, Debug, Clone, Copy, PartialEq, Eq, Default)]
156pub enum OtgPriority {
157    /// Never host USB peripherals, always device mode.
158    #[default]
159    Never,
160    /// Prefer the device mode but allow host (OTG) mode if a peripheral is connected.
161    Automatic,
162    /// Always host USB peripherals, never device mode.
163    Forced,
164}
165
166#[cfg(keyos)]
167impl From<OtgPriority> for tusb320::ModeSelect {
168    fn from(priority: OtgPriority) -> Self {
169        match priority {
170            OtgPriority::Never => tusb320::ModeSelect::Ufp,
171            OtgPriority::Automatic => tusb320::ModeSelect::Drp,
172            OtgPriority::Forced => tusb320::ModeSelect::Dfp,
173        }
174    }
175}
176
177#[derive(num_derive::FromPrimitive, num_derive::ToPrimitive, Debug, Clone, Copy, PartialEq, Eq)]
178pub enum AttachedState {
179    None = 0,
180    Source = 1,
181    Sink = 2,
182    Accessory = 3,
183}
184
185#[cfg(keyos)]
186impl From<tusb320::AttachedState> for AttachedState {
187    fn from(value: tusb320::AttachedState) -> Self {
188        match value {
189            tusb320::AttachedState::NotAttached => AttachedState::None,
190            tusb320::AttachedState::AttachedSrc => AttachedState::Source,
191            tusb320::AttachedState::AttachedSnk => AttachedState::Sink,
192            tusb320::AttachedState::AttachedAccessory => AttachedState::Accessory,
193        }
194    }
195}