From e0c3090ac8c5480824ab3f293fd449ffa3191be0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Lidwin?= Date: Tue, 4 Feb 2025 15:31:36 +0100 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20expose=C2=A0generic=20target=20inte?= =?UTF-8?q?rface=20on=20every=20target=20interface?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/dbus/interface/target/mod.rs | 15 ++++++++-- src/input/target/dbus.rs | 32 +++++++++++++-------- src/input/target/keyboard.rs | 40 +++++++++++++++++--------- src/input/target/mod.rs | 48 ++++++++++++++++++++++---------- src/input/target/mouse.rs | 40 +++++++++++++++++--------- 5 files changed, 120 insertions(+), 55 deletions(-) diff --git a/src/dbus/interface/target/mod.rs b/src/dbus/interface/target/mod.rs index 230186f..0f0f9ab 100644 --- a/src/dbus/interface/target/mod.rs +++ b/src/dbus/interface/target/mod.rs @@ -11,17 +11,21 @@ use zbus_macros::interface; /// 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 } + pub fn new(dev_name: String, device_type: String) -> TargetInterface { + TargetInterface { + dev_name, + device_type, + } } } impl Default for TargetInterface { fn default() -> Self { - Self::new("Gamepad".to_string()) + Self::new("Gamepad".to_string(), "gamepad".to_string()) } } @@ -32,4 +36,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..a9d5715 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::{ @@ -300,16 +300,23 @@ impl TargetInputDevice for DBusDevice { dbus: Connection, path: String, _client: TargetDeviceClient, + type_id: String, ) { log::debug!("Starting dbus interface: {path}"); self.dbus_path = Some(path.clone()); tokio::task::spawn(async move { + let generic_interface = TargetInterface::new("DBusDevice".into(), 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 +375,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..eb2dbf1 100644 --- a/src/input/target/keyboard.rs +++ b/src/input/target/keyboard.rs @@ -7,7 +7,7 @@ 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}, @@ -216,15 +216,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: String, + ) { log::debug!("Starting dbus interface: {path}"); tokio::task::spawn(async move { + let generic_interface = TargetInterface::new("Keyboard".into(), 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 +420,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..2485802 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,31 @@ 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: String, + ) { log::debug!("Starting dbus interface: {path}"); log::trace!("Using device client: {client:?}"); tokio::task::spawn(async move { let name = "Gamepad".to_string(); + let generic_interface = TargetInterface::new(name.clone(), type_id); 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 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 +294,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 +425,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.as_str().to_owned(), + ); log::debug!("Target device running: {dbus_path}"); loop { diff --git a/src/input/target/mouse.rs b/src/input/target/mouse.rs index 8d4942c..b9719ae 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, @@ -138,15 +138,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: String, + ) { log::debug!("Starting dbus interface: {path}"); tokio::task::spawn(async move { + let generic_interface = TargetInterface::new("Mouse".into(), 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 +201,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}"); - }; + } }); } From b72312c38fcfb1a6a20a7412768134bc7a2ed405 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Lidwin?= Date: Fri, 7 Feb 2025 13:21:49 +0100 Subject: [PATCH 2/2] refactor: use target type id instead of string --- src/dbus/interface/target/mod.rs | 14 +++++--------- src/input/target/dbus.rs | 8 +++++--- src/input/target/keyboard.rs | 9 ++++++--- src/input/target/mod.rs | 9 ++++----- src/input/target/mouse.rs | 7 ++++--- 5 files changed, 24 insertions(+), 23 deletions(-) diff --git a/src/dbus/interface/target/mod.rs b/src/dbus/interface/target/mod.rs index 0f0f9ab..1035f8f 100644 --- a/src/dbus/interface/target/mod.rs +++ b/src/dbus/interface/target/mod.rs @@ -7,6 +7,8 @@ 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 { @@ -15,20 +17,14 @@ pub struct TargetInterface { } impl TargetInterface { - pub fn new(dev_name: String, device_type: String) -> TargetInterface { + pub fn new(device_type: &TargetDeviceTypeId) -> TargetInterface { TargetInterface { - dev_name, - device_type, + dev_name: device_type.name().to_owned(), + device_type: device_type.as_str().to_owned(), } } } -impl Default for TargetInterface { - fn default() -> Self { - Self::new("Gamepad".to_string(), "gamepad".to_string()) - } -} - #[interface(name = "org.shadowblip.Input.Target")] impl TargetInterface { /// Name of the DBus device diff --git a/src/input/target/dbus.rs b/src/input/target/dbus.rs index a9d5715..aed2026 100644 --- a/src/input/target/dbus.rs +++ b/src/input/target/dbus.rs @@ -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,12 +302,12 @@ impl TargetInputDevice for DBusDevice { dbus: Connection, path: String, _client: TargetDeviceClient, - type_id: String, + 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("DBusDevice".into(), type_id); + let generic_interface = TargetInterface::new(&type_id); let iface = TargetDBusInterface::new(); let object_server = dbus.object_server(); let (gen_result, result) = tokio::join!( diff --git a/src/input/target/keyboard.rs b/src/input/target/keyboard.rs index eb2dbf1..c8e2a1a 100644 --- a/src/input/target/keyboard.rs +++ b/src/input/target/keyboard.rs @@ -14,7 +14,10 @@ use crate::{ }, }; -use super::{client::TargetDeviceClient, InputError, TargetInputDevice, TargetOutputDevice}; +use super::{ + client::TargetDeviceClient, InputError, TargetDeviceTypeId, TargetInputDevice, + TargetOutputDevice, +}; #[derive(Debug)] pub struct KeyboardDevice { @@ -221,11 +224,11 @@ impl TargetInputDevice for KeyboardDevice { dbus: Connection, path: String, client: TargetDeviceClient, - type_id: String, + type_id: TargetDeviceTypeId, ) { log::debug!("Starting dbus interface: {path}"); tokio::task::spawn(async move { - let generic_interface = TargetInterface::new("Keyboard".into(), type_id); + let generic_interface = TargetInterface::new(&type_id); let iface = TargetKeyboardInterface::new(client); let object_server = dbus.object_server(); diff --git a/src/input/target/mod.rs b/src/input/target/mod.rs index 2485802..4f17d4c 100644 --- a/src/input/target/mod.rs +++ b/src/input/target/mod.rs @@ -249,14 +249,13 @@ pub trait TargetInputDevice { dbus: Connection, path: String, client: TargetDeviceClient, - type_id: String, + 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 generic_interface = TargetInterface::new(name.clone(), type_id); - let iface = TargetGamepadInterface::new(name); + 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!( @@ -429,7 +428,7 @@ impl TargetDriver self.dbus.clone(), dbus_path.clone(), client, - self.type_id.as_str().to_owned(), + self.type_id, ); log::debug!("Target device running: {dbus_path}"); diff --git a/src/input/target/mouse.rs b/src/input/target/mouse.rs index b9719ae..137d755 100644 --- a/src/input/target/mouse.rs +++ b/src/input/target/mouse.rs @@ -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. @@ -143,11 +144,11 @@ impl TargetInputDevice for MouseDevice { dbus: Connection, path: String, client: TargetDeviceClient, - type_id: String, + type_id: TargetDeviceTypeId, ) { log::debug!("Starting dbus interface: {path}"); tokio::task::spawn(async move { - let generic_interface = TargetInterface::new("Mouse".into(), type_id); + let generic_interface = TargetInterface::new(&type_id); let iface = TargetMouseInterface::new(client); let gen_result = dbus