diff --git a/src/controller/emulated.rs b/src/controller/emulated.rs index 208ad32..2816908 100644 --- a/src/controller/emulated.rs +++ b/src/controller/emulated.rs @@ -1,23 +1,28 @@ use std::thread; +use std::fs; use std::fs::File; use std::io::{Read, Write}; use std::process::Command; +use std::path::Path; use crate::controller::physical::ControllerState; mod dgoc44u; mod tcpp20009; mod tcpp20011; +mod sotp031201_p5b7; mod vok00106; -const FFS_MOUNT: &str = "/tmp/ffs-mascon"; -const ENDPOINT0: &str = "/tmp/ffs-mascon/ep0"; -const ENDPOINT1: &str = "/tmp/ffs-mascon/ep1"; +const FFS_MOUNT: &str = "/tmp/ffs"; +const ENDPOINT0: &str = "/tmp/ffs/ep0"; +const ENDPOINT1: &str = "/tmp/ffs/ep1"; +const ANDROID_GADGET: &str = "/sys/class/android_usb/android0"; #[derive(PartialEq)] pub enum ControllerModel { DGOC44U, TCPP20009, TCPP20011, + SOTP031201P5B7, VOK00106, } @@ -37,20 +42,25 @@ pub fn set_model(state: &ControllerState) -> Option { init_gadget(&dgoc44u::DEVICE_DESCRIPTOR, &dgoc44u::DESCRIPTORS, &dgoc44u::STRINGS); return Some(ControllerModel::DGOC44U); } - else if state.button_up { + else if state.button_d { println!("Selected controller TCPP-20009."); init_gadget(&tcpp20009::DEVICE_DESCRIPTOR, &tcpp20009::DESCRIPTORS, &tcpp20009::STRINGS); return Some(ControllerModel::TCPP20009); } - else if state.button_c { + else if state.button_b { println!("Selected controller TCPP-20011."); init_gadget(&tcpp20011::DEVICE_DESCRIPTOR, &tcpp20011::DESCRIPTORS, &tcpp20011::STRINGS); return Some(ControllerModel::TCPP20011); } - else if state.button_a { + else if state.button_c && state.power == 0 { + println!("Selected controller SOTP-031201 (P5/B7 mode)."); + init_gadget(&sotp031201_p5b7::DEVICE_DESCRIPTOR, &sotp031201_p5b7::DESCRIPTORS, &sotp031201_p5b7::STRINGS); + return Some(ControllerModel::SOTP031201P5B7); + } +/* else if state.button_a { println!("Selected controller VOK-00106."); return Some(ControllerModel::VOK00106); - } + } */ else { println!("No controller selected."); return None; @@ -68,6 +78,9 @@ pub fn set_state(state: &mut ControllerState, model: &ControllerModel) { ControllerModel::TCPP20011 => { tcpp20011::update_gadget(state); } + ControllerModel::SOTP031201P5B7 => { + sotp031201_p5b7::update_gadget(state); + } ControllerModel::VOK00106 => { vok00106::update_gadget(state); } @@ -75,6 +88,7 @@ pub fn set_state(state: &mut ControllerState, model: &ControllerModel) { } fn init_gadget(device: &DeviceDescriptor, descriptors: &[u8], strings: &[u8]) { + // Init g_ffs kernel module Command::new("modprobe").arg("g_ffs") .arg(String::from("bDeviceClass=")+&device.b_device_class.to_string()) .arg(String::from("bDeviceSubClass=")+&device.b_device_sub_class.to_string()) @@ -85,7 +99,7 @@ fn init_gadget(device: &DeviceDescriptor, descriptors: &[u8], strings: &[u8]) { .arg(String::from("iSerialNumber=")+device.i_serial_number) .output().ok(); Command::new("mkdir").args(["-p",&FFS_MOUNT]).output().ok(); - Command::new("mount").args(["-t","functionfs","mascon",&FFS_MOUNT]).output().ok(); + Command::new("mount").args(["-t","functionfs","ffs",&FFS_MOUNT]).output().ok(); thread::spawn(move || { if let Ok(mut ep0) = File::open(&ENDPOINT0) { @@ -96,9 +110,24 @@ fn init_gadget(device: &DeviceDescriptor, descriptors: &[u8], strings: &[u8]) { } }); if let Ok(mut ep0) = File::create(&ENDPOINT0) { - ep0.write(descriptors).ok(); + ep0.write_all(descriptors).ok(); println!("USB Gadget: Descriptors written to EP0"); - ep0.write(strings).ok(); + ep0.write_all(strings).ok(); println!("USB Gadget: Strings written to EP0"); } + + // Init Android Gadget for old 3.4 kernel + let gadget = Path::new(&ANDROID_GADGET); + if gadget.is_dir() { + fs::write(gadget.join(Path::new("bDeviceClass")), &device.b_device_class.to_string()).ok(); + fs::write(gadget.join(Path::new("bDeviceSubClass")), &device.b_device_sub_class.to_string()).ok(); + fs::write(gadget.join(Path::new("idVendor")), format!("{:x}", &device.id_vendor)).ok(); + fs::write(gadget.join(Path::new("idProduct")), format!("{:x}", &device.id_product)).ok(); + fs::write(gadget.join(Path::new("iManufacturer")), &device.i_manufacturer.to_string()).ok(); + fs::write(gadget.join(Path::new("iProduct")), &device.i_product.to_string()).ok(); + fs::write(gadget.join(Path::new("iSerial")), &device.i_serial_number.to_string()).ok(); + fs::write(gadget.join(Path::new("functions")), "ffs").ok(); + fs::write(gadget.join(Path::new("f_ffs/aliases")), "ffs").ok(); + fs::write(gadget.join(Path::new("enable")), "1").ok(); + } } diff --git a/src/controller/emulated/sotp031201_p5b7.rs b/src/controller/emulated/sotp031201_p5b7.rs new file mode 100644 index 0000000..97f07be --- /dev/null +++ b/src/controller/emulated/sotp031201_p5b7.rs @@ -0,0 +1,69 @@ +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; 48] = [0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, +0x09, 0x04, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, +0x07, 0x05, 0x81, 0x03, 0x08, 0x00, 0x14, +0x09, 0x04, 0x00, 0x00, 0x01, 0x00, 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: 0x00, b_device_sub_class: 0x0, id_vendor: 0x0AE4, id_product: 0x0101, i_manufacturer: "TAITO", i_product: "Densha de Go! Plug & Play (MTC P5/B7 mode)", i_serial_number: "SOTP-031201"}; + +const POWER_NOTCHES: [u8; 6] = [0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E]; +const BRAKE_NOTCHES: [u8; 10] = [0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x02, 0x01]; + +bitflags! { + struct Buttons1: u8 { + const NONE = 0; + const S = 1; + const D = 2; + const A = 4; + const A2 = 8; + const B = 16; + const C = 32; + } + struct Buttons2: u8 { + const NONE = 0; + const START = 1; + const SELECT = 2; + const UP = 4; + const DOWN = 8; + const LEFT = 16; + const RIGHT = 32; + } + } + +pub fn update_gadget(state: &mut ControllerState) { + // Calculate data for handles + let mut handle = POWER_NOTCHES[state.power as usize]; + if state.brake > 0 { + handle = BRAKE_NOTCHES[state.brake as usize]; + } + + // Calculate data for buttons 1 + let mut buttons1 = Buttons1::NONE; + if state.button_a { buttons1.insert(Buttons1::A) } + if state.button_b { buttons1.insert(Buttons1::B) } + if state.button_c { buttons1.insert(Buttons1::C) } + if state.button_d { buttons1.insert(Buttons1::D) } + + // Calculate data for buttons 2 + let mut buttons2 = Buttons2::NONE; + if state.button_up { buttons2.insert(Buttons2::UP) } + if state.button_down { buttons2.insert(Buttons2::DOWN) } + if state.button_left { buttons2.insert(Buttons2::LEFT) } + if state.button_right { buttons2.insert(Buttons2::RIGHT) } + if state.button_start { buttons2.insert(Buttons2::START) } + if state.button_select { buttons2.insert(Buttons2::SELECT) } + + // Assemble data and send it to endpoint + let data = [handle, buttons1.bits, buttons2.bits, 0x0]; + 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 7b69907..79a31cd 100644 --- a/src/controller/emulated/tcpp20009.rs +++ b/src/controller/emulated/tcpp20009.rs @@ -5,7 +5,9 @@ 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, +pub const DESCRIPTORS: [u8; 48] = [0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, +0x09, 0x04, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, +0x07, 0x05, 0x81, 0x03, 0x08, 0x00, 0x14, 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]; diff --git a/src/controller/emulated/tcpp20011.rs b/src/controller/emulated/tcpp20011.rs index 06c8d4e..a1259a2 100644 --- a/src/controller/emulated/tcpp20011.rs +++ b/src/controller/emulated/tcpp20011.rs @@ -5,7 +5,9 @@ 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, +pub const DESCRIPTORS: [u8; 48] = [0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, +0x09, 0x04, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, +0x07, 0x05, 0x81, 0x03, 0x08, 0x00, 0x14, 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];