diff --git a/CHANGELOG.md b/CHANGELOG.md index f348a8e4..a0f35421 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +# [2.2.0] - 2021-01-26 +### Added +- Dbus command to fetch all supported functions of the laptop. That is, all the + functions that asusd supports for the currently running laptop. +- Bios setting toggles for: + + Dedicated gfx toggle (support depends on the laptop) + + Bios boot POST sound toggle + +### Changed +- added config option for dedicated gfx mode on laptops with it to enable + switching directly to dedicated using `asusctl graphics -m nvidia` + # [2.1.2] - 2021-01-10 ### Changed - Adjust gfx controller to assume that the graphics driver is loaded if the diff --git a/Cargo.lock b/Cargo.lock index 07e80a87..672d9554 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -29,9 +29,8 @@ checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" [[package]] name = "asus-nb" -version = "2.1.2" +version = "2.2.0" dependencies = [ - "ctrl-gfx", "dbus", "gumdrop", "rog_fan_curve", @@ -46,10 +45,9 @@ dependencies = [ [[package]] name = "asus-nb-ctrl" -version = "2.1.2" +version = "2.2.0" dependencies = [ "asus-nb", - "ctrl-gfx", "env_logger", "gumdrop", "intel-pstate", @@ -230,16 +228,6 @@ dependencies = [ "lazy_static", ] -[[package]] -name = "ctrl-gfx" -version = "2.1.4" -dependencies = [ - "log", - "sysfs-class", - "zbus", - "zvariant", -] - [[package]] name = "dbus" version = "0.8.4" @@ -252,13 +240,13 @@ dependencies = [ [[package]] name = "derivative" -version = "2.1.3" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaed5874effa6cde088c644ddcdcb4ffd1511391c5be4fdd7a5ccd02c7e4a183" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ "proc-macro2", "quote 1.0.8", - "syn 1.0.58", + "syn 1.0.60", ] [[package]] @@ -290,7 +278,7 @@ checksum = "946ee94e3dbf58fdd324f9ce245c7b238d46a66f00e86a020b71996349e46cce" dependencies = [ "proc-macro2", "quote 1.0.8", - "syn 1.0.58", + "syn 1.0.60", ] [[package]] @@ -316,7 +304,7 @@ dependencies = [ "proc-macro2", "quote 1.0.8", "rustversion", - "syn 1.0.58", + "syn 1.0.60", "synstructure", ] @@ -331,21 +319,21 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c122a393ea57648015bf06fbd3d372378992e86b9ff5a7a497b076a28c79efe" +checksum = "1d34cfa13a63ae058bfa601fe9e313bbdb3746427c1459185464ce0fcf62e1e8" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall", + "redox_syscall 0.2.4", "winapi", ] [[package]] name = "futures" -version = "0.3.9" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c70be434c505aee38639abccb918163b63158a4b4bb791b45b7023044bdc3c9c" +checksum = "da9052a1a50244d8d5aa9bf55cbc2fb6f357c86cc52e46c62ed390a7180cf150" dependencies = [ "futures-channel", "futures-core", @@ -358,9 +346,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.9" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f01c61843314e95f96cc9245702248733a3a3d744e43e2e755e3c7af8348a0a9" +checksum = "f2d31b7ec7efab6eefc7c57233bb10b847986139d88cc2f5a02a1ae6871a1846" dependencies = [ "futures-core", "futures-sink", @@ -368,15 +356,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.9" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8d3b0917ff63a2a96173133c02818fac4a746b0a57569d3baca9ec0e945e08" +checksum = "79e5145dde8da7d1b3892dad07a9c98fc04bc39892b1ecc9692cf53e2b780a65" [[package]] name = "futures-executor" -version = "0.3.9" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ee9ca2f7eb4475772cf39dd1cd06208dce2670ad38f4d9c7262b3e15f127068" +checksum = "e9e59fdc009a4b3096bf94f740a0f2424c082521f20a9b08c5c07c48d90fd9b9" dependencies = [ "futures-core", "futures-task", @@ -385,9 +373,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.9" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e37c1a51b037b80922864b8eed90692c5cd8abd4c71ce49b77146caa47f3253b" +checksum = "28be053525281ad8259d47e4de5de657b25e7bac113458555bb4b70bc6870500" [[package]] name = "futures-lite" @@ -406,36 +394,36 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.9" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f8719ca0e1f3c5e34f3efe4570ef2c0610ca6da85ae7990d472e9cbfba13664" +checksum = "c287d25add322d9f9abdcdc5927ca398917996600182178774032e9f8258fedd" dependencies = [ "proc-macro-hack", "proc-macro2", "quote 1.0.8", - "syn 1.0.58", + "syn 1.0.60", ] [[package]] name = "futures-sink" -version = "0.3.9" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6adabac1290109cfa089f79192fb6244ad2c3f1cc2281f3e1dd987592b71feb" +checksum = "caf5c69029bda2e743fddd0582d1083951d65cc9539aebf8812f36c3491342d6" [[package]] name = "futures-task" -version = "0.3.9" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92a0843a2ff66823a8f7c77bffe9a09be2b64e533562c412d63075643ec0038" +checksum = "13de07eb8ea81ae445aca7b69f5f7bf15d7bf4912d8ca37d6645c77ae8a58d86" dependencies = [ "once_cell", ] [[package]] name = "futures-util" -version = "0.3.9" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "036a2107cdeb57f6d7322f1b6c363dad67cd63ca3b7d1b925bdf75bd5d96cda9" +checksum = "632a8cd0f2a4b3fdea1657f08bde063848c3bd00f9bbf6e256b8be78802e624b" dependencies = [ "futures-channel", "futures-core", @@ -479,14 +467,14 @@ checksum = "915ef07c710d84733522461de2a734d4d62a3fd39a4d4f404c2f385ef8618d05" dependencies = [ "proc-macro2", "quote 1.0.8", - "syn 1.0.58", + "syn 1.0.60", ] [[package]] name = "hermit-abi" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8" +checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" dependencies = [ "libc", ] @@ -590,9 +578,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.11" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" +checksum = "fcf3805d4480bb5b86070dcfeb9e2cb2ebc148adb753c5cca5f884d1d65a42b2" dependencies = [ "cfg-if 0.1.10", ] @@ -739,9 +727,9 @@ checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" [[package]] name = "pin-project-lite" -version = "0.2.1" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36743d754ccdf9954c2e352ce2d4b106e024c814f6499c2dadff80da9a442d8" +checksum = "439697af366c49a6d0a010c56a0d97685bc140ce0d377b13a2ea2aa42d64a827" [[package]] name = "pin-utils" @@ -786,7 +774,7 @@ dependencies = [ "proc-macro-error-attr", "proc-macro2", "quote 1.0.8", - "syn 1.0.58", + "syn 1.0.60", "version_check", ] @@ -809,9 +797,9 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro-nested" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eba180dafb9038b050a4c280019bbedf9f2467b61e5d892dcad585bb57aadc5a" +checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" [[package]] name = "proc-macro2" @@ -849,6 +837,15 @@ version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" +[[package]] +name = "redox_syscall" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05ec8ca9416c5ea37062b502703cd7fcb207736bc294f6e0cf367ac6fc234570" +dependencies = [ + "bitflags 1.2.1", +] + [[package]] name = "redox_users" version = "0.3.5" @@ -856,7 +853,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d" dependencies = [ "getrandom", - "redox_syscall", + "redox_syscall 0.1.57", "rust-argon2", ] @@ -935,22 +932,22 @@ checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" [[package]] name = "serde" -version = "1.0.118" +version = "1.0.123" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800" +checksum = "92d5161132722baa40d802cc70b15262b98258453e85e5d1d365c757c73869ae" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.118" +version = "1.0.123" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df" +checksum = "9391c295d64fc0abb2c556bad848f33cb8296276b1ad2677d1ae1ace4f258f31" dependencies = [ "proc-macro2", "quote 1.0.8", - "syn 1.0.58", + "syn 1.0.60", ] [[package]] @@ -972,7 +969,7 @@ checksum = "2dc6b7951b17b051f3210b063f12cc17320e2fe30ae05b0fe2a3abb068551c76" dependencies = [ "proc-macro2", "quote 1.0.8", - "syn 1.0.58", + "syn 1.0.60", ] [[package]] @@ -989,7 +986,7 @@ checksum = "133659a15339456eeeb07572eb02a91c91e9815e9cbc89566944d2c8d3efdbf6" dependencies = [ "proc-macro2", "quote 1.0.8", - "syn 1.0.58", + "syn 1.0.60", ] [[package]] @@ -1021,9 +1018,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.58" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc60a3d73ea6594cd712d830cc1f0390fd71542d8c8cd24e70cc54cdfd5e05d5" +checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081" dependencies = [ "proc-macro2", "quote 1.0.8", @@ -1047,7 +1044,7 @@ checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" dependencies = [ "proc-macro2", "quote 1.0.8", - "syn 1.0.58", + "syn 1.0.60", "unicode-xid 0.2.1", ] @@ -1062,13 +1059,12 @@ dependencies = [ [[package]] name = "tar" -version = "0.4.30" +version = "0.4.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "489997b7557e9a43e192c527face4feacc78bfbe6eed67fd55c4c9e381cba290" +checksum = "0313546c01d59e29be4f09687bcb4fb6690cec931cc3607b6aec7a0e417f4cc6" dependencies = [ "filetime", "libc", - "redox_syscall", "xattr", ] @@ -1083,11 +1079,11 @@ dependencies = [ [[package]] name = "thread_local" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb9bc092d0d51e76b2b19d9d85534ffc9ec2db959a2523cdae0697e2972cd447" +checksum = "d8208a331e1cb318dd5bd76951d2b8fc48ca38a69f5f4e4af1b6a9f8c6236915" dependencies = [ - "lazy_static", + "once_cell", ] [[package]] @@ -1313,14 +1309,14 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote 1.0.8", - "syn 1.0.58", + "syn 1.0.60", ] [[package]] name = "zvariant" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bfdc513511335faee7b18d6e8b6086de555d6e8b0a598415571bb0f0b446519" +checksum = "2fc67d552ac18ccd9e440f062f5b32c46776f96073122a8da2fe0c533833a213" dependencies = [ "byteorder", "enumflags2", @@ -1330,12 +1326,12 @@ dependencies = [ [[package]] name = "zvariant_derive" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6651d08772eefc17d36ef4da3a521b2e5f87c10ef730125b83eb500512073c92" +checksum = "eaee686340b5bff077d52423d8cc4f0f7cb323fe3f31ef676b8a3a2810bc53c5" dependencies = [ "proc-macro-crate", "proc-macro2", "quote 1.0.8", - "syn 1.0.58", + "syn 1.0.60", ] diff --git a/Cargo.toml b/Cargo.toml index bd583b88..17db13b6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["asus-notify", "asus-nb-ctrl", "asus-nb", "ctrl-gfx"] +members = ["asus-notify", "asus-nb-ctrl", "asus-nb"] [profile.release] lto = true diff --git a/asus-nb-ctrl/Cargo.toml b/asus-nb-ctrl/Cargo.toml index d5642322..c45c80e4 100644 --- a/asus-nb-ctrl/Cargo.toml +++ b/asus-nb-ctrl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "asus-nb-ctrl" -version = "2.1.2" +version = "2.2.0" license = "MPL-2.0" readme = "README.md" authors = ["Luke "] @@ -22,7 +22,6 @@ name = "asusd" path = "src/daemon.rs" [dependencies] -ctrl-gfx = { path = "../ctrl-gfx" } asus-nb = { path = "../asus-nb" } rusb = "^0.6.0" udev = "^0.4.0" @@ -47,4 +46,4 @@ rog_fan_curve = { version = "0.1.5", features = ["serde"] } # cpu power management intel-pstate = "^0.2.1" -yansi-term = "^0.1" +yansi-term = "^0.1" \ No newline at end of file diff --git a/asus-nb-ctrl/src/config.rs b/asus-nb-ctrl/src/config.rs index 3b48604b..dd4ef184 100644 --- a/asus-nb-ctrl/src/config.rs +++ b/asus-nb-ctrl/src/config.rs @@ -1,16 +1,51 @@ use asus_nb::aura_modes::AuraModes; -use log::{error, warn}; +use log::{error, info, warn}; use rog_fan_curve::Curve; use serde_derive::{Deserialize, Serialize}; use std::collections::BTreeMap; use std::fs::{File, OpenOptions}; use std::io::{Read, Write}; +use crate::VERSION; + pub static CONFIG_PATH: &str = "/etc/asusd/asusd.conf"; +/// for parsing old v2.1.2 config +#[derive(Deserialize)] +struct ConfigV212 { + gfx_managed: bool, + active_profile: String, + toggle_profiles: Vec, + // TODO: remove power_profile + power_profile: u8, + bat_charge_limit: u8, + kbd_led_brightness: u8, + kbd_backlight_mode: u8, + kbd_backlight_modes: Vec, + power_profiles: BTreeMap, +} + +impl ConfigV212 { + fn into_current(self) -> Config { + Config { + gfx_managed: self.gfx_managed, + gfx_nv_mode_is_dedicated: true, + active_profile: self.active_profile, + toggle_profiles: self.toggle_profiles, + power_profile: self.power_profile, + bat_charge_limit: self.bat_charge_limit, + kbd_led_brightness: self.kbd_led_brightness, + kbd_backlight_mode: self.kbd_backlight_mode, + kbd_backlight_modes: self.kbd_backlight_modes, + power_profiles: self.power_profiles, + } + } +} + #[derive(Default, Deserialize, Serialize)] pub struct Config { pub gfx_managed: bool, + pub gfx_nv_mode_is_dedicated: bool, pub active_profile: String, pub toggle_profiles: Vec, // TODO: remove power_profile @@ -24,7 +59,7 @@ pub struct Config { impl Config { /// `load` will attempt to read the config, and panic if the dir is missing - pub fn load(mut self, supported_led_modes: &[u8]) -> Self { + pub fn load(supported_led_modes: &[u8]) -> Self { let mut file = OpenOptions::new() .read(true) .write(true) @@ -35,23 +70,30 @@ impl Config { CONFIG_PATH )); // okay to cause panic here let mut buf = String::new(); - if let Ok(l) = file.read_to_string(&mut buf) { - if l == 0 { - self = Config::create_default(&mut file, &supported_led_modes); + if let Ok(read_len) = file.read_to_string(&mut buf) { + if read_len == 0 { + return Config::create_default(&mut file, &supported_led_modes); } else { - self = serde_json::from_str(&buf).unwrap_or_else(|_| { - warn!("Could not deserialise {}", CONFIG_PATH); - panic!("Please remove {} then restart asusd", CONFIG_PATH); - }); + if let Ok(data) = serde_json::from_str(&buf) { + return data; + } else if let Ok(data) = serde_json::from_str::(&buf) { + let config = data.into_current(); + config.write(); + info!("Updated config version to: {}", VERSION); + return config; + } + warn!("Could not deserialise {}", CONFIG_PATH); + panic!("Please remove {} then restart asusd", CONFIG_PATH); } } - self + Config::create_default(&mut file, &supported_led_modes) } fn create_default(file: &mut File, supported_led_modes: &[u8]) -> Self { // create a default config here let mut config = Config::default(); config.gfx_managed = true; + config.gfx_nv_mode_is_dedicated = true; config.bat_charge_limit = 100; config.kbd_backlight_mode = 0; diff --git a/asus-nb-ctrl/src/ctrl_anime.rs b/asus-nb-ctrl/src/ctrl_anime.rs index e0cbb55e..fc4d5af4 100644 --- a/asus-nb-ctrl/src/ctrl_anime.rs +++ b/asus-nb-ctrl/src/ctrl_anime.rs @@ -21,6 +21,20 @@ use std::error::Error; use std::time::Duration; use zbus::dbus_interface; +use crate::GetSupported; + +use serde_derive::{Deserialize, Serialize}; +#[derive(Serialize, Deserialize)] +pub struct AnimeSupportedFunctions(bool); + +impl GetSupported for CtrlAnimeDisplay { + type A = AnimeSupportedFunctions; + + fn get_supported() -> Self::A { + AnimeSupportedFunctions(CtrlAnimeDisplay::get_device(0x0b05, 0x193b).is_ok()) + } +} + #[allow(dead_code)] #[derive(Debug)] pub enum AnimatrixCommand { diff --git a/asus-nb-ctrl/src/ctrl_charge.rs b/asus-nb-ctrl/src/ctrl_charge.rs index 497754bb..5666e613 100644 --- a/asus-nb-ctrl/src/ctrl_charge.rs +++ b/asus-nb-ctrl/src/ctrl_charge.rs @@ -1,6 +1,7 @@ -use crate::{config::Config, error::RogError}; +use crate::{config::Config, error::RogError, GetSupported}; //use crate::dbus::DbusEvents; use log::{info, warn}; +use serde_derive::{Deserialize, Serialize}; use std::convert::TryInto; use std::fs::OpenOptions; use std::io::Write; @@ -11,8 +12,22 @@ use zbus::dbus_interface; static BAT_CHARGE_PATH: &str = "/sys/class/power_supply/BAT0/charge_control_end_threshold"; +#[derive(Serialize, Deserialize)] +pub struct ChargeSupportedFunctions { + pub charge_level_set: bool, +} + +impl GetSupported for CtrlCharge { + type A = ChargeSupportedFunctions; + + fn get_supported() -> Self::A { + ChargeSupportedFunctions { + charge_level_set: CtrlCharge::get_battery_path().is_ok(), + } + } +} + pub struct CtrlCharge { - path: &'static str, config: Arc>, } @@ -43,7 +58,7 @@ impl CtrlCharge { } #[dbus_interface(signal)] - pub fn notify_charge(&self, limit: u8) -> zbus::Result<()>; + pub fn notify_charge(&self, limit: u8) -> zbus::Result<()> {} } impl crate::ZbusAdd for CtrlCharge { @@ -62,7 +77,6 @@ impl crate::Reloadable for CtrlCharge { fn reload(&mut self) -> Result<(), RogError> { if let Ok(mut config) = self.config.try_lock() { config.read(); - info!("Reloaded battery charge limit"); self.set(config.bat_charge_limit, &mut config)?; } Ok(()) @@ -71,9 +85,8 @@ impl crate::Reloadable for CtrlCharge { impl CtrlCharge { pub fn new(config: Arc>) -> Result { - let path = CtrlCharge::get_battery_path()?; - info!("Device has battery charge threshold control"); - Ok(CtrlCharge { path, config }) + CtrlCharge::get_battery_path()?; + Ok(CtrlCharge { config }) } fn get_battery_path() -> Result<&'static str, RogError> { @@ -97,10 +110,10 @@ impl CtrlCharge { let mut file = OpenOptions::new() .write(true) - .open(self.path) - .map_err(|err| RogError::Path(self.path.into(), err))?; + .open(BAT_CHARGE_PATH) + .map_err(|err| RogError::Path(BAT_CHARGE_PATH.into(), err))?; file.write_all(limit.to_string().as_bytes()) - .map_err(|err| RogError::Write(self.path.into(), err))?; + .map_err(|err| RogError::Write(BAT_CHARGE_PATH.into(), err))?; info!("Battery charge limit: {}", limit); config.read(); diff --git a/asus-nb-ctrl/src/ctrl_fan_cpu.rs b/asus-nb-ctrl/src/ctrl_fan_cpu.rs index 820eb352..d7ff6f3a 100644 --- a/asus-nb-ctrl/src/ctrl_fan_cpu.rs +++ b/asus-nb-ctrl/src/ctrl_fan_cpu.rs @@ -1,6 +1,10 @@ -use crate::config::{Config, Profile}; +use crate::{ + config::{Config, Profile}, + GetSupported, +}; use asus_nb::profile::ProfileEvent; use log::{info, warn}; +use serde_derive::{Deserialize, Serialize}; use std::convert::TryInto; use std::fs::OpenOptions; use std::io::{Read, Write}; @@ -19,6 +23,25 @@ pub struct CtrlFanAndCPU { config: Arc>, } +#[derive(Serialize, Deserialize)] +pub struct FanCpuSupportedFunctions { + pub stock_fan_modes: bool, + pub min_max_freq: bool, + pub fan_curve_set: bool, +} + +impl GetSupported for CtrlFanAndCPU { + type A = FanCpuSupportedFunctions; + + fn get_supported() -> Self::A { + FanCpuSupportedFunctions { + stock_fan_modes: CtrlFanAndCPU::get_fan_path().is_ok(), + min_max_freq: intel_pstate::PState::new().is_ok(), + fan_curve_set: rog_fan_curve::Board::from_board_name().is_some(), + } + } +} + pub struct DbusFanAndCpu { inner: Arc>, } @@ -101,7 +124,7 @@ impl DbusFanAndCpu { } #[dbus_interface(signal)] - fn notify_profile(&self, profile: &str) -> zbus::Result<()>; + fn notify_profile(&self, profile: &str) -> zbus::Result<()> {} } impl crate::ZbusAdd for DbusFanAndCpu { diff --git a/ctrl-gfx/src/error.rs b/asus-nb-ctrl/src/ctrl_gfx/error.rs similarity index 100% rename from ctrl-gfx/src/error.rs rename to asus-nb-ctrl/src/ctrl_gfx/error.rs diff --git a/ctrl-gfx/src/ctrl_gfx.rs b/asus-nb-ctrl/src/ctrl_gfx/gfx.rs similarity index 88% rename from ctrl-gfx/src/ctrl_gfx.rs rename to asus-nb-ctrl/src/ctrl_gfx/gfx.rs index 342fc023..a9fad9b2 100644 --- a/ctrl-gfx/src/ctrl_gfx.rs +++ b/asus-nb-ctrl/src/ctrl_gfx/gfx.rs @@ -1,16 +1,19 @@ +use ctrl_gfx::error::GfxError; +use ctrl_gfx::*; +use ctrl_rog_bios::CtrlRogBios; use log::{error, info, warn}; -use std::error::Error; use std::io::Write; use std::iter::FromIterator; use std::path::Path; use std::process::Command; use std::str::FromStr; +use std::{error::Error, sync::Arc, sync::Mutex}; use sysfs_class::{PciDevice, SysClass}; +use system::{GraphicsDevice, Module, PciBus}; +use vendors::{GfxCtrlAction, GfxVendors}; use zbus::dbus_interface; -use crate::vendors::*; use crate::*; -use crate::{error::GfxError, system::*}; pub struct CtrlGraphics { bus: PciBus, @@ -20,6 +23,7 @@ pub struct CtrlGraphics { #[allow(dead_code)] other: Vec, initfs_cmd: Option, + config: Arc>, } trait Dbus { @@ -30,10 +34,8 @@ trait Dbus { fn notify_action(&self, action: &str) -> zbus::Result<()>; } -#[cfg(feature = "use-zbus")] use std::convert::TryInto; -#[cfg(feature = "use-zbus")] #[dbus_interface(name = "org.asuslinux.Daemon")] impl Dbus for CtrlGraphics { fn vendor(&self) -> String { @@ -58,14 +60,14 @@ impl Dbus for CtrlGraphics { } #[dbus_interface(signal)] - fn notify_gfx(&self, vendor: &str) -> zbus::Result<()>; + fn notify_gfx(&self, vendor: &str) -> zbus::Result<()> {} #[dbus_interface(signal)] - fn notify_action(&self, action: &str) -> zbus::Result<()>; + fn notify_action(&self, action: &str) -> zbus::Result<()> {} } impl CtrlGraphics { - pub fn new() -> std::io::Result { + pub fn new(config: Arc>) -> std::io::Result { let bus = PciBus::new()?; info!("Rescanning PCI bus"); @@ -138,13 +140,16 @@ impl CtrlGraphics { nvidia, other, initfs_cmd, + config, }) } - #[cfg(feature = "use-zbus")] pub fn add_to_server(self, server: &mut zbus::ObjectServer) { server - .at(&"/org/asuslinux/Gfx".try_into().unwrap(), self) + .at( + &"/org/asuslinux/Gfx".try_into().expect("Some fail here"), + self, + ) .map_err(|err| { warn!("CtrlGraphics: add_to_server {}", err); err @@ -158,10 +163,6 @@ impl CtrlGraphics { Ok(()) } - // fn can_switch(&self) -> bool { - // !self.nvidia.is_empty() && (!self.intel.is_empty() || !self.amd.is_empty()) - // } - fn get_prime_discrete() -> Result { let s = std::fs::read_to_string(PRIME_DISCRETE_PATH) .map_err(|err| GfxError::Read(PRIME_DISCRETE_PATH.into(), err))? @@ -220,10 +221,7 @@ impl CtrlGraphics { Ok(x) } - /// Write out config files if required, enable/disable relevant services, and update the ramdisk - pub fn set(&mut self, vendor: GfxVendors) -> Result { - //self.switchable_or_fail()?; - + pub fn set_gfx_config(vendor: GfxVendors) -> Result<(), GfxError> { let mode = if vendor == GfxVendors::Hybrid { "on-demand\n" } else if vendor == GfxVendors::Nvidia { @@ -236,10 +234,6 @@ impl CtrlGraphics { info!("Setting {} to {}", PRIME_DISCRETE_PATH, mode); Self::set_prime_discrete(mode)?; - // Switching from hybrid to/from nvidia shouldn't require a ramdisk update - // or a reboot. - let no_reboot = Self::is_switching_prime_modes(&vendor)?; - { info!("Writing {}", MODPROBE_PATH); @@ -307,6 +301,32 @@ impl CtrlGraphics { status ); } + Ok(()) + } + + /// Write out config files if required, enable/disable relevant services, and update the ramdisk + pub fn set(&mut self, vendor: GfxVendors) -> Result { + if CtrlRogBios::has_dedicated_gfx_toggle() { + if let Ok(config) = self.config.clone().try_lock() { + // Switch to dedicated if config says to do so + if config.gfx_nv_mode_is_dedicated && vendor == GfxVendors::Nvidia { + CtrlRogBios::set_gfx_mode(true) + .unwrap_or_else(|err| warn!("Gfx controller: {}", err)); + } else if let Ok(ded) = CtrlRogBios::get_gfx_mode() { + // otherwise if switching to non-Nvidia mode turn off dedicated mode + if ded == 1 && vendor != GfxVendors::Nvidia { + CtrlRogBios::set_gfx_mode(false) + .unwrap_or_else(|err| warn!("Gfx controller: {}", err)); + } + } + } + } + + // Switching from hybrid to/from nvidia shouldn't require a ramdisk update + // or a reboot. + let no_reboot = Self::is_switching_prime_modes(&vendor)?; + + Self::set_gfx_config(vendor)?; let mut required_action = GfxCtrlAction::None; if !no_reboot { @@ -329,12 +349,6 @@ impl CtrlGraphics { Ok(required_action.into()) } - // pub fn get_power(&self) -> Option { - // if self.can_switch() { - // return Some(self.nvidia.iter().any(GraphicsDevice::exists)); - // } - // None - // } pub fn get_runtime_status() -> Result { const PATH: &str = "/sys/bus/pci/devices/0000:01:00.0/power/runtime_status"; let buf = std::fs::read_to_string(PATH).map_err(|err| GfxError::Read(PATH.into(), err))?; @@ -342,8 +356,6 @@ impl CtrlGraphics { } fn set_power(&self, power: bool) -> Result<(), GfxError> { - // self.switchable_or_fail()?; - if power { info!("Enabling graphics power"); self.bus diff --git a/ctrl-gfx/src/lib.rs b/asus-nb-ctrl/src/ctrl_gfx/mod.rs similarity index 98% rename from ctrl-gfx/src/lib.rs rename to asus-nb-ctrl/src/ctrl_gfx/mod.rs index a33685c3..9d065cf2 100644 --- a/ctrl-gfx/src/lib.rs +++ b/asus-nb-ctrl/src/ctrl_gfx/mod.rs @@ -2,7 +2,7 @@ pub mod vendors; pub mod error; -pub mod ctrl_gfx; +pub mod gfx; pub mod system; diff --git a/ctrl-gfx/src/system.rs b/asus-nb-ctrl/src/ctrl_gfx/system.rs similarity index 100% rename from ctrl-gfx/src/system.rs rename to asus-nb-ctrl/src/ctrl_gfx/system.rs diff --git a/ctrl-gfx/src/vendors.rs b/asus-nb-ctrl/src/ctrl_gfx/vendors.rs similarity index 98% rename from ctrl-gfx/src/vendors.rs rename to asus-nb-ctrl/src/ctrl_gfx/vendors.rs index 2d385fd6..c0e90a2d 100644 --- a/ctrl-gfx/src/vendors.rs +++ b/asus-nb-ctrl/src/ctrl_gfx/vendors.rs @@ -6,9 +6,10 @@ pub enum GfxVendors { Hybrid, } -use crate::error::GfxError; use std::str::FromStr; +use super::error::GfxError; + impl FromStr for GfxVendors { type Err = GfxError; diff --git a/asus-nb-ctrl/src/ctrl_leds.rs b/asus-nb-ctrl/src/ctrl_leds.rs index 1f900b76..07e0139e 100644 --- a/asus-nb-ctrl/src/ctrl_leds.rs +++ b/asus-nb-ctrl/src/ctrl_leds.rs @@ -4,8 +4,17 @@ static LED_SET: [u8; 17] = [0x5d, 0xb5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 static KBD_BRIGHT_PATH: &str = "/sys/class/leds/asus::kbd_backlight/brightness"; -use crate::{config::Config, error::RogError, laptops::HELP_ADDRESS}; -use asus_nb::{aura_brightness_bytes, aura_modes::AuraModes, fancy::KeyColourArray, LED_MSG_LEN}; +use crate::{ + config::Config, + error::RogError, + laptops::{match_laptop, HELP_ADDRESS}, +}; +use asus_nb::{ + aura_brightness_bytes, + aura_modes::{AuraModes, PER_KEY}, + fancy::KeyColourArray, + LED_MSG_LEN, +}; use log::{info, warn}; use std::fs::OpenOptions; use std::io::{Read, Write}; @@ -14,6 +23,44 @@ use std::sync::Mutex; use std::{convert::TryInto, path::Path}; use zbus::dbus_interface; +use crate::GetSupported; + +use serde_derive::{Deserialize, Serialize}; +#[derive(Serialize, Deserialize)] +pub struct LedSupportedFunctions { + pub brightness_set: bool, + pub stock_led_modes: Option>, + pub per_key_led_mode: bool, +} + +impl GetSupported for CtrlKbdBacklight { + type A = LedSupportedFunctions; + + fn get_supported() -> Self::A { + // let mode = <&str>::from(&::from(*mode)); + let mut stock_led_modes = None; + let mut per_key_led_mode = false; + if let Some(laptop) = match_laptop() { + let modes = laptop.supported_modes().to_vec(); + if modes.contains(&PER_KEY) { + per_key_led_mode = true; + let modes = modes + .iter() + .filter(|x| **x != PER_KEY) + .map(|x| *x) + .collect(); + stock_led_modes = Some(modes); + } + } + + LedSupportedFunctions { + brightness_set: CtrlKbdBacklight::get_kbd_bright_path().is_ok(), + stock_led_modes, + per_key_led_mode, + } + } +} + pub struct CtrlKbdBacklight { led_node: Option, #[allow(dead_code)] diff --git a/asus-nb-ctrl/src/ctrl_rog_bios.rs b/asus-nb-ctrl/src/ctrl_rog_bios.rs new file mode 100644 index 00000000..57884475 --- /dev/null +++ b/asus-nb-ctrl/src/ctrl_rog_bios.rs @@ -0,0 +1,261 @@ +use crate::{ + config::Config, + ctrl_gfx::{gfx::CtrlGraphics, vendors::GfxVendors}, + error::RogError, + GetSupported, +}; +//use crate::dbus::DbusEvents; +use log::{info, warn}; +use serde_derive::{Deserialize, Serialize}; +use std::convert::TryInto; +use std::fs::OpenOptions; +use std::io::{Read, Write}; +use std::path::Path; +use std::sync::Arc; +use std::sync::Mutex; +use zbus::dbus_interface; + +static ASUS_SWITCH_GRAPHIC_MODE: &str = + "/sys/firmware/efi/efivars/AsusSwitchGraphicMode-607005d5-3f75-4b2e-98f0-85ba66797a3e"; +static ASUS_POST_LOGO_SOUND: &str = + "/sys/firmware/efi/efivars/AsusPostLogoSound-607005d5-3f75-4b2e-98f0-85ba66797a3e"; + +pub struct CtrlRogBios { + config: Arc>, +} + +#[derive(Serialize, Deserialize)] +pub struct RogBiosSupportedFunctions { + pub post_sound_toggle: bool, + pub dedicated_gfx_toggle: bool, +} + +impl GetSupported for CtrlRogBios { + type A = RogBiosSupportedFunctions; + + fn get_supported() -> Self::A { + RogBiosSupportedFunctions { + post_sound_toggle: CtrlRogBios::check_path_exists(ASUS_POST_LOGO_SOUND).is_ok(), + dedicated_gfx_toggle: CtrlRogBios::check_path_exists(ASUS_SWITCH_GRAPHIC_MODE).is_ok(), + } + } +} + +#[dbus_interface(name = "org.asuslinux.Daemon")] +impl CtrlRogBios { + pub fn set_dedicated_graphic_mode(&mut self, dedicated: bool) { + Self::set_gfx_mode(dedicated) + .map_err(|err| { + warn!("CtrlRogBios: set_asus_switch_graphic_mode {}", err); + err + }) + .ok(); + self.notify_dedicated_graphic_mode(dedicated) + .map_err(|err| { + warn!("CtrlRogBios: notify_asus_switch_graphic_mode {}", err); + err + }) + .ok(); + } + + pub fn dedicated_graphic_mode(&self) -> i8 { + Self::get_gfx_mode() + .map_err(|err| { + warn!("CtrlRogBios: get_gfx_mode {}", err); + err + }) + .unwrap_or(-1) + } + + #[dbus_interface(signal)] + pub fn notify_dedicated_graphic_mode(&self, dedicated: bool) -> zbus::Result<()> {} + + // // // // // // // // // // + + pub fn set_post_boot_sound(&mut self, on: bool) { + Self::set_boot_sound(on) + .map_err(|err| { + warn!("CtrlRogBios: set_post_boot_sound {}", err); + err + }) + .ok(); + self.notify_post_boot_sound(on) + .map_err(|err| { + warn!("CtrlRogBios: notify_post_boot_sound {}", err); + err + }) + .ok(); + } + + pub fn post_boot_sound(&self) -> i8 { + Self::get_boot_sound() + .map_err(|err| { + warn!("CtrlRogBios: get_boot_sound {}", err); + err + }) + .unwrap_or(-1) + } + + #[dbus_interface(signal)] + pub fn notify_post_boot_sound(&self, dedicated: bool) -> zbus::Result<()> {} +} + +impl crate::ZbusAdd for CtrlRogBios { + fn add_to_server(self, server: &mut zbus::ObjectServer) { + server + .at(&"/org/asuslinux/RogBios".try_into().unwrap(), self) + .map_err(|err| { + warn!("CtrlRogBios: add_to_server {}", err); + err + }) + .ok(); + } +} + +impl crate::Reloadable for CtrlRogBios { + fn reload(&mut self) -> Result<(), RogError> { + Ok(()) + } +} + +impl CtrlRogBios { + pub fn new(config: Arc>) -> Result { + match CtrlRogBios::check_path_exists(ASUS_SWITCH_GRAPHIC_MODE) { + Ok(_) => { + CtrlRogBios::set_path_mutable(ASUS_SWITCH_GRAPHIC_MODE)?; + } + Err(err) => { + info!("ROG Switchable Graphics (bios) not detected: {}", err); + } + } + + match CtrlRogBios::check_path_exists(ASUS_POST_LOGO_SOUND) { + Ok(_) => { + CtrlRogBios::set_path_mutable(ASUS_POST_LOGO_SOUND)?; + } + Err(err) => { + info!("ROG boot sound toggle (bios) not detected: {}", err); + } + } + + Ok(CtrlRogBios { config }) + } + + fn set_path_mutable(path: &str) -> Result<(), RogError> { + use std::process::Command; + + let output = Command::new("/usr/bin/chattr") + .arg("-i") + .arg(path) + .output() + .map_err(|err| RogError::Path(path.into(), err))?; + info!("Set {} writeable: status: {}", path, output.status); + Ok(()) + } + + fn check_path_exists(path: &str) -> Result<(), RogError> { + if Path::new(path).exists() { + Ok(()) + } else { + Err(RogError::MissingFunction(path.into())) + } + } + + pub fn has_dedicated_gfx_toggle() -> bool { + if CtrlRogBios::check_path_exists(ASUS_SWITCH_GRAPHIC_MODE).is_ok() { + return true; + } + false + } + + pub fn get_gfx_mode() -> Result { + let path = ASUS_SWITCH_GRAPHIC_MODE; + let mut file = OpenOptions::new() + .read(true) + .open(path) + .map_err(|err| RogError::Path(path.into(), err))?; + + let mut data = Vec::new(); + file.read_to_end(&mut data) + .map_err(|err| RogError::Read(path.into(), err))?; + + let idx = data.len() - 1; + Ok(data[idx] as i8) + } + + pub(super) fn set_gfx_mode(dedicated: bool) -> Result<(), RogError> { + let path = ASUS_SWITCH_GRAPHIC_MODE; + let mut file = OpenOptions::new() + .read(true) + .write(true) + .open(path) + .map_err(|err| RogError::Path(path.into(), err))?; + + let mut data = Vec::new(); + file.read_to_end(&mut data).unwrap(); + + let idx = data.len() - 1; + if dedicated { + data[idx] = 1; + info!("Set system-level graphics mode: Dedicated Nvidia"); + } else { + data[idx] = 0; + info!("Set system-level graphics mode: Optimus"); + } + file.write_all(&data) + .map_err(|err| RogError::Path(path.into(), err))?; + + if let Ok(ded) = CtrlRogBios::get_gfx_mode() { + if let Ok(vendor) = CtrlGraphics::get_vendor() { + if ded == 1 && vendor != "nvidia" { + warn!("Dedicated GFX toggle is on but driver mode is not nvidia \nSetting to nvidia driver mode"); + CtrlGraphics::set_gfx_config(GfxVendors::Nvidia) + .unwrap_or_else(|err| warn!("Gfx controller: {}", err)); + } + } + } + + Ok(()) + } + + pub fn get_boot_sound() -> Result { + let path = ASUS_POST_LOGO_SOUND; + let mut file = OpenOptions::new() + .read(true) + .open(path) + .map_err(|err| RogError::Path(path.into(), err))?; + + let mut data = Vec::new(); + file.read_to_end(&mut data) + .map_err(|err| RogError::Read(path.into(), err))?; + + let idx = data.len() - 1; + Ok(data[idx] as i8) + } + + pub(super) fn set_boot_sound(on: bool) -> Result<(), RogError> { + let path = ASUS_POST_LOGO_SOUND; + let mut file = OpenOptions::new() + .read(true) + .write(true) + .open(path) + .map_err(|err| RogError::Path(path.into(), err))?; + + let mut data = Vec::new(); + file.read_to_end(&mut data) + .map_err(|err| RogError::Read(path.into(), err))?; + + let idx = data.len() - 1; + if on { + data[idx] = 1; + info!("Set boot POST sound on"); + } else { + data[idx] = 0; + info!("Set boot POST sound off"); + } + file.write_all(&data) + .map_err(|err| RogError::Path(path.into(), err))?; + + Ok(()) + } +} diff --git a/asus-nb-ctrl/src/daemon.rs b/asus-nb-ctrl/src/daemon.rs index 077b8d7b..bbb5eace 100644 --- a/asus-nb-ctrl/src/daemon.rs +++ b/asus-nb-ctrl/src/daemon.rs @@ -1,10 +1,14 @@ -use ctrl_gfx::ctrl_gfx::CtrlGraphics; -use daemon::config::Config; -use daemon::ctrl_anime::CtrlAnimeDisplay; use daemon::ctrl_charge::CtrlCharge; use daemon::ctrl_fan_cpu::{CtrlFanAndCPU, DbusFanAndCpu}; use daemon::ctrl_leds::{CtrlKbdBacklight, DbusKbdBacklight}; use daemon::laptops::match_laptop; +use daemon::{ + config::Config, laptops::print_board_info, supported::SupportedFunctions, GetSupported, +}; +use daemon::{ + ctrl_anime::CtrlAnimeDisplay, + ctrl_gfx::{gfx::CtrlGraphics, vendors::GfxVendors}, +}; use asus_nb::DBUS_NAME; use daemon::{CtrlTask, Reloadable, ZbusAdd}; @@ -15,6 +19,7 @@ use std::io::Write; use std::sync::Arc; use std::sync::Mutex; +use daemon::ctrl_rog_bios::CtrlRogBios; use std::convert::Into; use std::convert::TryInto; use zbus::fdo; @@ -40,14 +45,16 @@ pub fn main() -> Result<(), Box> { // - to maintain constant times of 1ms, per-key colours should use // the effect endpoint so that the complete colour block is written // as fast as 1ms per row of the matrix inside it. (10ms total time) -// -// DBUS processing takes 6ms if not tokiod fn start_daemon() -> Result<(), Box> { + let supported = SupportedFunctions::get_supported(); + print_board_info(); + println!("{}", serde_json::to_string_pretty(&supported).unwrap()); + let laptop = match_laptop(); let config = if let Some(laptop) = laptop.as_ref() { - Config::default().load(laptop.supported_modes()) + Config::load(laptop.supported_modes()) } else { - Config::default().load(&[]) + Config::load(&[]) }; let connection = Connection::new_system()?; @@ -55,9 +62,24 @@ fn start_daemon() -> Result<(), Box> { .request_name(DBUS_NAME, fdo::RequestNameFlags::ReplaceExisting.into())?; let mut object_server = zbus::ObjectServer::new(&connection); + supported.add_to_server(&mut object_server); + let enable_gfx_switching = config.gfx_managed; let config = Arc::new(Mutex::new(config)); + match CtrlRogBios::new(config.clone()) { + Ok(mut ctrl) => { + // Do a reload of any settings + ctrl.reload() + .unwrap_or_else(|err| warn!("Battery charge limit: {}", err)); + // Then register to dbus server + ctrl.add_to_server(&mut object_server); + } + Err(err) => { + error!("rog_bios_control: {}", err); + } + } + match CtrlCharge::new(config.clone()) { Ok(mut ctrl) => { // Do a reload of any settings @@ -81,10 +103,25 @@ fn start_daemon() -> Result<(), Box> { } if enable_gfx_switching { - match CtrlGraphics::new() { + match CtrlGraphics::new(config.clone()) { Ok(mut ctrl) => { - ctrl.reload() - .unwrap_or_else(|err| warn!("Gfx controller: {}", err)); + // Need to check if a laptop has the dedicated gfx switch + if CtrlRogBios::has_dedicated_gfx_toggle() { + if let Ok(ded) = CtrlRogBios::get_gfx_mode() { + if let Ok(vendor) = CtrlGraphics::get_vendor() { + if ded == 1 && vendor != "nvidia" { + error!("Dedicated GFX toggle is on but driver mode is not nvidia \nSetting to nvidia driver mode"); + error!("You must reboot to enable Nvidia driver"); + ctrl.set(GfxVendors::Nvidia)?; + } else if ded == 0 { + info!("Dedicated GFX toggle is off"); + } + } + } + } else { + ctrl.reload() + .unwrap_or_else(|err| warn!("Gfx controller: {}", err)); + } ctrl.add_to_server(&mut object_server); } Err(err) => { diff --git a/asus-nb-ctrl/src/error.rs b/asus-nb-ctrl/src/error.rs index 6bdaa8f3..b56c527c 100644 --- a/asus-nb-ctrl/src/error.rs +++ b/asus-nb-ctrl/src/error.rs @@ -20,6 +20,7 @@ pub enum RogError { DoTask(String), MissingFunction(String), MissingLedBrightNode(String, std::io::Error), + ReloadFail(String), } impl fmt::Display for RogError { @@ -41,6 +42,7 @@ impl fmt::Display for RogError { RogError::DoTask(deets) => write!(f, "Task error: {}", deets), RogError::MissingFunction(deets) => write!(f, "Missing functionality: {}", deets), RogError::MissingLedBrightNode(path, error) => write!(f, "Led node at {} is missing, please check you have the required patch or dkms module installed: {}", path, error), + RogError::ReloadFail(deets) => write!(f, "Task error: {}", deets), } } } diff --git a/asus-nb-ctrl/src/laptops.rs b/asus-nb-ctrl/src/laptops.rs index d3c7f859..fe23307e 100644 --- a/asus-nb-ctrl/src/laptops.rs +++ b/asus-nb-ctrl/src/laptops.rs @@ -27,13 +27,12 @@ impl LaptopBase { } pub fn match_laptop() -> Option { - for device in rusb::devices().unwrap().iter() { - let device_desc = device.device_descriptor().unwrap(); + for device in rusb::devices().expect("Failed here").iter() { + let device_desc = device.device_descriptor().expect("Failed there"); if device_desc.vendor_id() == 0x0b05 { match device_desc.product_id() { 0x1866 => { let laptop = select_1866_device("1866".to_owned()); - print_modes(&laptop.supported_modes); return Some(laptop); } 0x1869 => return Some(select_1866_device("1869".to_owned())), @@ -61,10 +60,6 @@ fn select_1866_device(prod: String) -> LaptopBase { let dmi = sysfs_class::DmiId::default(); let board_name = dmi.board_name().expect("Could not get board_name"); let prod_family = dmi.product_family().expect("Could not get product_family"); - let prod_name = dmi.product_name().expect("Could not get product_name"); - - info!("Product name: {}", prod_name.trim()); - info!("Board name: {}", board_name.trim()); let mut laptop = LaptopBase { usb_product: prod, @@ -81,7 +76,18 @@ fn select_1866_device(prod: String) -> LaptopBase { laptop } -fn print_modes(supported_modes: &[u8]) { +pub fn print_board_info() { + let dmi = sysfs_class::DmiId::default(); + let board_name = dmi.board_name().expect("Could not get board_name"); + let prod_name = dmi.product_name().expect("Could not get product_name"); + let prod_family = dmi.product_family().expect("Could not get product_family"); + + info!("Product name: {}", prod_name.trim()); + info!("Product family: {}", prod_family.trim()); + info!("Board name: {}", board_name.trim()); +} + +pub fn print_modes(supported_modes: &[u8]) { if !supported_modes.is_empty() { info!("Supported Keyboard LED modes are:"); for mode in supported_modes { diff --git a/asus-nb-ctrl/src/lib.rs b/asus-nb-ctrl/src/lib.rs index 651c32a0..0ff59f1c 100644 --- a/asus-nb-ctrl/src/lib.rs +++ b/asus-nb-ctrl/src/lib.rs @@ -8,11 +8,17 @@ pub mod ctrl_charge; /// pub mod ctrl_fan_cpu; /// -pub mod ctrl_leds; +pub mod ctrl_gfx; /// +pub mod ctrl_leds; +/// Control ASUS bios function such as boot sound, Optimus/Dedicated gfx mode +pub mod ctrl_rog_bios; /// Laptop matching to determine capabilities pub mod laptops; +/// Fetch all supported functions for the laptop +pub mod supported; + mod error; use crate::error::RogError; @@ -38,3 +44,9 @@ pub trait CtrlTaskComplex { fn do_task(&mut self, config: &mut Config, event: Self::A); } + +pub trait GetSupported { + type A; + + fn get_supported() -> Self::A; +} diff --git a/asus-nb-ctrl/src/main.rs b/asus-nb-ctrl/src/main.rs index b5bb0c1f..dfc3dbb0 100644 --- a/asus-nb-ctrl/src/main.rs +++ b/asus-nb-ctrl/src/main.rs @@ -4,8 +4,7 @@ use asus_nb::{ core_dbus::AuraDbusClient, profile::{ProfileCommand, ProfileEvent}, }; -use ctrl_gfx::vendors::GfxVendors; -use daemon::ctrl_fan_cpu::FanLevel; +use daemon::{ctrl_fan_cpu::FanLevel, ctrl_gfx::vendors::GfxVendors}; use gumdrop::{Opt, Options}; use log::LevelFilter; use std::{env::args, io::Write, process::Command}; @@ -18,11 +17,13 @@ struct CLIStart { help: bool, #[options(help = "show program version number")] version: bool, - #[options(meta = "VAL", help = "")] + #[options(help = "show supported functions of this laptop")] + show_supported: bool, + #[options(meta = "", help = "")] kbd_bright: Option, - #[options(meta = "PWR", help = "")] + #[options(meta = "", help = "")] pwr_profile: Option, - #[options(meta = "CHRG", help = "<20-100>")] + #[options(meta = "", help = "<20-100>")] chg_limit: Option, #[options(command)] command: Option, @@ -38,6 +39,8 @@ enum CliCommand { Graphics(GraphicsCommand), #[options(name = "anime", help = "Manage AniMe Matrix")] AniMe(AniMeCommand), + #[options(help = "Change bios settings")] + Bios(BiosCommand), } #[derive(Options)] @@ -56,7 +59,10 @@ struct LedModeCommand { struct GraphicsCommand { #[options(help = "print help message")] help: bool, - #[options(help = "Set graphics mode: ")] + #[options( + meta = "", + help = "Set graphics mode: " + )] mode: Option, #[options(help = "Get the current mode")] get: bool, @@ -70,14 +76,31 @@ struct GraphicsCommand { struct AniMeCommand { #[options(help = "print help message")] help: bool, - #[options(help = "turn on/off the panel (accept/reject write requests)")] + #[options( + meta = "", + help = "turn on/off the panel (accept/reject write requests)" + )] turn: Option, - #[options(help = "turn on/off the panel at boot (with Asus effect)")] + #[options(meta = "", help = "turn on/off the panel at boot (with Asus effect)")] boot: Option, #[options(command)] command: Option, } +#[derive(Options, Debug)] +struct BiosCommand { + #[options(help = "print help message")] + help: bool, + #[options(meta = "", no_long, help = "toggle bios POST sound")] + post_sound_set: Option, + #[options(no_long, help = "read bios POST sound")] + post_sound_get: bool, + #[options(meta = "", no_long, help = "toggle GPU to/from dedicated mode")] + dedicated_gfx_set: Option, + #[options(no_long, help = "get GPU mode")] + dedicated_gfx_get: bool, +} + fn main() -> Result<(), Box> { let mut logger = env_logger::Builder::new(); logger @@ -117,78 +140,157 @@ fn main() -> Result<(), Box> { println!("Version: {}", daemon::VERSION); } - let writer = AuraDbusClient::new()?; - let anime_writer = AniMeDbusWriter::new()?; + let dbus_client = AuraDbusClient::new()?; + let anime_dbus_client = AniMeDbusWriter::new()?; match parsed.command { Some(CliCommand::LedMode(mode)) => { + if (mode.command.is_none() && !mode.prev_mode && !mode.next_mode) || mode.help { + println!("Missing arg or command\n\n{}", mode.self_usage()); + if let Some(lst) = mode.self_command_list() { + println!("\n{}", lst); + } + } if mode.next_mode && mode.prev_mode { println!("Please specify either next or previous") } if mode.next_mode { - writer.next_keyboard_led_mode()?; + dbus_client.next_keyboard_led_mode()?; } else if mode.prev_mode { - writer.prev_keyboard_led_mode()?; + dbus_client.prev_keyboard_led_mode()?; } else if let Some(command) = mode.command { - writer.write_builtin_mode(&command.into())? + dbus_client.write_builtin_mode(&command.into())? } } - Some(CliCommand::Profile(command)) => { - if command.next { - writer.next_fan_profile()?; + Some(CliCommand::Profile(cmd)) => { + if (!cmd.next + && !cmd.create + && cmd.curve.is_none() + && cmd.max_percentage.is_none() + && cmd.min_percentage.is_none() + && cmd.preset.is_none() + && cmd.profile.is_none() + && cmd.turbo.is_none()) + || cmd.help + { + println!("Missing arg or command\n\n{}", cmd.self_usage()); + if let Some(lst) = cmd.self_command_list() { + println!("\n{}", lst); + } + } + if cmd.next { + dbus_client.next_fan_profile()?; } else { - writer.write_profile_command(&ProfileEvent::Cli(command))? + dbus_client.write_profile_command(&ProfileEvent::Cli(cmd))? } } - Some(CliCommand::Graphics(command)) => do_gfx(command, &writer)?, - Some(CliCommand::AniMe(anime)) => { - if let Some(anime_turn) = anime.turn { - anime_writer.turn_on_off(anime_turn.into())? + Some(CliCommand::Graphics(cmd)) => do_gfx(cmd, &dbus_client)?, + Some(CliCommand::AniMe(cmd)) => { + if (cmd.command.is_none() && cmd.boot.is_none() && cmd.turn.is_none()) || cmd.help { + println!("Missing arg or command\n\n{}", cmd.self_usage()); + if let Some(lst) = cmd.self_command_list() { + println!("\n{}", lst); + } } - if let Some(anime_boot) = anime.boot { - anime_writer.turn_boot_on_off(anime_boot.into())? + if let Some(anime_turn) = cmd.turn { + anime_dbus_client.turn_on_off(anime_turn.into())? } - if let Some(action) = anime.command { + if let Some(anime_boot) = cmd.boot { + anime_dbus_client.turn_boot_on_off(anime_boot.into())? + } + if let Some(action) = cmd.command { match action { AniMeActions::Leds(anime_leds) => { let led_brightness = anime_leds.led_brightness(); - anime_writer.set_leds_brightness(led_brightness)?; + anime_dbus_client.set_leds_brightness(led_brightness)?; } } } } - None => (), + Some(CliCommand::Bios(cmd)) => { + if (cmd.dedicated_gfx_set.is_none() + && !cmd.dedicated_gfx_get + && cmd.post_sound_set.is_none() + && !cmd.post_sound_get) + || cmd.help + { + println!("Missing arg or command\n\n{}", cmd.self_usage()); + if let Some(lst) = cmd.self_command_list() { + println!("\n{}", lst); + } + } + + if let Some(opt) = cmd.post_sound_set { + dbus_client.set_bios_post_sound(opt)?; + } + if cmd.post_sound_get { + let res = if dbus_client.get_bios_post_sound()? == 1 { + true + } else { + false + }; + println!("Bios POST sound on: {}", res); + } + if let Some(opt) = cmd.dedicated_gfx_set { + dbus_client.set_bios_dedicated_gfx(opt)?; + } + if cmd.dedicated_gfx_get { + let res = if dbus_client.get_bios_dedicated_gfx()? == 1 { + true + } else { + false + }; + println!("Bios dedicated GPU on: {}", res); + } + } + None => { + if (!parsed.show_supported + && parsed.kbd_bright.is_none() + && parsed.pwr_profile.is_none() + && parsed.chg_limit.is_none()) + || parsed.help + { + println!("{}", CLIStart::usage()); + println!(); + println!("{}", CLIStart::command_list().unwrap()); + } + } } if let Some(brightness) = parsed.kbd_bright { match brightness.level() { None => { - let level = writer.get_led_brightness()?; + let level = dbus_client.get_led_brightness()?; println!("Current keyboard led brightness: {}", level.to_string()); } - Some(level) => writer.write_brightness(level)?, + Some(level) => dbus_client.write_brightness(level)?, } } + if parsed.show_supported { + let dat = dbus_client.get_supported_functions()?; + println!("Supported laptop functions:\n{}", dat.to_string()); + } + if let Some(fan_level) = parsed.pwr_profile { - writer.write_fan_mode(fan_level.into())?; + dbus_client.write_fan_mode(fan_level.into())?; } if let Some(chg_limit) = parsed.chg_limit { - writer.write_charge_limit(chg_limit)?; + dbus_client.write_charge_limit(chg_limit)?; } Ok(()) } fn do_gfx( command: GraphicsCommand, - writer: &AuraDbusClient, + dbus_client: &AuraDbusClient, ) -> Result<(), Box> { if let Some(mode) = command.mode { println!("Updating settings, please wait..."); println!("If this takes longer than 30s, ctrl+c then check `journalctl -b -u asusd`"); - writer.write_gfx_mode(mode)?; - let res = writer.wait_gfx_changed()?; + dbus_client.write_gfx_mode(<&str>::from(&mode).into())?; + let res = dbus_client.wait_gfx_changed()?; match res.as_str() { "reboot" => { println!( @@ -222,11 +324,11 @@ fn do_gfx( std::process::exit(-1) } if command.get { - let res = writer.get_gfx_mode()?; + let res = dbus_client.get_gfx_mode()?; println!("Current graphics mode: {}", res); } if command.pow { - let res = writer.get_gfx_pwr()?; + let res = dbus_client.get_gfx_pwr()?; if res.contains("active") { println!("Current power status: {}", Red.paint(&format!("{}", res))); } else { diff --git a/asus-nb-ctrl/src/supported.rs b/asus-nb-ctrl/src/supported.rs new file mode 100644 index 00000000..9f2b6601 --- /dev/null +++ b/asus-nb-ctrl/src/supported.rs @@ -0,0 +1,56 @@ +use std::convert::TryInto; + +use log::warn; +use serde_derive::{Deserialize, Serialize}; +use zbus::dbus_interface; + +use crate::{ + ctrl_anime::{AnimeSupportedFunctions, CtrlAnimeDisplay}, + ctrl_charge::{ChargeSupportedFunctions, CtrlCharge}, + ctrl_fan_cpu::{CtrlFanAndCPU, FanCpuSupportedFunctions}, + ctrl_leds::{CtrlKbdBacklight, LedSupportedFunctions}, + ctrl_rog_bios::{CtrlRogBios, RogBiosSupportedFunctions}, + GetSupported, +}; + +#[derive(Serialize, Deserialize)] +pub struct SupportedFunctions { + anime_ctrl: AnimeSupportedFunctions, + charge_ctrl: ChargeSupportedFunctions, + fan_cpu_ctrl: FanCpuSupportedFunctions, + keyboard_led: LedSupportedFunctions, + rog_bios_ctrl: RogBiosSupportedFunctions, +} + +#[dbus_interface(name = "org.asuslinux.Daemon")] +impl SupportedFunctions { + fn supported_functions(&self) -> String { + serde_json::to_string_pretty(self).unwrap() + } +} + +impl crate::ZbusAdd for SupportedFunctions { + fn add_to_server(self, server: &mut zbus::ObjectServer) { + server + .at(&"/org/asuslinux/Supported".try_into().unwrap(), self) + .map_err(|err| { + warn!("SupportedFunctions: add_to_server {}", err); + err + }) + .ok(); + } +} + +impl GetSupported for SupportedFunctions { + type A = SupportedFunctions; + + fn get_supported() -> Self::A { + SupportedFunctions { + keyboard_led: CtrlKbdBacklight::get_supported(), + anime_ctrl: CtrlAnimeDisplay::get_supported(), + charge_ctrl: CtrlCharge::get_supported(), + fan_cpu_ctrl: CtrlFanAndCPU::get_supported(), + rog_bios_ctrl: CtrlRogBios::get_supported(), + } + } +} diff --git a/asus-nb/Cargo.toml b/asus-nb/Cargo.toml index c534fe4b..3a25dbb4 100644 --- a/asus-nb/Cargo.toml +++ b/asus-nb/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "asus-nb" -version = "2.1.2" +version = "2.2.0" license = "MPL-2.0" readme = "README.md" authors = ["Luke "] @@ -19,7 +19,6 @@ yansi-term = "^0.1" rog_fan_curve = { version = "0.1", features = ["serde"] } zbus = "^1.8.0" zvariant = "^2.4.0" -ctrl-gfx = { path = "../ctrl-gfx" } [dev-dependencies] tinybmp = "^0.2.3" \ No newline at end of file diff --git a/asus-nb/src/core_dbus.rs b/asus-nb/src/core_dbus.rs index a00d2946..a81e12ee 100644 --- a/asus-nb/src/core_dbus.rs +++ b/asus-nb/src/core_dbus.rs @@ -2,7 +2,6 @@ use super::*; use crate::cli_options::LedBrightness; use crate::fancy::KeyColourArray; use crate::profile::ProfileEvent; -use ctrl_gfx::vendors::GfxVendors; use dbus::{blocking::Connection, Message}; use std::error::Error; use std::sync::{ @@ -24,6 +23,8 @@ use crate::dbus_ledmode::{ use crate::dbus_profile::{ OrgAsuslinuxDaemon as OrgAsuslinuxDaemonProfile, OrgAsuslinuxDaemonNotifyProfile, }; +use crate::dbus_rogbios::OrgAsuslinuxDaemon as OrgAsuslinuxDaemonRogBios; +use crate::dbus_supported::OrgAsuslinuxDaemon as OrgAsuslinuxDaemonSupported; // Signals separated out pub struct CtrlSignals { @@ -278,13 +279,13 @@ impl AuraDbusClient { } #[inline] - pub fn write_gfx_mode(&self, vendor: GfxVendors) -> Result<(), Box> { + pub fn write_gfx_mode(&self, vendor: String) -> Result<(), Box> { let proxy = self.connection.with_proxy( "org.asuslinux.Daemon", "/org/asuslinux/Gfx", Duration::from_secs(30), ); - proxy.set_vendor(<&str>::from(&vendor))?; + proxy.set_vendor(&vendor)?; Ok(()) } @@ -358,4 +359,60 @@ impl AuraDbusClient { self.write_keyboard_leds(&AuraModes::LedBrightness(level))?; Ok(()) } + + // + #[inline] + pub fn get_bios_dedicated_gfx(&self) -> Result> { + let proxy = self.connection.with_proxy( + "org.asuslinux.Daemon", + "/org/asuslinux/RogBios", + Duration::from_secs(2), + ); + let x = proxy.dedicated_graphic_mode()?; + Ok(x) + } + + #[inline] + pub fn set_bios_dedicated_gfx(&self, on: bool) -> Result<(), Box> { + let proxy = self.connection.with_proxy( + "org.asuslinux.Daemon", + "/org/asuslinux/RogBios", + Duration::from_secs(2), + ); + proxy.set_dedicated_graphic_mode(::from(on))?; + Ok(()) + } + + #[inline] + pub fn get_bios_post_sound(&self) -> Result> { + let proxy = self.connection.with_proxy( + "org.asuslinux.Daemon", + "/org/asuslinux/RogBios", + Duration::from_secs(2), + ); + let x = proxy.post_boot_sound()?; + Ok(x) + } + + #[inline] + pub fn set_bios_post_sound(&self, on: bool) -> Result<(), Box> { + let proxy = self.connection.with_proxy( + "org.asuslinux.Daemon", + "/org/asuslinux/RogBios", + Duration::from_secs(2), + ); + proxy.set_post_boot_sound(::from(on))?; + Ok(()) + } + + #[inline] + pub fn get_supported_functions(&self) -> Result> { + let proxy = self.connection.with_proxy( + "org.asuslinux.Daemon", + "/org/asuslinux/Supported", + Duration::from_secs(2), + ); + let x = proxy.supported_functions()?; + Ok(x) + } } diff --git a/asus-nb/src/dbus_rogbios.rs b/asus-nb/src/dbus_rogbios.rs new file mode 100644 index 00000000..83e9e3e1 --- /dev/null +++ b/asus-nb/src/dbus_rogbios.rs @@ -0,0 +1,86 @@ +// This code was autogenerated with `dbus-codegen-rust -s -d org.asuslinux.Daemon -f org.asuslinux.Daemon -c blocking -p /org/asuslinux/RogBios -m None -o asus-nb/src/dbus_rogbios.rs`, see https://github.com/diwic/dbus-rs +use dbus; +#[allow(unused_imports)] +use dbus::arg; +use dbus::blocking; + +pub trait OrgAsuslinuxDaemon { + fn set_dedicated_graphic_mode(&self, dedicated: bool) -> Result<(), dbus::Error>; + fn dedicated_graphic_mode(&self) -> Result; + fn set_post_boot_sound(&self, on: bool) -> Result<(), dbus::Error>; + fn post_boot_sound(&self) -> Result; +} + +impl<'a, T: blocking::BlockingSender, C: ::std::ops::Deref> OrgAsuslinuxDaemon + for blocking::Proxy<'a, C> +{ + fn set_dedicated_graphic_mode(&self, dedicated: bool) -> Result<(), dbus::Error> { + self.method_call( + "org.asuslinux.Daemon", + "SetDedicatedGraphicMode", + (dedicated,), + ) + } + + fn dedicated_graphic_mode(&self) -> Result { + self.method_call("org.asuslinux.Daemon", "DedicatedGraphicMode", ()) + .and_then(|r: (i16,)| Ok(r.0)) + } + + fn set_post_boot_sound(&self, on: bool) -> Result<(), dbus::Error> { + self.method_call("org.asuslinux.Daemon", "SetPostBootSound", (on,)) + } + + fn post_boot_sound(&self) -> Result { + self.method_call("org.asuslinux.Daemon", "PostBootSound", ()) + .and_then(|r: (i16,)| Ok(r.0)) + } +} + +#[derive(Debug)] +pub struct OrgAsuslinuxDaemonNotifyDedicatedGraphicMode { + pub dedicated: bool, +} + +impl arg::AppendAll for OrgAsuslinuxDaemonNotifyDedicatedGraphicMode { + fn append(&self, i: &mut arg::IterAppend) { + arg::RefArg::append(&self.dedicated, i); + } +} + +impl arg::ReadAll for OrgAsuslinuxDaemonNotifyDedicatedGraphicMode { + fn read(i: &mut arg::Iter) -> Result { + Ok(OrgAsuslinuxDaemonNotifyDedicatedGraphicMode { + dedicated: i.read()?, + }) + } +} + +impl dbus::message::SignalArgs for OrgAsuslinuxDaemonNotifyDedicatedGraphicMode { + const NAME: &'static str = "NotifyDedicatedGraphicMode"; + const INTERFACE: &'static str = "org.asuslinux.Daemon"; +} + +#[derive(Debug)] +pub struct OrgAsuslinuxDaemonNotifyPostBootSound { + pub dedicated: bool, +} + +impl arg::AppendAll for OrgAsuslinuxDaemonNotifyPostBootSound { + fn append(&self, i: &mut arg::IterAppend) { + arg::RefArg::append(&self.dedicated, i); + } +} + +impl arg::ReadAll for OrgAsuslinuxDaemonNotifyPostBootSound { + fn read(i: &mut arg::Iter) -> Result { + Ok(OrgAsuslinuxDaemonNotifyPostBootSound { + dedicated: i.read()?, + }) + } +} + +impl dbus::message::SignalArgs for OrgAsuslinuxDaemonNotifyPostBootSound { + const NAME: &'static str = "NotifyPostBootSound"; + const INTERFACE: &'static str = "org.asuslinux.Daemon"; +} diff --git a/asus-nb/src/dbus_supported.rs b/asus-nb/src/dbus_supported.rs new file mode 100644 index 00000000..9a4a5ebf --- /dev/null +++ b/asus-nb/src/dbus_supported.rs @@ -0,0 +1,18 @@ +// This code was autogenerated with `dbus-codegen-rust -s -d org.asuslinux.Daemon -f org.asuslinux.Daemon -c blocking -p /org/asuslinux/Supported -m None -o asus-nb/src/dbus_supported.rs`, see https://github.com/diwic/dbus-rs +use dbus; +#[allow(unused_imports)] +use dbus::arg; +use dbus::blocking; + +pub trait OrgAsuslinuxDaemon { + fn supported_functions(&self) -> Result; +} + +impl<'a, T: blocking::BlockingSender, C: ::std::ops::Deref> OrgAsuslinuxDaemon + for blocking::Proxy<'a, C> +{ + fn supported_functions(&self) -> Result { + self.method_call("org.asuslinux.Daemon", "SupportedFunctions", ()) + .and_then(|r: (String,)| Ok(r.0)) + } +} diff --git a/asus-nb/src/lib.rs b/asus-nb/src/lib.rs index 4bf4adf8..fa823773 100644 --- a/asus-nb/src/lib.rs +++ b/asus-nb/src/lib.rs @@ -23,13 +23,15 @@ pub mod anime_dbus; /// Helper functions for the AniMe display pub mod anime_matrix; +pub mod error; + pub mod dbus_anime; pub mod dbus_charge; pub mod dbus_gfx; pub mod dbus_ledmode; pub mod dbus_profile; - -pub mod error; +pub mod dbus_rogbios; +pub mod dbus_supported; // static LED_INIT1: [u8; 2] = [0x5d, 0xb9]; // static LED_INIT2: &str = "]ASUS Tech.Inc."; // ] == 0x5d diff --git a/asus-nb/src/profile.rs b/asus-nb/src/profile.rs index c725fdbe..876d2b4e 100644 --- a/asus-nb/src/profile.rs +++ b/asus-nb/src/profile.rs @@ -75,7 +75,7 @@ fn parse_fan_curve(data: &str) -> Result { #[derive(Debug, Clone, Options, Serialize, Deserialize)] pub struct ProfileCommand { #[options(help = "print help message")] - help: bool, + pub help: bool, #[options(help = "toggle to next profile in list")] pub next: bool, #[options(help = "create the profile if it doesn't exist")] diff --git a/ctrl-gfx/Cargo.toml b/ctrl-gfx/Cargo.toml deleted file mode 100644 index 3a8053e5..00000000 --- a/ctrl-gfx/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -name = "ctrl-gfx" -version = "2.1.4" -license = "MPL-2.0" -readme = "README.md" -authors = ["Luke "] -description = "Fine control of laptop GPU" -edition = "2018" - -[dependencies] -sysfs-class = "^0.1.2" -log = "^0.4" - -zbus = { version = "1.8.0", optional = true } -zvariant = { version = "2.4.0", optional = true } - -[features] -default = ["use-zbus"] -use-zbus = ["zbus", "zvariant"] \ No newline at end of file