Browse Source

Finish up SSLC, SOC, ROMFS and PS

pull/134/head
Andrea Ciliberti 1 year ago
parent
commit
fde168cb17
  1. 14
      ctru-rs/src/applets/mii_selector.rs
  2. 18
      ctru-rs/src/applets/swkbd.rs
  3. 20
      ctru-rs/src/services/am.rs
  4. 12
      ctru-rs/src/services/apt.rs
  5. 2
      ctru-rs/src/services/gfx.rs
  6. 75
      ctru-rs/src/services/ps.rs
  7. 33
      ctru-rs/src/services/romfs.rs
  8. 92
      ctru-rs/src/services/soc.rs
  9. 14
      ctru-rs/src/services/sslc.rs

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

@ -96,7 +96,7 @@ impl MiiSelector {
/// This function will panic if the given `&str` contains NUL bytes. /// This function will panic if the given `&str` contains NUL bytes.
/// ///
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// # fn main() { /// # fn main() {
/// use ctru::applets::mii_selector::MiiSelector; /// use ctru::applets::mii_selector::MiiSelector;
@ -120,7 +120,7 @@ impl MiiSelector {
/// This will overwrite any previously saved options. Use bitwise operations to set all your wanted options at once. /// This will overwrite any previously saved options. Use bitwise operations to set all your wanted options at once.
/// ///
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// # fn main() { /// # fn main() {
/// use ctru::applets::mii_selector::{MiiSelector, Options}; /// use ctru::applets::mii_selector::{MiiSelector, Options};
@ -144,7 +144,7 @@ impl MiiSelector {
/// Look into [`MiiSelector::set_options()`] to see how to work with options. /// Look into [`MiiSelector::set_options()`] to see how to work with options.
/// ///
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// # fn main() { /// # fn main() {
/// # /// #
@ -173,7 +173,7 @@ impl MiiSelector {
/// Look into [`MiiSelector::set_options()`] to see how to work with options. /// Look into [`MiiSelector::set_options()`] to see how to work with options.
/// ///
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// # fn main() { /// # fn main() {
/// # /// #
@ -197,7 +197,7 @@ impl MiiSelector {
/// Whitelist a user-created Mii based on its index. /// Whitelist a user-created Mii based on its index.
/// ///
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// # fn main() { /// # fn main() {
/// # /// #
@ -221,7 +221,7 @@ impl MiiSelector {
/// Blacklist a user-created Mii based on its index. /// Blacklist a user-created Mii based on its index.
/// ///
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// # fn main() { /// # fn main() {
/// # /// #
@ -259,7 +259,7 @@ impl MiiSelector {
/// TODO: UNSAFE OPERATION, LAUNCHING APPLETS REQUIRES GRAPHICS, WITHOUT AN ACTIVE GFX THIS WILL CAUSE A SEGMENTATION FAULT. /// TODO: UNSAFE OPERATION, LAUNCHING APPLETS REQUIRES GRAPHICS, WITHOUT AN ACTIVE GFX THIS WILL CAUSE A SEGMENTATION FAULT.
/// ///
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// # use std::error::Error; /// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> { /// # fn main() -> Result<(), Box<dyn Error>> {

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

@ -158,7 +158,7 @@ impl SoftwareKeyboard {
/// Initialize a new configuration for the Software Keyboard applet depending on how many "exit" buttons are available to the user (1, 2 or 3). /// Initialize a new configuration for the Software Keyboard applet depending on how many "exit" buttons are available to the user (1, 2 or 3).
/// ///
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// # fn main() { /// # fn main() {
/// # /// #
@ -189,7 +189,7 @@ impl SoftwareKeyboard {
/// TODO: UNSAFE OPERATION, LAUNCHING APPLETS REQUIRES GRAPHICS, WITHOUT AN ACTIVE GFX THIS WILL CAUSE A SEGMENTATION FAULT. /// TODO: UNSAFE OPERATION, LAUNCHING APPLETS REQUIRES GRAPHICS, WITHOUT AN ACTIVE GFX THIS WILL CAUSE A SEGMENTATION FAULT.
/// ///
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// # use std::error::Error; /// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> { /// # fn main() -> Result<(), Box<dyn Error>> {
@ -233,7 +233,7 @@ impl SoftwareKeyboard {
/// TODO: UNSAFE OPERATION, LAUNCHING APPLETS REQUIRES GRAPHICS, WITHOUT AN ACTIVE GFX THIS WILL CAUSE A SEGMENTATION FAULT. /// TODO: UNSAFE OPERATION, LAUNCHING APPLETS REQUIRES GRAPHICS, WITHOUT AN ACTIVE GFX THIS WILL CAUSE A SEGMENTATION FAULT.
/// ///
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// # use std::error::Error; /// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> { /// # fn main() -> Result<(), Box<dyn Error>> {
@ -264,7 +264,7 @@ impl SoftwareKeyboard {
/// Set special features for this keyboard. /// Set special features for this keyboard.
/// ///
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// # fn main() { /// # fn main() {
/// # /// #
@ -284,7 +284,7 @@ impl SoftwareKeyboard {
/// Configure input validation for this keyboard. /// Configure input validation for this keyboard.
/// ///
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// # fn main() { /// # fn main() {
/// # /// #
@ -307,7 +307,7 @@ impl SoftwareKeyboard {
/// Configure the maximum number of digits that can be entered in the keyboard when the [`Filters::DIGITS`] flag is enabled. /// Configure the maximum number of digits that can be entered in the keyboard when the [`Filters::DIGITS`] flag is enabled.
/// ///
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// # fn main() { /// # fn main() {
/// # /// #
@ -334,7 +334,7 @@ impl SoftwareKeyboard {
/// The hint text is the text shown in gray before any text gets written in the input box. /// The hint text is the text shown in gray before any text gets written in the input box.
/// ///
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// # fn main() { /// # fn main() {
/// # /// #
@ -361,7 +361,7 @@ impl SoftwareKeyboard {
/// - `submit` - whether pressing the button will accept the keyboard's input or discard it. /// - `submit` - whether pressing the button will accept the keyboard's input or discard it.
/// ///
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// # fn main() { /// # fn main() {
/// # /// #
@ -400,7 +400,7 @@ impl SoftwareKeyboard {
/// receivable by [`SoftwareKeyboard::get_string()`] and [`SoftwareKeyboard::write_exact()`]. /// receivable by [`SoftwareKeyboard::get_string()`] and [`SoftwareKeyboard::write_exact()`].
/// ///
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// # fn main() { /// # fn main() {
/// # /// #

20
ctru-rs/src/services/am.rs

@ -58,7 +58,7 @@ impl Am {
/// Initialize a new service handle. /// Initialize a new service handle.
/// ///
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// # use std::error::Error; /// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> { /// # fn main() -> Result<(), Box<dyn Error>> {
@ -81,7 +81,7 @@ impl Am {
/// Returns the amount of titles currently installed in a specific install location. /// Returns the amount of titles currently installed in a specific install location.
/// ///
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// # use std::error::Error; /// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> { /// # fn main() -> Result<(), Box<dyn Error>> {
@ -110,7 +110,7 @@ impl Am {
/// Returns the list of titles installed in a specific install location. /// Returns the list of titles installed in a specific install location.
/// ///
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// # use std::error::Error; /// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> { /// # fn main() -> Result<(), Box<dyn Error>> {
@ -157,14 +157,12 @@ impl Am {
Ok(info Ok(info
.into_iter() .into_iter()
.map(|title| { .map(|title| Title {
Title { id: title.titleID,
id: title.titleID, mediatype,
mediatype, size: title.size,
size: title.size, version: title.version,
version: title.version, _am: PhantomData,
_am: PhantomData,
}
}) })
.collect()) .collect())
} }

12
ctru-rs/src/services/apt.rs

@ -13,9 +13,9 @@ pub struct Apt(());
impl Apt { impl Apt {
/// Initialize a new service handle. /// Initialize a new service handle.
/// ///
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// # use std::error::Error; /// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> { /// # fn main() -> Result<(), Box<dyn Error>> {
@ -43,20 +43,20 @@ impl Apt {
/// For this reason, its main use is as the condition of a while loop that controls the main logic for your program. /// For this reason, its main use is as the condition of a while loop that controls the main logic for your program.
/// ///
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// use std::error::Error; /// use std::error::Error;
/// use ctru::services::apt::Apt; /// use ctru::services::apt::Apt;
/// ///
/// // In a simple `main` function, the structure should be the following. /// // In a simple `main` function, the structure should be the following.
/// fn main() -> Result<(), Box<dyn Error>> { /// fn main() -> Result<(), Box<dyn Error>> {
/// ///
/// let apt = Apt::new()?; /// let apt = Apt::new()?;
/// ///
/// while apt.main_loop() { /// while apt.main_loop() {
/// // Main program logic should be written here. /// // Main program logic should be written here.
/// } /// }
/// ///
/// // Optional clean-ups after running the application should be written after the main loop. /// // Optional clean-ups after running the application should be written after the main loop.
/// # /// #
/// # Ok(()) /// # Ok(())

2
ctru-rs/src/services/gfx.rs

@ -220,7 +220,7 @@ static GFX_ACTIVE: Mutex<usize> = Mutex::new(0);
impl Gfx { impl Gfx {
/// Initialize a new default service handle. /// Initialize a new default service handle.
/// ///
/// It's the same as calling: /// It's the same as calling:
/// ///
/// ```no_run /// ```no_run

75
ctru-rs/src/services/ps.rs

@ -1,14 +1,15 @@
//! Process Services. //! Process Services.
//! //!
//! This is used for miscellaneous utility tasks, but //! This service handles miscellaneous utility tasks used by the various processes.
//! is particularly important because it is used to generate random data, which //! However, it is particularly important because it is used to generate cryptographically secure random data, which
//! is required for common things like [`HashMap`](std::collections::HashMap). //! is required for commonly used functionality such as hashing (e.g. [`HashMap`](std::collections::HashMap) will not work without it).
//!
//! See also <https://www.3dbrew.org/wiki/Process_Services> //! See also <https://www.3dbrew.org/wiki/Process_Services>
use crate::error::ResultCode; use crate::error::ResultCode;
use crate::Result; use crate::Result;
/// Kind of AES algorithm to use. /// Type of AES algorithm to use.
#[doc(alias = "PS_AESAlgorithm")] #[doc(alias = "PS_AESAlgorithm")]
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u32)] #[repr(u32)]
@ -59,6 +60,20 @@ pub struct Ps(());
impl Ps { impl Ps {
/// Initialize a new service handle. /// Initialize a new service handle.
///
/// # Example
///
/// ```no_run
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// #
/// use ctru::services::ps::Ps;
///
/// let ps = Ps::new()?;
/// #
/// # Ok(())
/// # }
/// ```
#[doc(alias = "psInit")] #[doc(alias = "psInit")]
pub fn new() -> Result<Self> { pub fn new() -> Result<Self> {
unsafe { unsafe {
@ -68,6 +83,21 @@ impl Ps {
} }
/// Returns the console's local friend code seed. /// Returns the console's local friend code seed.
///
/// # Example
///
/// ```no_run
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// #
/// use ctru::services::ps::Ps;
/// let ps = Ps::new()?;
///
/// let friend_code_seed = ps.local_friend_code_seed()?;
/// #
/// # Ok(())
/// # }
/// ```
#[doc(alias = "PS_GetLocalFriendCodeSeed")] #[doc(alias = "PS_GetLocalFriendCodeSeed")]
pub fn local_friend_code_seed(&self) -> crate::Result<u64> { pub fn local_friend_code_seed(&self) -> crate::Result<u64> {
let mut seed: u64 = 0; let mut seed: u64 = 0;
@ -77,6 +107,21 @@ impl Ps {
} }
/// Returns the console's devide ID. /// Returns the console's devide ID.
///
/// # Example
///
/// ```no_run
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// #
/// use ctru::services::ps::Ps;
/// let ps = Ps::new()?;
///
/// let device_id = ps.device_id()?;
/// #
/// # Ok(())
/// # }
/// ```
#[doc(alias = "PS_GetDeviceId")] #[doc(alias = "PS_GetDeviceId")]
pub fn device_id(&self) -> crate::Result<u32> { pub fn device_id(&self) -> crate::Result<u32> {
let mut id: u32 = 0; let mut id: u32 = 0;
@ -86,6 +131,24 @@ impl Ps {
} }
/// Generates cryptografically secure random bytes and writes them into the `out` buffer. /// Generates cryptografically secure random bytes and writes them into the `out` buffer.
///
/// # Example
///
/// ```no_run
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// #
/// use ctru::services::ps::Ps;
/// let ps = Ps::new()?;
///
/// let mut buffer = vec![0; 128];
///
/// // The buffer is now randomized!
/// ps.generate_random_bytes(&mut buffer)?;
/// #
/// # Ok(())
/// # }
/// ```
#[doc(alias = "PS_GenerateRandomBytes")] #[doc(alias = "PS_GenerateRandomBytes")]
pub fn generate_random_bytes(&self, out: &mut [u8]) -> crate::Result<()> { pub fn generate_random_bytes(&self, out: &mut [u8]) -> crate::Result<()> {
ResultCode(unsafe { ResultCode(unsafe {

33
ctru-rs/src/services/romfs.rs

@ -1,9 +1,14 @@
//! Read-Only Memory FileSystem service. //! Read-Only Memory FileSystem service.
//! //!
//! This service lets the application access a virtual mounted device created using a folder included within the application bundle.
//! After mounting the RomFS file system, the included files and folders will be accessible exactly like any other file, just by using the drive prefix `romfs:/<file-path>`.
//!
//! # Usage
//!
//! This module only gets compiled if the configured RomFS directory is found and the `romfs` //! This module only gets compiled if the configured RomFS directory is found and the `romfs`
//! feature is enabled. //! feature is enabled.
//! //!
//! Configure the path in Cargo.toml (the default path is "romfs"). Paths are relative to the //! Configure the path in your project's `Cargo.toml` manifest (the default path is "romfs"). Paths are relative to the
//! `CARGO_MANIFEST_DIR` environment variable, which is the directory containing the manifest of //! `CARGO_MANIFEST_DIR` environment variable, which is the directory containing the manifest of
//! your package. //! your package.
//! //!
@ -11,6 +16,8 @@
//! [package.metadata.cargo-3ds] //! [package.metadata.cargo-3ds]
//! romfs_dir = "romfs" //! romfs_dir = "romfs"
//! ``` //! ```
//!
//! Alternatively, you can include the RomFS archive manually when building with `3dsxtool`.
use crate::error::ResultCode; use crate::error::ResultCode;
use std::ffi::CStr; use std::ffi::CStr;
@ -19,11 +26,6 @@ use std::sync::Mutex;
use crate::services::ServiceReference; use crate::services::ServiceReference;
/// Handle to the RomFS service. /// Handle to the RomFS service.
///
/// This service lets the application access a virtual mounted device created using a folder included within the application bundle.
/// `ctru-rs` will include as RomFS the folder specified in the `Cargo.toml` manifest (or use `./romfs` by default). Look at the [`romfs`](self) module for more information.
///
/// After mounting the RomFS file system, the included files and folders will be accessible exactly like any other file, just by using the drive prefix `romfs:/`.
pub struct RomFS { pub struct RomFS {
_service_handler: ServiceReference, _service_handler: ServiceReference,
} }
@ -31,7 +33,24 @@ pub struct RomFS {
static ROMFS_ACTIVE: Mutex<usize> = Mutex::new(0); static ROMFS_ACTIVE: Mutex<usize> = Mutex::new(0);
impl RomFS { impl RomFS {
/// Mount the specified RomFS folder as a virtual drive. /// Mount the bundled RomFS archive as a virtual drive.
///
/// # Example
///
/// ```no_run
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// #
/// use ctru::services::romfs::RomFS;
///
/// let romfs = RomFS::new()?;
///
/// // Remember to include the RomFS archive and to use your actual files!
/// let contents = std::fs::read_to_string("romfs:/test-file.txt");
/// #
/// # Ok(())
/// # }
/// ```
#[doc(alias = "romfsMountSelf")] #[doc(alias = "romfsMountSelf")]
pub fn new() -> crate::Result<Self> { pub fn new() -> crate::Result<Self> {
let _service_handler = ServiceReference::new( let _service_handler = ServiceReference::new(

92
ctru-rs/src/services/soc.rs

@ -1,4 +1,7 @@
//! Network Socket service. //! Network Socket service.
//!
//! By using this service the program enables the use of network sockets and utilities such as those found in `std::net`, which are completely inaccessible by default.
//! As such, remember to hold a handle to this service handle while using any network functionality, or else the `std::net` methods will return generic OS errors.
use libc::memalign; use libc::memalign;
use std::net::Ipv4Addr; use std::net::Ipv4Addr;
@ -8,10 +11,7 @@ use crate::error::ResultCode;
use crate::services::ServiceReference; use crate::services::ServiceReference;
use crate::Error; use crate::Error;
/// Network socket service /// Handle to the Network Socket service.
///
/// Initializing this service will enable the use of network sockets and utilities
/// such as those found in `std::net`. The service will close once this struct gets dropped.
pub struct Soc { pub struct Soc {
_service_handler: ServiceReference, _service_handler: ServiceReference,
sock_3dslink: libc::c_int, sock_3dslink: libc::c_int,
@ -20,22 +20,51 @@ pub struct Soc {
static SOC_ACTIVE: Mutex<usize> = Mutex::new(0); static SOC_ACTIVE: Mutex<usize> = Mutex::new(0);
impl Soc { impl Soc {
/// Initialize a new service handle using a socket buffer size of 0x100000 bytes. /// Initialize a new service handle using a socket buffer size of `0x100000` bytes.
/// ///
/// # Errors /// # Errors
/// ///
/// This function will return an error if the [`Soc`] service is already initialized /// This function will return an error if the [`Soc`] service is already being used.
///
/// # Example
///
/// ```no_run
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// #
/// use ctru::services::soc::Soc;
///
/// let soc = Soc::new()?;
/// #
/// # Ok(())
/// # }
/// ```
#[doc(alias = "socInit")] #[doc(alias = "socInit")]
pub fn new() -> crate::Result<Self> { pub fn new() -> crate::Result<Self> {
Self::init_with_buffer_size(0x100000) Self::init_with_buffer_size(0x100000)
} }
/// Initialize the Soc service with a custom buffer size in bytes. The size should be /// Initialize a new service handle using a custom socket buffer size.
/// 0x100000 bytes or greater. ///
/// The size should be `0x100000` bytes or greater.
/// ///
/// # Errors /// # Errors
/// ///
/// This function will return an error if the [`Soc`] service is already initialized /// This function will return an error if the [`Soc`] service is already being used.
///
/// # Example
///
/// ```no_run
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// #
/// use ctru::services::soc::Soc;
///
/// let soc = Soc::init_with_buffer_size(0x100000)?;
/// #
/// # Ok(())
/// # }
/// ```
#[doc(alias = "socInit")] #[doc(alias = "socInit")]
pub fn init_with_buffer_size(num_bytes: usize) -> crate::Result<Self> { pub fn init_with_buffer_size(num_bytes: usize) -> crate::Result<Self> {
let _service_handler = ServiceReference::new( let _service_handler = ServiceReference::new(
@ -62,20 +91,55 @@ impl Soc {
}) })
} }
/// IP Address of the Nintendo 3DS system. /// Returns the local IP Address of the Nintendo 3DS system.
///
/// # Example
///
/// ```no_run
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// #
/// use ctru::services::soc::Soc;
/// let soc = Soc::new()?;
///
/// let address = soc.host_address();
/// #
/// # Ok(())
/// # }
/// ```
#[doc(alias = "gethostid")] #[doc(alias = "gethostid")]
pub fn host_address(&self) -> Ipv4Addr { pub fn host_address(&self) -> Ipv4Addr {
let raw_id = unsafe { libc::gethostid() }; let raw_id = unsafe { libc::gethostid() };
Ipv4Addr::from(raw_id.to_ne_bytes()) Ipv4Addr::from(raw_id.to_ne_bytes())
} }
/// Redirect output streams (i.e. [`println`] and [`eprintln`]) to the `3dslink` server. /// Redirect output streams (i.e. `println` and `eprintln`) to the `3dslink` server.
/// Requires `3dslink` >= 0.6.1 and `new-hbmenu` >= 2.3.0. ///
/// Requires `3dslink` >= 0.6.1 and `new-hbmenu` >= 2.3.0 and the use of the `--server` flag.
/// The `--server` flag is also availble to use via `cargo-3ds` if the requirements are met.
/// ///
/// # Errors /// # Errors
/// ///
/// Returns an error if a connection cannot be established to the server, or /// Returns an error if a connection cannot be established to the server,
/// output was already previously redirected. /// or if the output was already being redirected.
///
/// # Example
///
/// ```no_run
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// #
/// use ctru::services::soc::Soc;
/// let mut soc = Soc::new()?;
///
/// // Redirect to the `3dslink` server that sent this program.
/// let address = soc.redirect_to_3dslink(true, true)?;
///
/// println!("I'm visible from a PC!");
/// #
/// # Ok(())
/// # }
/// ```
#[doc(alias = "link3dsConnectToHost")] #[doc(alias = "link3dsConnectToHost")]
pub fn redirect_to_3dslink(&mut self, stdout: bool, stderr: bool) -> crate::Result<()> { pub fn redirect_to_3dslink(&mut self, stdout: bool, stderr: bool) -> crate::Result<()> {
if self.sock_3dslink >= 0 { if self.sock_3dslink >= 0 {

14
ctru-rs/src/services/sslc.rs

@ -9,6 +9,20 @@ pub struct SslC(());
impl SslC { impl SslC {
/// Initialize a new service handle. /// Initialize a new service handle.
///
/// # Example
///
/// ```no_run
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// #
/// use ctru::services::sslc::SslC;
///
/// let sslc = SslC::new()?;
/// #
/// # Ok(())
/// # }
/// ```
#[doc(alias = "sslcInit")] #[doc(alias = "sslcInit")]
pub fn new() -> crate::Result<Self> { pub fn new() -> crate::Result<Self> {
unsafe { unsafe {

Loading…
Cancel
Save