1
0
Fork 0
forked from wry/wry

autocommit 2022-03-09 14:01:21 CET

This commit is contained in:
Julian Orth 2022-03-09 14:01:21 +01:00
parent aa0cb94143
commit 4df6b559b7
32 changed files with 1121 additions and 172 deletions

View file

@ -1,12 +1,19 @@
mod input;
mod monitor;
use crate::async_engine::AsyncFd;
use crate::dbus::DbusError;
use crate::libinput::device::RegisteredDevice;
use crate::libinput::{LibInput, LibInputAdapter, LibInputError};
use crate::logind::{LogindError, Session};
use crate::{AsyncQueue, ErrorFmt, State, Udev};
use crate::udev::{UdevError, UdevMonitor};
use crate::utils::copyhashmap::CopyHashMap;
use crate::{AsyncQueue, CloneCell, ErrorFmt, NumCell, State, Udev};
use std::cell::{Cell, RefCell};
use std::ffi::{CStr, CString};
use std::rc::Rc;
use thiserror::Error;
use uapi::OwnedFd;
use crate::async_engine::{AsyncFd, FdStatus};
use crate::libinput::{LibInput, LibInputError};
use crate::udev::{UdevError, UdevMonitor};
use uapi::{c, OwnedFd};
#[derive(Debug, Error)]
pub enum MetalError {
@ -16,12 +23,14 @@ pub enum MetalError {
LogindSession(#[source] LogindError),
#[error("Could not take control of the logind session")]
TakeControl(#[source] LogindError),
#[error("Could not enumerate devices")]
Enumerate(#[source] Box<Self>),
#[error(transparent)]
Udev(#[from] UdevError),
#[error(transparent)]
LibInput(#[from] LibInputError),
#[error("Dupfd failed")]
Dup(#[source] std::io::Error),
Dup(#[source] crate::utils::oserror::OsError),
}
pub async fn run(state: Rc<State>) {
@ -30,6 +39,18 @@ pub async fn run(state: Rc<State>) {
}
}
struct MetalBackend {
state: Rc<State>,
udev: Rc<Udev>,
monitor: Rc<UdevMonitor>,
monitor_fd: AsyncFd,
libinput: Rc<LibInput>,
libinput_fd: AsyncFd,
device_holder: Rc<DeviceHolder>,
session: Session,
ids: NumCell<u64>,
}
async fn run_(state: Rc<State>) -> Result<(), MetalError> {
let socket = match state.dbus.system() {
Ok(s) => s,
@ -39,90 +60,83 @@ async fn run_(state: Rc<State>) -> Result<(), MetalError> {
Ok(s) => s,
Err(e) => return Err(MetalError::LogindSession(e)),
};
// if let Err(e) = session.take_control().await {
// return Err(MetalError::TakeControl(e));
// }
if let Err(e) = session.take_control().await {
return Err(MetalError::TakeControl(e));
}
let device_holder = Rc::new(DeviceHolder {
input_devices: Default::default(),
input_devices_: Default::default(),
});
let udev = Rc::new(Udev::new()?);
let monitor = Rc::new(udev.create_monitor()?);
monitor.add_match_subsystem_devtype(Some("input"), None)?;
monitor.enable_receiving()?;
let libinput = Rc::new(LibInput::new()?);
let libinput = Rc::new(LibInput::new(device_holder.clone())?);
let monitor_fd = match uapi::fcntl_dupfd_cloexec(monitor.fd(), 0) {
Ok(m) => state.eng.fd(&Rc::new(m)).unwrap(),
Err(e) => return Err(MetalError::Dup(e.into())),
};
let libinput_fd = match uapi::fcntl_dupfd_cloexec(libinput.fd(), 0) {
Ok(m) => state.eng.fd(&Rc::new(m)).unwrap(),
Err(e) => return Err(MetalError::Dup(e.into())),
};
let metal = Rc::new(MetalBackend {
state: state.clone(),
udev,
monitor,
monitor_fd,
libinput,
libinput_fd,
device_holder,
session,
ids: Default::default(),
});
let _monitor = state.eng.spawn(metal.clone().monitor_devices());
let mut queue = AsyncQueue::<String>::new();
let _events = state.eng.spawn(metal.clone().handle_libinput_events());
if let Err(e) = metal.enumerate_devices() {
return Err(MetalError::Enumerate(Box::new(e)));
}
let queue = AsyncQueue::<String>::new();
queue.pop().await;
Ok(())
// let libinput_fd = match uapi::fcntl_dupfd_cloexec(monitor.fd(), 0) {
// Ok(m) => m,
// Err(e) => Err(MetalError::Dup(e.into())),
// };
// let mut enumerate = udev.create_enumerate()?;
// enumerate.add_match_subsystem("input")?;
// enumerate.scan_devices()?;
// let mut entry_opt = enumerate.get_list_entry()?;
// while let Some(entry) = entry_opt {
// let device = udev.create_device_from_syspath(entry.name()?)?;
// if device.sysname()?.to_bytes().starts_with(b"event") {
// let devnode = device.devnode()?;
// }
// }
}
struct MetalBackend {
state: Rc<State>,
udev: Rc<Udev>,
monitor: Rc<UdevMonitor>,
monitor_fd: AsyncFd,
libinput: Rc<LibInput>,
libinput_fd: AsyncFd,
struct MetalDevice {
slot: usize,
device_id: u64,
devnum: c::dev_t,
fd: CloneCell<Option<Rc<OwnedFd>>>,
inputdev: Cell<Option<RegisteredDevice>>,
devnode: CString,
sysname: CString,
}
struct DeviceHolder {
input_devices: CopyHashMap<c::dev_t, Rc<MetalDevice>>,
input_devices_: RefCell<Vec<Option<Rc<MetalDevice>>>>,
}
impl LibInputAdapter for DeviceHolder {
fn open(&self, path: &CStr) -> Result<OwnedFd, LibInputError> {
let stat = match uapi::stat(path) {
Ok(s) => s,
Err(e) => return Err(LibInputError::Stat(e.into())),
};
match self.input_devices.get(&stat.st_rdev) {
Some(d) => match d.fd.get() {
Some(fd) => match uapi::fcntl_dupfd_cloexec(fd.raw(), 0) {
Ok(fd) => Ok(fd),
Err(e) => Err(LibInputError::DupFd(e.into())),
},
_ => Err(LibInputError::DeviceUnavailable),
},
_ => Err(LibInputError::DeviceUnavailable),
}
}
}
impl MetalBackend {
async fn monitor_devices(self: Rc<Self>) {
loop {
match self.monitor_fd.readable().await {
Err(e) => {
log::error!("Cannot wait for udev_monitor to become readable: {}", ErrorFmt(e));
break;
}
Ok(FdStatus::Err) => {
log::error!("udev_monitor fd is in an error state");
break;
}
_ => { },
}
while let Some(dev) = self.monitor.receive_device() {
log::info!("x {:?}", dev.devnode());
}
}
log::error!("Monitor task exited. Future hotplug events will be ignored.");
}
async fn handle_libinput_events(self: Rc<Self>) {
loop {
match self.libinput_fd.readable().await {
Err(e) => {
log::error!("Cannot wait for udev_monitor to become readable: {}", ErrorFmt(e));
break;
}
Ok(FdStatus::Err) => {
log::error!("udev_monitor fd is in an error state");
break;
}
_ => { },
}
self.libinput.fd()
}
log::error!("Monitor task exited. Future hotplug events will be ignored.");
fn id(&self) -> u64 {
self.ids.fetch_add(1)
}
}

View file

@ -0,0 +1,55 @@
use crate::async_engine::FdStatus;
use crate::libinput::consts::LIBINPUT_EVENT_KEYBOARD_KEY;
use crate::libinput::event::LibInputEvent;
use crate::metal::MetalBackend;
use crate::ErrorFmt;
use std::rc::Rc;
impl MetalBackend {
pub async fn handle_libinput_events(self: Rc<Self>) {
loop {
match self.libinput_fd.readable().await {
Err(e) => {
log::error!(
"Cannot wait for libinput fd to become readable: {}",
ErrorFmt(e)
);
break;
}
Ok(FdStatus::Err) => {
log::error!("libinput fd fd is in an error state");
break;
}
_ => {}
}
if let Err(e) = self.libinput.dispatch() {
log::error!("Could not dispatch libinput events: {}", ErrorFmt(e));
break;
}
while let Some(event) = self.libinput.event() {
self.handle_event(event);
}
}
log::error!("Libinput task exited. Future input events will be ignored.");
}
fn handle_event(self: &Rc<Self>, event: LibInputEvent) {
match event.ty() {
LIBINPUT_EVENT_KEYBOARD_KEY => self.handle_keyboard_event(event),
_ => {}
}
}
fn handle_keyboard_event(self: &Rc<Self>, event: LibInputEvent) {
let event = match event.keyboard_event() {
Some(event) => event,
_ => return,
};
log::info!(
"key: {}, state: {:?}, time: {}",
event.key(),
event.key_state(),
event.time_usec()
);
}
}

View file

@ -0,0 +1,131 @@
use crate::async_engine::FdStatus;
use crate::dbus::TRUE;
use crate::metal::{MetalBackend, MetalDevice, MetalError};
use crate::udev::UdevDevice;
use crate::ErrorFmt;
use std::rc::Rc;
impl MetalBackend {
pub async fn monitor_devices(self: Rc<Self>) {
loop {
match self.monitor_fd.readable().await {
Err(e) => {
log::error!(
"Cannot wait for udev_monitor to become readable: {}",
ErrorFmt(e)
);
break;
}
Ok(FdStatus::Err) => {
log::error!("udev_monitor fd is in an error state");
break;
}
_ => {}
}
while let Some(dev) = self.monitor.receive_device() {
log::info!("x {:?}", dev.devnode());
}
}
log::error!("Monitor task exited. Future hotplug events will be ignored.");
}
pub fn enumerate_devices(self: &Rc<Self>) -> Result<(), MetalError> {
let mut enumerate = self.udev.create_enumerate()?;
enumerate.add_match_subsystem("input")?;
enumerate.scan_devices()?;
let mut entry_opt = enumerate.get_list_entry()?;
while let Some(entry) = entry_opt.take() {
'inner: {
let device = match self.udev.create_device_from_syspath(entry.name()) {
Ok(d) => d,
_ => break 'inner,
};
let sysname = match device.sysname() {
Ok(s) => s,
_ => break 'inner,
};
if sysname.to_bytes().starts_with(b"event") {
self.add_input_device(&device);
}
}
entry_opt = entry.next();
}
Ok(())
}
fn add_input_device(self: &Rc<Self>, dev: &UdevDevice) {
let slf = self.clone();
let device_id = self.id();
let devnum = dev.devnum();
let devnode = match dev.devnode() {
Ok(n) => n,
Err(e) => {
log::error!("Could not retrieve devnode of udev device: {}", ErrorFmt(e));
return;
}
};
let sysname = match dev.sysname() {
Ok(n) => n,
Err(e) => {
log::error!("Could not retrieve sysname of udev device: {}", ErrorFmt(e));
return;
}
};
let mut slots = self.device_holder.input_devices_.borrow_mut();
let slot = 'slot: {
for (i, s) in slots.iter().enumerate() {
if s.is_none() {
break 'slot i;
}
}
slots.push(None);
slots.len() - 1
};
let dev = Rc::new(MetalDevice {
slot,
device_id,
devnum,
fd: Default::default(),
inputdev: Default::default(),
devnode: devnode.to_owned(),
sysname: sysname.to_owned(),
});
slots[slot] = Some(dev.clone());
self.device_holder.input_devices.set(devnum, dev);
self.session.get_device(devnum, move |res| {
let id = &slf.device_holder.input_devices;
let mut slots = slf.device_holder.input_devices_.borrow_mut();
let dev = 'dev: {
if let Some(dev) = id.get(&devnum) {
if dev.device_id == device_id {
break 'dev dev;
}
}
return;
};
let res = match res {
Ok(r) => r,
Err(e) => {
log::error!("Could not take control of input device: {}", ErrorFmt(e));
slots[dev.slot] = None;
id.remove(&devnum);
return;
}
};
if res.inactive == TRUE {
return;
}
dev.fd.set(Some(res.fd.clone()));
let inputdev = match slf.libinput.open(dev.devnode.as_c_str()) {
Ok(d) => d,
Err(_) => {
slots[dev.slot] = None;
id.remove(&devnum);
return;
}
};
inputdev.device().set_slot(slot);
dev.inputdev.set(Some(inputdev));
});
}
}