Browse Source

Fixed duplicate services and constistency in naming

pull/50/head
Andrea Ciliberti 3 years ago
parent
commit
060b14f068
  1. 2
      ctru-rs/examples/buttons.rs
  2. 4
      ctru-rs/examples/file-explorer.rs
  3. 2
      ctru-rs/examples/futures-basic.rs
  4. 2
      ctru-rs/examples/futures-tokio.rs
  5. 2
      ctru-rs/examples/gfx-wide-mode.rs
  6. 2
      ctru-rs/examples/graphics-bitmap.rs
  7. 2
      ctru-rs/examples/hashmaps.rs
  8. 2
      ctru-rs/examples/hello-both-screens.rs
  9. 2
      ctru-rs/examples/hello-world.rs
  10. 2
      ctru-rs/examples/network-sockets.rs
  11. 4
      ctru-rs/examples/romfs.rs
  12. 2
      ctru-rs/examples/thread-basic.rs
  13. 2
      ctru-rs/examples/thread-locals.rs
  14. 2
      ctru-rs/examples/time-rtc.rs
  15. 3
      ctru-rs/src/error.rs
  16. 58
      ctru-rs/src/gfx.rs
  17. 29
      ctru-rs/src/lib.rs
  18. 38
      ctru-rs/src/romfs.rs
  19. 50
      ctru-rs/src/services/apt.rs
  20. 42
      ctru-rs/src/services/fs.rs
  21. 39
      ctru-rs/src/services/hid.rs
  22. 2
      ctru-rs/src/services/ps.rs
  23. 51
      ctru-rs/src/services/soc.rs
  24. 49
      ctru-rs/src/services/sslc.rs
  25. 38
      ctru-rs/src/srv.rs
  26. 7
      ctru-rs/src/test_runner.rs

2
ctru-rs/examples/buttons.rs

@ -8,7 +8,7 @@ fn main() { @@ -8,7 +8,7 @@ fn main() {
ctru::init();
let apt = Apt::init().unwrap();
let hid = Hid::init().unwrap();
let gfx = Gfx::default();
let gfx = Gfx::init_default().unwrap();
let console = Console::init(gfx.top_screen.borrow_mut());
println!("Hi there! Try pressing a button");

4
ctru-rs/examples/file-explorer.rs

@ -14,10 +14,10 @@ fn main() { @@ -14,10 +14,10 @@ fn main() {
ctru::init();
let apt = Apt::init().unwrap();
let hid = Hid::init().unwrap();
let gfx = Gfx::default();
let gfx = Gfx::init_default().unwrap();
#[cfg(all(feature = "romfs", romfs_exists))]
let _romfs = ctru::romfs::RomFS::new().unwrap();
let _romfs = ctru::romfs::RomFS::init().unwrap();
FileExplorer::init(&apt, &hid, &gfx).run();
}

2
ctru-rs/examples/futures-basic.rs

@ -13,7 +13,7 @@ use futures::StreamExt; @@ -13,7 +13,7 @@ use futures::StreamExt;
fn main() {
ctru::init();
let gfx = Gfx::default();
let gfx = Gfx::init_default().expect("Couldn't obtaint GFX controller");
let hid = Hid::init().expect("Couldn't obtain HID controller");
let apt = Apt::init().expect("Couldn't obtain APT controller");
let _console = Console::init(gfx.top_screen.borrow_mut());

2
ctru-rs/examples/futures-tokio.rs

@ -6,7 +6,7 @@ use std::time::Duration; @@ -6,7 +6,7 @@ use std::time::Duration;
fn main() {
ctru::init();
let gfx = Gfx::default();
let gfx = Gfx::init_default().expect("Couldn't obtaint GFX controller");
let hid = Hid::init().expect("Couldn't obtain HID controller");
let apt = Apt::init().expect("Couldn't obtain APT controller");
let _console = Console::init(gfx.top_screen.borrow_mut());

2
ctru-rs/examples/gfx-wide-mode.rs

@ -7,7 +7,7 @@ fn main() { @@ -7,7 +7,7 @@ fn main() {
ctru::init();
let apt = Apt::init().unwrap();
let hid = Hid::init().unwrap();
let gfx = Gfx::default();
let gfx = Gfx::init_default().unwrap();
let mut console = Console::init(gfx.top_screen.borrow_mut());
println!("Press A to enable/disable wide screen mode.");

2
ctru-rs/examples/graphics-bitmap.rs

@ -19,7 +19,7 @@ static IMAGE: &[u8] = include_bytes!("assets/ferris.rgb"); @@ -19,7 +19,7 @@ static IMAGE: &[u8] = include_bytes!("assets/ferris.rgb");
fn main() {
ctru::init();
let gfx = Gfx::default();
let gfx = Gfx::init_default().expect("Couldn't obtaint GFX controller");
let hid = Hid::init().expect("Couldn't obtain HID controller");
let apt = Apt::init().expect("Couldn't obtain APT controller");
let _console = Console::init(gfx.top_screen.borrow_mut());

2
ctru-rs/examples/hashmaps.rs

@ -12,7 +12,7 @@ fn main() { @@ -12,7 +12,7 @@ fn main() {
ctru::init();
let apt = Apt::init().unwrap();
let hid = Hid::init().unwrap();
let gfx = Gfx::default();
let gfx = Gfx::init_default().unwrap();
let _console = Console::init(gfx.top_screen.borrow_mut());
let mut map = std::collections::HashMap::new();

2
ctru-rs/examples/hello-both-screens.rs

@ -8,7 +8,7 @@ fn main() { @@ -8,7 +8,7 @@ fn main() {
ctru::init();
let apt = Apt::init().unwrap();
let hid = Hid::init().unwrap();
let gfx = Gfx::default();
let gfx = Gfx::init_default().unwrap();
// Start a console on the top screen
let top_screen = Console::init(gfx.top_screen.borrow_mut());

2
ctru-rs/examples/hello-world.rs

@ -7,7 +7,7 @@ use std::io::BufWriter; @@ -7,7 +7,7 @@ use std::io::BufWriter;
fn main() {
ctru::init();
let gfx = Gfx::default();
let gfx = Gfx::init_default().expect("Couldn't obtain GFX controller");
let hid = Hid::init().expect("Couldn't obtain HID controller");
let apt = Apt::init().expect("Couldn't obtain APT controller");
let _console = Console::init(gfx.top_screen.borrow_mut());

2
ctru-rs/examples/network-sockets.rs

@ -10,7 +10,7 @@ use std::time::Duration; @@ -10,7 +10,7 @@ use std::time::Duration;
fn main() {
ctru::init();
let gfx = Gfx::default();
let gfx = Gfx::init_default().unwrap();
let _console = Console::init(gfx.top_screen.borrow_mut());
let hid = Hid::init().unwrap();
let apt = Apt::init().unwrap();

4
ctru-rs/examples/romfs.rs

@ -5,7 +5,7 @@ use ctru::services::hid::{Hid, KeyPad}; @@ -5,7 +5,7 @@ use ctru::services::hid::{Hid, KeyPad};
fn main() {
ctru::init();
let gfx = Gfx::default();
let gfx = Gfx::init_default().expect("Couldn't obtaint GFX controller");
let hid = Hid::init().expect("Couldn't obtain HID controller");
let apt = Apt::init().expect("Couldn't obtain APT controller");
let _console = Console::init(gfx.top_screen.borrow_mut());
@ -15,7 +15,7 @@ fn main() { @@ -15,7 +15,7 @@ fn main() {
// This never fails as `ctru-rs` examples inherit all of the `ctru` features,
// but it might if a normal user application wasn't setup correctly
if #[cfg(all(feature = "romfs", romfs_exists))] {
let _romfs = ctru::romfs::RomFS::new().unwrap();
let _romfs = ctru::romfs::RomFS::init().unwrap();
let f = std::fs::read_to_string("romfs:/test-file.txt").unwrap();
println!("Contents of test-file.txt: \n{f}\n");

2
ctru-rs/examples/thread-basic.rs

@ -11,7 +11,7 @@ fn main() { @@ -11,7 +11,7 @@ fn main() {
ctru::init();
let apt = Apt::init().unwrap();
let hid = Hid::init().unwrap();
let gfx = Gfx::default();
let gfx = Gfx::init_default().unwrap();
let _console = Console::init(gfx.top_screen.borrow_mut());
let prio = thread::current().priority();

2
ctru-rs/examples/thread-locals.rs

@ -10,7 +10,7 @@ std::thread_local! { @@ -10,7 +10,7 @@ std::thread_local! {
fn main() {
ctru::init();
let gfx = Gfx::default();
let gfx = Gfx::init_default().expect("Couldn't obtaint GFX controller");
gfx.top_screen.borrow_mut().set_wide_mode(true);
let hid = Hid::init().expect("Couldn't obtain HID controller");
let apt = Apt::init().expect("Couldn't obtain APT controller");

2
ctru-rs/examples/time-rtc.rs

@ -6,7 +6,7 @@ use ctru::services::hid::{Hid, KeyPad}; @@ -6,7 +6,7 @@ use ctru::services::hid::{Hid, KeyPad};
fn main() {
ctru::init();
let gfx = Gfx::default();
let gfx = Gfx::init_default().expect("Couldn't obtaint GFX controller");
let hid = Hid::init().expect("Couldn't obtain HID controller");
let apt = Apt::init().expect("Couldn't obtain APT controller");

3
ctru-rs/src/error.rs

@ -9,6 +9,7 @@ pub type Result<T> = ::std::result::Result<T, Error>; @@ -9,6 +9,7 @@ pub type Result<T> = ::std::result::Result<T, Error>;
#[non_exhaustive]
pub enum Error {
Os(ctru_sys::Result),
ServiceAlreadyActive(&'static str),
}
impl From<ctru_sys::Result> for Error {
@ -28,6 +29,7 @@ impl fmt::Debug for Error { @@ -28,6 +29,7 @@ impl fmt::Debug for Error {
.field("summary", &R_SUMMARY(err))
.field("level", &R_LEVEL(err))
.finish(),
Error::ServiceAlreadyActive(service) => write!(f, "Service {service} already active"),
}
}
}
@ -39,6 +41,7 @@ impl fmt::Display for Error { @@ -39,6 +41,7 @@ impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::Os(err) => write!(f, "libctru result code: 0x{:08X}", err),
Error::ServiceAlreadyActive(service) => write!(f, "Service {service} already active"),
}
}
}

58
ctru-rs/src/gfx.rs

@ -1,10 +1,11 @@ @@ -1,10 +1,11 @@
//! LCD screens manipulation helper
use std::cell::RefCell;
use std::default::Default;
use std::marker::PhantomData;
use std::ops::Drop;
use std::sync::atomic::{AtomicBool, Ordering};
use crate::error::{Error, Result};
use crate::services::gspgpu::{self, FramebufferFormat};
/// Trait implemented by TopScreen and BottomScreen for common methods
@ -73,25 +74,39 @@ pub struct Gfx { @@ -73,25 +74,39 @@ pub struct Gfx {
pub bottom_screen: RefCell<BottomScreen>,
}
static GFX_ACTIVE: AtomicBool = AtomicBool::new(false);
impl Gfx {
/// Initialize the Gfx module with the chosen framebuffer formats for the top and bottom
/// screens
///
/// Use `Gfx::default()` instead of this function to initialize the module with default parameters
pub fn new(
/// Use `Gfx::init_default()` instead of this function to initialize the module with default parameters
pub fn init(
top_fb_fmt: FramebufferFormat,
bottom_fb_fmt: FramebufferFormat,
use_vram_buffers: bool,
) -> Self {
unsafe {
ctru_sys::gfxInit(top_fb_fmt.into(), bottom_fb_fmt.into(), use_vram_buffers);
}
Gfx {
top_screen: RefCell::new(TopScreen),
bottom_screen: RefCell::new(BottomScreen),
) -> Result<Self> {
match GFX_ACTIVE.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) {
Ok(_) => {
unsafe {
ctru_sys::gfxInit(top_fb_fmt.into(), bottom_fb_fmt.into(), use_vram_buffers);
}
Ok(Gfx {
top_screen: RefCell::new(TopScreen),
bottom_screen: RefCell::new(BottomScreen),
})
}
Err(_) => Err(Error::ServiceAlreadyActive("Gfx")),
}
}
/// Creates a new Gfx instance with default init values
/// It's the same as calling: `Gfx::init(FramebufferFormat::Bgr8, FramebufferFormat::Bgr8, false)
pub fn init_default() -> Result<Self> {
Gfx::init(FramebufferFormat::Bgr8, FramebufferFormat::Bgr8, false)
}
/// Flushes the current framebuffers
pub fn flush_buffers(&self) {
unsafe { ctru_sys::gfxFlushBuffers() };
@ -197,18 +212,21 @@ impl From<Side> for ctru_sys::gfx3dSide_t { @@ -197,18 +212,21 @@ impl From<Side> for ctru_sys::gfx3dSide_t {
}
}
impl Default for Gfx {
fn default() -> Self {
unsafe { ctru_sys::gfxInitDefault() };
Gfx {
top_screen: RefCell::new(TopScreen),
bottom_screen: RefCell::new(BottomScreen),
}
}
}
impl Drop for Gfx {
fn drop(&mut self) {
unsafe { ctru_sys::gfxExit() };
GFX_ACTIVE.store(false, Ordering::Release);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn gfx_duplicate() {
// We don't need to build a `Gfx` because the test runner has one already
assert!(Gfx::init_default().is_err());
}
}

29
ctru-rs/src/lib.rs

@ -38,12 +38,31 @@ pub fn init() { @@ -38,12 +38,31 @@ pub fn init() {
// Only for panics in the main thread
if main_thread == thread::current().id() && console::Console::exists() {
println!("\nPress SELECT to exit the software");
let hid = services::hid::Hid::init().unwrap();
loop {
hid.scan_input();
if hid.keys_down().contains(services::hid::KeyPad::KEY_SELECT) {
break;
// The use of unsafe functions here is basically obligatory.
// To have memory safety when using the `Hid` struct, we must not make more
// than one available at the same time, so no drop/service ownership issues arise.
// The problem here is that the `panic_hook` is run _before_ the app cleanup,
// so an `Hid` stuct may still be alive and thus make the `panic_hook` panic.
// If that were to happen, the system would have to reboot to properly close the app.
//
// Using `hidInit` is safe when another instance is open, and we can do safe operations afterwards.
// The only (probably) unsafe part of this system is the `hidExit`, since in a multithreaded
// environment some other threads may still be doing operations on the service
// before the cleanup, though the time window would be almost nonexistent, and it would only
// really be a problem in preemptive threads.
//
// TL;DR : This code is bad.
unsafe {
ctru_sys::hidInit();
loop {
ctru_sys::hidScanInput();
let keys = services::hid::KeyPad::from_bits_truncate(ctru_sys::hidKeysDown());
if keys.contains(services::hid::KeyPad::KEY_SELECT) {
ctru_sys::hidExit();
break;
}
}
}
}

38
ctru-rs/src/romfs.rs

@ -11,19 +11,29 @@ @@ -11,19 +11,29 @@
//! ```
use std::ffi::CStr;
use std::sync::atomic::{AtomicBool, Ordering};
use crate::error::Error;
#[non_exhaustive]
pub struct RomFS;
static ROMFS_ACTIVE: AtomicBool = AtomicBool::new(false);
impl RomFS {
pub fn new() -> crate::Result<Self> {
let mount_name = CStr::from_bytes_with_nul(b"romfs\0").unwrap();
let result = unsafe { ctru_sys::romfsMountSelf(mount_name.as_ptr()) };
pub fn init() -> crate::Result<Self> {
match ROMFS_ACTIVE.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) {
Ok(_) => {
let mount_name = CStr::from_bytes_with_nul(b"romfs\0").unwrap();
let result = unsafe { ctru_sys::romfsMountSelf(mount_name.as_ptr()) };
if result < 0 {
Err(result.into())
} else {
Ok(Self)
if result < 0 {
Err(result.into())
} else {
Ok(Self)
}
}
Err(_) => Err(Error::ServiceAlreadyActive("RomFS")),
}
}
}
@ -32,5 +42,19 @@ impl Drop for RomFS { @@ -32,5 +42,19 @@ impl Drop for RomFS {
fn drop(&mut self) {
let mount_name = CStr::from_bytes_with_nul(b"romfs\0").unwrap();
unsafe { ctru_sys::romfsUnmount(mount_name.as_ptr()) };
ROMFS_ACTIVE.store(false, Ordering::Release);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn romfs_duplicate() {
let _romfs = RomFS::init().unwrap();
assert!(RomFS::init().is_err());
}
}

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

@ -1,14 +1,24 @@ @@ -1,14 +1,24 @@
use std::sync::atomic::{AtomicBool, Ordering};
use crate::error::Error;
#[non_exhaustive]
pub struct Apt(());
static APT_ACTIVE: AtomicBool = AtomicBool::new(false);
impl Apt {
pub fn init() -> crate::Result<Apt> {
unsafe {
let r = ctru_sys::aptInit();
if r < 0 {
Err(r.into())
} else {
Ok(Apt(()))
pub fn init() -> crate::Result<Self> {
match APT_ACTIVE.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) {
Ok(_) => {
let r = unsafe { ctru_sys::aptInit() };
if r < 0 {
Err(r.into())
} else {
Ok(Self(()))
}
}
Err(_) => Err(Error::ServiceAlreadyActive("Apt")),
}
}
@ -17,13 +27,11 @@ impl Apt { @@ -17,13 +27,11 @@ impl Apt {
}
pub fn set_app_cpu_time_limit(&self, percent: u32) -> crate::Result<()> {
unsafe {
let r = ctru_sys::APT_SetAppCpuTimeLimit(percent);
if r < 0 {
Err(r.into())
} else {
Ok(())
}
let r = unsafe { ctru_sys::APT_SetAppCpuTimeLimit(percent) };
if r < 0 {
Err(r.into())
} else {
Ok(())
}
}
}
@ -31,5 +39,19 @@ impl Apt { @@ -31,5 +39,19 @@ impl Apt {
impl Drop for Apt {
fn drop(&mut self) {
unsafe { ctru_sys::aptExit() };
APT_ACTIVE.store(false, Ordering::Release);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn gfx_duplicate() {
// We don't need to build a `Apt` because the test runner has one already
assert!(Apt::init().is_err());
}
}

42
ctru-rs/src/services/fs.rs

@ -13,9 +13,12 @@ use std::mem; @@ -13,9 +13,12 @@ use std::mem;
use std::path::{Path, PathBuf};
use std::ptr;
use std::slice;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use widestring::{WideCStr, WideCString};
use crate::error::Error;
bitflags! {
#[derive(Default)]
struct FsOpen: u32 {
@ -82,8 +85,11 @@ pub enum ArchiveID { @@ -82,8 +85,11 @@ pub enum ArchiveID {
/// until an instance of this struct is created.
///
/// The service exits when all instances of this struct go out of scope.
#[non_exhaustive]
pub struct Fs(());
static FS_ACTIVE: AtomicBool = AtomicBool::new(false);
/// Handle to an open filesystem archive.
///
/// Archives are automatically closed when they go out of scope.
@ -96,6 +102,7 @@ pub struct Fs(()); @@ -96,6 +102,7 @@ pub struct Fs(());
/// let fs = Fs::init().unwrap();
/// let sdmc_archive = fs.sdmc().unwrap();
/// ```
#[non_exhaustive]
pub struct Archive {
id: ArchiveID,
handle: u64,
@ -164,6 +171,7 @@ pub struct Archive { @@ -164,6 +171,7 @@ pub struct Archive {
/// # Ok(())
/// # }
/// ```
#[non_exhaustive]
pub struct File {
handle: u32,
offset: u64,
@ -175,6 +183,7 @@ pub struct File { @@ -175,6 +183,7 @@ pub struct File {
/// represents known metadata about a file.
///
/// [`metadata`]: fn.metadata.html
#[non_exhaustive]
pub struct Metadata {
attributes: u32,
size: u64,
@ -257,6 +266,7 @@ pub struct OpenOptions { @@ -257,6 +266,7 @@ pub struct OpenOptions {
///
/// This Result will return Err if there's some sort of intermittent IO error
/// during iteration.
#[non_exhaustive]
pub struct ReadDir<'a> {
handle: Dir,
root: Arc<PathBuf>,
@ -297,14 +307,17 @@ impl Fs { @@ -297,14 +307,17 @@ impl Fs {
/// ctrulib services are reference counted, so this function may be called
/// as many times as desired and the service will not exit until all
/// instances of Fs drop out of scope.
pub fn init() -> crate::Result<Fs> {
unsafe {
let r = ctru_sys::fsInit();
if r < 0 {
Err(r.into())
} else {
Ok(Fs(()))
pub fn init() -> crate::Result<Self> {
match FS_ACTIVE.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) {
Ok(_) => {
let r = unsafe { ctru_sys::fsInit() };
if r < 0 {
Err(r.into())
} else {
Ok(Self(()))
}
}
Err(_) => Err(Error::ServiceAlreadyActive("Fs")),
}
}
@ -990,6 +1003,8 @@ impl Drop for Fs { @@ -990,6 +1003,8 @@ impl Drop for Fs {
unsafe {
ctru_sys::fsExit();
}
FS_ACTIVE.store(false, Ordering::Release);
}
}
@ -1059,3 +1074,16 @@ impl From<ArchiveID> for ctru_sys::FS_ArchiveID { @@ -1059,3 +1074,16 @@ impl From<ArchiveID> for ctru_sys::FS_ArchiveID {
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn fs_duplicate() {
let _fs = Fs::init().unwrap();
assert!(Fs::init().is_err());
}
}

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

@ -4,6 +4,10 @@ @@ -4,6 +4,10 @@
//! and circle pad information. It also provides information from the sound volume slider,
//! the accelerometer, and the gyroscope.
use std::sync::atomic::{AtomicBool, Ordering};
use crate::error::Error;
bitflags::bitflags! {
/// A set of flags corresponding to the button and directional pad
/// inputs on the 3DS
@ -44,12 +48,17 @@ bitflags::bitflags! { @@ -44,12 +48,17 @@ bitflags::bitflags! {
/// when all instances of this struct fall out of scope.
///
/// This service requires no special permissions to use.
#[non_exhaustive]
pub struct Hid(());
static HID_ACTIVE: AtomicBool = AtomicBool::new(false);
/// Represents user input to the touchscreen.
#[non_exhaustive]
pub struct TouchPosition(ctru_sys::touchPosition);
/// Represents the current position of the 3DS circle pad.
#[non_exhaustive]
pub struct CirclePosition(ctru_sys::circlePosition);
/// Initializes the HID service.
@ -60,14 +69,17 @@ pub struct CirclePosition(ctru_sys::circlePosition); @@ -60,14 +69,17 @@ pub struct CirclePosition(ctru_sys::circlePosition);
/// Since this service requires no special or elevated permissions, errors are
/// rare in practice.
impl Hid {
pub fn init() -> crate::Result<Hid> {
unsafe {
let r = ctru_sys::hidInit();
if r < 0 {
Err(r.into())
} else {
Ok(Hid(()))
pub fn init() -> crate::Result<Self> {
match HID_ACTIVE.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) {
Ok(_) => {
let r = unsafe { ctru_sys::hidInit() };
if r < 0 {
Err(r.into())
} else {
Ok(Self(()))
}
}
Err(_) => Err(Error::ServiceAlreadyActive("Hid")),
}
}
@ -151,5 +163,18 @@ impl CirclePosition { @@ -151,5 +163,18 @@ impl CirclePosition {
impl Drop for Hid {
fn drop(&mut self) {
unsafe { ctru_sys::hidExit() };
HID_ACTIVE.store(false, Ordering::Release);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn hid_duplicate() {
// We don't need to build a `Hid` because the test runner has one already
assert!(Hid::init().is_err());
}
}

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

@ -63,8 +63,6 @@ pub fn generate_random_bytes(out: &mut [u8]) -> crate::Result<()> { @@ -63,8 +63,6 @@ pub fn generate_random_bytes(out: &mut [u8]) -> crate::Result<()> {
mod tests {
use std::collections::HashMap;
use super::*;
#[test]
fn construct_hash_map() {
let mut input = vec![

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

@ -1,21 +1,27 @@ @@ -1,21 +1,27 @@
use ctru_sys::{socExit, socInit};
use libc::{free, memalign};
use std::net::Ipv4Addr;
use std::sync::atomic::{AtomicBool, Ordering};
use crate::error::Error;
use ctru_sys::{socExit, socInit};
/// Soc service. Initializing this service will enable the use of network sockets and utilities
/// such as those found in `std::net`. The service will be closed when this struct is is dropped.
#[non_exhaustive]
pub struct Soc {
soc_mem: *mut u32,
}
static SOC_ACTIVE: AtomicBool = AtomicBool::new(false);
impl Soc {
/// Initialize the Soc service with a default buffer size of 0x100000 bytes
///
/// # Errors
///
/// This function will return an error if the `Soc` service is already initialized
pub fn init() -> crate::Result<Soc> {
Soc::init_with_buffer_size(0x100000)
pub fn init() -> crate::Result<Self> {
Self::init_with_buffer_size(0x100000)
}
/// Initialize the Soc service with a custom buffer size in bytes. The size should be
@ -24,17 +30,20 @@ impl Soc { @@ -24,17 +30,20 @@ impl Soc {
/// # Errors
///
/// This function will return an error if the `Soc` service is already initialized
pub fn init_with_buffer_size(num_bytes: usize) -> crate::Result<Soc> {
unsafe {
let soc_mem = memalign(0x1000, num_bytes) as *mut u32;
let r = socInit(soc_mem, num_bytes as u32);
if r < 0 {
free(soc_mem as *mut _);
Err(r.into())
} else {
Ok(Soc { soc_mem })
}
pub fn init_with_buffer_size(num_bytes: usize) -> crate::Result<Self> {
match SOC_ACTIVE.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) {
Ok(_) => unsafe {
let soc_mem = memalign(0x1000, num_bytes) as *mut u32;
let r = socInit(soc_mem, num_bytes as u32);
if r < 0 {
free(soc_mem as *mut _);
Err(r.into())
} else {
Ok(Self { soc_mem })
}
},
Err(_) => Err(Error::ServiceAlreadyActive("Soc")),
}
}
@ -51,5 +60,19 @@ impl Drop for Soc { @@ -51,5 +60,19 @@ impl Drop for Soc {
socExit();
free(self.soc_mem as *mut _);
}
SOC_ACTIVE.store(false, Ordering::Release);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn soc_duplicate() {
let _soc = Soc::init().unwrap();
assert!(Soc::init().is_err());
}
}

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

@ -1,29 +1,37 @@ @@ -1,29 +1,37 @@
// TODO: Implement remaining functions
use std::sync::atomic::{AtomicBool, Ordering};
use crate::error::Error;
#[non_exhaustive]
pub struct SslC(());
static SSLC_ACTIVE: AtomicBool = AtomicBool::new(false);
impl SslC {
/// Initialize sslc
pub fn init() -> crate::Result<Self> {
unsafe {
let r = ctru_sys::sslcInit(0);
if r < 0 {
Err(r.into())
} else {
Ok(SslC(()))
match SSLC_ACTIVE.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) {
Ok(_) => {
let r = unsafe { ctru_sys::sslcInit(0) };
if r < 0 {
Err(r.into())
} else {
Ok(Self(()))
}
}
Err(_) => Err(Error::ServiceAlreadyActive("SslC")),
}
}
/// Fill `buf` with `buf.len()` random bytes
pub fn generate_random_data(&self, buf: &mut [u8]) -> crate::Result<()> {
unsafe {
let r = ctru_sys::sslcGenerateRandomData(buf.as_ptr() as _, buf.len() as u32);
if r < 0 {
Err(r.into())
} else {
Ok(())
}
let r = unsafe { ctru_sys::sslcGenerateRandomData(buf.as_ptr() as _, buf.len() as u32) };
if r < 0 {
Err(r.into())
} else {
Ok(())
}
}
}
@ -31,5 +39,20 @@ impl SslC { @@ -31,5 +39,20 @@ impl SslC {
impl Drop for SslC {
fn drop(&mut self) {
unsafe { ctru_sys::sslcExit() };
SSLC_ACTIVE.store(false, Ordering::Release);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn sslc_duplicate() {
let _sslc = SslC::init().unwrap();
assert!(SslC::init().is_err());
}
}

38
ctru-rs/src/srv.rs

@ -1,14 +1,24 @@ @@ -1,14 +1,24 @@
use std::sync::atomic::{AtomicBool, Ordering};
use crate::error::Error;
#[non_exhaustive]
pub struct Srv(());
static SRV_ACTIVE: AtomicBool = AtomicBool::new(false);
impl Srv {
pub fn init() -> crate::Result<Srv> {
unsafe {
let r = ctru_sys::srvInit();
if r < 0 {
Err(r.into())
} else {
Ok(Srv(()))
pub fn init() -> crate::Result<Self> {
match SRV_ACTIVE.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) {
Ok(_) => {
let r = unsafe { ctru_sys::srvInit() };
if r < 0 {
Err(r.into())
} else {
Ok(Self(()))
}
}
Err(_) => Err(Error::ServiceAlreadyActive("Srv")),
}
}
}
@ -16,5 +26,19 @@ impl Srv { @@ -16,5 +26,19 @@ impl Srv {
impl Drop for Srv {
fn drop(&mut self) {
unsafe { ctru_sys::srvExit() };
SRV_ACTIVE.store(false, Ordering::Release);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn srv_duplicate() {
let _srv = Srv::init().unwrap();
assert!(Srv::init().is_err());
}
}

7
ctru-rs/src/test_runner.rs

@ -17,7 +17,7 @@ use crate::services::Apt; @@ -17,7 +17,7 @@ use crate::services::Apt;
pub(crate) fn run(tests: &[&TestDescAndFn]) {
crate::init();
let gfx = Gfx::default();
let gfx = Gfx::init_default().unwrap();
let hid = Hid::init().unwrap();
let apt = Apt::init().unwrap();
@ -115,9 +115,4 @@ mod link_fix { @@ -115,9 +115,4 @@ mod link_fix {
extern "C" fn sigemptyset(_arg1: *mut libc::sigset_t) -> ::libc::c_int {
-1
}
#[no_mangle]
extern "C" fn sysconf(_name: libc::c_int) -> libc::c_long {
-1
}
}

Loading…
Cancel
Save