diff --git a/.gitignore b/.gitignore index 54f1838..ce18a29 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,6 @@ Cargo.lock # IDE files .idea + +# 3ds files +*.cia diff --git a/ctru-rs/examples/camera-image.rs b/ctru-rs/examples/camera-image.rs index be93f86..6f25c26 100644 --- a/ctru-rs/examples/camera-image.rs +++ b/ctru-rs/examples/camera-image.rs @@ -87,14 +87,14 @@ fn main() { gfx.swap_buffers(); gfx.wait_for_vblank(); held_r = true; - take_picture(&mut cam, buf.as_mut_ptr()); + take_picture(&mut cam, &mut buf); } else if !key_held.contains(KeyPad::KEY_R) { held_r = false; } write_picture_to_frame_buffer_rgb_565( gfx.top_screen.borrow_mut().get_raw_framebuffer(Side::Left), - buf.as_mut_ptr(), + &mut buf, 0, 0, WIDTH as u16, @@ -107,7 +107,7 @@ fn main() { } } -fn take_picture(cam: &mut Cam, buf: *mut u8) { +fn take_picture(cam: &mut Cam, buf: &mut [u8]) { let mut buf_size = 0; cam.get_max_bytes(&mut buf_size, WIDTH as i16, HEIGHT as i16) .expect("Failed to get max bytes"); @@ -138,7 +138,7 @@ fn take_picture(cam: &mut Cam, buf: *mut u8) { .expect("Failed to set receiving"); cam.set_receiving( &mut receive_event2, - unsafe { buf.add(SCREEN_SIZE) }, + &mut buf[SCREEN_SIZE..], CamPort::PORT_CAM2, SCREEN_SIZE as u32, buf_size as i16, @@ -175,14 +175,14 @@ fn take_picture(cam: &mut Cam, buf: *mut u8) { fn write_picture_to_frame_buffer_rgb_565( fb: RawFrameBuffer, - img: *mut u8, + img: &mut [u8], x: u16, y: u16, width: u16, height: u16, ) { let fb_8 = fb.ptr; - let img_16 = img as *mut u16; + let img_16 = img.as_mut_ptr() as *mut u16; let mut draw_x; let mut draw_y; for j in 0..height { diff --git a/ctru-rs/examples/network-sockets.rs b/ctru-rs/examples/network-sockets.rs index ac8953d..6526d41 100644 --- a/ctru-rs/examples/network-sockets.rs +++ b/ctru-rs/examples/network-sockets.rs @@ -43,7 +43,7 @@ fn main() { } else { println!("Unable to read stream: {}", e) } - }, + } } let response = b"HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\nHello world\r\n"; diff --git a/ctru-rs/src/services/cam.rs b/ctru-rs/src/services/cam.rs index 0c24093..c0c5078 100644 --- a/ctru-rs/src/services/cam.rs +++ b/ctru-rs/src/services/cam.rs @@ -26,6 +26,26 @@ bitflags! { } } +bitflags! { + #[derive(Default)] + pub struct CamContext: u32 { + const CONTEXT_NONE = 0; + const CONTEXT_A = 1; + const CONTEXT_B = 2; + const CONTEXT_BOTH = Self::CONTEXT_A.bits | Self::CONTEXT_B.bits; + } +} + +bitflags! { + #[derive(Default)] + pub struct CamFlip: u32 { + const FLIP_NONE = 0; + const FLIP_HORIZONTAL = 1; + const FLIP_VERTICAL = 2; + const FLIP_REVERSE = 3; + } +} + bitflags! { #[derive(Default)] pub struct CamSize: u32 { @@ -43,11 +63,97 @@ bitflags! { bitflags! { #[derive(Default)] - pub struct CamContext: u32 { - const CONTEXT_NONE = 0; - const CONTEXT_A = 1; - const CONTEXT_B = 2; - const CONTEXT_BOTH = Self::CONTEXT_A.bits | Self::CONTEXT_B.bits; + pub struct CamFrameRate: u32 { + const FRAME_RATE_15 = 0; + const FRAME_RATE_15_TO_5 = 1; + const FRAME_RATE_15_TO_2 = 2; + const FRAME_RATE_10 = 3; + const FRAME_RATE_8_5 = 4; + const FRAME_RATE_5 = 5; + const FRAME_RATE_20 = 6; + const FRAME_RATE_20_TO_5 = 7; + const FRAME_RATE_30 = 8; + const FRAME_RATE_30_TO_5 = 9; + const FRAME_RATE_15_TO_10 = 10; + const FRAME_RATE_20_TO_10 = 11; + const FRAME_RATE_30_TO_10 = 12; + } +} + +bitflags! { + #[derive(Default)] + pub struct CamWhiteBalance: u32 { + const WHITE_BALANCE_AUTO = 0; + const WHITE_BALANCE_3200K = 1; + const WHITE_BALANCE_4150K = 2; + const WHITE_BALANCE_5200K = 3; + const WHITE_BALANCE_6000K = 4; + const WHITE_BALANCE_7000K = 5; + + const WHITE_BALANCE_NORMAL = Self::WHITE_BALANCE_AUTO.bits; + const WHITE_BALANCE_TUNGSTEN = Self::WHITE_BALANCE_3200K.bits; + const WHITE_BALANCE_WHITE_FLUORESCENT_LIGHT = Self::WHITE_BALANCE_4150K.bits; + const WHITE_BALANCE_DAYLIGHT = Self::WHITE_BALANCE_5200K.bits; + const WHITE_BALANCE_CLOUDY = Self::WHITE_BALANCE_6000K.bits; + const WHITE_BALANCE_HORIZON = Self::WHITE_BALANCE_6000K.bits; + const WHITE_BALANCE_SHADE = Self::WHITE_BALANCE_7000K.bits; + } +} + +bitflags! { + #[derive(Default)] + pub struct CamPhotoMode: u32 { + const PHOTO_MODE_NORMAL = 0; + const PHOTO_MODE_PORTRAIT = 1; + const PHOTO_MODE_LANDSCAPE = 2; + const PHOTO_MODE_NIGHTVIEW = 3; + const PHOTO_MODE_LETTER = 4; + } +} + +bitflags! { + #[derive(Default)] + pub struct CamEffect: u32 { + const EFFECT_NONE = 0; + const EFFECT_MONO = 1; + const EFFECT_SEPIA = 2; + const EFFECT_NEGATIVE = 3; + const EFFECT_NEGAFILM = 4; + const EFFECT_SEPIA01 = 5; + } +} + +bitflags! { + #[derive(Default)] + pub struct CamContrast: u32 { + const CONTRAST_PATTERN_01 = 0; + const CONTRAST_PATTERN_02 = 1; + const CONTRAST_PATTERN_03 = 2; + const CONTRAST_PATTERN_04 = 3; + const CONTRAST_PATTERN_05 = 4; + const CONTRAST_PATTERN_06 = 5; + const CONTRAST_PATTERN_07 = 6; + const CONTRAST_PATTERN_08 = 7; + const CONTRAST_PATTERN_09 = 8; + const CONTRAST_PATTERN_10 = 9; + const CONTRAST_PATTERN_11 = 10; + + const CONTRAST_LOW = Self::CONTRAST_PATTERN_05.bits; + const CONTRAST_NORMAL = Self::CONTRAST_PATTERN_06.bits; + const CONTRAST_HIGH = Self::CONTRAST_PATTERN_07.bits; + } +} + +bitflags! { + #[derive(Default)] + pub struct CamLensCorrection: u32 { + const LENS_CORRECTION_OFF = 0; + const LENS_CORRECTION_ON_70 = 1; + const LENS_CORRECTION_ON_90 = 2; + + const LENS_CORRECTION_DARK = Self::LENS_CORRECTION_OFF.bits; + const LENS_CORRECTION_NORMAL = Self::LENS_CORRECTION_ON_70.bits; + const LENS_CORRECTION_BRIGHT = Self::LENS_CORRECTION_ON_90.bits; } } @@ -80,14 +186,304 @@ impl Cam { } } - pub fn set_size( - &mut self, + pub fn start_capture(&self, port: CamPort) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_StartCapture(port.bits()); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn stop_capture(&self, port: CamPort) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_StopCapture(port.bits()); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn is_busy(&self, bool: &mut bool, port: CamPort) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_IsBusy(bool, port.bits()); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn clear_buffer(&self, port: CamPort) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_ClearBuffer(port.bits()); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn get_vsync_interrupt_event(&self, event: &mut u32, port: CamPort) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_GetVsyncInterruptEvent(event, port.bits()); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn get_buffer_error_interrupt_event( + &self, + event: &mut u32, + port: CamPort, + ) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_GetBufferErrorInterruptEvent(event, port.bits()); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn set_receiving( + &self, + handle: &mut u32, + buf: &mut [u8], + port: CamPort, + size: u32, + buf_size: i16, + ) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_SetReceiving( + handle, + buf.as_mut_ptr() as *mut ::libc::c_void, + port.bits(), + size, + buf_size, + ); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn is_finished_receiving( + &self, + finished_receiving: &mut bool, + port: CamPort, + ) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_IsFinishedReceiving(finished_receiving, port.bits()); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn set_transfer_lines( + &self, + port: CamPort, + lines: i16, + width: i16, + height: i16, + ) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_SetTransferLines(port.bits(), lines, width, height); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn get_max_lines(&self, max_lines: &mut i16, width: i16, height: i16) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_GetMaxLines(max_lines, width, height); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn set_transfer_bytes( + &self, + port: CamPort, + buf_size: u32, + width: i16, + height: i16, + ) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_SetTransferBytes(port.bits(), buf_size, width, height); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn get_transfer_bytes(&self, transfer_bytes: &mut u32, port: CamPort) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_GetTransferBytes(transfer_bytes, port.bits()); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn get_max_bytes(&self, buf_size: &mut u32, width: i16, height: i16) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_GetMaxBytes(buf_size, width, height); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn set_trimming(&self, port: CamPort, enabled: bool) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_SetTrimming(port.bits(), enabled); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn is_trimming(&self, trimming: &mut bool, port: CamPort) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_IsTrimming(trimming, port.bits()); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn set_trimming_params( + &self, + port: CamPort, + x_start: i16, + y_start: i16, + x_end: i16, + y_end: i16, + ) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_SetTrimmingParams(port.bits(), x_start, y_start, x_end, y_end); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn get_trimming_params( + &self, + x_start: &mut i16, + y_start: &mut i16, + x_end: &mut i16, + y_end: &mut i16, + port: CamPort, + ) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_GetTrimmingParams(x_start, y_start, x_end, y_end, port.bits()); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn set_trimming_params_center( + &self, + port: CamPort, + trim_width: i16, + trim_height: i16, + cam_width: i16, + cam_height: i16, + ) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_SetTrimmingParamsCenter( + port.bits(), + trim_width, + trim_height, + cam_width, + cam_height, + ); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn activate(&self, camera: CamSelect) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_Activate(camera.bits()); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn switch_context(&self, camera: CamSelect, context: CamContext) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_SwitchContext(camera.bits(), context.bits()); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn set_exposure(&self, camera: CamSelect, exposure: i8) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_SetExposure(camera.bits(), exposure); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn set_white_balance( + &self, camera: CamSelect, - size: CamSize, - context: CamContext, + white_balance: CamWhiteBalance, ) -> crate::Result<()> { unsafe { - let r = ctru_sys::CAMU_SetSize(camera.bits(), size.bits(), context.bits()); + let r = ctru_sys::CAMU_SetWhiteBalance(camera.bits(), white_balance.bits()); if r < 0 { Err(r.into()) } else { @@ -96,14 +492,14 @@ impl Cam { } } - pub fn set_output_format( - &mut self, + pub fn set_white_balance_without_base_up( + &self, camera: CamSelect, - format: CamOutputFormat, - context: CamContext, + white_balance: CamWhiteBalance, ) -> crate::Result<()> { unsafe { - let r = ctru_sys::CAMU_SetOutputFormat(camera.bits(), format.bits(), context.bits()); + let r = + ctru_sys::CAMU_SetWhiteBalanceWithoutBaseUp(camera.bits(), white_balance.bits()); if r < 0 { Err(r.into()) } else { @@ -112,9 +508,9 @@ impl Cam { } } - pub fn set_noise_filter(&mut self, camera: CamSelect, enabled: bool) -> crate::Result<()> { + pub fn set_sharpness(&self, camera: CamSelect, sharpness: i8) -> crate::Result<()> { unsafe { - let r = ctru_sys::CAMU_SetNoiseFilter(camera.bits(), enabled); + let r = ctru_sys::CAMU_SetSharpness(camera.bits(), sharpness); if r < 0 { Err(r.into()) } else { @@ -123,7 +519,7 @@ impl Cam { } } - pub fn set_auto_exposure(&mut self, camera: CamSelect, enabled: bool) -> crate::Result<()> { + pub fn set_auto_exposure(&self, camera: CamSelect, enabled: bool) -> crate::Result<()> { unsafe { let r = ctru_sys::CAMU_SetAutoExposure(camera.bits(), enabled); if r < 0 { @@ -134,11 +530,22 @@ impl Cam { } } - pub fn set_auto_white_balance( - &mut self, + pub fn is_auto_exposure( + &self, + is_auto_exposure: &mut bool, camera: CamSelect, - enabled: bool, ) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_IsAutoExposure(is_auto_exposure, camera.bits()); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn set_auto_white_balance(&self, camera: CamSelect, enabled: bool) -> crate::Result<()> { unsafe { let r = ctru_sys::CAMU_SetAutoWhiteBalance(camera.bits(), enabled); if r < 0 { @@ -149,9 +556,13 @@ impl Cam { } } - pub fn set_trimming(&mut self, port: CamPort, enabled: bool) -> crate::Result<()> { + pub fn is_auto_white_balance( + &self, + is_auto_white_balance: &mut bool, + camera: CamSelect, + ) -> crate::Result<()> { unsafe { - let r = ctru_sys::CAMU_SetTrimming(port.bits(), enabled); + let r = ctru_sys::CAMU_IsAutoWhiteBalance(is_auto_white_balance, camera.bits()); if r < 0 { Err(r.into()) } else { @@ -160,9 +571,14 @@ impl Cam { } } - pub fn get_max_bytes(&self, buf_size: &mut u32, width: i16, height: i16) -> crate::Result<()> { + pub fn flip_image( + &self, + camera: CamSelect, + flip: CamFlip, + context: CamContext, + ) -> crate::Result<()> { unsafe { - let r = ctru_sys::CAMU_GetMaxBytes(buf_size, width, height); + let r = ctru_sys::CAMU_FlipImage(camera.bits(), flip.bits(), context.bits()); if r < 0 { Err(r.into()) } else { @@ -171,15 +587,28 @@ impl Cam { } } - pub fn set_transfer_bytes( - &mut self, - port: CamPort, - buf_size: u32, + pub fn set_detail_size( + &self, + camera: CamSelect, width: i16, height: i16, + crop_x0: i16, + crop_y0: i16, + crop_x1: i16, + crop_y1: i16, + context: CamContext, ) -> crate::Result<()> { unsafe { - let r = ctru_sys::CAMU_SetTransferBytes(port.bits(), buf_size, width, height); + let r = ctru_sys::CAMU_SetDetailSize( + camera.bits(), + width, + height, + crop_x0, + crop_y0, + crop_x1, + crop_y1, + context.bits(), + ); if r < 0 { Err(r.into()) } else { @@ -188,9 +617,141 @@ impl Cam { } } - pub fn clear_buffer(&mut self, port: CamPort) -> crate::Result<()> { + pub fn set_size( + &self, + camera: CamSelect, + size: CamSize, + context: CamContext, + ) -> crate::Result<()> { unsafe { - let r = ctru_sys::CAMU_ClearBuffer(port.bits()); + let r = ctru_sys::CAMU_SetSize(camera.bits(), size.bits(), context.bits()); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn set_frame_rate(&self, camera: CamSelect, frame_rate: CamFrameRate) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_SetFrameRate(camera.bits(), frame_rate.bits()); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn set_photo_mode(&self, camera: CamSelect, photo_mode: CamPhotoMode) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_SetPhotoMode(camera.bits(), photo_mode.bits()); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn set_effect( + &self, + camera: CamSelect, + effect: CamEffect, + context: CamContext, + ) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_SetEffect(camera.bits(), effect.bits(), context.bits()); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn set_contrast(&self, camera: CamSelect, contrast: CamContrast) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_SetContrast(camera.bits(), contrast.bits()); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn set_lens_correction( + &self, + camera: CamSelect, + lens_correction: CamLensCorrection, + ) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_SetLensCorrection(camera.bits(), lens_correction.bits()); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn set_output_format( + &self, + camera: CamSelect, + format: CamOutputFormat, + context: CamContext, + ) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_SetOutputFormat(camera.bits(), format.bits(), context.bits()); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn set_auto_exposure_window( + &self, + camera: CamSelect, + x: i16, + y: i16, + width: i16, + height: i16, + ) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_SetAutoExposureWindow(camera.bits(), x, y, width, height); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn set_auto_white_balance_window( + &self, + camera: CamSelect, + x: i16, + y: i16, + width: i16, + height: i16, + ) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_SetAutoWhiteBalanceWindow(camera.bits(), x, y, width, height); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn set_noise_filter(&self, camera: CamSelect, enabled: bool) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_SetNoiseFilter(camera.bits(), enabled); if r < 0 { Err(r.into()) } else { @@ -200,7 +761,7 @@ impl Cam { } pub fn synchronize_vsync_timing( - &mut self, + &self, camera1: CamSelect, camera2: CamSelect, ) -> crate::Result<()> { @@ -214,16 +775,73 @@ impl Cam { } } - pub fn set_receiving( - &mut self, - handle: &mut u32, - buf: *mut u8, + pub fn get_latest_vsync_timing( + &self, + timing: &mut i64, port: CamPort, - size: u32, - buf_size: i16, + past: u32, ) -> crate::Result<()> { unsafe { - let r = ctru_sys::CAMU_SetReceiving(handle, buf as *mut ::libc::c_void, port.bits(), size, buf_size); + let r = ctru_sys::CAMU_GetLatestVsyncTiming(timing, port.bits(), past); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn write_register_i2c(&self, camera: CamSelect, addr: u16, data: u16) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_WriteRegisterI2c(camera.bits(), addr, data); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn write_mcu_variable_i2c( + &self, + camera: CamSelect, + addr: u16, + data: u16, + ) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_WriteMcuVariableI2c(camera.bits(), addr, data); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn read_register_i2c_exclusive( + &self, + data: &mut u16, + camera: CamSelect, + addr: u16, + ) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_ReadRegisterI2cExclusive(data, camera.bits(), addr); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn read_mcu_variable_i2c_exclusive( + &self, + data: &mut u16, + camera: CamSelect, + addr: u16, + ) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_ReadMcuVariableI2cExclusive(data, camera.bits(), addr); if r < 0 { Err(r.into()) } else { @@ -243,9 +861,9 @@ impl Cam { } } - pub fn start_capture(&self, port: CamPort) -> crate::Result<()> { + pub fn driver_initialize(&self) -> crate::Result<()> { unsafe { - let r = ctru_sys::CAMU_StartCapture(port.bits()); + let r = ctru_sys::CAMU_DriverInitialize(); if r < 0 { Err(r.into()) } else { @@ -254,9 +872,9 @@ impl Cam { } } - pub fn stop_capture(&self, port: CamPort) -> crate::Result<()> { + pub fn driver_finalize(&self) -> crate::Result<()> { unsafe { - let r = ctru_sys::CAMU_StopCapture(port.bits()); + let r = ctru_sys::CAMU_DriverFinalize(); if r < 0 { Err(r.into()) } else { @@ -265,9 +883,45 @@ impl Cam { } } - pub fn activate(&mut self, camera: CamSelect) -> crate::Result<()> { + pub fn get_activated_camera(&self, camera: &mut u32) -> crate::Result<()> { unsafe { - let r = ctru_sys::CAMU_Activate(camera.bits()); + let r = ctru_sys::CAMU_GetActivatedCamera(camera); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn get_sleep_camera(&self, camera: &mut u32) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_GetSleepCamera(camera); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn set_sleep_camera(&self, camera: CamSelect) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_SetSleepCamera(camera.bits()); + if r < 0 { + Err(r.into()) + } else { + Ok(()) + } + } + } + + pub fn set_brightness_synchronization( + &self, + brightness_synchronization: bool, + ) -> crate::Result<()> { + unsafe { + let r = ctru_sys::CAMU_SetBrightnessSynchronization(brightness_synchronization); if r < 0 { Err(r.into()) } else { diff --git a/ctru-rs/src/services/reference.rs b/ctru-rs/src/services/reference.rs index 7fac227..41319a7 100644 --- a/ctru-rs/src/services/reference.rs +++ b/ctru-rs/src/services/reference.rs @@ -16,7 +16,9 @@ impl ServiceReference { S: FnOnce() -> crate::Result<()>, E: Fn() + Send + Sync + 'static, { - let mut value = counter.lock().expect("Mutex Counter for ServiceReference is poisoned"); // todo: handle poisoning + let mut value = counter + .lock() + .expect("Mutex Counter for ServiceReference is poisoned"); // todo: handle poisoning if *value == 0 { start()?; @@ -35,7 +37,10 @@ impl ServiceReference { impl Drop for ServiceReference { fn drop(&mut self) { - let mut value = self.counter.lock().expect("Mutex Counter for ServiceReference is poisoned"); // todo: handle poisoning + let mut value = self + .counter + .lock() + .expect("Mutex Counter for ServiceReference is poisoned"); // todo: handle poisoning *value -= 1; if *value == 0 { (self.close)(); diff --git a/example.rsf b/example.rsf new file mode 100644 index 0000000..b415eeb --- /dev/null +++ b/example.rsf @@ -0,0 +1,184 @@ +BasicInfo: + Title : ctru-rs-test + ProductCode : CTRU-TEST + Logo : Homebrew # Nintendo / Licensed / Distributed / iQue / iQueForSystem + +TitleInfo: + Category : Application + UniqueId : 0xCC + +Option: + UseOnSD : true # true if App is to be installed to SD + FreeProductCode : true # Removes limitations on ProductCode + MediaFootPadding : false # If true CCI files are created with padding + EnableCrypt : false # Enables encryption for NCCH and CIA + EnableCompress : false # Compresses where applicable (currently only exefs:/.code) + +AccessControlInfo: + CoreVersion : 2 + + # Exheader Format Version + DescVersion : 2 + + # ExtData + UseExtSaveData : false # enables ExtData + + # FS:USER Archive Access Permissions + FileSystemAccess: + - DirectSdmc + + # Process Settings + MemoryType : Application # Application/System/Base + SystemMode : 64MB # 64MB(Default)/96MB/80MB/72MB/32MB + IdealProcessor : 0 + AffinityMask : 1 + Priority : 16 + MaxCpu : 0 # Let system decide + HandleTableSize : 0x200 + DisableDebug : false + EnableForceDebug : false + CanWriteSharedPage : true + CanUsePrivilegedPriority : false + CanUseNonAlphabetAndNumber : true + PermitMainFunctionArgument : true + CanShareDeviceMemory : true + RunnableOnSleep : false + SpecialMemoryArrange : true + + # New3DS Exclusive Process Settings + SystemModeExt : 124MB # Legacy(Default)/124MB/178MB Legacy:Use Old3DS SystemMode + CpuSpeed : 804MHz # 268MHz(Default)/804MHz + EnableL2Cache : true # false(default)/true + CanAccessCore2 : true + + # Virtual Address Mappings + IORegisterMapping: + - 1ff00000-1ff7ffff # DSP memory + MemoryMapping: + - 1f000000-1f5fffff:r # VRAM + + # Accessible SVCs, : + SystemCallAccess: + ArbitrateAddress: 34 + Break: 60 + CancelTimer: 28 + ClearEvent: 25 + ClearTimer: 29 + CloseHandle: 35 + ConnectToPort: 45 + ControlMemory: 1 + CreateAddressArbiter: 33 + CreateEvent: 23 + CreateMemoryBlock: 30 + CreateMutex: 19 + CreateSemaphore: 21 + CreateThread: 8 + CreateTimer: 26 + DuplicateHandle: 39 + ExitProcess: 3 + ExitThread: 9 + GetCurrentProcessorNumber: 17 + GetHandleInfo: 41 + GetProcessId: 53 + GetProcessIdOfThread: 54 + GetProcessIdealProcessor: 6 + GetProcessInfo: 43 + GetResourceLimit: 56 + GetResourceLimitCurrentValues: 58 + GetResourceLimitLimitValues: 57 + GetSystemInfo: 42 + GetSystemTick: 40 + GetThreadContext: 59 + GetThreadId: 55 + GetThreadIdealProcessor: 15 + GetThreadInfo: 44 + GetThreadPriority: 11 + MapMemoryBlock: 31 + OutputDebugString: 61 + QueryMemory: 2 + ReleaseMutex: 20 + ReleaseSemaphore: 22 + SendSyncRequest1: 46 + SendSyncRequest2: 47 + SendSyncRequest3: 48 + SendSyncRequest4: 49 + SendSyncRequest: 50 + SetThreadPriority: 12 + SetTimer: 27 + SignalEvent: 24 + SleepThread: 10 + UnmapMemoryBlock: 32 + WaitSynchronization1: 36 + WaitSynchronizationN: 37 + Backdoor: 123 + + # Service List + # Maximum 34 services (32 if firmware is prior to 9.3.0) + ServiceAccessControl: + - cfg:u + - fs:USER + - gsp::Gpu + - hid:USER + - ndm:u + - pxi:dev + - APT:U + - ac:u + - act:u + - am:net + - boss:U + - cam:u + - cecd:u + - csnd:SND + - frd:u + - http:C + - ir:USER + - ir:u + - ir:rst + - ldr:ro + - mic:u + - news:u + - nfc:u + - nim:aoc + - nwm::UDS + - ptm:u + - qtm:u + - soc:U + - ssl:C + - y2r:u + + +SystemControlInfo: + SaveDataSize: 0KB # It doesn't use any save data. + RemasterVersion: 0 + StackSize: 0x40000 + Dependency: + ac: 0x0004013000002402 + am: 0x0004013000001502 + boss: 0x0004013000003402 + camera: 0x0004013000001602 + cecd: 0x0004013000002602 + cfg: 0x0004013000001702 + codec: 0x0004013000001802 + csnd: 0x0004013000002702 + dlp: 0x0004013000002802 + dsp: 0x0004013000001a02 + friends: 0x0004013000003202 + gpio: 0x0004013000001b02 + gsp: 0x0004013000001c02 + hid: 0x0004013000001d02 + http: 0x0004013000002902 + i2c: 0x0004013000001e02 + ir: 0x0004013000003302 + mcu: 0x0004013000001f02 + mic: 0x0004013000002002 + ndm: 0x0004013000002b02 + news: 0x0004013000003502 + nim: 0x0004013000002c02 + nwm: 0x0004013000002d02 + pdn: 0x0004013000002102 + ps: 0x0004013000003102 + ptm: 0x0004013000002202 + ro: 0x0004013000003702 + socket: 0x0004013000002e02 + spi: 0x0004013000002302 + ssl: 0x0004013000002f02 \ No newline at end of file