diff --git a/Cargo.lock b/Cargo.lock index 0066341..5dbaf95 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -95,16 +95,15 @@ dependencies = [ [[package]] name = "anstream" -version = "0.3.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" +checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", - "is-terminal", "utf8parse", ] @@ -134,9 +133,9 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "1.0.1" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" +checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" dependencies = [ "anstyle", "windows-sys", @@ -390,33 +389,31 @@ dependencies = [ [[package]] name = "clap" -version = "4.3.3" +version = "4.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca8f255e4b8027970e78db75e78831229c9815fdbfa67eb1a1b777a62e24b4a0" +checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956" dependencies = [ "clap_builder", "clap_derive", - "once_cell 1.18.0", ] [[package]] name = "clap_builder" -version = "4.3.3" +version = "4.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acd4f3c17c83b0ba34ffbc4f8bbd74f079413f747f84a6f89292f138057e36ab" +checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45" dependencies = [ "anstream", "anstyle", - "bitflags 1.3.2", "clap_lex", "strsim", ] [[package]] name = "clap_derive" -version = "4.3.2" +version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8cd2b2a819ad6eec39e8f1d6b53001af1e5469f8c177579cdaeb313115b825f" +checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" dependencies = [ "heck", "proc-macro2", @@ -606,6 +603,17 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" +[[package]] +name = "dbus" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bb21987b9fb1613058ba3843121dd18b163b254d8a6e797e144cbac14d96d1b" +dependencies = [ + "libc", + "libdbus-sys", + "winapi", +] + [[package]] name = "debug-helper" version = "0.3.13" @@ -820,6 +828,21 @@ dependencies = [ "num-traits", ] +[[package]] +name = "framework-inputmodule-dbus-monitor" +version = "0.0.1" +dependencies = [ + "clap", + "dbus", + "env_logger", + "inputmodule-control", + "lazy_static", + "libdbus-sys", + "log", + "serde", + "serde_json", +] + [[package]] name = "fuchsia-cprng" version = "0.1.1" @@ -1021,8 +1044,8 @@ dependencies = [ [[package]] name = "is31fl3741" -version = "0.2.1" -source = "git+https://github.com/FrameworkComputer/is31fl3741-rs?branch=sw-enablement#fb88ad1baf28aa2a61bc85ff5db83c6e2b661ed5" +version = "0.2.2" +source = "git+https://github.com/FrameworkComputer/is31fl3741-rs?branch=is31fl3743a#1814f6a838560c7553cda34cdad4692dc5da2d5f" dependencies = [ "embedded-graphics-core", "embedded-hal", @@ -1037,6 +1060,12 @@ dependencies = [ "either", ] +[[package]] +name = "itoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" + [[package]] name = "jni" version = "0.19.0" @@ -1128,6 +1157,16 @@ version = "0.2.146" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" +[[package]] +name = "libdbus-sys" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06085512b750d640299b79be4bad3d2fa90a9c00b1fd9e1b46364f66f0485c72" +dependencies = [ + "cc", + "pkg-config", +] + [[package]] name = "libloading" version = "0.7.4" @@ -1956,6 +1995,12 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "ryu" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" + [[package]] name = "same-file" version = "1.0.6" @@ -2003,6 +2048,31 @@ name = "serde" version = "1.0.164" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.164" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.18", +] + +[[package]] +name = "serde_json" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3" +dependencies = [ + "itoa", + "ryu", + "serde", +] [[package]] name = "serialport" diff --git a/Cargo.toml b/Cargo.toml index e86f3e3..840ff91 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ members = [ "ledmatrix", "fl16-inputmodules", "inputmodule-control", + "dbus-monitor" ] # Don't build all of them by default. # Because that'll lead to all features enabled in `fl16-inputmodules` and it @@ -36,7 +37,7 @@ usbd-serial = "0.1.1" usbd-hid = "0.6.1" fugit = "0.3.7" # LED Matrix -is31fl3741 = { git = "https://github.com/FrameworkComputer/is31fl3741-rs", branch = "sw-enablement" } +is31fl3741 = { git = "https://github.com/FrameworkComputer/is31fl3741-rs", branch = "is31fl3743a" } # B1 Display st7306 = { git = "https://github.com/FrameworkComputer/st7306-rs", branch = "update-deps" } embedded-graphics = "0.8" diff --git a/dbus-monitor/Cargo.toml b/dbus-monitor/Cargo.toml new file mode 100644 index 0000000..ae43a17 --- /dev/null +++ b/dbus-monitor/Cargo.toml @@ -0,0 +1,21 @@ +[package] +edition = "2021" +name = "framework-inputmodule-dbus-monitor" +version = "0.0.1" + +[dependencies] +dbus = { version = "0.9.7", features = ["vendored"] } +clap = { version = "4.4.6", features = ["derive"] } +log = "0.4" +env_logger = "0.10.0" +serde = { version="1.0", features = ["derive"] } +serde_json = "1.0" +lazy_static = "1.4" + +[dependencies.libdbus-sys] +default-features = false +features = ["vendored"] +version = "0.2.5" + +[dependencies.inputmodule-control] +path = "../inputmodule-control" \ No newline at end of file diff --git a/dbus-monitor/src/config.json b/dbus-monitor/src/config.json new file mode 100644 index 0000000..f838111 --- /dev/null +++ b/dbus-monitor/src/config.json @@ -0,0 +1,10 @@ +{ + "dbus_interface": "org.freedesktop.Notifications", + "dbus_member": "Notify", + "scan_args_for": "calendar.google.com", + "run_inputmodule_commands": [ + "led-matrix --pattern all-on --blink-n-times 3", + "led-matrix --brightness 0" + ] +} + diff --git a/dbus-monitor/src/dbus_monitor.rs b/dbus-monitor/src/dbus_monitor.rs new file mode 100644 index 0000000..05212a4 --- /dev/null +++ b/dbus-monitor/src/dbus_monitor.rs @@ -0,0 +1,165 @@ +// 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 interface specificied in config.json, +// and then run arbitary inputmodule-rs commands to react to them + +use dbus::blocking::Connection; +use dbus::channel::MatchingReceiver; +use dbus::message::MatchRule; + +use dbus::Message; +use dbus::MessageType; + +use std::time::Duration; + +use clap::Parser; +use inputmodule_control::commands::ClapCli; +use inputmodule_control::inputmodule::serial_commands; + +use log::debug; + +use serde::{Deserialize, Serialize}; +use serde_json; +use std::fs::File; +use std::io::Read; + +use lazy_static::lazy_static; + +#[derive(Debug, Deserialize, Serialize)] +pub struct Config { + dbus_interface: String, + dbus_member: String, + scan_args_for: String, + run_inputmodule_commands: Vec, +} + +fn read_config(file_path: &str) -> Result> { + let mut file = File::open(file_path)?; + let mut config_data = String::new(); + file.read_to_string(&mut config_data)?; + + let config: Config = serde_json::from_str(&config_data)?; + + Ok(config) +} + +lazy_static! { + pub static ref CONFIG: Config = { + // Read and deserialize the JSON configuration + let config_file = "dbus-monitor/src/config.json"; + let config = read_config(config_file).expect("Failed to read config"); + config + }; +} + +fn handle_message(msg: &Message) { + debug!("Got message from DBus: {:?}", msg); + + let mut iter = msg.iter_init(); + while let Some(arg) = iter.get_refarg() { + if let Some(string_ref) = arg.as_str() { + let string_value: String = string_ref.to_string(); + debug!("String value: {}", string_value); + + if string_value.contains(&CONFIG.scan_args_for) { + for command in &CONFIG.run_inputmodule_commands { + let command_vec: Vec<&str> = command.split_whitespace().collect(); + run_inputmodule_command(command_vec); + } + } + } + iter.next(); + } + + debug!("DBus 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"); + debug!("Connection to DBus session monitor opened"); + + // Second create a rule to match messages we want to receive + let rule = MatchRule::new() + .with_type(MessageType::MethodCall) + .with_interface(&CONFIG.dbus_interface) + .with_member(&CONFIG.dbus_member); + + // 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), + ); + debug!("Monitoring DBus channel..."); + + match result { + // BecomeMonitor was successful, start listening for messages + Ok(_) => { + conn.start_receive( + rule, + Box::new(|msg, _| { + debug!("Start listening"); + handle_message(&msg); + true + }), + ); + } + // BecomeMonitor failed, fallback to using the old scheme + Err(e) => { + debug!( + "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) => { + debug!("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(); + } +} diff --git a/dbus-monitor/src/main.rs b/dbus-monitor/src/main.rs new file mode 100644 index 0000000..aa4bcc6 --- /dev/null +++ b/dbus-monitor/src/main.rs @@ -0,0 +1,9 @@ +mod dbus_monitor; + +extern crate log; +use env_logger; + +fn main() { + env_logger::init(); + dbus_monitor::run_dbus_monitor(); +} diff --git a/inputmodule-control/src/commands.rs b/inputmodule-control/src/commands.rs new file mode 100644 index 0000000..c959c5d --- /dev/null +++ b/inputmodule-control/src/commands.rs @@ -0,0 +1,50 @@ +#![allow(clippy::needless_range_loop)] +#![allow(clippy::single_match)] + +use crate::b1display::B1DisplaySubcommand; +use crate::c1minimal::C1MinimalSubcommand; +use crate::inputmodule::{B1_LCD_PID, LED_MATRIX_PID}; +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, + + /// 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, + + /// Retry connecting to the device until it works + #[arg(long)] + pub wait_for_device: bool, +} diff --git a/inputmodule-control/src/inputmodule.rs b/inputmodule-control/src/inputmodule.rs index 25baa57..2ca8c8e 100644 --- a/inputmodule-control/src/inputmodule.rs +++ b/inputmodule-control/src/inputmodule.rs @@ -10,6 +10,7 @@ use serialport::{SerialPort, SerialPortInfo, SerialPortType}; use crate::b1display::{B1Pattern, Fps, PowerMode}; use crate::c1minimal::Color; +use crate::commands::ClapCli; use crate::font::{convert_font, convert_symbol}; use crate::ledmatrix::{Game, GameOfLifeStartParam, Pattern}; @@ -99,7 +100,7 @@ fn match_serialdevs( } } -pub fn find_serialdevs(args: &crate::ClapCli, wait_for_device: bool) -> (Vec, bool) { +pub fn find_serialdevs(args: &ClapCli, wait_for_device: bool) -> (Vec, bool) { let mut serialdevs: Vec; let mut waited = false; loop { @@ -151,7 +152,7 @@ pub fn find_serialdevs(args: &crate::ClapCli, wait_for_device: bool) -> (Vec, bool) = find_serialdevs(args, args.wait_for_device); if serialdevs.is_empty() { println!("Failed to find serial devivce. Please manually specify with --serial-dev"); @@ -164,7 +165,7 @@ pub fn serial_commands(args: &crate::ClapCli) { match &args.command { // TODO: Handle generic commands without code deduplication - Some(crate::Commands::LedMatrix(ledmatrix_args)) => { + Some(crate::commands::Commands::LedMatrix(ledmatrix_args)) => { for serialdev in &serialdevs { if args.verbose { println!("Selected serialdev: {:?}", serialdev); @@ -189,6 +190,9 @@ pub fn serial_commands(args: &crate::ClapCli) { if let Some(pattern) = ledmatrix_args.pattern { pattern_cmd(serialdev, pattern); } + if let Some(blink_n_times_arg) = ledmatrix_args.blink_n_times { + blink_n_cmd(&serialdevs, blink_n_times_arg); + } if ledmatrix_args.all_brightnesses { all_brightnesses_cmd(serialdev); } @@ -262,7 +266,7 @@ pub fn serial_commands(args: &crate::ClapCli) { clock_cmd(&serialdevs); } } - Some(crate::Commands::B1Display(b1display_args)) => { + Some(crate::commands::Commands::B1Display(b1display_args)) => { for serialdev in &serialdevs { if args.verbose { println!("Selected serialdev: {:?}", serialdev); @@ -312,7 +316,7 @@ pub fn serial_commands(args: &crate::ClapCli) { } } } - Some(crate::Commands::C1Minimal(c1minimal_args)) => { + Some(crate::commands::Commands::C1Minimal(c1minimal_args)) => { for serialdev in &serialdevs { if args.verbose { println!("Selected serialdev: {:?}", serialdev); @@ -555,6 +559,16 @@ fn blinking_cmd(serialdevs: &Vec) { } } +fn blink_n_cmd(serialdevs: &Vec, blink_n_times: u8) { + let duration = Duration::from_millis(500); + for _ in 0..blink_n_times { + simple_cmd_multiple(serialdevs, Command::Brightness, &[0]); + thread::sleep(duration); + simple_cmd_multiple(serialdevs, Command::Brightness, &[200]); + thread::sleep(duration); + } +} + fn breathing_cmd(serialdevs: &Vec) { loop { // Go quickly from 250 to 50 diff --git a/inputmodule-control/src/ledmatrix.rs b/inputmodule-control/src/ledmatrix.rs index b5f5ac1..01e0afb 100644 --- a/inputmodule-control/src/ledmatrix.rs +++ b/inputmodule-control/src/ledmatrix.rs @@ -70,6 +70,10 @@ pub struct LedMatrixSubcommand { #[arg(long)] pub blinking: bool, + /// Blink the current pattern once a second, n times + #[arg(long)] + pub blink_n_times: Option, + /// Breathing brightness of the current pattern #[arg(long)] pub breathing: bool, diff --git a/inputmodule-control/src/lib.rs b/inputmodule-control/src/lib.rs new file mode 100644 index 0000000..698e610 --- /dev/null +++ b/inputmodule-control/src/lib.rs @@ -0,0 +1,8 @@ +#![allow(clippy::needless_range_loop)] + +mod b1display; +mod c1minimal; +pub mod commands; +mod font; +pub mod inputmodule; +mod ledmatrix; diff --git a/inputmodule-control/src/main.rs b/inputmodule-control/src/main.rs index 8348ad7..d8d9dc6 100644 --- a/inputmodule-control/src/main.rs +++ b/inputmodule-control/src/main.rs @@ -2,58 +2,17 @@ #![allow(clippy::single_match)] mod b1display; mod c1minimal; +mod commands; mod font; mod inputmodule; mod ledmatrix; -use clap::{Parser, Subcommand}; +use clap::Parser; use inputmodule::find_serialdevs; -use crate::b1display::B1DisplaySubcommand; -use crate::c1minimal::C1MinimalSubcommand; -use crate::inputmodule::{serial_commands, B1_LCD_PID, LED_MATRIX_PID}; -use crate::ledmatrix::LedMatrixSubcommand; +use crate::inputmodule::serial_commands; -#[derive(Subcommand, Debug)] -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)] - command: Option, - - /// List connected HID devices - #[arg(short, long)] - list: bool, - - /// Verbose outputs to the console - #[arg(short, long)] - verbose: bool, - - /// Serial device, like /dev/ttyACM0 or COM0 - #[arg(long)] - pub serial_dev: Option, - - /// Retry connecting to the device until it works - #[arg(long)] - wait_for_device: bool, -} +use crate::commands::ClapCli; fn main() { let args: Vec = std::env::args().collect(); diff --git a/inputmodule-dbus-monitor/Cargo.toml b/inputmodule-dbus-monitor/Cargo.toml new file mode 100644 index 0000000..541bb31 --- /dev/null +++ b/inputmodule-dbus-monitor/Cargo.toml @@ -0,0 +1,7 @@ +[package] +edition = "2021" +name = "inputmodule-dbus-monitor" +version = "0.0.1" + +[dependencies] +dbus = { version = "0.9.7", features = ["vendored"] } diff --git a/inputmodule-dbus-monitor/src/main.rs b/inputmodule-dbus-monitor/src/main.rs new file mode 100644 index 0000000..882c612 --- /dev/null +++ b/inputmodule-dbus-monitor/src/main.rs @@ -0,0 +1,82 @@ +// Source: https://github.com/diwic/dbus-rs/blob/master/dbus/examples/monitor.rs + +use std::time::Duration; + +use dbus::blocking::Connection; +use dbus::channel::MatchingReceiver; +use dbus::message::MatchRule; +use dbus::Message; + +// This programs implements the equivalent of running the "dbus-monitor" tool +fn main() { + // Very simple argument parsing. + let use_system_bus = std::env::args().into_iter().any(|a| a == "--system"); + + // First open up a connection to the desired bus. + let conn = (if use_system_bus { Connection::new_system() } else { Connection::new_session() }).expect("D-Bus connection failed"); + + // 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(); + + // 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)); + + match result { + // BecomeMonitor was successful, start listening for messages + Ok(_) => { + conn.start_receive( + rule, + Box::new(|msg, _| { + 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(); + } +} + +fn handle_message(msg: &Message) { + println!("Got message: {:?}", msg); +} \ No newline at end of file diff --git a/release/postinstall.sh b/release/postinstall.sh index 4df223d..6c98c81 100755 --- a/release/postinstall.sh +++ b/release/postinstall.sh @@ -1,3 +1,3 @@ #!/bin/bash -cp -u ./ledmatrix/50-framework.rules /etc/udev/rules.d/ +cp -u ./release/50-framework-inputmodule.rules /etc/udev/rules.d/