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; 80] = [0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x09, 0x21, 0x11, 0x01, 0x00, 0x01, 0x22, 0x94, 0x00, 0x07, 0x05, 0x02, 0x03, 0x40, 0x00, 0x05, 0x07, 0x05, 0x81, 0x03, 0x40, 0x00, 0x05, 0x09, 0x04, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x09, 0x21, 0x11, 0x01, 0x00, 0x01, 0x22, 0x94, 0x00, 0x07, 0x05, 0x02, 0x03, 0x40, 0x00, 0x05, 0x07, 0x05, 0x81, 0x03, 0x40, 0x00, 0x05]; 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: 0x0, b_device_sub_class: 0x0, id_vendor: 0x054C, id_product: 0x0268, bcd_device: 0x0100, i_manufacturer: "TAITO", i_product: "Densha de Go! Plug & Play (PS1 Two Handle mode)", i_serial_number: "SLPH-00051"}; pub const HID_REPORT_DESCRIPTOR: [u8; 148] = [ 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) 0x09, 0x04, // Usage (Joystick) 0xA1, 0x01, // Collection (Physical) 0xA1, 0x02, // Collection (Application) 0x85, 0x01, // Report ID (1) 0x75, 0x08, // Report Size (8) 0x95, 0x01, // Report Count (1) 0x15, 0x00, // Logical Minimum (0) 0x26, 0xFF, 0x00, // Logical Maximum (255) 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) // NOTE: reserved byte 0x75, 0x01, // Report Size (1) 0x95, 0x13, // Report Count (19) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x01, // Logical Maximum (1) 0x35, 0x00, // Physical Minimum (0) 0x45, 0x01, // Physical Maximum (1) 0x05, 0x09, // Usage Page (Button) 0x19, 0x01, // Usage Minimum (0x01) 0x29, 0x13, // Usage Maximum (0x13) 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 0x75, 0x01, // Report Size (1) 0x95, 0x0D, // Report Count (13) 0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00) 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) // NOTE: 32 bit integer, where 0:18 are buttons and 19:31 are reserved 0x15, 0x00, // Logical Minimum (0) 0x26, 0xFF, 0x00, // Logical Maximum (255) 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) 0x09, 0x01, // Usage (Pointer) 0xA1, 0x00, // Collection (Undefined) 0x75, 0x08, // Report Size (8) 0x95, 0x04, // Report Count (4) 0x35, 0x00, // Physical Minimum (0) 0x46, 0xFF, 0x00, // Physical Maximum (255) 0x09, 0x30, // Usage (X) 0x09, 0x31, // Usage (Y) 0x09, 0x32, // Usage (Z) 0x09, 0x35, // Usage (Rz) 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) // NOTE: four joysticks 0xC0, // End Collection 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) 0x75, 0x08, // Report Size (8) 0x95, 0x27, // Report Count (39) 0x09, 0x01, // Usage (Pointer) 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 0x75, 0x08, // Report Size (8) 0x95, 0x30, // Report Count (48) 0x09, 0x01, // Usage (Pointer) 0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) 0x75, 0x08, // Report Size (8) 0x95, 0x30, // Report Count (48) 0x09, 0x01, // Usage (Pointer) 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) 0xC0, // End Collection 0xA1, 0x02, // Collection (Application) 0x85, 0x02, // Report ID (2) 0x75, 0x08, // Report Size (8) 0x95, 0x30, // Report Count (48) 0x09, 0x01, // Usage (Pointer) 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) 0xC0, // End Collection 0xA1, 0x02, // Collection (Application) 0x85, 0xEE, // Report ID (238) 0x75, 0x08, // Report Size (8) 0x95, 0x30, // Report Count (48) 0x09, 0x01, // Usage (Pointer) 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) 0xC0, // End Collection 0xA1, 0x02, // Collection (Application) 0x85, 0xEF, // Report ID (239) 0x75, 0x08, // Report Size (8) 0x95, 0x30, // Report Count (48) 0x09, 0x01, // Usage (Pointer) 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) 0xC0, // End Collection 0xC0, // End Collection ]; bitflags! { struct Buttons1: u8 { const NONE = 0; const SELECT = 1; const L3 = 2; const R3 = 4; const START = 8; const UP = 16; const RIGHT = 32; const DOWN = 64; const LEFT = 128; } struct Buttons2: u8 { const NONE = 0; const L2 = 1; const R2 = 2; const L1 = 4; const R1 = 8; const TRIANGLE = 16; const CIRCLE = 32; const CROSS = 64; const SQUARE = 128; } } pub fn update_gadget(state: &mut ControllerState) { let mut buttons1 = Buttons1::UP | Buttons1::DOWN; let mut buttons2 = Buttons2::NONE; // Calculate data for handles match state.power { 0 => { buttons1.insert(Buttons1::LEFT | Buttons1::RIGHT); } 1 => { buttons1.insert(Buttons1::RIGHT); buttons2.insert(Buttons2::TRIANGLE); } 2 => { buttons1.insert(Buttons1::RIGHT); } 3 => { buttons1.insert(Buttons1::LEFT); buttons2.insert(Buttons2::TRIANGLE); } 4 => { buttons1.insert(Buttons1::LEFT); } _ => { buttons2.insert(Buttons2::TRIANGLE); } } match state.brake { 0 => { buttons2.insert(Buttons2::L2 | Buttons2::R1 | Buttons2::R2); } 1 => { buttons2.insert(Buttons2::L1 | Buttons2::R1 | Buttons2::R2); } 2 => { buttons2.insert(Buttons2::R1 | Buttons2::R2); } 3 => { buttons2.insert(Buttons2::L1 | Buttons2::L2 | Buttons2::R2); } 4 => { buttons2.insert(Buttons2::L2 | Buttons2::R2); } 5 => { buttons2.insert(Buttons2::L1 | Buttons2::R2); } 6 => { buttons2.insert(Buttons2::R2); } 7 => { buttons2.insert(Buttons2::L1 | Buttons2::L2 | Buttons2::R1); } 8 => { buttons2.insert(Buttons2::L2 | Buttons2::R1); } _ => () } // Calculate data for buttons if state.button_a { buttons2.insert(Buttons2::SQUARE) } if state.button_b { buttons2.insert(Buttons2::CROSS) } if state.button_c { buttons2.insert(Buttons2::CIRCLE) } if state.button_start { buttons1.insert(Buttons1::START) } if state.button_select { buttons1.insert(Buttons1::SELECT) } // Assemble data and send it to gadget let data = [0x1, 0x0, buttons1.bits, buttons2.bits, 0x0, 0x0, 0x80, 0x80, 0x80, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xEF, 0x14, 0x0, 0x0, 0x0, 0x0, 0x23, 0x1A, 0x77, 0x1, 0x81, 0x1, 0xFE, 0x1, 0xFE, 0x1, 0xFE, 0x1, 0xFE]; if let Ok(mut file) = File::create(ENDPOINT1) { file.write(&data).ok(); } }