diff --git a/src/dbus/interface/target/mod.rs b/src/dbus/interface/target/mod.rs index 230186f..1035f8f 100644 --- a/src/dbus/interface/target/mod.rs +++ b/src/dbus/interface/target/mod.rs @@ -7,21 +7,21 @@ pub mod touchscreen; use zbus::fdo; use zbus_macros::interface; +use crate::input::target::TargetDeviceTypeId; + /// The [TargetInterface] provides a DBus interface that can be exposed for managing /// a target input device. pub struct TargetInterface { dev_name: String, + device_type: String, } impl TargetInterface { - pub fn new(dev_name: String) -> TargetInterface { - TargetInterface { dev_name } - } -} - -impl Default for TargetInterface { - fn default() -> Self { - Self::new("Gamepad".to_string()) + pub fn new(device_type: &TargetDeviceTypeId) -> TargetInterface { + TargetInterface { + dev_name: device_type.name().to_owned(), + device_type: device_type.as_str().to_owned(), + } } } @@ -32,4 +32,9 @@ impl TargetInterface { async fn name(&self) -> fdo::Result { Ok(self.dev_name.clone()) } + + #[zbus(property)] + async fn device_type(&self) -> fdo::Result { + Ok(self.device_type.clone()) + } } diff --git a/src/input/target/dbus.rs b/src/input/target/dbus.rs index 5c2cbf1..aed2026 100644 --- a/src/input/target/dbus.rs +++ b/src/input/target/dbus.rs @@ -3,7 +3,7 @@ use std::{collections::HashMap, error::Error}; use zbus::Connection; use crate::{ - dbus::interface::target::dbus::TargetDBusInterface, + dbus::interface::target::{dbus::TargetDBusInterface, TargetInterface}, input::{ capability::{Capability, Gamepad, GamepadButton}, event::{ @@ -14,7 +14,9 @@ use crate::{ }, }; -use super::{client::TargetDeviceClient, TargetInputDevice, TargetOutputDevice}; +use super::{ + client::TargetDeviceClient, TargetDeviceTypeId, TargetInputDevice, TargetOutputDevice, +}; /// The threshold for axis inputs to be considered "pressed" const AXIS_THRESHOLD: f64 = 0.60; @@ -300,16 +302,23 @@ impl TargetInputDevice for DBusDevice { dbus: Connection, path: String, _client: TargetDeviceClient, + type_id: TargetDeviceTypeId, ) { log::debug!("Starting dbus interface: {path}"); self.dbus_path = Some(path.clone()); tokio::task::spawn(async move { + let generic_interface = TargetInterface::new(&type_id); let iface = TargetDBusInterface::new(); - if let Err(e) = dbus.object_server().at(path.clone(), iface).await { - log::debug!("Failed to start dbus interface {path}: {e:?}"); + let object_server = dbus.object_server(); + let (gen_result, result) = tokio::join!( + object_server.at(path.clone(), generic_interface), + object_server.at(path.clone(), iface) + ); + if gen_result.is_err() || result.is_err() { + log::debug!("Failed to start dbus interface: {path} generic: {gen_result:?} type-specific: {result:?}"); } else { - log::debug!("Started dbus interface on {path}"); - }; + log::debug!("Started dbus interface: {path}"); + } }); } @@ -368,15 +377,16 @@ impl TargetInputDevice for DBusDevice { fn stop_dbus_interface(&mut self, dbus: Connection, path: String) { log::debug!("Stopping dbus interface for {path}"); tokio::task::spawn(async move { - let result = dbus - .object_server() - .remove::(path.clone()) - .await; - if let Err(e) = result { - log::error!("Failed to stop dbus interface {path}: {e:?}"); + let object_server = dbus.object_server(); + let (target, generic) = tokio::join!( + object_server.remove::(path.clone()), + object_server.remove::(path.clone()) + ); + if generic.is_err() || target.is_err() { + log::debug!("Failed to stop dbus interface: {path} generic: {generic:?} type-specific: {target:?}"); } else { log::debug!("Stopped dbus interface for {path}"); - }; + } }); } } diff --git a/src/input/target/keyboard.rs b/src/input/target/keyboard.rs index 7c1e417..c8e2a1a 100644 --- a/src/input/target/keyboard.rs +++ b/src/input/target/keyboard.rs @@ -7,14 +7,17 @@ use evdev::{ use zbus::Connection; use crate::{ - dbus::interface::target::keyboard::TargetKeyboardInterface, + dbus::interface::target::{keyboard::TargetKeyboardInterface, TargetInterface}, input::{ capability::{Capability, Keyboard}, event::{evdev::EvdevEvent, native::NativeEvent}, }, }; -use super::{client::TargetDeviceClient, InputError, TargetInputDevice, TargetOutputDevice}; +use super::{ + client::TargetDeviceClient, InputError, TargetDeviceTypeId, TargetInputDevice, + TargetOutputDevice, +}; #[derive(Debug)] pub struct KeyboardDevice { @@ -216,15 +219,28 @@ impl KeyboardDevice { } impl TargetInputDevice for KeyboardDevice { - fn start_dbus_interface(&mut self, dbus: Connection, path: String, client: TargetDeviceClient) { + fn start_dbus_interface( + &mut self, + dbus: Connection, + path: String, + client: TargetDeviceClient, + type_id: TargetDeviceTypeId, + ) { log::debug!("Starting dbus interface: {path}"); tokio::task::spawn(async move { + let generic_interface = TargetInterface::new(&type_id); let iface = TargetKeyboardInterface::new(client); - if let Err(e) = dbus.object_server().at(path.clone(), iface).await { - log::debug!("Failed to start dbus interface {path}: {e:?}"); + + let object_server = dbus.object_server(); + let (gen_result, result) = tokio::join!( + object_server.at(path.clone(), generic_interface), + object_server.at(path.clone(), iface) + ); + if gen_result.is_err() || result.is_err() { + log::debug!("Failed to start dbus interface: {path} generic: {gen_result:?} type-specific: {result:?}"); } else { - log::debug!("Started dbus interface on {path}"); - }; + log::debug!("Started dbus interface: {path}"); + } }); } @@ -407,15 +423,16 @@ impl TargetInputDevice for KeyboardDevice { fn stop_dbus_interface(&mut self, dbus: Connection, path: String) { log::debug!("Stopping dbus interface for {path}"); tokio::task::spawn(async move { - let result = dbus - .object_server() - .remove::(path.clone()) - .await; - if let Err(e) = result { - log::error!("Failed to stop dbus interface {path}: {e:?}"); + let object_server = dbus.object_server(); + let (target, generic) = tokio::join!( + object_server.remove::(path.clone()), + object_server.remove::(path.clone()) + ); + if generic.is_err() || target.is_err() { + log::debug!("Failed to stop dbus interface: {path} generic: {generic:?} type-specific: {target:?}"); } else { log::debug!("Stopped dbus interface for {path}"); - }; + } }); } } diff --git a/src/input/target/mod.rs b/src/input/target/mod.rs index f5a9651..4f17d4c 100644 --- a/src/input/target/mod.rs +++ b/src/input/target/mod.rs @@ -10,7 +10,7 @@ use horipad_steam::HoripadSteamDevice; use thiserror::Error; use tokio::sync::mpsc::{self, error::TryRecvError}; -use crate::dbus::interface::target::gamepad::TargetGamepadInterface; +use crate::dbus::interface::target::{gamepad::TargetGamepadInterface, TargetInterface}; use super::{ capability::Capability, @@ -244,17 +244,30 @@ impl TryFrom<&str> for TargetDeviceTypeId { /// a composite device, and are sent to a target device to be emitted. pub trait TargetInputDevice { /// Start the DBus interface for this target device - fn start_dbus_interface(&mut self, dbus: Connection, path: String, client: TargetDeviceClient) { + fn start_dbus_interface( + &mut self, + dbus: Connection, + path: String, + client: TargetDeviceClient, + type_id: TargetDeviceTypeId, + ) { log::debug!("Starting dbus interface: {path}"); log::trace!("Using device client: {client:?}"); tokio::task::spawn(async move { - let name = "Gamepad".to_string(); - let iface = TargetGamepadInterface::new(name); - if let Err(e) = dbus.object_server().at(path.clone(), iface).await { - log::debug!("Failed to start dbus interface {path}: {e:?}"); + let generic_interface = TargetInterface::new(&type_id); + let iface = TargetGamepadInterface::new(type_id.name().to_owned()); + + let object_server = dbus.object_server(); + let (gen_result, result) = tokio::join!( + object_server.at(path.clone(), generic_interface), + object_server.at(path.clone(), iface) + ); + + if gen_result.is_err() || result.is_err() { + log::debug!("Failed to start dbus interface: {path} generic: {gen_result:?} type-specific: {result:?}"); } else { - log::debug!("Started dbus interface on {path}"); - }; + log::debug!("Started dbus interface: {path}"); + } }); } @@ -280,15 +293,16 @@ pub trait TargetInputDevice { fn stop_dbus_interface(&mut self, dbus: Connection, path: String) { log::debug!("Stopping dbus interface for {path}"); tokio::task::spawn(async move { - let result = dbus - .object_server() - .remove::(path.clone()) - .await; - if let Err(e) = result { - log::error!("Failed to stop dbus interface {path}: {e:?}"); + let object_server = dbus.object_server(); + let (target, generic) = tokio::join!( + object_server.remove::(path.clone()), + object_server.remove::(path.clone()) + ); + if generic.is_err() || target.is_err() { + log::debug!("Failed to stop dbus interface: {path} generic: {generic:?} type-specific: {target:?}"); } else { log::debug!("Stopped dbus interface for {path}"); - }; + } }); } @@ -410,7 +424,12 @@ impl TargetDriver let mut implementation = self.implementation.lock().unwrap(); // Start the DBus interface for the device - implementation.start_dbus_interface(self.dbus.clone(), dbus_path.clone(), client); + implementation.start_dbus_interface( + self.dbus.clone(), + dbus_path.clone(), + client, + self.type_id, + ); log::debug!("Target device running: {dbus_path}"); loop { diff --git a/src/input/target/mouse.rs b/src/input/target/mouse.rs index 8d4942c..137d755 100644 --- a/src/input/target/mouse.rs +++ b/src/input/target/mouse.rs @@ -8,7 +8,7 @@ use evdev::{ use zbus::Connection; use crate::{ - dbus::interface::target::mouse::TargetMouseInterface, + dbus::interface::target::{mouse::TargetMouseInterface, TargetInterface}, input::{ capability::{Capability, Mouse, MouseButton}, composite_device::client::CompositeDeviceClient, @@ -18,7 +18,8 @@ use crate::{ }; use super::{ - client::TargetDeviceClient, InputError, OutputError, TargetInputDevice, TargetOutputDevice, + client::TargetDeviceClient, InputError, OutputError, TargetDeviceTypeId, TargetInputDevice, + TargetOutputDevice, }; /// Configuration of the target touchpad device. @@ -138,15 +139,28 @@ impl MouseDevice { } impl TargetInputDevice for MouseDevice { - fn start_dbus_interface(&mut self, dbus: Connection, path: String, client: TargetDeviceClient) { + fn start_dbus_interface( + &mut self, + dbus: Connection, + path: String, + client: TargetDeviceClient, + type_id: TargetDeviceTypeId, + ) { log::debug!("Starting dbus interface: {path}"); tokio::task::spawn(async move { + let generic_interface = TargetInterface::new(&type_id); let iface = TargetMouseInterface::new(client); - if let Err(e) = dbus.object_server().at(path.clone(), iface).await { - log::debug!("Failed to start dbus interface {path}: {e:?}"); + + let gen_result = dbus + .object_server() + .at(path.clone(), generic_interface) + .await; + let result = dbus.object_server().at(path.clone(), iface).await; + if gen_result.is_err() || result.is_err() { + log::debug!("Failed to start dbus interface: {path} generic: {gen_result:?} type-specific: {result:?}"); } else { - log::debug!("Started dbus interface on {path}"); - }; + log::debug!("Started dbus interface: {path}"); + } }); } @@ -188,15 +202,16 @@ impl TargetInputDevice for MouseDevice { fn stop_dbus_interface(&mut self, dbus: Connection, path: String) { log::debug!("Stopping dbus interface for {path}"); tokio::task::spawn(async move { - let result = dbus - .object_server() - .remove::(path.clone()) - .await; - if let Err(e) = result { - log::error!("Failed to stop dbus interface {path}: {e:?}"); + let object_server = dbus.object_server(); + let (target, generic) = tokio::join!( + object_server.remove::(path.clone()), + object_server.remove::(path.clone()) + ); + if generic.is_err() || target.is_err() { + log::debug!("Failed to stop dbus interface: {path} generic: {generic:?} type-specific: {target:?}"); } else { log::debug!("Stopped dbus interface for {path}"); - }; + } }); }