-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial commit with working implementation
- Loading branch information
1 parent
20b25e8
commit 83bc861
Showing
10 changed files
with
272 additions
and
50 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains 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 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,16 @@ | ||
[package] | ||
edition = "2021" | ||
name = "framework-inputmodule-dbus-monitor" | ||
version = "0.0.1" | ||
|
||
[dependencies] | ||
dbus = { version = "0.9.7", features = ["vendored"] } | ||
clap = { version = "4.0", features = ["derive"] } | ||
|
||
[dependencies.libdbus-sys] | ||
default-features = false | ||
features = ["vendored"] | ||
version = "0.2.5" | ||
|
||
[dependencies.inputmodule-control] | ||
path = "../inputmodule-control" |
This file contains 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,120 @@ | ||
// Mostly taken from https://github.com/diwic/dbus-rs/blob/366a6dca3d20745f5dcfa006b1b1311c376d420e/dbus/examples/monitor.rs | ||
|
||
// This programs implements the equivalent of running the "dbus-monitor" tool | ||
// modified to only search for messages in the org.freedesktop.Notifications interface | ||
use dbus::blocking::Connection; | ||
use dbus::channel::MatchingReceiver; | ||
use dbus::message::MatchRule; | ||
|
||
use dbus::Message; | ||
use dbus::MessageType; | ||
|
||
use std::process::Command; | ||
use std::time::Duration; | ||
|
||
use crate::utils; | ||
|
||
use inputmodule_control::inputmodule::find_serialdevs; | ||
use inputmodule_control::commands::ClapCli; | ||
use inputmodule_control::inputmodule::{serial_commands}; | ||
use clap::{Parser, Subcommand}; | ||
|
||
fn handle_message(msg: &Message) { | ||
println!("Got message from DBus: {:?}", msg); | ||
|
||
run_inputmodule_command(vec!["led-matrix", "--pattern", "all-on", "--blinking"]); | ||
// Can't seem to get to this second command | ||
run_inputmodule_command(vec!["led-matrix", "--brightness", "0"]); | ||
|
||
println!("Message handled"); | ||
} | ||
|
||
pub fn run_inputmodule_command(args: Vec<&str>){ | ||
let bin_placeholder = vec!["bin-placeholder"]; | ||
let full_args = [&bin_placeholder[..], &args[..]].concat(); | ||
let args = ClapCli::parse_from(full_args); | ||
|
||
serial_commands(&args); | ||
} | ||
|
||
pub fn run_dbus_monitor() { | ||
// First open up a connection to the desired bus. | ||
let conn = Connection::new_session().expect("D-Bus connection failed"); | ||
println!("Connection to DBus session monitor opened"); | ||
|
||
// Second create a rule to match messages we want to receive; in this example we add no | ||
// further requirements, so all messages will match | ||
let rule = MatchRule::new() | ||
.with_type(MessageType::MethodCall) | ||
.with_interface("org.freedesktop.Notifications") | ||
.with_member("Notify"); | ||
|
||
// Try matching using new scheme | ||
let proxy = conn.with_proxy( | ||
"org.freedesktop.DBus", | ||
"/org/freedesktop/DBus", | ||
Duration::from_millis(5000), | ||
); | ||
let result: Result<(), dbus::Error> = proxy.method_call( | ||
"org.freedesktop.DBus.Monitoring", | ||
"BecomeMonitor", | ||
(vec![rule.match_str()], 0u32), | ||
); | ||
println!("Monitoring DBus channel..."); | ||
|
||
match result { | ||
// BecomeMonitor was successful, start listening for messages | ||
Ok(_) => { | ||
conn.start_receive( | ||
rule, | ||
Box::new(|msg, _| { | ||
println!("Start listening"); | ||
handle_message(&msg); | ||
true | ||
}), | ||
); | ||
} | ||
// BecomeMonitor failed, fallback to using the old scheme | ||
Err(e) => { | ||
eprintln!( | ||
"Failed to BecomeMonitor: '{}', falling back to eavesdrop", | ||
e | ||
); | ||
|
||
// First, we'll try "eavesdrop", which as the name implies lets us receive | ||
// *all* messages, not just ours. | ||
let rule_with_eavesdrop = { | ||
let mut rule = rule.clone(); | ||
rule.eavesdrop = true; | ||
rule | ||
}; | ||
|
||
let result = conn.add_match(rule_with_eavesdrop, |_: (), _, msg| { | ||
handle_message(&msg); | ||
true | ||
}); | ||
|
||
match result { | ||
Ok(_) => { | ||
// success, we're now listening | ||
} | ||
// This can sometimes fail, for example when listening to the system bus as a non-root user. | ||
// So, just like `dbus-monitor`, we attempt to fallback without `eavesdrop=true`: | ||
Err(e) => { | ||
eprintln!("Failed to eavesdrop: '{}', trying without it", e); | ||
conn.add_match(rule, |_: (), _, msg| { | ||
handle_message(&msg); | ||
true | ||
}) | ||
.expect("add_match failed"); | ||
} | ||
} | ||
} | ||
} | ||
|
||
// Loop and print out all messages received (using handle_message()) as they come. | ||
// Some can be quite large, e.g. if they contain embedded images.. | ||
loop { | ||
conn.process(Duration::from_millis(1000)).unwrap(); | ||
} | ||
} |
This file contains 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,6 @@ | ||
mod dbus_monitor; | ||
mod utils; | ||
|
||
fn main() { | ||
dbus_monitor::run_dbus_monitor(); | ||
} |
This file contains 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,27 @@ | ||
use std::process::Child; | ||
use std::process::Command; | ||
use std::time::Duration; | ||
use std::time::Instant; | ||
|
||
pub fn run_command_with_timeout( | ||
command: &str, | ||
timeout_seconds: u64, | ||
) -> Result<Child, Box<dyn std::error::Error>> { | ||
let mut child_process = Command::new("bash").arg("-c").arg(command).spawn()?; | ||
|
||
let start_time = Instant::now(); | ||
while start_time.elapsed() < Duration::from_secs(timeout_seconds) { | ||
if let Some(exit_status) = child_process.try_wait()? { | ||
println!( | ||
"Command finished before the specified duration. Exit status: {:?}", | ||
exit_status | ||
); | ||
return Ok(child_process); | ||
} | ||
} | ||
|
||
child_process.kill()?; // Attempt to kill the process | ||
|
||
println!("Command terminated after {} seconds", timeout_seconds); | ||
Ok(child_process) | ||
} |
This file contains 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,50 @@ | ||
#![allow(clippy::needless_range_loop)] | ||
#![allow(clippy::single_match)] | ||
|
||
use crate::inputmodule::{B1_LCD_PID, LED_MATRIX_PID}; | ||
use crate::b1display::B1DisplaySubcommand; | ||
use crate::c1minimal::C1MinimalSubcommand; | ||
use crate::ledmatrix::LedMatrixSubcommand; | ||
|
||
use clap::{Parser, Subcommand}; | ||
|
||
#[derive(Subcommand, Debug)] | ||
pub enum Commands { | ||
LedMatrix(LedMatrixSubcommand), | ||
B1Display(B1DisplaySubcommand), | ||
C1Minimal(C1MinimalSubcommand), | ||
} | ||
|
||
impl Commands { | ||
pub fn to_pid(&self) -> u16 { | ||
match self { | ||
Self::LedMatrix(_) => LED_MATRIX_PID, | ||
Self::B1Display(_) => B1_LCD_PID, | ||
Self::C1Minimal(_) => 0x22, | ||
} | ||
} | ||
} | ||
|
||
/// RAW HID and VIA commandline for QMK devices | ||
#[derive(Parser, Debug)] | ||
#[command(version, arg_required_else_help = true)] | ||
pub struct ClapCli { | ||
#[command(subcommand)] | ||
pub command: Option<Commands>, | ||
|
||
/// List connected HID devices | ||
#[arg(short, long)] | ||
pub list: bool, | ||
|
||
/// Verbose outputs to the console | ||
#[arg(short, long)] | ||
pub verbose: bool, | ||
|
||
/// Serial device, like /dev/ttyACM0 or COM0 | ||
#[arg(long)] | ||
pub serial_dev: Option<String>, | ||
|
||
/// Retry connecting to the device until it works | ||
#[arg(long)] | ||
pub wait_for_device: bool, | ||
} |
This file contains 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 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,9 @@ | ||
#![allow(clippy::needless_range_loop)] | ||
|
||
mod b1display; | ||
mod c1minimal; | ||
mod font; | ||
pub mod inputmodule; | ||
mod ledmatrix; | ||
pub mod commands; | ||
|
Oops, something went wrong.