From 9d68409a8aed3f0d140212ad6d6a779706f7d64f Mon Sep 17 00:00:00 2001 From: Frank Villaro-Dixon Date: Tue, 7 May 2024 21:02:22 +0200 Subject: [PATCH] events async Signed-off-by: Frank Villaro-Dixon --- src/hid.rs | 189 +++++++++++++++++++++++++++++----------------------- src/main.rs | 20 ++++-- 2 files changed, 120 insertions(+), 89 deletions(-) diff --git a/src/hid.rs b/src/hid.rs index e7230e1..1d062a0 100644 --- a/src/hid.rs +++ b/src/hid.rs @@ -5,12 +5,14 @@ use nix::{ sys::epoll, }; use std::{ + collections::VecDeque, io, os::fd::{AsRawFd, FromRawFd, OwnedFd}, }; use evdev; +const LASER_POINTER_MAX: i32 = 121; #[derive(Debug)] pub enum Beo5Event { LaserPosition(f32), @@ -28,10 +30,7 @@ pub enum Beo5Event { pub struct Beo5Device { device: evdev::Device, -} - -pub struct Beo5DeviceEvents<'a> { - events: Option>, + evts_in_queue: VecDeque, } impl Beo5Device { @@ -46,15 +45,17 @@ impl Beo5Device { ); // XXX Is there a better way than this into_iter.nth.unwrap ? let mut d = devices.into_iter().nth(i).unwrap(); + //println!("Using device: {}", d.name().unwrap()); + //println!(">> {}", d.physical_path().unwrap()); - // From evdev's example let raw_fd = d.as_raw_fd(); + d.grab().unwrap(); // Set nonblocking - nix::fcntl::fcntl(raw_fd, FcntlArg::F_SETFL(OFlag::O_NONBLOCK)); //("Couldn't set nonblocking"); + nix::fcntl::fcntl(raw_fd, FcntlArg::F_SETFL(OFlag::O_NONBLOCK)).unwrap(); // Create epoll handle and attach raw_fd - //let epoll_fd = epoll::epoll_create1(epoll::EpollCreateFlags::EPOLL_CLOEXEC)?; let epoll_fd = epoll::epoll_create1(epoll::EpollCreateFlags::EPOLL_CLOEXEC).ok()?; + println!("epoll_fd: {epoll_fd}."); let epoll_fd = unsafe { OwnedFd::from_raw_fd(epoll_fd) }; let mut event = epoll::EpollEvent::new(epoll::EpollFlags::EPOLLIN, 0); epoll::epoll_ctl( @@ -65,95 +66,117 @@ impl Beo5Device { ) .unwrap(); - //let events = d.fetch_events().unwrap(); + //loop {} - return Some(Beo5Device { device: d }); + return Some(Beo5Device { + device: d, + evts_in_queue: VecDeque::new(), + }); } } println!("Couldn't find a Beosound 5 device! Is the Beosound 5 kernel module loaded + device connected?"); None } - pub fn fetch_events(&self) -> io::Result { - let events = &mut self.device.fetch_events()?; - Ok(Beo5DeviceEvents { - events: Some(events), - }) + pub fn get_event_nonblocking(&mut self) -> Option { + let evts = self.device.fetch_events(); + + match evts { + Ok(evts) => { + println!("Will iterate!"); + for ev in evts { + match ev.kind() { + evdev::InputEventKind::Synchronization(_) => {} + _ => { + self.evts_in_queue.push_back(ev); + } + } + } + } + Err(x) => { + if (x.kind() == std::io::ErrorKind::WouldBlock) { + // Wait forever for bytes available on raw_fd + let mut events = [epoll::EpollEvent::empty(); 2]; + epoll::epoll_wait(8, &mut events, -1); + } else { + println!("Error getting event: {x} - {}", x.kind()); + //panic!("Error getting event: {x}"); + } + } + } + let ev = self.evts_in_queue.pop_front(); + if ev.is_some() { + return Beo5Device::parse_event(ev.unwrap()); + } + return None; } - pub fn get_event_nonblocking(&mut self) -> Option { - if self.events.is_none() { - self.events = Some(self.device.fetch_events().unwrap()); - } - - for ev in self.events.unwrap().into_iter() { - println!("Beosound event: {ev:?}"); - // XXX What happens with the other events in the iterator? - match ev.kind() { - // Look at the beosound 5 kernel module for the correct event codes - evdev::InputEventKind::RelAxis(axis) => { - match axis { - evdev::RelativeAxisType::REL_Y => { - return Some(Beo5Event::SelectionWheelRel(ev.value())); - } - evdev::RelativeAxisType::REL_Z => { - return Some(Beo5Event::VolumeWheelRel(ev.value())); - } - // Shouldn't be any more relative axe - _ => {} + fn parse_event(ev: evdev::InputEvent) -> Option { + println!("Beosound event: {ev:?}"); + // XXX What happens with the other events in the iterator? + match ev.kind() { + // Look at the beosound 5 kernel module for the correct event codes + evdev::InputEventKind::RelAxis(axis) => { + match axis { + evdev::RelativeAxisType::REL_Y => { + return Some(Beo5Event::SelectionWheelRel(ev.value())); } - } - evdev::InputEventKind::AbsAxis(axis) => { - match axis { - evdev::AbsoluteAxisType::ABS_X => { - let pos_pct = ev.value() as f32 / 255.0; - return Some(Beo5Event::LaserPosition(pos_pct)); - } - // Shouldn't be any other absolute axe - _ => {} + evdev::RelativeAxisType::REL_Z => { + return Some(Beo5Event::VolumeWheelRel(ev.value())); } + // Shouldn't be any more relative axe + _ => {} } - evdev::InputEventKind::Switch(switch) => { - /* - match switch { - evdev::SwitchType::LE=> { - if ev.value() == 1 { - return Beo5Event::RightButtonPressed; - } else { - return Beo5Event::RightButtonReleased; - } - } - evdev::Switch::SW_LEFT => { - if ev.value() == 1 { - return Beo5Event::LeftButtonPressed; - } else { - return Beo5Event::LeftButtonReleased; - } - } - evdev::Switch::SW_GO => { - if ev.value() == 1 { - return Beo5Event::GoButtonPressed; - } else { - return Beo5Event::GoButtonReleased; - } - } - evdev::Switch::SW_POWER => { - if ev.value() == 1 { - return Beo5Event::PowerButtonPressed; - } else { - return Beo5Event::PowerButtonReleased; - } - } - // Shouldn't be any other switches - _ => { - panic!("Unknown switch event: {ev:?}") - } - } - */ - } - _ => {} //SYN et al } - return None; + evdev::InputEventKind::AbsAxis(axis) => { + match axis { + evdev::AbsoluteAxisType::ABS_X => { + let pos_pct = (ev.value() as f32 / LASER_POINTER_MAX as f32).min(1.0); + return Some(Beo5Event::LaserPosition(pos_pct)); + } + // Shouldn't be any other absolute axe + _ => {} + } + } + evdev::InputEventKind::Switch(switch) => { + /* + match switch { + evdev::SwitchType::LE=> { + if ev.value() == 1 { + return Beo5Event::RightButtonPressed; + } else { + return Beo5Event::RightButtonReleased; + } + } + evdev::Switch::SW_LEFT => { + if ev.value() == 1 { + return Beo5Event::LeftButtonPressed; + } else { + return Beo5Event::LeftButtonReleased; + } + } + evdev::Switch::SW_GO => { + if ev.value() == 1 { + return Beo5Event::GoButtonPressed; + } else { + return Beo5Event::GoButtonReleased; + } + } + evdev::Switch::SW_POWER => { + if ev.value() == 1 { + return Beo5Event::PowerButtonPressed; + } else { + return Beo5Event::PowerButtonReleased; + } + } + // Shouldn't be any other switches + _ => { + panic!("Unknown switch event: {ev:?}") + } + } + */ + } + _ => {} //SYN et al } return None; } diff --git a/src/main.rs b/src/main.rs index 577cb6c..fb91200 100644 --- a/src/main.rs +++ b/src/main.rs @@ -51,7 +51,7 @@ fn run( let beo = ui::Beo::new(); for app in &beo.apps { - println!("{}", app.name()); + println!(">> {}", app.name()); } let start = Instant::now(); @@ -65,15 +65,16 @@ fn run( let mut font_texture_to_show: Option = None; let mut beo_device = hid::Beo5Device::new_autodiscover().expect("Couldn't find Beo5 device"); + /* loop { - if let Some(ev) = beo_device.get_event_nonblocking() { - println!("HW Event: {:?}", ev); - } else { - break; - } + let ev = beo_device.get_event_nonblocking(); } + */ + + let mut t = 0; el.run(move |event, _, control_flow| { + t = t + 1; *control_flow = ControlFlow::Poll; let hw_event = beo_device.get_event_nonblocking(); @@ -162,6 +163,13 @@ fn run( perf.update(dt); draw_main_menu(&mut canvas, &fonts, &beo); + + let mut paint = Paint::color(Color::hex("B7410E")); + paint.set_font(&[fonts.bold]); + paint.set_text_baseline(Baseline::Top); + paint.set_text_align(Align::Right); + let _ = canvas.fill_text(size.width as f32 - 10.0, 10.0, format!("{t}"), &paint); + /* draw_baselines(&mut canvas, &fonts, 5.0, 50.0, font_size); draw_alignments(&mut canvas, &fonts, 120.0, 200.0, font_size);