Browse Source

Implement ir:USER service shutdown, and do more code cleanup

pull/129/head
AzureMarker 2 years ago committed by Mark Drobnak
parent
commit
5a357dc844
No known key found for this signature in database
GPG Key ID: 47A133F3BF9D03D3
  1. 6
      ctru-rs/examples/ir-user.rs
  2. 96
      ctru-rs/src/services/ir_user.rs

6
ctru-rs/examples/ir-user.rs

@ -68,7 +68,8 @@ fn main() {
.expect("Couldn't initialize circle pad pro connection"); .expect("Couldn't initialize circle pad pro connection");
// Wait for the connection to establish // Wait for the connection to establish
if let Err(e) = IrUser::wait_for_event(conn_status_event, Duration::from_millis(100)) if let Err(e) =
IrUser::wait_for_event(conn_status_event, Duration::from_millis(100))
{ {
if !e.is_timeout() { if !e.is_timeout() {
panic!("Couldn't initialize circle pad pro connection: {e}"); panic!("Couldn't initialize circle pad pro connection: {e}");
@ -87,7 +88,8 @@ fn main() {
.expect("Failed to disconnect circle pad pro connection"); .expect("Failed to disconnect circle pad pro connection");
// Wait for the disconnect to go through // Wait for the disconnect to go through
if let Err(e) = IrUser::wait_for_event(conn_status_event, Duration::from_millis(100)) if let Err(e) =
IrUser::wait_for_event(conn_status_event, Duration::from_millis(100))
{ {
if !e.is_timeout() { if !e.is_timeout() {
panic!("Couldn't initialize circle pad pro connection: {e}"); panic!("Couldn't initialize circle pad pro connection: {e}");

96
ctru-rs/src/services/ir_user.rs

@ -20,9 +20,9 @@ struct IrUserState {
service_handle: Handle, service_handle: Handle,
shared_memory_handle: Handle, shared_memory_handle: Handle,
shared_memory: &'static [u8], shared_memory: &'static [u8],
shared_memory_layout: Layout,
recv_buffer_size: usize, recv_buffer_size: usize,
recv_packet_count: usize, recv_packet_count: usize,
// shared_memory: Box<[u8]>,
} }
const REQUIRE_CONNECTION_COMMAND_HEADER: u32 = 0x00060040; const REQUIRE_CONNECTION_COMMAND_HEADER: u32 = 0x00060040;
@ -42,10 +42,9 @@ impl IrUser {
) -> crate::Result<Self> { ) -> crate::Result<Self> {
let service_reference = ServiceReference::new( let service_reference = ServiceReference::new(
&IR_USER_ACTIVE, &IR_USER_ACTIVE,
true, false,
|| unsafe { || unsafe {
println!("Starting IrUser"); // Get the ir:USER service handle
println!("Getting ir:USER service handle");
let mut service_handle = Handle::default(); let mut service_handle = Handle::default();
let service_name = CString::new("ir:USER").unwrap(); let service_name = CString::new("ir:USER").unwrap();
ResultCode(ctru_sys::srvGetServiceHandle( ResultCode(ctru_sys::srvGetServiceHandle(
@ -53,7 +52,8 @@ impl IrUser {
service_name.as_ptr(), service_name.as_ptr(),
))?; ))?;
println!("Getting shared memory pointer"); // Calculate the shared memory size.
// Shared memory length must be page aligned.
let info_sections_size = 0x30; let info_sections_size = 0x30;
let minimum_shared_memory_len = let minimum_shared_memory_len =
info_sections_size + recv_buffer_size + send_buffer_size; info_sections_size + recv_buffer_size + send_buffer_size;
@ -63,21 +63,14 @@ impl IrUser {
(minimum_shared_memory_len / 0x1000) * 0x1000 (minimum_shared_memory_len / 0x1000) * 0x1000
}; };
assert_eq!(shared_memory_len % 0x1000, 0); assert_eq!(shared_memory_len % 0x1000, 0);
// let shared_memory_len = info_sections_size + recv_buffer_size + send_buffer_size;
println!("Shared memory size: {shared_memory_len:#x}");
// let shared_memory_len = info_sections_size + packet_count * (packet_info_size + max_packet_size); // Allocate the shared memory
// let shared_memory = Box::new([0; 0x1000]);
// let shared_memory_ptr = ctru_sys::mappableAlloc(shared_memory_len) as *const u8;
let shared_memory_layout = let shared_memory_layout =
Layout::from_size_align(shared_memory_len, 0x1000).unwrap(); Layout::from_size_align(shared_memory_len, 0x1000).unwrap();
let shared_memory_ptr = std::alloc::alloc_zeroed(shared_memory_layout); let shared_memory_ptr = std::alloc::alloc_zeroed(shared_memory_layout);
println!( let shared_memory = &*slice_from_raw_parts(shared_memory_ptr, shared_memory_len);
"Using shared memory address: {:#08x}",
shared_memory_ptr as usize
);
println!("Marking memory block as shared memory"); // Mark the memory as shared
let mut shared_memory_handle = Handle::default(); let mut shared_memory_handle = Handle::default();
ResultCode(ctru_sys::svcCreateMemoryBlock( ResultCode(ctru_sys::svcCreateMemoryBlock(
&mut shared_memory_handle, &mut shared_memory_handle,
@ -86,9 +79,8 @@ impl IrUser {
MEMPERM_READ, MEMPERM_READ,
MEMPERM_READWRITE, MEMPERM_READWRITE,
))?; ))?;
let shared_memory = &*slice_from_raw_parts(shared_memory_ptr, shared_memory_len);
println!("Initializing ir:USER service"); // Initialize the ir:USER service with the shared memory
initialize_irnop_shared(InitializeIrnopSharedParams { initialize_irnop_shared(InitializeIrnopSharedParams {
ir_user_handle: service_handle, ir_user_handle: service_handle,
shared_memory_len: shared_memory_len as u32, shared_memory_len: shared_memory_len as u32,
@ -100,43 +92,38 @@ impl IrUser {
shared_memory_handle, shared_memory_handle,
})?; })?;
println!("Setting IrUserState in static"); // Set up our service state
let user_state = IrUserState { let user_state = IrUserState {
service_handle, service_handle,
shared_memory_handle, shared_memory_handle,
shared_memory, shared_memory,
shared_memory_layout,
recv_buffer_size, recv_buffer_size,
recv_packet_count, recv_packet_count,
}; };
*IR_USER_STATE.lock().unwrap() = Some(user_state); *IR_USER_STATE.lock().unwrap() = Some(user_state);
println!("Done starting IrUser");
Ok(()) Ok(())
}, },
|| { || {
println!("Close called for IrUser"); // Remove our service state from the global location
let mut shared_mem_guard = IR_USER_STATE.lock().unwrap(); let mut shared_mem_guard = IR_USER_STATE.lock().unwrap();
let shared_mem = shared_mem_guard let shared_mem = shared_mem_guard.take().unwrap();
.take()
.expect("ir:USER shared memory mutex shouldn't be empty"); (move || unsafe {
// (|| unsafe { // Close service and memory handles
// // println!("Unmapping the ir:USER shared memory"); ResultCode(ctru_sys::svcCloseHandle(shared_mem.service_handle))?;
// // ResultCode(ctru_sys::svcUnmapMemoryBlock( ResultCode(ctru_sys::svcCloseHandle(shared_mem.shared_memory_handle))?;
// // shared_mem.shared_memory_handle,
// // shared_mem.shared_memory.as_ptr() as u32, // Free shared memory
// // ))?; std::alloc::dealloc(
// shared_mem.shared_memory.as_ptr() as *mut u8,
// println!("Closing memory and service handles"); shared_mem.shared_memory_layout,
// // ResultCode(ctru_sys::svcCloseHandle(shared_mem.shared_memory_handle))?; );
// ResultCode(ctru_sys::svcCloseHandle(shared_mem.service_handle))?;
// Ok(())
// // println!("Freeing shared memory"); })()
// // ctru_sys::mappableFree(shared_mem.shared_memory.as_ptr() as *mut libc::c_void); .unwrap();
//
// Ok(())
// })()
// .unwrap();
println!("Done closing IrUser");
}, },
)?; )?;
@ -146,40 +133,30 @@ impl IrUser {
} }
pub fn require_connection(&self, device_id: IrDeviceId) -> crate::Result<()> { pub fn require_connection(&self, device_id: IrDeviceId) -> crate::Result<()> {
println!("RequireConnection called");
self.send_service_request( self.send_service_request(
vec![REQUIRE_CONNECTION_COMMAND_HEADER, device_id.get_id()], vec![REQUIRE_CONNECTION_COMMAND_HEADER, device_id.get_id()],
2, 2,
)?; )?;
println!("RequireConnection succeeded");
Ok(()) Ok(())
} }
pub fn disconnect(&self) -> crate::Result<()> { pub fn disconnect(&self) -> crate::Result<()> {
println!("Disconnect called");
self.send_service_request(vec![DISCONNECT_COMMAND_HEADER], 2)?; self.send_service_request(vec![DISCONNECT_COMMAND_HEADER], 2)?;
println!("Disconnect succeeded");
Ok(()) Ok(())
} }
pub fn get_connection_status_event(&self) -> crate::Result<Handle> { pub fn get_connection_status_event(&self) -> crate::Result<Handle> {
println!("GetConnectionStatusEvent called");
let response = let response =
self.send_service_request(vec![GET_CONNECTION_STATUS_EVENT_COMMAND_HEADER], 4)?; self.send_service_request(vec![GET_CONNECTION_STATUS_EVENT_COMMAND_HEADER], 4)?;
let status_event = response[3] as Handle; let status_event = response[3] as Handle;
println!("GetConnectionStatusEvent succeeded");
Ok(status_event) Ok(status_event)
} }
pub fn get_recv_event(&self) -> crate::Result<Handle> { pub fn get_recv_event(&self) -> crate::Result<Handle> {
println!("GetReceiveEvent called");
let response = self.send_service_request(vec![GET_RECEIVE_EVENT_COMMAND_HEADER], 4)?; let response = self.send_service_request(vec![GET_RECEIVE_EVENT_COMMAND_HEADER], 4)?;
let recv_event = response[3] as Handle; let recv_event = response[3] as Handle;
println!("GetReceiveEvent succeeded");
Ok(recv_event) Ok(recv_event)
} }
@ -259,12 +236,6 @@ impl IrUser {
shared_mem[0x12], shared_mem[0x12],
shared_mem[0x13], shared_mem[0x13],
]); ]);
// let end_index = u32::from_ne_bytes([
// shared_mem[0x14],
// shared_mem[0x15],
// shared_mem[0x16],
// shared_mem[0x17],
// ]);
let valid_packet_count = u32::from_ne_bytes([ let valid_packet_count = u32::from_ne_bytes([
shared_mem[0x18], shared_mem[0x18],
shared_mem[0x19], shared_mem[0x19],
@ -292,14 +263,10 @@ impl IrUser {
]) as usize; ]) as usize;
let packet_info_section_size = user_state.recv_packet_count * 8; let packet_info_section_size = user_state.recv_packet_count * 8;
// let data_start_offset = 0x20 + packet_info_section_size + offset_to_data_buffer;
// let packet_data_offset = &shared_mem
// [data_start_offset..data_start_offset + data_length];
let packet_data = |idx| -> u8 { let packet_data = |idx| -> u8 {
shared_mem[0x20 let offset = 0x20 + packet_info_section_size + (offset_to_data_buffer + idx);
+ packet_info_section_size let data_buffer_size = (user_state.recv_buffer_size - packet_info_section_size);
+ (offset_to_data_buffer + idx) shared_mem[offset % data_buffer_size]
% (user_state.recv_buffer_size - packet_info_section_size)]
}; };
let (payload_length, payload_offset) = if packet_data(2) & 0x40 != 0 { let (payload_length, payload_offset) = if packet_data(2) & 0x40 != 0 {
@ -336,6 +303,7 @@ impl IrUser {
let mut shared_mem_guard = IR_USER_STATE.lock().unwrap(); let mut shared_mem_guard = IR_USER_STATE.lock().unwrap();
let shared_mem = shared_mem_guard.as_mut().unwrap(); let shared_mem = shared_mem_guard.as_mut().unwrap();
// Set up the request
let cmd_buffer = unsafe { let cmd_buffer = unsafe {
&mut *(slice_from_raw_parts_mut( &mut *(slice_from_raw_parts_mut(
ctru_sys::getThreadCommandBuffer(), ctru_sys::getThreadCommandBuffer(),

Loading…
Cancel
Save