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

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

@ -22,11 +22,12 @@ struct IrUserState { @@ -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 { @@ -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 { @@ -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<Handle> {
println!("GetConnectionStatusEvent called");
let response = self.send_service_request(vec![GET_CONNECTION_STATUS_EVENT_COMMAND_HEADER], 4)?;
@ -170,7 +176,7 @@ impl IrUser { @@ -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 { @@ -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,
}

Loading…
Cancel
Save