Skip to content
Draft
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ hidapi = "2.6.4"
industrial-io = "0.6.1"
#evdev = { version = "0.12.1", features = ["tokio"] }
inotify = "0.11.0"
libloading = "0.9.0"
# Omit trace logging for release builds
log = { version = "0.4.29", features = [
"max_level_trace",
Expand Down
45 changes: 45 additions & 0 deletions bindings/dbus-xml/org.shadowblip.Input.Source.FastRPCDevice.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@

<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.freedesktop.DBus.Properties">
<method name="Get">
<arg name="interface_name" type="s" direction="in"/>
<arg name="property_name" type="s" direction="in"/>
<arg type="v" direction="out"/>
</method>
<method name="Set">
<arg name="interface_name" type="s" direction="in"/>
<arg name="property_name" type="s" direction="in"/>
<arg name="value" type="v" direction="in"/>
</method>
<method name="GetAll">
<arg name="interface_name" type="s" direction="in"/>
<arg type="a{sv}" direction="out"/>
</method>
<signal name="PropertiesChanged">
<arg name="interface_name" type="s"/>
<arg name="changed_properties" type="a{sv}"/>
<arg name="invalidated_properties" type="as"/>
</signal>
</interface>
<interface name="org.freedesktop.DBus.Introspectable">
<method name="Introspect">
<arg type="s" direction="out"/>
</method>
</interface>
<interface name="org.freedesktop.DBus.Peer">
<method name="Ping">
</method>
<method name="GetMachineId">
<arg type="s" direction="out"/>
</method>
</interface>
<interface name="org.shadowblip.Input.Source.FastRPCDevice">
<!--
Returns the human readable name of the device (e.g. XBox 360 Pad)
-->
<property name="Id" type="s" access="read"/>
</interface>
</node>

17 changes: 17 additions & 0 deletions rootfs/usr/share/inputplumber/schema/composite_device_v1.json
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,9 @@
"evdev": {
"$ref": "#/definitions/Evdev"
},
"fastrpc": {
"$ref": "#/definitions/FastRPC"
},
"hidraw": {
"$ref": "#/definitions/Hidraw"
},
Expand Down Expand Up @@ -380,6 +383,20 @@
"required": [],
"title": "Evdev"
},
"FastRPC": {
"type": "object",
"additionalProperties": false,
"properties": {
"id": {
"description": "Name of the FastRPC device: /dev/fastrpc*",
"type": "string"
},
"name": {
"type": "string"
}
},
"title": "FastRPC"
},
"Hidraw": {
"type": "object",
"additionalProperties": false,
Expand Down
57 changes: 57 additions & 0 deletions src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,9 @@ pub struct SourceDevice {
/// Devices that match the given evdev properties will be captured by InputPlumber
#[serde(skip_serializing_if = "Option::is_none")]
pub evdev: Option<Evdev>,
/// Devices that match the given fastrpc properties will be captured by InputPlumber
#[serde(skip_serializing_if = "Option::is_none")]
pub fastrpc: Option<FastRpc>,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this new config interface add additional value? I would think that the udev config would be able to find these devices without the need for another protocol specific entry. evdev/hidraw/etc. are all legacy config options we'd ideally like to get away from.

/// Devices that match the given hidraw properties will be captured by InputPlumber
#[serde(skip_serializing_if = "Option::is_none")]
pub hidraw: Option<Hidraw>,
Expand Down Expand Up @@ -403,6 +406,15 @@ pub struct IIO {
pub mount_matrix: Option<MountMatrix>,
}

#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
#[serde(rename_all = "snake_case")]
pub struct FastRpc {
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
}

#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
#[serde(rename_all = "snake_case")]
#[allow(clippy::upper_case_acronyms)]
Expand Down Expand Up @@ -440,6 +452,16 @@ pub struct MountMatrix {
pub z: [f64; 3],
}

impl Default for MountMatrix {
fn default() -> Self {
MountMatrix {
x: [1.0, 0.0, 0.0],
y: [0.0, 1.0, 0.0],
z: [0.0, 0.0, 1.0],
}
}
}

#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
#[serde(rename_all = "snake_case")]
pub struct EventsConfig {
Expand Down Expand Up @@ -579,6 +601,12 @@ impl CompositeDeviceConfig {
return Some(config.clone());
}
}
"fastrpc" => {
let fastrpc_config = config.fastrpc.as_ref()?;
if self.has_matching_fastrpc(udevice, fastrpc_config) {
return Some(config.clone());
}
}
_ => (),
}

Expand Down Expand Up @@ -841,6 +869,35 @@ impl CompositeDeviceConfig {
true
}

/// Returns true if a given FastRPC device is within a list of fastrpc configs.
pub fn has_matching_fastrpc(&self, device: &UdevDevice, fastrpc_config: &FastRpc) -> bool {
log::trace!(
"Checking FastRPC config: {:?} against {:?}",
fastrpc_config,
device
);

if let Some(id) = fastrpc_config.id.as_ref() {
let dsyspath = device.syspath();
log::trace!("Checking id: {id} against {dsyspath}");
if !glob_match(id.as_str(), dsyspath.as_str()) {
return false;
}
}

if let Some(name) = fastrpc_config.name.as_ref() {
// FastRPC devices don't seem to have a name (or it's empty)
// The sysname works fine
let dname = device.sysname();
log::trace!("Checking sysname: {name} against {dname}");
if !glob_match(name.as_str(), dname.as_str()) {
return false;
}
}

true
}

/// Returns true if a given evdev device is within a list of evdev configs.
pub fn has_matching_evdev(&self, device: &UdevDevice, evdev_config: &Evdev) -> bool {
//TODO: Check if the evdev has no proterties defined, that would always match.
Expand Down
33 changes: 33 additions & 0 deletions src/dbus/interface/source/fastrpc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use crate::{
dbus::{interface::Unregisterable, polkit::check_polkit},
udev::device::UdevDevice,
};
use zbus::{fdo, message::Header, Connection};
use zbus_macros::interface;

/// DBusInterface exposing information about a FastRPC device
pub struct SourceFastRpcInterface {
device: UdevDevice,
}

impl SourceFastRpcInterface {
pub fn new(device: UdevDevice) -> SourceFastRpcInterface {
SourceFastRpcInterface { device }
}
}

#[interface(name = "org.shadowblip.Input.Source.FastRPCDevice")]
impl SourceFastRpcInterface {
/// Returns the human readable name of the device (e.g. XBox 360 Pad)
#[zbus(property)]
async fn id(
&self,
#[zbus(connection)] conn: &Connection,
#[zbus(header)] hdr: Option<Header<'_>>,
) -> fdo::Result<String> {
check_polkit(conn, hdr, "org.shadowblip.Input.Source.FastRPCDevice.Id").await?;
Ok(self.device.sysname())
}
}

impl Unregisterable for SourceFastRpcInterface {}
1 change: 1 addition & 0 deletions src/dbus/interface/source/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod evdev;
pub mod fastrpc;
pub mod hidraw;
pub mod iio_imu;
pub mod led;
Expand Down
1 change: 1 addition & 0 deletions src/drivers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub mod opineo;
pub mod oxp_hid;
pub mod oxp_tty;
pub mod rog_ally;
pub mod ssc;
pub mod steam_deck;
pub mod ultimate2_wireless;
pub mod unified_gamepad;
Expand Down
Loading
Loading