From 6c2b184e00d238ecd4f9950f91fe23afb6f4852b Mon Sep 17 00:00:00 2001 From: AzureMarker Date: Mon, 2 Jan 2023 09:11:49 -0800 Subject: [PATCH] Got connection working and packets flowing Need to parse packets now to make sure input signal is getting transferred correctly. --- ctru-rs/examples/ir-user.rs | 226 +++++++++++++++++++++++--------- ctru-rs/src/services/ir_user.rs | 44 ++++--- 2 files changed, 187 insertions(+), 83 deletions(-) diff --git a/ctru-rs/examples/ir-user.rs b/ctru-rs/examples/ir-user.rs index eda0eb9..2c5b31e 100644 --- a/ctru-rs/examples/ir-user.rs +++ b/ctru-rs/examples/ir-user.rs @@ -1,19 +1,23 @@ +use ctru::error::ResultCode; use ctru::prelude::*; -use ctru::services::ir_user::{IrDeviceId, IrUser}; +use ctru::services::ir_user::{IrDeviceId, IrUser, IrUserStatusInfo}; use time::Duration; -use ctru::error::ResultCode; const PACKET_INFO_SIZE: usize = 8; const MAX_PACKET_SIZE: usize = 32; const PACKET_COUNT: usize = 1; const PACKET_BUFFER_SIZE: usize = PACKET_COUNT * (PACKET_INFO_SIZE + MAX_PACKET_SIZE); +const CPP_CONNECTION_POLLING_PERIOD_MS: u8 = 0x08; +const CPP_POLLING_PERIOD_MS: u8 = 0x32; fn main() { ctru::init(); let apt = Apt::init().unwrap(); let hid = Hid::init().unwrap(); let gfx = Gfx::init().unwrap(); - let console = Console::init(gfx.top_screen.borrow_mut()); + let bottom_console = Console::init(gfx.bottom_screen.borrow_mut()); + let top_console = Console::init(gfx.top_screen.borrow_mut()); + let ir_user = IrUser::init( PACKET_BUFFER_SIZE, PACKET_COUNT, @@ -21,87 +25,181 @@ fn main() { PACKET_COUNT, ) .expect("Couldn't initialize ir:USER service"); - let ir_user_connection_status_event = ir_user + + let print_status_info = || { + bottom_console.select(); + bottom_console.clear(); + println!("{:#x?}", ir_user.get_status_info()); + top_console.select(); + }; + + let conn_status_event = ir_user .get_connection_status_event() .expect("Couldn't get ir:USER connection status event"); - ir_user - .require_connection(IrDeviceId::CirclePadPro) - .expect("Couldn't initialize circle pad pro connection"); - let ir_user_recv_event = ir_user + let recv_event = ir_user .get_recv_event() .expect("Couldn't get ir:USER recv event"); - println!("StatusInfo:\n{:#?}", ir_user.get_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"); - - ir_user - .start_polling_input(20) - .expect("Couldn't configure circle pad pro polling interval"); - - while apt.main_loop() { + 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; + + '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(ir_user_recv_event, 0) == 0 }; + let check_ir_packet = unsafe { ctru_sys::svcWaitSynchronization(recv_event, 0) == 0 }; if check_ir_packet { - console.clear(); - - // Move the cursor back to the top of the screen - print!("\x1b[0;0H"); - - println!("StatusInfo:\n{:?}", ir_user.get_status_info()); + print_status_info(); + handle_packet(&ir_user, &top_console, &bottom_console); + } - ir_user.process_shared_memory(|ir_mem| { - println!("\nReceiveBufferInfo:"); - for byte in &ir_mem[0x10..0x20] { - print!("{byte:02x} "); - } + if hid.keys_held().contains(KeyPad::KEY_START) { + break; + } - println!("\nReceiveBuffer:"); - let mut counter = 0; - for byte in &ir_mem[0x20..0x20 + PACKET_BUFFER_SIZE] { - print!("{byte:02x} "); - counter += 1; - if counter % 16 == 0 { - println!() + 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"); + } + // } + // _ => { + 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; + } } } + _ => {} + } - println!("\nSendBufferInfo:"); - for byte in &ir_mem[0x20 + PACKET_BUFFER_SIZE..0x30 + PACKET_BUFFER_SIZE] { - print!("{byte:02x} "); - } + step += 1; + } - println!("\n(skipping send packet buffer)"); - }); + gfx.flush_buffers(); + gfx.swap_buffers(); + gfx.wait_for_vblank(); + } +} - // Done handling the packet, release it - ir_user - .release_received_data(1) - .expect("Failed to release ir:USER packet"); +fn handle_packet(ir_user: &IrUser, top_console: &Console, bottom_console: &Console) { + ir_user.process_shared_memory(|ir_mem| { + bottom_console.select(); + println!("\nReceiveBufferInfo:"); + let mut counter = 0; + for byte in &ir_mem[0x10..0x20] { + print!("{byte:02x} "); + counter += 1; + if counter % 12 == 0 { + println!() + } + } - println!("\x1b[29;16HPress Start to exit"); + println!("\nReceiveBuffer:"); + counter = 0; + for byte in &ir_mem[0x20..0x20 + PACKET_BUFFER_SIZE] { + print!("{byte:02x} "); + counter += 1; + if counter % 12 == 0 { + println!() + } } - if hid.keys_held().intersects(KeyPad::KEY_START) { - break; + println!("\nSendBufferInfo:"); + counter = 0; + for byte in &ir_mem[0x20 + PACKET_BUFFER_SIZE..0x30 + PACKET_BUFFER_SIZE] { + print!("{byte:02x} "); + counter += 1; + if counter % 12 == 0 { + println!() + } } - gfx.flush_buffers(); - gfx.swap_buffers(); - gfx.wait_for_vblank(); + println!("\n(skipping send packet buffer)"); + top_console.select(); + }); + + // Done handling the packet, release it + ir_user + .release_received_data(1) + .expect("Failed to release ir:USER packet"); + + if let Err(e) = ir_user.start_polling_input(CPP_POLLING_PERIOD_MS) { + println!("Error: {e:?}"); } } diff --git a/ctru-rs/src/services/ir_user.rs b/ctru-rs/src/services/ir_user.rs index 212588e..10bbf4c 100644 --- a/ctru-rs/src/services/ir_user.rs +++ b/ctru-rs/src/services/ir_user.rs @@ -22,11 +22,12 @@ struct IrUserState { // shared_memory: Box<[u8]>, } -const INITIALIZE_IRNOP_SHARED_COMMAND_HEADER: u32 = 0x00180182; const REQUIRE_CONNECTION_COMMAND_HEADER: u32 = 0x00060040; -const GET_CONNECTION_STATUS_EVENT_COMMAND_HEADER: u32 = 0x000C0000; +const DISCONNECT_COMMAND_HEADER: u32 = 0x00090000; const GET_RECEIVE_EVENT_COMMAND_HEADER: u32 = 0x000A0000; +const GET_CONNECTION_STATUS_EVENT_COMMAND_HEADER: u32 = 0x000C0000; const SEND_IR_NOP_COMMAND_HEADER: u32 = 0x000D0042; +const INITIALIZE_IRNOP_SHARED_COMMAND_HEADER: u32 = 0x00180182; const RELEASE_RECEIVED_DATA_COMMAND_HEADER: u32 = 0x00190040; impl IrUser { @@ -46,12 +47,6 @@ impl IrUser { println!("Getting shared memory pointer"); let info_sections_size = 0x30; - // let packet_count = 3; - // let max_packet_size = 32; - // let packet_info_size = 8; - // let recv_buffer_len = recv_packet_count * (packet_info_size + max_packet_size); - // let send_buffer_len = send_packet_count * (packet_info_size + max_packet_size); - let minimum_shared_memory_len = info_sections_size + recv_buffer_size + send_buffer_size; let shared_memory_len = if minimum_shared_memory_len % 0x1000 != 0 { (minimum_shared_memory_len / 0x1000) * 0x1000 + 0x1000 @@ -150,6 +145,17 @@ impl IrUser { Ok(()) } + pub fn disconnect(&self) -> crate::Result<()> { + println!("Disconnect called"); + self.send_service_request( + vec![DISCONNECT_COMMAND_HEADER], + 2, + )?; + + println!("Disconnect succeeded"); + Ok(()) + } + pub fn get_connection_status_event(&self) -> crate::Result { println!("GetConnectionStatusEvent called"); let response = self.send_service_request(vec![GET_CONNECTION_STATUS_EVENT_COMMAND_HEADER], 4)?; @@ -170,7 +176,7 @@ impl IrUser { pub fn start_polling_input(&self, period_ms: u8) -> crate::Result<()> { println!("SendIrnop (start_polling_input) called"); - let ir_request: [u8; 3] = [1, period_ms, 0]; + let ir_request: [u8; 3] = [1, period_ms, (period_ms + 2) << 2]; self.send_service_request( vec![ SEND_IR_NOP_COMMAND_HEADER, @@ -305,14 +311,14 @@ impl IrDeviceId { #[derive(Debug)] pub struct IrUserStatusInfo { - recv_err_result: ctru_sys::Result, - send_err_result: ctru_sys::Result, - connection_status: u8, - trying_to_connect_status: u8, - connection_role: u8, - machine_id: u8, - unknown_field_1: u8, - network_id: u8, - unknown_field_2: u8, - unknown_field_3: u8, + pub recv_err_result: ctru_sys::Result, + pub send_err_result: ctru_sys::Result, + pub connection_status: u8, + pub trying_to_connect_status: u8, + pub connection_role: u8, + pub machine_id: u8, + pub unknown_field_1: u8, + pub network_id: u8, + pub unknown_field_2: u8, + pub unknown_field_3: u8, }