WIP: Work on Infrastructure to Listen to the Touchinfo
This commit is contained in:
parent
1c1d98ca48
commit
b5e5f99906
4 changed files with 170 additions and 13 deletions
|
@ -5,7 +5,7 @@ use evdev::{Device, Key};
|
|||
use std::{thread, time};
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
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<dyn std::error::Error>> {
|
|||
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;
|
||||
}
|
||||
_ => {}
|
||||
|
|
|
@ -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<PoisonError<MutexGuard<'_, TouchbarMode>>> for TouchbarError {
|
||||
fn from(_: PoisonError<MutexGuard<TouchbarMode>>) -> Self {
|
||||
Self::PoisionCantChangeMode
|
||||
}
|
||||
}
|
||||
impl From<PoisonError<MutexGuard<'_, bool>>> for TouchbarError {
|
||||
fn from(_: PoisonError<MutexGuard<bool>>) -> Self {
|
||||
Self::PoisionCantSendEvent
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Mutex<hid::Handle>>,
|
||||
mode: Mutex<TouchbarMode>,
|
||||
listeners: Arc<Mutex<Vec<Box<dyn TouchbarEventListener>>>>,
|
||||
listener_handle: Option<JoinHandle<()>>,
|
||||
listener_running: Arc<Mutex<bool>>,
|
||||
}
|
||||
|
||||
impl TouchbarImp {
|
||||
pub fn new(hid_manager: &hid::Manager) -> Result<Self, TouchbarError> {
|
||||
Self::from(hid_manager, TouchbarMode::Special)
|
||||
}
|
||||
|
||||
pub fn from(
|
||||
hid_manager: &hid::Manager,
|
||||
default_mode: TouchbarMode,
|
||||
) -> Result<Self, TouchbarError> {
|
||||
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<dyn super::TouchbarEventListener>) {
|
||||
//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!()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<dyn TouchbarEventListener>);
|
||||
fn start_listening_input(&mut self) -> Result<(), TouchbarError>;
|
||||
fn stop_listening_input(&mut self) -> Result<(), TouchbarError>;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue