diff --git a/Cargo.lock b/Cargo.lock index a20590a8..23083b9d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -155,6 +155,7 @@ dependencies = [ "inotify", "log", "logind-zbus", + "mio", "rog_anime", "rog_aura", "rog_platform", @@ -383,7 +384,7 @@ checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -412,13 +413,13 @@ checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" [[package]] name = "async-trait" -version = "0.1.77" +version = "0.1.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +checksum = "461abc97219de0eaaf81fe3ef974a540158f3d079c2ab200f891f1a2ef201e85" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -436,7 +437,7 @@ dependencies = [ "derive_utils", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -510,7 +511,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.52", + "syn 2.0.53", "which", ] @@ -614,7 +615,7 @@ checksum = "4da9a32f3fed317401fa3c862968128267c3106685286e15d5aaa3d7389c2f60" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -823,7 +824,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f76990911f2267d837d9d0ad060aa63aaad170af40904b29461734c339030d4d" dependencies = [ "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -850,8 +851,8 @@ dependencies = [ [[package]] name = "const-field-offset" -version = "0.1.4" -source = "git+https://github.com/flukejones/sixtyfps.git?branch=asusctl#7fb37b184fcc62a63b0c71cb096fbd62ef8d533b" +version = "0.1.5" +source = "git+https://github.com/flukejones/sixtyfps.git?branch=asusctl#0e9797e7ec4c1b8b1f342287072ccfa9712b54db" dependencies = [ "const-field-offset-macro", "field-offset", @@ -859,12 +860,12 @@ dependencies = [ [[package]] name = "const-field-offset-macro" -version = "0.1.4" -source = "git+https://github.com/flukejones/sixtyfps.git?branch=asusctl#7fb37b184fcc62a63b0c71cb096fbd62ef8d533b" +version = "0.1.5" +source = "git+https://github.com/flukejones/sixtyfps.git?branch=asusctl#0e9797e7ec4c1b8b1f342287072ccfa9712b54db" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -1030,7 +1031,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad291aa74992b9b7a7e88c38acbbf6ad7e107f1d90ee8775b7bc1fc3394f485c" dependencies = [ "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -1086,7 +1087,7 @@ checksum = "61bb5a1014ce6dfc2a378578509abe775a5aa06bff584a547555d9efdb81b926" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -1274,7 +1275,7 @@ checksum = "5c785274071b1b420972453b306eeca06acf4633829db4223b58a2a8c5953bc4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -1552,7 +1553,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -1928,7 +1929,7 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "i-slint-backend-linuxkms" version = "1.5.0" -source = "git+https://github.com/flukejones/sixtyfps.git?branch=asusctl#7fb37b184fcc62a63b0c71cb096fbd62ef8d533b" +source = "git+https://github.com/flukejones/sixtyfps.git?branch=asusctl#0e9797e7ec4c1b8b1f342287072ccfa9712b54db" dependencies = [ "calloop", "drm", @@ -1948,7 +1949,7 @@ dependencies = [ [[package]] name = "i-slint-backend-qt" version = "1.5.0" -source = "git+https://github.com/flukejones/sixtyfps.git?branch=asusctl#7fb37b184fcc62a63b0c71cb096fbd62ef8d533b" +source = "git+https://github.com/flukejones/sixtyfps.git?branch=asusctl#0e9797e7ec4c1b8b1f342287072ccfa9712b54db" dependencies = [ "const-field-offset", "i-slint-common", @@ -1960,7 +1961,7 @@ dependencies = [ [[package]] name = "i-slint-backend-selector" version = "1.5.0" -source = "git+https://github.com/flukejones/sixtyfps.git?branch=asusctl#7fb37b184fcc62a63b0c71cb096fbd62ef8d533b" +source = "git+https://github.com/flukejones/sixtyfps.git?branch=asusctl#0e9797e7ec4c1b8b1f342287072ccfa9712b54db" dependencies = [ "cfg-if", "i-slint-backend-linuxkms", @@ -1973,7 +1974,7 @@ dependencies = [ [[package]] name = "i-slint-backend-winit" version = "1.5.0" -source = "git+https://github.com/flukejones/sixtyfps.git?branch=asusctl#7fb37b184fcc62a63b0c71cb096fbd62ef8d533b" +source = "git+https://github.com/flukejones/sixtyfps.git?branch=asusctl#0e9797e7ec4c1b8b1f342287072ccfa9712b54db" dependencies = [ "bytemuck", "cfg-if", @@ -2006,7 +2007,7 @@ dependencies = [ [[package]] name = "i-slint-common" version = "1.5.0" -source = "git+https://github.com/flukejones/sixtyfps.git?branch=asusctl#7fb37b184fcc62a63b0c71cb096fbd62ef8d533b" +source = "git+https://github.com/flukejones/sixtyfps.git?branch=asusctl#0e9797e7ec4c1b8b1f342287072ccfa9712b54db" dependencies = [ "cfg-if", "derive_more", @@ -2017,7 +2018,7 @@ dependencies = [ [[package]] name = "i-slint-compiler" version = "1.5.0" -source = "git+https://github.com/flukejones/sixtyfps.git?branch=asusctl#7fb37b184fcc62a63b0c71cb096fbd62ef8d533b" +source = "git+https://github.com/flukejones/sixtyfps.git?branch=asusctl#0e9797e7ec4c1b8b1f342287072ccfa9712b54db" dependencies = [ "by_address", "codemap", @@ -2046,7 +2047,7 @@ dependencies = [ [[package]] name = "i-slint-core" version = "1.5.0" -source = "git+https://github.com/flukejones/sixtyfps.git?branch=asusctl#7fb37b184fcc62a63b0c71cb096fbd62ef8d533b" +source = "git+https://github.com/flukejones/sixtyfps.git?branch=asusctl#0e9797e7ec4c1b8b1f342287072ccfa9712b54db" dependencies = [ "auto_enums", "bytemuck", @@ -2090,16 +2091,16 @@ dependencies = [ [[package]] name = "i-slint-core-macros" version = "1.5.0" -source = "git+https://github.com/flukejones/sixtyfps.git?branch=asusctl#7fb37b184fcc62a63b0c71cb096fbd62ef8d533b" +source = "git+https://github.com/flukejones/sixtyfps.git?branch=asusctl#0e9797e7ec4c1b8b1f342287072ccfa9712b54db" dependencies = [ "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] name = "i-slint-renderer-femtovg" version = "1.5.0" -source = "git+https://github.com/flukejones/sixtyfps.git?branch=asusctl#7fb37b184fcc62a63b0c71cb096fbd62ef8d533b" +source = "git+https://github.com/flukejones/sixtyfps.git?branch=asusctl#0e9797e7ec4c1b8b1f342287072ccfa9712b54db" dependencies = [ "cfg-if", "const-field-offset", @@ -2130,7 +2131,7 @@ dependencies = [ [[package]] name = "i-slint-renderer-skia" version = "1.5.0" -source = "git+https://github.com/flukejones/sixtyfps.git?branch=asusctl#7fb37b184fcc62a63b0c71cb096fbd62ef8d533b" +source = "git+https://github.com/flukejones/sixtyfps.git?branch=asusctl#0e9797e7ec4c1b8b1f342287072ccfa9712b54db" dependencies = [ "bytemuck", "cfg-if", @@ -2774,6 +2775,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", + "log", "wasi", "windows-sys 0.48.0", ] @@ -2908,7 +2910,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -3083,7 +3085,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -3208,7 +3210,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" dependencies = [ "proc-macro2", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -3428,6 +3430,7 @@ dependencies = [ "concat-idents", "config-traits", "dirs", + "dmi_id", "env_logger", "gumdrop", "i-slint-backend-selector", @@ -3761,7 +3764,7 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -3783,7 +3786,7 @@ checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -3883,7 +3886,7 @@ dependencies = [ [[package]] name = "slint" version = "1.5.0" -source = "git+https://github.com/flukejones/sixtyfps.git?branch=asusctl#7fb37b184fcc62a63b0c71cb096fbd62ef8d533b" +source = "git+https://github.com/flukejones/sixtyfps.git?branch=asusctl#0e9797e7ec4c1b8b1f342287072ccfa9712b54db" dependencies = [ "const-field-offset", "i-slint-backend-selector", @@ -3899,7 +3902,7 @@ dependencies = [ [[package]] name = "slint-build" version = "1.5.0" -source = "git+https://github.com/flukejones/sixtyfps.git?branch=asusctl#7fb37b184fcc62a63b0c71cb096fbd62ef8d533b" +source = "git+https://github.com/flukejones/sixtyfps.git?branch=asusctl#0e9797e7ec4c1b8b1f342287072ccfa9712b54db" dependencies = [ "i-slint-compiler", "spin_on", @@ -3910,7 +3913,7 @@ dependencies = [ [[package]] name = "slint-macros" version = "1.5.0" -source = "git+https://github.com/flukejones/sixtyfps.git?branch=asusctl#7fb37b184fcc62a63b0c71cb096fbd62ef8d533b" +source = "git+https://github.com/flukejones/sixtyfps.git?branch=asusctl#0e9797e7ec4c1b8b1f342287072ccfa9712b54db" dependencies = [ "i-slint-compiler", "proc-macro2", @@ -4103,13 +4106,13 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] name = "supergfxctl" -version = "5.2.0" -source = "git+https://gitlab.com/asus-linux/supergfxctl.git#82e2cc93222998a9fd26427f682e0828f00f5a57" +version = "5.2.1" +source = "git+https://gitlab.com/asus-linux/supergfxctl.git#508d15e4bc5dc14bac27146d3bc66c31436bcdb5" dependencies = [ "log", "logind-zbus", @@ -4144,9 +4147,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.52" +version = "2.0.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" +checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032" dependencies = [ "proc-macro2", "quote", @@ -4234,7 +4237,7 @@ checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -4353,7 +4356,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -4440,7 +4443,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -4483,7 +4486,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ecce25dea8aeaadc44909f4c1226d22d84512fccd07d22447ecbad176bc09545" dependencies = [ "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -4506,6 +4509,7 @@ dependencies = [ "io-lifetimes", "libc", "libudev-sys", + "mio", "pkg-config", ] @@ -4684,7 +4688,7 @@ dependencies = [ [[package]] name = "vtable" version = "0.2.0" -source = "git+https://github.com/flukejones/sixtyfps.git?branch=asusctl#7fb37b184fcc62a63b0c71cb096fbd62ef8d533b" +source = "git+https://github.com/flukejones/sixtyfps.git?branch=asusctl#0e9797e7ec4c1b8b1f342287072ccfa9712b54db" dependencies = [ "const-field-offset", "portable-atomic", @@ -4695,11 +4699,11 @@ dependencies = [ [[package]] name = "vtable-macro" version = "0.2.0" -source = "git+https://github.com/flukejones/sixtyfps.git?branch=asusctl#7fb37b184fcc62a63b0c71cb096fbd62ef8d533b" +source = "git+https://github.com/flukejones/sixtyfps.git?branch=asusctl#0e9797e7ec4c1b8b1f342287072ccfa9712b54db" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -4745,7 +4749,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", "wasm-bindgen-shared", ] @@ -4779,7 +4783,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5583,7 +5587,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 15e55280..c25d3efc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,6 +37,7 @@ tokio = { version = "^1.23.0", default-features = false, features = [ concat-idents = "^1.1" dirs = "^4.0" smol = "^1.3" +mio = "0.8.11" zbus = "~4.0.1" logind-zbus = { version = "~4.0.0" } #, default-features = false, features = ["non_blocking"] } @@ -53,7 +54,7 @@ env_logger = "^0.10.0" glam = { version = "^0.22", features = ["serde"] } gumdrop = "^0.8" -udev = "^0.8" +udev = { version = "^0.8", features = ["mio"] } rusb = "^0.9" inotify = "^0.10.0" diff --git a/asusctl/Cargo.toml b/asusctl/Cargo.toml index 9b26db3e..ead75c5b 100644 --- a/asusctl/Cargo.toml +++ b/asusctl/Cargo.toml @@ -17,6 +17,7 @@ dmi_id = { path = "../dmi-id" } gumdrop.workspace = true toml.workspace = true zbus.workspace = true +tokio.workspace = true [dev-dependencies] gif.workspace = true diff --git a/asusctl/src/main.rs b/asusctl/src/main.rs index fdc745c4..2ed66005 100644 --- a/asusctl/src/main.rs +++ b/asusctl/src/main.rs @@ -5,7 +5,6 @@ use std::process::Command; use std::thread::sleep; use anime_cli::{AnimeActions, AnimeCommand}; -use asusd::ctrl_aura::trait_impls::AURA_ZBUS_NAME; use asusd::ctrl_fancurves::FAN_CURVE_ZBUS_NAME; use aura_cli::{LedPowerCommand1, LedPowerCommand2}; use dmi_id::DMIID; @@ -14,10 +13,10 @@ use gumdrop::{Opt, Options}; use rog_anime::usb::get_anime_type; use rog_anime::{AnimTime, AnimeDataBuffer, AnimeDiagonal, AnimeGif, AnimeImage, AnimeType, Vec2}; use rog_aura::power::KbAuraPowerState; -use rog_aura::usb::{AuraDevRog1, AuraDevTuf, AuraPowerDev}; +use rog_aura::usb::{AuraDevRog1, AuraDevTuf, AuraDevice, AuraPowerDev}; use rog_aura::{self, AuraEffect}; +use rog_dbus::zbus_aura::AuraProxyBlocking; use rog_dbus::RogDbusClientBlocking; -use rog_platform::error::PlatformError; use rog_platform::platform::{GpuMode, Properties, ThrottlePolicy}; use rog_profiles::error::ProfileError; @@ -104,6 +103,36 @@ fn check_service(name: &str) -> bool { false } +fn find_aura_iface() -> Result, Box> { + let conn = zbus::blocking::Connection::system().unwrap(); + let f = zbus::blocking::fdo::ObjectManagerProxy::new(&conn, "org.asuslinux.Daemon", "/org") + .unwrap(); + let interfaces = f.get_managed_objects().unwrap(); + let mut aura_paths = Vec::new(); + for v in interfaces.iter() { + // let o: Vec = v.1.keys().map(|e| + // e.to_owned()).collect(); println!("{}, {:?}", v.0, o); + for k in v.1.keys() { + if k.as_str() == "org.asuslinux.Aura" { + println!("Found aura device at {}, {}", v.0, k); + aura_paths.push(v.0.clone()); + } + } + } + if aura_paths.len() > 1 { + println!("Multiple aura devices found: {aura_paths:?}"); + println!("TODO: enable selection"); + } + if let Some(path) = aura_paths.first() { + return Ok(AuraProxyBlocking::builder(&conn) + .path(path.clone())? + .destination("org.asuslinux.Daemon")? + .build()?); + } + + Err("No Aura interface".into()) +} + fn do_parsed( parsed: &CliStart, supported_interfaces: &[String], @@ -111,9 +140,9 @@ fn do_parsed( dbus: &RogDbusClientBlocking<'_>, ) -> Result<(), Box> { match &parsed.command { - Some(CliCommand::LedMode(mode)) => handle_led_mode(dbus, supported_interfaces, mode)?, - Some(CliCommand::LedPow1(pow)) => handle_led_power1(dbus, supported_interfaces, pow)?, - Some(CliCommand::LedPow2(pow)) => handle_led_power2(dbus, supported_interfaces, pow)?, + Some(CliCommand::LedMode(mode)) => handle_led_mode(&find_aura_iface()?, mode)?, + Some(CliCommand::LedPow1(pow)) => handle_led_power1(&find_aura_iface()?, pow)?, + Some(CliCommand::LedPow2(pow)) => handle_led_power2(&find_aura_iface()?, pow)?, Some(CliCommand::Profile(cmd)) => handle_throttle_profile(dbus, supported_properties, cmd)?, Some(CliCommand::FanCurve(cmd)) => { handle_fan_curve(dbus, supported_interfaces, cmd)?; @@ -132,7 +161,11 @@ fn do_parsed( println!("{}", CliStart::usage()); println!(); if let Some(cmdlist) = CliStart::command_list() { - let dev_type = dbus.proxies().aura().device_type()?; + let dev_type = if let Ok(proxy) = find_aura_iface() { + proxy.device_type().unwrap_or(AuraDevice::Unknown) + } else { + AuraDevice::Unknown + }; let commands: Vec = cmdlist.lines().map(|s| s.to_owned()).collect(); for command in commands.iter().filter(|command| { if !dev_type.is_old_style() @@ -158,26 +191,35 @@ fn do_parsed( } if let Some(brightness) = &parsed.kbd_bright { - match brightness.level() { - None => { - let level = dbus.proxies().aura().brightness()?; - println!("Current keyboard led brightness: {level:?}"); + if let Ok(aura) = find_aura_iface() { + match brightness.level() { + None => { + let level = aura.brightness()?; + println!("Current keyboard led brightness: {level:?}"); + } + Some(level) => aura.set_brightness(rog_aura::LedBrightness::from(level))?, } - Some(level) => dbus - .proxies() - .aura() - .set_brightness(rog_aura::LedBrightness::from(level))?, + } else { + println!("No aura interface found"); } } if parsed.next_kbd_bright { - let brightness = dbus.proxies().aura().brightness()?; - dbus.proxies().aura().set_brightness(brightness.next())?; + if let Ok(aura) = find_aura_iface() { + let brightness = aura.brightness()?; + aura.set_brightness(brightness.next())?; + } else { + println!("No aura interface found"); + } } if parsed.prev_kbd_bright { - let brightness = dbus.proxies().aura().brightness()?; - dbus.proxies().aura().set_brightness(brightness.prev())?; + if let Ok(aura) = find_aura_iface() { + let brightness = aura.brightness()?; + aura.set_brightness(brightness.prev())?; + } else { + println!("No aura interface found"); + } } if parsed.show_supported { @@ -186,15 +228,17 @@ fn do_parsed( "Supported Platform Properties:\n{:#?}", supported_properties ); - if supported_interfaces.contains(&"Aura".to_owned()) { - let bright = dbus.proxies().aura().supported_brightness()?; - let modes = dbus.proxies().aura().supported_basic_modes()?; - let zones = dbus.proxies().aura().supported_basic_zones()?; - let power = dbus.proxies().aura().supported_power_zones()?; + if let Ok(aura) = find_aura_iface() { + let bright = aura.supported_brightness()?; + let modes = aura.supported_basic_modes()?; + let zones = aura.supported_basic_zones()?; + let power = aura.supported_power_zones()?; println!("Supported Keyboard Brightness:\n{:#?}", bright); println!("Supported Aura Modes:\n{:#?}", modes); println!("Supported Aura Zones:\n{:#?}", zones); println!("Supported Aura Power Zones:\n{:#?}", power); + } else { + println!("No aura interface found"); } } @@ -415,14 +459,13 @@ fn verify_brightness(brightness: f32) { } fn handle_led_mode( - dbus: &RogDbusClientBlocking<'_>, - supported: &[String], + aura: &AuraProxyBlocking, mode: &LedModeCommand, ) -> Result<(), Box> { - if !supported.contains(&AURA_ZBUS_NAME.to_string()) { - println!("This laptop does not support power options"); - return Err(PlatformError::NotSupported.into()); - } + // if !supported.contains(&AURA_ZBUS_NAME.to_string()) { + // println!("This laptop does not support power options"); + // return Err(PlatformError::NotSupported.into()); + // } if mode.command.is_none() && !mode.prev_mode && !mode.next_mode { if !mode.help { @@ -433,7 +476,7 @@ fn handle_led_mode( if let Some(cmdlist) = LedModeCommand::command_list() { let commands: Vec = cmdlist.lines().map(|s| s.to_owned()).collect(); - let modes = dbus.proxies().aura().supported_basic_modes()?; + let modes = aura.supported_basic_modes()?; for command in commands.iter().filter(|command| { for mode in &modes { if command @@ -462,46 +505,43 @@ fn handle_led_mode( return Ok(()); } if mode.next_mode { - let mode = dbus.proxies().aura().led_mode()?; - let modes = dbus.proxies().aura().supported_basic_modes()?; + let mode = aura.led_mode()?; + let modes = aura.supported_basic_modes()?; let mut pos = modes.iter().position(|m| *m == mode).unwrap() + 1; if pos >= modes.len() { pos = 0; } - dbus.proxies().aura().set_led_mode(modes[pos])?; + aura.set_led_mode(modes[pos])?; } else if mode.prev_mode { - let mode = dbus.proxies().aura().led_mode()?; - let modes = dbus.proxies().aura().supported_basic_modes()?; + let mode = aura.led_mode()?; + let modes = aura.supported_basic_modes()?; let mut pos = modes.iter().position(|m| *m == mode).unwrap(); if pos == 0 { pos = modes.len() - 1; } else { pos -= 1; } - dbus.proxies().aura().set_led_mode(modes[pos])?; + aura.set_led_mode(modes[pos])?; } else if let Some(mode) = mode.command.as_ref() { if mode.help_requested() { println!("{}", mode.self_usage()); return Ok(()); } - dbus.proxies() - .aura() - .set_led_mode_data(::from(mode))?; + aura.set_led_mode_data(::from(mode))?; } Ok(()) } fn handle_led_power1( - dbus: &RogDbusClientBlocking<'_>, - supported: &[String], + aura: &AuraProxyBlocking, power: &LedPowerCommand1, ) -> Result<(), Box> { - if !supported.contains(&AURA_ZBUS_NAME.to_string()) { - println!("This laptop does not support power options"); - return Err(PlatformError::NotSupported.into()); - } - let dev_type = dbus.proxies().aura().device_type()?; + // if !supported.contains(&AURA_ZBUS_NAME.to_string()) { + // println!("This laptop does not support power options"); + // return Err(PlatformError::NotSupported.into()); + // } + let dev_type = aura.device_type()?; if !dev_type.is_old_style() && !dev_type.is_tuf_style() { println!("This option applies only to keyboards 2021+"); } @@ -520,12 +560,12 @@ fn handle_led_power1( } if dev_type.is_old_style() { - handle_led_power_1_do_1866(dbus, power)?; + handle_led_power_1_do_1866(aura, power)?; return Ok(()); } if dev_type.is_tuf_style() { - handle_led_power_1_do_tuf(dbus, power)?; + handle_led_power_1_do_tuf(aura, power)?; return Ok(()); } @@ -534,7 +574,7 @@ fn handle_led_power1( } fn handle_led_power_1_do_1866( - dbus: &RogDbusClientBlocking<'_>, + aura: &AuraProxyBlocking, power: &LedPowerCommand1, ) -> Result<(), Box> { let mut enabled: Vec = Vec::new(); @@ -560,13 +600,13 @@ fn handle_led_power_1_do_1866( old_rog: enabled, ..Default::default() }; - dbus.proxies().aura().set_led_power(data)?; // TODO: verify this + aura.set_led_power(data)?; // TODO: verify this Ok(()) } fn handle_led_power_1_do_tuf( - dbus: &RogDbusClientBlocking<'_>, + aura: &AuraProxyBlocking, power: &LedPowerCommand1, ) -> Result<(), Box> { let mut enabled: Vec = Vec::new(); @@ -591,21 +631,20 @@ fn handle_led_power_1_do_tuf( tuf: enabled, ..Default::default() }; - dbus.proxies().aura().set_led_power(data)?; // TODO: verify this + aura.set_led_power(data)?; // TODO: verify this Ok(()) } fn handle_led_power2( - dbus: &RogDbusClientBlocking<'_>, - supported: &[String], + aura: &AuraProxyBlocking, power: &LedPowerCommand2, ) -> Result<(), Box> { - if !supported.contains(&AURA_ZBUS_NAME.to_string()) { - println!("This laptop does not support power options"); - return Err(PlatformError::NotSupported.into()); - } - let dev_type = dbus.proxies().aura().device_type()?; + // if !supported.contains(&AURA_ZBUS_NAME.to_string()) { + // println!("This laptop does not support power options"); + // return Err(PlatformError::NotSupported.into()); + // } + let dev_type = aura.device_type()?; if !dev_type.is_new_style() { println!("This option applies only to keyboards 2021+"); } @@ -641,7 +680,7 @@ fn handle_led_power2( power.shutdown = set_to.shutdown; }; - let mut enabled = dbus.proxies().aura().led_power()?; + let mut enabled = aura.led_power()?; if let Some(cmd) = &power.command { match cmd { aura_cli::SetAuraZoneEnabled::Keyboard(k) => set(&mut enabled.rog.keyboard, k), @@ -652,7 +691,7 @@ fn handle_led_power2( } } - dbus.proxies().aura().set_led_power(enabled)?; + aura.set_led_power(enabled)?; } Ok(()) diff --git a/asusd/Cargo.toml b/asusd/Cargo.toml index 41e9d71a..2e5abfba 100644 --- a/asusd/Cargo.toml +++ b/asusd/Cargo.toml @@ -24,6 +24,7 @@ futures-lite = "*" udev.workspace = true inotify.workspace = true +mio.workspace = true tokio.workspace = true # cli and logging @@ -42,4 +43,4 @@ concat-idents.workspace = true systemd-zbus = "*" [dev-dependencies] -cargo-husky.workspace = true \ No newline at end of file +cargo-husky.workspace = true diff --git a/asusd/src/ctrl_anime/mod.rs b/asusd/src/ctrl_anime/mod.rs index b846f4f9..939d22a0 100644 --- a/asusd/src/ctrl_anime/mod.rs +++ b/asusd/src/ctrl_anime/mod.rs @@ -68,7 +68,7 @@ impl CtrlAnime { let node = if usb.is_some() { unsafe { Node::Usb(usb.unwrap_unchecked()) } } else if hid.is_some() { - unsafe { Node::Hid(hid.unwrap_unchecked()) } + unsafe { Node::Hid(hid.unwrap_unchecked().0) } } else { return Err(RogError::Anime(AnimeError::NoDevice)); }; diff --git a/asusd/src/ctrl_anime/trait_impls.rs b/asusd/src/ctrl_anime/trait_impls.rs index 9686537d..419c4022 100644 --- a/asusd/src/ctrl_anime/trait_impls.rs +++ b/asusd/src/ctrl_anime/trait_impls.rs @@ -16,7 +16,7 @@ use super::CtrlAnime; use crate::error::RogError; pub const ANIME_ZBUS_NAME: &str = "Anime"; -pub const ANIME_ZBUS_PATH: &str = "/org/asuslinux/Anime"; +pub const ANIME_ZBUS_PATH: &str = "/org/asuslinux"; async fn get_logind_manager<'a>() -> ManagerProxy<'a> { let connection = Connection::system() @@ -43,7 +43,7 @@ impl crate::ZbusRun for CtrlAnimeZbus { // None of these calls can be guarnateed to succeed unless we loop until okay // If the try_lock *does* succeed then any other thread trying to lock will not // grab it until we finish. -#[interface(name = "org.asuslinux.Daemon")] +#[interface(name = "org.asuslinux.Anime")] impl CtrlAnimeZbus { /// Writes a data stream of length. Will force system thread to exit until /// it is restarted diff --git a/asusd/src/ctrl_aura/config.rs b/asusd/src/ctrl_aura/config.rs index e90eac52..3119124a 100644 --- a/asusd/src/ctrl_aura/config.rs +++ b/asusd/src/ctrl_aura/config.rs @@ -1,16 +1,13 @@ use std::collections::{BTreeMap, HashSet}; use config_traits::{StdConfig, StdConfigLoad}; -use log::{debug, warn}; -use rog_aura::aura_detection::{LaptopLedData, ASUS_KEYBOARD_DEVICES}; +use log::{debug, info}; +use rog_aura::aura_detection::LaptopLedData; use rog_aura::power::AuraPower; use rog_aura::usb::{AuraDevRog1, AuraDevTuf, AuraDevice, AuraPowerDev}; use rog_aura::{AuraEffect, AuraModeNum, AuraZone, Direction, LedBrightness, Speed, GRADIENT}; -use rog_platform::hid_raw::HidRaw; use serde_derive::{Deserialize, Serialize}; -const CONFIG_FILE: &str = "aura.ron"; - /// Enable/disable LED control in various states such as /// when the device is awake, suspended, shutting down or /// booting. @@ -107,6 +104,7 @@ impl From<&AuraPowerConfig> for AuraPowerDev { #[derive(Deserialize, Serialize, Debug, Clone)] // #[serde(default)] pub struct AuraConfig { + pub config_name: String, pub brightness: LedBrightness, pub current_mode: AuraModeNum, pub builtins: BTreeMap, @@ -115,18 +113,18 @@ pub struct AuraConfig { pub enabled: AuraPowerConfig, } +impl AuraConfig { + /// Detect the keyboard type and load from default DB if data available + pub fn new_with(prod_id: AuraDevice) -> Self { + info!("creating new AuraConfig"); + Self::from_default_support(prod_id, &LaptopLedData::get_data()) + } +} + impl StdConfig for AuraConfig { /// Detect the keyboard type and load from default DB if data available fn new() -> Self { - warn!("creating new config"); - let mut prod_id = AuraDevice::Unknown; - for prod in ASUS_KEYBOARD_DEVICES { - if HidRaw::new(prod.into()).is_ok() { - prod_id = prod; - break; - } - } - Self::from_default_support(prod_id, &LaptopLedData::get_data()) + panic!("This should not be used"); } fn config_dir() -> std::path::PathBuf { @@ -134,13 +132,20 @@ impl StdConfig for AuraConfig { } fn file_name(&self) -> String { - CONFIG_FILE.to_owned() + if self.config_name.is_empty() { + panic!("Config file name should not be empty"); + } + self.config_name.to_owned() } } impl StdConfigLoad for AuraConfig {} impl AuraConfig { + pub fn set_filename(&mut self, prod_id: AuraDevice) { + self.config_name = format!("aura_{prod_id:?}.ron"); + } + pub fn from_default_support(prod_id: AuraDevice, support_data: &LaptopLedData) -> Self { // create a default config here let enabled = if prod_id.is_new_style() { @@ -162,6 +167,7 @@ impl AuraConfig { ])) }; let mut config = AuraConfig { + config_name: format!("aura_{prod_id:?}.ron"), brightness: LedBrightness::Med, current_mode: AuraModeNum::Static, builtins: BTreeMap::new(), diff --git a/asusd/src/ctrl_aura/controller.rs b/asusd/src/ctrl_aura/controller.rs index 9f87363d..a914b924 100644 --- a/asusd/src/ctrl_aura/controller.rs +++ b/asusd/src/ctrl_aura/controller.rs @@ -1,37 +1,65 @@ use std::collections::BTreeMap; use config_traits::{StdConfig, StdConfigLoad}; -use dmi_id::DMIID; -use log::{info, warn}; +use inotify::Inotify; +use log::info; use rog_aura::advanced::{LedUsbPackets, UsbPackets}; use rog_aura::aura_detection::{LaptopLedData, ASUS_KEYBOARD_DEVICES}; use rog_aura::usb::{AuraDevice, LED_APPLY, LED_SET}; use rog_aura::{AuraEffect, Direction, LedBrightness, Speed, GRADIENT, LED_MSG_LEN}; use rog_platform::hid_raw::HidRaw; use rog_platform::keyboard_led::KeyboardLed; +use zbus::zvariant::OwnedObjectPath; use super::config::{AuraConfig, AuraPowerConfig}; +use crate::ctrl_aura::manager::dbus_path_for_dev; use crate::error::RogError; #[derive(Debug)] pub enum LEDNode { + /// Brightness and/or TUF RGB controls KbdLed(KeyboardLed), - Rog(HidRaw), - None, + /// Raw HID handle + Rog(KeyboardLed, HidRaw), } +impl LEDNode { + // TODO: move various methods upwards to this + pub fn set_brightness(&self, value: u8) -> Result<(), RogError> { + match self { + LEDNode::KbdLed(k) => k.set_brightness(value)?, + LEDNode::Rog(k, _) => k.set_brightness(value)?, + } + Ok(()) + } + + pub fn get_brightness(&self) -> Result { + Ok(match self { + LEDNode::KbdLed(k) => k.get_brightness()?, + LEDNode::Rog(k, _) => k.get_brightness()?, + }) + } + + pub fn monitor_brightness(&self) -> Result { + Ok(match self { + LEDNode::KbdLed(k) => k.monitor_brightness()?, + LEDNode::Rog(k, _) => k.monitor_brightness()?, + }) + } +} + +/// Individual controller for one Aura device pub struct CtrlKbdLed { - // TODO: config stores the keyboard type as an AuraPower, use or update this pub led_prod: AuraDevice, pub led_node: LEDNode, - pub sysfs_node: KeyboardLed, - pub supported_data: LaptopLedData, + pub supported_data: LaptopLedData, // TODO: is storing this really required? pub per_key_mode_active: bool, pub config: AuraConfig, + pub dbus_path: OwnedObjectPath, } impl CtrlKbdLed { - pub fn new(supported_basic_modes: LaptopLedData) -> Result { + pub fn new(data: LaptopLedData) -> Result { let mut led_prod = AuraDevice::Unknown; let mut usb_node = None; for prod in ASUS_KEYBOARD_DEVICES { @@ -52,32 +80,63 @@ impl CtrlKbdLed { } } + let mut dbus_path = Default::default(); let rgb_led = KeyboardLed::new()?; - - if usb_node.is_none() && !rgb_led.has_kbd_rgb_mode() { - let dmi = DMIID::new().unwrap_or_default(); - if dmi.dmi_family.contains("TUF") { - warn!( - "kbd_rgb_mode was not found in the /sys/. You require a minimum 6.1 kernel \ - and a supported TUF laptop" - ); - } - return Err(RogError::NoAuraKeyboard); - } - let led_node = if let Some(rog) = usb_node { info!("Found ROG USB keyboard"); - LEDNode::Rog(rog) + dbus_path = dbus_path_for_dev(rog.1).unwrap_or_default(); + LEDNode::Rog(rgb_led, rog.0) } else if rgb_led.has_kbd_rgb_mode() { info!("Found TUF keyboard"); LEDNode::KbdLed(rgb_led.clone()) } else { - LEDNode::None + return Err(RogError::NoAuraKeyboard); + // LEDNode::None }; - // New loads data fromt he DB also - let mut config_init = AuraConfig::new(); + // New loads data from the DB also + let config = Self::init_config(led_prod, &data); + + let ctrl = CtrlKbdLed { + led_prod, + led_node, // on TUF this is the same as rgb_led / kd_brightness + supported_data: data, + per_key_mode_active: false, + config, + dbus_path, + }; + Ok(ctrl) + } + + pub fn from_device( + device: HidRaw, + dbus_path: OwnedObjectPath, + data: LaptopLedData, + ) -> Result { + let rgb_led = KeyboardLed::new()?; + let prod_id = AuraDevice::from(device.prod_id()); + + // New loads data from the DB also + let config = Self::init_config(prod_id, &data); + + let ctrl = CtrlKbdLed { + led_prod: prod_id, + led_node: LEDNode::Rog(rgb_led, device), /* on TUF this is the same as rgb_led / + * kd_brightness */ + supported_data: data, + per_key_mode_active: false, + config, + dbus_path, + }; + Ok(ctrl) + } + + fn init_config(prod_id: AuraDevice, supported_basic_modes: &LaptopLedData) -> AuraConfig { + // New loads data from the DB also + let mut config_init = AuraConfig::new_with(prod_id); + // config_init.set_filename(prod_id); let mut config_loaded = config_init.clone().load(); + config_loaded.set_filename(prod_id); // update the initialised data with what we loaded from disk for mode in &mut config_init.builtins { // update init values from loaded values if they exist @@ -107,15 +166,7 @@ impl CtrlKbdLed { *multizone_loaded = multizone_init; } - let ctrl = CtrlKbdLed { - led_prod, - led_node, // on TUF this is the same as rgb_led / kd_brightness - sysfs_node: rgb_led, // If was none then we already returned above - supported_data: supported_basic_modes, - per_key_mode_active: false, - config: config_loaded, - }; - Ok(ctrl) + config_loaded } /// Set combination state for boot animation/sleep animation/all leds/keys @@ -126,7 +177,7 @@ impl CtrlKbdLed { let buf = [1, pwr[1] as u8, pwr[2] as u8, pwr[3] as u8, pwr[4] as u8]; platform.set_kbd_rgb_state(&buf)?; } - } else if let LEDNode::Rog(hid_raw) = &self.led_node { + } else if let LEDNode::Rog(_, hid_raw) = &self.led_node { let bytes = AuraPowerConfig::to_bytes(&self.config.enabled); let message = [0x5d, 0xbd, 0x01, bytes[0], bytes[1], bytes[2], bytes[3]]; @@ -152,20 +203,20 @@ impl CtrlKbdLed { if pkt_type != PER_KEY_TYPE { self.per_key_mode_active = false; - if let LEDNode::Rog(hid_raw) = &self.led_node { + if let LEDNode::Rog(_, hid_raw) = &self.led_node { hid_raw.write_bytes(&effect[0])?; hid_raw.write_bytes(&LED_SET)?; // hid_raw.write_bytes(&LED_APPLY)?; } } else { if !self.per_key_mode_active { - if let LEDNode::Rog(hid_raw) = &self.led_node { + if let LEDNode::Rog(_, hid_raw) = &self.led_node { let init = LedUsbPackets::get_init_msg(); hid_raw.write_bytes(&init)?; } self.per_key_mode_active = true; } - if let LEDNode::Rog(hid_raw) = &self.led_node { + if let LEDNode::Rog(_, hid_raw) = &self.led_node { for row in effect.iter() { hid_raw.write_bytes(row)?; } @@ -192,7 +243,7 @@ impl CtrlKbdLed { mode.speed as u8, ]; platform.set_kbd_rgb_mode(&buf)?; - } else if let LEDNode::Rog(hid_raw) = &self.led_node { + } else if let LEDNode::Rog(_, hid_raw) = &self.led_node { let bytes: [u8; LED_MSG_LEN] = mode.into(); hid_raw.write_bytes(&bytes)?; hid_raw.write_bytes(&LED_SET)?; @@ -275,7 +326,9 @@ mod tests { use rog_aura::aura_detection::{LaptopLedData, PowerZones}; use rog_aura::usb::AuraDevice; use rog_aura::{AuraModeNum, AuraZone}; + use rog_platform::hid_raw::HidRaw; use rog_platform::keyboard_led::KeyboardLed; + use zbus::zvariant::OwnedObjectPath; use super::CtrlKbdLed; use crate::ctrl_aura::config::AuraConfig; @@ -295,11 +348,11 @@ mod tests { }; let mut controller = CtrlKbdLed { led_prod: AuraDevice::X19b6, - led_node: LEDNode::None, - sysfs_node: KeyboardLed::default(), + led_node: LEDNode::Rog(KeyboardLed::default(), HidRaw::new("id_product").unwrap()), supported_data: supported_basic_modes, per_key_mode_active: false, config, + dbus_path: OwnedObjectPath::default(), }; assert!(controller.config.multizone.is_none()); @@ -333,11 +386,11 @@ mod tests { }; let mut controller = CtrlKbdLed { led_prod: AuraDevice::X19b6, - led_node: LEDNode::None, - sysfs_node: KeyboardLed::default(), + led_node: LEDNode::Rog(KeyboardLed::default(), HidRaw::new("id_product").unwrap()), supported_data: supported_basic_modes, per_key_mode_active: false, config, + dbus_path: OwnedObjectPath::default(), }; assert!(controller.config.multizone.is_none()); diff --git a/asusd/src/ctrl_aura/manager.rs b/asusd/src/ctrl_aura/manager.rs new file mode 100644 index 00000000..52e021b1 --- /dev/null +++ b/asusd/src/ctrl_aura/manager.rs @@ -0,0 +1,203 @@ +// Plan: +// - Manager has udev monitor on USB looking for ROG devices +// - If a device is found, add it to watch +// - Add it to Zbus server +// - If udev sees device removed then remove the zbus path + +use std::collections::HashSet; +use std::sync::Arc; + +use log::{error, info, warn}; +use mio::{Events, Interest, Poll, Token}; +use rog_aura::aura_detection::LaptopLedData; +use rog_aura::usb::AuraDevice; +use rog_platform::hid_raw::HidRaw; +use tokio::sync::Mutex; +use udev::{Device, MonitorBuilder}; +// use zbus::fdo::ObjectManager; +use zbus::object_server::SignalContext; +use zbus::zvariant::{ObjectPath, OwnedObjectPath}; +use zbus::Connection; + +use crate::ctrl_aura::controller::CtrlKbdLed; +use crate::ctrl_aura::trait_impls::{CtrlAuraZbus, AURA_ZBUS_PATH}; +use crate::error::RogError; +use crate::{CtrlTask, Reloadable}; + +pub struct AuraManager { + _connection: Connection, + _interfaces: Arc>>, +} + +impl AuraManager { + pub async fn new(mut connection: Connection) -> Result { + let conn_copy = connection.clone(); + let data = LaptopLedData::get_data(); + + // Do the initial keyboard detection: + match CtrlKbdLed::new(data.clone()) { + Ok(ctrl) => { + let path = ctrl.dbus_path.clone(); + let sig_ctx = CtrlAuraZbus::signal_context(&connection)?; + let sig_ctx2 = sig_ctx.clone(); + let zbus = CtrlAuraZbus::new(ctrl, sig_ctx); + start_tasks(zbus, &mut connection, sig_ctx2, &path).await?; + } + Err(err) => { + error!("Keyboard control: {}", err); + } + } + + // connection.object_server().at("/org/asuslinux", + // ObjectManager).await.unwrap(); + + let manager = Self { + _connection: connection, + _interfaces: Default::default(), + }; + + // detect all plugged in aura devices (eventually) + tokio::spawn(async move { + let mut monitor = MonitorBuilder::new()?.match_subsystem("hidraw")?.listen()?; + let mut poll = Poll::new()?; + let mut events = Events::with_capacity(1024); + poll.registry() + .register(&mut monitor, Token(0), Interest::READABLE)?; + + loop { + poll.poll(&mut events, None).unwrap(); + for event in monitor.iter() { + if let Some(parent) = + event.parent_with_subsystem_devtype("usb", "usb_device")? + { + let action = if let Some(action) = event.action() { + action + } else { + continue; + }; + + if action == "remove" { + if let Some(path) = dbus_path_for_dev(parent.clone()) { + info!("AuraManager removing: {path:?}"); + let conn_copy = conn_copy.clone(); + tokio::spawn(async move { + let res = conn_copy + .object_server() + .remove::(&path) + .await + .map_err(|e| { + error!("Failed to remove {path:?}, {e:?}"); + e + })?; + info!("AuraManager removed: {path:?}, {res}"); + Ok::<(), RogError>(()) + }); + } + } + + let id_product = + if let Some(id_product) = parent.attribute_value("idProduct") { + id_product + } else { + continue; + }; + if let Some(p2) = event.parent() { + if let Some(driver) = p2.driver() { + // There is a tree of devices added so filter by driver + if driver != "asus" { + continue; + } + } else { + continue; + } + } + + // try conversion to known idProduct + let aura_device = AuraDevice::from(id_product.to_str().unwrap()); + if aura_device != AuraDevice::Unknown { + if action == "add" { + let dev_node = if let Some(dev_node) = event.devnode() { + dev_node + } else { + continue; + }; + + if let Ok(raw) = HidRaw::from_device(event.device()) + .map_err(|e| error!("device path error: {e:?}")) + { + let path = if let Some(path) = dbus_path_for_dev(parent) { + path + } else { + continue; + }; + if let Ok(ctrl) = + CtrlKbdLed::from_device(raw, path.clone(), data.clone()) + { + info!("AuraManager found device at: {:?}", dev_node); + let mut conn_copy = conn_copy.clone(); + // + tokio::spawn(async move { + let sig_ctx = CtrlAuraZbus::signal_context(&conn_copy)?; + let zbus = CtrlAuraZbus::new(ctrl, sig_ctx); + // Now add it to device list + let sig_ctx = CtrlAuraZbus::signal_context(&conn_copy)?; + start_tasks(zbus, &mut conn_copy, sig_ctx, &path) + .await?; + Ok::<(), RogError>(()) + }); // Can't get result from here due to + // MonitorSocket + } + } + } + } else { + warn!("idProduct:{id_product:?} is unknown, not using") + } + } + } + } + // Required for return type on tokio::spawn + #[allow(unreachable_code)] + Ok::<(), RogError>(()) + }); + Ok(manager) + } +} + +pub(crate) fn dbus_path_for_dev(parent: Device) -> Option { + if let Some(id_product) = parent.attribute_value("idProduct") { + let id_product = id_product.to_string_lossy(); + let path = if let Some(devnum) = parent.attribute_value("devnum") { + let devnum = devnum.to_string_lossy(); + if let Some(devpath) = parent.attribute_value("devpath") { + let devpath = devpath.to_string_lossy(); + format!("{AURA_ZBUS_PATH}/{id_product}_{devnum}_{devpath}") + } else { + format!("{AURA_ZBUS_PATH}/{id_product}_{devnum}") + } + } else { + format!("{AURA_ZBUS_PATH}/{id_product}") + }; + return Some(ObjectPath::from_str_unchecked(&path).into()); + } + None +} + +async fn start_tasks( + mut zbus: CtrlAuraZbus, + connection: &mut Connection, + signal_ctx: SignalContext<'static>, + path: &ObjectPath<'static>, +) -> Result<(), RogError> { + let task = zbus.clone(); + zbus.reload() + .await + .unwrap_or_else(|err| warn!("Controller error: {}", err)); + + connection + .object_server() + .at(&ObjectPath::from_str_unchecked(path), zbus) + .await + .unwrap(); + task.create_tasks(signal_ctx).await.ok(); + Ok(()) +} diff --git a/asusd/src/ctrl_aura/mod.rs b/asusd/src/ctrl_aura/mod.rs index 2da39c6e..c0d41765 100644 --- a/asusd/src/ctrl_aura/mod.rs +++ b/asusd/src/ctrl_aura/mod.rs @@ -1,4 +1,5 @@ pub mod config; pub mod controller; +pub mod manager; /// Implements `CtrlTask`, `Reloadable`, `ZbusRun` pub mod trait_impls; diff --git a/asusd/src/ctrl_aura/trait_impls.rs b/asusd/src/ctrl_aura/trait_impls.rs index 34203e52..2f852d61 100644 --- a/asusd/src/ctrl_aura/trait_impls.rs +++ b/asusd/src/ctrl_aura/trait_impls.rs @@ -10,24 +10,25 @@ use rog_aura::{AuraEffect, AuraModeNum, AuraZone, LedBrightness}; use zbus::export::futures_util::lock::{Mutex, MutexGuard}; use zbus::export::futures_util::StreamExt; use zbus::fdo::Error as ZbErr; -use zbus::{interface, Connection, SignalContext}; +use zbus::{interface, SignalContext}; use super::controller::CtrlKbdLed; use crate::error::RogError; use crate::CtrlTask; pub const AURA_ZBUS_NAME: &str = "Aura"; -pub const AURA_ZBUS_PATH: &str = "/org/asuslinux/Aura"; +pub const AURA_ZBUS_PATH: &str = "/org/asuslinux"; #[derive(Clone)] -pub struct CtrlAuraZbus( - pub Arc>, - pub Option>, -); +pub struct CtrlAuraZbus(Arc>, SignalContext<'static>); impl CtrlAuraZbus { + pub fn new(controller: CtrlKbdLed, signal: SignalContext<'static>) -> Self { + Self(Arc::new(Mutex::new(controller)), signal) + } + fn update_config(lock: &mut CtrlKbdLed) -> Result<(), RogError> { - let bright = lock.sysfs_node.get_brightness()?; + let bright = lock.led_node.get_brightness()?; lock.config.read(); lock.config.brightness = bright.into(); lock.config.write(); @@ -35,16 +36,10 @@ impl CtrlAuraZbus { } } -impl crate::ZbusRun for CtrlAuraZbus { - async fn add_to_server(self, server: &mut Connection) { - Self::add_to_server_helper(self, AURA_ZBUS_PATH, server).await; - } -} - /// The main interface for changing, reading, or notfying /// /// LED commands are split between Brightness, Modes, Per-Key -#[interface(name = "org.asuslinux.Daemon")] +#[interface(name = "org.asuslinux.Aura")] impl CtrlAuraZbus { /// Return the device type for this Aura keyboard #[zbus(property)] @@ -57,14 +52,14 @@ impl CtrlAuraZbus { #[zbus(property)] async fn brightness(&self) -> Result { let ctrl = self.0.lock().await; - Ok(ctrl.sysfs_node.get_brightness().map(|n| n.into())?) + Ok(ctrl.led_node.get_brightness().map(|n| n.into())?) } /// Set the keyboard brightness level (0-3) #[zbus(property)] async fn set_brightness(&mut self, brightness: LedBrightness) -> Result<(), ZbErr> { let ctrl = self.0.lock().await; - Ok(ctrl.sysfs_node.set_brightness(brightness.into())?) + Ok(ctrl.led_node.set_brightness(brightness.into())?) } /// Total levels of brightness available @@ -116,13 +111,11 @@ impl CtrlAuraZbus { if ctrl.config.brightness == LedBrightness::Off { ctrl.config.brightness = LedBrightness::Med; } - ctrl.sysfs_node + ctrl.led_node .set_brightness(ctrl.config.brightness.into())?; ctrl.config.write(); - if let Some(ct) = self.1.as_ref() { - self.led_mode_data_invalidate(ct).await.ok(); - } + self.led_mode_data_invalidate(&self.1).await.ok(); Ok(()) } @@ -157,14 +150,12 @@ impl CtrlAuraZbus { if ctrl.config.brightness == LedBrightness::Off { ctrl.config.brightness = LedBrightness::Med; } - ctrl.sysfs_node + ctrl.led_node .set_brightness(ctrl.config.brightness.into())?; ctrl.config.set_builtin(effect); ctrl.config.write(); - if let Some(ct) = self.1.as_ref() { - self.led_mode_invalidate(ct).await.ok(); - } + self.led_mode_invalidate(&self.1).await.ok(); Ok(()) } @@ -215,7 +206,7 @@ impl CtrlAuraZbus { impl CtrlTask for CtrlAuraZbus { fn zbus_path() -> &'static str { - AURA_ZBUS_PATH + "/org/asuslinux" } async fn create_tasks(&self, _: SignalContext<'static>) -> Result<(), RogError> { @@ -223,7 +214,7 @@ impl CtrlTask for CtrlAuraZbus { // If waking up if !start { info!("CtrlKbdLedTask reloading brightness and modes"); - lock.sysfs_node + lock.led_node .set_brightness(lock.config.brightness.into()) .map_err(|e| error!("CtrlKbdLedTask: {e}")) .ok(); @@ -267,7 +258,7 @@ impl CtrlTask for CtrlAuraZbus { let ctrl2 = self.0.clone(); let ctrl = self.0.lock().await; - let watch = ctrl.sysfs_node.monitor_brightness()?; + let watch = ctrl.led_node.monitor_brightness()?; tokio::spawn(async move { let mut buffer = [0; 32]; watch diff --git a/asusd/src/ctrl_fancurves.rs b/asusd/src/ctrl_fancurves.rs index 1e3d1c6a..4bb3b571 100644 --- a/asusd/src/ctrl_fancurves.rs +++ b/asusd/src/ctrl_fancurves.rs @@ -16,7 +16,7 @@ use crate::error::RogError; use crate::{CtrlTask, CONFIG_PATH_BASE}; pub const FAN_CURVE_ZBUS_NAME: &str = "FanCurves"; -pub const FAN_CURVE_ZBUS_PATH: &str = "/org/asuslinux/FanCurves"; +pub const FAN_CURVE_ZBUS_PATH: &str = "/org/asuslinux"; #[derive(Deserialize, Serialize, Debug, Default)] pub struct FanCurveConfig { @@ -100,7 +100,7 @@ impl CtrlFanCurveZbus { } } -#[interface(name = "org.asuslinux.Daemon")] +#[interface(name = "org.asuslinux.FanCurves")] impl CtrlFanCurveZbus { /// Set all fan curves for a profile to enabled status. Will also activate a /// fan curve if in the same profile mode diff --git a/asusd/src/ctrl_platform.rs b/asusd/src/ctrl_platform.rs index 2cb192df..0184a8b6 100644 --- a/asusd/src/ctrl_platform.rs +++ b/asusd/src/ctrl_platform.rs @@ -19,7 +19,7 @@ use crate::error::RogError; use crate::{task_watch_item, task_watch_item_notify, CtrlTask, ReloadAndNotify}; const PLATFORM_ZBUS_NAME: &str = "Platform"; -const PLATFORM_ZBUS_PATH: &str = "/org/asuslinux/Platform"; +const PLATFORM_ZBUS_PATH: &str = "/org/asuslinux"; macro_rules! platform_get_value { ($self:ident, $property:tt, $prop_name:literal) => { @@ -34,7 +34,6 @@ macro_rules! platform_get_value { }) }) } else { - debug!("RogPlatform: getting {} not supported", $prop_name); return Err(FdoErr::NotSupported(format!("RogPlatform: {} not supported", $prop_name))); } }) @@ -263,8 +262,12 @@ impl CtrlPlatform { } } -#[interface(name = "org.asuslinux.Daemon")] +#[interface(name = "org.asuslinux.Platform")] impl CtrlPlatform { + async fn version(&self) -> String { + crate::VERSION.to_string() + } + /// Returns a list of property names that this system supports async fn supported_properties(&self) -> Vec { let mut supported = Vec::new(); diff --git a/asusd/src/daemon.rs b/asusd/src/daemon.rs index 4fdaca3c..e6d09984 100644 --- a/asusd/src/daemon.rs +++ b/asusd/src/daemon.rs @@ -8,15 +8,13 @@ use asusd::config::Config; use asusd::ctrl_anime::config::AnimeConfig; use asusd::ctrl_anime::trait_impls::CtrlAnimeZbus; use asusd::ctrl_anime::CtrlAnime; -use asusd::ctrl_aura::controller::CtrlKbdLed; -use asusd::ctrl_aura::trait_impls::CtrlAuraZbus; +use asusd::ctrl_aura::manager::AuraManager; use asusd::ctrl_fancurves::CtrlFanCurveZbus; use asusd::ctrl_platform::CtrlPlatform; -use asusd::{print_board_info, CtrlTask, Reloadable, ZbusRun, DBUS_NAME}; +use asusd::{print_board_info, start_tasks, CtrlTask, DBUS_NAME}; use config_traits::{StdConfig, StdConfigLoad2, StdConfigLoad3}; -use log::{error, info, warn}; -use rog_aura::aura_detection::LaptopLedData; -use zbus::SignalContext; +use log::{error, info}; +use zbus::fdo::ObjectManager; #[tokio::main] async fn main() -> Result<(), Box> { @@ -59,6 +57,11 @@ async fn start_daemon() -> Result<(), Box> { // Start zbus server let mut connection = Connection::system().await?; + connection + .object_server() + .at("/org", ObjectManager) + .await + .unwrap(); let config = Config::new().load(); let cfg_path = config.file_path(); @@ -101,21 +104,7 @@ async fn start_daemon() -> Result<(), Box> { } } - let laptop = LaptopLedData::get_data(); - // CtrlKbdLed deviates from the config pattern above due to requiring a keyboard - // detection first - match CtrlKbdLed::new(laptop) { - Ok(ctrl) => { - let mut zbus = CtrlAuraZbus(Arc::new(Mutex::new(ctrl)), None); - let sig_ctx = CtrlAuraZbus::signal_context(&connection)?; - zbus.1 = Some(sig_ctx); - let sig_ctx = CtrlAuraZbus::signal_context(&connection)?; - start_tasks(zbus, &mut connection, sig_ctx).await?; - } - Err(err) => { - error!("Keyboard control: {}", err); - } - } + let _ = AuraManager::new(connection.clone()).await?; // Request dbus name after finishing initalizing all functions connection.request_name(DBUS_NAME).await?; @@ -125,22 +114,3 @@ async fn start_daemon() -> Result<(), Box> { connection.executor().tick().await; } } - -async fn start_tasks( - mut zbus: T, - connection: &mut Connection, - signal_ctx: SignalContext<'static>, -) -> Result<(), Box> -where - T: ZbusRun + Reloadable + CtrlTask + Clone, -{ - let task = zbus.clone(); - - zbus.reload() - .await - .unwrap_or_else(|err| warn!("Controller error: {}", err)); - zbus.add_to_server(connection).await; - - task.create_tasks(signal_ctx).await.ok(); - Ok(()) -} diff --git a/asusd/src/lib.rs b/asusd/src/lib.rs index 1e22307c..db784d39 100644 --- a/asusd/src/lib.rs +++ b/asusd/src/lib.rs @@ -298,3 +298,22 @@ pub trait GetSupported { fn get_supported() -> Self::A; } + +pub async fn start_tasks( + mut zbus: T, + connection: &mut Connection, + signal_ctx: SignalContext<'static>, +) -> Result<(), RogError> +where + T: ZbusRun + Reloadable + CtrlTask + Clone, +{ + let task = zbus.clone(); + + zbus.reload() + .await + .unwrap_or_else(|err| warn!("Controller error: {}", err)); + zbus.add_to_server(connection).await; + + task.create_tasks(signal_ctx).await.ok(); + Ok(()) +} diff --git a/rog-control-center/Cargo.toml b/rog-control-center/Cargo.toml index c3fe4f90..d3ae7f04 100644 --- a/rog-control-center/Cargo.toml +++ b/rog-control-center/Cargo.toml @@ -23,6 +23,7 @@ rog_aura = { path = "../rog-aura" } rog_profiles = { path = "../rog-profiles" } rog_platform = { path = "../rog-platform" } supergfxctl = { git = "https://gitlab.com/asus-linux/supergfxctl.git", default-features = false } +dmi_id = { path = "../dmi-id" } gumdrop.workspace = true log.workspace = true diff --git a/rog-control-center/src/main.rs b/rog-control-center/src/main.rs index a230c0e3..fbda2320 100644 --- a/rog-control-center/src/main.rs +++ b/rog-control-center/src/main.rs @@ -8,8 +8,9 @@ use std::thread::{self, sleep}; use std::time::Duration; use config_traits::{StdConfig, StdConfigLoad1}; +use dmi_id::DMIID; use gumdrop::Options; -use log::LevelFilter; +use log::{info, LevelFilter}; use rog_control_center::cli_options::CliStart; use rog_control_center::config::Config; use rog_control_center::error::Result; @@ -27,6 +28,12 @@ use tokio::runtime::Runtime; // use winit::window::{Fullscreen, WindowLevel}; fn main() -> Result<()> { + let dmi = DMIID::new().unwrap_or_default(); + let board_name = dmi.board_name; + let prod_family = dmi.product_family; + info!("Running on {board_name}, product: {prod_family}"); + let is_rog_ally = prod_family == "RC71L"; + // tmp-dir must live to the end of program life let _tmp_dir = match tempfile::Builder::new() .prefix("rog-gui") diff --git a/rog-control-center/src/types/fan_types.rs b/rog-control-center/src/types/fan_types.rs index f96fa2c2..013e263b 100644 --- a/rog-control-center/src/types/fan_types.rs +++ b/rog-control-center/src/types/fan_types.rs @@ -1,7 +1,8 @@ -use crate::{FanType, Profile}; use rog_platform::platform::ThrottlePolicy; use rog_profiles::FanCurvePU; +use crate::{FanType, Profile}; + impl From for ThrottlePolicy { fn from(value: Profile) -> Self { match value { diff --git a/rog-control-center/src/ui/mod.rs b/rog-control-center/src/ui/mod.rs index 1dcaacb7..45bfcda5 100644 --- a/rog-control-center/src/ui/mod.rs +++ b/rog-control-center/src/ui/mod.rs @@ -3,15 +3,15 @@ pub mod setup_aura; pub mod setup_fans; pub mod setup_system; -use config_traits::StdConfig; -use rog_dbus::zbus_platform::PlatformProxyBlocking; use std::sync::{Arc, Mutex}; +use config_traits::StdConfig; +use rog_dbus::zbus_platform::PlatformProxyBlocking; use slint::{ComponentHandle, PhysicalSize, SharedString, Weak}; use crate::config::Config; use crate::ui::setup_anime::setup_anime_page; -use crate::ui::setup_aura::setup_aura_page; +use crate::ui::setup_aura::{has_aura_iface_blocking, setup_aura_page}; use crate::ui::setup_fans::setup_fan_curve_page; use crate::ui::setup_system::{setup_system_page, setup_system_page_callbacks}; use crate::{AppSettingsPageData, MainWindow}; @@ -118,7 +118,7 @@ pub fn setup_window(config: Arc>) -> MainWindow { [ // Needs to match the order of slint sidebar items interfaces.contains(&"Platform".into()), - interfaces.contains(&"Aura".into()), + has_aura_iface_blocking().unwrap_or(false), interfaces.contains(&"Anime".into()), interfaces.contains(&"FanCurves".into()), true, diff --git a/rog-control-center/src/ui/setup_anime.rs b/rog-control-center/src/ui/setup_anime.rs index c226ddd0..188a693f 100644 --- a/rog-control-center/src/ui/setup_anime.rs +++ b/rog-control-center/src/ui/setup_anime.rs @@ -6,8 +6,7 @@ use slint::ComponentHandle; use crate::config::Config; use crate::ui::show_toast; -use crate::{set_ui_callbacks, set_ui_props_async}; -use crate::{AnimePageData, MainWindow}; +use crate::{set_ui_callbacks, set_ui_props_async, AnimePageData, MainWindow}; pub fn setup_anime_page(ui: &MainWindow, _states: Arc>) { let handle = ui.as_weak(); diff --git a/rog-control-center/src/ui/setup_aura.rs b/rog-control-center/src/ui/setup_aura.rs index f23237cd..6a857853 100644 --- a/rog-control-center/src/ui/setup_aura.rs +++ b/rog-control-center/src/ui/setup_aura.rs @@ -1,14 +1,14 @@ -use rog_aura::usb::AuraPowerDev; -use rog_dbus::zbus_aura::AuraProxy; use std::sync::{Arc, Mutex}; +use rog_aura::usb::AuraPowerDev; +use rog_dbus::zbus_aura::AuraProxy; use slint::{ComponentHandle, Model, RgbaColor, SharedString}; -use zbus::proxy::CacheProperties; use crate::config::Config; use crate::ui::show_toast; -use crate::{set_ui_callbacks, set_ui_props_async}; -use crate::{AuraPageData, MainWindow, PowerZones as SlintPowerZones}; +use crate::{ + set_ui_callbacks, set_ui_props_async, AuraPageData, MainWindow, PowerZones as SlintPowerZones, +}; fn decode_hex(s: &str) -> RgbaColor { let s = s.trim_start_matches('#'); @@ -24,6 +24,51 @@ fn decode_hex(s: &str) -> RgbaColor { } } +pub fn has_aura_iface_blocking() -> Result> { + let conn = zbus::blocking::Connection::system()?; + let f = zbus::blocking::fdo::ObjectManagerProxy::new(&conn, "org.asuslinux.Daemon", "/org")?; + let interfaces = f.get_managed_objects()?; + let mut aura_paths = Vec::new(); + for v in interfaces.iter() { + for k in v.1.keys() { + if k.as_str() == "org.asuslinux.Aura" { + aura_paths.push(v.0.clone()); + } + } + } + Ok(!aura_paths.is_empty()) +} + +/// Returns the first available Aura interface +// TODO: return all +async fn find_aura_iface() -> Result, Box> { + let conn = zbus::Connection::system().await?; + let f = zbus::fdo::ObjectManagerProxy::new(&conn, "org.asuslinux.Daemon", "/org").await?; + let interfaces = f.get_managed_objects().await?; + let mut aura_paths = Vec::new(); + for v in interfaces.iter() { + for k in v.1.keys() { + if k.as_str() == "org.asuslinux.Aura" { + println!("Found aura device at {}, {}", v.0, k); + aura_paths.push(v.0.clone()); + } + } + } + if aura_paths.len() > 1 { + println!("Multiple aura devices found: {aura_paths:?}"); + println!("TODO: enable selection"); + } + if let Some(path) = aura_paths.first() { + return Ok(AuraProxy::builder(&conn) + .path(path.clone())? + .destination("org.asuslinux.Daemon")? + .build() + .await?); + } + + Err("No Aura interface".into()) +} + pub fn setup_aura_page(ui: &MainWindow, _states: Arc>) { ui.global::().on_set_hex_from_colour(|c| { format!("#{:02X}{:02X}{:02X}", c.red(), c.green(), c.blue()).into() @@ -34,12 +79,7 @@ pub fn setup_aura_page(ui: &MainWindow, _states: Arc>) { let handle = ui.as_weak(); tokio::spawn(async move { - let conn = zbus::Connection::system().await.unwrap(); - let aura = AuraProxy::builder(&conn) - .cache_properties(CacheProperties::Yes) - .build() - .await - .unwrap(); + let aura = find_aura_iface().await.unwrap(); set_ui_props_async!(handle, aura, AuraPageData, brightness); set_ui_props_async!(handle, aura, AuraPageData, led_mode); diff --git a/rog-control-center/src/ui/setup_fans.rs b/rog-control-center/src/ui/setup_fans.rs index 54599606..896ca896 100644 --- a/rog-control-center/src/ui/setup_fans.rs +++ b/rog-control-center/src/ui/setup_fans.rs @@ -1,8 +1,8 @@ +use std::sync::{Arc, Mutex}; + use rog_dbus::zbus_fan_curves::FanCurvesProxy; use rog_platform::platform::ThrottlePolicy; use rog_profiles::fan_curve_set::CurveData; -use std::sync::{Arc, Mutex}; - use slint::{ComponentHandle, Model, Weak}; use crate::config::Config; diff --git a/rog-control-center/src/ui/setup_system.rs b/rog-control-center/src/ui/setup_system.rs index 1b36ad85..69f92388 100644 --- a/rog-control-center/src/ui/setup_system.rs +++ b/rog-control-center/src/ui/setup_system.rs @@ -1,7 +1,7 @@ -use rog_dbus::zbus_platform::{PlatformProxy, PlatformProxyBlocking}; -use rog_platform::platform::Properties; use std::sync::{Arc, Mutex}; +use rog_dbus::zbus_platform::{PlatformProxy, PlatformProxyBlocking}; +use rog_platform::platform::Properties; use slint::ComponentHandle; use super::show_toast; diff --git a/rog-control-center/ui/pages/about.slint b/rog-control-center/ui/pages/about.slint index 718fcfe4..395613f7 100644 --- a/rog-control-center/ui/pages/about.slint +++ b/rog-control-center/ui/pages/about.slint @@ -49,6 +49,14 @@ export component PageAbout inherits VerticalLayout { Text { text: "- [ ] Include fan speeds, temps in a bottom bar"; } + + Text { + text: "- [ ] Screenpad controls"; + } + + Text { + text: "- [ ] ROG Ally specific settings"; + } } } diff --git a/rog-dbus/src/zbus_anime.rs b/rog-dbus/src/zbus_anime.rs index da91971f..ef1b1e3b 100644 --- a/rog-dbus/src/zbus_anime.rs +++ b/rog-dbus/src/zbus_anime.rs @@ -3,9 +3,9 @@ use rog_anime::{Animations, AnimeDataBuffer, DeviceState as AnimeDeviceState}; use zbus::proxy; #[proxy( - interface = "org.asuslinux.Daemon", + interface = "org.asuslinux.Anime", default_service = "org.asuslinux.Daemon", - default_path = "/org/asuslinux/Anime" + default_path = "/org/asuslinux" )] trait Anime { /// DeviceState method diff --git a/rog-dbus/src/zbus_aura.rs b/rog-dbus/src/zbus_aura.rs index fc011a96..f1e5e221 100644 --- a/rog-dbus/src/zbus_aura.rs +++ b/rog-dbus/src/zbus_aura.rs @@ -32,7 +32,7 @@ use zbus::{proxy, Result}; const BLOCKING_TIME: u64 = 33; // 100ms = 10 FPS, max 50ms = 20 FPS, 40ms = 25 FPS #[proxy( - interface = "org.asuslinux.Daemon", + interface = "org.asuslinux.Aura", default_service = "org.asuslinux.Daemon", default_path = "/org/asuslinux/Aura" )] diff --git a/rog-dbus/src/zbus_fan_curves.rs b/rog-dbus/src/zbus_fan_curves.rs index e8cf4d12..ad6764c1 100644 --- a/rog-dbus/src/zbus_fan_curves.rs +++ b/rog-dbus/src/zbus_fan_curves.rs @@ -26,9 +26,9 @@ use rog_profiles::FanCurvePU; use zbus::proxy; #[proxy( - interface = "org.asuslinux.Daemon", + interface = "org.asuslinux.FanCurves", default_service = "org.asuslinux.Daemon", - default_path = "/org/asuslinux/FanCurves" + default_path = "/org/asuslinux" )] trait FanCurves { /// Get the fan-curve data for the currently active PlatformProfile diff --git a/rog-dbus/src/zbus_platform.rs b/rog-dbus/src/zbus_platform.rs index 521700fc..b7be05ce 100644 --- a/rog-dbus/src/zbus_platform.rs +++ b/rog-dbus/src/zbus_platform.rs @@ -25,9 +25,9 @@ use rog_platform::platform::{GpuMode, Properties, ThrottlePolicy}; use zbus::proxy; #[proxy( - interface = "org.asuslinux.Daemon", + interface = "org.asuslinux.Platform", default_service = "org.asuslinux.Daemon", - default_path = "/org/asuslinux/Platform" + default_path = "/org/asuslinux" )] trait Platform { /// NextThrottleThermalPolicy method diff --git a/rog-platform/src/hid_raw.rs b/rog-platform/src/hid_raw.rs index 42715d6f..40de1c5d 100644 --- a/rog-platform/src/hid_raw.rs +++ b/rog-platform/src/hid_raw.rs @@ -1,7 +1,7 @@ use std::cell::UnsafeCell; use std::fs::OpenOptions; use std::io::Write; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use log::{info, warn}; use udev::Device; @@ -10,12 +10,13 @@ use crate::error::{PlatformError, Result}; #[derive(Debug)] pub struct HidRaw { - path: UnsafeCell, + devfs_path: UnsafeCell, + syspath: PathBuf, prod_id: String, } impl HidRaw { - pub fn new(id_product: &str) -> Result { + pub fn new(id_product: &str) -> Result<(Self, Device)> { let mut enumerator = udev::Enumerator::new().map_err(|err| { warn!("{}", err); PlatformError::Udev("enumerator failed".into(), err) @@ -30,20 +31,23 @@ impl HidRaw { .scan_devices() .map_err(|e| PlatformError::IoPath("enumerator".to_owned(), e))? { - if let Some(parent) = device + if let Some(parent_device) = device .parent_with_subsystem_devtype("usb", "usb_device") .map_err(|e| { - PlatformError::IoPath(device.devpath().to_string_lossy().to_string(), e) - })? - { - if let Some(parent) = parent.attribute_value("idProduct") { + PlatformError::IoPath(device.devpath().to_string_lossy().to_string(), e) + })? { + if let Some(parent) = parent_device.attribute_value("idProduct") { if parent == id_product { if let Some(dev_node) = device.devnode() { info!("Using device at: {:?} for hidraw control", dev_node); - return Ok(Self { - path: UnsafeCell::new(dev_node.to_owned()), - prod_id: id_product.to_string(), - }); + return Ok(( + Self { + devfs_path: UnsafeCell::new(dev_node.to_owned()), + prod_id: id_product.to_string(), + syspath: device.syspath().into(), + }, + parent_device, + )); } } } @@ -56,10 +60,14 @@ impl HidRaw { "Using device at: {:?} for control", dev_node ); - return Ok(Self { - path: UnsafeCell::new(dev_node.to_owned()), - prod_id: id_product.to_string(), - }); + return Ok(( + Self { + devfs_path: UnsafeCell::new(dev_node.to_owned()), + prod_id: id_product.to_string(), + syspath: device.syspath().into(), + }, + device, + )); } } } @@ -70,15 +78,51 @@ impl HidRaw { ))) } + pub fn from_device(device: Device) -> Result { + if let Some(parent) = device + .parent_with_subsystem_devtype("usb", "usb_device") + .map_err(|e| PlatformError::IoPath(device.devpath().to_string_lossy().to_string(), e))? + { + if let Some(dev_node) = device.devnode() { + if let Some(id_product) = parent.attribute_value("idProduct") { + return Ok(Self { + devfs_path: UnsafeCell::new(dev_node.to_owned()), + prod_id: id_product.to_string_lossy().into(), + syspath: device.syspath().into(), + }); + } + } + } + Err(PlatformError::MissingFunction( + "hidraw dev no dev path".to_string(), + )) + } + + pub fn prod_id(&self) -> &str { + &self.prod_id + } + + pub fn devfs_path(&self) -> PathBuf { + unsafe { &*(self.devfs_path.get()) }.clone() + } + + pub fn syspath(&self) -> &Path { + &self.syspath + } + pub fn write_bytes(&self, message: &[u8]) -> Result<()> { - let mut path = unsafe { &*(self.path.get()) }; + let mut path = unsafe { &*(self.devfs_path.get()) }; let mut file = match OpenOptions::new().write(true).open(path) { Ok(f) => f, Err(e) => { - warn!("write_bytes failed for {:?}, trying again: {e}", self.path); + warn!( + "write_bytes failed for {:?}, trying again: {e}", + self.devfs_path + ); unsafe { - *(self.path.get()) = (*(Self::new(&self.prod_id)?.path.get())).clone(); - path = &mut *(self.path.get()); + *(self.devfs_path.get()) = + (*(Self::new(&self.prod_id)?.0.devfs_path.get())).clone(); + path = &mut *(self.devfs_path.get()); } OpenOptions::new() .write(true) @@ -91,7 +135,7 @@ impl HidRaw { } pub fn set_wakeup_disabled(&self) -> Result<()> { - let path = unsafe { &*(self.path.get()) }; + let path = unsafe { &*(self.devfs_path.get()) }; let mut dev = Device::from_syspath(path)?; Ok(dev.set_attribute_value("power/wakeup", "disabled")?) }