AzureMarker
1 year ago
5 changed files with 124 additions and 131 deletions
@ -1,37 +0,0 @@
@@ -1,37 +0,0 @@
|
||||
//! Service API
|
||||
//!
|
||||
//! Not all APIs are wrapped in this module, since a lot are fundamentally unsafe.
|
||||
//! Most APIs should be used directly from `ctru-sys`.
|
||||
|
||||
use crate::error::ResultCode; |
||||
use ctru_sys::Handle; |
||||
use std::time::Duration; |
||||
|
||||
/// Extension trait for [Handle]
|
||||
pub trait HandleExt { |
||||
/// Wait for an event to fire. If the timeout is reached, an error is returned. You can use
|
||||
/// [`Error::is_timeout`] to check if the error is due to a timeout.
|
||||
fn wait_for_event(self, timeout: Duration) -> crate::Result<()>; |
||||
} |
||||
|
||||
impl HandleExt for Handle { |
||||
fn wait_for_event(self, timeout: Duration) -> crate::Result<()> { |
||||
let timeout = i64::try_from(timeout.as_nanos()).map_err(|e| { |
||||
crate::Error::Other(format!( |
||||
"Failed to convert timeout to 64-bit nanoseconds: {}", |
||||
e |
||||
)) |
||||
})?; |
||||
unsafe { |
||||
ResultCode(ctru_sys::svcWaitSynchronization(self, timeout))?; |
||||
} |
||||
Ok(()) |
||||
} |
||||
} |
||||
|
||||
/// Creates a command header to be used for IPC. This is a const fn version of [`ctru_sys::IPC_MakeHeader`].
|
||||
pub const fn make_ipc_header(command_id: u16, normal_params: u8, translate_params: u8) -> u32 { |
||||
((command_id as u32) << 16) |
||||
| (((normal_params as u32) & 0x3F) << 6) |
||||
| ((translate_params as u32) & 0x3F) |
||||
} |
@ -0,0 +1,76 @@
@@ -0,0 +1,76 @@
|
||||
//! Syscall APIs
|
||||
//!
|
||||
//! Not all APIs are wrapped in this module, since a lot are fundamentally unsafe.
|
||||
//! Most APIs should be used directly from `ctru-sys`.
|
||||
|
||||
use crate::error::ResultCode; |
||||
use ctru_sys::Handle; |
||||
use std::time::Duration; |
||||
|
||||
/// Extension trait for [Handle]
|
||||
pub trait HandleExt { |
||||
/// Wait for an event to fire. If the timeout is reached, an error is returned. You can use
|
||||
/// [`Error::is_timeout`] to check if the error is due to a timeout.
|
||||
fn wait_for_event(self, timeout: Duration) -> crate::Result<()>; |
||||
|
||||
/// Send a service request to the handle.
|
||||
/// The request vector must contain the command header and any parameters.
|
||||
/// The request vector is overwritten with the response and returned.
|
||||
/// The error in the response is checked and returned as a `Result::Err` if the operation failed.
|
||||
///
|
||||
/// # Safety
|
||||
/// This function is unsafe because it directly accesses the thread command buffer.
|
||||
/// If the request vector or the expected response length is incorrect, or the handle is not a service that accepts
|
||||
/// requests, the function may cause undefined behavior.
|
||||
unsafe fn send_service_request( |
||||
self, |
||||
request: Vec<u32>, |
||||
expected_response_len: usize, |
||||
) -> crate::Result<Vec<u32>>; |
||||
} |
||||
|
||||
impl HandleExt for Handle { |
||||
fn wait_for_event(self, timeout: Duration) -> crate::Result<()> { |
||||
let timeout = i64::try_from(timeout.as_nanos()).map_err(|e| { |
||||
crate::Error::Other(format!( |
||||
"Failed to convert timeout to 64-bit nanoseconds: {}", |
||||
e |
||||
)) |
||||
})?; |
||||
unsafe { |
||||
ResultCode(ctru_sys::svcWaitSynchronization(self, timeout))?; |
||||
} |
||||
Ok(()) |
||||
} |
||||
|
||||
unsafe fn send_service_request( |
||||
self, |
||||
mut request: Vec<u32>, |
||||
expected_response_len: usize, |
||||
) -> crate::Result<Vec<u32>> { |
||||
// Copy over the request
|
||||
let cmd_buffer_ptr = unsafe { ctru_sys::getThreadCommandBuffer() }; |
||||
std::ptr::copy_nonoverlapping(request.as_ptr(), cmd_buffer_ptr, request.len()); |
||||
|
||||
// Send the request
|
||||
ResultCode(ctru_sys::svcSendSyncRequest(self))?; |
||||
|
||||
// Handle the result returned by the service
|
||||
let result = unsafe { std::ptr::read(cmd_buffer_ptr.add(1)) }; |
||||
ResultCode(result as ctru_sys::Result)?; |
||||
|
||||
// Copy back the response
|
||||
request.clear(); |
||||
request.resize(expected_response_len, 0); |
||||
std::ptr::copy_nonoverlapping(cmd_buffer_ptr, request.as_mut_ptr(), expected_response_len); |
||||
|
||||
Ok(request) |
||||
} |
||||
} |
||||
|
||||
/// Creates a command header to be used for IPC. This is a const fn version of [`ctru_sys::IPC_MakeHeader`].
|
||||
pub const fn make_ipc_header(command_id: u16, normal_params: u8, translate_params: u8) -> u32 { |
||||
((command_id as u32) << 16) |
||||
| (((normal_params as u32) & 0x3F) << 6) |
||||
| ((translate_params as u32) & 0x3F) |
||||
} |
Loading…
Reference in new issue