diff --git a/src-tauri/src/slider_io/device.rs b/src-tauri/src/slider_io/device.rs index b1e963b..e8086dd 100644 --- a/src-tauri/src/slider_io/device.rs +++ b/src-tauri/src/slider_io/device.rs @@ -1,89 +1,169 @@ -use std::{ - sync::{ - atomic::{AtomicBool, Ordering}, - Arc, - }, - thread::{self, JoinHandle}, +use std::{error, ops::DerefMut, time::Duration}; + +use rusb::{self, DeviceHandle, GlobalContext}; + +use crate::slider_io::{ + config::DeviceMode, + controller_state::{ControllerState, FullState, LedState}, + worker::Job, }; -use crate::slider_io::{config::DeviceMode, controller_state::FullState, hid}; - -pub struct DeviceThread { - thread: Option>, - stop_signal: Arc, +pub struct Buffer { + pub data: [u8; 128], + pub len: usize, } -impl DeviceThread { - pub fn new(state: &FullState, mode: DeviceMode) -> Self { - let controller_state = state.clone_controller(); - let led_state = state.clone_led(); - let stop_signal = Arc::new(AtomicBool::new(false)); +impl Buffer { + pub fn new() -> Self { + Buffer { + data: [0; 128], + len: 0, + } + } - let stop_signal_clone = Arc::clone(&stop_signal); + fn slice(&self) -> &[u8] { + &self.data[0..self.len] + } +} + +type HidReadCallback = fn(&Buffer, &mut ControllerState) -> (); +type HidLedCallback = fn(&mut Buffer, &mut LedState) -> (); + +pub struct HidDeviceJob { + state: FullState, + vid: u16, + pid: u16, + read_endpoint: u8, + led_endpoint: u8, + + read_callback: HidReadCallback, + read_buf: Buffer, + + led_callback: HidLedCallback, + led_buf: Buffer, + + handle: Option>, +} + +impl HidDeviceJob { + fn new( + state: FullState, + vid: u16, + pid: u16, + read_endpoint: u8, + led_endpoint: u8, + read_callback: HidReadCallback, + led_callback: HidLedCallback, + ) -> Self { Self { - thread: Some(match mode { - DeviceMode::None => thread::spawn(|| {}), - DeviceMode::TasollerOne => thread::spawn(|| {}), - DeviceMode::TasollerTwo => thread::spawn(|| {}), - DeviceMode::Yuancon => thread::spawn(move || { - hid::poll_controller( - 0x1973, - 0x2001, - move |buf| { - if (buf.len != 34) { - return; - } - - let mut controller_state_handle = controller_state.lock().unwrap(); - controller_state_handle - .ground_state - .clone_from_slice(&buf.data[2..34]); - for i in 0..6 { - controller_state_handle.air_state[i ^ 1] = - if buf.data[0] & (1 << i) == 0 { 1 } else { 0 }; - } - for i in 0..3 { - controller_state_handle.extra_state[i] = - if buf.data[1] & (1 << i) == 0 { 1 } else { 0 }; - } - - // println!("{:?}", controller_state_handle.ground_state); - }, - move |buf| { - let mut led_state_handle = led_state.lock().unwrap(); - if led_state_handle.dirty { - buf.len = 31 * 2; - buf - .data - .chunks_mut(2) - .take(31) - .zip(led_state_handle.led_state.chunks(3).rev()) - .for_each(|(buf_chunk, state_chunk)| { - buf_chunk[0] = (state_chunk[0] << 3 & 0xe0) | (state_chunk[2] >> 3); - buf_chunk[1] = (state_chunk[1] & 0xf8) | (state_chunk[0] >> 5); - }); - led_state_handle.dirty = false; - } - }, - &stop_signal_clone, - ) - // .unwrap_or_else(|err| { - // println!("Device thread: {:?}", err); - // }); - .unwrap(); - }), - DeviceMode::Brokenithm { .. } => thread::spawn(|| {}), - }), - stop_signal: stop_signal, + state, + vid, + pid, + read_endpoint, + led_endpoint, + read_callback, + read_buf: Buffer::new(), + led_callback, + led_buf: Buffer::new(), + handle: None, } } + + pub fn from_config(mode: &DeviceMode, state: &FullState) -> Self { + match mode { + DeviceMode::Yuancon => Self::new( + state.clone(), + 0x1973, + 0x2001, + 0x81, + 0x02, + |buf, controller_state| { + if buf.len != 34 { + return; + } + + controller_state + .ground_state + .clone_from_slice(&buf.data[2..34]); + for i in 0..6 { + controller_state.air_state[i ^ 1] = if buf.data[0] & (1 << i) == 0 { 1 } else { 0 }; + } + for i in 0..3 { + controller_state.extra_state[i] = if buf.data[1] & (1 << i) == 0 { 1 } else { 0 }; + } + }, + |buf, led_state| { + if !led_state.dirty { + return; + } + buf.len = 31 * 2; + buf + .data + .chunks_mut(2) + .take(31) + .zip(led_state.led_state.chunks(3).rev()) + .for_each(|(buf_chunk, state_chunk)| { + buf_chunk[0] = (state_chunk[0] << 3 & 0xe0) | (state_chunk[2] >> 3); + buf_chunk[1] = (state_chunk[1] & 0xf8) | (state_chunk[0] >> 5); + }); + led_state.dirty = false; + }, + ), + _ => panic!("Not implemented"), + } + } + + fn setup_impl(&mut self) -> Result<(), Box> { + let mut handle = rusb::open_device_with_vid_pid(self.vid, self.pid).unwrap(); + if handle.kernel_driver_active(0).unwrap_or(false) { + handle.detach_kernel_driver(0)?; + } + handle.set_active_configuration(1)?; + handle.claim_interface(0)?; + self.handle = Some(handle); + Ok(()) + } } -impl Drop for DeviceThread { - fn drop(&mut self) { - self.stop_signal.swap(true, Ordering::SeqCst); - if self.thread.is_some() { - self.thread.take().unwrap().join().ok(); +const timeout: Duration = Duration::from_millis(20); + +impl Job for HidDeviceJob { + fn setup(&mut self) { + self.setup_impl().unwrap(); + } + + fn tick(&mut self) { + // Input loop + let handle = self.handle.as_mut().unwrap(); + + { + let res = handle + .read_interrupt(self.read_endpoint, &mut self.read_buf.data, timeout) + .unwrap_or(0); + self.read_buf.len = res; + if self.read_buf.len != 0 { + let mut controller_state_handle = self.state.controller_state.lock().unwrap(); + (self.read_callback)(&self.read_buf, controller_state_handle.deref_mut()); + } + } + + // Led loop + { + let mut led_state_handle = self.state.led_state.lock().unwrap(); + (self.led_callback)(&mut self.led_buf, led_state_handle.deref_mut()); + if self.led_buf.len != 0 { + let res = handle + .write_interrupt(self.led_endpoint, &self.led_buf.data, timeout) + .unwrap_or(0); + if res == self.led_buf.len + 1 { + self.led_buf.len = 0; + } + } } } + + fn teardown(&mut self) { + let handle = self.handle.as_mut().unwrap(); + handle.release_interface(0).ok(); + } } diff --git a/src-tauri/src/slider_io/device_job.rs b/src-tauri/src/slider_io/device_job.rs deleted file mode 100644 index 073a8c3..0000000 --- a/src-tauri/src/slider_io/device_job.rs +++ /dev/null @@ -1,170 +0,0 @@ -use std::{error, ops::DerefMut, time::Duration}; - -use rusb::{self, DeviceHandle, GlobalContext}; - -use crate::slider_io::{ - config::DeviceMode, - controller_state::{ControllerState, FullState, LedState}, - hid, - worker::{Job, Worker}, -}; - -pub struct Buffer { - pub data: [u8; 128], - pub len: usize, -} - -impl Buffer { - pub fn new() -> Self { - Buffer { - data: [0; 128], - len: 0, - } - } - - fn slice(&self) -> &[u8] { - &self.data[0..self.len] - } -} - -type HidReadCallback = fn(&Buffer, &mut ControllerState) -> (); -type HidLedCallback = fn(&mut Buffer, &mut LedState) -> (); - -pub struct HidDeviceJob { - state: FullState, - vid: u16, - pid: u16, - read_endpoint: u8, - led_endpoint: u8, - - read_callback: HidReadCallback, - read_buf: Buffer, - - led_callback: HidLedCallback, - led_buf: Buffer, - - handle: Option>, -} - -impl HidDeviceJob { - fn new( - state: FullState, - vid: u16, - pid: u16, - read_endpoint: u8, - led_endpoint: u8, - read_callback: HidReadCallback, - led_callback: HidLedCallback, - ) -> Self { - Self { - state, - vid, - pid, - read_endpoint, - led_endpoint, - read_callback, - read_buf: Buffer::new(), - led_callback, - led_buf: Buffer::new(), - handle: None, - } - } - - pub fn from_config(mode: &DeviceMode, state: &FullState) -> Self { - match mode { - DeviceMode::Yuancon => Self::new( - state.clone(), - 0x1973, - 0x2001, - 0x81, - 0x02, - |buf, controller_state| { - if buf.len != 34 { - return; - } - - controller_state - .ground_state - .clone_from_slice(&buf.data[2..34]); - for i in 0..6 { - controller_state.air_state[i ^ 1] = if buf.data[0] & (1 << i) == 0 { 1 } else { 0 }; - } - for i in 0..3 { - controller_state.extra_state[i] = if buf.data[1] & (1 << i) == 0 { 1 } else { 0 }; - } - }, - |buf, led_state| { - if !led_state.dirty { - return; - } - buf.len = 31 * 2; - buf - .data - .chunks_mut(2) - .take(31) - .zip(led_state.led_state.chunks(3).rev()) - .for_each(|(buf_chunk, state_chunk)| { - buf_chunk[0] = (state_chunk[0] << 3 & 0xe0) | (state_chunk[2] >> 3); - buf_chunk[1] = (state_chunk[1] & 0xf8) | (state_chunk[0] >> 5); - }); - led_state.dirty = false; - }, - ), - _ => panic!("Not implemented"), - } - } - - fn setup_impl(&mut self) -> Result<(), Box> { - let mut handle = rusb::open_device_with_vid_pid(self.vid, self.pid).unwrap(); - if handle.kernel_driver_active(0).unwrap_or(false) { - handle.detach_kernel_driver(0)?; - } - handle.set_active_configuration(1)?; - handle.claim_interface(0)?; - self.handle = Some(handle); - Ok(()) - } -} - -const timeout: Duration = Duration::from_millis(20); - -impl Job for HidDeviceJob { - fn setup(&mut self) { - self.setup_impl().unwrap(); - } - - fn tick(&mut self) { - // Input loop - let handle = self.handle.as_mut().unwrap(); - - { - let res = handle - .read_interrupt(self.read_endpoint, &mut self.read_buf.data, timeout) - .unwrap_or(0); - self.read_buf.len = res; - if self.read_buf.len != 0 { - let mut controller_state_handle = self.state.controller_state.lock().unwrap(); - (self.read_callback)(&self.read_buf, controller_state_handle.deref_mut()); - } - } - - // Led loop - { - let mut led_state_handle = self.state.led_state.lock().unwrap(); - (self.led_callback)(&mut self.led_buf, led_state_handle.deref_mut()); - if self.led_buf.len != 0 { - let res = handle - .write_interrupt(self.led_endpoint, &self.led_buf.data, timeout) - .unwrap_or(0); - if res == self.led_buf.len + 1 { - self.led_buf.len = 0; - } - } - } - } - - fn teardown(&mut self) { - let handle = self.handle.as_mut().unwrap(); - handle.release_interface(0).ok(); - } -} diff --git a/src-tauri/src/slider_io/hid.rs b/src-tauri/src/slider_io/hid.rs deleted file mode 100644 index a12f3b8..0000000 --- a/src-tauri/src/slider_io/hid.rs +++ /dev/null @@ -1,124 +0,0 @@ -use std::{ - error, - sync::{ - atomic::{AtomicBool, Ordering}, - Arc, Mutex, - }, - time::Duration, -}; - -use rusb::{self, UsbContext}; - -const timeout: Duration = Duration::from_millis(20); - -pub struct Buffer { - pub data: [u8; 128], - pub len: usize, -} - -impl Buffer { - pub fn new() -> Self { - Buffer { - data: [0; 128], - len: 0, - } - } - - fn slice(&self) -> &[u8] { - &self.data[0..self.len] - } -} - -pub fn poll_controller( - vid: u16, - pid: u16, - read_callback: impl Fn(&Buffer) -> (), - write_callback: impl Fn(&mut Buffer) -> (), - // write_buf: Arc>, - stop: &AtomicBool, -) -> Result<(), Box> { - // println!("Getting context"); - // let mut context = rusb::Context::new().unwrap(); - // println!("Getting devices"); - // let devices: Vec> = context - // .devices() - // .unwrap() - // .iter() - // .filter(|d| { - // d.device_descriptor() - // .map(|d| d.vendor_id() == vid && d.product_id() == pid) - // .unwrap_or(false) - // }) - // .collect(); - // println!("Found {:?}", devices); - // let mut handle = devices[0].open().unwrap(); - - let mut handle = rusb::open_device_with_vid_pid(vid, pid).unwrap(); - println!("Found device {:?}", handle); - // .ok_or("Cannot find usb device".to_string())?; - - // let device = handle.device(); - if handle.kernel_driver_active(0).unwrap_or(false) { - println!("Disabling kernel driver"); - handle.detach_kernel_driver(0)?; - } - - println!("Kernel driver OK"); - handle.set_active_configuration(1)?; - println!("Configuration OK"); - handle.claim_interface(0)?; - println!("Interface OK"); - - let mut in_buf = Buffer::new(); - let mut led_buf = Buffer::new(); - loop { - { - // Read loop - - let res = handle - .read_interrupt(0x81, &mut in_buf.data, timeout) - .unwrap_or(0); - - in_buf.len = res; - - // println!("Read {:?}", res); - // println!("Data {:?}", in_buf.data); - - if in_buf.len != 0 { - read_callback(&in_buf); - } - } - - { - // Write loop - write_callback(&mut led_buf); - if led_buf.len != 0 { - let res = handle - .write_interrupt(0x02, led_buf.slice(), timeout) - .unwrap_or(0); - - // println!( - // "Sent {:?} {:?} {:?}", - // led_buf.len, - // res, - // led_buf.slice().len() - // ); - if res == led_buf.len + 1 { - led_buf.len = 0; - } - } - } - - { - if stop.load(Ordering::SeqCst) { - break; - } - } - } - - println!("HID thread stopped"); - - handle.release_interface(0)?; - - Ok(()) -} diff --git a/src-tauri/src/slider_io/manager.rs b/src-tauri/src/slider_io/manager.rs index e75610e..b8c8e6a 100644 --- a/src-tauri/src/slider_io/manager.rs +++ b/src-tauri/src/slider_io/manager.rs @@ -1,6 +1,5 @@ use crate::slider_io::{ - config::Config, controller_state::FullState, device::DeviceThread, device_job::HidDeviceJob, - led::LedThread, worker::Worker, + config::Config, controller_state::FullState, device::HidDeviceJob, led::LedThread, worker::Worker, }; pub struct Manager { diff --git a/src-tauri/src/slider_io/mod.rs b/src-tauri/src/slider_io/mod.rs index 4abd2c5..549a2fe 100644 --- a/src-tauri/src/slider_io/mod.rs +++ b/src-tauri/src/slider_io/mod.rs @@ -1,8 +1,6 @@ pub mod config; pub mod controller_state; pub mod device; -pub mod device_job; -pub mod hid; pub mod keyboard; pub mod led; pub mod manager;