-
Notifications
You must be signed in to change notification settings - Fork 46
feat(CapabilityMap): add generic hidraw button driver #563
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
honjow
wants to merge
4
commits into
ShadowBlip:main
Choose a base branch
from
honjow:feat/generic_hidraw
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
dc2ddc6
feat(CapabilityMap): add generic hidraw button driver
honjow 0a0613d
feat(Hardware Support): add GPD Win 5 HID button support for new firm…
honjow 3152835
refactor(hidraw): simplify generic button driver and translator API
honjow 401830a
feat(Hardware Support): rename GPD Win 5 HID capability map and updat…
honjow File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
44 changes: 44 additions & 0 deletions
44
rootfs/usr/share/inputplumber/capability_maps/gpd_v2_hid1.yaml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| # yaml-language-server: $schema=https://raw.githubusercontent.com/ShadowBlip/InputPlumber/main/rootfs/usr/share/inputplumber/schema/capability_map_v2.json | ||
| # Schema version number | ||
| version: 2 | ||
|
|
||
| # The type of configuration schema | ||
| kind: CapabilityMap | ||
|
|
||
| # Name for the device event map | ||
| name: GPD HID Type 1 | ||
|
|
||
| id: gpd_v2_hid1 | ||
|
|
||
| # GPD Win 5 vendor HID report (VID 0x2f24, PID 0x0137, Usage Page 0xFF00) | ||
| # Idle: 01 a5 00 5a ff 00 01 09 00 00 00 00 | ||
|
pastaq marked this conversation as resolved.
|
||
| # BUF[8] = 0x68 mode switch, 0x00 released | ||
| # BUF[9] = 0x69 left back, 0x00 released | ||
| # BUF[10] = 0x6a right back, 0x00 released | ||
| mapping: | ||
| - name: Mode Switch | ||
| source_events: | ||
| - hidraw: | ||
| input_type: button | ||
| byte_start: 8 | ||
| target_event: | ||
| gamepad: | ||
| button: QuickAccess | ||
|
|
||
| - name: Left Back | ||
| source_events: | ||
| - hidraw: | ||
| input_type: button | ||
| byte_start: 9 | ||
| target_event: | ||
| gamepad: | ||
| button: LeftPaddle1 | ||
|
|
||
| - name: Right Back | ||
| source_events: | ||
| - hidraw: | ||
| input_type: button | ||
| byte_start: 10 | ||
| target_event: | ||
| gamepad: | ||
| button: RightPaddle1 | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| pub mod translator; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,129 @@ | ||
| use crate::{ | ||
| config::capability_map::CapabilityMapConfigV2, | ||
| input::{ | ||
| capability::Capability, | ||
| event::{native::NativeEvent, value::InputValue}, | ||
| }, | ||
| }; | ||
|
|
||
| #[derive(Debug, Clone)] | ||
| struct HidrawButtonMapping { | ||
| report_id: Option<u8>, | ||
| byte_index: usize, | ||
| detection: DetectionMode, | ||
| capability: Capability, | ||
| } | ||
|
|
||
| #[derive(Debug, Clone)] | ||
| enum DetectionMode { | ||
| NonZero, | ||
| Value(u8), | ||
| /// Bit position (LSB=0) | ||
| Bit(u8), | ||
| } | ||
|
|
||
| /// Translates raw HID reports into [NativeEvent]s using a capability map. | ||
| #[derive(Debug)] | ||
| pub struct HidrawEventTranslator { | ||
| source_events: Vec<HidrawButtonMapping>, | ||
| state: Vec<bool>, | ||
| } | ||
|
|
||
| impl HidrawEventTranslator { | ||
| /// Create a new translator from a V2 capability map. | ||
| pub fn new(capability_map: &CapabilityMapConfigV2) -> Self { | ||
| let mut source_events = Vec::new(); | ||
|
|
||
| for mapping in capability_map.mapping.iter() { | ||
| for source in mapping.source_events.iter() { | ||
|
pastaq marked this conversation as resolved.
|
||
| let Some(hidraw) = source.hidraw.as_ref() else { | ||
| continue; | ||
| }; | ||
|
|
||
| if hidraw.input_type != "button" { | ||
| log::warn!( | ||
| "Unsupported hidraw input_type '{}' in mapping '{}', skipping", | ||
| hidraw.input_type, | ||
| mapping.name, | ||
| ); | ||
| continue; | ||
| } | ||
|
|
||
| let cap: Capability = mapping.target_event.clone().into(); | ||
| if cap == Capability::NotImplemented { | ||
| log::warn!( | ||
| "Unresolved target capability in mapping '{}', skipping", | ||
| mapping.name, | ||
| ); | ||
| continue; | ||
| } | ||
|
|
||
| let detection = if let Some(value) = hidraw.value { | ||
| DetectionMode::Value(value) | ||
| } else if let Some(bit) = hidraw.bit_offset { | ||
| DetectionMode::Bit(bit) | ||
| } else { | ||
| DetectionMode::NonZero | ||
| }; | ||
|
|
||
| source_events.push(HidrawButtonMapping { | ||
| report_id: hidraw.report_id, | ||
| byte_index: hidraw.byte_start as usize, | ||
| detection, | ||
| capability: cap, | ||
| }); | ||
| } | ||
| } | ||
|
|
||
| let state = vec![false; source_events.len()]; | ||
| Self { source_events, state } | ||
| } | ||
|
|
||
| pub fn has_hid_translation(&self) -> bool { | ||
| !self.source_events.is_empty() | ||
| } | ||
|
|
||
| pub fn capabilities(&self) -> Vec<Capability> { | ||
| self.source_events.iter().map(|m| m.capability.clone()).collect() | ||
| } | ||
|
|
||
| /// Translate a raw HID report into [NativeEvent]s. Only emits events on | ||
| /// state changes. | ||
| pub fn translate(&mut self, report: &[u8]) -> Vec<NativeEvent> { | ||
| let mut events = Vec::new(); | ||
|
|
||
| for (idx, mapping) in self.source_events.iter().enumerate() { | ||
| if let Some(expected_id) = mapping.report_id { | ||
| if report.first().copied() != Some(expected_id) { | ||
| continue; | ||
| } | ||
| } | ||
|
|
||
| if mapping.byte_index >= report.len() { | ||
| log::warn!( | ||
| "HID report too short for mapping at byte {}: got {} bytes", | ||
| mapping.byte_index, | ||
| report.len(), | ||
| ); | ||
| continue; | ||
|
pastaq marked this conversation as resolved.
|
||
| } | ||
|
|
||
| let byte_val = report[mapping.byte_index]; | ||
| let pressed = match mapping.detection { | ||
| DetectionMode::NonZero => byte_val != 0, | ||
| DetectionMode::Value(expected) => byte_val == expected, | ||
| DetectionMode::Bit(bit) => (byte_val & (1 << bit)) != 0, | ||
| }; | ||
|
|
||
| if pressed != self.state[idx] { | ||
| self.state[idx] = pressed; | ||
| events.push(NativeEvent::new( | ||
| mapping.capability.clone(), | ||
| InputValue::Bool(pressed), | ||
| )); | ||
| } | ||
| } | ||
|
|
||
| events | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
| pub mod context; | ||
| pub mod dbus; | ||
| pub mod evdev; | ||
| pub mod hidraw; | ||
| pub mod native; | ||
| pub mod value; | ||
|
|
||
|
|
||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.