From 39b6bc92b5b18278ce000b5e14a0005735068227 Mon Sep 17 00:00:00 2001 From: AzureMarker Date: Mon, 2 Jan 2023 20:37:38 -0800 Subject: [PATCH] Tidy up the ir:USER code/example and fix a bug in the service code --- ctru-rs/examples/ir-user.rs | 64 +++++++++++++++++---------------- ctru-rs/src/services/ir_user.rs | 24 ++++++++----- 2 files changed, 49 insertions(+), 39 deletions(-) diff --git a/ctru-rs/examples/ir-user.rs b/ctru-rs/examples/ir-user.rs index c467e5e..d0c1abd 100644 --- a/ctru-rs/examples/ir-user.rs +++ b/ctru-rs/examples/ir-user.rs @@ -15,9 +15,12 @@ fn main() { let apt = Apt::init().unwrap(); let hid = Hid::init().unwrap(); let gfx = Gfx::init().unwrap(); - let bottom_console = Console::init(gfx.bottom_screen.borrow_mut()); let top_console = Console::init(gfx.top_screen.borrow_mut()); + let bottom_console = Console::init(gfx.bottom_screen.borrow_mut()); + + println!("Welcome to the ir:USER / Circle Pad Pro Demo"); + println!("Starting up ir:USER service"); let ir_user = IrUser::init( PACKET_BUFFER_SIZE, PACKET_COUNT, @@ -25,12 +28,13 @@ fn main() { PACKET_COUNT, ) .expect("Couldn't initialize ir:USER service"); + println!("ir:USER service initialized\nPress A to connect to the CPP"); let print_status_info = || { - bottom_console.select(); - bottom_console.clear(); - println!("{:#x?}", ir_user.get_status_info()); top_console.select(); + top_console.clear(); + println!("{:#x?}", ir_user.get_status_info()); + bottom_console.select(); }; let conn_status_event = ir_user @@ -56,6 +60,8 @@ fn main() { } if hid.keys_down().contains(KeyPad::KEY_A) && !is_connected { + println!("Attempting to connect to the CPP"); + // Connection loop loop { hid.scan_input(); @@ -114,7 +120,7 @@ fn main() { print_status_info(); if recv_event_result.is_ok() { - println!("Got packet from CPP"); + println!("Got first packet from CPP"); handle_packet(&ir_user, &top_console, &bottom_console); break; } @@ -136,44 +142,29 @@ fn handle_packet(ir_user: &IrUser, top_console: &Console, bottom_console: &Conso 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; - for byte in &ir_mem[0x10..0x20] { - write!(&mut output_buffer, "{byte:02x} ").unwrap(); - counter += 1; - if counter % 12 == 0 { - writeln!(&mut output_buffer).unwrap(); - } - } + writeln!(&mut output_buffer, "\nReceiveBufferInfo:").unwrap(); + write_buffer_as_hex(&ir_mem[0x10..0x20], &mut output_buffer); writeln!(&mut output_buffer, "\nReceiveBuffer:").unwrap(); - counter = 0; - for byte in &ir_mem[0x20..0x20 + PACKET_BUFFER_SIZE] { - write!(&mut output_buffer, "{byte:02x} ").unwrap(); - counter += 1; - if counter % 12 == 0 { - writeln!(&mut output_buffer).unwrap(); - } - } - + write_buffer_as_hex(&ir_mem[0x20..0x20 + PACKET_BUFFER_SIZE], &mut output_buffer); writeln!(&mut output_buffer).unwrap(); }); - let mut packets = ir_user.get_packets(); + let 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, "\nPacket count: {packet_count}").unwrap(); + let last_packet = packets.last().unwrap(); writeln!(&mut output_buffer, "{last_packet:02x?}").unwrap(); let cpp_response = CirclePadProInputResponse::try_from(last_packet) .expect("Failed to parse CPP response from IR packet"); - writeln!(&mut output_buffer, "{cpp_response:#02x?}").unwrap(); + writeln!(&mut output_buffer, "\n{cpp_response:#02x?}").unwrap(); - // Write output to bottom screen - bottom_console.select(); - bottom_console.clear(); - std::io::stdout().write_all(&output_buffer).unwrap(); + // Write output to top screen top_console.select(); + top_console.clear(); + std::io::stdout().write_all(&output_buffer).unwrap(); + bottom_console.select(); // Done handling the packet, release it ir_user @@ -185,3 +176,14 @@ fn handle_packet(ir_user: &IrUser, top_console: &Console, bottom_console: &Conso println!("Error: {e:?}"); } } + +fn write_buffer_as_hex(buffer: &[u8], output: &mut Vec) { + let mut counter = 0; + for byte in buffer { + write!(output, "{byte:02x} ").unwrap(); + counter += 1; + if counter % 16 == 0 { + writeln!(output).unwrap(); + } + } +} diff --git a/ctru-rs/src/services/ir_user.rs b/ctru-rs/src/services/ir_user.rs index eacd8a7..a171812 100644 --- a/ctru-rs/src/services/ir_user.rs +++ b/ctru-rs/src/services/ir_user.rs @@ -11,7 +11,6 @@ use std::time::Duration; static IR_USER_ACTIVE: Mutex = Mutex::new(0); static IR_USER_STATE: Mutex> = Mutex::new(None); -#[non_exhaustive] pub struct IrUser { _service_reference: ServiceReference, } @@ -264,9 +263,10 @@ impl IrUser { let packet_info_section_size = user_state.recv_packet_count * 8; let packet_data = |idx| -> u8 { - let offset = 0x20 + packet_info_section_size + (offset_to_data_buffer + idx); - let data_buffer_size = (user_state.recv_buffer_size - packet_info_section_size); - shared_mem[offset % data_buffer_size] + let header_size = 0x20 + packet_info_section_size; + let data_buffer_offset = offset_to_data_buffer + idx; + let data_buffer_size = user_state.recv_buffer_size - packet_info_section_size; + shared_mem[header_size + data_buffer_offset % data_buffer_size] }; let (payload_length, payload_offset) = if packet_data(2) & 0x40 != 0 { @@ -282,6 +282,9 @@ impl IrUser { assert_eq!(data_length, payload_offset + payload_length + 1); + let magic_number = packet_data(0); + assert_eq!(magic_number, 0xA5); + IrUserPacket { magic_number: packet_data(0), destination_network_id: packet_data(1), @@ -400,7 +403,6 @@ pub struct IrUserPacket { #[derive(Debug)] pub struct CirclePadProInputResponse { - pub response_id: u8, pub c_stick_x: u16, pub c_stick_y: u16, pub battery_level: u8, @@ -410,10 +412,10 @@ pub struct CirclePadProInputResponse { pub unknown_field: u8, } -impl TryFrom for CirclePadProInputResponse { +impl TryFrom<&IrUserPacket> for CirclePadProInputResponse { type Error = String; - fn try_from(packet: IrUserPacket) -> Result { + fn try_from(packet: &IrUserPacket) -> Result { if packet.payload.len() != 6 { return Err(format!( "Invalid payload length (expected 6 bytes, got {})", @@ -422,6 +424,13 @@ impl TryFrom for CirclePadProInputResponse { } let response_id = packet.payload[0]; + if response_id != 0x10 { + return Err(format!( + "Invalid response ID (expected 0x10, got {:#x}", + 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); @@ -432,7 +441,6 @@ impl TryFrom for CirclePadProInputResponse { let unknown_field = packet.payload[5]; Ok(CirclePadProInputResponse { - response_id, c_stick_x, c_stick_y, battery_level,