Browse Source

Finished HID and CFGU

pull/134/head
Andrea Ciliberti 1 year ago
parent
commit
db2bb7c765
  1. 117
      ctru-rs/src/services/cfgu.rs
  2. 150
      ctru-rs/src/services/hid.rs

117
ctru-rs/src/services/cfgu.rs

@ -4,7 +4,7 @@
use crate::error::ResultCode; use crate::error::ResultCode;
/// Console's region. /// Console region.
#[doc(alias = "CFG_Region")] #[doc(alias = "CFG_Region")]
#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)] #[repr(u32)]
@ -56,7 +56,7 @@ pub enum Language {
TraditionalChinese = ctru_sys::CFG_LANGUAGE_TW, TraditionalChinese = ctru_sys::CFG_LANGUAGE_TW,
} }
/// 3DS model. /// Specific model of the console.
#[doc(alias = "CFG_SystemModel")] #[doc(alias = "CFG_SystemModel")]
#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)] #[repr(u32)]
@ -75,30 +75,47 @@ pub enum SystemModel {
New2DSXL = ctru_sys::CFG_MODEL_N2DSXL, New2DSXL = ctru_sys::CFG_MODEL_N2DSXL,
} }
/// Represents the configuration service. No actions can be performed /// Handle to the System Configuration service.
/// until an instance of this struct is created.
///
/// The service exits when all instances of this struct go out of scope.
pub struct Cfgu(()); pub struct Cfgu(());
impl Cfgu { impl Cfgu {
/// Initialize a new service handle. /// Initialize a new service handle.
/// ///
/// # Errors /// # Example
/// ///
/// This function will return Err if there was an error initializing the /// ```no_run
/// CFGU service. /// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// #
/// use ctru::services::cfgu::Cfgu;
/// ///
/// ctrulib services are reference counted, so this function may be called /// let cfgu = Cfgu::new()?;
/// as many times as desired and the service will not exit until all /// #
/// instances of Cfgu drop out of scope. /// # Ok(())
/// # }
/// ```
#[doc(alias = "cfguInit")] #[doc(alias = "cfguInit")]
pub fn new() -> crate::Result<Cfgu> { pub fn new() -> crate::Result<Cfgu> {
ResultCode(unsafe { ctru_sys::cfguInit() })?; ResultCode(unsafe { ctru_sys::cfguInit() })?;
Ok(Cfgu(())) Ok(Cfgu(()))
} }
/// Gets system region from secure info /// Returns the console's region from the system's secure info.
///
/// # Example
///
/// ```no_run
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// #
/// use ctru::services::cfgu::Cfgu;
/// let cfgu = Cfgu::new()?;
///
/// let region = cfgu.region()?;
/// #
/// # Ok(())
/// # }
/// ```
#[doc(alias = "CFGU_SecureInfoGetRegion")] #[doc(alias = "CFGU_SecureInfoGetRegion")]
pub fn region(&self) -> crate::Result<Region> { pub fn region(&self) -> crate::Result<Region> {
let mut region: u8 = 0; let mut region: u8 = 0;
@ -107,7 +124,22 @@ impl Cfgu {
Ok(Region::try_from(region).unwrap()) Ok(Region::try_from(region).unwrap())
} }
/// Gets system's model /// Returns the console's model.
///
/// # Example
///
/// ```no_run
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// #
/// use ctru::services::cfgu::Cfgu;
/// let cfgu = Cfgu::new()?;
///
/// let model = cfgu.model()?;
/// #
/// # Ok(())
/// # }
/// ```
#[doc(alias = "CFGU_GetSystemModel")] #[doc(alias = "CFGU_GetSystemModel")]
pub fn model(&self) -> crate::Result<SystemModel> { pub fn model(&self) -> crate::Result<SystemModel> {
let mut model: u8 = 0; let mut model: u8 = 0;
@ -116,7 +148,22 @@ impl Cfgu {
Ok(SystemModel::try_from(model).unwrap()) Ok(SystemModel::try_from(model).unwrap())
} }
/// Gets system's language /// Returns the system language set for the console.
///
/// # Example
///
/// ```no_run
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// #
/// use ctru::services::cfgu::Cfgu;
/// let cfgu = Cfgu::new()?;
///
/// let language = cfgu.language()?;
/// #
/// # Ok(())
/// # }
/// ```
#[doc(alias = "CFGU_GetSystemLanguage")] #[doc(alias = "CFGU_GetSystemLanguage")]
pub fn language(&self) -> crate::Result<Language> { pub fn language(&self) -> crate::Result<Language> {
let mut language: u8 = 0; let mut language: u8 = 0;
@ -125,7 +172,24 @@ impl Cfgu {
Ok(Language::try_from(language).unwrap()) Ok(Language::try_from(language).unwrap())
} }
/// Checks if NFC is supported by the console /// Check if NFC is supported by the console.
///
/// # Example
///
/// ```no_run
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// #
/// use ctru::services::cfgu::Cfgu;
/// let cfgu = Cfgu::new()?;
///
/// if cfgu.is_nfc_supported()? {
/// println!("NFC is available!");
/// }
/// #
/// # Ok(())
/// # }
/// ```
#[doc(alias = "CFGU_IsNFCSupported")] #[doc(alias = "CFGU_IsNFCSupported")]
pub fn is_nfc_supported(&self) -> crate::Result<bool> { pub fn is_nfc_supported(&self) -> crate::Result<bool> {
let mut supported: bool = false; let mut supported: bool = false;
@ -134,7 +198,26 @@ impl Cfgu {
Ok(supported) Ok(supported)
} }
/// Check if the console is from the 2DS family (2DS, New2DS, New2DSXL) /// Check if the console is from the 2DS family ([`Old2DS`](SystemModel::Old2DS), [`New2DSXL`](SystemModel::New2DSXL)).
///
/// Useful to avoid stereoscopic 3D rendering when working with 2DS consoles.
///
/// # Example
///
/// ```no_run
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// #
/// use ctru::services::cfgu::Cfgu;
/// let cfgu = Cfgu::new()?;
///
/// if cfgu.is_2ds_family()? {
/// println!("Stereoscopic 3D is not supported.");
/// }
/// #
/// # Ok(())
/// # }
/// ```
#[doc(alias = "CFGU_GetModelNintendo2DS")] #[doc(alias = "CFGU_GetModelNintendo2DS")]
pub fn is_2ds_family(&self) -> crate::Result<bool> { pub fn is_2ds_family(&self) -> crate::Result<bool> {
let mut is_2ds_family: u8 = 0; let mut is_2ds_family: u8 = 0;

150
ctru-rs/src/services/hid.rs

@ -1,15 +1,14 @@
//! Human-Interface Device service. //! Human Interface Device service.
//! //!
//! The HID service provides access to user input such as button presses, touch screen presses, //! The HID service provides read access to user input such as [button presses](Hid::keys_down), [touch screen presses](Hid::touch_position),
//! and circle pad information. It also provides information from the sound volume slider, //! and [circle pad information](Hid::circlepad_position). It also provides information from the sound volume slider, the accelerometer, and the gyroscope.
//! the accelerometer, and the gyroscope. // TODO: Implement volume slider, accelerometer and gyroscope + any other missing functionality.
use crate::error::ResultCode; use crate::error::ResultCode;
use bitflags::bitflags; use bitflags::bitflags;
bitflags! { bitflags! {
/// A set of flags corresponding to the button and directional pad /// A set of flags corresponding to the button and directional pad inputs present on the 3DS.
/// inputs on the 3DS
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)] #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
pub struct KeyPad: u32 { pub struct KeyPad: u32 {
/// A button. /// A button.
@ -72,10 +71,7 @@ bitflags! {
} }
} }
/// A reference-counted handle to the HID service. The service is closed /// Handle to the HID service.
/// when all instances of this struct fall out of scope.
///
/// This service requires no special permissions to use.
pub struct Hid(()); pub struct Hid(());
impl Hid { impl Hid {
@ -84,8 +80,21 @@ impl Hid {
/// # Errors /// # Errors
/// ///
/// This function will return an error if the service was unable to be initialized. /// This function will return an error if the service was unable to be initialized.
/// Since this service requires no special or elevated permissions, errors are /// Since this service requires no special or elevated permissions, errors are rare in practice.
/// rare in practice. ///
/// # Example
///
/// ```no_run
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// #
/// use ctru::services::hid::Hid;
///
/// let hid = Hid::new()?;
/// #
/// # Ok(())
/// # }
/// ```
#[doc(alias = "hidInit")] #[doc(alias = "hidInit")]
pub fn new() -> crate::Result<Hid> { pub fn new() -> crate::Result<Hid> {
unsafe { unsafe {
@ -94,9 +103,25 @@ impl Hid {
} }
} }
/// Scans the HID service for all user input occurring on the current /// Scan the HID service for all user input occurring on the current frame.
/// frame. This function should be called on every frame when polling ///
/// This function should be called on every frame when polling
/// for user input. /// for user input.
///
/// # Example
///
/// ```no_run
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// #
/// use ctru::services::hid::Hid;
/// let mut hid = Hid::new()?;
///
/// hid.scan_input();
/// #
/// # Ok(())
/// # }
/// ```
#[doc(alias = "hidScanInput")] #[doc(alias = "hidScanInput")]
pub fn scan_input(&mut self) { pub fn scan_input(&mut self) {
unsafe { ctru_sys::hidScanInput() }; unsafe { ctru_sys::hidScanInput() };
@ -104,6 +129,25 @@ impl Hid {
/// Returns a bitflag struct representing which buttons have just been pressed /// Returns a bitflag struct representing which buttons have just been pressed
/// on the current frame (and were not pressed on the previous frame). /// on the current frame (and were not pressed on the previous frame).
///
/// # Example
///
/// ```no_run
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// #
/// use ctru::services::hid::{Hid, KeyPad};
/// let mut hid = Hid::new()?;
///
/// hid.scan_input();
///
/// if hid.keys_down().contains(KeyPad::A) {
/// println!("You just pressed the A button!")
/// }
/// #
/// # Ok(())
/// # }
/// ```
#[doc(alias = "hidKeysDown")] #[doc(alias = "hidKeysDown")]
pub fn keys_down(&self) -> KeyPad { pub fn keys_down(&self) -> KeyPad {
unsafe { unsafe {
@ -114,6 +158,25 @@ impl Hid {
/// Returns a bitflag struct representing which buttons have been held down /// Returns a bitflag struct representing which buttons have been held down
/// during the current frame. /// during the current frame.
///
/// # Example
///
/// ```no_run
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// #
/// use ctru::services::hid::{Hid, KeyPad};
/// let mut hid = Hid::new()?;
///
/// hid.scan_input();
///
/// if hid.keys_held().contains(KeyPad::START) {
/// println!("You are holding the START button!")
/// }
/// #
/// # Ok(())
/// # }
/// ```
#[doc(alias = "hidKeysHeld")] #[doc(alias = "hidKeysHeld")]
pub fn keys_held(&self) -> KeyPad { pub fn keys_held(&self) -> KeyPad {
unsafe { unsafe {
@ -124,6 +187,25 @@ impl Hid {
/// Returns a bitflag struct representing which buttons have just been released on /// Returns a bitflag struct representing which buttons have just been released on
/// the current frame. /// the current frame.
///
/// # Example
///
/// ```no_run
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// #
/// use ctru::services::hid::{Hid, KeyPad};
/// let mut hid = Hid::new()?;
///
/// hid.scan_input();
///
/// if hid.keys_held().contains(KeyPad::B) {
/// println!("You have released the B button!")
/// }
/// #
/// # Ok(())
/// # }
/// ```
#[doc(alias = "hidKeysUp")] #[doc(alias = "hidKeysUp")]
pub fn keys_up(&self) -> KeyPad { pub fn keys_up(&self) -> KeyPad {
unsafe { unsafe {
@ -137,13 +219,31 @@ impl Hid {
/// # Notes /// # Notes
/// ///
/// (0, 0) represents the top left corner of the screen. /// (0, 0) represents the top left corner of the screen.
///
/// # Example
///
/// ```no_run
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// #
/// use ctru::services::hid::Hid;
/// let mut hid = Hid::new()?;
///
/// hid.scan_input();
///
/// let (touch_x, touch_y) = hid.touch_position();
/// #
/// # Ok(())
/// # }
/// ```
#[doc(alias = "hidTouchRead")] #[doc(alias = "hidTouchRead")]
pub fn touch_position(&mut self) -> (u16, u16) { pub fn touch_position(&self) -> (u16, u16) {
let mut res = ctru_sys::touchPosition { px: 0, py: 0 }; let mut res = ctru_sys::touchPosition { px: 0, py: 0 };
unsafe { unsafe {
ctru_sys::hidTouchRead(&mut res); ctru_sys::hidTouchRead(&mut res);
} }
(res.px, res.py) (res.px, res.py)
} }
@ -152,13 +252,31 @@ impl Hid {
/// # Notes /// # Notes
/// ///
/// (0, 0) represents the center of the circle pad. /// (0, 0) represents the center of the circle pad.
///
/// # Example
///
/// ```no_run
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// #
/// use ctru::services::hid::Hid;
/// let mut hid = Hid::new()?;
///
/// hid.scan_input();
///
/// let (pad_x, pad_y) = hid.circlepad_position();
/// #
/// # Ok(())
/// # }
/// ```
#[doc(alias = "hidCircleRead")] #[doc(alias = "hidCircleRead")]
pub fn circlepad_position(&mut self) -> (i16, i16) { pub fn circlepad_position(&self) -> (i16, i16) {
let mut res = ctru_sys::circlePosition { dx: 0, dy: 0 }; let mut res = ctru_sys::circlePosition { dx: 0, dy: 0 };
unsafe { unsafe {
ctru_sys::hidCircleRead(&mut res); ctru_sys::hidCircleRead(&mut res);
} }
(res.dx, res.dy) (res.dx, res.dy)
} }
} }

Loading…
Cancel
Save