Browse Source

Finish up SSLC, SOC, ROMFS and PS

pull/134/head
Andrea Ciliberti 1 year ago
parent
commit
fde168cb17
  1. 4
      ctru-rs/src/services/am.rs
  2. 71
      ctru-rs/src/services/ps.rs
  3. 33
      ctru-rs/src/services/romfs.rs
  4. 92
      ctru-rs/src/services/soc.rs
  5. 14
      ctru-rs/src/services/sslc.rs

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

@ -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())
} }

71
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