Add support for Android Gadget, MTC test

This commit is contained in:
Marc Riera 2023-04-11 00:18:51 +02:00
parent 09c269e852
commit 38d88d9e7f
4 changed files with 114 additions and 12 deletions

View file

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

View file

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

View file

@ -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];

View file

@ -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];