Add support for Shinkansen controller

This commit is contained in:
Marc Riera 2023-04-01 19:03:15 +02:00
parent be4bb1f76d
commit 09c269e852
4 changed files with 86 additions and 10 deletions

View file

@ -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<ControllerModel> {
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();

View file

@ -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();
}
}

View file

@ -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();
}
}

View file

@ -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();
}
}