ctru/services/ptm/
sysm.rs

1//! PTM SystemMenu service.
2//!
3//! This sub-service of the Power-Time service family is able to control shutdown/sleep functionality and how those states are
4//! communicated to the user (such as via the notification/battery LED).
5#[doc(alias = "sleep")]
6#[doc(alias = "shutdown")]
7#[doc(alias = "led")]
8use std::sync::Mutex;
9use std::time::Duration;
10
11use crate::error::{Result, ResultCode};
12use crate::services::ServiceReference;
13
14static PTMSYSM_ACTIVE: Mutex<()> = Mutex::new(());
15
16/// Handle to the PTM:SysM service.
17pub struct PTMSysM {
18    _service_handler: ServiceReference,
19}
20
21impl PTMSysM {
22    /// Initialize a new service handle.
23    ///
24    /// # Errors
25    ///
26    /// This function will return an error if the service was unable to be initialized.
27    /// Since this service requires no special or elevated permissions, errors are rare in practice.
28    ///
29    /// # Example
30    ///
31    /// ```
32    /// # let _runner = test_runner::GdbRunner::default();
33    /// # use std::error::Error;
34    /// # fn main() -> Result<(), Box<dyn Error>> {
35    /// #
36    /// use ctru::services::ptm::sysm::PTMSysM;
37    ///
38    /// let ptm_sysm = PTMSysM::new()?;
39    /// #
40    /// # Ok(())
41    /// # }
42    /// ```
43    #[doc(alias = "ptmSysmInit")]
44    pub fn new() -> Result<Self> {
45        let handler = ServiceReference::new(
46            &PTMSYSM_ACTIVE,
47            || {
48                ResultCode(unsafe { ctru_sys::ptmSysmInit() })?;
49
50                Ok(())
51            },
52            || unsafe {
53                ctru_sys::ptmSysmExit();
54            },
55        )?;
56
57        Ok(Self {
58            _service_handler: handler,
59        })
60    }
61
62    /// Try putting the console in sleep mode.
63    ///
64    /// # Notes
65    ///
66    /// This request can be denied for various reasons. This does not "force" the console to sleep.
67    ///
68    /// # Example
69    ///
70    /// ```
71    /// # let _runner = test_runner::GdbRunner::default();
72    /// # use std::error::Error;
73    /// # fn main() -> Result<(), Box<dyn Error>> {
74    /// #
75    /// use ctru::services::ptm::sysm::PTMSysM;
76    /// use std::time::Duration;
77    ///
78    /// let ptm_sysm = PTMSysM::new()?;
79    ///
80    /// // Request the activation of sleep mode.
81    /// ptm_sysm.request_sleep().unwrap();
82    /// #
83    /// # Ok(())
84    /// # }
85    /// ```
86    #[doc(alias = "PTMSYSM_RequestSleep")]
87    pub fn request_sleep(&self) -> Result<()> {
88        ResultCode(unsafe { ctru_sys::PTMSYSM_RequestSleep() })?;
89
90        Ok(())
91    }
92
93    /// Request a system shutdown within the given timeout.
94    ///
95    /// # Example
96    ///
97    /// ```
98    /// # let _runner = test_runner::GdbRunner::default();
99    /// # use std::error::Error;
100    /// # fn main() -> Result<(), Box<dyn Error>> {
101    /// #
102    /// use ctru::services::ptm::sysm::PTMSysM;
103    /// use std::time::Duration;
104    ///
105    /// let ptm_sysm = PTMSysM::new()?;
106    ///
107    /// // Shutdown the system (usually the request succeeds immediately).
108    /// ptm_sysm.request_shutdown(Duration::from_nanos(0)).unwrap();
109    /// #
110    /// # Ok(())
111    /// # }
112    /// ```
113    #[doc(alias = "PTMSYSM_ShutdownAsync")]
114    pub fn request_shutdown(&self, timeout: Duration) -> Result<()> {
115        let timeout = timeout.as_nanos() as u64;
116
117        ResultCode(unsafe { ctru_sys::PTMSYSM_ShutdownAsync(timeout) })?;
118
119        Ok(())
120    }
121
122    /// Request a system reboot within the given timeout.
123    ///
124    /// # Example
125    ///
126    /// ```
127    /// # let _runner = test_runner::GdbRunner::default();
128    /// # use std::error::Error;
129    /// # fn main() -> Result<(), Box<dyn Error>> {
130    /// #
131    /// use ctru::services::ptm::sysm::PTMSysM;
132    /// use std::time::Duration;
133    ///
134    /// let ptm_sysm = PTMSysM::new()?;
135    ///
136    /// // Reboot the system.
137    /// ptm_sysm.request_reboot(Duration::from_nanos(0)).unwrap();
138    /// #
139    /// # Ok(())
140    /// # }
141    /// ```
142    #[doc(alias = "PTMSYSM_RebootAsync")]
143    pub fn request_reboot(&self, timeout: Duration) -> Result<()> {
144        let timeout = timeout.as_nanos() as u64;
145
146        ResultCode(unsafe { ctru_sys::PTMSYSM_RebootAsync(timeout) })?;
147
148        Ok(())
149    }
150}