Skip to content

Commit

Permalink
fix(TargetDevice): add method for target devices to query composite d…
Browse files Browse the repository at this point in the history
…evice config
  • Loading branch information
ShadowApex committed Jan 28, 2025
1 parent b7a9cc6 commit 97eec27
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 10 deletions.
32 changes: 32 additions & 0 deletions src/input/composite_device/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -97,6 +98,26 @@ impl CompositeDeviceClient {
Err(ClientError::ChannelClosed)
}

/// Get the [CompositeDeviceConfig] from the [CompositeDevice]
pub async fn get_config(&self) -> Result<CompositeDeviceConfig, ClientError> {
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<CompositeDeviceConfig, ClientError> {
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<HashSet<Capability>, ClientError> {
let (tx, mut rx) = channel(1);
Expand Down Expand Up @@ -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<Vec<String>, 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<Vec<String>, ClientError> {
let (tx, mut rx) = channel(1);
Expand Down
2 changes: 2 additions & 0 deletions src/input/composite_device/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::collections::{HashMap, HashSet};
use tokio::sync::mpsc;

use crate::{
config::CompositeDeviceConfig,
input::{
capability::Capability,
event::{native::NativeEvent, Event},
Expand All @@ -20,6 +21,7 @@ use super::InterceptMode;
#[derive(Debug, Clone)]
pub enum CompositeCommand {
AttachTargetDevices(HashMap<String, TargetDeviceClient>),
GetConfig(mpsc::Sender<CompositeDeviceConfig>),
GetCapabilities(mpsc::Sender<HashSet<Capability>>),
GetDBusDevicePaths(mpsc::Sender<Vec<String>>),
GetInterceptMode(mpsc::Sender<InterceptMode>),
Expand Down
21 changes: 13 additions & 8 deletions src/input/composite_device/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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,
Expand All @@ -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);
Expand Down
19 changes: 17 additions & 2 deletions src/input/target/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -89,6 +89,12 @@ impl From<io::Error> for InputError {
}
}

impl From<ClientError> 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 {
Expand Down Expand Up @@ -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(())
Expand Down Expand Up @@ -492,7 +506,8 @@ impl<T: TargetInputDevice + TargetOutputDevice + Send + 'static> TargetDriver<T>
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();
Expand Down

0 comments on commit 97eec27

Please sign in to comment.