Browse Source

Add `os` module for querying OS and hardware state

Most of these are dead simple and don't require any service
initialization etc., so all we need is a simple wrapper. I didn't
implement everything in <3ds/os.h> yet, but got most of the basic ones
which seemed like likely use cases to me.
pull/136/head
Ian Chamberlain 1 year ago
parent
commit
c2827aa269
No known key found for this signature in database
GPG Key ID: AE5484D09405AA60
  1. 2
      ctru-rs/src/error.rs
  2. 1
      ctru-rs/src/lib.rs
  3. 135
      ctru-rs/src/os.rs

2
ctru-rs/src/error.rs

@ -152,6 +152,8 @@ impl fmt::Debug for Error {
impl fmt::Display for Error { impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
// TODO: should we consider using ctru_sys::osStrError here as well?
// It might do some of the work for us or provide additional details
&Self::Os(err) => write!( &Self::Os(err) => write!(
f, f,
"libctru result code 0x{err:08X}: [{} {}] {}: {}", "libctru result code 0x{err:08X}: [{} {}] {}: {}",

1
ctru-rs/src/lib.rs

@ -107,6 +107,7 @@ pub mod console;
pub mod error; pub mod error;
pub mod linear; pub mod linear;
pub mod mii; pub mod mii;
pub mod os;
pub mod prelude; pub mod prelude;
pub mod services; pub mod services;

135
ctru-rs/src/os.rs

@ -0,0 +1,135 @@
//! Utilities to get information about the operating system and hardware state.
/// System version information.
#[derive(Clone, Copy)]
pub struct Version(u32);
impl Version {
/// Pack a system version from its components
pub fn new(major: u8, minor: u8, revision: u8) -> Self {
let major = u32::from(major);
let minor = u32::from(minor);
let revision = u32::from(revision);
Self(major << 24 | minor << 16 | revision << 8)
}
/// Get the major version from a packed system version.
pub fn major(&self) -> u8 {
(self.0 >> 24).try_into().unwrap()
}
/// Get the minor version from a packed system version.
pub fn minor(&self) -> u8 {
(self.0 >> 16 & 0xFF).try_into().unwrap()
}
/// Get the revision from a packed system version.
pub fn revision(&self) -> u8 {
(self.0 >> 8 & 0xFF).try_into().unwrap()
}
}
/// Get the system's FIRM version.
pub fn firm_version() -> Version {
Version(unsafe { ctru_sys::osGetFirmVersion() })
}
/// Get the system's kernel version.
pub fn kernel_version() -> Version {
Version(unsafe { ctru_sys::osGetKernelVersion() })
}
// TODO: I can't seem to find good documentation on it, but we could probably
// define enums for firmware type (NATIVE_FIRM, SAFE_FIRM etc.) as well as
// application memory layout. Leaving those as future enhancements for now
/// A region of memory. Most applications will only use [`Application`](MemRegion::Application)
/// memory, but the other types can be used to query memory usage information.
/// See <https://www.3dbrew.org/wiki/Memory_layout#FCRAM_memory-regions_layout>
/// for more details on the different types of memory.
///
/// # Example
/// ```
/// # let _runner = test_runner::GdbRunner::default();
/// let all_memory = ctru::os::MemRegion::All;
///
/// assert!(all_memory.size() > 0);
/// assert!(all_memory.used() > 0);
/// assert!(all_memory.free() > 0);
/// ```
#[derive(Clone, Copy, Debug)]
#[non_exhaustive]
#[repr(u32)]
pub enum MemRegion {
/// All memory regions.
All = ctru_sys::MEMREGION_ALL,
/// APPLICATION memory.
Application = ctru_sys::MEMREGION_APPLICATION,
/// SYSTEM memory.
System = ctru_sys::MEMREGION_SYSTEM,
/// BASE memory.
Base = ctru_sys::MEMREGION_BASE,
}
impl MemRegion {
/// Get the total size of this memory region, in bytes.
pub fn size(&self) -> usize {
unsafe { ctru_sys::osGetMemRegionSize(*self as u32) }
.try_into()
.unwrap()
}
/// Get the number of bytes used within this memory region.
pub fn used(&self) -> usize {
unsafe { ctru_sys::osGetMemRegionUsed(*self as u32) }
.try_into()
.unwrap()
}
/// Get the number of bytes free within this memory region.
pub fn free(&self) -> usize {
unsafe { ctru_sys::osGetMemRegionFree(*self as u32) }
.try_into()
.unwrap()
}
}
/// WiFi signal strength. This enum's [`u8`] representation corresponds with
/// the number of bars displayed in the Home menu.
#[non_exhaustive]
#[repr(u8)]
pub enum WifiStrength {
/// This may indicate a very poor signal quality even worse than `Bad`,
/// or it may indicate that no network is connected at all.
Disconnected = 0,
/// Poor signal strength.
Bad = 1,
/// Medium signal strength.
Decent = 2,
/// Good signal strength.
Good = 3,
}
impl WifiStrength {
/// Get the current WiFi signal strength.
pub fn current() -> Self {
match unsafe { ctru_sys::osGetWifiStrength() } {
0 => Self::Disconnected,
1 => Self::Bad,
2 => Self::Decent,
3 => Self::Good,
other => panic!("Got unexpected WiFi strength value {other}"),
}
}
}
/// Get the current value of the stereoscopic 3D slider on a scale from 0.0­­1.0.
pub fn current_3d_slider_state() -> f32 {
unsafe { ctru_sys::osGet3DSliderState() }
}
/// Whether or not a headset is currently plugged into the device.
pub fn is_headset_connected() -> bool {
unsafe { ctru_sys::osIsHeadsetConnected() }
}
Loading…
Cancel
Save