From d798f56ad91083fe3df72fa5a7086fe50c3b2eac Mon Sep 17 00:00:00 2001 From: AzureMarker Date: Mon, 2 Jan 2023 19:34:32 -0800 Subject: [PATCH] Clean up some of the code and warnings --- ctru-rs/examples/ir-user.rs | 188 ++++++++++++++------------------ ctru-rs/src/error.rs | 7 ++ ctru-rs/src/services/ir_user.rs | 16 ++- 3 files changed, 100 insertions(+), 111 deletions(-) diff --git a/ctru-rs/examples/ir-user.rs b/ctru-rs/examples/ir-user.rs index 76f7c1e..0cbaf7d 100644 --- a/ctru-rs/examples/ir-user.rs +++ b/ctru-rs/examples/ir-user.rs @@ -1,8 +1,7 @@ -use ctru::error::ResultCode; use ctru::prelude::*; -use ctru::services::ir_user::{CirclePadProInputResponse, IrDeviceId, IrUser, IrUserStatusInfo}; +use ctru::services::ir_user::{CirclePadProInputResponse, IrDeviceId, IrUser}; use std::io::Write; -use time::Duration; +use std::time::Duration; const PACKET_INFO_SIZE: usize = 8; const MAX_PACKET_SIZE: usize = 32; @@ -42,115 +41,84 @@ fn main() { .expect("Couldn't get ir:USER recv event"); print_status_info(); - // // Wait for the connection to establish - // (|| unsafe { - // ResultCode(ctru_sys::svcWaitSynchronization( - // ir_user_connection_status_event, - // Duration::seconds(10).whole_nanoseconds() as i64, - // ))?; - // - // println!("Finished waiting on connection status event"); - // println!("StatusInfo:\n{:#?}", ir_user.get_status_info()); - // - // Ok(()) - // })().expect("Failed to connect to circle pad pro"); - - let mut step = 0; - + let mut is_connected = false; 'main_loop: while apt.main_loop() { hid.scan_input(); - // Check if we've received a packet from the circle pad pro - let check_ir_packet = unsafe { ctru_sys::svcWaitSynchronization(recv_event, 0) == 0 }; + if hid.keys_held().contains(KeyPad::KEY_START) { + break; + } - if check_ir_packet { + // Check if we've received a packet from the circle pad pro + let packet_received = IrUser::wait_for_event(recv_event, Duration::ZERO).is_ok(); + if packet_received { handle_packet(&ir_user, &top_console, &bottom_console); } - if hid.keys_held().contains(KeyPad::KEY_START) { - break; - } + if hid.keys_down().contains(KeyPad::KEY_A) && !is_connected { + // Connection loop + loop { + hid.scan_input(); + if hid.keys_held().contains(KeyPad::KEY_START) { + break 'main_loop; + } - if hid.keys_down().contains(KeyPad::KEY_A) { - match step { - 0 => { - loop { - hid.scan_input(); - if hid.keys_held().contains(KeyPad::KEY_START) { - break 'main_loop; - } - - ir_user - .require_connection(IrDeviceId::CirclePadPro) - .expect("Couldn't initialize circle pad pro connection"); - - // Wait for the connection to establish - (|| unsafe { - ResultCode(ctru_sys::svcWaitSynchronization( - conn_status_event, - Duration::milliseconds(10).whole_nanoseconds() as i64, - ))?; - - Ok(()) - })() - .expect("Failed to synchronize on connection status event"); - - print_status_info(); - let status_info = ir_user.get_status_info(); - if status_info.connection_status == 2 { - println!("Connected!"); - break; - } - - ir_user - .disconnect() - .expect("Failed to disconnect circle pad pro connection"); - - // Wait for the disconnect to go through - (|| unsafe { - ResultCode(ctru_sys::svcWaitSynchronization( - conn_status_event, - Duration::milliseconds(10).whole_nanoseconds() as i64, - ))?; - - Ok(()) - })() - .expect("Failed to synchronize on connection status event"); + ir_user + .require_connection(IrDeviceId::CirclePadPro) + .expect("Couldn't initialize circle pad pro connection"); + + // Wait for the connection to establish + if let Err(e) = IrUser::wait_for_event(conn_status_event, Duration::from_millis(100)) + { + if !e.is_timeout() { + panic!("Couldn't initialize circle pad pro connection: {e}"); } - // } - // _ => { - loop { - hid.scan_input(); - if hid.keys_held().contains(KeyPad::KEY_START) { - break 'main_loop; - } - - if let Err(e) = - ir_user.start_polling_input(CPP_CONNECTION_POLLING_PERIOD_MS) - { - println!("Error: {e:?}"); - } - print_status_info(); - - let check_ir_packet = unsafe { - ctru_sys::svcWaitSynchronization( - recv_event, - Duration::milliseconds(10).whole_nanoseconds() as i64, - ) == 0 - }; - print_status_info(); - - if check_ir_packet { - println!("Got packet from CPP"); - handle_packet(&ir_user, &top_console, &bottom_console); - break; - } + } + + print_status_info(); + let status_info = ir_user.get_status_info(); + if status_info.connection_status == 2 { + println!("Connected!"); + break; + } + + ir_user + .disconnect() + .expect("Failed to disconnect circle pad pro connection"); + + // Wait for the disconnect to go through + if let Err(e) = IrUser::wait_for_event(conn_status_event, Duration::from_millis(100)) + { + if !e.is_timeout() { + panic!("Couldn't initialize circle pad pro connection: {e}"); } } - _ => {} } - step += 1; + // Sending first packet retry loop + loop { + hid.scan_input(); + if hid.keys_held().contains(KeyPad::KEY_START) { + break 'main_loop; + } + + if let Err(e) = ir_user.start_polling_input(CPP_CONNECTION_POLLING_PERIOD_MS) { + println!("Error: {e:?}"); + } + print_status_info(); + + let recv_event_result = + IrUser::wait_for_event(recv_event, Duration::from_millis(100)); + print_status_info(); + + if recv_event_result.is_ok() { + println!("Got packet from CPP"); + handle_packet(&ir_user, &top_console, &bottom_console); + break; + } + } + + is_connected = true; } gfx.flush_buffers(); @@ -163,6 +131,8 @@ fn handle_packet(ir_user: &IrUser, top_console: &Console, bottom_console: &Conso // Use a buffer to avoid flickering the screen (write all output at once) let mut output_buffer = Vec::with_capacity(0x1000); + writeln!(&mut output_buffer, "{:x?}", ir_user.get_status_info()).unwrap(); + ir_user.process_shared_memory(|ir_mem| { writeln!(&mut output_buffer, "ReceiveBufferInfo:").unwrap(); let mut counter = 0; @@ -170,7 +140,7 @@ fn handle_packet(ir_user: &IrUser, top_console: &Console, bottom_console: &Conso write!(&mut output_buffer, "{byte:02x} ").unwrap(); counter += 1; if counter % 12 == 0 { - writeln!(&mut output_buffer, "").unwrap(); + writeln!(&mut output_buffer).unwrap(); } } @@ -180,28 +150,27 @@ fn handle_packet(ir_user: &IrUser, top_console: &Console, bottom_console: &Conso write!(&mut output_buffer, "{byte:02x} ").unwrap(); counter += 1; if counter % 12 == 0 { - writeln!(&mut output_buffer, "").unwrap(); + writeln!(&mut output_buffer).unwrap(); } } - writeln!(&mut output_buffer, "").unwrap(); + writeln!(&mut output_buffer).unwrap(); }); let mut packets = ir_user.get_packets(); let packet_count = packets.len(); writeln!(&mut output_buffer, "Packet count: {packet_count}").unwrap(); let last_packet = packets.pop().unwrap(); - writeln!(&mut output_buffer, "Last packet:\n{last_packet:02x?}").unwrap(); - - bottom_console.select(); - bottom_console.clear(); - std::io::stdout().write_all(&output_buffer).unwrap(); + writeln!(&mut output_buffer, "{last_packet:02x?}").unwrap(); - // Use println in case this fails let cpp_response = CirclePadProInputResponse::try_from(last_packet) .expect("Failed to parse CPP response from IR packet"); - println!("CPP Response:\n{cpp_response:#02x?}"); + writeln!(&mut output_buffer, "{cpp_response:#02x?}").unwrap(); + // Write output to bottom screen + bottom_console.select(); + bottom_console.clear(); + std::io::stdout().write_all(&output_buffer).unwrap(); top_console.select(); // Done handling the packet, release it @@ -209,6 +178,7 @@ fn handle_packet(ir_user: &IrUser, top_console: &Console, bottom_console: &Conso .release_received_data(packet_count as u32) .expect("Failed to release ir:USER packet"); + // Remind the CPP that we're still listening if let Err(e) = ir_user.start_polling_input(CPP_POLLING_PERIOD_MS) { println!("Error: {e:?}"); } diff --git a/ctru-rs/src/error.rs b/ctru-rs/src/error.rs index 44c9d41..af377c9 100644 --- a/ctru-rs/src/error.rs +++ b/ctru-rs/src/error.rs @@ -69,6 +69,13 @@ impl Error { // Copy out of the error string, since it may be changed by other libc calls later Self::Libc(error_str.to_string_lossy().into()) } + + pub fn is_timeout(&self) -> bool { + match *self { + Error::Os(code) => R_DESCRIPTION(code) == ctru_sys::RD_TIMEOUT as ctru_sys::Result, + _ => false, + } + } } impl From for Error { diff --git a/ctru-rs/src/services/ir_user.rs b/ctru-rs/src/services/ir_user.rs index 410d433..949fbbf 100644 --- a/ctru-rs/src/services/ir_user.rs +++ b/ctru-rs/src/services/ir_user.rs @@ -6,6 +6,7 @@ use std::cmp::max; use std::ffi::CString; use std::ptr::{slice_from_raw_parts, slice_from_raw_parts_mut}; use std::sync::Mutex; +use std::time::Duration; static IR_USER_ACTIVE: Mutex = Mutex::new(0); static IR_USER_STATE: Mutex> = Mutex::new(None); @@ -182,6 +183,16 @@ impl IrUser { Ok(recv_event) } + pub fn wait_for_event(event: Handle, timeout: Duration) -> crate::Result<()> { + unsafe { + ResultCode(ctru_sys::svcWaitSynchronization( + event, + timeout.as_nanos() as i64, + ))?; + } + Ok(()) + } + pub fn start_polling_input(&self, period_ms: u8) -> crate::Result<()> { let ir_request: [u8; 3] = [1, period_ms, (period_ms + 2) << 2]; self.send_service_request( @@ -280,7 +291,7 @@ impl IrUser { packet_info[7], ]) 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]; @@ -444,7 +455,8 @@ impl TryFrom for CirclePadProInputResponse { let response_id = packet.payload[0]; let c_stick_x = packet.payload[1] as u16 + (((packet.payload[2] & 0x0F) as u16) << 8); - let c_stick_y = (((packet.payload[2] & 0xF0) as u16) >> 4) + ((packet.payload[3] as u16) << 4); + let c_stick_y = + (((packet.payload[2] & 0xF0) as u16) >> 4) + ((packet.payload[3] as u16) << 4); let battery_level = packet.payload[4] & 0x1F; let zl_pressed = packet.payload[4] & 0x20 == 0; let zr_pressed = packet.payload[4] & 0x40 == 0;