ctru/
os.rs

1//! Utilities to get information about the operating system and hardware state.
2
3/// System version information. This struct is used for both kernel and firmware versions.
4///
5/// # Example
6/// ```
7/// # let _runner = test_runner::GdbRunner::default();
8/// let firm_version = ctru::os::firm_version();
9/// assert_ne!(firm_version.major(), 0);
10///
11/// let kernel_version = ctru::os::kernel_version();
12/// assert_ne!(kernel_version.major(), 0);
13/// ```
14#[derive(Clone, Copy)]
15pub struct Version(u32);
16
17impl Version {
18    /// Pack a system version from its components
19    pub fn new(major: u8, minor: u8, revision: u8) -> Self {
20        let major = u32::from(major);
21        let minor = u32::from(minor);
22        let revision = u32::from(revision);
23
24        Self(major << 24 | minor << 16 | revision << 8)
25    }
26
27    /// Get the major version from a packed system version.
28    pub fn major(&self) -> u8 {
29        (self.0 >> 24).try_into().unwrap()
30    }
31
32    /// Get the minor version from a packed system version.
33    pub fn minor(&self) -> u8 {
34        (self.0 >> 16 & 0xFF).try_into().unwrap()
35    }
36
37    /// Get the revision from a packed system version.
38    pub fn revision(&self) -> u8 {
39        (self.0 >> 8 & 0xFF).try_into().unwrap()
40    }
41}
42
43/// Get the system's FIRM version.
44pub fn firm_version() -> Version {
45    Version(unsafe { ctru_sys::osGetFirmVersion() })
46}
47
48/// Get the system's kernel version.
49pub fn kernel_version() -> Version {
50    Version(unsafe { ctru_sys::osGetKernelVersion() })
51}
52
53// TODO: I can't seem to find good documentation on it, but we could probably
54// define enums for firmware type (NATIVE_FIRM, SAFE_FIRM etc.) as well as
55// application memory layout. Leaving those as future enhancements for now
56
57/// A region of memory. Most applications will only use [`Application`](MemRegion::Application)
58/// memory, but the other types can be used to query memory usage information.
59/// See <https://www.3dbrew.org/wiki/Memory_layout#FCRAM_memory-regions_layout>
60/// for more details on the different types of memory.
61///
62/// # Example
63/// ```
64/// # let _runner = test_runner::GdbRunner::default();
65/// let all_memory = ctru::os::MemRegion::All;
66///
67/// assert!(all_memory.size() > 0);
68/// assert!(all_memory.used() > 0);
69/// assert!(all_memory.free() > 0);
70/// ```
71#[derive(Clone, Copy, Debug)]
72#[non_exhaustive]
73#[repr(u8)]
74pub enum MemRegion {
75    /// All memory regions.
76    All = ctru_sys::MEMREGION_ALL,
77    /// APPLICATION memory.
78    Application = ctru_sys::MEMREGION_APPLICATION,
79    /// SYSTEM memory.
80    System = ctru_sys::MEMREGION_SYSTEM,
81    /// BASE memory.
82    Base = ctru_sys::MEMREGION_BASE,
83}
84
85impl MemRegion {
86    /// Get the total size of this memory region, in bytes.
87    pub fn size(&self) -> usize {
88        unsafe { ctru_sys::osGetMemRegionSize(*self as u8) }
89            .try_into()
90            .unwrap()
91    }
92
93    /// Get the number of bytes used within this memory region.
94    pub fn used(&self) -> usize {
95        unsafe { ctru_sys::osGetMemRegionUsed(*self as u8) }
96            .try_into()
97            .unwrap()
98    }
99
100    /// Get the number of bytes free within this memory region.
101    pub fn free(&self) -> usize {
102        unsafe { ctru_sys::osGetMemRegionFree(*self as u8) }
103            .try_into()
104            .unwrap()
105    }
106}
107
108/// WiFi signal strength. This enum's `u8` representation corresponds with
109/// the number of bars displayed in the Home menu.
110///
111/// # Example
112///
113/// ```
114/// let _runner = test_runner::GdbRunner::default();
115/// let strength = ctru::os::WifiStrength::current();
116/// assert!((strength as u8) < 4);
117/// ```
118#[derive(Clone, Copy, Debug)]
119#[non_exhaustive]
120#[repr(u8)]
121pub enum WifiStrength {
122    /// This may indicate a very poor signal quality even worse than `Bad`,
123    /// or that no network is connected at all.
124    Disconnected = 0,
125    /// Poor signal strength.
126    Bad = 1,
127    /// Medium signal strength.
128    Decent = 2,
129    /// Good signal strength.
130    Good = 3,
131}
132
133impl WifiStrength {
134    /// Get the current WiFi signal strength.
135    pub fn current() -> Self {
136        match unsafe { ctru_sys::osGetWifiStrength() } {
137            0 => Self::Disconnected,
138            1 => Self::Bad,
139            2 => Self::Decent,
140            3 => Self::Good,
141            other => panic!("Got unexpected WiFi strength value {other}"),
142        }
143    }
144}
145
146/// Get the current value of the stereoscopic 3D slider on a scale from 0.0­–­1.0.
147pub fn current_3d_slider_state() -> f32 {
148    unsafe { ctru_sys::osGet3DSliderState() }
149}
150
151/// Whether or not a headset is currently plugged into the device.
152pub fn is_headset_connected() -> bool {
153    unsafe { ctru_sys::osIsHeadsetConnected() }
154}