Skip to content

Commit

Permalink
feat(Touchpad): Add Touchpad event type.
Browse files Browse the repository at this point in the history
  • Loading branch information
pastaq authored and ShadowApex committed May 8, 2024
1 parent 7492d78 commit 3c03606
Show file tree
Hide file tree
Showing 17 changed files with 636 additions and 233 deletions.
4 changes: 2 additions & 2 deletions src/drivers/dualsense/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,5 @@ pub const DS5_ACC_RES_PER_G: u32 = 8192;
pub const DS5_ACC_RANGE: u32 = 4 * DS5_ACC_RES_PER_G;
pub const DS5_GYRO_RES_PER_DEG_S: u32 = 1024;
pub const DS5_GYRO_RANGE: u32 = 2048 * DS5_GYRO_RES_PER_DEG_S;
pub const DS5_TOUCHPAD_WIDTH: u32 = 1920;
pub const DS5_TOUCHPAD_HEIGHT: u32 = 1080;
pub const DS5_TOUCHPAD_WIDTH: f64 = 1920.0;
pub const DS5_TOUCHPAD_HEIGHT: f64 = 1080.0;
45 changes: 30 additions & 15 deletions src/drivers/dualsense/hid_report.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,31 @@ pub enum PowerState {
#[packed_struct(bit_numbering = "msb0", size_bytes = "4")]
pub struct TouchFingerData {
// byte 0
// Set to 127 when touching and 128 when not.
#[packed_field(bytes = "0")]
pub contact: u8,
pub context: u8,
// byte 1
#[packed_field(bytes = "1")]
pub x_low: u8,
pub x_lo: u8,
// byte 2
#[packed_field(bits = "16..=19")]
pub x_high: Integer<u8, packed_bits::Bits<4>>,
pub y_lo: Integer<u8, packed_bits::Bits<4>>,
#[packed_field(bits = "20..=23")]
pub y_low: Integer<u8, packed_bits::Bits<4>>,
pub x_hi: Integer<u8, packed_bits::Bits<4>>,
// byte 3
#[packed_field(bytes = "3")]
pub y_high: u8,
pub y_hi: u8,
}

impl TouchFingerData {
pub fn set_x(&mut self, x_raw: u16) {
self.x_lo = (x_raw & 0x00FF) as u8;
self.x_hi = Integer::from_primitive((x_raw & 0x0F00).rotate_right(8) as u8);
}
pub fn set_y(&mut self, y_raw: u16) {
self.y_lo = Integer::from_primitive((y_raw & 0x000F) as u8);
self.y_hi = (y_raw & 0x0FF0).rotate_right(4) as u8;
}
}

#[derive(PackedStruct, Debug, Copy, Clone, PartialEq)]
Expand Down Expand Up @@ -264,18 +279,18 @@ impl USBPackedInputDataReport {
touch_data: TouchData {
touch_finger_data: [
TouchFingerData {
contact: 0,
x_low: 0,
x_high: Integer::from_primitive(0),
y_low: Integer::from_primitive(0),
y_high: 0,
context: 128,
x_lo: 0,
y_lo: Integer::from_primitive(0),
x_hi: Integer::from_primitive(0),
y_hi: 0,
},
TouchFingerData {
contact: 0,
x_low: 0,
x_high: Integer::from_primitive(0),
y_low: Integer::from_primitive(0),
y_high: 0,
context: 128,
x_lo: 0,
y_lo: Integer::from_primitive(0),
x_hi: Integer::from_primitive(0),
y_hi: 0,
},
],
timestamp: 0,
Expand Down
23 changes: 23 additions & 0 deletions src/drivers/dualsense/hid_report_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use std::error::Error;

use packed_struct::{PackedStruct, PackedStructSlice};

use crate::drivers::dualsense::hid_report::USBPackedInputDataReport;

#[tokio::test]
async fn test_ds_hid() -> Result<(), Box<dyn Error>> {
let mut report = USBPackedInputDataReport::default();
println!("Before Report: {}", report.touch_data.touch_finger_data[0]);
report.touch_data.touch_finger_data[0].set_y(1068);
report.touch_data.touch_finger_data[0].set_x(1919);

println!("After Report: {}", report.touch_data.touch_finger_data[0]);
assert_eq!(
report.touch_data.touch_finger_data[0]
.pack_to_vec()
.unwrap(),
vec![0x80, 0x7F, 0xC7, 0x42]
);

Ok(())
}
6 changes: 4 additions & 2 deletions src/drivers/dualsense/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
pub mod report_descriptor;
pub mod driver;
pub mod hid_report;
pub mod hid_report;
mod hid_report_test;
pub mod report_descriptor;

133 changes: 82 additions & 51 deletions src/drivers/lego/driver.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
use std::{error::Error, ffi::CString, u8, vec};
use std::{
error::Error,
ffi::CString,
time::{Duration, Instant},
u8, vec,
};

use hidapi::HidDevice;
use packed_struct::{types::SizedInteger, PackedStruct};
Expand All @@ -15,52 +20,52 @@ use super::{
},
};

// Hardware ID's
pub const VID: u16 = 0x17ef;
pub const PID: u16 = 0x6182;
pub const PID2: u16 = 0x6185;

const DINPUT_PACKET_SIZE: usize = 13;
const XINPUT_PACKET_SIZE: usize = 60;
const KEYBOARD_PACKET_SIZE: usize = 15;
const MOUSE_PACKET_SIZE: usize = 7;
const TOUCHPAD_PACKET_SIZE: usize = 20;
const HID_TIMEOUT: i32 = 5000;

// Hardware limits
pub const DINPUT_LEFT_DATA: u8 = 0x07;
pub const DINPUT_RIGHT_DATA: u8 = 0x08;
pub const KEYBOARD_TOUCH_DATA: u8 = 0x01;
pub const MOUSE_FPS_DATA: u8 = 0x02;
//pub const MOUSE_DATA: u8 = 0x09;
pub const XINPUT_DATA: u8 = 0x04;

// Input report sizes
const DINPUT_PACKET_SIZE: usize = 13;
const XINPUT_PACKET_SIZE: usize = 60;
const KEYBOARD_PACKET_SIZE: usize = 15;
const MOUSE_PACKET_SIZE: usize = 7;
const TOUCHPAD_PACKET_SIZE: usize = 20;
const HID_TIMEOUT: i32 = 10;
// Input report axis ranges
// TODO: actual mouse range
// TODO: ACCEL Left/Right X/Y, Z?
//pub const GYRO_X_MAX: f64 = 255.0;
//pub const GYRO_X_MIN: f64 = 0.0;
//pub const GYRO_Y_MAX: f64 = 255.0;
//pub const GYRO_Y_MIN: f64 = 0.0;
pub const MOUSE_WHEEL_MAX: f64 = 120.0;
//pub const MOUSE_WHEEL_MIN: f64 = -120.0;
pub const PAD_X_MAX: f64 = 1024.0;
pub const PAD_X_MIN: f64 = 0.0;
pub const PAD_Y_MAX: f64 = 1024.0;
pub const PAD_Y_MIN: f64 = 0.0;
pub const STICK_X_MAX: f64 = 255.0;
pub const STICK_X_MIN: f64 = 0.0;
pub const STICK_Y_MAX: f64 = 255.0;
pub const STICK_Y_MIN: f64 = 0.0;
pub const TRIGG_MAX: f64 = 255.0;
//pub const TRIGG_MIN: f64 = 0.0;

pub struct Driver {
/// State for the left detachable controller when in dinput mode
dinputl_state: Option<DInputDataLeftReport>,
/// State for the right detachable controller when in dinput mode
dinputr_state: Option<DInputDataRightReport>,
/// State for the vitrual keyboard device on the left controller in FPS mode
keyboard_state: Option<KeyboardDataReport>,
/// State for the mouse device
mouse_state: Option<MouseDataReport>,
/// State for the touchpad device
touchpad_state: Option<TouchpadDataReport>,
/// State for the internal gamepad controller
xinput_state: Option<XInputDataReport>,
/// HIDRAW device instance
device: HidDevice,
/// Timestamp of the last touch event.
last_touch: Instant,
/// Whether or not we are detecting a touch event currently.
is_touching: bool,
}

impl Driver {
Expand All @@ -82,6 +87,8 @@ impl Driver {
keyboard_state: None,
mouse_state: None,
touchpad_state: None,
last_touch: Instant::now(),
is_touching: false,
})
}

Expand All @@ -96,15 +103,15 @@ impl Driver {
//log::trace!("Got Report ID: {report_id}");
//log::trace!("Got Report Size: {bytes_read}");

match report_id {
let mut events = match report_id {
DINPUT_LEFT_DATA => {
if bytes_read != DINPUT_PACKET_SIZE {
return Err("Invalid packet size for Direct Input Data.".into());
}
// Handle the incoming input report
let sized_buf = slice.try_into()?;
let events = self.handle_dinputl_report(sized_buf)?;
Ok(events)

self.handle_dinputl_report(sized_buf)?
}

DINPUT_RIGHT_DATA => {
Expand All @@ -113,8 +120,8 @@ impl Driver {
}
// Handle the incoming input report
let sized_buf = slice.try_into()?;
let events = self.handle_dinputr_report(sized_buf)?;
Ok(events)

self.handle_dinputr_report(sized_buf)?
}

KEYBOARD_TOUCH_DATA => {
Expand All @@ -125,13 +132,13 @@ impl Driver {
}
// Handle the incoming input report
let sized_buf = slice.try_into()?;
let events = self.handle_touchinput_report(sized_buf)?;
Ok(events)

self.handle_touchinput_report(sized_buf)?
} else {
// Handle the incoming input report
let sized_buf = slice.try_into()?;
let events = self.handle_keyboard_report(sized_buf)?;
Ok(events)

self.handle_keyboard_report(sized_buf)?
}
}

Expand All @@ -141,8 +148,8 @@ impl Driver {
}
// Handle the incoming input report
let sized_buf = slice.try_into()?;
let events = self.handle_mouseinput_report(sized_buf)?;
Ok(events)

self.handle_mouseinput_report(sized_buf)?
}

XINPUT_DATA => {
Expand All @@ -151,15 +158,22 @@ impl Driver {
}
// Handle the incoming input report
let sized_buf = slice.try_into()?;
let events = self.handle_xinput_report(sized_buf)?;
Ok(events)

self.handle_xinput_report(sized_buf)?
}
_ => {
//log::trace!("Invalid Report ID.");
let events = vec![];
Ok(events)
events
}
};

if self.is_touching && (self.last_touch.elapsed() > Duration::from_millis(4)) {
let event: Event = self.release_touch();
events.push(event);
}

Ok(events)
}
/// Unpacks the buffer into a [DInputDataReport] structure and updates
/// the internal dinput_state
Expand Down Expand Up @@ -346,11 +360,9 @@ impl Driver {
})));
}
if state.mouse_click != old_state.mouse_click {
events.push(Event::MouseButton(MouseButtonEvent::MouseClick(
BinaryInput {
pressed: state.mouse_click,
},
)));
events.push(Event::MouseButton(MouseButtonEvent::Left(BinaryInput {
pressed: state.mouse_click,
})));
}
if state.m2 != old_state.m2 {
events.push(Event::MouseButton(MouseButtonEvent::M2(BinaryInput {
Expand Down Expand Up @@ -412,14 +424,29 @@ impl Driver {
}

/// Translate the state into individual events
fn translate_touch(&self, _old_state: Option<TouchpadDataReport>) -> Vec<Event> {
let events = Vec::new();
let Some(_) = self.touchpad_state else {
fn translate_touch(&mut self, old_state: Option<TouchpadDataReport>) -> Vec<Event> {
let mut events = Vec::new();
let Some(state) = self.touchpad_state else {
return events;
};

// Translate state changes into events if they have changed
//if let Some(_) = old_state {}
let Some(_) = old_state else {
return events;
};
//// Axis events
if !self.is_touching {
self.is_touching = true;
log::trace!("Started TOUCH event");
}
events.push(Event::Axis(AxisEvent::Touchpad(TouchAxisInput {
index: 0,
is_touching: true,
x: state.touch_x_0,
y: state.touch_y_0,
})));

self.last_touch = Instant::now();
events
}

Expand Down Expand Up @@ -594,13 +621,6 @@ impl Driver {
})));
}

// Axis events
if state.touch_x_0 != old_state.touch_x_0 || state.touch_y_0 != old_state.touch_y_0 {
events.push(Event::Axis(AxisEvent::Touchpad(TouchAxisInput {
x: state.touch_x_0,
y: state.touch_y_0,
})));
}
if state.l_stick_x != old_state.l_stick_x || state.l_stick_y != old_state.l_stick_y {
events.push(Event::Axis(AxisEvent::LStick(JoyAxisInput {
x: state.l_stick_x,
Expand Down Expand Up @@ -690,4 +710,15 @@ impl Driver {

events
}

fn release_touch(&mut self) -> Event {
log::trace!("Released TOUCH event.");
self.is_touching = false;
Event::Axis(AxisEvent::Touchpad(TouchAxisInput {
index: 0,
is_touching: false,
x: 0,
y: 0,
}))
}
}
10 changes: 9 additions & 1 deletion src/drivers/lego/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,18 @@ pub struct BinaryInput {
/// Axis input contain (x, y) coordinates
#[derive(Clone, Debug)]
pub struct TouchAxisInput {
pub index: u8,
pub is_touching: bool,
pub x: u16,
pub y: u16,
}

/// TouchAxisID tracks the sequential count of touch inputs
#[derive(Clone, Debug)]
pub struct TouchAxisID {
pub value: u32,
}

/// Axis input contain (x, y) coordinates
#[derive(Clone, Debug)]
pub struct MouseAxisInput {
Expand Down Expand Up @@ -126,7 +134,7 @@ pub enum MouseButtonEvent {
/// M3 on the back of the right controller
M3(BinaryInput),
/// Mouse wheel click on the back of the right controller
MouseClick(BinaryInput),
Left(BinaryInput),
}

/// Axis events are events that have (x, y) values
Expand Down
Loading

0 comments on commit 3c03606

Please sign in to comment.