From 4c18e70ce8bfbd32d4f8977660c9a1fd622a5afd Mon Sep 17 00:00:00 2001
From: Marc Riera <marc.riera.irigoyen@gmail.com>
Date: Thu, 2 Mar 2023 00:20:31 +0100
Subject: [PATCH] Fix input reading bug, module subdivision

---
 src/controller.rs                             |  2 ++
 .../emulated.rs}                              | 17 +++++++++--
 src/controller/emulated/dgoc44u.rs            | 13 ++++++++
 .../physical.rs}                              | 30 +++++--------------
 src/main.rs                                   | 29 +++++++++++-------
 src/state.rs                                  |  2 ++
 6 files changed, 59 insertions(+), 34 deletions(-)
 create mode 100644 src/controller.rs
 rename src/{virtual_controller.rs => controller/emulated.rs} (61%)
 create mode 100644 src/controller/emulated/dgoc44u.rs
 rename src/{physical_controller.rs => controller/physical.rs} (84%)

diff --git a/src/controller.rs b/src/controller.rs
new file mode 100644
index 0000000..4586bff
--- /dev/null
+++ b/src/controller.rs
@@ -0,0 +1,2 @@
+pub mod physical;
+pub mod emulated;
diff --git a/src/virtual_controller.rs b/src/controller/emulated.rs
similarity index 61%
rename from src/virtual_controller.rs
rename to src/controller/emulated.rs
index 5479e0b..7e65eff 100644
--- a/src/virtual_controller.rs
+++ b/src/controller/emulated.rs
@@ -1,4 +1,5 @@
 use crate::state::ControllerState;
+mod dgoc44u;
 
 #[derive(PartialEq)]
 pub enum ControllerModel {
@@ -12,7 +13,7 @@ pub fn set_model(state: &ControllerState) -> ControllerModel {
         println!("Selected controller DGOC44-U.");
         return ControllerModel::DGOC44U;
     }
-    else if state.button_left {
+    else if state.button_up {
         println!("Selected controller TCPP-20009.");
         return ControllerModel::TYPE2;
     }
@@ -20,4 +21,16 @@ pub fn set_model(state: &ControllerState) -> ControllerModel {
         println!("No controller selected.");
         return ControllerModel::NONE;
     }
-}
\ No newline at end of file
+}
+
+pub fn set_state(state: &mut ControllerState, model: &ControllerModel) {
+    match model {
+        ControllerModel::DGOC44U => {
+            dgoc44u::update_gadget(state);
+        }
+        ControllerModel::TYPE2 => {
+
+        }
+        ControllerModel::NONE => (),
+    }
+}
diff --git a/src/controller/emulated/dgoc44u.rs b/src/controller/emulated/dgoc44u.rs
new file mode 100644
index 0000000..5845a30
--- /dev/null
+++ b/src/controller/emulated/dgoc44u.rs
@@ -0,0 +1,13 @@
+use crate::state::ControllerState;
+
+const POWER_NOTCHES: [u8; 6] = [0x81, 0x6D, 0x54, 0x3F, 0x21, 0x00];
+const BRAKE_NOTCHES: [u8; 10] = [0x79, 0x8A, 0x94, 0x9A, 0xA2, 0xA8, 0xAF, 0xB2, 0xB5, 0xB9];
+
+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];
+
+        // Assemble data and send it to gadget
+        let data = [brake, power, 0, 0, 0, 0];
+}
\ No newline at end of file
diff --git a/src/physical_controller.rs b/src/controller/physical.rs
similarity index 84%
rename from src/physical_controller.rs
rename to src/controller/physical.rs
index 735b9bb..94f3131 100644
--- a/src/physical_controller.rs
+++ b/src/controller/physical.rs
@@ -21,28 +21,14 @@ pub fn get_state(state: &mut ControllerState, dev: &[Device; 2]) {
     for d in dev {
         if let Ok(key_vals) = d.get_key_state() {
             for key in USED_KEYS {
-                read_input(state, key, key_vals.contains(key));
+                if d.supported_keys().map_or(true, |k| k.contains(key)) {
+                    read_input(state, key, key_vals.contains(key));
+                }
             }
         }
     }
 }
 
-/* pub fn fetch_input(state: &mut ControllerState, dev: &mut [Device; 2]) {
-    for device in dev {
-        let evs = device.fetch_events();
-        match evs {
-            Ok(evs) => {
-                for event in evs {
-                    if event.event_type() == EventType::KEY {
-                        read_input(state, Key(event.code()), event.value() != 0);
-                    }
-                }
-            },
-            Err(_e) => (),
-        }
-    }
-} */
-
 fn read_input(controller: &mut ControllerState, key: Key, value: bool) {
     // Save input status to object for processing
     match key{
@@ -80,16 +66,16 @@ pub fn set_lamp(status: bool) {
     if let Ok(mut out) = File::create("/sys/class/leds/led2/brightness") {
         out.write(if status {b"1"} else {b"0"}).ok();
     }
-    else {
+    /*else {
         println!("WARNING: Could not set door lamp status!")
-    }
+    }*/
 }
 
 pub fn set_rumble(status: bool) {
     if let Ok(mut out) = File::create("/sys/class/leds/led1/brightness") {
         out.write(if status {b"1"} else {b"0"}).ok();
     }
-    else {
+    /*else {
         println!("WARNING: Could not set rumble motor status!")
-    }
-}
\ No newline at end of file
+    }*/
+}
diff --git a/src/main.rs b/src/main.rs
index 20ba255..186a49e 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,5 +1,4 @@
-mod physical_controller;
-mod virtual_controller;
+mod controller;
 mod state;
 
 use std::io::Result;
@@ -7,17 +6,18 @@ use std::process::Command;
 use std::time::Duration;
 use std::thread::sleep;
 
-use virtual_controller::ControllerModel;
+use controller::emulated::ControllerModel;
+use controller::physical::{set_lamp,set_rumble};
 
 fn main() -> Result<()> {
-    match physical_controller::init() {
+    match controller::physical::init() {
         Ok(dev) => {
             // Wait 3 seconds and get current state of the controller
             println!("Press a button to select the controller model...");
             sleep(Duration::from_secs(3));
             let mut controller_state = Default::default();
-            physical_controller::get_state(&mut controller_state, &dev);
-            let controller_model = virtual_controller::set_model(&controller_state);
+            controller::physical::get_state(&mut controller_state, &dev);
+            let controller_model = controller::emulated::set_model(&controller_state);
 
             // If no model selected, quit
             if controller_model == ControllerModel::NONE {
@@ -28,14 +28,23 @@ fn main() -> Result<()> {
             stop_game();
 
             // Vibrate to end selection mode
-            physical_controller::set_rumble(true);
+            set_rumble(true);
             sleep(Duration::from_millis(500));
-            physical_controller::set_rumble(false);
+            set_rumble(false);
 
             loop {
                 // Fetch events from input devices
-                physical_controller::get_state(&mut controller_state, &dev);
-                sleep(Duration::from_millis(100));
+                controller::physical::get_state(&mut controller_state, &dev);
+
+                // Send input to virtual controller
+                controller::emulated::set_state(&mut controller_state, &controller_model);
+
+                // Update lamp and rumble
+                set_lamp(controller_state.lamp);
+                set_rumble(controller_state.rumble);
+
+                // Wait between cycles
+                sleep(Duration::from_millis(20));
             }
         },
         Err(_e) => println!("ERROR: Could not read input devices! Exiting."),
diff --git a/src/state.rs b/src/state.rs
index e22d5a2..6960331 100644
--- a/src/state.rs
+++ b/src/state.rs
@@ -12,4 +12,6 @@ pub struct ControllerState {
     pub button_down: bool,
     pub button_left: bool,
     pub button_right: bool,
+    pub lamp: bool,
+    pub rumble: bool,
 }
\ No newline at end of file