Skip to content

Commit

Permalink
feat(Touchscreen): add support for generic touchscreen devices
Browse files Browse the repository at this point in the history
  • Loading branch information
ShadowApex committed Jan 29, 2025
1 parent e4131c5 commit d47180a
Show file tree
Hide file tree
Showing 8 changed files with 701 additions and 17 deletions.
14 changes: 14 additions & 0 deletions rootfs/usr/share/inputplumber/devices/50-legion_go.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,19 @@ source_devices:
y: [-1, 0, 0]
z: [0, 0, -1]

# Touchscreen
#- group: touchscreen
# evdev:
# name: "NVTK0603:00 0603:F001"
# vendor_id: "*603"
# product_id: "f001"
# handler: event*
# config:
# touchscreen:
# orientation: "left"
# width: 2560
# height: 1600

# Block all evdev devices; mouse, touchpad, gamepad, keyboard
- group: gamepad
blocked: true
Expand All @@ -160,3 +173,4 @@ target_devices:
- mouse
- keyboard
- touchpad
- touchscreen
12 changes: 6 additions & 6 deletions rootfs/usr/share/inputplumber/devices/50-steam_deck.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,16 @@ source_devices:
product_id: 0x1205
interface_num: 2
# Touchscreen
- group: mouse
hidraw:
vendor_id: 0x2808
product_id: 0x1015
- group: mouse
- group: touchscreen
unique: false
blocked: true
evdev:
name: "FTS3528:00 2808:1015*"
handler: event*
config:
touchscreen:
orientation: "right"
width: 1280
height: 800
# Keyboard
- group: keyboard
evdev:
Expand Down
49 changes: 49 additions & 0 deletions rootfs/usr/share/inputplumber/schema/composite_device_v1.json
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@
"keyboard",
"mouse",
"gamepad",
"touchscreen",
"imu"
]
},
Expand All @@ -186,6 +187,9 @@
"iio": {
"$ref": "#/definitions/IIO"
},
"config": {
"$ref": "#/definitions/SourceDeviceConfig"
},
"unique": {
"description": "If false, any devices matching this description will be added to the existing composite device. Defaults to true.",
"type": "boolean"
Expand All @@ -196,6 +200,51 @@
],
"title": "SourceDevice"
},
"SourceDeviceConfig": {
"type": "object",
"additionalProperties": false,
"properties": {
"touchscreen": {
"$ref": "#/definitions/TouchscreenConfig"
},
"imu": {
"$ref": "#/definitions/ImuConfig"
}
}
},
"TouchscreenConfig": {
"type": "object",
"additionalProperties": false,
"properties": {
"orientation": {
"description": "Orientation of the touchscreen device. Defaults to normal.",
"type": "string",
"enum": [
"normal",
"left",
"right",
"upsidedown"
]
},
"width": {
"description": "Width of the touchscreen in pixels.",
"type": "integer"
},
"height": {
"description": "Height of the touchscreen in pixels.",
"type": "integer"
}
}
},
"ImuConfig": {
"type": "object",
"additionalProperties": false,
"properties": {
"mount_matrix": {
"$ref": "#/definitions/MountMatrix"
}
}
},
"Udev": {
"description": "Source device to manage. Properties support globbing patterns.",
"type": "object",
Expand Down
26 changes: 26 additions & 0 deletions src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,11 +308,36 @@ pub struct SourceDevice {
pub hidraw: Option<Hidraw>,
pub iio: Option<IIO>,
pub udev: Option<Udev>,
pub config: Option<SourceDeviceConfig>,
pub unique: Option<bool>,
pub blocked: Option<bool>,
pub ignore: Option<bool>,
}

#[derive(Debug, Deserialize, Clone, PartialEq)]
#[serde(rename_all = "snake_case")]
pub struct SourceDeviceConfig {
pub touchscreen: Option<TouchscreenConfig>,
pub imu: Option<ImuConfig>,
}

#[derive(Debug, Deserialize, Clone, PartialEq)]
#[serde(rename_all = "snake_case")]
pub struct TouchscreenConfig {
/// Orientation of the touchscreen. Can be one of: ["normal", "left", "right", "upsidedown"]
pub orientation: Option<String>,
/// Width of the touchscreen
pub width: Option<u32>,
/// Height of the touchscreen
pub height: Option<u32>,
}

#[derive(Debug, Deserialize, Clone, PartialEq)]
#[serde(rename_all = "snake_case")]
pub struct ImuConfig {
pub mount_matrix: Option<MountMatrix>,
}

#[derive(Debug, Deserialize, Clone, PartialEq)]
#[serde(rename_all = "snake_case")]
pub struct Evdev {
Expand Down Expand Up @@ -359,6 +384,7 @@ pub struct UdevAttribute {
pub struct IIO {
pub id: Option<String>,
pub name: Option<String>,
// DEPRECATED: use config.imu.mount_matrix instead
pub mount_matrix: Option<MountMatrix>,
}

Expand Down
5 changes: 4 additions & 1 deletion src/input/composite_device/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1404,11 +1404,14 @@ impl CompositeDevice {

let source_device = match subsystem.as_str() {
"input" => {
// Get any defined config for the event device
let config = self.config.get_matching_device(&device);

log::debug!("Adding source device: {:?}", device.name());
if is_blocked {
is_blocked_evdev = true;
}
let device = EventDevice::new(device, self.client(), is_blocked)?;
let device = EventDevice::new(device, self.client(), config, is_blocked)?;
SourceDevice::Event(device)
}
"hidraw" => {
Expand Down
29 changes: 28 additions & 1 deletion src/input/source/evdev.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
pub mod blocked;
pub mod gamepad;
pub mod touchscreen;

use std::{collections::HashMap, error::Error, time::Duration};

use evdev::{Device, EventType};
use touchscreen::TouchscreenEventDevice;

use crate::{
constants::BUS_SOURCES_PREFIX, input::composite_device::client::CompositeDeviceClient,
config, constants::BUS_SOURCES_PREFIX, input::composite_device::client::CompositeDeviceClient,
udev::device::UdevDevice,
};

Expand All @@ -18,41 +20,47 @@ use super::{SourceDeviceCompatible, SourceDriver, SourceDriverOptions};
enum DriverType {
Blocked,
Gamepad,
Touchscreen,
}

/// [EventDevice] represents an input device using the input event subsystem.
#[derive(Debug)]
pub enum EventDevice {
Blocked(SourceDriver<BlockedEventDevice>),
Gamepad(SourceDriver<GamepadEventDevice>),
Touchscreen(SourceDriver<TouchscreenEventDevice>),
}

impl SourceDeviceCompatible for EventDevice {
fn get_device_ref(&self) -> &UdevDevice {
match self {
EventDevice::Blocked(source_driver) => source_driver.info_ref(),
EventDevice::Gamepad(source_driver) => source_driver.info_ref(),
EventDevice::Touchscreen(source_driver) => source_driver.info_ref(),
}
}

fn get_id(&self) -> String {
match self {
EventDevice::Blocked(source_driver) => source_driver.get_id(),
EventDevice::Gamepad(source_driver) => source_driver.get_id(),
EventDevice::Touchscreen(source_driver) => source_driver.get_id(),
}
}

fn client(&self) -> super::client::SourceDeviceClient {
match self {
EventDevice::Blocked(source_driver) => source_driver.client(),
EventDevice::Gamepad(source_driver) => source_driver.client(),
EventDevice::Touchscreen(source_driver) => source_driver.client(),
}
}

async fn run(self) -> Result<(), Box<dyn Error>> {
match self {
EventDevice::Blocked(source_driver) => source_driver.run().await,
EventDevice::Gamepad(source_driver) => source_driver.run().await,
EventDevice::Touchscreen(source_driver) => source_driver.run().await,
}
}

Expand All @@ -62,13 +70,15 @@ impl SourceDeviceCompatible for EventDevice {
match self {
EventDevice::Blocked(source_driver) => source_driver.get_capabilities(),
EventDevice::Gamepad(source_driver) => source_driver.get_capabilities(),
EventDevice::Touchscreen(source_driver) => source_driver.get_capabilities(),
}
}

fn get_device_path(&self) -> String {
match self {
EventDevice::Blocked(source_driver) => source_driver.get_device_path(),
EventDevice::Gamepad(source_driver) => source_driver.get_device_path(),
EventDevice::Touchscreen(source_driver) => source_driver.get_device_path(),
}
}
}
Expand All @@ -77,6 +87,7 @@ impl EventDevice {
pub fn new(
device_info: UdevDevice,
composite_device: CompositeDeviceClient,
config: Option<config::SourceDevice>,
is_blocked: bool,
) -> Result<Self, Box<dyn Error + Send + Sync>> {
let driver_type = EventDevice::get_driver_type(&device_info, is_blocked);
Expand All @@ -97,6 +108,12 @@ impl EventDevice {
let source_device = SourceDriver::new(composite_device, device, device_info);
Ok(Self::Gamepad(source_device))
}
DriverType::Touchscreen => {
let config = config.and_then(|c| c.config).and_then(|c| c.touchscreen);
let device = TouchscreenEventDevice::new(device_info.clone(), config)?;
let source_device = SourceDriver::new(composite_device, device, device_info);
Ok(Self::Touchscreen(source_device))
}
}
}

Expand All @@ -108,6 +125,16 @@ impl EventDevice {
if is_blocked {
return DriverType::Blocked;
}

let properties = device.get_properties();
if properties.contains_key("ID_INPUT_TOUCHSCREEN") {
return DriverType::Touchscreen;
}
if properties.contains_key("ID_INPUT_JOYSTICK") {
return DriverType::Gamepad;
}

log::debug!("Unknown input device, falling back to gamepad implementation");
DriverType::Gamepad
}
}
Expand Down
Loading

0 comments on commit d47180a

Please sign in to comment.