From 1edd1eb7d61e3ffe4dbf3692b2a8d2a244c80b43 Mon Sep 17 00:00:00 2001 From: "Derek J. Clark" Date: Mon, 3 Jun 2024 13:58:26 -0700 Subject: [PATCH] fix(Set Target Devices): Add workaround when starting new target devices. - If a dualsense HIDRAW interface is still present when a new one is started, since the 'unique' ID is the same, the kernel driver will close the HIDRAW interface after the new device has started, orphaning the dbus interface. This change waits for the HIDRAW interfaces to close before starting the new target devices. --- src/input/composite_device/mod.rs | 28 +++++++++++++++++----------- src/input/manager.rs | 24 ++++++++++++------------ 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/src/input/composite_device/mod.rs b/src/input/composite_device/mod.rs index d36c064..6589664 100644 --- a/src/input/composite_device/mod.rs +++ b/src/input/composite_device/mod.rs @@ -1648,8 +1648,24 @@ impl CompositeDevice { return Ok(()); } - // Keep a list of old target devices to stop + // Stop all old target devices let targets_to_stop = self.target_devices.clone(); + let targets_to_stop_len = targets_to_stop.len(); + for (path, target) in targets_to_stop.into_iter() { + log::debug!("Stopping old target device: {path}"); + self.target_devices.remove(&path); + if let Err(e) = target.send(TargetCommand::Stop).await { + log::error!("Failed to stop old target device: {e:?}"); + } + } + + // TODO: This is a cheap hack to let the target devices stop before starting more. + // The dualsense controller will close the HIDRAW as the "unique" ID is the same + // if the new and old target devices are both dualsense. + if targets_to_stop_len > 0 { + tokio::time::sleep(Duration::from_millis(80)).await; + } + let Some(composite_path) = self.dbus_path.clone() else { return Err("No composite device DBus path found".into()); }; @@ -1697,16 +1713,6 @@ impl CompositeDevice { // from mangling attachment. self.target_devices_queued.insert(target_path); } - - // Stop all old target devices - for (path, target) in targets_to_stop.into_iter() { - log::debug!("Stopping old target device: {path}"); - self.target_devices.remove(&path); - if let Err(e) = target.send(TargetCommand::Stop).await { - log::error!("Failed to stop old target device: {e:?}"); - } - } - // Signal change in target devices to DBus // TODO: Check this //self.signal_targets_changed().await; diff --git a/src/input/manager.rs b/src/input/manager.rs index 8f33828..3e24559 100644 --- a/src/input/manager.rs +++ b/src/input/manager.rs @@ -454,12 +454,12 @@ impl Manager { let event_tx = device.transmitter(); target_devices.insert(path.clone(), event_tx.clone()); self.target_devices.insert(path.clone(), event_tx.clone()); - device.listen_on_dbus(path).await?; + device.listen_on_dbus(path.clone()).await?; tokio::spawn(async move { if let Err(e) = device.run().await { log::error!("Failed to run target keyboard: {:?}", e); } - log::debug!("Target keyboard device closed"); + log::debug!("Target keyboard device closed at: {}", path); }); } TargetDeviceType::Mouse(mut mouse) => { @@ -467,12 +467,12 @@ impl Manager { let event_tx = mouse.transmitter(); target_devices.insert(path.clone(), event_tx.clone()); self.target_devices.insert(path.clone(), event_tx.clone()); - mouse.listen_on_dbus(path).await?; + mouse.listen_on_dbus(path.clone()).await?; tokio::spawn(async move { if let Err(e) = mouse.run().await { log::error!("Failed to run target mouse: {:?}", e); } - log::debug!("Target mouse device closed"); + log::debug!("Target mouse device closed at: {}", path); }); } TargetDeviceType::GenericGamepad(mut gamepad) => { @@ -480,12 +480,12 @@ impl Manager { let event_tx = gamepad.transmitter(); target_devices.insert(path.clone(), event_tx.clone()); self.target_devices.insert(path.clone(), event_tx.clone()); - gamepad.listen_on_dbus(path).await?; + gamepad.listen_on_dbus(path.clone()).await?; tokio::spawn(async move { if let Err(e) = gamepad.run().await { log::error!("Failed to run target gamepad: {:?}", e); } - log::debug!("Target gamepad device closed"); + log::debug!("Target gamepad device closed at: {}", path); }); } TargetDeviceType::DBus(mut device) => { @@ -493,12 +493,12 @@ impl Manager { let event_tx = device.transmitter(); target_devices.insert(path.clone(), event_tx.clone()); self.target_devices.insert(path.clone(), event_tx.clone()); - device.listen_on_dbus(path).await?; + device.listen_on_dbus(path.clone()).await?; tokio::spawn(async move { if let Err(e) = device.run().await { log::error!("Failed to run target dbus device: {:?}", e); } - log::debug!("Target dbus device closed"); + log::debug!("Target dbus device closed at: {}", path); }); } TargetDeviceType::SteamDeck(mut device) => { @@ -506,12 +506,12 @@ impl Manager { let event_tx = device.transmitter(); target_devices.insert(path.clone(), event_tx.clone()); self.target_devices.insert(path.clone(), event_tx.clone()); - device.listen_on_dbus(path).await?; + device.listen_on_dbus(path.clone()).await?; tokio::spawn(async move { if let Err(e) = device.run().await { log::error!("Failed to run target steam deck device: {:?}", e); } - log::debug!("Target steam deck device closed"); + log::debug!("Target steam deck device closed at: {}", path); }); } TargetDeviceType::DualSense(mut device) => { @@ -519,12 +519,12 @@ impl Manager { let event_tx = device.transmitter(); target_devices.insert(path.clone(), event_tx.clone()); self.target_devices.insert(path.clone(), event_tx.clone()); - device.listen_on_dbus(path).await?; + device.listen_on_dbus(path.clone()).await?; tokio::spawn(async move { if let Err(e) = device.run().await { log::error!("Failed to run target dualsense device: {:?}", e); } - log::debug!("Target dualsense device closed"); + log::debug!("Target dualsense device closed at: {}", path); }); } TargetDeviceType::XBox360(_) => todo!(),