diff --git a/src/input/capability.rs b/src/input/capability.rs index 7c1462ef..ae0f4af8 100644 --- a/src/input/capability.rs +++ b/src/input/capability.rs @@ -517,8 +517,6 @@ pub enum GamepadAxis { Hat1, Hat2, Hat3, - /// Axis input from two binary button inputs - Buttons(GamepadButton, GamepadButton), } impl fmt::Display for GamepadAxis { @@ -530,7 +528,6 @@ impl fmt::Display for GamepadAxis { GamepadAxis::Hat1 => write!(f, "Hat1"), GamepadAxis::Hat2 => write!(f, "Hat2"), GamepadAxis::Hat3 => write!(f, "Hat3"), - GamepadAxis::Buttons(_, _) => write!(f, "Buttons"), } } } diff --git a/src/input/event/dbus.rs b/src/input/event/dbus.rs index 185f238b..01874a80 100644 --- a/src/input/event/dbus.rs +++ b/src/input/event/dbus.rs @@ -218,31 +218,6 @@ fn actions_from_capability(capability: Capability) -> Vec { GamepadAxis::Hat0 => { vec![Action::Left, Action::Right, Action::Up, Action::Down] } - GamepadAxis::Buttons(negative, positive) => { - let mut dpad_actions = vec![]; - // Match negative axis buttons (up and left) - match negative { - GamepadButton::DPadUp => { - dpad_actions.push(Action::Up); - } - GamepadButton::DPadLeft => { - dpad_actions.push(Action::Left); - } - _ => (), - }; - // Match positive axis buttons (down and right) - match positive { - GamepadButton::DPadDown => { - dpad_actions.push(Action::Down); - } - GamepadButton::DPadRight => { - dpad_actions.push(Action::Right); - } - _ => (), - } - - dpad_actions - } _ => vec![Action::None], }, _ => vec![Action::None], diff --git a/src/input/event/evdev.rs b/src/input/event/evdev.rs index 610a5bfb..1313d7dc 100644 --- a/src/input/event/evdev.rs +++ b/src/input/event/evdev.rs @@ -50,14 +50,20 @@ impl EvdevEvent { x: None, y: Some(normal_value), }, - AbsoluteAxisCode::ABS_HAT0X => InputValue::Vector2 { - x: Some(normal_value), - y: None, - }, - AbsoluteAxisCode::ABS_HAT0Y => InputValue::Vector2 { - x: None, - y: Some(normal_value), - }, + AbsoluteAxisCode::ABS_HAT0X => { + if normal_value == 0.0 { + InputValue::Bool(false) + } else { + InputValue::Bool(true) + } + } + AbsoluteAxisCode::ABS_HAT0Y => { + if normal_value == 0.0 { + InputValue::Bool(false) + } else { + InputValue::Bool(true) + } + } AbsoluteAxisCode::ABS_HAT1X => InputValue::Vector2 { x: Some(normal_value), y: None, @@ -427,12 +433,12 @@ impl EvdevEvent { AbsoluteAxisCode::ABS_RZ => { Capability::Gamepad(Gamepad::Trigger(GamepadTrigger::RightTrigger)) } - AbsoluteAxisCode::ABS_HAT0X => Capability::Gamepad(Gamepad::Axis( - GamepadAxis::Buttons(GamepadButton::DPadLeft, GamepadButton::DPadRight), - )), - AbsoluteAxisCode::ABS_HAT0Y => Capability::Gamepad(Gamepad::Axis( - GamepadAxis::Buttons(GamepadButton::DPadUp, GamepadButton::DPadDown), - )), + AbsoluteAxisCode::ABS_HAT0X => { + Capability::Gamepad(Gamepad::Axis(GamepadAxis::Hat0)) + } + AbsoluteAxisCode::ABS_HAT0Y => { + Capability::Gamepad(Gamepad::Axis(GamepadAxis::Hat0)) + } _ => Capability::NotImplemented, }, EventType::RELATIVE => match RelativeAxisCode(code) { @@ -635,9 +641,6 @@ fn event_codes_from_capability(capability: Capability) -> Vec { GamepadAxis::Hat3 => { vec![AbsoluteAxisCode::ABS_HAT3X.0, AbsoluteAxisCode::ABS_HAT3Y.0] } - GamepadAxis::Buttons(_, _) => { - vec![AbsoluteAxisCode::ABS_HAT0X.0, AbsoluteAxisCode::ABS_HAT0Y.0] - } }, Gamepad::Trigger(trigg) => match trigg { GamepadTrigger::LeftTrigger => { diff --git a/src/input/event/native.rs b/src/input/event/native.rs index 10a4f77f..bf31f49e 100644 --- a/src/input/event/native.rs +++ b/src/input/event/native.rs @@ -1,4 +1,6 @@ -use crate::input::capability::Capability; +use evdev::AbsoluteAxisCode; + +use crate::input::capability::{Capability, Gamepad, GamepadButton}; use super::{evdev::EvdevEvent, value::InputValue}; @@ -71,6 +73,49 @@ impl NativeEvent { pub fn pressed(&self) -> bool { self.value.pressed() } + + pub fn from_evdev_raw(event: EvdevEvent, hat_state: Option) -> NativeEvent { + // If this is a Dpad input, figure out with button this event is for + let capability = if let Some(old_state) = hat_state { + let axis = AbsoluteAxisCode(event.as_input_event().code()); + let value = event.as_input_event().value(); + + match axis { + AbsoluteAxisCode::ABS_HAT0X => match value { + -1 => Capability::Gamepad(Gamepad::Button(GamepadButton::DPadLeft)), + 1 => Capability::Gamepad(Gamepad::Button(GamepadButton::DPadRight)), + 0 => match old_state { + -1 => Capability::Gamepad(Gamepad::Button(GamepadButton::DPadLeft)), + 1 => Capability::Gamepad(Gamepad::Button(GamepadButton::DPadRight)), + _ => Capability::NotImplemented, + }, + _ => Capability::NotImplemented, + }, + AbsoluteAxisCode::ABS_HAT0Y => match value { + -1 => Capability::Gamepad(Gamepad::Button(GamepadButton::DPadUp)), + 1 => Capability::Gamepad(Gamepad::Button(GamepadButton::DPadDown)), + 0 => match old_state { + -1 => Capability::Gamepad(Gamepad::Button(GamepadButton::DPadUp)), + 1 => Capability::Gamepad(Gamepad::Button(GamepadButton::DPadDown)), + _ => Capability::NotImplemented, + }, + _ => Capability::NotImplemented, + }, + + _ => Capability::NotImplemented, + } + } else { + event.as_capability() + }; + + let value = event.get_value(); + + NativeEvent { + capability, + value, + source_capability: None, + } + } } impl From for NativeEvent { diff --git a/src/input/source/evdev.rs b/src/input/source/evdev.rs index efb68483..49bc267e 100644 --- a/src/input/source/evdev.rs +++ b/src/input/source/evdev.rs @@ -11,9 +11,9 @@ use crate::{ constants::BUS_PREFIX, drivers::dualsense::hid_report::SetStatePackedOutputData, input::{ - capability::Capability, + capability::{Capability, Gamepad, GamepadAxis, GamepadButton}, composite_device::client::CompositeDeviceClient, - event::{evdev::EvdevEvent, Event}, + event::{evdev::EvdevEvent, native::NativeEvent, Event}, output_event::OutputEvent, }, procfs, @@ -35,6 +35,7 @@ pub struct EventDevice { rx: mpsc::Receiver, ff_effects: HashMap, ff_effects_dualsense: Option, + hat_state: HashMap, } impl EventDevice { @@ -47,6 +48,7 @@ impl EventDevice { rx, ff_effects: HashMap::new(), ff_effects_dualsense: None, + hat_state: HashMap::new(), } } @@ -129,7 +131,7 @@ impl EventDevice { /// Process incoming events and send them to the composite device. async fn process_events( - &self, + &mut self, events: Vec, axes_info: &HashMap, ) -> Result<(), Box> { @@ -150,6 +152,26 @@ impl EventDevice { None }; + let state = if event.event_type() == EventType::ABSOLUTE { + let axis = AbsoluteAxisCode(event.code()); + + let state = match axis { + AbsoluteAxisCode::ABS_HAT0X | AbsoluteAxisCode::ABS_HAT0Y => { + let value = event.value(); + let last_value = *self.hat_state.get(&axis).unwrap_or(&0); + self.hat_state + .entry(axis) + .and_modify(|v| *v = value) + .or_insert(value); + Some(last_value) + } + _ => None, + }; + state + } else { + None + }; + // Convert the event into an [EvdevEvent] and optionally include // the axis information with min/max values let mut evdev_event: EvdevEvent = event.into(); @@ -157,8 +179,11 @@ impl EventDevice { evdev_event.set_abs_info(*info); } + // Convert the event into a [NativeEvent] + let native_event: NativeEvent = NativeEvent::from_evdev_raw(evdev_event, state); + // Send the event to the composite device - let event = Event::Evdev(evdev_event); + let event = Event::Native(native_event); self.composite_device .process_event(self.get_id(), event) .await?; @@ -432,6 +457,20 @@ impl EventDevice { let input_event = InputEvent::new(event.0, axis.0, 0); let evdev_event = EvdevEvent::from(input_event); let cap = evdev_event.as_capability(); + if cap == Capability::Gamepad(Gamepad::Axis(GamepadAxis::Hat0)) { + capabilities + .push(Capability::Gamepad(Gamepad::Button(GamepadButton::DPadUp))); + capabilities.push(Capability::Gamepad(Gamepad::Button( + GamepadButton::DPadDown, + ))); + capabilities.push(Capability::Gamepad(Gamepad::Button( + GamepadButton::DPadLeft, + ))); + capabilities.push(Capability::Gamepad(Gamepad::Button( + GamepadButton::DPadRight, + ))); + continue; + } capabilities.push(cap); } } diff --git a/src/input/target/dualsense.rs b/src/input/target/dualsense.rs index 9bdc1be5..f60be214 100644 --- a/src/input/target/dualsense.rs +++ b/src/input/target/dualsense.rs @@ -1483,217 +1483,6 @@ impl DualSenseDevice { GamepadAxis::Hat1 => (), GamepadAxis::Hat2 => (), GamepadAxis::Hat3 => (), - // TODO: Remove GamepadAxis::Buttons - // NativeEvent { capability: Gamepad(Axis(Buttons(DPadLeft, DPadRight))), source_capability: None, value: Vector2 { x: Some(1.0), y: None } } - GamepadAxis::Buttons(neg, _) => match neg { - GamepadButton::DPadUp => - { - #[allow(clippy::collapsible_match)] - if let InputValue::Vector2 { x: _, y } = value { - if let Some(y) = y { - let value = y as i8; - match value.cmp(&0) { - Ordering::Less => match self.state { - PackedInputDataReport::Usb(ref mut state) => { - match state.dpad { - Direction::East => { - state.dpad = Direction::NorthEast - } - Direction::West => { - state.dpad = Direction::NorthWest - } - _ => state.dpad = Direction::North, - } - } - PackedInputDataReport::Bluetooth(ref mut state) => { - match state.dpad { - Direction::East => { - state.dpad = Direction::NorthEast - } - Direction::West => { - state.dpad = Direction::NorthWest - } - _ => state.dpad = Direction::North, - } - } - }, - Ordering::Equal => match self.state { - PackedInputDataReport::Usb(ref mut state) => { - match state.dpad { - Direction::NorthWest => { - state.dpad = Direction::West - } - Direction::SouthWest => { - state.dpad = Direction::West - } - Direction::NorthEast => { - state.dpad = Direction::East - } - Direction::SouthEast => { - state.dpad = Direction::East - } - Direction::North => { - state.dpad = Direction::None - } - Direction::South => { - state.dpad = Direction::None - } - _ => (), - } - } - PackedInputDataReport::Bluetooth(ref mut state) => { - match state.dpad { - Direction::NorthWest => { - state.dpad = Direction::West - } - Direction::SouthWest => { - state.dpad = Direction::West - } - Direction::NorthEast => { - state.dpad = Direction::East - } - Direction::SouthEast => { - state.dpad = Direction::East - } - Direction::North => { - state.dpad = Direction::None - } - Direction::South => { - state.dpad = Direction::None - } - _ => (), - } - } - }, - Ordering::Greater => match self.state { - PackedInputDataReport::Usb(ref mut state) => { - match state.dpad { - Direction::East => { - state.dpad = Direction::SouthEast - } - Direction::West => { - state.dpad = Direction::SouthWest - } - _ => state.dpad = Direction::South, - } - } - PackedInputDataReport::Bluetooth(ref mut state) => { - match state.dpad { - Direction::East => { - state.dpad = Direction::SouthEast - } - Direction::West => { - state.dpad = Direction::SouthWest - } - _ => state.dpad = Direction::South, - } - } - }, - } - } - } - } - GamepadButton::DPadLeft => - { - #[allow(clippy::collapsible_match)] - if let InputValue::Vector2 { x, y: _ } = value { - if let Some(x) = x { - let value = x as i8; - match value.cmp(&0) { - Ordering::Less => match self.state { - PackedInputDataReport::Usb(ref mut state) => { - match state.dpad { - Direction::North => { - state.dpad = Direction::NorthWest - } - Direction::South => { - state.dpad = Direction::SouthWest - } - _ => state.dpad = Direction::West, - } - } - PackedInputDataReport::Bluetooth(ref mut state) => { - match state.dpad { - Direction::North => { - state.dpad = Direction::NorthWest - } - Direction::South => { - state.dpad = Direction::SouthWest - } - _ => state.dpad = Direction::West, - } - } - }, - Ordering::Equal => match self.state { - PackedInputDataReport::Usb(ref mut state) => { - match state.dpad { - Direction::NorthWest => { - state.dpad = Direction::North - } - Direction::SouthWest => { - state.dpad = Direction::South - } - Direction::NorthEast => { - state.dpad = Direction::North - } - Direction::SouthEast => { - state.dpad = Direction::South - } - Direction::East => state.dpad = Direction::None, - Direction::West => state.dpad = Direction::None, - _ => (), - } - } - PackedInputDataReport::Bluetooth(ref mut state) => { - match state.dpad { - Direction::NorthWest => { - state.dpad = Direction::North - } - Direction::SouthWest => { - state.dpad = Direction::South - } - Direction::NorthEast => { - state.dpad = Direction::North - } - Direction::SouthEast => { - state.dpad = Direction::South - } - Direction::East => state.dpad = Direction::None, - Direction::West => state.dpad = Direction::None, - _ => (), - } - } - }, - Ordering::Greater => match self.state { - PackedInputDataReport::Usb(ref mut state) => { - match state.dpad { - Direction::North => { - state.dpad = Direction::NorthEast - } - Direction::South => { - state.dpad = Direction::SouthEast - } - _ => state.dpad = Direction::East, - } - } - PackedInputDataReport::Bluetooth(ref mut state) => { - match state.dpad { - Direction::North => { - state.dpad = Direction::NorthEast - } - Direction::South => { - state.dpad = Direction::SouthEast - } - _ => state.dpad = Direction::East, - } - } - }, - } - } - } - } - _ => (), - }, }, Gamepad::Trigger(trigger) => match trigger { GamepadTrigger::LeftTrigger => { @@ -1875,14 +1664,6 @@ impl DualSenseDevice { fn get_capabilities(&self) -> Vec { vec![ Capability::Gamepad(Gamepad::Accelerometer), - Capability::Gamepad(Gamepad::Axis(GamepadAxis::Buttons( - GamepadButton::DPadUp, - GamepadButton::DPadDown, - ))), - Capability::Gamepad(Gamepad::Axis(GamepadAxis::Buttons( - GamepadButton::DPadLeft, - GamepadButton::DPadRight, - ))), Capability::Gamepad(Gamepad::Axis(GamepadAxis::LeftStick)), Capability::Gamepad(Gamepad::Axis(GamepadAxis::RightStick)), Capability::Gamepad(Gamepad::Button(GamepadButton::DPadDown)), diff --git a/src/input/target/steam_deck.rs b/src/input/target/steam_deck.rs index 9da13bca..efe6cc8f 100644 --- a/src/input/target/steam_deck.rs +++ b/src/input/target/steam_deck.rs @@ -408,7 +408,6 @@ impl SteamDeckDevice { GamepadAxis::Hat1 => (), GamepadAxis::Hat2 => (), GamepadAxis::Hat3 => (), - GamepadAxis::Buttons(_, _) => (), }, Gamepad::Trigger(_) => (), Gamepad::Accelerometer => (), diff --git a/src/input/target/xb360.rs b/src/input/target/xb360.rs index 1a3c55ae..41748756 100644 --- a/src/input/target/xb360.rs +++ b/src/input/target/xb360.rs @@ -403,14 +403,6 @@ impl XBox360Controller { /// Returns capabilities of the target device fn get_capabilities(&self) -> Vec { vec![ - Capability::Gamepad(Gamepad::Axis(GamepadAxis::Buttons( - GamepadButton::DPadUp, - GamepadButton::DPadDown, - ))), - Capability::Gamepad(Gamepad::Axis(GamepadAxis::Buttons( - GamepadButton::DPadLeft, - GamepadButton::DPadRight, - ))), Capability::Gamepad(Gamepad::Axis(GamepadAxis::LeftStick)), Capability::Gamepad(Gamepad::Axis(GamepadAxis::RightStick)), Capability::Gamepad(Gamepad::Button(GamepadButton::DPadDown)), diff --git a/src/input/target/xbox_elite.rs b/src/input/target/xbox_elite.rs index 7eef350d..21a7d4c4 100644 --- a/src/input/target/xbox_elite.rs +++ b/src/input/target/xbox_elite.rs @@ -408,14 +408,6 @@ impl XboxEliteController { /// Returns capabilities of the target device fn get_capabilities(&self) -> Vec { vec![ - Capability::Gamepad(Gamepad::Axis(GamepadAxis::Buttons( - GamepadButton::DPadUp, - GamepadButton::DPadDown, - ))), - Capability::Gamepad(Gamepad::Axis(GamepadAxis::Buttons( - GamepadButton::DPadLeft, - GamepadButton::DPadRight, - ))), Capability::Gamepad(Gamepad::Axis(GamepadAxis::LeftStick)), Capability::Gamepad(Gamepad::Axis(GamepadAxis::RightStick)), Capability::Gamepad(Gamepad::Button(GamepadButton::DPadDown)), diff --git a/src/input/target/xbox_series.rs b/src/input/target/xbox_series.rs index 9548a00c..241a91e8 100644 --- a/src/input/target/xbox_series.rs +++ b/src/input/target/xbox_series.rs @@ -404,14 +404,6 @@ impl XboxSeriesController { /// Returns capabilities of the target device fn get_capabilities(&self) -> Vec { vec![ - Capability::Gamepad(Gamepad::Axis(GamepadAxis::Buttons( - GamepadButton::DPadUp, - GamepadButton::DPadDown, - ))), - Capability::Gamepad(Gamepad::Axis(GamepadAxis::Buttons( - GamepadButton::DPadLeft, - GamepadButton::DPadRight, - ))), Capability::Gamepad(Gamepad::Axis(GamepadAxis::LeftStick)), Capability::Gamepad(Gamepad::Axis(GamepadAxis::RightStick)), Capability::Gamepad(Gamepad::Button(GamepadButton::DPadDown)),