Skip to content

Commit 2912f29

Browse files
authored
Add basic PTM service implementation (#198)
* WIP PTM service * Complete PTM:User implementation * Add PTM:SysM implementation * Fix typo in sysm example * Bump rustdoc toolchain
1 parent 5c4c27c commit 2912f29

File tree

5 files changed

+459
-0
lines changed

5 files changed

+459
-0
lines changed

ctru-rs/examples/ptm-user.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//! Power-Time Services example.
2+
//!
3+
//! This example shows off common functionality found in the PTM family of system services, like pedometer steps count, battery state reading
4+
//! and some light shows with the notification LED.
5+
6+
use ctru::prelude::*;
7+
use ctru::services::ptm::user::{BatteryLevel, PTMUser};
8+
9+
fn main() {
10+
let apt = Apt::new().unwrap();
11+
let mut hid = Hid::new().unwrap();
12+
let gfx = Gfx::new().unwrap();
13+
let _top_screen = Console::new(gfx.top_screen.borrow_mut());
14+
15+
let ptm_user = PTMUser::new().unwrap();
16+
17+
// Let's gather some simple data with PTM:User
18+
let battery_level = ptm_user.battery_level().unwrap();
19+
let charging = ptm_user.is_charging().unwrap();
20+
let steps = ptm_user.step_count().unwrap();
21+
22+
if battery_level >= BatteryLevel::Low {
23+
println!("The battery level is sufficient to play a while.")
24+
} else {
25+
println!("The battery level is low.")
26+
}
27+
28+
if charging {
29+
println!("The battery is currently charging.")
30+
} else {
31+
println!("The battery is discharging.")
32+
}
33+
34+
println!("You accumulated a total of {steps} steps.");
35+
36+
println!("\x1b[29;16HPress Start to exit");
37+
38+
while apt.main_loop() {
39+
gfx.wait_for_vblank();
40+
41+
hid.scan_input();
42+
if hid.keys_down().contains(KeyPad::START) {
43+
break;
44+
}
45+
}
46+
}

ctru-rs/src/services/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ pub mod hid;
2222
pub mod ir_user;
2323
pub mod ndsp;
2424
pub mod ps;
25+
pub mod ptm;
2526
mod reference;
2627
pub mod soc;
2728
pub mod sslc;

ctru-rs/src/services/ptm/mod.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//! Power-Time service.
2+
//!
3+
//! This service manages user information such as registered playtime, step count (using the pedometer) and control to various
4+
//! hardware and features to notify the user during play (such as the Notification/Info LED).
5+
#![doc(alias = "led")]
6+
#![doc(alias = "playtime")]
7+
#![doc(alias = "step")]
8+
#![doc(alias = "power")]
9+
10+
pub mod sysm;
11+
pub mod user;

ctru-rs/src/services/ptm/sysm.rs

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
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")]
8+
use std::sync::Mutex;
9+
use std::time::Duration;
10+
11+
use crate::error::{Result, ResultCode};
12+
use crate::services::ServiceReference;
13+
14+
static PTMSYSM_ACTIVE: Mutex<()> = Mutex::new(());
15+
16+
/// Handle to the PTM:SysM service.
17+
pub struct PTMSysM {
18+
_service_handler: ServiceReference,
19+
}
20+
21+
impl 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+
}

0 commit comments

Comments
 (0)