From b5e5f99906c8414719a828055fe406ae2c0ea8f2 Mon Sep 17 00:00:00 2001 From: Snoweuph Date: Sun, 5 Jan 2025 23:57:11 +0100 Subject: [PATCH] WIP: Work on Infrastructure to Listen to the Touchinfo --- drivers/simple-cider/src/main.rs | 6 +- drivers/simple-cider/src/tb/err.rs | 31 +++++++++- drivers/simple-cider/src/tb/imp.rs | 94 ++++++++++++++++++++++++++++-- drivers/simple-cider/src/tb/mod.rs | 52 ++++++++++++++++- 4 files changed, 170 insertions(+), 13 deletions(-) diff --git a/drivers/simple-cider/src/main.rs b/drivers/simple-cider/src/main.rs index db09bbe..de0c0fb 100644 --- a/drivers/simple-cider/src/main.rs +++ b/drivers/simple-cider/src/main.rs @@ -5,7 +5,7 @@ use evdev::{Device, Key}; use std::{thread, time}; fn main() -> Result<(), Box> { - let mut device = Device::open("/dev/input/event4")?; + let mut device = Device::open("/dev/input/event13")?; //4 normally, but with xremap its 13 on my Device let hid_manager = hid::init()?; let mut touchbar = TouchbarImp::new(&hid_manager)?; @@ -16,11 +16,11 @@ fn main() -> Result<(), Box> { if let evdev::InputEventKind::Key(key) = event.kind() { match event.value() { 0 if key == Key::KEY_FN && fn_key_pressed => { - touchbar.set_mode(tb::Mode::Special)?; + touchbar.set_mode(tb::TouchbarMode::Special)?; fn_key_pressed = false; } 1 if key == Key::KEY_FN && !fn_key_pressed => { - touchbar.set_mode(tb::Mode::Function)?; + touchbar.set_mode(tb::TouchbarMode::Function)?; fn_key_pressed = true; } _ => {} diff --git a/drivers/simple-cider/src/tb/err.rs b/drivers/simple-cider/src/tb/err.rs index ff1407b..c3d0962 100644 --- a/drivers/simple-cider/src/tb/err.rs +++ b/drivers/simple-cider/src/tb/err.rs @@ -1,10 +1,18 @@ -use std::fmt; +use std::{ + fmt, + sync::{MutexGuard, PoisonError}, +}; + +use super::TouchbarMode; #[derive(Debug)] pub enum TouchbarError { DeviceNotFound, CantOpenDevice, WriteError, + PoisionCantChangeMode, + PoisionCantSendEvent, + AlreadyListening, } impl fmt::Display for TouchbarError { @@ -13,8 +21,29 @@ impl fmt::Display for TouchbarError { TouchbarError::DeviceNotFound => write!(f, "Touchbar device not found"), TouchbarError::CantOpenDevice => write!(f, "Cannot open the Touchbar device"), TouchbarError::WriteError => write!(f, "Error writing to the Touchbar device"), + TouchbarError::PoisionCantChangeMode => write!( + f, + "Unable to Change Mode, because previous thread was posioned" + ), + TouchbarError::PoisionCantSendEvent => { + write!(f, "Unable to Send Event, previous thread was poisioned") + } + TouchbarError::AlreadyListening => { + write!(f, "There is Allready a Listenr Thread running.") + } } } } impl std::error::Error for TouchbarError {} + +impl From>> for TouchbarError { + fn from(_: PoisonError>) -> Self { + Self::PoisionCantChangeMode + } +} +impl From>> for TouchbarError { + fn from(_: PoisonError>) -> Self { + Self::PoisionCantSendEvent + } +} diff --git a/drivers/simple-cider/src/tb/imp.rs b/drivers/simple-cider/src/tb/imp.rs index 89815e5..e7ae9f4 100644 --- a/drivers/simple-cider/src/tb/imp.rs +++ b/drivers/simple-cider/src/tb/imp.rs @@ -1,17 +1,33 @@ -use crate::tb::{Mode, Touchbar}; - -use super::TouchbarError; +use super::{TouchbarError, TouchbarEventListener}; +use crate::tb::{Touchbar, TouchbarEvent, TouchbarMediaEvent, TouchbarMode}; +use std::{ + sync::{Arc, Mutex}, + thread::{spawn, JoinHandle}, + time::Duration, +}; const TOUCHBAR_VENDOR_ID: u16 = 0x05ac; const TOUCHBAR_PRODUCT_ID: u16 = 0x8600; const TOUCHBAR_MODE_PAYLOAD: u8 = 0x02; +const TOUCHBAR_MAX_PAYLOAD_SIZE: usize = 64; pub struct TouchbarImp { - device: hid::Handle, + device: Arc>, + mode: Mutex, + listeners: Arc>>>, + listener_handle: Option>, + listener_running: Arc>, } impl TouchbarImp { pub fn new(hid_manager: &hid::Manager) -> Result { + Self::from(hid_manager, TouchbarMode::Special) + } + + pub fn from( + hid_manager: &hid::Manager, + default_mode: TouchbarMode, + ) -> Result { let device = hid_manager .find(Some(TOUCHBAR_VENDOR_ID), Some(TOUCHBAR_PRODUCT_ID)) .next() @@ -19,16 +35,82 @@ impl TouchbarImp { let handle = device.open().map_err(|_| TouchbarError::CantOpenDevice)?; - Ok(TouchbarImp { device: handle }) + let mut this = TouchbarImp { + device: Arc::new(Mutex::new(handle)), + mode: Mutex::new(default_mode), + listeners: Arc::new(Mutex::new(vec![])), + listener_handle: None, + listener_running: Arc::new(Mutex::new(false)), + }; + this.set_mode(default_mode)?; + + Ok(this) } } impl Touchbar for TouchbarImp { - fn set_mode(&mut self, mode: Mode) -> Result<(), TouchbarError> { + fn set_mode(&mut self, mode: TouchbarMode) -> Result<(), TouchbarError> { + let mut mode_guard = self.mode.lock()?; + *mode_guard = mode; + + //TODO: Do real Error handeling here self.device + .lock() + .unwrap() .data() .write([TOUCHBAR_MODE_PAYLOAD, mode as u8]) .map_err(|_| TouchbarError::WriteError)?; Ok(()) } + + fn add_listener(&mut self, listener: Box) { + //TODO: Remove Unwrap with Real Error handeling + self.listeners.lock().unwrap().push(listener); + } + + fn start_listening_input(&mut self) -> Result<(), TouchbarError> { + let mut running = self.listener_running.lock()?; + if *running { + return Err(TouchbarError::AlreadyListening); + } + + *running = true; + + let data = Arc::clone(&self.device); + let running = Arc::clone(&self.listener_running); + let listeners = Arc::clone(&self.listeners); + + self.listener_handle = Some(spawn(move || { + //TODO: Real Error Handeling instead of unwraps + while *running.lock().unwrap() { + //TODO: replace unwrap with real error handeling + let device_lock = data.lock().unwrap(); + match device_lock.data().read( + &mut [0u8; TOUCHBAR_MAX_PAYLOAD_SIZE], + Duration::from_millis(300000), // 5 minutes + ) { + Ok(data) => { + //TODO: Parse Event + let event = TouchbarEvent::Media(TouchbarMediaEvent::VolumeUp); + //TODO: remove unwrap with real error Handeling + let listener_lock = listeners.lock().unwrap(); + for listener in listener_lock.iter() { + listener.on_event(event.clone()); + } + } + Err(e) => { + //TODO: Real Error Handeling + println!("Error reading data: {:?}", e); + break; + } + } + } + })); + + Ok(()) + } + + fn stop_listening_input(&mut self) -> Result<(), TouchbarError> { + todo!() + } } diff --git a/drivers/simple-cider/src/tb/mod.rs b/drivers/simple-cider/src/tb/mod.rs index 2c976dd..30ae57b 100644 --- a/drivers/simple-cider/src/tb/mod.rs +++ b/drivers/simple-cider/src/tb/mod.rs @@ -1,15 +1,61 @@ mod err; mod imp; + pub use err::*; pub use imp::*; -pub enum Mode { +#[derive(Clone, Copy)] +pub enum TouchbarMode { EscOnly = 0x00, Function = 0x01, Special = 0x02, Off = 0x03, } -pub trait Touchbar { - fn set_mode(&mut self, mode: Mode) -> Result<(), TouchbarError>; +#[derive(Clone, Copy)] +pub enum TouchbarEvent { + Esc, + Function(TouchbarFunctionEvent), + BrightnessDown, + BrightnessUp, + BacklightDown, + BacklightUp, + Media(TouchbarMediaEvent), +} + +#[derive(Clone, Copy)] +pub enum TouchbarFunctionEvent { + F1, + F2, + F3, + F4, + F5, + F6, + F7, + F8, + F9, + F10, + F11, + F12, +} + +#[derive(Clone, Copy)] +pub enum TouchbarMediaEvent { + SkipBack, + PauseResume, + SkipForward, + MuteVolume, + VolumeDown, + VolumeUp, +} + +pub trait TouchbarEventListener: Send { + fn on_event(&self, event: TouchbarEvent); +} + +pub trait Touchbar { + fn set_mode(&mut self, mode: TouchbarMode) -> Result<(), TouchbarError>; + fn add_listener(&mut self, listener: Box); + fn start_listening_input(&mut self) -> Result<(), TouchbarError>; + fn stop_listening_input(&mut self) -> Result<(), TouchbarError>; }