Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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