Browse Source

Got connection working and packets flowing

Need to parse packets now to make sure input signal is getting
transferred correctly.
pull/129/head
AzureMarker 2 years ago committed by Mark Drobnak
parent
commit
6c2b184e00
No known key found for this signature in database
GPG Key ID: 47A133F3BF9D03D3
  1. 226
      ctru-rs/examples/ir-user.rs
  2. 44
      ctru-rs/src/services/ir_user.rs

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

@ -1,19 +1,23 @@
use ctru::error::ResultCode;
use ctru::prelude::*; use ctru::prelude::*;
use ctru::services::ir_user::{IrDeviceId, IrUser}; use ctru::services::ir_user::{IrDeviceId, IrUser, IrUserStatusInfo};
use time::Duration; use time::Duration;
use ctru::error::ResultCode;
const PACKET_INFO_SIZE: usize = 8; const PACKET_INFO_SIZE: usize = 8;
const MAX_PACKET_SIZE: usize = 32; const MAX_PACKET_SIZE: usize = 32;
const PACKET_COUNT: usize = 1; const PACKET_COUNT: usize = 1;
const PACKET_BUFFER_SIZE: usize = PACKET_COUNT * (PACKET_INFO_SIZE + MAX_PACKET_SIZE); 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() { fn main() {
ctru::init(); ctru::init();
let apt = Apt::init().unwrap(); let apt = Apt::init().unwrap();
let hid = Hid::init().unwrap(); let hid = Hid::init().unwrap();
let gfx = Gfx::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( let ir_user = IrUser::init(
PACKET_BUFFER_SIZE, PACKET_BUFFER_SIZE,
PACKET_COUNT, PACKET_COUNT,
@ -21,87 +25,181 @@ fn main() {
PACKET_COUNT, PACKET_COUNT,
) )
.expect("Couldn't initialize ir:USER service"); .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() .get_connection_status_event()
.expect("Couldn't get ir:USER connection status event"); .expect("Couldn't get ir:USER connection status event");
ir_user let recv_event = ir_user
.require_connection(IrDeviceId::CirclePadPro)
.expect("Couldn't initialize circle pad pro connection");
let ir_user_recv_event = ir_user
.get_recv_event() .get_recv_event()
.expect("Couldn't get ir:USER recv event"); .expect("Couldn't get ir:USER recv event");
println!("StatusInfo:\n{:#?}", ir_user.get_status_info()); print_status_info();
// Wait for the connection to establish // // Wait for the connection to establish
(|| unsafe { // (|| unsafe {
ResultCode(ctru_sys::svcWaitSynchronization( // ResultCode(ctru_sys::svcWaitSynchronization(
ir_user_connection_status_event, // ir_user_connection_status_event,
Duration::seconds(10).whole_nanoseconds() as i64, // Duration::seconds(10).whole_nanoseconds() as i64,
))?; // ))?;
//
println!("Finished waiting on connection status event"); // println!("Finished waiting on connection status event");
println!("StatusInfo:\n{:#?}", ir_user.get_status_info()); // println!("StatusInfo:\n{:#?}", ir_user.get_status_info());
//
Ok(()) // Ok(())
})().expect("Failed to connect to circle pad pro"); // })().expect("Failed to connect to circle pad pro");
ir_user let mut step = 0;
.start_polling_input(20)
.expect("Couldn't configure circle pad pro polling interval"); 'main_loop: while apt.main_loop() {
while apt.main_loop() {
hid.scan_input(); hid.scan_input();
// Check if we've received a packet from the circle pad pro // Check if we've received a packet from the circle pad pro
let check_ir_packet = let check_ir_packet = unsafe { ctru_sys::svcWaitSynchronization(recv_event, 0) == 0 };
unsafe { ctru_sys::svcWaitSynchronization(ir_user_recv_event, 0) == 0 };
if check_ir_packet { if check_ir_packet {
console.clear(); print_status_info();
handle_packet(&ir_user, &top_console, &bottom_console);
// Move the cursor back to the top of the screen }
print!("\x1b[0;0H");
println!("StatusInfo:\n{:?}", ir_user.get_status_info());
ir_user.process_shared_memory(|ir_mem| { if hid.keys_held().contains(KeyPad::KEY_START) {
println!("\nReceiveBufferInfo:"); break;
for byte in &ir_mem[0x10..0x20] { }
print!("{byte:02x} ");
}
println!("\nReceiveBuffer:"); if hid.keys_down().contains(KeyPad::KEY_A) {
let mut counter = 0; match step {
for byte in &ir_mem[0x20..0x20 + PACKET_BUFFER_SIZE] { 0 => {
print!("{byte:02x} "); loop {
counter += 1; hid.scan_input();
if counter % 16 == 0 { if hid.keys_held().contains(KeyPad::KEY_START) {
println!() 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:"); step += 1;
for byte in &ir_mem[0x20 + PACKET_BUFFER_SIZE..0x30 + PACKET_BUFFER_SIZE] { }
print!("{byte:02x} ");
}
println!("\n(skipping send packet buffer)"); gfx.flush_buffers();
}); gfx.swap_buffers();
gfx.wait_for_vblank();
}
}
// Done handling the packet, release it fn handle_packet(ir_user: &IrUser, top_console: &Console, bottom_console: &Console) {
ir_user ir_user.process_shared_memory(|ir_mem| {
.release_received_data(1) bottom_console.select();
.expect("Failed to release ir:USER packet"); 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) { println!("\nSendBufferInfo:");
break; 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(); println!("\n(skipping send packet buffer)");
gfx.swap_buffers(); top_console.select();
gfx.wait_for_vblank(); });
// 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:?}");
} }
} }

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

@ -22,11 +22,12 @@ struct IrUserState {
// shared_memory: Box<[u8]>, // shared_memory: Box<[u8]>,
} }
const INITIALIZE_IRNOP_SHARED_COMMAND_HEADER: u32 = 0x00180182;
const REQUIRE_CONNECTION_COMMAND_HEADER: u32 = 0x00060040; 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_RECEIVE_EVENT_COMMAND_HEADER: u32 = 0x000A0000;
const GET_CONNECTION_STATUS_EVENT_COMMAND_HEADER: u32 = 0x000C0000;
const SEND_IR_NOP_COMMAND_HEADER: u32 = 0x000D0042; const SEND_IR_NOP_COMMAND_HEADER: u32 = 0x000D0042;
const INITIALIZE_IRNOP_SHARED_COMMAND_HEADER: u32 = 0x00180182;
const RELEASE_RECEIVED_DATA_COMMAND_HEADER: u32 = 0x00190040; const RELEASE_RECEIVED_DATA_COMMAND_HEADER: u32 = 0x00190040;
impl IrUser { impl IrUser {
@ -46,12 +47,6 @@ impl IrUser {
println!("Getting shared memory pointer"); println!("Getting shared memory pointer");
let info_sections_size = 0x30; 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 minimum_shared_memory_len = info_sections_size + recv_buffer_size + send_buffer_size;
let shared_memory_len = if minimum_shared_memory_len % 0x1000 != 0 { let shared_memory_len = if minimum_shared_memory_len % 0x1000 != 0 {
(minimum_shared_memory_len / 0x1000) * 0x1000 + 0x1000 (minimum_shared_memory_len / 0x1000) * 0x1000 + 0x1000
@ -150,6 +145,17 @@ impl IrUser {
Ok(()) 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<Handle> { pub fn get_connection_status_event(&self) -> crate::Result<Handle> {
println!("GetConnectionStatusEvent called"); println!("GetConnectionStatusEvent called");
let response = self.send_service_request(vec![GET_CONNECTION_STATUS_EVENT_COMMAND_HEADER], 4)?; 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<()> { pub fn start_polling_input(&self, period_ms: u8) -> crate::Result<()> {
println!("SendIrnop (start_polling_input) called"); 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( self.send_service_request(
vec![ vec![
SEND_IR_NOP_COMMAND_HEADER, SEND_IR_NOP_COMMAND_HEADER,
@ -305,14 +311,14 @@ impl IrDeviceId {
#[derive(Debug)] #[derive(Debug)]
pub struct IrUserStatusInfo { pub struct IrUserStatusInfo {
recv_err_result: ctru_sys::Result, pub recv_err_result: ctru_sys::Result,
send_err_result: ctru_sys::Result, pub send_err_result: ctru_sys::Result,
connection_status: u8, pub connection_status: u8,
trying_to_connect_status: u8, pub trying_to_connect_status: u8,
connection_role: u8, pub connection_role: u8,
machine_id: u8, pub machine_id: u8,
unknown_field_1: u8, pub unknown_field_1: u8,
network_id: u8, pub network_id: u8,
unknown_field_2: u8, pub unknown_field_2: u8,
unknown_field_3: u8, pub unknown_field_3: u8,
} }

Loading…
Cancel
Save