Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 30 additions & 18 deletions src/input/target/dualsense.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,10 @@ pub struct DualSenseDevice {
context: u8,
hardware: DualSenseHardware,
queued_events: Vec<ScheduledNativeEvent>,
/// Last report written, used to skip re-emitting identical reports.
last_written: Option<Vec<u8>>,
/// Whether a consumer has the device open, writes are skipped while closed.
is_open: bool,
}

impl DualSenseDevice {
Expand All @@ -137,6 +141,8 @@ impl DualSenseDevice {
context: Default::default(),
hardware,
queued_events: Vec::new(),
last_written: None,
Comment thread
pastaq marked this conversation as resolved.
is_open: false,
})
}

Expand Down Expand Up @@ -193,27 +199,29 @@ impl DualSenseDevice {

/// Write the current device state to the device
fn write_state(&mut self) -> Result<(), Box<dyn Error>> {
match self.state {
PackedInputDataReport::Usb(state) => {
let data = state.pack()?;

// Write the state to the virtual HID
if let Err(e) = self.device.write(&data) {
let err = format!("Failed to write input data report: {:?}", e);
return Err(err.into());
}
}
PackedInputDataReport::Bluetooth(state) => {
let data = state.pack()?;
// No consumer so don't bother emitting.
if !self.is_open {
return Ok(());
}

// Write the state to the virtual HID
if let Err(e) = self.device.write(&data) {
let err = format!("Failed to write input data report: {:?}", e);
return Err(err.into());
}
}
let data = match self.state {
PackedInputDataReport::Usb(state) => state.pack()?.to_vec(),
PackedInputDataReport::Bluetooth(state) => state.pack()?.to_vec(),
};

// Skip re-emitting an identical report: runs every poll, so an
// idle controller would otherwise send the same bytes every cycle.
if self.last_written.as_ref() == Some(&data) {
Comment thread
pastaq marked this conversation as resolved.
return Ok(());
}

// Write the state to the virtual HID
if let Err(e) = self.device.write(&data) {
let err = format!("Failed to write input data report: {:?}", e);
return Err(err.into());
}
self.last_written = Some(data);

Ok(())
}

Expand Down Expand Up @@ -1073,12 +1081,16 @@ impl TargetOutputDevice for DualSenseDevice {
// send UHID_INPUT events to the kernel.
uhid_virt::OutputEvent::Open => {
log::debug!("Open event received");
self.is_open = true;
Ok(vec![])
}
// This is sent when there are no more processes which read the HID data. It is
// the counterpart of UHID_OPEN and you may as well ignore this event.
uhid_virt::OutputEvent::Close => {
log::debug!("Close event received");
// Drop the cached report so the next consumer to open is synced.
self.is_open = false;
self.last_written = None;
Ok(vec![])
}
// This is sent if the HID device driver wants to send raw data to the I/O
Expand Down
Loading