autocommit 2022-03-09 14:01:21 CET
This commit is contained in:
parent
aa0cb94143
commit
4df6b559b7
32 changed files with 1121 additions and 172 deletions
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue