diff --git a/src/controller/emulated.rs b/src/controller/emulated.rs index c2bf3e8..208ad32 100644 --- a/src/controller/emulated.rs +++ b/src/controller/emulated.rs @@ -6,12 +6,18 @@ use std::process::Command; use crate::controller::physical::ControllerState; mod dgoc44u; mod tcpp20009; +mod tcpp20011; mod vok00106; +const FFS_MOUNT: &str = "/tmp/ffs-mascon"; +const ENDPOINT0: &str = "/tmp/ffs-mascon/ep0"; +const ENDPOINT1: &str = "/tmp/ffs-mascon/ep1"; + #[derive(PartialEq)] pub enum ControllerModel { DGOC44U, TCPP20009, + TCPP20011, VOK00106, } @@ -36,6 +42,11 @@ pub fn set_model(state: &ControllerState) -> Option { init_gadget(&tcpp20009::DEVICE_DESCRIPTOR, &tcpp20009::DESCRIPTORS, &tcpp20009::STRINGS); return Some(ControllerModel::TCPP20009); } + else if state.button_c { + println!("Selected controller TCPP-20011."); + init_gadget(&tcpp20011::DEVICE_DESCRIPTOR, &tcpp20011::DESCRIPTORS, &tcpp20011::STRINGS); + return Some(ControllerModel::TCPP20011); + } else if state.button_a { println!("Selected controller VOK-00106."); return Some(ControllerModel::VOK00106); @@ -54,6 +65,9 @@ pub fn set_state(state: &mut ControllerState, model: &ControllerModel) { ControllerModel::TCPP20009 => { tcpp20009::update_gadget(state); } + ControllerModel::TCPP20011 => { + tcpp20011::update_gadget(state); + } ControllerModel::VOK00106 => { vok00106::update_gadget(state); } @@ -70,18 +84,18 @@ fn init_gadget(device: &DeviceDescriptor, descriptors: &[u8], strings: &[u8]) { .arg(String::from("iProduct=")+device.i_product) .arg(String::from("iSerialNumber=")+device.i_serial_number) .output().ok(); - Command::new("mkdir").args(["-p","/tmp/ffs-mascon"]).output().ok(); - Command::new("mount").args(["-t","functionfs","mascon","/tmp/ffs-mascon"]).output().ok(); + Command::new("mkdir").args(["-p",&FFS_MOUNT]).output().ok(); + Command::new("mount").args(["-t","functionfs","mascon",&FFS_MOUNT]).output().ok(); thread::spawn(move || { - if let Ok(mut ep0) = File::open("/tmp/ffs-mascon/ep0") { - let mut buffer = [0; 100]; + if let Ok(mut ep0) = File::open(&ENDPOINT0) { + let mut buffer = [0; 4]; loop { ep0.read(&mut buffer).ok(); } } }); - if let Ok(mut ep0) = File::create("/tmp/ffs-mascon/ep0") { + if let Ok(mut ep0) = File::create(&ENDPOINT0) { ep0.write(descriptors).ok(); println!("USB Gadget: Descriptors written to EP0"); ep0.write(strings).ok(); diff --git a/src/controller/emulated/dgoc44u.rs b/src/controller/emulated/dgoc44u.rs index c799283..b7cbdea 100644 --- a/src/controller/emulated/dgoc44u.rs +++ b/src/controller/emulated/dgoc44u.rs @@ -2,7 +2,7 @@ use std::fs::File; use std::io::{Write}; use bitflags::bitflags; use crate::controller::physical::ControllerState; -use crate::controller::emulated::DeviceDescriptor; +use crate::controller::emulated::{DeviceDescriptor, ENDPOINT1}; pub const DESCRIPTORS: [u8; 41] = [0x01, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, @@ -52,4 +52,7 @@ pub fn update_gadget(state: &mut ControllerState) { // Assemble data and send it to gadget let data = [brake, power, 0, buttons.bits, 0, 0]; + if let Ok(mut file) = File::create(ENDPOINT1) { + file.write(&data).ok(); + } } \ No newline at end of file diff --git a/src/controller/emulated/tcpp20009.rs b/src/controller/emulated/tcpp20009.rs index 1267b97..7b69907 100644 --- a/src/controller/emulated/tcpp20009.rs +++ b/src/controller/emulated/tcpp20009.rs @@ -3,7 +3,7 @@ use std::io::Write; use bitflags::bitflags; use crate::controller::physical::ControllerState; -use crate::controller::emulated::DeviceDescriptor; +use crate::controller::emulated::{DeviceDescriptor, ENDPOINT1}; pub const DESCRIPTORS: [u8; 32] = [0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, @@ -52,10 +52,9 @@ pub fn update_gadget(state: &mut ControllerState) { if state.button_down & state.button_left { dpad = 0x5 } if state.button_down & state.button_right { dpad = 0x3 } - // Assemble data and send it to gadget + // Assemble data and send it to endpoint let data = [0x1, brake, power, 0xFF, dpad, buttons.bits]; - - if let Ok(mut file) = File::create("/tmp/ffs-mascon/ep1") { + if let Ok(mut file) = File::create(ENDPOINT1) { file.write(&data).ok(); } } \ No newline at end of file diff --git a/src/controller/emulated/tcpp20011.rs b/src/controller/emulated/tcpp20011.rs new file mode 100644 index 0000000..06c8d4e --- /dev/null +++ b/src/controller/emulated/tcpp20011.rs @@ -0,0 +1,60 @@ +use std::fs::File; +use std::io::Write; + +use bitflags::bitflags; +use crate::controller::physical::ControllerState; +use crate::controller::emulated::{DeviceDescriptor, ENDPOINT1}; + +pub const DESCRIPTORS: [u8; 32] = [0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x09, 0x04, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, +0x07, 0x05, 0x81, 0x03, 0x08, 0x00, 0x14]; +pub const STRINGS: [u8; 16] = [0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; + +pub const DEVICE_DESCRIPTOR: DeviceDescriptor = DeviceDescriptor{b_device_class: 0xFF, b_device_sub_class: 0x5, id_vendor: 0x0AE4, id_product: 0x0005, i_manufacturer: "TAITO", i_product: "Densha de Go! Plug & Play (Shinkansen)", i_serial_number: "TCPP20011"}; + +const POWER_NOTCHES: [u8; 6] = [0x12, 0x36, 0x5A, 0x90, 0xC6, 0xFB]; +const BRAKE_NOTCHES: [u8; 10] = [0x1C, 0x38, 0x54, 0x70, 0x8B, 0xA7, 0xC3, 0xDF, 0xDF, 0xFB]; + +bitflags! { + struct Buttons: u8 { + const NONE = 0; + const D = 1; + const C = 2; + const B = 4; + const A = 8; + const SELECT = 16; + const START = 32; + } + } + +pub fn update_gadget(state: &mut ControllerState) { + // Calculate data for handles + let power = POWER_NOTCHES[state.power as usize]; + let brake = BRAKE_NOTCHES[state.brake as usize]; + + // Calculate data for buttons + let mut buttons = Buttons::NONE; + if state.button_a { buttons.insert(Buttons::A) } + if state.button_b { buttons.insert(Buttons::B) } + if state.button_c { buttons.insert(Buttons::C) } + if state.button_d { buttons.insert(Buttons::D) } + if state.button_select { buttons.insert(Buttons::SELECT) } + if state.button_start { buttons.insert(Buttons::START) } + + // Calculate data for D-pad + let mut dpad: u8 = 0x8; + if state.button_up { dpad = 0x0 } + if state.button_down { dpad = 0x4 } + if state.button_left { dpad = 0x6 } + if state.button_right { dpad = 0x2 } + if state.button_up & state.button_left { dpad = 0x7 } + if state.button_up & state.button_right { dpad = 0x1 } + if state.button_down & state.button_left { dpad = 0x5 } + if state.button_down & state.button_right { dpad = 0x3 } + + // Assemble data and send it to endpoint + let data = [brake, power, 0xFF, dpad, buttons.bits, 0x0]; + if let Ok(mut file) = File::create(ENDPOINT1) { + file.write(&data).ok(); + } +} \ No newline at end of file