|
|
|
@ -1,8 +1,7 @@
@@ -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() {
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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:?}"); |
|
|
|
|
} |
|
|
|
|