Browse Source

Split parental lock into a different type

pull/149/head
Andrea Ciliberti 1 year ago
parent
commit
ab9713941c
  1. 1
      ctru-rs/src/applets/mii_selector.rs
  2. 117
      ctru-rs/src/applets/swkbd.rs

1
ctru-rs/src/applets/mii_selector.rs

@ -277,6 +277,7 @@ impl MiiSelector {
/// # } /// # }
/// ``` /// ```
#[doc(alias = "miiSelectorLaunch")] #[doc(alias = "miiSelectorLaunch")]
#[allow(unused_variables)]
pub fn launch(&mut self, apt: &Apt, gfx: &Gfx) -> Result<Selection, Error> { pub fn launch(&mut self, apt: &Apt, gfx: &Gfx) -> Result<Selection, Error> {
let mut return_val = Box::<ctru_sys::MiiSelectorReturn>::default(); let mut return_val = Box::<ctru_sys::MiiSelectorReturn>::default();
unsafe { ctru_sys::miiSelectorLaunch(self.config.as_mut(), return_val.as_mut()) } unsafe { ctru_sys::miiSelectorLaunch(self.config.as_mut(), return_val.as_mut()) }

117
ctru-rs/src/applets/swkbd.rs

@ -2,14 +2,13 @@
//! //!
//! This applet opens a virtual keyboard on the console's bottom screen which lets the user write UTF-16 valid text. //! This applet opens a virtual keyboard on the console's bottom screen which lets the user write UTF-16 valid text.
// TODO: Implement remaining functionality (password mode, filter callbacks, etc.). Also improve "max text length" API. Improve `number of buttons` API when creating a new SoftwareKeyboard. // TODO: Implement remaining functionality (password mode, filter callbacks, etc.). Also improve "max text length" API. Improve `number of buttons` API when creating a new SoftwareKeyboard.
// TODO: Split the Parental PIN lock operations into a different type.
#![doc(alias = "keyboard")] #![doc(alias = "keyboard")]
use crate::services::{apt::Apt, gfx::Gfx};
use ctru_sys::{ use ctru_sys::{
self, swkbdInit, swkbdInputText, swkbdSetButton, swkbdSetFeatures, swkbdSetHintText, self, swkbdInit, swkbdInputText, swkbdSetButton, swkbdSetFeatures, swkbdSetHintText,
swkbdSetInitialText, SwkbdState, swkbdSetInitialText, SwkbdState,
}; };
use crate::services::{apt::Apt, gfx::Gfx};
use bitflags::bitflags; use bitflags::bitflags;
use libc; use libc;
@ -24,6 +23,15 @@ pub struct SoftwareKeyboard {
state: Box<SwkbdState>, state: Box<SwkbdState>,
} }
/// Configuration structure to setup the Parental Lock applet.
///
/// Internally, the Parental Lock is just a different kind of [`SoftwareKeyboard`].
#[doc(alias = "SwkbdState")]
#[derive(Clone)]
pub struct ParentalLock {
state: Box<SwkbdState>,
}
/// The type of keyboard used by the [`SoftwareKeyboard`]. /// The type of keyboard used by the [`SoftwareKeyboard`].
/// ///
/// Can be set with [`SoftwareKeyboard::new()`] /// Can be set with [`SoftwareKeyboard::new()`]
@ -75,15 +83,22 @@ pub enum Error {
PowerPressed = ctru_sys::SWKBD_POWERPRESSED, PowerPressed = ctru_sys::SWKBD_POWERPRESSED,
/// The parental lock PIN was correct. /// The parental lock PIN was correct.
/// ///
/// While this variant isn't *technically* considerable an error /// This variant should never be returned by normal operations made using this module,
/// the result of a Parental PIN operation won't return a string to the program, thus it's still exceptional behaviour. /// and is listed here only for compatibility purposes.
/// Refer to the return value of [`ParentalLock::launch()`] to confirm the outcome
/// of the Parental Lock PIN operation.
ParentalOk = ctru_sys::SWKBD_PARENTAL_OK, ParentalOk = ctru_sys::SWKBD_PARENTAL_OK,
/// The parental lock PIN was incorrect. /// The parental lock PIN was incorrect.
///
/// Refer to the return value of [`ParentalLock::launch()`] to confirm the outcome
/// of the Parental Lock PIN operation.
ParentalFail = ctru_sys::SWKBD_PARENTAL_FAIL, ParentalFail = ctru_sys::SWKBD_PARENTAL_FAIL,
/// Input triggered the filter. /// Input triggered the filter.
/// ///
/// You can have a look at [`Filters`] to activate custom filters. /// You can have a look at [`Filters`] to activate custom filters.
BannedInput = ctru_sys::SWKBD_BANNED_INPUT, BannedInput = ctru_sys::SWKBD_BANNED_INPUT,
/// An on-screen button was pressed to exit the prompt.
ButtonPressed = ctru_sys::SWKBD_D0_CLICK,
} }
/// Restrictions to enforce rules on the keyboard input. /// Restrictions to enforce rules on the keyboard input.
@ -109,12 +124,6 @@ bitflags! {
/// Special features that can be activated via [`SoftwareKeyboard::set_features()`]. /// Special features that can be activated via [`SoftwareKeyboard::set_features()`].
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)] #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
pub struct Features: u32 { pub struct Features: u32 {
/// Parental PIN mode.
///
/// # Notes
///
/// Refer to [`Error::ParentalOk`] and [`Error::ParentalFail`] to check whether the Parental PIN lock was successfully opened.
const PARENTAL_PIN = ctru_sys::SWKBD_PARENTAL;
/// Darken top screen while the [`SoftwareKeyboard`] is active. /// Darken top screen while the [`SoftwareKeyboard`] is active.
const DARKEN_TOP_SCREEN = ctru_sys::SWKBD_DARKEN_TOP_SCREEN; const DARKEN_TOP_SCREEN = ctru_sys::SWKBD_DARKEN_TOP_SCREEN;
/// Enable predictive input (necessary for Kanji on JPN consoles). /// Enable predictive input (necessary for Kanji on JPN consoles).
@ -181,7 +190,7 @@ impl SoftwareKeyboard {
unsafe { unsafe {
let mut state = Box::<SwkbdState>::default(); let mut state = Box::<SwkbdState>::default();
swkbdInit(state.as_mut(), keyboard_type.into(), num_buttons, -1); swkbdInit(state.as_mut(), keyboard_type.into(), num_buttons, -1);
SoftwareKeyboard { state } Self { state }
} }
} }
@ -208,7 +217,12 @@ impl SoftwareKeyboard {
/// # } /// # }
/// ``` /// ```
#[doc(alias = "swkbdInputText")] #[doc(alias = "swkbdInputText")]
pub fn get_string(&mut self, max_bytes: usize, apt: &Apt, gfx: &Gfx) -> Result<(String, Button), Error> { pub fn get_string(
&mut self,
max_bytes: usize,
apt: &Apt,
gfx: &Gfx,
) -> Result<(String, Button), Error> {
// Unfortunately the libctru API doesn't really provide a way to get the exact length // Unfortunately the libctru API doesn't really provide a way to get the exact length
// of the string that it receieves from the software keyboard. Instead it expects you // of the string that it receieves from the software keyboard. Instead it expects you
// to pass in a buffer and hope that it's big enough to fit the entire string, so // to pass in a buffer and hope that it's big enough to fit the entire string, so
@ -253,10 +267,11 @@ impl SoftwareKeyboard {
/// # } /// # }
/// ``` /// ```
#[doc(alias = "swkbdInputText")] #[doc(alias = "swkbdInputText")]
#[allow(unused_variables)]
pub fn write_exact(&mut self, buf: &mut [u8], apt: &Apt, gfx: &Gfx) -> Result<Button, Error> { pub fn write_exact(&mut self, buf: &mut [u8], apt: &Apt, gfx: &Gfx) -> Result<Button, Error> {
unsafe { unsafe {
match swkbdInputText(self.state.as_mut(), buf.as_mut_ptr(), buf.len()) { match swkbdInputText(self.state.as_mut(), buf.as_mut_ptr(), buf.len()) {
ctru_sys::SWKBD_BUTTON_NONE => Err(self.parse_swkbd_error()), ctru_sys::SWKBD_BUTTON_NONE => Err(self.state.result.into()),
ctru_sys::SWKBD_BUTTON_LEFT => Ok(Button::Left), ctru_sys::SWKBD_BUTTON_LEFT => Ok(Button::Left),
ctru_sys::SWKBD_BUTTON_MIDDLE => Ok(Button::Middle), ctru_sys::SWKBD_BUTTON_MIDDLE => Ok(Button::Middle),
ctru_sys::SWKBD_BUTTON_RIGHT => Ok(Button::Right), ctru_sys::SWKBD_BUTTON_RIGHT => Ok(Button::Right),
@ -448,18 +463,49 @@ impl SoftwareKeyboard {
pub fn set_max_text_len(&mut self, len: u16) { pub fn set_max_text_len(&mut self, len: u16) {
self.state.max_text_len = len; self.state.max_text_len = len;
} }
}
fn parse_swkbd_error(&self) -> Error { impl ParentalLock {
match self.state.result { /// Initialize a new configuration for the Parental Lock applet.
ctru_sys::SWKBD_INVALID_INPUT => Error::InvalidParameters, ///
ctru_sys::SWKBD_OUTOFMEM => Error::OutOfMem, /// # Example
ctru_sys::SWKBD_HOMEPRESSED => Error::HomePressed, ///
ctru_sys::SWKBD_RESETPRESSED => Error::ResetPressed, /// ```
ctru_sys::SWKBD_POWERPRESSED => Error::PowerPressed, /// # let _runner = test_runner::GdbRunner::default();
ctru_sys::SWKBD_PARENTAL_OK => Error::ParentalOk, /// # fn main() {
ctru_sys::SWKBD_PARENTAL_FAIL => Error::ParentalFail, /// #
ctru_sys::SWKBD_BANNED_INPUT => Error::BannedInput, /// use ctru::applets::swkbd::{SoftwareKeyboard, Kind};
_ => unreachable!(), ///
/// // Standard keyboard.
/// let keyboard = SoftwareKeyboard::new(Kind::Normal, 2);
///
/// // Numpad (with only the "confirm" button).
/// let keyboard = SoftwareKeyboard::new(Kind::Numpad, 1);
/// #
/// # }
#[doc(alias = "swkbdInit")]
pub fn new() -> Self {
unsafe {
let mut state = Box::<SwkbdState>::default();
swkbdInit(state.as_mut(), Kind::Normal.into(), 1, -1);
swkbdSetFeatures(state.as_mut(), ctru_sys::SWKBD_PARENTAL);
Self { state }
}
}
/// Launch the Parental Lock applet based on the configuration and return a result depending on whether the operation was successful or not.
#[doc(alias = "swkbdInputText")]
#[allow(unused_variables)]
pub fn launch(&mut self, apt: &Apt, gfx: &Gfx) -> Result<(), Error> {
unsafe {
let mut buf = [0; 10];
swkbdInputText(self.state.as_mut(), buf.as_mut_ptr(), 10);
let e = self.state.result.into();
match e {
Error::ParentalOk => Ok(()),
_ => Err(e),
}
} }
} }
} }
@ -496,12 +542,35 @@ impl Display for Error {
f, f,
"input given to the software keyboard triggered the active filters" "input given to the software keyboard triggered the active filters"
), ),
Self::ButtonPressed => write!(f, "on-screen button was pressed to exit the prompt"),
} }
} }
} }
impl std::error::Error for Error {} impl std::error::Error for Error {}
impl From<ctru_sys::SwkbdResult> for Error {
fn from(value: ctru_sys::SwkbdResult) -> Self {
match value {
ctru_sys::SWKBD_INVALID_INPUT => Error::InvalidParameters,
ctru_sys::SWKBD_OUTOFMEM => Error::OutOfMem,
ctru_sys::SWKBD_HOMEPRESSED => Error::HomePressed,
ctru_sys::SWKBD_RESETPRESSED => Error::ResetPressed,
ctru_sys::SWKBD_POWERPRESSED => Error::PowerPressed,
ctru_sys::SWKBD_PARENTAL_OK => Error::ParentalOk,
ctru_sys::SWKBD_PARENTAL_FAIL => Error::ParentalFail,
ctru_sys::SWKBD_BANNED_INPUT => Error::BannedInput,
ctru_sys::SWKBD_D0_CLICK => Error::ButtonPressed,
ctru_sys::SWKBD_D1_CLICK0 => Error::ButtonPressed,
ctru_sys::SWKBD_D1_CLICK1 => Error::ButtonPressed,
ctru_sys::SWKBD_D2_CLICK0 => Error::ButtonPressed,
ctru_sys::SWKBD_D2_CLICK1 => Error::ButtonPressed,
ctru_sys::SWKBD_D2_CLICK2 => Error::ButtonPressed,
_ => unreachable!(),
}
}
}
from_impl!(Kind, ctru_sys::SwkbdType); from_impl!(Kind, ctru_sys::SwkbdType);
from_impl!(Button, ctru_sys::SwkbdButton); from_impl!(Button, ctru_sys::SwkbdButton);
from_impl!(Error, ctru_sys::SwkbdResult); from_impl!(Error, ctru_sys::SwkbdResult);

Loading…
Cancel
Save