diff --git a/src/input/manager.rs b/src/input/manager.rs index 269ac76..f9b1683 100644 --- a/src/input/manager.rs +++ b/src/input/manager.rs @@ -195,6 +195,7 @@ impl Manager { } } + /// Manage events generated by various components async fn events_loop(&mut self) -> Result<(), Box> { // Loop and listen for command events while let Some(cmd) = self.rx.recv().await { @@ -428,15 +429,10 @@ impl Manager { log::debug!("Starting input manager task..."); let _ = tokio::join!( - // Discover all (initial) devices Self::discover_all_devices(&cmd_tx_all_devices), - // Watch for IIO device events Self::watch_iio_devices(cmd_tx_iio), - // Watch for iio and other devices - Self::watch_hidraw_devices(cmd_tx_hidraw, &mut watcher_rx), - // Create a DBus interface + Self::watch_devnodes(cmd_tx_hidraw, &mut watcher_rx), Self::listen_on_dbus(dbus_for_listen_on_dbus, tx_for_listen_on_dbus), - // Manage events generated by other tasks self.events_loop() ); @@ -762,300 +758,88 @@ impl Manager { // If the CompositeDevice only allows a maximum number of source devices, // check to see if that limit has been reached. If that limit is reached, // then a new CompositeDevice will be created for the source device. - if let Some(max_sources) = config.maximum_sources { - // If maximum_sources is less than 1 (e.g. 0, -1) then consider - // the maximum to be 'unlimited'. - if max_sources > 0 { - // Check to see how many source devices this composite device is - // currently managing. - if let Some(sources) = self.composite_device_sources.get(composite_device) { - let sources_count = sources.len() as i32; - if sources_count >= max_sources { - log::trace!( - "{composite_device:?} maximum source devices reached: {max_sources}. Skipping." - ); - continue; - } - } + // If maximum_sources is less than 1 (e.g. 0, -1) then consider + // the maximum to be 'unlimited'. + if let Some(max_sources) = config + .maximum_sources + .filter(|max_sources| *max_sources > 0) + { + // Check to see how many source devices this composite device is + // currently managing. + if self + .composite_device_sources + .get(composite_device) + .map_or(false, |sources| (sources.len() as i32) >= max_sources) + { + log::trace!( + "{composite_device:?} maximum source devices reached: {max_sources}. Skipping." + ); + continue; } } // Check if this device matches any source udev configs of the running // CompositeDevice. - for source_device in config.source_devices.iter() { - log::trace!("Checking if existing composite device is missing udev device {id}"); - let Some(udev_config) = source_device.udev.as_ref() else { - continue; - }; - if !config.has_matching_udev(&device, udev_config) { - continue; - } - - // Check if the device has already been used in this config or not, - // stop here if the device must be unique. - if let Some(sources) = self.composite_device_sources.get(composite_device) { - for source in sources { - if source != source_device { - continue; - } - if let Some(ignored) = source_device.ignore { - if ignored { - log::debug!( - "Ignoring device {:?}, not adding to composite device: {}", - source_device, - composite_device - ); - break 'start; - } - } - if let Some(unique) = source_device.clone().unique { - if unique { - log::trace!( - "Found unique device {:?}, not adding to composite device {}", - source_device, - composite_device - ); - break 'start; - } - // Default to being unique - } else { - log::trace!( - "Found unique device {:?}, not adding to composite device {}", - source_device, - composite_device - ); - break 'start; - } - } - } - - log::info!("Found missing device, adding source device {id:?} to existing composite device: {composite_device:?}"); - let client = self.composite_devices.get(composite_device.as_str()); - if client.is_none() { - log::error!("No existing composite device found for key {composite_device:?}"); - continue; - } - self.add_device_to_composite_device(device, client.unwrap()) - .await?; - self.source_devices_used - .insert(id.clone(), composite_device.clone()); - let composite_id = composite_device.clone(); - if !self.composite_device_sources.contains_key(&composite_id) { - self.composite_device_sources - .insert(composite_id.clone(), Vec::new()); - } - let sources = self - .composite_device_sources - .get_mut(&composite_id) - .unwrap(); - sources.push(source_device.clone()); - self.source_devices.insert(id, source_device.clone()); - - return Ok(()); - } - - // TODO: Consolidate these - match device.subsystem().as_str() { - "input" => { - log::trace!( - "Checking if existing composite device is missing evdev device: {:?}", - device.name() - ); - for source_device in config.source_devices.iter() { - let Some(evdev_config) = source_device.evdev.as_ref() else { - log::trace!("Evdev section is empty"); - continue; - }; - if !config.has_matching_evdev(&device, evdev_config) { - continue; - } - - // Check if the device has already been used in this config or not, stop here if the device must be unique. - if let Some(sources) = self.composite_device_sources.get(composite_device) { - for source in sources { - if source != source_device { - continue; - } - if let Some(ignored) = source_device.ignore { - if ignored { - log::debug!("Ignoring device {:?}, not adding to composite device: {}", source_device, composite_device); - break 'start; - } - } - if let Some(unique) = source_device.clone().unique { - if unique { - log::trace!("Found unique device {:?}, not adding to composite device {}", source_device, composite_device); - break 'start; - } - // Default to being unique - } else { - log::trace!("Found unique device {:?}, not adding to composite device {}", source_device, composite_device); - break 'start; - } - } - } + let Some(source_device) = config.get_matching_device(&device) else { + log::trace!( + "Device {id} does not match existing device: {:?}", + config.name + ); - log::info!("Found missing device, adding source device {id:?} to existing composite device: {composite_device:?}"); - let client = self.composite_devices.get(composite_device.as_str()); - if client.is_none() { - log::error!( - "No existing composite device found for key {composite_device:?}" - ); - continue; - } - self.add_device_to_composite_device(device, client.unwrap()) - .await?; - self.source_devices_used - .insert(id.clone(), composite_device.clone()); - let composite_id = composite_device.clone(); - if !self.composite_device_sources.contains_key(&composite_id) { - self.composite_device_sources - .insert(composite_id.clone(), Vec::new()); - } - let sources = self - .composite_device_sources - .get_mut(&composite_id) - .unwrap(); - sources.push(source_device.clone()); - self.source_devices.insert(id, source_device.clone()); + continue; + }; - return Ok(()); + // Check if the device has already been used in this config or not, + // stop here if the device must be unique. + if let Some(sources) = self.composite_device_sources.get(composite_device) { + for source in sources { + if *source != source_device { + continue; } - } - "hidraw" => { - log::trace!( - "Checking if existing composite device is missing hidraw device: {:?}", - device.name() - ); - for source_device in config.source_devices.iter() { - let Some(hidraw_config) = source_device.hidraw.as_ref() else { - continue; - }; - if !config.has_matching_hidraw(&device, hidraw_config) { - continue; - } - - // Check if the device has already been used in this config or not, stop here if the device must be unique. - if let Some(sources) = self.composite_device_sources.get(composite_device) { - for source in sources { - if source != source_device { - continue; - } - if let Some(ignored) = source_device.ignore { - if ignored { - log::debug!("Ignoring device {:?}, not adding to composite device: {}", source_device, composite_device); - break 'start; - } - } - if let Some(unique) = source_device.clone().unique { - if unique { - log::trace!("Found unique device {:?}, not adding to composite device {}", source_device, composite_device); - break 'start; - } - } else { - log::trace!("Found unique device {:?}, not adding to composite device {}", source_device, composite_device); - break 'start; - } - } - } - log::info!("Found missing device, adding source device {id} to existing composite device: {composite_device}"); - let handle = self.composite_devices.get(composite_device.as_str()); - if handle.is_none() { - log::error!( - "No existing composite device found for key {}", - composite_device.as_str() - ); - continue; - } - self.add_device_to_composite_device(device, handle.unwrap()) - .await?; - self.source_devices_used - .insert(id.clone(), composite_device.clone()); - let composite_id = composite_device.clone(); - if !self.composite_device_sources.contains_key(&composite_id) { - self.composite_device_sources - .insert(composite_id.clone(), Vec::new()); - } - let sources = self - .composite_device_sources - .get_mut(&composite_id) - .unwrap(); - sources.push(source_device.clone()); + if source_device.ignore.map_or(false, |ignored| ignored) { + log::debug!( + "Ignoring device {:?}, not adding to composite device: {composite_device}", + source_device + ); + break 'start; + } - self.source_devices.insert(id, source_device.clone()); - return Ok(()); + // Check if the composite device has to be unique (default to being unique) + if source_device.unique.map_or(true, |unique| unique) { + log::trace!( + "Found unique device {:?}, not adding to composite device {composite_device}", + source_device + ); + break 'start; } } - "iio" => { - log::trace!("Checking if existing composite device is missing iio device"); - for source_device in config.source_devices.iter() { - let Some(iio_config) = source_device.iio.as_ref() else { - continue; - }; - if !config.has_matching_iio(&device, iio_config) { - continue; - } + } - // Check if the device has already been used in this config or not, stop here if the device must be unique. - if let Some(sources) = self.composite_device_sources.get(composite_device) { - for source in sources { - if source != source_device { - continue; - } - if let Some(ignored) = source_device.ignore { - if ignored { - log::debug!("Ignoring device {:?}, not adding to composite device: {}", source_device, composite_device); - continue; - } - } - if let Some(unique) = source_device.clone().unique { - if unique { - log::trace!("Found unique device {:?}, not adding to composite device {}", source_device, composite_device); - break 'start; - } - } else { - log::trace!("Found unique device {:?}, not adding to composite device {}", source_device, composite_device); - break 'start; - } - } - } + log::info!("Found missing {} device, adding source device {id} to existing composite device: {composite_device:?}", device.subsystem()); + let Some(client) = self.composite_devices.get(composite_device.as_str()) else { + log::error!("No existing composite device found for key {composite_device:?}"); + continue; + }; - log::info!("Found missing device, adding source device {id} to existing composite device: {composite_device}"); - let handle = self.composite_devices.get(composite_device.as_str()); - if handle.is_none() { - log::error!( - "No existing composite device found for key {}", - composite_device.as_str() - ); - continue; - } - self.add_device_to_composite_device(device, handle.unwrap()) - .await?; - self.source_devices_used - .insert(id.clone(), composite_device.clone()); - let composite_id = composite_device.clone(); - if !self.composite_device_sources.contains_key(&composite_id) { - self.composite_device_sources - .insert(composite_id.clone(), Vec::new()); - } - let sources = self - .composite_device_sources - .get_mut(&composite_id) - .unwrap(); - sources.push(source_device.clone()); + self.add_device_to_composite_device(device, client).await?; + self.source_devices_used + .insert(id.clone(), composite_device.clone()); + let composite_id = composite_device.clone(); + if !self.composite_device_sources.contains_key(&composite_id) { + self.composite_device_sources + .insert(composite_id.clone(), Vec::new()); + } + let sources = self + .composite_device_sources + .get_mut(&composite_id) + .unwrap(); + sources.push(source_device.clone()); + self.source_devices.insert(id, source_device.clone()); - self.source_devices.insert(id, source_device.clone()); - return Ok(()); - } - } - _ => (), - }; - log::trace!( - "Device {id} does not match existing device: {:?}", - config.name - ); + return Ok(()); } + log::debug!("No existing composite device matches device {id}."); // Check all CompositeDevice configs to see if this device creates @@ -1066,13 +850,11 @@ impl Manager { log::trace!("Checking config {:?} for device", config.name); // Check to see if 'auto_manage' is enabled for this config. - let auto_manage = { - if let Some(options) = config.options.as_ref() { - options.auto_manage.unwrap_or(false) - } else { - false - } - }; + let auto_manage = config + .options + .as_ref() + .and_then(|options| Some(options.auto_manage.unwrap_or(false))) + .unwrap_or(false); if !self.manage_all_devices && !auto_manage { log::trace!( "Config {:?} does not have 'auto_manage' option enabled. Skipping.", @@ -1087,22 +869,18 @@ impl Manager { continue; } - // Check if this device matches any source udev configs - for source_device in config.source_devices.iter() { - let Some(udev_config) = source_device.udev.as_ref() else { - continue; - }; - if !config.has_matching_udev(&device, udev_config) { - continue; - } - + // Check if this device matches any source configs + if let Some(source_device) = config.get_matching_device(&device) { if let Some(ignored) = source_device.ignore { if ignored { log::trace!("Event device configured to ignore: {:?}", device); return Ok(()); } } - log::info!("Found a matching udev device {id}, creating CompositeDevice"); + log::info!( + "Found a matching {} device {id}, creating CompositeDevice", + device.subsystem() + ); let dev = self .create_composite_device_from_config(&config, device) .await?; @@ -1122,120 +900,6 @@ impl Manager { return Ok(()); } - let source_devices = config.source_devices.clone(); - match device.subsystem().as_str() { - "input" => { - for source_device in source_devices { - if source_device.evdev.is_none() { - continue; - } - // how to refrence source devices used by this config? - - if config.has_matching_evdev(&device, &source_device.clone().evdev.unwrap()) - { - if let Some(ignored) = source_device.ignore { - if ignored { - log::trace!("Event device configured to ignore: {:?}", device); - return Ok(()); - } - } - log::info!( - "Found a matching evdev device {id}, creating CompositeDevice" - ); - let dev = self - .create_composite_device_from_config(&config, device) - .await?; - - // Get the target input devices from the config - let target_devices_config = config.target_devices.clone(); - - // Create the composite deivce - self.start_composite_device( - dev, - config, - target_devices_config, - source_device.clone(), - ) - .await?; - - return Ok(()); - } - } - } - "hidraw" => { - for source_device in source_devices { - if source_device.hidraw.is_none() { - continue; - } - if config - .has_matching_hidraw(&device, &source_device.clone().hidraw.unwrap()) - { - if let Some(ignored) = source_device.ignore { - if ignored { - log::trace!("hidraw device configured to ignore: {:?}", device); - return Ok(()); - } - } - log::info!( - "Found a matching hidraw device {id}, creating CompositeDevice" - ); - let dev = self - .create_composite_device_from_config(&config, device) - .await?; - - // Get the target input devices from the config - let target_devices_config = config.target_devices.clone(); - - // Create the composite deivce - self.start_composite_device( - dev, - config, - target_devices_config, - source_device.clone(), - ) - .await?; - - return Ok(()); - } - } - } - "iio" => { - for source_device in source_devices { - if source_device.iio.is_none() { - continue; - } - if config.has_matching_iio(&device, &source_device.clone().iio.unwrap()) { - if let Some(ignored) = source_device.ignore { - if ignored { - log::trace!("iio device configured to ignore: {:?}", device); - return Ok(()); - } - } - log::info!( - "Found a matching iio device {id}, creating CompositeDevice" - ); - let dev = self - .create_composite_device_from_config(&config, device.clone()) - .await?; - - // Get the target input devices from the config - let target_devices_config = config.target_devices.clone(); - - // Create the composite deivce - self.start_composite_device( - dev, - config, - target_devices_config, - source_device.clone(), - ) - .await?; - - return Ok(()); - } - } - } - _ => (), - } log::trace!("Device does not match config: {:?}", config.name); } log::debug!("No unused configs found for device."); @@ -1630,6 +1294,7 @@ impl Manager { } } + /// Watch for IIO device events fn watch_iio_devices( cmd_tx: mpsc::Sender, ) -> tokio::task::JoinHandle>> { @@ -1679,7 +1344,8 @@ impl Manager { }) } - async fn watch_hidraw_devices( + /// Watch for appearance and disappearence of devices is /dev and associate the corresponding udev device + async fn watch_devnodes( cmd_tx: mpsc::Sender, watcher_rx: &mut mpsc::Receiver, ) -> () { @@ -1905,7 +1571,7 @@ impl Manager { result.unwrap_or_default() } - /// Creates a DBus object + /// Creates a DBus object and return the (active) handle to the listener async fn listen_on_dbus( dbus: Connection, tx: mpsc::Sender,