From 4c91655bad8a42e26d44a4708dc9b1f662ff2bb7 Mon Sep 17 00:00:00 2001 From: William Edwards Date: Thu, 7 Mar 2024 13:04:57 -0800 Subject: [PATCH] feat(CapabilityMap): add capability mapping and translation support --- Cargo.lock | 2 +- Makefile | 20 +- .../capability_maps/onexplayer_type3.yaml | 50 +- ...player_amd.yaml => 50-onexplayer_amd.yaml} | 4 +- ...er_intel.yaml => 50-onexplayer_intel.yaml} | 4 +- ...i_a07.yaml => 50-onexplayer_mini_a07.yaml} | 4 +- .../{steam_deck.yaml => 50-steam_deck.yaml} | 3 - ...{gamepads.yaml => 70-generic_gamepad.yaml} | 3 - .../share/inputplumber/devices/xbox360.yaml | 30 - .../event_maps/onexplayer_type3.yaml | 45 -- .../schema/capability_map_v1.json | 335 ++++++++++ .../schema/composite_device_v1.json | 5 +- .../inputplumber/schema/event_map_v1.json | 90 --- src/config/mod.rs | 94 ++- src/input/capability.rs | 589 +++++++++++++++++- src/input/composite_device/mod.rs | 314 +++++++++- src/input/event/dbus.rs | 7 +- src/input/event/evdev.rs | 302 ++++++++- src/input/manager.rs | 65 +- src/input/source/hidraw/steam_deck.rs | 2 +- src/input/target/gamepad.rs | 2 +- src/input/target/keyboard.rs | 50 +- src/input/target/steam_deck.rs | 3 +- 23 files changed, 1709 insertions(+), 314 deletions(-) rename rootfs/usr/share/inputplumber/devices/{onexplayer_amd.yaml => 50-onexplayer_amd.yaml} (94%) rename rootfs/usr/share/inputplumber/devices/{onexplayer_intel.yaml => 50-onexplayer_intel.yaml} (92%) rename rootfs/usr/share/inputplumber/devices/{onexplayer_mini_a07.yaml => 50-onexplayer_mini_a07.yaml} (91%) rename rootfs/usr/share/inputplumber/devices/{steam_deck.yaml => 50-steam_deck.yaml} (92%) rename rootfs/usr/share/inputplumber/devices/{gamepads.yaml => 70-generic_gamepad.yaml} (89%) delete mode 100644 rootfs/usr/share/inputplumber/devices/xbox360.yaml delete mode 100644 rootfs/usr/share/inputplumber/event_maps/onexplayer_type3.yaml create mode 100644 rootfs/usr/share/inputplumber/schema/capability_map_v1.json delete mode 100644 rootfs/usr/share/inputplumber/schema/event_map_v1.json diff --git a/Cargo.lock b/Cargo.lock index 03468c57..f48c91f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -604,7 +604,7 @@ dependencies = [ [[package]] name = "inputplumber" -version = "0.4.2" +version = "0.4.3" dependencies = [ "evdev", "glob-match", diff --git a/Makefile b/Makefile index d9560428..fcd45b1c 100644 --- a/Makefile +++ b/Makefile @@ -43,10 +43,17 @@ install: build ## Install inputplumber to the given prefix (default: PREFIX=/usr $(PREFIX)/share/dbus-1/system.d/$(DBUS_NAME).conf install -D -m 644 rootfs/usr/lib/systemd/system/$(NAME).service \ $(PREFIX)/lib/systemd/system/$(NAME).service - install -D -m 644 rootfs/usr/share/$(NAME)/devices/steam_deck.yaml \ - $(PREFIX)/share/$(NAME)/devices/steam_deck.yaml + install -D -m 644 -t $(PREFIX)/share/$(NAME)/devices/ \ + rootfs/usr/share/$(NAME)/devices/* + install -D -m 644 -t $(PREFIX)/share/$(NAME)/schema/ \ + rootfs/usr/share/$(NAME)/schema/* + install -D -m 644 -t $(PREFIX)/share/$(NAME)/capability_maps/ \ + rootfs/usr/share/$(NAME)/capability_maps/* + install -D -m 644 -t $(PREFIX)/share/$(NAME)/profiles/ \ + rootfs/usr/share/$(NAME)/profiles/* + @echo "" - @echo "Install completed. Enable service with:" + @echo "Install completed. Enable service with:" @echo " systemctl enable --now $(NAME)" .PHONY: uninstall @@ -54,7 +61,10 @@ uninstall: ## Uninstall inputplumber rm $(PREFIX)/bin/$(NAME) rm $(PREFIX)/share/dbus-1/system.d/$(DBUS_NAME).conf rm $(PREFIX)/lib/systemd/system/$(NAME).service - rm $(PREFIX)/share/$(NAME)/devices/steam_deck.yaml + rm -rf $(PREFIX)/share/$(NAME)/devices/ + rm -rf $(PREFIX)/share/$(NAME)/schema/ + rm -rf $(PREFIX)/share/$(NAME)/capability_maps/ + rm -rf $(PREFIX)/share/$(NAME)/profiles/ ##@ Development @@ -77,7 +87,7 @@ run: setup debug ## Build and run .PHONY: clean clean: ## Remove build artifacts - rm -rf target + rm -rf target dist .cache .PHONY: format format: ## Run rustfmt on all source files diff --git a/rootfs/usr/share/inputplumber/capability_maps/onexplayer_type3.yaml b/rootfs/usr/share/inputplumber/capability_maps/onexplayer_type3.yaml index 7a909a51..ec7bb6ef 100644 --- a/rootfs/usr/share/inputplumber/capability_maps/onexplayer_type3.yaml +++ b/rootfs/usr/share/inputplumber/capability_maps/onexplayer_type3.yaml @@ -1,3 +1,4 @@ +# yaml-language-server: $schema=../schema/capability_map_v1.json # Schema version number version: 1 @@ -13,12 +14,49 @@ id: oxp3 # List of mapped events that are activated by a specific set of activation keys. mapping: - name: Turbo - from: keyboard - source_capabilities: - - Keyboard:Key:LeftCtrl - - Keyboard:Key:LeftAlt - - Keyboard:Key:LeftMeta - target_capability: Gamepad:Button:Base + source_events: + - keyboard: KeyLeftCtrl + - keyboard: KeyLeftAlt + - keyboard: KeyLeftMeta + target_event: + gamepad: + button: QuickAccess + - name: KB (Short Press) + source_events: + - keyboard: KeyRightCtrl + - keyboard: KeyLeftMeta + - keyboard: KeyO + target_event: + gamepad: + button: Keyboard + - name: Orange Button (Short Press) + source_events: + - keyboard: KeyLeftMeta + - keyboard: KeyD + target_event: + gamepad: + button: Guide + - name: Orange Button (Long Press) + source_events: + - keyboard: KeyLeftMeta + - keyboard: KeyG + target_event: + gamepad: + button: QuickAccess2 + - name: Turbo + Orange Button + source_events: + - keyboard: KeyLeftMeta + - keyboard: KeySysrq + target_event: + gamepad: + button: Screenshot + - name: KB + Orange Button + source_events: + - keyboard: KeyRightCtrl + - keyboard: KeyRightAlt + - keyboard: KeyDelete + target_event: + keyboard: KeyF13 # List of events to filter from the source devices filtered_events: [] diff --git a/rootfs/usr/share/inputplumber/devices/onexplayer_amd.yaml b/rootfs/usr/share/inputplumber/devices/50-onexplayer_amd.yaml similarity index 94% rename from rootfs/usr/share/inputplumber/devices/onexplayer_amd.yaml rename to rootfs/usr/share/inputplumber/devices/50-onexplayer_amd.yaml index 10443b55..b8cc2d66 100644 --- a/rootfs/usr/share/inputplumber/devices/onexplayer_amd.yaml +++ b/rootfs/usr/share/inputplumber/devices/50-onexplayer_amd.yaml @@ -51,5 +51,5 @@ target_devices: - mouse - keyboard -# The ID of a device event mapping in the 'event_maps' folder -event_map_id: oxp2 +# The ID of a device event mapping in the 'capability_maps' folder +capability_map_id: oxp2 diff --git a/rootfs/usr/share/inputplumber/devices/onexplayer_intel.yaml b/rootfs/usr/share/inputplumber/devices/50-onexplayer_intel.yaml similarity index 92% rename from rootfs/usr/share/inputplumber/devices/onexplayer_intel.yaml rename to rootfs/usr/share/inputplumber/devices/50-onexplayer_intel.yaml index 9a1c61ce..c49c6f05 100644 --- a/rootfs/usr/share/inputplumber/devices/onexplayer_intel.yaml +++ b/rootfs/usr/share/inputplumber/devices/50-onexplayer_intel.yaml @@ -39,5 +39,5 @@ target_devices: - mouse - keyboard -# The ID of a device event mapping in the 'event_maps' folder -event_map_id: oxp1 +# The ID of a device event mapping in the 'capability_maps' folder +capability_map_id: oxp1 diff --git a/rootfs/usr/share/inputplumber/devices/onexplayer_mini_a07.yaml b/rootfs/usr/share/inputplumber/devices/50-onexplayer_mini_a07.yaml similarity index 91% rename from rootfs/usr/share/inputplumber/devices/onexplayer_mini_a07.yaml rename to rootfs/usr/share/inputplumber/devices/50-onexplayer_mini_a07.yaml index d111f007..3c5710b9 100644 --- a/rootfs/usr/share/inputplumber/devices/onexplayer_mini_a07.yaml +++ b/rootfs/usr/share/inputplumber/devices/50-onexplayer_mini_a07.yaml @@ -35,5 +35,5 @@ target_devices: - mouse - keyboard -# The ID of a device event mapping in the 'event_maps' folder -event_map_id: oxp3 +# The ID of a device event mapping in the 'capability_maps' folder +capability_map_id: oxp3 diff --git a/rootfs/usr/share/inputplumber/devices/steam_deck.yaml b/rootfs/usr/share/inputplumber/devices/50-steam_deck.yaml similarity index 92% rename from rootfs/usr/share/inputplumber/devices/steam_deck.yaml rename to rootfs/usr/share/inputplumber/devices/50-steam_deck.yaml index 6f0ceab4..ba5ac695 100644 --- a/rootfs/usr/share/inputplumber/devices/steam_deck.yaml +++ b/rootfs/usr/share/inputplumber/devices/50-steam_deck.yaml @@ -35,6 +35,3 @@ target_devices: - gamepad - mouse - keyboard - -# The ID of a device event mapping in the 'event_maps' folder -event_map_id: deck diff --git a/rootfs/usr/share/inputplumber/devices/gamepads.yaml b/rootfs/usr/share/inputplumber/devices/70-generic_gamepad.yaml similarity index 89% rename from rootfs/usr/share/inputplumber/devices/gamepads.yaml rename to rootfs/usr/share/inputplumber/devices/70-generic_gamepad.yaml index 0fdfe0b5..5166f611 100644 --- a/rootfs/usr/share/inputplumber/devices/gamepads.yaml +++ b/rootfs/usr/share/inputplumber/devices/70-generic_gamepad.yaml @@ -25,6 +25,3 @@ target_devices: - gamepad - mouse - keyboard - -# The ID of a device event mapping in the 'event_maps' folder -event_map_id: xb360 diff --git a/rootfs/usr/share/inputplumber/devices/xbox360.yaml b/rootfs/usr/share/inputplumber/devices/xbox360.yaml deleted file mode 100644 index ef5c1eeb..00000000 --- a/rootfs/usr/share/inputplumber/devices/xbox360.yaml +++ /dev/null @@ -1,30 +0,0 @@ -# yaml-language-server: $schema=../schema/composite_device_v1.json -# Schema version number -version: 1 - -# The type of configuration schema -kind: CompositeDevice - -# Name of the composite device mapping -name: XBox 360 - -# Only use this profile if *any* of the given matches matches. If this list is -# empty, then the source devices will *always* be checked. -# /sys/class/dmi/id/product_name -matches: [] - -# One or more source devices to combine into a single virtual device. The events -# from these devices will be watched and translated according to the key map. -source_devices: - - group: gamepad - evdev: - name: Xbox 360 Wireless Receiver (XBOX) - -# The target input device(s) that the virtual device profile can use -target_devices: - - gamepad - - mouse - - keyboard - -# The ID of a device event mapping in the 'event_maps' folder -event_map_id: xb360 diff --git a/rootfs/usr/share/inputplumber/event_maps/onexplayer_type3.yaml b/rootfs/usr/share/inputplumber/event_maps/onexplayer_type3.yaml deleted file mode 100644 index 83221a76..00000000 --- a/rootfs/usr/share/inputplumber/event_maps/onexplayer_type3.yaml +++ /dev/null @@ -1,45 +0,0 @@ -# yaml-language-server: $schema=../schema/event_map_v1.json -# Schema version number -version: 1 - -# The type of configuration schema -kind: EventMap - -# Name for the device event map -name: OneXPlayer Type 3 - -# Unique identifier of the event mapping -id: oxp3 - -# List of mapped events that are activated by a specific set of activation keys. -mapping: - - name: Volume Up - from: keyboard - source_events: - - code: KEY_VOLUMEUP - type: EV_KEY - intermediary_event: - code: volume_up - - - name: Volume Down - from: keyboard - source_events: - - code: KEY_VOLUMEDOWN - type: EV_KEY - intermediary_event: - code: volume_down - - - name: Turbo - from: keyboard - source_events: - - code: KEY_LEFTCTL - type: EV_KEY - - code: KEY_LEFTALT - type: EV_KEY - - code: KEY_LEFTMETA - type: EV_KEY - emits: - code: base - -# List of events to filter from the source devices -filtered_events: [] diff --git a/rootfs/usr/share/inputplumber/schema/capability_map_v1.json b/rootfs/usr/share/inputplumber/schema/capability_map_v1.json new file mode 100644 index 00000000..20542821 --- /dev/null +++ b/rootfs/usr/share/inputplumber/schema/capability_map_v1.json @@ -0,0 +1,335 @@ +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$ref": "#/definitions/CapabilityMap", + "definitions": { + "CapabilityMap": { + "type": "object", + "additionalProperties": false, + "properties": { + "version": { + "type": "integer" + }, + "kind": { + "type": "string" + }, + "name": { + "type": "string" + }, + "id": { + "type": "string" + }, + "mapping": { + "type": "array", + "items": { + "$ref": "#/definitions/Mapping" + } + }, + "filtered_events": { + "type": "array", + "items": {} + } + }, + "required": [ + "filtered_events", + "id", + "kind", + "mapping", + "name", + "version" + ], + "title": "CapabilityMap" + }, + "Mapping": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "source_events": { + "type": "array", + "items": { + "$ref": "#/definitions/Capability" + } + }, + "target_event": { + "$ref": "#/definitions/Capability" + } + }, + "required": [ + "name", + "source_events", + "target_event" + ], + "title": "Mapping" + }, + "Capability": { + "type": "object", + "additionalProperties": false, + "properties": { + "keyboard": { + "type": "string", + "enum": [ + "KeyEsc", + "Key1", + "Key2", + "Key3", + "Key4", + "Key5", + "Key6", + "Key7", + "Key8", + "Key9", + "Key0", + "KeyMinus", + "KeyEqual", + "KeyBackspace", + "KeyTab", + "KeyQ", + "KeyW", + "KeyE", + "KeyR", + "KeyT", + "KeyY", + "KeyU", + "KeyI", + "KeyO", + "KeyP", + "KeyLeftBrace", + "KeyRightBrace", + "KeyEnter", + "KeyLeftCtrl", + "KeyA", + "KeyS", + "KeyD", + "KeyF", + "KeyG", + "KeyH", + "KeyJ", + "KeyK", + "KeyL", + "KeySemicolon", + "KeyApostrophe", + "KeyGrave", + "KeyLeftShift", + "KeyBackslash", + "KeyZ", + "KeyX", + "KeyC", + "KeyV", + "KeyB", + "KeyN", + "KeyM", + "KeyComma", + "KeyDot", + "KeySlash", + "KeyRightShift", + "KeyKpAsterisk", + "KeyLeftAlt", + "KeySpace", + "KeyCapslock", + "KeyF1", + "KeyF2", + "KeyF3", + "KeyF4", + "KeyF5", + "KeyF6", + "KeyF7", + "KeyF8", + "KeyF9", + "KeyF10", + "KeyNumlock", + "KeyScrollLock", + "KeyKp7", + "KeyKp8", + "KeyKp9", + "KeyKpMinus", + "KeyKp4", + "KeyKp5", + "KeyKp6", + "KeyKpPlus", + "KeyKp1", + "KeyKp2", + "KeyKp3", + "KeyKp0", + "KeyKpDot", + "KeyZenkakuhankaku", + "Key102nd", + "KeyF11", + "KeyF12", + "KeyRo", + "KeyKatakana", + "KeyHiragana", + "KeyHenkan", + "KeyKatakanaHiragana", + "KeyMuhenkan", + "KeyKpJpComma", + "KeyKpEnter", + "KeyRightCtrl", + "KeyKpSlash", + "KeySysrq", + "KeyRightAlt", + "KeyHome", + "KeyUp", + "KeyPageUp", + "KeyLeft", + "KeyRight", + "KeyEnd", + "KeyDown", + "KeyPageDown", + "KeyInsert", + "KeyDelete", + "KeyMute", + "KeyVolumeDown", + "KeyVolumeUp", + "KeyPower", + "KeyKpEqual", + "KeyPause", + "KeyKpComma", + "KeyHanja", + "KeyYen", + "KeyLeftMeta", + "KeyRightMeta", + "KeyCompose", + "KeyStop", + "KeyAgain", + "KeyProps", + "KeyUndo", + "KeyFront", + "KeyCopy", + "KeyOpen", + "KeyPaste", + "KeyFind", + "KeyCut", + "KeyHelp", + "KeyCalc", + "KeySleep", + "KeyWww", + "KeyBack", + "KeyForward", + "KeyEjectCD", + "KeyNextSong", + "KeyPlayPause", + "KeyPreviousSong", + "KeyStopCD", + "KeyRefresh", + "KeyEdit", + "KeyScrollUp", + "KeyScrollDown", + "KeyKpLeftParen", + "KeyKpRightParen", + "KeyF13", + "KeyF14", + "KeyF15", + "KeyF16", + "KeyF17", + "KeyF18", + "KeyF19", + "KeyF20", + "KeyF21", + "KeyF22", + "KeyF23", + "KeyF24" + ] + }, + "gamepad": { + "$ref": "#/definitions/GamepadCapability" + }, + "mouse": { + "$ref": "#/definitions/MouseCapability" + } + }, + "title": "Capability" + }, + "GamepadCapability": { + "type": "object", + "additionalProperties": false, + "properties": { + "axis": { + "type": "string", + "enum": [ + "LeftStick", + "RightStick", + "Hat1", + "Hat2", + "Hat3" + ] + }, + "button": { + "type": "string", + "enum": [ + "South", + "East", + "North", + "West", + "Start", + "Select", + "Guide", + "QuickAccess", + "QuickAccess2", + "Keyboard", + "Screenshot", + "DPadUp", + "DPadDown", + "DPadLeft", + "DPadRight", + "LeftBumper", + "LeftTop", + "LeftTrigger", + "LeftPaddle1", + "LeftPaddle2", + "LeftStick", + "LeftStickTouch", + "LeftTouchpadTouch", + "LeftTouchpadPress", + "RightBumper", + "RightTop", + "RightTrigger", + "RightPaddle1", + "RightPaddle2", + "RightStick", + "RightStickTouch", + "RightTouchpadTouch", + "RightTouchpadPress" + ] + }, + "trigger": { + "type": "string", + "enum": [ + "LeftTrigger", + "LeftTouchpadForce", + "LeftStickForce", + "RightTrigger", + "RightTouchpadForce", + "RightStickForce" + ] + } + }, + "title": "GamepadCapability" + }, + "MouseCapability": { + "type": "object", + "additionalProperties": false, + "properties": { + "button": { + "type": "string", + "enum": [ + "Left", + "Right", + "Middle", + "WheelUp", + "WheelDown", + "WheelLeft", + "WheelRight", + "Extra1", + "Extra2" + ] + }, + "motion": { + "type": "string" + } + }, + "title": "Mouse" + } + } +} diff --git a/rootfs/usr/share/inputplumber/schema/composite_device_v1.json b/rootfs/usr/share/inputplumber/schema/composite_device_v1.json index 0e1ddc81..b73e16e7 100644 --- a/rootfs/usr/share/inputplumber/schema/composite_device_v1.json +++ b/rootfs/usr/share/inputplumber/schema/composite_device_v1.json @@ -33,8 +33,8 @@ "$ref": "#/definitions/SourceDevice" } }, - "event_map_id": { - "description": "The ID of a device event mapping in the 'event_maps' directory", + "capability_map_id": { + "description": "The ID of a device event mapping in the 'capability_maps' directory", "type": "string" }, "target_devices": { @@ -53,7 +53,6 @@ } }, "required": [ - "event_map_id", "kind", "matches", "name", diff --git a/rootfs/usr/share/inputplumber/schema/event_map_v1.json b/rootfs/usr/share/inputplumber/schema/event_map_v1.json deleted file mode 100644 index e205e842..00000000 --- a/rootfs/usr/share/inputplumber/schema/event_map_v1.json +++ /dev/null @@ -1,90 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-06/schema#", - "$ref": "#/definitions/EventMap", - "definitions": { - "EventMap": { - "type": "object", - "additionalProperties": false, - "properties": { - "version": { - "type": "integer" - }, - "kind": { - "type": "string" - }, - "name": { - "type": "string" - }, - "id": { - "type": "string" - }, - "mapping": { - "type": "array", - "items": { - "$ref": "#/definitions/Mapping" - } - }, - "filtered_events": { - "type": "array", - "items": { - "$ref": "#/definitions/Event" - } - } - }, - "required": [ - "filtered_events", - "id", - "kind", - "mapping", - "name", - "version" - ], - "title": "EventMap" - }, - "Event": { - "type": "object", - "additionalProperties": false, - "properties": { - "code": { - "type": "string" - }, - "type": { - "type": "string" - } - }, - "required": [ - "code", - "type" - ], - "title": "Event" - }, - "Mapping": { - "type": "object", - "additionalProperties": false, - "properties": { - "name": { - "type": "string" - }, - "from": { - "type": "string" - }, - "source_events": { - "type": "array", - "items": { - "$ref": "#/definitions/Event" - } - }, - "emits": { - "$ref": "#/definitions/Event" - } - }, - "required": [ - "emits", - "from", - "name", - "source_events" - ], - "title": "Mapping" - } - } -} diff --git a/src/config/mod.rs b/src/config/mod.rs index 0c776f11..b19e7ec3 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -17,6 +17,63 @@ pub enum LoadError { DeserializeError(#[from] serde_yaml::Error), } +#[derive(Debug, Deserialize, Clone)] +#[serde(rename_all = "snake_case")] +pub struct CapabilityMap { + pub version: u32, + pub kind: String, + pub name: String, + pub id: String, + pub mapping: Vec, + //pub filtered_events: Option>, +} + +#[derive(Debug, Deserialize, Clone)] +#[serde(rename_all = "snake_case")] +pub struct CapabilityMapping { + pub name: String, + pub source_events: Vec, + pub target_event: Capability, +} + +#[derive(Debug, Deserialize, Clone)] +#[serde(rename_all = "snake_case")] +pub struct Capability { + pub gamepad: Option, + pub keyboard: Option, + pub mouse: Option, +} + +#[derive(Debug, Deserialize, Clone)] +#[serde(rename_all = "snake_case")] +pub struct GamepadCapability { + pub axis: Option, + pub button: Option, + pub trigger: Option, +} + +#[derive(Debug, Deserialize, Clone)] +#[serde(rename_all = "snake_case")] +pub struct MouseCapability { + pub button: Option, + pub motion: Option, +} + +impl CapabilityMap { + /// Load a [CapabilityMap] from the given YAML string + pub fn from_yaml(content: String) -> Result { + let device: CapabilityMap = serde_yaml::from_str(content.as_str())?; + Ok(device) + } + + /// Load a [CapabilityMap] from the given YAML file + pub fn from_yaml_file(path: String) -> Result { + let file = std::fs::File::open(path)?; + let device: CapabilityMap = serde_yaml::from_reader(file)?; + Ok(device) + } +} + /// Defines a platform match for loading a [CompositeDevice] #[derive(Debug, Deserialize, Clone)] #[serde(rename_all = "snake_case")] @@ -64,23 +121,6 @@ pub struct Hidraw { pub handler: Option, } -#[derive(Debug, Deserialize, Clone)] -#[serde(rename_all = "snake_case")] -pub struct EventMapping { - pub name: String, - pub from: String, - pub source_events: Vec, - pub emits: Event, -} - -#[derive(Debug, Deserialize, Clone)] -#[serde(rename_all = "snake_case")] -pub struct Event { - pub code: String, - #[serde(rename = "type")] - pub event_type: String, -} - /// Defines a combined device #[derive(Debug, Deserialize, Clone)] #[serde(rename_all = "snake_case")] @@ -89,7 +129,7 @@ pub struct CompositeDeviceConfig { pub kind: String, pub name: String, pub matches: Vec, - pub event_map_id: String, + pub capability_map_id: Option, pub source_devices: Vec, pub target_devices: Option>, } @@ -118,23 +158,22 @@ impl CompositeDeviceConfig { Ok(evdev_exists && hidraw_exists) } - /// Returns true if all the hidraw source devices in the config exist on the system + /// Returns true if any of the hidraw source devices in the config exist on the system fn sources_exist_hidraw(&self) -> Result> { let Some(hidraw_devices) = self.get_matching_hidraw()? else { return Ok(true); }; - Ok(hidraw_devices.len() >= 1) + Ok(!hidraw_devices.is_empty()) } - /// Returns true if all the evdev source devices in the config exist on the system + /// Returns true if any of the evdev source devices in the config exist on the system fn sources_exist_evdev(&self) -> Result> { let Some(evdev_devices) = self.get_matching_evdev()? else { return Ok(true); }; - let evdev_configs = self.get_evdev_configs(); - Ok(evdev_configs.len() >= 1) + Ok(!evdev_devices.is_empty()) } /// Returns an array of all defined hidraw source devices @@ -233,9 +272,11 @@ impl CompositeDeviceConfig { ) -> Result>, Box> { // Only consider evdev devices let evdev_configs = self.get_evdev_configs(); + log::debug!("Got evdev configs: {:?}", evdev_configs); // If there are no evdev definitions, consider it a match if evdev_configs.is_empty() { + log::debug!("No evdev config was defined"); return Ok(None); } let mut matches: Vec = Vec::new(); @@ -261,6 +302,7 @@ impl CompositeDeviceConfig { if !glob_match(name.as_str(), device.name.as_str()) { continue; } + log::debug!("Name in config '{}' matches device {}", name, device.name); has_matches = true; } @@ -268,6 +310,11 @@ impl CompositeDeviceConfig { if !glob_match(phys_path.as_str(), device.phys_path.as_str()) { continue; } + log::debug!( + "Phys path in config '{}' matches device {}", + phys_path, + device.phys_path + ); has_matches = true; } @@ -276,6 +323,7 @@ impl CompositeDeviceConfig { if !glob_match(handler.as_str(), handle.as_str()) { continue; } + log::debug!("Handler in config '{}' matches device {}", handler, handle); has_matches = true; } } diff --git a/src/input/capability.rs b/src/input/capability.rs index 662dab9b..3b524a24 100644 --- a/src/input/capability.rs +++ b/src/input/capability.rs @@ -1,6 +1,8 @@ +use std::{fmt, str::FromStr}; + /// A capability describes what kind of input events an input device is capable /// of emitting. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub enum Capability { /// Used to purposefully disable input capabilities None, @@ -13,7 +15,33 @@ pub enum Capability { Keyboard(Keyboard), } -#[derive(Clone, Debug)] +impl fmt::Display for Capability { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Capability::None => write!(f, "None"), + Capability::NotImplemented => write!(f, "NotImplemented"), + Capability::Sync => write!(f, "Sync"), + Capability::Gamepad(_) => write!(f, "Gamepad"), + Capability::Mouse(_) => write!(f, "Mouse"), + Capability::Keyboard(_) => write!(f, "Keyboard"), + } + } +} + +impl FromStr for Capability { + type Err = (); + + fn from_str(s: &str) -> Result { + match s { + "None" => Ok(Capability::None), + "NotImplemented" => Ok(Capability::NotImplemented), + "Sync" => Ok(Capability::Sync), + _ => Err(()), + } + } +} + +#[derive(Clone, Debug, PartialEq)] pub enum Gamepad { /// Gamepad Buttons typically use binary input that represents button presses Button(GamepadButton), @@ -26,7 +54,19 @@ pub enum Gamepad { Gyro, } -#[derive(Clone, Debug)] +impl fmt::Display for Gamepad { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Gamepad::Button(_) => write!(f, "Button"), + Gamepad::Axis(_) => write!(f, "Axis"), + Gamepad::Trigger(_) => write!(f, "Trigger"), + Gamepad::Accelerometer => write!(f, "Accelerometer"), + Gamepad::Gyro => write!(f, "Gyro"), + } + } +} + +#[derive(Clone, Debug, PartialEq)] pub enum Mouse { /// Represents (x, y) relative mouse motion Motion, @@ -34,7 +74,16 @@ pub enum Mouse { Button(MouseButton), } -#[derive(Clone, Debug)] +impl fmt::Display for Mouse { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Mouse::Motion => write!(f, "Motion"), + Mouse::Button(_) => write!(f, "Button"), + } + } +} + +#[derive(Clone, Debug, PartialEq)] pub enum MouseButton { /// Left mouse button Left, @@ -56,8 +105,24 @@ pub enum MouseButton { Extra2, } +impl fmt::Display for MouseButton { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + MouseButton::Left => write!(f, "Left"), + MouseButton::Right => write!(f, "Right"), + MouseButton::Middle => write!(f, "Middle"), + MouseButton::WheelUp => write!(f, "WheelUp"), + MouseButton::WheelDown => write!(f, "WheelDown"), + MouseButton::WheelLeft => write!(f, "WheelLeft"), + MouseButton::WheelRight => write!(f, "WheelRight"), + MouseButton::Extra1 => write!(f, "Extra1"), + MouseButton::Extra2 => write!(f, "Extra2"), + } + } +} + /// Gamepad Buttons typically use binary input that represents button presses -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub enum GamepadButton { /// South action, Sony Cross x, Xbox A, Nintendo B South, @@ -74,7 +139,13 @@ pub enum GamepadButton { /// Guide button, Sony PS, Xbox Home, Steam Deck ⧉ Guide, /// Base button, usually on the bottom right, Steam Quick Access Button (...) - Base, + QuickAccess, + /// Base button, usually on the bottom of the device + QuickAccess2, + /// Dedicated button for opening an on-screen keyboard + Keyboard, + /// Dedicated screenshot button + Screenshot, /// Directional Pad up DPadUp, /// Directional Pad down @@ -85,6 +156,8 @@ pub enum GamepadButton { DPadRight, /// Left shoulder button, Sony L1, Xbox LB LeftBumper, + /// Left top button on AyaNeo devices, inboard of left bumper + LeftTop, /// Left trigger button, Deck binary sensor for left trigger LeftTrigger, /// Left back paddle button, Xbox P3, Steam Deck L4 @@ -101,6 +174,8 @@ pub enum GamepadButton { LeftTouchpadPress, /// Right shoulder button, Sony R1, Xbox RB RightBumper, + /// Right top button on AyaNeo devices, inboard of right bumper + RightTop, /// Right trigger button, Deck binary sensor for right trigger RightTrigger, /// Right back paddle button, Xbox P1, Steam Deck R4 @@ -117,7 +192,90 @@ pub enum GamepadButton { RightTouchpadPress, } -#[derive(Clone, Debug)] +impl fmt::Display for GamepadButton { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + GamepadButton::South => write!(f, "South"), + GamepadButton::East => write!(f, "East"), + GamepadButton::North => write!(f, "North"), + GamepadButton::West => write!(f, "West"), + GamepadButton::Start => write!(f, "Start"), + GamepadButton::Select => write!(f, "Select"), + GamepadButton::Guide => write!(f, "Guide"), + GamepadButton::QuickAccess => write!(f, "QuickAccess"), + GamepadButton::QuickAccess2 => write!(f, "QuickAccess2"), + GamepadButton::Keyboard => write!(f, "Keyboard"), + GamepadButton::Screenshot => write!(f, "Screenshot"), + GamepadButton::DPadUp => write!(f, "DPadUp"), + GamepadButton::DPadDown => write!(f, "DPadDown"), + GamepadButton::DPadLeft => write!(f, "DPadLeft"), + GamepadButton::DPadRight => write!(f, "DPadRight"), + GamepadButton::LeftBumper => write!(f, "LeftBumper"), + GamepadButton::LeftTop => write!(f, "LeftTop"), + GamepadButton::LeftTrigger => write!(f, "LeftTrigger"), + GamepadButton::LeftPaddle1 => write!(f, "LeftPaddle1"), + GamepadButton::LeftPaddle2 => write!(f, "LeftPaddle2"), + GamepadButton::LeftStick => write!(f, "LeftStick"), + GamepadButton::LeftStickTouch => write!(f, "LeftStickTouch"), + GamepadButton::LeftTouchpadTouch => write!(f, "LeftTouchpadTouch"), + GamepadButton::LeftTouchpadPress => write!(f, "LeftTouchpadPress"), + GamepadButton::RightBumper => write!(f, "RightBumper"), + GamepadButton::RightTop => write!(f, "RightTop"), + GamepadButton::RightTrigger => write!(f, "RightTrigger"), + GamepadButton::RightPaddle1 => write!(f, "RightPaddle1"), + GamepadButton::RightPaddle2 => write!(f, "RightPaddle2"), + GamepadButton::RightStick => write!(f, "RightStick"), + GamepadButton::RightStickTouch => write!(f, "RightStickTouch"), + GamepadButton::RightTouchpadTouch => write!(f, "RightTouchpadTouch"), + GamepadButton::RightTouchpadPress => write!(f, "RightTouchpadPress"), + } + } +} + +impl FromStr for GamepadButton { + type Err = (); + + fn from_str(s: &str) -> Result { + match s { + "South" => Ok(GamepadButton::South), + "East" => Ok(GamepadButton::East), + "North" => Ok(GamepadButton::North), + "West" => Ok(GamepadButton::West), + "Start" => Ok(GamepadButton::Start), + "Select" => Ok(GamepadButton::Select), + "Guide" => Ok(GamepadButton::Guide), + "QuickAccess" => Ok(GamepadButton::QuickAccess), + "QuickAccess2" => Ok(GamepadButton::QuickAccess2), + "Keyboard" => Ok(GamepadButton::Keyboard), + "Screenshot" => Ok(GamepadButton::Screenshot), + "DPadUp" => Ok(GamepadButton::DPadUp), + "DPadDown" => Ok(GamepadButton::DPadDown), + "DPadLeft" => Ok(GamepadButton::DPadLeft), + "DPadRight" => Ok(GamepadButton::DPadRight), + "LeftBumper" => Ok(GamepadButton::LeftBumper), + "LeftTop" => Ok(GamepadButton::LeftTop), + "LeftTrigger" => Ok(GamepadButton::LeftTrigger), + "LeftPaddle1" => Ok(GamepadButton::LeftPaddle1), + "LeftPaddle2" => Ok(GamepadButton::LeftPaddle2), + "LeftStick" => Ok(GamepadButton::LeftStick), + "LeftStickTouch" => Ok(GamepadButton::LeftStickTouch), + "LeftTouchpadTouch" => Ok(GamepadButton::LeftTouchpadTouch), + "LeftTouchpadPress" => Ok(GamepadButton::LeftTouchpadPress), + "RightBumper" => Ok(GamepadButton::RightBumper), + "RightTop" => Ok(GamepadButton::RightTop), + "RightTrigger" => Ok(GamepadButton::RightTrigger), + "RightPaddle1" => Ok(GamepadButton::RightPaddle1), + "RightPaddle2" => Ok(GamepadButton::RightPaddle2), + "RightStick" => Ok(GamepadButton::RightStick), + "RightStickTouch" => Ok(GamepadButton::RightStickTouch), + "RightTouchpadTouch" => Ok(GamepadButton::RightTouchpadTouch), + "RightTouchpadPress" => Ok(GamepadButton::RightTouchpadPress), + _ => Err(()), + } + } +} + +#[derive(Clone, Debug, PartialEq)] pub enum GamepadAxis { LeftStick, RightStick, @@ -128,7 +286,20 @@ pub enum GamepadAxis { Buttons(GamepadButton, GamepadButton), } -#[derive(Clone, Debug)] +impl fmt::Display for GamepadAxis { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + GamepadAxis::LeftStick => write!(f, "LeftStick"), + GamepadAxis::RightStick => write!(f, "RightStick"), + GamepadAxis::Hat1 => write!(f, "Hat1"), + GamepadAxis::Hat2 => write!(f, "Hat2"), + GamepadAxis::Hat3 => write!(f, "Hat3"), + GamepadAxis::Buttons(_, _) => write!(f, "Buttons"), + } + } +} + +#[derive(Clone, Debug, PartialEq)] pub enum GamepadTrigger { LeftTrigger, LeftTouchpadForce, @@ -138,7 +309,20 @@ pub enum GamepadTrigger { RightStickForce, } -#[derive(Clone, Debug)] +impl fmt::Display for GamepadTrigger { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + GamepadTrigger::LeftTrigger => write!(f, "LeftTrigger"), + GamepadTrigger::LeftTouchpadForce => write!(f, "LeftTouchpadForce"), + GamepadTrigger::LeftStickForce => write!(f, "LeftStickForce"), + GamepadTrigger::RightTrigger => write!(f, "RightTrigger"), + GamepadTrigger::RightTouchpadForce => write!(f, "RightTouchpadForce"), + GamepadTrigger::RightStickForce => write!(f, "RightStickForce"), + } + } +} + +#[derive(Clone, Debug, PartialEq)] pub enum Keyboard { KeyEsc, Key1, @@ -193,8 +377,8 @@ pub enum Keyboard { KeyComma, KeyDot, KeySlash, - KeyRightshift, - KeyKpasterisk, + KeyRightShift, + KeyKpAsterisk, KeyLeftAlt, KeySpace, KeyCapslock, @@ -209,20 +393,20 @@ pub enum Keyboard { KeyF9, KeyF10, KeyNumlock, - KeyScrolllock, + KeyScrollLock, KeyKp7, KeyKp8, KeyKp9, - KeyKpminus, + KeyKpMinus, KeyKp4, KeyKp5, KeyKp6, - KeyKpplus, + KeyKpPlus, KeyKp1, KeyKp2, KeyKp3, KeyKp0, - KeyKpdot, + KeyKpDot, KeyZenkakuhankaku, Key102nd, KeyF11, @@ -231,35 +415,35 @@ pub enum Keyboard { KeyKatakana, KeyHiragana, KeyHenkan, - KeyKatakanahiragana, + KeyKatakanaHiragana, KeyMuhenkan, - KeyKpjpcomma, - KeyKpenter, - KeyRightctrl, - KeyKpslash, + KeyKpJpComma, + KeyKpEnter, + KeyRightCtrl, + KeyKpSlash, KeySysrq, - KeyRightalt, + KeyRightAlt, KeyHome, KeyUp, - KeyPageup, + KeyPageUp, KeyLeft, KeyRight, KeyEnd, KeyDown, - KeyPagedown, + KeyPageDown, KeyInsert, KeyDelete, KeyMute, KeyVolumeDown, KeyVolumeUp, KeyPower, - KeyKpequal, + KeyKpEqual, KeyPause, - KeyKpcomma, + KeyKpComma, KeyHanja, KeyYen, - KeyLeftmeta, - KeyRightmeta, + KeyLeftMeta, + KeyRightMeta, KeyCompose, KeyStop, KeyAgain, @@ -277,17 +461,17 @@ pub enum Keyboard { KeyWww, KeyBack, KeyForward, - KeyEjectcd, - KeyNextsong, - KeyPlaypause, - KeyPrevioussong, - KeyStopcd, + KeyEjectCD, + KeyNextSong, + KeyPlayPause, + KeyPreviousSong, + KeyStopCD, KeyRefresh, KeyEdit, KeyScrollUp, KeyScrollDown, - KeyKpleftparen, - KeyKprightparen, + KeyKpLeftParen, + KeyKpRightParen, KeyF13, KeyF14, KeyF15, @@ -301,3 +485,340 @@ pub enum Keyboard { KeyF23, KeyF24, } + +impl fmt::Display for Keyboard { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Keyboard::KeyEsc => write!(f, "KeyEsc"), + Keyboard::Key1 => write!(f, "Key1"), + Keyboard::Key2 => write!(f, "Key2"), + Keyboard::Key3 => write!(f, "Key3"), + Keyboard::Key4 => write!(f, "Key4"), + Keyboard::Key5 => write!(f, "Key5"), + Keyboard::Key6 => write!(f, "Key6"), + Keyboard::Key7 => write!(f, "Key7"), + Keyboard::Key8 => write!(f, "Key8"), + Keyboard::Key9 => write!(f, "Key9"), + Keyboard::Key0 => write!(f, "Key0"), + Keyboard::KeyMinus => write!(f, "KeyMinus"), + Keyboard::KeyEqual => write!(f, "KeyEqual"), + Keyboard::KeyBackspace => write!(f, "KeyBackspace"), + Keyboard::KeyTab => write!(f, "KeyTab"), + Keyboard::KeyQ => write!(f, "KeyQ"), + Keyboard::KeyW => write!(f, "KeyW"), + Keyboard::KeyE => write!(f, "KeyE"), + Keyboard::KeyR => write!(f, "KeyR"), + Keyboard::KeyT => write!(f, "KeyT"), + Keyboard::KeyY => write!(f, "KeyY"), + Keyboard::KeyU => write!(f, "KeyU"), + Keyboard::KeyI => write!(f, "KeyI"), + Keyboard::KeyO => write!(f, "KeyO"), + Keyboard::KeyP => write!(f, "KeyP"), + Keyboard::KeyLeftBrace => write!(f, "KeyLeftBrace"), + Keyboard::KeyRightBrace => write!(f, "KeyRightBrace"), + Keyboard::KeyEnter => write!(f, "KeyEnter"), + Keyboard::KeyLeftCtrl => write!(f, "KeyLeftCtrl"), + Keyboard::KeyA => write!(f, "KeyA"), + Keyboard::KeyS => write!(f, "KeyS"), + Keyboard::KeyD => write!(f, "KeyD"), + Keyboard::KeyF => write!(f, "KeyF"), + Keyboard::KeyG => write!(f, "KeyG"), + Keyboard::KeyH => write!(f, "KeyH"), + Keyboard::KeyJ => write!(f, "KeyJ"), + Keyboard::KeyK => write!(f, "KeyK"), + Keyboard::KeyL => write!(f, "KeyL"), + Keyboard::KeySemicolon => write!(f, "KeySemicolon"), + Keyboard::KeyApostrophe => write!(f, "KeyApostrophe"), + Keyboard::KeyGrave => write!(f, "KeyGrave"), + Keyboard::KeyLeftShift => write!(f, "KeyLeftShift"), + Keyboard::KeyBackslash => write!(f, "KeyBackslash"), + Keyboard::KeyZ => write!(f, "KeyZ"), + Keyboard::KeyX => write!(f, "KeyX"), + Keyboard::KeyC => write!(f, "KeyC"), + Keyboard::KeyV => write!(f, "KeyV"), + Keyboard::KeyB => write!(f, "KeyB"), + Keyboard::KeyN => write!(f, "KeyN"), + Keyboard::KeyM => write!(f, "KeyM"), + Keyboard::KeyComma => write!(f, "KeyComma"), + Keyboard::KeyDot => write!(f, "KeyDot"), + Keyboard::KeySlash => write!(f, "KeySlash"), + Keyboard::KeyRightShift => write!(f, "KeyRightShift"), + Keyboard::KeyKpAsterisk => write!(f, "KeyKpAsterisk"), + Keyboard::KeyLeftAlt => write!(f, "KeyLeftAlt"), + Keyboard::KeySpace => write!(f, "KeySpace"), + Keyboard::KeyCapslock => write!(f, "KeyCapslock"), + Keyboard::KeyF1 => write!(f, "KeyF1"), + Keyboard::KeyF2 => write!(f, "KeyF2"), + Keyboard::KeyF3 => write!(f, "KeyF3"), + Keyboard::KeyF4 => write!(f, "KeyF4"), + Keyboard::KeyF5 => write!(f, "KeyF5"), + Keyboard::KeyF6 => write!(f, "KeyF6"), + Keyboard::KeyF7 => write!(f, "KeyF7"), + Keyboard::KeyF8 => write!(f, "KeyF8"), + Keyboard::KeyF9 => write!(f, "KeyF9"), + Keyboard::KeyF10 => write!(f, "KeyF10"), + Keyboard::KeyNumlock => write!(f, "KeyNumlock"), + Keyboard::KeyScrollLock => write!(f, "KeyScrollLock"), + Keyboard::KeyKp7 => write!(f, "KeyKp7"), + Keyboard::KeyKp8 => write!(f, "KeyKp8"), + Keyboard::KeyKp9 => write!(f, "KeyKp9"), + Keyboard::KeyKpMinus => write!(f, "KeyKpMinus"), + Keyboard::KeyKp4 => write!(f, "KeyKp4"), + Keyboard::KeyKp5 => write!(f, "KeyKp5"), + Keyboard::KeyKp6 => write!(f, "KeyKp6"), + Keyboard::KeyKpPlus => write!(f, "KeyKpPlus"), + Keyboard::KeyKp1 => write!(f, "KeyKp1"), + Keyboard::KeyKp2 => write!(f, "KeyKp2"), + Keyboard::KeyKp3 => write!(f, "KeyKp3"), + Keyboard::KeyKp0 => write!(f, "KeyKp0"), + Keyboard::KeyKpDot => write!(f, "KeyKpDot"), + Keyboard::KeyZenkakuhankaku => write!(f, "KeyZenkakuhankaku"), + Keyboard::Key102nd => write!(f, "Key102nd"), + Keyboard::KeyF11 => write!(f, "KeyF11"), + Keyboard::KeyF12 => write!(f, "KeyF12"), + Keyboard::KeyRo => write!(f, "KeyRo"), + Keyboard::KeyKatakana => write!(f, "KeyKatakana"), + Keyboard::KeyHiragana => write!(f, "KeyHiragana"), + Keyboard::KeyHenkan => write!(f, "KeyHenkan"), + Keyboard::KeyKatakanaHiragana => write!(f, "KeyKatakanaHiragana"), + Keyboard::KeyMuhenkan => write!(f, "KeyMuhenkan"), + Keyboard::KeyKpJpComma => write!(f, "KeyKpJpComma"), + Keyboard::KeyKpEnter => write!(f, "KeyKpEnter"), + Keyboard::KeyRightCtrl => write!(f, "KeyRightCtrl"), + Keyboard::KeyKpSlash => write!(f, "KeyKpSlash"), + Keyboard::KeySysrq => write!(f, "KeySysrq"), + Keyboard::KeyRightAlt => write!(f, "KeyRightAlt"), + Keyboard::KeyHome => write!(f, "KeyHome"), + Keyboard::KeyUp => write!(f, "KeyUp"), + Keyboard::KeyPageUp => write!(f, "KeyPageUp"), + Keyboard::KeyLeft => write!(f, "KeyLeft"), + Keyboard::KeyRight => write!(f, "KeyRight"), + Keyboard::KeyEnd => write!(f, "KeyEnd"), + Keyboard::KeyDown => write!(f, "KeyDown"), + Keyboard::KeyPageDown => write!(f, "KeyPageDown"), + Keyboard::KeyInsert => write!(f, "KeyInsert"), + Keyboard::KeyDelete => write!(f, "KeyDelete"), + Keyboard::KeyMute => write!(f, "KeyMute"), + Keyboard::KeyVolumeDown => write!(f, "KeyVolumeDown"), + Keyboard::KeyVolumeUp => write!(f, "KeyVolumeUp"), + Keyboard::KeyPower => write!(f, "KeyPower"), + Keyboard::KeyKpEqual => write!(f, "KeyKpEqual"), + Keyboard::KeyPause => write!(f, "KeyPause"), + Keyboard::KeyKpComma => write!(f, "KeyKpComma"), + Keyboard::KeyHanja => write!(f, "KeyHanja"), + Keyboard::KeyYen => write!(f, "KeyYen"), + Keyboard::KeyLeftMeta => write!(f, "KeyLeftMeta"), + Keyboard::KeyRightMeta => write!(f, "KeyRightMeta"), + Keyboard::KeyCompose => write!(f, "KeyCompose"), + Keyboard::KeyStop => write!(f, "KeyStop"), + Keyboard::KeyAgain => write!(f, "KeyAgain"), + Keyboard::KeyProps => write!(f, "KeyProps"), + Keyboard::KeyUndo => write!(f, "KeyUndo"), + Keyboard::KeyFront => write!(f, "KeyFront"), + Keyboard::KeyCopy => write!(f, "KeyCopy"), + Keyboard::KeyOpen => write!(f, "KeyOpen"), + Keyboard::KeyPaste => write!(f, "KeyPaste"), + Keyboard::KeyFind => write!(f, "KeyFind"), + Keyboard::KeyCut => write!(f, "KeyCut"), + Keyboard::KeyHelp => write!(f, "KeyHelp"), + Keyboard::KeyCalc => write!(f, "KeyCalc"), + Keyboard::KeySleep => write!(f, "KeySleep"), + Keyboard::KeyWww => write!(f, "KeyWww"), + Keyboard::KeyBack => write!(f, "KeyBack"), + Keyboard::KeyForward => write!(f, "KeyForward"), + Keyboard::KeyEjectCD => write!(f, "KeyEjectCD"), + Keyboard::KeyNextSong => write!(f, "KeyNextSong"), + Keyboard::KeyPlayPause => write!(f, "KeyPlayPause"), + Keyboard::KeyPreviousSong => write!(f, "KeyPreviousSong"), + Keyboard::KeyStopCD => write!(f, "KeyStopCD"), + Keyboard::KeyRefresh => write!(f, "KeyRefresh"), + Keyboard::KeyEdit => write!(f, "KeyEdit"), + Keyboard::KeyScrollUp => write!(f, "KeyScrollUp"), + Keyboard::KeyScrollDown => write!(f, "KeyScrollDown"), + Keyboard::KeyKpLeftParen => write!(f, "KeyKpLeftParen"), + Keyboard::KeyKpRightParen => write!(f, "KeyKpRightParen"), + Keyboard::KeyF13 => write!(f, "KeyF13"), + Keyboard::KeyF14 => write!(f, "KeyF14"), + Keyboard::KeyF15 => write!(f, "KeyF15"), + Keyboard::KeyF16 => write!(f, "KeyF16"), + Keyboard::KeyF17 => write!(f, "KeyF17"), + Keyboard::KeyF18 => write!(f, "KeyF18"), + Keyboard::KeyF19 => write!(f, "KeyF19"), + Keyboard::KeyF20 => write!(f, "KeyF20"), + Keyboard::KeyF21 => write!(f, "KeyF21"), + Keyboard::KeyF22 => write!(f, "KeyF22"), + Keyboard::KeyF23 => write!(f, "KeyF23"), + Keyboard::KeyF24 => write!(f, "KeyF24"), + } + } +} + +impl FromStr for Keyboard { + type Err = (); + + fn from_str(s: &str) -> Result { + match s { + "KeyEsc" => Ok(Keyboard::KeyEsc), + "Key1" => Ok(Keyboard::Key1), + "Key2" => Ok(Keyboard::Key2), + "Key3" => Ok(Keyboard::Key3), + "Key4" => Ok(Keyboard::Key4), + "Key5" => Ok(Keyboard::Key5), + "Key6" => Ok(Keyboard::Key6), + "Key7" => Ok(Keyboard::Key7), + "Key8" => Ok(Keyboard::Key8), + "Key9" => Ok(Keyboard::Key9), + "Key0" => Ok(Keyboard::Key0), + "KeyMinus" => Ok(Keyboard::KeyMinus), + "KeyEqual" => Ok(Keyboard::KeyEqual), + "KeyBackspace" => Ok(Keyboard::KeyBackspace), + "KeyTab" => Ok(Keyboard::KeyTab), + "KeyQ" => Ok(Keyboard::KeyQ), + "KeyW" => Ok(Keyboard::KeyW), + "KeyE" => Ok(Keyboard::KeyE), + "KeyR" => Ok(Keyboard::KeyR), + "KeyT" => Ok(Keyboard::KeyT), + "KeyY" => Ok(Keyboard::KeyY), + "KeyU" => Ok(Keyboard::KeyU), + "KeyI" => Ok(Keyboard::KeyI), + "KeyO" => Ok(Keyboard::KeyO), + "KeyP" => Ok(Keyboard::KeyP), + "KeyLeftBrace" => Ok(Keyboard::KeyLeftBrace), + "KeyRightBrace" => Ok(Keyboard::KeyRightBrace), + "KeyEnter" => Ok(Keyboard::KeyEnter), + "KeyLeftCtrl" => Ok(Keyboard::KeyLeftCtrl), + "KeyA" => Ok(Keyboard::KeyA), + "KeyS" => Ok(Keyboard::KeyS), + "KeyD" => Ok(Keyboard::KeyD), + "KeyF" => Ok(Keyboard::KeyF), + "KeyG" => Ok(Keyboard::KeyG), + "KeyH" => Ok(Keyboard::KeyH), + "KeyJ" => Ok(Keyboard::KeyJ), + "KeyK" => Ok(Keyboard::KeyK), + "KeyL" => Ok(Keyboard::KeyL), + "KeySemicolon" => Ok(Keyboard::KeySemicolon), + "KeyApostrophe" => Ok(Keyboard::KeyApostrophe), + "KeyGrave" => Ok(Keyboard::KeyGrave), + "KeyLeftShift" => Ok(Keyboard::KeyLeftShift), + "KeyBackslash" => Ok(Keyboard::KeyBackslash), + "KeyZ" => Ok(Keyboard::KeyZ), + "KeyX" => Ok(Keyboard::KeyX), + "KeyC" => Ok(Keyboard::KeyC), + "KeyV" => Ok(Keyboard::KeyV), + "KeyB" => Ok(Keyboard::KeyB), + "KeyN" => Ok(Keyboard::KeyN), + "KeyM" => Ok(Keyboard::KeyM), + "KeyComma" => Ok(Keyboard::KeyComma), + "KeyDot" => Ok(Keyboard::KeyDot), + "KeySlash" => Ok(Keyboard::KeySlash), + "KeyRightShift" => Ok(Keyboard::KeyRightShift), + "KeyKpAsterisk" => Ok(Keyboard::KeyKpAsterisk), + "KeyLeftAlt" => Ok(Keyboard::KeyLeftAlt), + "KeySpace" => Ok(Keyboard::KeySpace), + "KeyCapslock" => Ok(Keyboard::KeyCapslock), + "KeyF1" => Ok(Keyboard::KeyF1), + "KeyF2" => Ok(Keyboard::KeyF2), + "KeyF3" => Ok(Keyboard::KeyF3), + "KeyF4" => Ok(Keyboard::KeyF4), + "KeyF5" => Ok(Keyboard::KeyF5), + "KeyF6" => Ok(Keyboard::KeyF6), + "KeyF7" => Ok(Keyboard::KeyF7), + "KeyF8" => Ok(Keyboard::KeyF8), + "KeyF9" => Ok(Keyboard::KeyF9), + "KeyF10" => Ok(Keyboard::KeyF10), + "KeyNumlock" => Ok(Keyboard::KeyNumlock), + "KeyScrollLock" => Ok(Keyboard::KeyScrollLock), + "KeyKp7" => Ok(Keyboard::KeyKp7), + "KeyKp8" => Ok(Keyboard::KeyKp8), + "KeyKp9" => Ok(Keyboard::KeyKp9), + "KeyKpMinus" => Ok(Keyboard::KeyKpMinus), + "KeyKp4" => Ok(Keyboard::KeyKp4), + "KeyKp5" => Ok(Keyboard::KeyKp5), + "KeyKp6" => Ok(Keyboard::KeyKp6), + "KeyKpPlus" => Ok(Keyboard::KeyKpPlus), + "KeyKp1" => Ok(Keyboard::KeyKp1), + "KeyKp2" => Ok(Keyboard::KeyKp2), + "KeyKp3" => Ok(Keyboard::KeyKp3), + "KeyKp0" => Ok(Keyboard::KeyKp0), + "KeyKpdot" => Ok(Keyboard::KeyKpDot), + "KeyZenkakuhankaku" => Ok(Keyboard::KeyZenkakuhankaku), + "Key102nd" => Ok(Keyboard::Key102nd), + "KeyF11" => Ok(Keyboard::KeyF11), + "KeyF12" => Ok(Keyboard::KeyF12), + "KeyRo" => Ok(Keyboard::KeyRo), + "KeyKatakana" => Ok(Keyboard::KeyKatakana), + "KeyHiragana" => Ok(Keyboard::KeyHiragana), + "KeyHenkan" => Ok(Keyboard::KeyHenkan), + "KeyKatakanaHiragana" => Ok(Keyboard::KeyKatakanaHiragana), + "KeyMuhenkan" => Ok(Keyboard::KeyMuhenkan), + "KeyKpJpComma" => Ok(Keyboard::KeyKpJpComma), + "KeyKpEnter" => Ok(Keyboard::KeyKpEnter), + "KeyRightCtrl" => Ok(Keyboard::KeyRightCtrl), + "KeyKpSlash" => Ok(Keyboard::KeyKpSlash), + "KeySysrq" => Ok(Keyboard::KeySysrq), + "KeyRightAlt" => Ok(Keyboard::KeyRightAlt), + "KeyHome" => Ok(Keyboard::KeyHome), + "KeyUp" => Ok(Keyboard::KeyUp), + "KeyPageUp" => Ok(Keyboard::KeyPageUp), + "KeyLeft" => Ok(Keyboard::KeyLeft), + "KeyRight" => Ok(Keyboard::KeyRight), + "KeyEnd" => Ok(Keyboard::KeyEnd), + "KeyDown" => Ok(Keyboard::KeyDown), + "KeyPageDown" => Ok(Keyboard::KeyPageDown), + "KeyInsert" => Ok(Keyboard::KeyInsert), + "KeyDelete" => Ok(Keyboard::KeyDelete), + "KeyMute" => Ok(Keyboard::KeyMute), + "KeyVolumeDown" => Ok(Keyboard::KeyVolumeDown), + "KeyVolumeUp" => Ok(Keyboard::KeyVolumeUp), + "KeyPower" => Ok(Keyboard::KeyPower), + "KeyKpEqual" => Ok(Keyboard::KeyKpEqual), + "KeyPause" => Ok(Keyboard::KeyPause), + "KeyKpComma" => Ok(Keyboard::KeyKpComma), + "KeyHanja" => Ok(Keyboard::KeyHanja), + "KeyYen" => Ok(Keyboard::KeyYen), + "KeyLeftMeta" => Ok(Keyboard::KeyLeftMeta), + "KeyRightMeta" => Ok(Keyboard::KeyRightMeta), + "KeyCompose" => Ok(Keyboard::KeyCompose), + "KeyStop" => Ok(Keyboard::KeyStop), + "KeyAgain" => Ok(Keyboard::KeyAgain), + "KeyProps" => Ok(Keyboard::KeyProps), + "KeyUndo" => Ok(Keyboard::KeyUndo), + "KeyFront" => Ok(Keyboard::KeyFront), + "KeyCopy" => Ok(Keyboard::KeyCopy), + "KeyOpen" => Ok(Keyboard::KeyOpen), + "KeyPaste" => Ok(Keyboard::KeyPaste), + "KeyFind" => Ok(Keyboard::KeyFind), + "KeyCut" => Ok(Keyboard::KeyCut), + "KeyHelp" => Ok(Keyboard::KeyHelp), + "KeyCalc" => Ok(Keyboard::KeyCalc), + "KeySleep" => Ok(Keyboard::KeySleep), + "KeyWww" => Ok(Keyboard::KeyWww), + "KeyBack" => Ok(Keyboard::KeyBack), + "KeyForward" => Ok(Keyboard::KeyForward), + "KeyEjectCD" => Ok(Keyboard::KeyEjectCD), + "KeyNextSong" => Ok(Keyboard::KeyNextSong), + "KeyPlayPause" => Ok(Keyboard::KeyPlayPause), + "KeyPreviousSong" => Ok(Keyboard::KeyPreviousSong), + "KeyStopCD" => Ok(Keyboard::KeyStopCD), + "KeyRefresh" => Ok(Keyboard::KeyRefresh), + "KeyEdit" => Ok(Keyboard::KeyEdit), + "KeyScrollUp" => Ok(Keyboard::KeyScrollUp), + "KeyScrollDown" => Ok(Keyboard::KeyScrollDown), + "KeyKpLeftParen" => Ok(Keyboard::KeyKpLeftParen), + "KeyKpRightParen" => Ok(Keyboard::KeyKpRightParen), + "KeyF13" => Ok(Keyboard::KeyF13), + "KeyF14" => Ok(Keyboard::KeyF14), + "KeyF15" => Ok(Keyboard::KeyF15), + "KeyF16" => Ok(Keyboard::KeyF16), + "KeyF17" => Ok(Keyboard::KeyF17), + "KeyF18" => Ok(Keyboard::KeyF18), + "KeyF19" => Ok(Keyboard::KeyF19), + "KeyF20" => Ok(Keyboard::KeyF20), + "KeyF21" => Ok(Keyboard::KeyF21), + "KeyF22" => Ok(Keyboard::KeyF22), + "KeyF23" => Ok(Keyboard::KeyF23), + "KeyF24" => Ok(Keyboard::KeyF24), + _ => Err(()), + } + } +} diff --git a/src/input/composite_device/mod.rs b/src/input/composite_device/mod.rs index 8e40c792..cf9dd829 100644 --- a/src/input/composite_device/mod.rs +++ b/src/input/composite_device/mod.rs @@ -1,23 +1,23 @@ -use std::{collections::HashMap, error::Error}; +use std::{collections::HashMap, error::Error, str::FromStr}; use tokio::{ sync::{broadcast, mpsc}, task::JoinSet, }; -use zbus::{fdo, Connection, SignalContext}; +use zbus::{fdo, Connection}; use zbus_macros::dbus_interface; use crate::{ - config::CompositeDeviceConfig, + config::{CapabilityMap, CapabilityMapping, CompositeDeviceConfig}, input::{event::native::NativeEvent, source}, udev::{hide_device, unhide_device}, }; use super::{ capability, - event::Event, + event::{native::InputValue, Event}, source::SourceDevice, - target::{TargetCommand, TargetDeviceType}, + target::TargetCommand, }; const BUFFER_SIZE: usize = 2048; @@ -166,6 +166,18 @@ impl Handle { pub struct CompositeDevice { /// Connection to DBus conn: Connection, + /// Configuration for the CompositeDevice + config: CompositeDeviceConfig, + /// Capability mapping for the CompositeDevice + capability_map: Option, + /// List of input capabilities that can be translated by the capability map + translatable_capabilities: Vec, + /// List of currently "pressed" actions used to translate multiple input + /// sequences into a single input event. + translatable_active_inputs: Vec, + /// Keep track of translated events we've emitted so we can send + /// release events + emitted_mappings: HashMap, /// The DBus path this [CompositeDevice] is listening on dbus_path: Option, /// Mode defining how inputs should be routed @@ -191,7 +203,12 @@ pub struct CompositeDevice { } impl CompositeDevice { - pub fn new(conn: Connection, config: CompositeDeviceConfig) -> Result> { + pub fn new( + conn: Connection, + config: CompositeDeviceConfig, + capability_map: Option, + ) -> Result> { + log::info!("Creating CompositeDevice with config: {}", config.name); let (tx, rx) = broadcast::channel(BUFFER_SIZE); let mut source_devices: Vec = Vec::new(); let mut source_device_paths: Vec = Vec::new(); @@ -248,6 +265,11 @@ impl CompositeDevice { Ok(Self { conn, + config, + capability_map, + translatable_capabilities: Vec::new(), + translatable_active_inputs: Vec::new(), + emitted_mappings: HashMap::new(), dbus_path: None, intercept_mode: InterceptMode::None, tx, @@ -272,6 +294,7 @@ impl CompositeDevice { log::error!("Failed to setup DBus interface for device: {:?}", e); } }); + log::info!("Started listening on {}", self.dbus_path.as_ref().unwrap()); Ok(()) } @@ -283,6 +306,11 @@ impl CompositeDevice { ) -> Result<(), Box> { log::debug!("Starting composite device"); + // Load the capability map if one was defined + if self.capability_map.is_some() { + self.load_capability_map()?; + } + // Start all source devices let mut tasks = self.run_source_devices().await?; @@ -467,7 +495,7 @@ impl CompositeDevice { /// Process a single event from a source device. Events are piped through /// a translation layer, then dispatched to the appropriate target device(s) async fn process_event(&mut self, raw_event: Event) -> Result<(), Box> { - //log::debug!("Received event: {:?}", raw_event); + log::trace!("Received event: {:?}", raw_event); // Convert the event into a NativeEvent let event: NativeEvent = match raw_event { @@ -476,9 +504,27 @@ impl CompositeDevice { Event::Native(event) => event, Event::DBus(_) => todo!(), }; + let cap = event.as_capability(); + log::trace!("Event capability: {:?}", cap); + + // Only send valid events to the target device(s) + if cap == capability::Capability::NotImplemented { + log::trace!("Refusing to send 'NotImplemented' event to target devices"); + return Ok(()); + } - // TODO: Check if the event needs to be translated based on the - // capability map. + // Check if the event needs to be translated based on the + // capability map. Translated events will be re-enqueued, so this will + // return early. + log::trace!( + "Translatable capabilities: {:?}", + self.translatable_capabilities + ); + if self.capability_map.is_some() && self.translatable_capabilities.contains(&cap) { + log::trace!("Capability mapping found for event"); + self.translate_capability(&event).await?; + return Ok(()); + } // TODO: Translate the event based on the device profile. @@ -524,9 +570,259 @@ impl CompositeDevice { Ok(()) } + /// Loads the input capabilities to translate from the capability map + fn load_capability_map(&mut self) -> Result<(), Box> { + let Some(map) = self.capability_map.as_ref() else { + return Err("Cannot translate device capabilities without capability map!".into()); + }; + + // Loop over each mapping and try to match source events + for mapping in map.mapping.iter() { + for source_event in mapping.source_events.iter() { + if let Some(keyboard) = source_event.keyboard.as_ref() { + let key = capability::Keyboard::from_str(keyboard.as_str()); + if key.is_err() { + return Err( + format!("Invalid or unimplemented capability: {keyboard}").into() + ); + } + let key = key.unwrap(); + let cap = capability::Capability::Keyboard(key); + self.translatable_capabilities.push(cap) + } + if let Some(gamepad) = source_event.gamepad.as_ref() { + unimplemented!(); + } + if let Some(mouse) = source_event.mouse.as_ref() { + unimplemented!(); + } + } + } + + Ok(()) + } + /// Sets the intercept mode to the given value fn set_intercept_mode(&mut self, mode: InterceptMode) { log::debug!("Setting intercept mode to: {:?}", mode); self.intercept_mode = mode; } + + /// Translates the given event into a different event based on the given + /// [CapabilityMap]. + async fn translate_capability(&mut self, event: &NativeEvent) -> Result<(), Box> { + // Get the capability map to translate input events + let Some(map) = self.capability_map.as_ref() else { + return Err("Cannot translate device capability without capability map!".into()); + }; + + // Add or remove the event from translatable_active_inputs. + let event_capability = event.as_capability(); + let capability_idx = self + .translatable_active_inputs + .iter() + .position(|c| c == &event_capability); + if event.pressed() { + if capability_idx.is_none() { + log::trace!("Adding capability to active inputs: {:?}", event_capability); + self.translatable_active_inputs.push(event_capability); + log::trace!( + "Active translatable inputs: {:?}", + self.translatable_active_inputs + ); + } else { + return Ok(()); + } + } else if capability_idx.is_some() { + log::trace!( + "Removing capability from active inputs: {:?}", + event_capability + ); + let idx = capability_idx.unwrap(); + self.translatable_active_inputs.remove(idx); + log::trace!( + "Active translatable inputs: {:?}", + self.translatable_active_inputs + ); + } else { + return Ok(()); + } + + // Keep a list of events to emit + let mut emit_queue = Vec::new(); + + // Loop over each mapping and try to match source events + for mapping in map.mapping.iter() { + // If the event was not pressed and it exists in the emitted_mappings array, + // then we need to check to see if ALL of its events no longer exist in + // translatable_active_inputs. + if !event.pressed() && self.emitted_mappings.contains_key(&mapping.name) { + let mut has_keys_pressed = false; + + // Loop through each source capability in the mapping + for source_event in mapping.source_events.iter() { + if let Some(keyboard) = source_event.keyboard.as_ref() { + let key = capability::Keyboard::from_str(keyboard.as_str()); + if key.is_err() { + log::error!( + "Invalid or unimplemented capability: {}", + keyboard.as_str() + ); + continue; + } + let key = key.unwrap(); + let cap = capability::Capability::Keyboard(key); + if self.translatable_active_inputs.contains(&cap) { + has_keys_pressed = true; + break; + } + } + if let Some(gamepad) = source_event.gamepad.as_ref() { + unimplemented!(); + } + if let Some(mouse) = source_event.mouse.as_ref() { + unimplemented!(); + } + } + + // If no more inputs are being pressed, send a release event. + if !has_keys_pressed { + if let Some(keyboard) = &mapping.target_event.keyboard { + let key = capability::Keyboard::from_str(keyboard.as_str()); + if key.is_err() { + log::error!( + "Invalid or unimplemented capability: {}", + keyboard.as_str() + ); + continue; + } + let key = key.unwrap(); + let cap = capability::Capability::Keyboard(key); + let event = NativeEvent::new(cap, InputValue::Bool(false)); + log::trace!("Adding event to emit queue: {:?}", event); + emit_queue.push(event); + self.emitted_mappings.remove(&mapping.name); + } + if let Some(gamepad) = &mapping.target_event.gamepad { + if let Some(button) = gamepad.button.as_ref() { + let btn = capability::GamepadButton::from_str(button.as_str()); + if btn.is_err() { + log::error!( + "Invalid or unimplemented capability: {}", + button.as_str() + ); + continue; + } + let btn = btn.unwrap(); + let cap = + capability::Capability::Gamepad(capability::Gamepad::Button(btn)); + let event = NativeEvent::new(cap, InputValue::Bool(false)); + log::trace!("Adding event to emit queue: {:?}", event); + emit_queue.push(event); + self.emitted_mappings.remove(&mapping.name); + } + } + if let Some(mouse) = &mapping.target_event.mouse { + unimplemented!(); + } + } + } + + // If the event is pressed, check for any matches to send a 'press' event + if event.pressed() { + let mut is_missing_keys = false; + for source_event in mapping.source_events.iter() { + if let Some(keyboard) = source_event.keyboard.as_ref() { + let key = capability::Keyboard::from_str(keyboard.as_str()); + if key.is_err() { + log::error!( + "Invalid or unimplemented capability: {}", + keyboard.as_str() + ); + continue; + } + let key = key.unwrap(); + let cap = capability::Capability::Keyboard(key); + if !self.translatable_active_inputs.contains(&cap) { + is_missing_keys = true; + break; + } + } + if let Some(gamepad) = source_event.gamepad.as_ref() { + if let Some(button) = gamepad.button.as_ref() { + let btn = capability::GamepadButton::from_str(button.as_str()); + if btn.is_err() { + log::error!( + "Invalid or unimplemented capability: {}", + button.as_str() + ); + continue; + } + let btn = btn.unwrap(); + let cap = + capability::Capability::Gamepad(capability::Gamepad::Button(btn)); + if !self.translatable_active_inputs.contains(&cap) { + is_missing_keys = true; + break; + } + } + } + if let Some(mouse) = source_event.mouse.as_ref() { + unimplemented!(); + } + } + + if !is_missing_keys { + if let Some(keyboard) = &mapping.target_event.keyboard { + let key = capability::Keyboard::from_str(keyboard.as_str()); + if key.is_err() { + log::error!( + "Invalid or unimplemented capability: {}", + keyboard.as_str() + ); + continue; + } + let key = key.unwrap(); + let cap = capability::Capability::Keyboard(key); + let event = NativeEvent::new(cap, InputValue::Bool(true)); + log::trace!("Adding event to emit queue: {:?}", event); + emit_queue.push(event); + self.emitted_mappings + .insert(mapping.name.clone(), mapping.clone()); + } + if let Some(gamepad) = &mapping.target_event.gamepad { + if let Some(button) = gamepad.button.as_ref() { + let btn = capability::GamepadButton::from_str(button.as_str()); + if btn.is_err() { + log::error!( + "Invalid or unimplemented capability: {}", + button.as_str() + ); + continue; + } + let btn = btn.unwrap(); + let cap = + capability::Capability::Gamepad(capability::Gamepad::Button(btn)); + let event = NativeEvent::new(cap, InputValue::Bool(true)); + log::trace!("Adding event to emit queue: {:?}", event); + emit_queue.push(event); + self.emitted_mappings + .insert(mapping.name.clone(), mapping.clone()); + } + } + if let Some(mouse) = &mapping.target_event.mouse { + unimplemented!(); + } + } + } + } + + // Emit the translated events + for event in emit_queue { + log::trace!("Emitting event: {:?}", event); + self.tx.send(Command::ProcessEvent(Event::Native(event)))?; + } + + Ok(()) + } } diff --git a/src/input/event/dbus.rs b/src/input/event/dbus.rs index 6dfe14f6..7caff4f2 100644 --- a/src/input/event/dbus.rs +++ b/src/input/event/dbus.rs @@ -112,12 +112,16 @@ fn actions_from_capability(capability: Capability) -> Vec { GamepadButton::Start => vec![Action::Option], GamepadButton::Select => vec![Action::Select], GamepadButton::Guide => vec![Action::Guide], - GamepadButton::Base => vec![Action::Quick], + GamepadButton::QuickAccess => vec![Action::Quick], + GamepadButton::QuickAccess2 => vec![Action::None], + GamepadButton::Keyboard => vec![Action::None], + GamepadButton::Screenshot => vec![Action::None], GamepadButton::DPadUp => vec![Action::Up], GamepadButton::DPadDown => vec![Action::Down], GamepadButton::DPadLeft => vec![Action::Left], GamepadButton::DPadRight => vec![Action::Right], GamepadButton::LeftBumper => vec![Action::L1], + GamepadButton::LeftTop => vec![Action::None], GamepadButton::LeftTrigger => vec![Action::L2], GamepadButton::LeftPaddle1 => vec![Action::None], GamepadButton::LeftPaddle2 => vec![Action::None], @@ -126,6 +130,7 @@ fn actions_from_capability(capability: Capability) -> Vec { GamepadButton::LeftTouchpadTouch => vec![Action::None], GamepadButton::LeftTouchpadPress => vec![Action::None], GamepadButton::RightBumper => vec![Action::R1], + GamepadButton::RightTop => vec![Action::None], GamepadButton::RightTrigger => vec![Action::R2], GamepadButton::RightPaddle1 => vec![Action::None], GamepadButton::RightPaddle2 => vec![Action::None], diff --git a/src/input/event/evdev.rs b/src/input/event/evdev.rs index 4c452dfa..b7da0ec7 100644 --- a/src/input/event/evdev.rs +++ b/src/input/event/evdev.rs @@ -125,6 +125,7 @@ impl EvdevEvent { match event_type { EventType::SYNCHRONIZATION => Capability::Sync, EventType::KEY => match KeyCode::new(code) { + // Gamepad Buttons KeyCode::BTN_SOUTH => Capability::Gamepad(Gamepad::Button(GamepadButton::South)), KeyCode::BTN_NORTH => Capability::Gamepad(Gamepad::Button(GamepadButton::North)), KeyCode::BTN_WEST => Capability::Gamepad(Gamepad::Button(GamepadButton::West)), @@ -140,6 +141,250 @@ impl EvdevEvent { KeyCode::BTN_THUMBR => { Capability::Gamepad(Gamepad::Button(GamepadButton::RightStick)) } + KeyCode::KEY_ESC => Capability::Keyboard(Keyboard::KeyEsc), + KeyCode::KEY_1 => Capability::Keyboard(Keyboard::Key1), + KeyCode::KEY_2 => Capability::Keyboard(Keyboard::Key2), + KeyCode::KEY_3 => Capability::Keyboard(Keyboard::Key3), + KeyCode::KEY_4 => Capability::Keyboard(Keyboard::Key4), + KeyCode::KEY_5 => Capability::Keyboard(Keyboard::Key5), + KeyCode::KEY_6 => Capability::Keyboard(Keyboard::Key6), + KeyCode::KEY_7 => Capability::Keyboard(Keyboard::Key7), + KeyCode::KEY_8 => Capability::Keyboard(Keyboard::Key8), + KeyCode::KEY_9 => Capability::Keyboard(Keyboard::Key9), + KeyCode::KEY_0 => Capability::Keyboard(Keyboard::Key0), + KeyCode::KEY_MINUS => Capability::Keyboard(Keyboard::KeyMinus), + KeyCode::KEY_EQUAL => Capability::Keyboard(Keyboard::KeyEqual), + KeyCode::KEY_BACKSPACE => Capability::Keyboard(Keyboard::KeyBackspace), + KeyCode::KEY_TAB => Capability::Keyboard(Keyboard::KeyTab), + KeyCode::KEY_Q => Capability::Keyboard(Keyboard::KeyQ), + KeyCode::KEY_W => Capability::Keyboard(Keyboard::KeyW), + KeyCode::KEY_E => Capability::Keyboard(Keyboard::KeyE), + KeyCode::KEY_R => Capability::Keyboard(Keyboard::KeyR), + KeyCode::KEY_T => Capability::Keyboard(Keyboard::KeyT), + KeyCode::KEY_Y => Capability::Keyboard(Keyboard::KeyY), + KeyCode::KEY_U => Capability::Keyboard(Keyboard::KeyU), + KeyCode::KEY_I => Capability::Keyboard(Keyboard::KeyI), + KeyCode::KEY_O => Capability::Keyboard(Keyboard::KeyO), + KeyCode::KEY_P => Capability::Keyboard(Keyboard::KeyP), + KeyCode::KEY_LEFTBRACE => Capability::Keyboard(Keyboard::KeyLeftBrace), + KeyCode::KEY_RIGHTBRACE => Capability::Keyboard(Keyboard::KeyRightBrace), + KeyCode::KEY_ENTER => Capability::Keyboard(Keyboard::KeyEnter), + KeyCode::KEY_LEFTCTRL => Capability::Keyboard(Keyboard::KeyLeftCtrl), + KeyCode::KEY_A => Capability::Keyboard(Keyboard::KeyA), + KeyCode::KEY_S => Capability::Keyboard(Keyboard::KeyS), + KeyCode::KEY_D => Capability::Keyboard(Keyboard::KeyD), + KeyCode::KEY_F => Capability::Keyboard(Keyboard::KeyF), + KeyCode::KEY_G => Capability::Keyboard(Keyboard::KeyG), + KeyCode::KEY_H => Capability::Keyboard(Keyboard::KeyH), + KeyCode::KEY_J => Capability::Keyboard(Keyboard::KeyJ), + KeyCode::KEY_K => Capability::Keyboard(Keyboard::KeyK), + KeyCode::KEY_L => Capability::Keyboard(Keyboard::KeyL), + KeyCode::KEY_SEMICOLON => Capability::Keyboard(Keyboard::KeySemicolon), + KeyCode::KEY_APOSTROPHE => Capability::Keyboard(Keyboard::KeyApostrophe), + KeyCode::KEY_GRAVE => Capability::Keyboard(Keyboard::KeyGrave), + KeyCode::KEY_LEFTSHIFT => Capability::Keyboard(Keyboard::KeyLeftShift), + KeyCode::KEY_BACKSLASH => Capability::Keyboard(Keyboard::KeyBackslash), + KeyCode::KEY_Z => Capability::Keyboard(Keyboard::KeyZ), + KeyCode::KEY_X => Capability::Keyboard(Keyboard::KeyX), + KeyCode::KEY_C => Capability::Keyboard(Keyboard::KeyC), + KeyCode::KEY_V => Capability::Keyboard(Keyboard::KeyV), + KeyCode::KEY_B => Capability::Keyboard(Keyboard::KeyB), + KeyCode::KEY_N => Capability::Keyboard(Keyboard::KeyN), + KeyCode::KEY_M => Capability::Keyboard(Keyboard::KeyM), + KeyCode::KEY_COMMA => Capability::Keyboard(Keyboard::KeyComma), + KeyCode::KEY_DOT => Capability::Keyboard(Keyboard::KeyDot), + KeyCode::KEY_SLASH => Capability::Keyboard(Keyboard::KeySlash), + KeyCode::KEY_RIGHTSHIFT => Capability::Keyboard(Keyboard::KeyRightShift), + KeyCode::KEY_KPASTERISK => Capability::Keyboard(Keyboard::KeyKpAsterisk), + KeyCode::KEY_LEFTALT => Capability::Keyboard(Keyboard::KeyLeftAlt), + KeyCode::KEY_SPACE => Capability::Keyboard(Keyboard::KeySpace), + KeyCode::KEY_CAPSLOCK => Capability::Keyboard(Keyboard::KeyCapslock), + KeyCode::KEY_F1 => Capability::Keyboard(Keyboard::KeyF1), + KeyCode::KEY_F2 => Capability::Keyboard(Keyboard::KeyF2), + KeyCode::KEY_F3 => Capability::Keyboard(Keyboard::KeyF3), + KeyCode::KEY_F4 => Capability::Keyboard(Keyboard::KeyF4), + KeyCode::KEY_F5 => Capability::Keyboard(Keyboard::KeyF5), + KeyCode::KEY_F6 => Capability::Keyboard(Keyboard::KeyF6), + KeyCode::KEY_F7 => Capability::Keyboard(Keyboard::KeyF7), + KeyCode::KEY_F8 => Capability::Keyboard(Keyboard::KeyF8), + KeyCode::KEY_F9 => Capability::Keyboard(Keyboard::KeyF9), + KeyCode::KEY_F10 => Capability::Keyboard(Keyboard::KeyF10), + KeyCode::KEY_NUMLOCK => Capability::Keyboard(Keyboard::KeyNumlock), + KeyCode::KEY_SCROLLLOCK => Capability::Keyboard(Keyboard::KeyScrollLock), + KeyCode::KEY_KP7 => Capability::Keyboard(Keyboard::KeyKp7), + KeyCode::KEY_KP8 => Capability::Keyboard(Keyboard::KeyKp8), + KeyCode::KEY_KP9 => Capability::Keyboard(Keyboard::KeyKp9), + KeyCode::KEY_KPMINUS => Capability::Keyboard(Keyboard::KeyKpMinus), + KeyCode::KEY_KP4 => Capability::Keyboard(Keyboard::KeyKp4), + KeyCode::KEY_KP5 => Capability::Keyboard(Keyboard::KeyKp5), + KeyCode::KEY_KP6 => Capability::Keyboard(Keyboard::KeyKp6), + KeyCode::KEY_KPPLUS => Capability::Keyboard(Keyboard::KeyKpPlus), + KeyCode::KEY_KP1 => Capability::Keyboard(Keyboard::KeyKp1), + KeyCode::KEY_KP2 => Capability::Keyboard(Keyboard::KeyKp2), + KeyCode::KEY_KP3 => Capability::Keyboard(Keyboard::KeyKp3), + KeyCode::KEY_KP0 => Capability::Keyboard(Keyboard::KeyKp0), + KeyCode::KEY_KPDOT => Capability::Keyboard(Keyboard::KeyKpDot), + KeyCode::KEY_ZENKAKUHANKAKU => Capability::Keyboard(Keyboard::KeyZenkakuhankaku), + KeyCode::KEY_102ND => Capability::Keyboard(Keyboard::Key102nd), + KeyCode::KEY_F11 => Capability::Keyboard(Keyboard::KeyF11), + KeyCode::KEY_F12 => Capability::Keyboard(Keyboard::KeyF12), + KeyCode::KEY_RO => Capability::Keyboard(Keyboard::KeyRo), + KeyCode::KEY_KATAKANA => Capability::Keyboard(Keyboard::KeyKatakana), + KeyCode::KEY_HIRAGANA => Capability::Keyboard(Keyboard::KeyHiragana), + KeyCode::KEY_HENKAN => Capability::Keyboard(Keyboard::KeyHenkan), + KeyCode::KEY_KATAKANAHIRAGANA => { + Capability::Keyboard(Keyboard::KeyKatakanaHiragana) + } + KeyCode::KEY_MUHENKAN => Capability::Keyboard(Keyboard::KeyMuhenkan), + KeyCode::KEY_KPJPCOMMA => Capability::Keyboard(Keyboard::KeyKpJpComma), + KeyCode::KEY_KPENTER => Capability::Keyboard(Keyboard::KeyKpEnter), + KeyCode::KEY_RIGHTCTRL => Capability::Keyboard(Keyboard::KeyRightCtrl), + KeyCode::KEY_KPSLASH => Capability::Keyboard(Keyboard::KeyKpSlash), + KeyCode::KEY_SYSRQ => Capability::Keyboard(Keyboard::KeySysrq), + KeyCode::KEY_RIGHTALT => Capability::Keyboard(Keyboard::KeyRightAlt), + KeyCode::KEY_LINEFEED => Capability::NotImplemented, + KeyCode::KEY_HOME => Capability::Keyboard(Keyboard::KeyHome), + KeyCode::KEY_UP => Capability::Keyboard(Keyboard::KeyUp), + KeyCode::KEY_PAGEUP => Capability::Keyboard(Keyboard::KeyPageUp), + KeyCode::KEY_LEFT => Capability::Keyboard(Keyboard::KeyLeft), + KeyCode::KEY_RIGHT => Capability::Keyboard(Keyboard::KeyRight), + KeyCode::KEY_END => Capability::Keyboard(Keyboard::KeyEnd), + KeyCode::KEY_DOWN => Capability::Keyboard(Keyboard::KeyDown), + KeyCode::KEY_PAGEDOWN => Capability::Keyboard(Keyboard::KeyPageDown), + KeyCode::KEY_INSERT => Capability::Keyboard(Keyboard::KeyInsert), + KeyCode::KEY_DELETE => Capability::Keyboard(Keyboard::KeyDelete), + KeyCode::KEY_MACRO => Capability::NotImplemented, + KeyCode::KEY_MUTE => Capability::Keyboard(Keyboard::KeyMute), + KeyCode::KEY_VOLUMEDOWN => Capability::Keyboard(Keyboard::KeyVolumeDown), + KeyCode::KEY_VOLUMEUP => Capability::Keyboard(Keyboard::KeyVolumeUp), + KeyCode::KEY_POWER => Capability::Keyboard(Keyboard::KeyPower), + KeyCode::KEY_KPEQUAL => Capability::Keyboard(Keyboard::KeyKpEqual), + KeyCode::KEY_KPPLUSMINUS => Capability::NotImplemented, + KeyCode::KEY_PAUSE => Capability::Keyboard(Keyboard::KeyPause), + KeyCode::KEY_SCALE => Capability::NotImplemented, + KeyCode::KEY_KPCOMMA => Capability::Keyboard(Keyboard::KeyKpComma), + KeyCode::KEY_HANGEUL => Capability::NotImplemented, + KeyCode::KEY_HANJA => Capability::Keyboard(Keyboard::KeyHanja), + KeyCode::KEY_YEN => Capability::Keyboard(Keyboard::KeyYen), + KeyCode::KEY_LEFTMETA => Capability::Keyboard(Keyboard::KeyLeftMeta), + KeyCode::KEY_RIGHTMETA => Capability::Keyboard(Keyboard::KeyRightMeta), + KeyCode::KEY_COMPOSE => Capability::Keyboard(Keyboard::KeyCompose), + KeyCode::KEY_STOP => Capability::Keyboard(Keyboard::KeyStop), + KeyCode::KEY_AGAIN => Capability::Keyboard(Keyboard::KeyAgain), + KeyCode::KEY_PROPS => Capability::Keyboard(Keyboard::KeyProps), + KeyCode::KEY_UNDO => Capability::Keyboard(Keyboard::KeyUndo), + KeyCode::KEY_FRONT => Capability::Keyboard(Keyboard::KeyFront), + KeyCode::KEY_COPY => Capability::Keyboard(Keyboard::KeyCopy), + KeyCode::KEY_OPEN => Capability::Keyboard(Keyboard::KeyOpen), + KeyCode::KEY_PASTE => Capability::Keyboard(Keyboard::KeyPaste), + KeyCode::KEY_FIND => Capability::Keyboard(Keyboard::KeyFind), + KeyCode::KEY_CUT => Capability::Keyboard(Keyboard::KeyCut), + KeyCode::KEY_HELP => Capability::Keyboard(Keyboard::KeyHelp), + KeyCode::KEY_MENU => Capability::NotImplemented, + KeyCode::KEY_CALC => Capability::Keyboard(Keyboard::KeyCalc), + KeyCode::KEY_SETUP => Capability::NotImplemented, + KeyCode::KEY_SLEEP => Capability::Keyboard(Keyboard::KeySleep), + KeyCode::KEY_WAKEUP => Capability::NotImplemented, + KeyCode::KEY_FILE => Capability::NotImplemented, + KeyCode::KEY_SENDFILE => Capability::NotImplemented, + KeyCode::KEY_DELETEFILE => Capability::NotImplemented, + KeyCode::KEY_XFER => Capability::NotImplemented, + KeyCode::KEY_PROG1 => Capability::NotImplemented, + KeyCode::KEY_PROG2 => Capability::NotImplemented, + KeyCode::KEY_WWW => Capability::Keyboard(Keyboard::KeyWww), + KeyCode::KEY_MSDOS => Capability::NotImplemented, + KeyCode::KEY_COFFEE => Capability::NotImplemented, + KeyCode::KEY_ROTATE_DISPLAY => Capability::NotImplemented, + KeyCode::KEY_CYCLEWINDOWS => Capability::NotImplemented, + KeyCode::KEY_MAIL => Capability::NotImplemented, + KeyCode::KEY_BOOKMARKS => Capability::NotImplemented, + KeyCode::KEY_COMPUTER => Capability::NotImplemented, + KeyCode::KEY_BACK => Capability::Keyboard(Keyboard::KeyBack), + KeyCode::KEY_FORWARD => Capability::Keyboard(Keyboard::KeyForward), + KeyCode::KEY_CLOSECD => Capability::NotImplemented, + KeyCode::KEY_EJECTCD => Capability::Keyboard(Keyboard::KeyEjectCD), + KeyCode::KEY_EJECTCLOSECD => Capability::NotImplemented, + KeyCode::KEY_NEXTSONG => Capability::Keyboard(Keyboard::KeyNextSong), + KeyCode::KEY_PLAYPAUSE => Capability::Keyboard(Keyboard::KeyPlayPause), + KeyCode::KEY_PREVIOUSSONG => Capability::Keyboard(Keyboard::KeyPreviousSong), + KeyCode::KEY_STOPCD => Capability::Keyboard(Keyboard::KeyStopCD), + KeyCode::KEY_RECORD => Capability::NotImplemented, + KeyCode::KEY_REWIND => Capability::NotImplemented, + KeyCode::KEY_PHONE => Capability::NotImplemented, + KeyCode::KEY_ISO => Capability::NotImplemented, + KeyCode::KEY_CONFIG => Capability::NotImplemented, + KeyCode::KEY_HOMEPAGE => Capability::NotImplemented, + KeyCode::KEY_REFRESH => Capability::Keyboard(Keyboard::KeyRefresh), + KeyCode::KEY_EXIT => Capability::NotImplemented, + KeyCode::KEY_MOVE => Capability::NotImplemented, + KeyCode::KEY_EDIT => Capability::Keyboard(Keyboard::KeyEdit), + KeyCode::KEY_SCROLLUP => Capability::Keyboard(Keyboard::KeyScrollUp), + KeyCode::KEY_SCROLLDOWN => Capability::Keyboard(Keyboard::KeyScrollDown), + KeyCode::KEY_KPLEFTPAREN => Capability::Keyboard(Keyboard::KeyKpLeftParen), + KeyCode::KEY_KPRIGHTPAREN => Capability::Keyboard(Keyboard::KeyKpRightParen), + KeyCode::KEY_NEW => Capability::NotImplemented, + KeyCode::KEY_REDO => Capability::NotImplemented, + KeyCode::KEY_F13 => Capability::Keyboard(Keyboard::KeyF13), + KeyCode::KEY_F14 => Capability::Keyboard(Keyboard::KeyF14), + KeyCode::KEY_F15 => Capability::Keyboard(Keyboard::KeyF15), + KeyCode::KEY_F16 => Capability::Keyboard(Keyboard::KeyF16), + KeyCode::KEY_F17 => Capability::Keyboard(Keyboard::KeyF17), + KeyCode::KEY_F18 => Capability::Keyboard(Keyboard::KeyF18), + KeyCode::KEY_F19 => Capability::Keyboard(Keyboard::KeyF19), + KeyCode::KEY_F20 => Capability::Keyboard(Keyboard::KeyF20), + KeyCode::KEY_F21 => Capability::Keyboard(Keyboard::KeyF21), + KeyCode::KEY_F22 => Capability::Keyboard(Keyboard::KeyF22), + KeyCode::KEY_F23 => Capability::Keyboard(Keyboard::KeyF23), + KeyCode::KEY_F24 => Capability::Keyboard(Keyboard::KeyF24), + KeyCode::KEY_PLAYCD => Capability::NotImplemented, + KeyCode::KEY_PAUSECD => Capability::NotImplemented, + KeyCode::KEY_PROG3 => Capability::NotImplemented, + KeyCode::KEY_PROG4 => Capability::NotImplemented, + KeyCode::KEY_DASHBOARD => Capability::NotImplemented, + KeyCode::KEY_SUSPEND => Capability::NotImplemented, + KeyCode::KEY_CLOSE => Capability::NotImplemented, + KeyCode::KEY_PLAY => Capability::NotImplemented, + KeyCode::KEY_FASTFORWARD => Capability::NotImplemented, + KeyCode::KEY_BASSBOOST => Capability::NotImplemented, + KeyCode::KEY_PRINT => Capability::NotImplemented, + KeyCode::KEY_HP => Capability::NotImplemented, + KeyCode::KEY_CAMERA => Capability::NotImplemented, + KeyCode::KEY_SOUND => Capability::NotImplemented, + KeyCode::KEY_QUESTION => Capability::NotImplemented, + KeyCode::KEY_EMAIL => Capability::NotImplemented, + KeyCode::KEY_CHAT => Capability::NotImplemented, + KeyCode::KEY_SEARCH => Capability::NotImplemented, + KeyCode::KEY_CONNECT => Capability::NotImplemented, + KeyCode::KEY_FINANCE => Capability::NotImplemented, + KeyCode::KEY_SPORT => Capability::NotImplemented, + KeyCode::KEY_SHOP => Capability::NotImplemented, + KeyCode::KEY_ALTERASE => Capability::NotImplemented, + KeyCode::KEY_CANCEL => Capability::NotImplemented, + KeyCode::KEY_BRIGHTNESSDOWN => Capability::NotImplemented, + KeyCode::KEY_BRIGHTNESSUP => Capability::NotImplemented, + KeyCode::KEY_MEDIA => Capability::NotImplemented, + KeyCode::KEY_SWITCHVIDEOMODE => Capability::NotImplemented, + KeyCode::KEY_KBDILLUMTOGGLE => Capability::NotImplemented, + KeyCode::KEY_KBDILLUMDOWN => Capability::NotImplemented, + KeyCode::KEY_KBDILLUMUP => Capability::NotImplemented, + KeyCode::KEY_SEND => Capability::NotImplemented, + KeyCode::KEY_REPLY => Capability::NotImplemented, + KeyCode::KEY_FORWARDMAIL => Capability::NotImplemented, + KeyCode::KEY_SAVE => Capability::NotImplemented, + KeyCode::KEY_DOCUMENTS => Capability::NotImplemented, + KeyCode::KEY_BATTERY => Capability::NotImplemented, + KeyCode::KEY_BLUETOOTH => Capability::NotImplemented, + KeyCode::KEY_WLAN => Capability::NotImplemented, + KeyCode::KEY_UWB => Capability::NotImplemented, + KeyCode::KEY_UNKNOWN => Capability::NotImplemented, + KeyCode::KEY_VIDEO_NEXT => Capability::NotImplemented, + KeyCode::KEY_VIDEO_PREV => Capability::NotImplemented, + KeyCode::KEY_BRIGHTNESS_CYCLE => Capability::NotImplemented, + KeyCode::KEY_BRIGHTNESS_AUTO => Capability::NotImplemented, + KeyCode::KEY_DISPLAY_OFF => Capability::NotImplemented, + KeyCode::KEY_WWAN => Capability::NotImplemented, + KeyCode::KEY_RFKILL => Capability::NotImplemented, + KeyCode::KEY_MICMUTE => Capability::NotImplemented, _ => Capability::NotImplemented, }, EventType::ABSOLUTE => match AbsoluteAxisCode(code) { @@ -314,10 +559,15 @@ fn event_codes_from_capability(capability: Capability) -> Vec { GamepadButton::West => vec![KeyCode::BTN_WEST.0], GamepadButton::LeftBumper => vec![KeyCode::BTN_TL.0], GamepadButton::RightBumper => vec![KeyCode::BTN_TR.0], + GamepadButton::LeftTop => vec![], + GamepadButton::RightTop => vec![], GamepadButton::Start => vec![KeyCode::BTN_START.0], GamepadButton::Select => vec![KeyCode::BTN_SELECT.0], GamepadButton::Guide => vec![KeyCode::BTN_MODE.0], - GamepadButton::Base => vec![KeyCode::BTN_BASE.0], + GamepadButton::QuickAccess => vec![], + GamepadButton::QuickAccess2 => vec![], + GamepadButton::Keyboard => vec![], + GamepadButton::Screenshot => vec![], GamepadButton::LeftStick => vec![KeyCode::BTN_THUMBL.0], GamepadButton::RightStick => vec![KeyCode::BTN_THUMBR.0], GamepadButton::DPadUp => vec![AbsoluteAxisCode::ABS_HAT0Y.0], @@ -427,8 +677,8 @@ fn event_codes_from_capability(capability: Capability) -> Vec { Keyboard::KeyComma => vec![KeyCode::KEY_COMMA.0], Keyboard::KeyDot => vec![KeyCode::KEY_DOT.0], Keyboard::KeySlash => vec![KeyCode::KEY_SLASH.0], - Keyboard::KeyRightshift => vec![KeyCode::KEY_RIGHTSHIFT.0], - Keyboard::KeyKpasterisk => vec![KeyCode::KEY_KPASTERISK.0], + Keyboard::KeyRightShift => vec![KeyCode::KEY_RIGHTSHIFT.0], + Keyboard::KeyKpAsterisk => vec![KeyCode::KEY_KPASTERISK.0], Keyboard::KeyLeftAlt => vec![KeyCode::KEY_LEFTALT.0], Keyboard::KeySpace => vec![KeyCode::KEY_SPACE.0], Keyboard::KeyCapslock => vec![KeyCode::KEY_CAPSLOCK.0], @@ -443,20 +693,20 @@ fn event_codes_from_capability(capability: Capability) -> Vec { Keyboard::KeyF9 => vec![KeyCode::KEY_F9.0], Keyboard::KeyF10 => vec![KeyCode::KEY_F10.0], Keyboard::KeyNumlock => vec![KeyCode::KEY_NUMLOCK.0], - Keyboard::KeyScrolllock => vec![KeyCode::KEY_SCROLLLOCK.0], + Keyboard::KeyScrollLock => vec![KeyCode::KEY_SCROLLLOCK.0], Keyboard::KeyKp7 => vec![KeyCode::KEY_KP7.0], Keyboard::KeyKp8 => vec![KeyCode::KEY_KP8.0], Keyboard::KeyKp9 => vec![KeyCode::KEY_KP9.0], - Keyboard::KeyKpminus => vec![KeyCode::KEY_KPMINUS.0], + Keyboard::KeyKpMinus => vec![KeyCode::KEY_KPMINUS.0], Keyboard::KeyKp4 => vec![KeyCode::KEY_KP4.0], Keyboard::KeyKp5 => vec![KeyCode::KEY_KP5.0], Keyboard::KeyKp6 => vec![KeyCode::KEY_KP6.0], - Keyboard::KeyKpplus => vec![KeyCode::KEY_KPPLUS.0], + Keyboard::KeyKpPlus => vec![KeyCode::KEY_KPPLUS.0], Keyboard::KeyKp1 => vec![KeyCode::KEY_KP1.0], Keyboard::KeyKp2 => vec![KeyCode::KEY_KP2.0], Keyboard::KeyKp3 => vec![KeyCode::KEY_KP3.0], Keyboard::KeyKp0 => vec![KeyCode::KEY_KP0.0], - Keyboard::KeyKpdot => vec![KeyCode::KEY_KPDOT.0], + Keyboard::KeyKpDot => vec![KeyCode::KEY_KPDOT.0], Keyboard::KeyZenkakuhankaku => vec![KeyCode::KEY_ZENKAKUHANKAKU.0], Keyboard::Key102nd => vec![KeyCode::KEY_102ND.0], Keyboard::KeyF11 => vec![KeyCode::KEY_F11.0], @@ -465,35 +715,35 @@ fn event_codes_from_capability(capability: Capability) -> Vec { Keyboard::KeyKatakana => vec![KeyCode::KEY_KATAKANA.0], Keyboard::KeyHiragana => vec![KeyCode::KEY_HIRAGANA.0], Keyboard::KeyHenkan => vec![KeyCode::KEY_HENKAN.0], - Keyboard::KeyKatakanahiragana => vec![KeyCode::KEY_KATAKANAHIRAGANA.0], + Keyboard::KeyKatakanaHiragana => vec![KeyCode::KEY_KATAKANAHIRAGANA.0], Keyboard::KeyMuhenkan => vec![KeyCode::KEY_MUHENKAN.0], - Keyboard::KeyKpjpcomma => vec![KeyCode::KEY_KPJPCOMMA.0], - Keyboard::KeyKpenter => vec![KeyCode::KEY_KPENTER.0], - Keyboard::KeyRightctrl => vec![KeyCode::KEY_RIGHTCTRL.0], - Keyboard::KeyKpslash => vec![KeyCode::KEY_KPSLASH.0], + Keyboard::KeyKpJpComma => vec![KeyCode::KEY_KPJPCOMMA.0], + Keyboard::KeyKpEnter => vec![KeyCode::KEY_KPENTER.0], + Keyboard::KeyRightCtrl => vec![KeyCode::KEY_RIGHTCTRL.0], + Keyboard::KeyKpSlash => vec![KeyCode::KEY_KPSLASH.0], Keyboard::KeySysrq => vec![KeyCode::KEY_SYSRQ.0], - Keyboard::KeyRightalt => vec![KeyCode::KEY_RIGHTALT.0], + Keyboard::KeyRightAlt => vec![KeyCode::KEY_RIGHTALT.0], Keyboard::KeyHome => vec![KeyCode::KEY_HOME.0], Keyboard::KeyUp => vec![KeyCode::KEY_UP.0], - Keyboard::KeyPageup => vec![KeyCode::KEY_PAGEUP.0], + Keyboard::KeyPageUp => vec![KeyCode::KEY_PAGEUP.0], Keyboard::KeyLeft => vec![KeyCode::KEY_LEFT.0], Keyboard::KeyRight => vec![KeyCode::KEY_RIGHT.0], Keyboard::KeyEnd => vec![KeyCode::KEY_END.0], Keyboard::KeyDown => vec![KeyCode::KEY_DOWN.0], - Keyboard::KeyPagedown => vec![KeyCode::KEY_PAGEDOWN.0], + Keyboard::KeyPageDown => vec![KeyCode::KEY_PAGEDOWN.0], Keyboard::KeyInsert => vec![KeyCode::KEY_INSERT.0], Keyboard::KeyDelete => vec![KeyCode::KEY_DELETE.0], Keyboard::KeyMute => vec![KeyCode::KEY_MUTE.0], Keyboard::KeyVolumeDown => vec![KeyCode::KEY_VOLUMEDOWN.0], Keyboard::KeyVolumeUp => vec![KeyCode::KEY_VOLUMEUP.0], Keyboard::KeyPower => vec![KeyCode::KEY_POWER.0], - Keyboard::KeyKpequal => vec![KeyCode::KEY_KPEQUAL.0], + Keyboard::KeyKpEqual => vec![KeyCode::KEY_KPEQUAL.0], Keyboard::KeyPause => vec![KeyCode::KEY_PAUSE.0], - Keyboard::KeyKpcomma => vec![KeyCode::KEY_KPCOMMA.0], + Keyboard::KeyKpComma => vec![KeyCode::KEY_KPCOMMA.0], Keyboard::KeyHanja => vec![KeyCode::KEY_HANJA.0], Keyboard::KeyYen => vec![KeyCode::KEY_YEN.0], - Keyboard::KeyLeftmeta => vec![KeyCode::KEY_LEFTMETA.0], - Keyboard::KeyRightmeta => vec![KeyCode::KEY_RIGHTMETA.0], + Keyboard::KeyLeftMeta => vec![KeyCode::KEY_LEFTMETA.0], + Keyboard::KeyRightMeta => vec![KeyCode::KEY_RIGHTMETA.0], Keyboard::KeyCompose => vec![KeyCode::KEY_COMPOSE.0], Keyboard::KeyStop => vec![KeyCode::KEY_STOP.0], Keyboard::KeyAgain => vec![KeyCode::KEY_AGAIN.0], @@ -511,17 +761,17 @@ fn event_codes_from_capability(capability: Capability) -> Vec { Keyboard::KeyWww => vec![KeyCode::KEY_WWW.0], Keyboard::KeyBack => vec![KeyCode::KEY_BACK.0], Keyboard::KeyForward => vec![KeyCode::KEY_FORWARD.0], - Keyboard::KeyEjectcd => vec![KeyCode::KEY_EJECTCD.0], - Keyboard::KeyNextsong => vec![KeyCode::KEY_NEXTSONG.0], - Keyboard::KeyPlaypause => vec![KeyCode::KEY_PLAYPAUSE.0], - Keyboard::KeyPrevioussong => vec![KeyCode::KEY_PREVIOUSSONG.0], - Keyboard::KeyStopcd => vec![KeyCode::KEY_STOPCD.0], + Keyboard::KeyEjectCD => vec![KeyCode::KEY_EJECTCD.0], + Keyboard::KeyNextSong => vec![KeyCode::KEY_NEXTSONG.0], + Keyboard::KeyPlayPause => vec![KeyCode::KEY_PLAYPAUSE.0], + Keyboard::KeyPreviousSong => vec![KeyCode::KEY_PREVIOUSSONG.0], + Keyboard::KeyStopCD => vec![KeyCode::KEY_STOPCD.0], Keyboard::KeyRefresh => vec![KeyCode::KEY_REFRESH.0], Keyboard::KeyEdit => vec![KeyCode::KEY_EDIT.0], Keyboard::KeyScrollUp => vec![KeyCode::KEY_SCROLLUP.0], Keyboard::KeyScrollDown => vec![KeyCode::KEY_SCROLLDOWN.0], - Keyboard::KeyKpleftparen => vec![KeyCode::KEY_KPLEFTPAREN.0], - Keyboard::KeyKprightparen => vec![KeyCode::KEY_KPRIGHTPAREN.0], + Keyboard::KeyKpLeftParen => vec![KeyCode::KEY_KPLEFTPAREN.0], + Keyboard::KeyKpRightParen => vec![KeyCode::KEY_KPRIGHTPAREN.0], Keyboard::KeyF13 => vec![KeyCode::KEY_F13.0], Keyboard::KeyF14 => vec![KeyCode::KEY_F14.0], Keyboard::KeyF15 => vec![KeyCode::KEY_F15.0], diff --git a/src/input/manager.rs b/src/input/manager.rs index f354e7fc..c0dda789 100644 --- a/src/input/manager.rs +++ b/src/input/manager.rs @@ -9,6 +9,8 @@ use zbus::zvariant::ObjectPath; use zbus::Connection; use zbus_macros::dbus_interface; +use crate::config::CapabilityMap; +use crate::config::CapabilityMapping; use crate::config::CompositeDeviceConfig; use crate::constants::BUS_PREFIX; use crate::constants::BUS_TARGETS_PREFIX; @@ -216,9 +218,18 @@ impl Manager { // TODO: Check to see if there's already a composite device running // but without all its source devices + // Lookup the capability map associated with this config if it exists + let capability_map = if let Some(map_id) = config.capability_map_id.clone() { + log::debug!("Found capability mapping in config: {}", map_id); + let capability_map = self.load_capability_mappings().await; + capability_map.get(&map_id).cloned() + } else { + None + }; + // Create a composite device to manage these devices log::info!("Found matching source devices: {:?}", config.name); - let device = CompositeDevice::new(self.dbus.clone(), config)?; + let device = CompositeDevice::new(self.dbus.clone(), config, capability_map)?; // Check to see if there's already a CompositeDevice for // these source devices. @@ -722,6 +733,58 @@ impl Manager { Ok(()) } + /// Loads all capability mappings in all default locations and returns a hashmap + /// of the CapabilityMap ID and the [CapabilityMap]. + pub async fn load_capability_mappings(&self) -> HashMap { + let mut mappings = HashMap::new(); + let paths = vec![ + "/usr/share/inputplumber/capability_maps", + "/etc/inputplumber/capability_maps.d", + "./rootfs/usr/share/inputplumber/capability_maps", + ]; + + // Look for capability mappings in all known locations + for path in paths { + let files = fs::read_dir(path); + if files.is_err() { + log::debug!("Failed to load directory {}: {}", path, files.unwrap_err()); + continue; + } + let files = files.unwrap(); + + // Look at each file in the directory and try to load them + for file in files { + if file.is_err() { + log::debug!("Failed read directory entry: {}", file.unwrap_err()); + continue; + } + let file = file.unwrap(); + let filename = file.file_name(); + let filename = filename.as_os_str().to_str().unwrap(); + + // Skip any non-yaml files + if !filename.ends_with(".yaml") { + continue; + } + + // Try to load the composite device profile + log::debug!("Found file: {}", file.path().display()); + let mapping = CapabilityMap::from_yaml_file(file.path().display().to_string()); + if mapping.is_err() { + log::debug!( + "Failed to parse capability mapping: {}", + mapping.unwrap_err() + ); + continue; + } + let map = mapping.unwrap(); + mappings.insert(map.id.clone(), map); + } + } + + mappings + } + /// Looks in all default locations for [CompositeDeviceConfig] definitions and /// load/parse them. Returns an array of these configs which can be used /// to automatically create a [CompositeDevice]. diff --git a/src/input/source/hidraw/steam_deck.rs b/src/input/source/hidraw/steam_deck.rs index 350c62bd..38a07da8 100644 --- a/src/input/source/hidraw/steam_deck.rs +++ b/src/input/source/hidraw/steam_deck.rs @@ -238,7 +238,7 @@ fn translate_event(event: steam_deck::event::Event) -> NativeEvent { InputValue::Bool(value.pressed), ), steam_deck::event::ButtonEvent::QuickAccess(value) => NativeEvent::new( - Capability::Gamepad(Gamepad::Button(GamepadButton::Base)), + Capability::Gamepad(Gamepad::Button(GamepadButton::QuickAccess)), InputValue::Bool(value.pressed), ), steam_deck::event::ButtonEvent::DPadDown(value) => NativeEvent::new( diff --git a/src/input/target/gamepad.rs b/src/input/target/gamepad.rs index c83da3b0..607095a9 100644 --- a/src/input/target/gamepad.rs +++ b/src/input/target/gamepad.rs @@ -111,7 +111,7 @@ impl GenericGamepad { while let Some(command) = self.rx.recv().await { match command { TargetCommand::WriteEvent(event) => { - //log::debug!("Got event to emit: {:?}", event); + log::trace!("Got event to emit: {:?}", event); let evdev_events = self.translate_event(event, axes_map.clone()); device.emit(evdev_events.as_slice())?; device.emit(&[SynchronizationEvent::new( diff --git a/src/input/target/keyboard.rs b/src/input/target/keyboard.rs index d5f59445..fbd471bc 100644 --- a/src/input/target/keyboard.rs +++ b/src/input/target/keyboard.rs @@ -387,8 +387,8 @@ fn capability_from_key_string(key: &str) -> Capability { "KEY_COMMA" => Capability::Keyboard(Keyboard::KeyComma), "KEY_DOT" => Capability::Keyboard(Keyboard::KeyDot), "KEY_SLASH" => Capability::Keyboard(Keyboard::KeySlash), - "KEY_RIGHTSHIFT" => Capability::Keyboard(Keyboard::KeyRightshift), - "KEY_KPASTERISK" => Capability::Keyboard(Keyboard::KeyKpasterisk), + "KEY_RIGHTSHIFT" => Capability::Keyboard(Keyboard::KeyRightShift), + "KEY_KPASTERISK" => Capability::Keyboard(Keyboard::KeyKpAsterisk), "KEY_LEFTALT" => Capability::Keyboard(Keyboard::KeyLeftAlt), "KEY_SPACE" => Capability::Keyboard(Keyboard::KeySpace), "KEY_CAPSLOCK" => Capability::Keyboard(Keyboard::KeyCapslock), @@ -403,20 +403,20 @@ fn capability_from_key_string(key: &str) -> Capability { "KEY_F9" => Capability::Keyboard(Keyboard::KeyF9), "KEY_F10" => Capability::Keyboard(Keyboard::KeyF10), "KEY_NUMLOCK" => Capability::Keyboard(Keyboard::KeyNumlock), - "KEY_SCROLLLOCK" => Capability::Keyboard(Keyboard::KeyScrolllock), + "KEY_SCROLLLOCK" => Capability::Keyboard(Keyboard::KeyScrollLock), "KEY_KP7" => Capability::Keyboard(Keyboard::KeyKp7), "KEY_KP8" => Capability::Keyboard(Keyboard::KeyKp8), "KEY_KP9" => Capability::Keyboard(Keyboard::KeyKp9), - "KEY_KPMINUS" => Capability::Keyboard(Keyboard::KeyKpminus), + "KEY_KPMINUS" => Capability::Keyboard(Keyboard::KeyKpMinus), "KEY_KP4" => Capability::Keyboard(Keyboard::KeyKp4), "KEY_KP5" => Capability::Keyboard(Keyboard::KeyKp5), "KEY_KP6" => Capability::Keyboard(Keyboard::KeyKp6), - "KEY_KPPLUS" => Capability::Keyboard(Keyboard::KeyKpplus), + "KEY_KPPLUS" => Capability::Keyboard(Keyboard::KeyKpPlus), "KEY_KP1" => Capability::Keyboard(Keyboard::KeyKp1), "KEY_KP2" => Capability::Keyboard(Keyboard::KeyKp2), "KEY_KP3" => Capability::Keyboard(Keyboard::KeyKp3), "KEY_KP0" => Capability::Keyboard(Keyboard::KeyKp0), - "KEY_KPDOT" => Capability::Keyboard(Keyboard::KeyKpdot), + "KEY_KPDOT" => Capability::Keyboard(Keyboard::KeyKpDot), "KEY_ZENKAKUHANKAKU" => Capability::Keyboard(Keyboard::KeyZenkakuhankaku), "KEY_102ND" => Capability::Keyboard(Keyboard::Key102nd), "KEY_F11" => Capability::Keyboard(Keyboard::KeyF11), @@ -425,35 +425,35 @@ fn capability_from_key_string(key: &str) -> Capability { "KEY_KATAKANA" => Capability::Keyboard(Keyboard::KeyKatakana), "KEY_HIRAGANA" => Capability::Keyboard(Keyboard::KeyHiragana), "KEY_HENKAN" => Capability::Keyboard(Keyboard::KeyHenkan), - "KEY_KATAKANAHIRAGANA" => Capability::Keyboard(Keyboard::KeyKatakanahiragana), + "KEY_KATAKANAHIRAGANA" => Capability::Keyboard(Keyboard::KeyKatakanaHiragana), "KEY_MUHENKAN" => Capability::Keyboard(Keyboard::KeyMuhenkan), - "KEY_KPJPCOMMA" => Capability::Keyboard(Keyboard::KeyKpjpcomma), - "KEY_KPENTER" => Capability::Keyboard(Keyboard::KeyKpenter), - "KEY_RIGHTCTRL" => Capability::Keyboard(Keyboard::KeyRightctrl), - "KEY_KPSLASH" => Capability::Keyboard(Keyboard::KeyKpslash), + "KEY_KPJPCOMMA" => Capability::Keyboard(Keyboard::KeyKpJpComma), + "KEY_KPENTER" => Capability::Keyboard(Keyboard::KeyKpEnter), + "KEY_RIGHTCTRL" => Capability::Keyboard(Keyboard::KeyRightCtrl), + "KEY_KPSLASH" => Capability::Keyboard(Keyboard::KeyKpSlash), "KEY_SYSRQ" => Capability::Keyboard(Keyboard::KeySysrq), - "KEY_RIGHTALT" => Capability::Keyboard(Keyboard::KeyRightalt), + "KEY_RIGHTALT" => Capability::Keyboard(Keyboard::KeyRightAlt), "KEY_HOME" => Capability::Keyboard(Keyboard::KeyHome), "KEY_UP" => Capability::Keyboard(Keyboard::KeyUp), - "KEY_PAGEUP" => Capability::Keyboard(Keyboard::KeyPageup), + "KEY_PAGEUP" => Capability::Keyboard(Keyboard::KeyPageUp), "KEY_LEFT" => Capability::Keyboard(Keyboard::KeyLeft), "KEY_RIGHT" => Capability::Keyboard(Keyboard::KeyRight), "KEY_END" => Capability::Keyboard(Keyboard::KeyEnd), "KEY_DOWN" => Capability::Keyboard(Keyboard::KeyDown), - "KEY_PAGEDOWN" => Capability::Keyboard(Keyboard::KeyPagedown), + "KEY_PAGEDOWN" => Capability::Keyboard(Keyboard::KeyPageDown), "KEY_INSERT" => Capability::Keyboard(Keyboard::KeyInsert), "KEY_DELETE" => Capability::Keyboard(Keyboard::KeyDelete), "KEY_MUTE" => Capability::Keyboard(Keyboard::KeyMute), "KEY_VOLUMEDOWN" => Capability::Keyboard(Keyboard::KeyVolumeDown), "KEY_VOLUMEUP" => Capability::Keyboard(Keyboard::KeyVolumeUp), "KEY_POWER" => Capability::Keyboard(Keyboard::KeyPower), - "KEY_KPEQUAL" => Capability::Keyboard(Keyboard::KeyKpequal), + "KEY_KPEQUAL" => Capability::Keyboard(Keyboard::KeyKpEqual), "KEY_PAUSE" => Capability::Keyboard(Keyboard::KeyPause), - "KEY_KPCOMMA" => Capability::Keyboard(Keyboard::KeyKpcomma), + "KEY_KPCOMMA" => Capability::Keyboard(Keyboard::KeyKpComma), "KEY_HANJA" => Capability::Keyboard(Keyboard::KeyHanja), "KEY_YEN" => Capability::Keyboard(Keyboard::KeyYen), - "KEY_LEFTMETA" => Capability::Keyboard(Keyboard::KeyLeftmeta), - "KEY_RIGHTMETA" => Capability::Keyboard(Keyboard::KeyRightmeta), + "KEY_LEFTMETA" => Capability::Keyboard(Keyboard::KeyLeftMeta), + "KEY_RIGHTMETA" => Capability::Keyboard(Keyboard::KeyRightMeta), "KEY_COMPOSE" => Capability::Keyboard(Keyboard::KeyCompose), "KEY_STOP" => Capability::Keyboard(Keyboard::KeyStop), "KEY_AGAIN" => Capability::Keyboard(Keyboard::KeyAgain), @@ -471,17 +471,17 @@ fn capability_from_key_string(key: &str) -> Capability { "KEY_WWW" => Capability::Keyboard(Keyboard::KeyWww), "KEY_BACK" => Capability::Keyboard(Keyboard::KeyBack), "KEY_FORWARD" => Capability::Keyboard(Keyboard::KeyForward), - "KEY_EJECTCD" => Capability::Keyboard(Keyboard::KeyEjectcd), - "KEY_NEXTSONG" => Capability::Keyboard(Keyboard::KeyNextsong), - "KEY_PLAYPAUSE" => Capability::Keyboard(Keyboard::KeyPlaypause), - "KEY_PREVIOUSSONG" => Capability::Keyboard(Keyboard::KeyPrevioussong), - "KEY_STOPCD" => Capability::Keyboard(Keyboard::KeyStopcd), + "KEY_EJECTCD" => Capability::Keyboard(Keyboard::KeyEjectCD), + "KEY_NEXTSONG" => Capability::Keyboard(Keyboard::KeyNextSong), + "KEY_PLAYPAUSE" => Capability::Keyboard(Keyboard::KeyPlayPause), + "KEY_PREVIOUSSONG" => Capability::Keyboard(Keyboard::KeyPreviousSong), + "KEY_STOPCD" => Capability::Keyboard(Keyboard::KeyStopCD), "KEY_REFRESH" => Capability::Keyboard(Keyboard::KeyRefresh), "KEY_EDIT" => Capability::Keyboard(Keyboard::KeyEdit), "KEY_SCROLLUP" => Capability::Keyboard(Keyboard::KeyScrollUp), "KEY_SCROLLDOWN" => Capability::Keyboard(Keyboard::KeyScrollDown), - "KEY_KPLEFTPAREN" => Capability::Keyboard(Keyboard::KeyKpleftparen), - "KEY_KPRIGHTPAREN" => Capability::Keyboard(Keyboard::KeyKprightparen), + "KEY_KPLEFTPAREN" => Capability::Keyboard(Keyboard::KeyKpLeftParen), + "KEY_KPRIGHTPAREN" => Capability::Keyboard(Keyboard::KeyKpRightParen), "KEY_F13" => Capability::Keyboard(Keyboard::KeyF13), "KEY_F14" => Capability::Keyboard(Keyboard::KeyF14), "KEY_F15" => Capability::Keyboard(Keyboard::KeyF15), diff --git a/src/input/target/steam_deck.rs b/src/input/target/steam_deck.rs index 1e5b243e..c204063b 100644 --- a/src/input/target/steam_deck.rs +++ b/src/input/target/steam_deck.rs @@ -245,7 +245,7 @@ impl SteamDeckDevice { GamepadButton::Start => self.state.menu = event.pressed(), GamepadButton::Select => self.state.options = event.pressed(), GamepadButton::Guide => self.state.steam = event.pressed(), - GamepadButton::Base => self.state.quick_access = event.pressed(), + GamepadButton::QuickAccess => self.state.quick_access = event.pressed(), GamepadButton::DPadUp => self.state.up = event.pressed(), GamepadButton::DPadDown => self.state.down = event.pressed(), GamepadButton::DPadLeft => self.state.left = event.pressed(), @@ -266,6 +266,7 @@ impl SteamDeckDevice { GamepadButton::RightStickTouch => self.state.r_stick_touch = event.pressed(), GamepadButton::RightTouchpadTouch => self.state.r_pad_touch = event.pressed(), GamepadButton::RightTouchpadPress => self.state.r_pad_press = event.pressed(), + _ => (), }, Gamepad::Axis(axis) => match axis { GamepadAxis::LeftStick => match value {