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) { 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) -> 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, 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)); }); } }