Skip to content

Commit

Permalink
fix(Set Target Devices): Add workaround when starting new target devi…
Browse files Browse the repository at this point in the history
…ces.

- 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.
  • Loading branch information
pastaq committed Jun 7, 2024
1 parent d0963f3 commit 5f3f7bf
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 23 deletions.
28 changes: 17 additions & 11 deletions src/input/composite_device/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1678,8 +1678,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());
};
Expand Down Expand Up @@ -1727,16 +1743,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;
Expand Down
24 changes: 12 additions & 12 deletions src/input/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -455,77 +455,77 @@ 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) => {
let path = self.next_target_path("mouse")?;
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) => {
let path = self.next_target_path("gamepad")?;
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) => {
let path = self.next_target_path("dbus")?;
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) => {
let path = self.next_target_path("gamepad")?;
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) => {
let path = self.next_target_path("gamepad")?;
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!(),
Expand Down

0 comments on commit 5f3f7bf

Please sign in to comment.