From 97eec27b8cf524657a906c7e420ca49ef39c35d1 Mon Sep 17 00:00:00 2001 From: William Edwards Date: Tue, 28 Jan 2025 13:30:18 -0800 Subject: [PATCH] fix(TargetDevice): add method for target devices to query composite device config --- src/input/composite_device/client.rs | 32 +++++++++++++++++++++++++++ src/input/composite_device/command.rs | 2 ++ src/input/composite_device/mod.rs | 21 +++++++++++------- src/input/target/mod.rs | 19 ++++++++++++++-- 4 files changed, 64 insertions(+), 10 deletions(-) diff --git a/src/input/composite_device/client.rs b/src/input/composite_device/client.rs index daca66d..a04e099 100644 --- a/src/input/composite_device/client.rs +++ b/src/input/composite_device/client.rs @@ -2,6 +2,7 @@ use std::collections::{HashMap, HashSet}; use thiserror::Error; use tokio::sync::mpsc::{channel, error::SendError, Sender}; +use crate::config::CompositeDeviceConfig; use crate::input::event::native::NativeEvent; use crate::input::target::client::TargetDeviceClient; use crate::input::{capability::Capability, event::Event, output_event::OutputEvent}; @@ -97,6 +98,26 @@ impl CompositeDeviceClient { Err(ClientError::ChannelClosed) } + /// Get the [CompositeDeviceConfig] from the [CompositeDevice] + pub async fn get_config(&self) -> Result { + let (tx, mut rx) = channel(1); + self.tx.send(CompositeCommand::GetConfig(tx)).await?; + if let Some(config) = rx.recv().await { + return Ok(config); + } + Err(ClientError::ChannelClosed) + } + + /// Get the [CompositeDeviceConfig] from the [CompositeDevice] (blocking) + pub fn blocking_get_config(&self) -> Result { + let (tx, mut rx) = channel(1); + self.tx.blocking_send(CompositeCommand::GetConfig(tx))?; + if let Some(config) = rx.blocking_recv() { + return Ok(config); + } + Err(ClientError::ChannelClosed) + } + /// Get capabilities from all target devices pub async fn get_target_capabilities(&self) -> Result, ClientError> { let (tx, mut rx) = channel(1); @@ -139,6 +160,17 @@ impl CompositeDeviceClient { Err(ClientError::ChannelClosed) } + /// Get the source device paths of the composite device (blocking) + pub fn blocking_get_source_device_paths(&self) -> Result, ClientError> { + let (tx, mut rx) = channel(1); + self.tx + .blocking_send(CompositeCommand::GetSourceDevicePaths(tx))?; + if let Some(paths) = rx.blocking_recv() { + return Ok(paths); + } + Err(ClientError::ChannelClosed) + } + /// Get the target device paths of the composite device pub async fn get_target_device_paths(&self) -> Result, ClientError> { let (tx, mut rx) = channel(1); diff --git a/src/input/composite_device/command.rs b/src/input/composite_device/command.rs index f073031..4b41663 100644 --- a/src/input/composite_device/command.rs +++ b/src/input/composite_device/command.rs @@ -3,6 +3,7 @@ use std::collections::{HashMap, HashSet}; use tokio::sync::mpsc; use crate::{ + config::CompositeDeviceConfig, input::{ capability::Capability, event::{native::NativeEvent, Event}, @@ -20,6 +21,7 @@ use super::InterceptMode; #[derive(Debug, Clone)] pub enum CompositeCommand { AttachTargetDevices(HashMap), + GetConfig(mpsc::Sender), GetCapabilities(mpsc::Sender>), GetDBusDevicePaths(mpsc::Sender>), GetInterceptMode(mpsc::Sender), diff --git a/src/input/composite_device/mod.rs b/src/input/composite_device/mod.rs index b0079b9..d716026 100644 --- a/src/input/composite_device/mod.rs +++ b/src/input/composite_device/mod.rs @@ -352,6 +352,11 @@ impl CompositeDevice { log::error!("Failed to send intercept mode: {:?}", e); } } + CompositeCommand::GetConfig(sender) => { + if let Err(e) = sender.send(self.config.clone()).await { + log::error!("Failed to send config: {e:?}"); + } + } CompositeCommand::GetSourceDevicePaths(sender) => { if let Err(e) = sender.send(self.get_source_device_paths()).await { log::error!("Failed to send source device paths: {:?}", e); @@ -1902,14 +1907,6 @@ impl CompositeDevice { // Keep track of all target devices for (path, target) in targets.into_iter() { - log::debug!("Attaching target device: {path}"); - if let Err(e) = target.set_composite_device(self.client()).await { - return Err( - format!("Failed to set composite device for target device: {:?}", e).into(), - ); - } - log::debug!("Attached device {path} to {dbus_path}"); - // Query the target device for its capabilities let caps = match target.get_capabilities().await { Ok(caps) => caps, @@ -1918,6 +1915,14 @@ impl CompositeDevice { } }; + log::debug!("Attaching target device: {path}"); + if let Err(e) = target.set_composite_device(self.client()).await { + return Err( + format!("Failed to set composite device for target device: {:?}", e).into(), + ); + } + log::debug!("Attached device {path} to {dbus_path}"); + // Add the target device self.target_devices_queued.remove(&path); self.target_devices.insert(path.clone(), target); diff --git a/src/input/target/mod.rs b/src/input/target/mod.rs index 0bf5c93..f5a9651 100644 --- a/src/input/target/mod.rs +++ b/src/input/target/mod.rs @@ -14,7 +14,7 @@ use crate::dbus::interface::target::gamepad::TargetGamepadInterface; use super::{ capability::Capability, - composite_device::client::CompositeDeviceClient, + composite_device::client::{ClientError, CompositeDeviceClient}, event::native::{NativeEvent, ScheduledNativeEvent}, output_capability::OutputCapability, output_event::OutputEvent, @@ -89,6 +89,12 @@ impl From for InputError { } } +impl From for InputError { + fn from(value: ClientError) -> Self { + InputError::DeviceError(value.to_string()) + } +} + /// Possible errors for a target device client #[derive(Error, Debug)] pub enum OutputError { @@ -291,6 +297,14 @@ pub trait TargetInputDevice { /// that the target device should stop sending input. fn clear_state(&mut self) {} + /// Called when the target device has been attached to a composite device. + fn on_composite_device_attached( + &mut self, + _device: CompositeDeviceClient, + ) -> Result<(), InputError> { + Ok(()) + } + /// Stop the target device fn stop(&mut self) -> Result<(), InputError> { Ok(()) @@ -492,7 +506,8 @@ impl TargetDriver implementation.write_event(event)?; } TargetCommand::SetCompositeDevice(device) => { - *composite_device = Some(device); + *composite_device = Some(device.clone()); + implementation.on_composite_device_attached(device)?; } TargetCommand::GetCapabilities(sender) => { let capabilities = implementation.get_capabilities().unwrap_or_default();