diff --git a/CHANGELOG.md b/CHANGELOG.md index e9bbc4a4..cb851f7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +# [2.0.0] - 2020-09-21 +### Changed +- graphics options via CLI are now a command block: + + `asusctl graphics` + + -m Mode + + -g Get current mode + + -f Force reboot or restart display manager without confirmation + # [2.0.0] - 2020-09-21 ### Changed - Code refactor to spawn less tasks. Main loop will run only as fast as diff --git a/Cargo.lock b/Cargo.lock index 43fa5d08..c3a979fa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -29,7 +29,7 @@ checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" [[package]] name = "asus-nb" -version = "2.0.1" +version = "2.0.2" dependencies = [ "ctrl-gfx", "dbus", @@ -46,7 +46,7 @@ dependencies = [ [[package]] name = "asus-nb-ctrl" -version = "2.0.1" +version = "2.0.2" dependencies = [ "asus-nb", "ctrl-gfx", @@ -189,7 +189,7 @@ dependencies = [ [[package]] name = "ctrl-gfx" -version = "2.0.0" +version = "2.1.0" dependencies = [ "log", "sysfs-class", diff --git a/Makefile b/Makefile index b3956128..de77023a 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ BIN_D=asusd BIN_N=asus-notify LEDCFG=asusd-ledmodes.toml X11CFG=90-nvidia-screen-G05.conf -UDEVRULES=90-nvidia-pm.rules +PMRULES=90-asusd-nvidia-pm.rules VERSION:=$(shell grep -Pm1 'version = "(\d.\d.\d)"' asus-nb-ctrl/Cargo.toml | cut -d'"' -f2) DEBUG ?= 0 @@ -42,8 +42,9 @@ install: all install -D -m 0755 "target/release/$(BIN_C)" "$(DESTDIR)$(bindir)/$(BIN_C)" install -D -m 0755 "target/release/$(BIN_D)" "$(DESTDIR)$(bindir)/$(BIN_D)" install -D -m 0755 "target/release/$(BIN_N)" "$(DESTDIR)$(bindir)/$(BIN_N)" - install -D -m 0644 "data/$(UDEVRULES)" "$(DESTDIR)/lib/udev/rules.d/$(UDEVRULES)" + install -D -m 0644 "data/$(PMRULES)" "$(DESTDIR)/lib/udev/rules.d/$(PMRULES)" install -D -m 0644 "data/$(BIN_D).rules" "$(DESTDIR)/lib/udev/rules.d/99-$(BIN_D).rules" + install -D -m 0644 "data/$(PMRULES).rules" "$(DESTDIR)/lib/udev/rules.d/$(PMRULES).rules" install -D -m 0644 "data/$(LEDCFG)" "$(DESTDIR)$(sysconfdir)/asusd/$(LEDCFG)" install -D -m 0644 "data/$(BIN_D).conf" "$(DESTDIR)$(sysconfdir)/dbus-1/system.d/$(BIN_D).conf" install -D -m 0644 "data/$(X11CFG)" "$(DESTDIR)$(sysconfdir)/X11/xorg.conf.d/$(X11CFG)" @@ -57,8 +58,9 @@ uninstall: rm -f "$(DESTDIR)$(bindir)/$(BIN_C)" rm -f "$(DESTDIR)$(bindir)/$(BIN_D)" rm -f "$(DESTDIR)$(bindir)/$(BIN_N)" - rm -f "$(DESTDIR)/lib/udev/rules.d/$(UDEVRULES)" + rm -f "$(DESTDIR)/lib/udev/rules.d/$(PMRULES)" rm -f "$(DESTDIR)/lib/udev/rules.d/99-$(BIN_D).rules" + rm -f "$(DESTDIR)/lib/udev/rules.d/$(PMRULES).rules" rm -f "$(DESTDIR)$(sysconfdir)/dbus-1/system.d/$(BIN_D).conf" rm -f "$(DESTDIR)$(sysconfdir)/X11/xorg.conf.d/$(X11CFG)" rm -f "$(DESTDIR)/lib/systemd/system/$(BIN_D).service" diff --git a/README.md b/README.md index 97aee335..8cb6e38c 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # ASUS NB Ctrl +`asusd` is a utility for Linux to control many aspects of various ASUS laptops +but can also be used with non-asus laptops with reduced features. + **NOTICE:** This program requires the kernel patch [here](https://www.spinics.net/lists/linux-input/msg68977.html) to be applied. @@ -12,17 +15,12 @@ The patch enables the following in kernel: - Control of keyboard brightness using FN+Key combos (not RGB) - FN+F5 (fan) to toggle fan modes -You will not get RGB control in kernel (yet), and asusd is still required to -change modes and RGB settings. The previous version of this program is named -`rog-core` and takes full control of the interfaces required - if you can't -apply the kernel patches then `rog-core` is still highly usable. +You will not get RGB control in kernel (yet), and `asusd` + `asusctl` is required +to change modes and RGB settings. Many other patches for these laptops, AMD and Intel based, are working their way in to the kernel. ---- -asusd is a utility for Linux to control many aspects of various ASUS laptops. - ## Discord [Discord server link](https://discord.gg/PVyFzWj) @@ -54,9 +52,9 @@ will probably suffer another rename once it becomes generic enough to do so. - [X] Fancy fan control on G14 + G15 thanks to @Yarn1 - [X] Graphics mode switching between iGPU, dGPU, and On-Demand -## FUNCTIONS +# FUNCTIONS -### Graphics switching +## Graphics switching A new feature has been added to enable switching graphics modes. This can be disabled in the config with `"manage_gfx": false,`. Please be aware it is a work in progress. @@ -64,7 +62,37 @@ in the config with `"manage_gfx": false,`. Please be aware it is a work in progr The CLI option for this does not require root until it asks for it, and provides instructions. -### KEYBOARD BACKLIGHT MODES +This switcher conflicts with other gpu switchers like optimus-manager, suse-prime +or ubuntu-prime, system76-power, and bbswitch. If you have issues with `asusd` +always defaulting to `integrated` mode on boot then you will need to check for +stray configs blocking nvidia modules from loading in: +- `/etc/modprobe.d/` +- `/usr/lib/modprope.d/` + +### Power management udev rule + +If you have installed the Nvidia driver manually you will require the +`data/90-asusd-nvidia-pm.rules` udev rule to be installed in `/etc/udev/rules.d/`. + +The above seems to also apply to Arch in general as it leaves a lot of things up +to the user. + +### fedora and openSUSE + +You *may* need a file `/etc/dracut.conf.d/90-nvidia-dracut-G05.conf` installed +to stop dracut including the nvidia modules in the ramdisk. + +``` +# filename /etc/dracut.conf.d/90-nvidia-dracut-G05.conf +# Omit the nvidia driver from the ramdisk, to avoid needing to regenerate +# the ramdisk on updates, and to ensure the power-management udev rules run +# on module load +omit_drivers+=" nvidia nvidia-drm nvidia-modeset nvidia-uvm " +``` + +and run `dracut -f` after creating it. + +## KEYBOARD BACKLIGHT MODES Models GA401, GA502, GU502 support LED brightness change only (no RGB). @@ -90,7 +118,9 @@ If you model isn't getting the correct led modes, you can edit the file use `cat /sys/class/dmi/id/product_name` to get details about your laptop. -## Requirements for compiling +# BUILDING + +Requirements are: - `rustc` + `cargo` + `make` - `libusb-1.0-0-dev` @@ -120,6 +150,11 @@ $ systemctl daemon-reload && systemctl restart asusd You may also need to activate the service for debian install. If running Pop!_OS, I suggest disabling `system76-power` gnome-shell extension and systemd service. +If you would like to run this daemon on another non-ASUS laptop you can. You'll +have all features available except the LED and AniMe control (further controllers +can be added on request). You will need to install the alternative service from +`data/asusd-alt.service`. + ## Uninstalling Run `sudo make uninstall` in the source repo, and remove `/etc/asusd/`. @@ -130,7 +165,7 @@ If there has been a config file format change your config will be overwritten. T become less of an issue once the feature set is nailed down. Work is happening to enable parsing of older configs and transferring settings to new. -# Usage +# USAGE **NOTE! Fan mode toggling requires a newer kernel**. I'm unsure when the patches required for it got merged - I've tested with the 5.6.6 kernel and above only. @@ -180,7 +215,7 @@ Daemon mode creates a config file at `/etc/asusd/asusd.conf` which you can edit little of. Most parts will be byte arrays, but you can adjust things like `mode_performance`. -## User daemon for notification via dbus +## User NOTIFICATIONS via dbus If you have a notifications handler set up, or are using KDE or Gnome then you can enable the user service to get basic notifications when something changes. @@ -189,7 +224,7 @@ can enable the user service to get basic notifications when something changes. systemctl --user enable asus-notify.service systemctl --user start asus-notify.service ``` -# Other +# OTHER ## DBUS Input @@ -208,6 +243,14 @@ Please file a support request. - If charge limit or fan modes are not working, then you may require a kernel newer than 5.6.10. - AniMe device check is performed on start, if your device has one it will be detected. - GA14/GA401 and GA15/GA502/GU502, You will need kernel [patches](https://lab.retarded.farm/zappel/asus-rog-zephyrus-g14/-/tree/master/kernel_patches), these are on their way to the kernel upstream. +- On fedora manually installed Nvidia driver requires a dracut config as follows: +``` +# filename/etc/dracut.conf.d/90-nvidia-dracut-G05.conf +# Omit the nvidia driver from the ramdisk, to avoid needing to regenerate +# the ramdisk on updates, and to ensure the power-management udev rules run +# on module load +omit_drivers+=" nvidia nvidia-drm nvidia-modeset nvidia-uvm " +``` # License diff --git a/asus-nb-ctrl/Cargo.toml b/asus-nb-ctrl/Cargo.toml index a0975183..7c49fccd 100644 --- a/asus-nb-ctrl/Cargo.toml +++ b/asus-nb-ctrl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "asus-nb-ctrl" -version = "2.0.1" +version = "2.0.2" license = "MPL-2.0" readme = "README.md" authors = ["Luke "] diff --git a/asus-nb-ctrl/src/lib.rs b/asus-nb-ctrl/src/lib.rs index 72bf9f3e..36a63708 100644 --- a/asus-nb-ctrl/src/lib.rs +++ b/asus-nb-ctrl/src/lib.rs @@ -19,7 +19,7 @@ use config::Config; use crate::error::RogError; use zbus::ObjectServer; -pub static VERSION: &str = "2.0.1"; +pub static VERSION: &str = "2.0.2"; pub trait Reloadable { fn reload(&mut self) -> Result<(), RogError>; diff --git a/asus-nb-ctrl/src/main.rs b/asus-nb-ctrl/src/main.rs index 9dcda24b..39d1fd56 100644 --- a/asus-nb-ctrl/src/main.rs +++ b/asus-nb-ctrl/src/main.rs @@ -8,6 +8,7 @@ use daemon::ctrl_fan_cpu::FanLevel; use gumdrop::Options; use log::LevelFilter; use std::io::Write; +use std::process::Command; use yansi_term::Colour::Green; use yansi_term::Colour::Red; @@ -23,18 +24,18 @@ struct CLIStart { pwr_profile: Option, #[options(meta = "CHRG", help = "<20-100>")] chg_limit: Option, - #[options(help = "Set graphics mode: ")] - graphics: Option, #[options(command)] - command: Option, + command: Option, } #[derive(Options)] -enum Command { +enum CliCommand { #[options(help = "Set the keyboard lighting from built-in modes")] LedMode(LedModeCommand), #[options(help = "Create and configure profiles")] Profile(ProfileCommand), + #[options(help = "Set the graphics mode")] + Graphics(GraphicsCommand), } #[derive(Options)] @@ -45,6 +46,20 @@ struct LedModeCommand { command: Option, } +#[derive(Options)] +struct GraphicsCommand { + #[options(help = "print help message")] + help: bool, + #[options(help = "Set graphics mode: ")] + mode: Option, + #[options(help = "Get the current mode")] + get: bool, + #[options(help = "Get the current power status")] + pow: bool, + #[options(help = "Do not ask for confirmation")] + force: bool, +} + fn main() -> Result<(), Box> { let mut logger = env_logger::Builder::new(); logger @@ -62,14 +77,15 @@ fn main() -> Result<(), Box> { let writer = AuraDbusClient::new()?; match parsed.command { - Some(Command::LedMode(mode)) => { + Some(CliCommand::LedMode(mode)) => { if let Some(command) = mode.command { writer.write_builtin_mode(&command.into())? } } - Some(Command::Profile(command)) => { + Some(CliCommand::Profile(command)) => { writer.write_profile_command(&ProfileEvent::Cli(command))? } + Some(CliCommand::Graphics(command)) => do_gfx(command, &writer)?, None => (), } @@ -82,52 +98,94 @@ fn main() -> Result<(), Box> { if let Some(chg_limit) = parsed.chg_limit { writer.write_charge_limit(chg_limit)?; } - if let Some(gfx) = parsed.graphics { + Ok(()) +} + +fn do_gfx( + command: GraphicsCommand, + writer: &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"); - writer.write_gfx_mode(gfx)?; + writer.write_gfx_mode(mode)?; let res = writer.wait_gfx_changed()?; match res.as_str() { - "reboot" => println!( - "{}\n{}", - Green.paint("\nGraphics vendor mode changed successfully\n"), - Red.paint("\nPlease reboot to complete switch\n") - ), + "reboot" => { + println!( + "{}", + Green.paint("\nGraphics vendor mode changed successfully\n"), + ); + do_gfx_action( + command.force, + Command::new("systemctl").arg("reboot"), + "Reboot Linux PC", + "Please reboot when ready", + )?; + } "restartx" => { println!( "{}", Green.paint("\nGraphics vendor mode changed successfully\n") ); - restart_x()?; + do_gfx_action( + command.force, + Command::new("systemctl") + .arg("restart") + .arg("display-manager.service"), + "Restart display-manager server", + "Please restart display-manager when ready", + )?; std::process::exit(1) } _ => std::process::exit(-1), } std::process::exit(-1) } - Ok(()) -} - -fn restart_x() -> Result<(), Box> { - println!("Restart X server? y/n"); - - let mut buf = String::new(); - std::io::stdin().read_line(&mut buf).expect("Input failed"); - let input = buf.chars().next().unwrap() as char; - - if input == 'Y' || input == 'y' { - println!("Restarting X server"); - let status = std::process::Command::new("systemctl") - .arg("restart") - .arg("display-manager.service") - .status()?; - - if !status.success() { - println!("systemctl: display-manager returned with {}", status); + if command.get { + let res = writer.get_gfx_mode()?; + println!("Current graphics mode: {}", res); + } + if command.pow { + let res = writer.get_gfx_pwr()?; + if res.contains("active") { + println!("Current power status: {}", Red.paint(&format!("{}", res))); + } else { + println!("Current power status: {}", Green.paint(&format!("{}", res))); } - } else { - println!("{}", Red.paint("Cancelled. Please restart X when ready")); + } + Ok(()) +} + +fn do_gfx_action( + no_confirm: bool, + command: &mut Command, + ask_msg: &str, + cancel_msg: &str, +) -> Result<(), Box> { + println!("{}? y/n", ask_msg); + + let mut buf = String::new(); + if no_confirm { + let status = command.status()?; + + if !status.success() { + println!("systemctl: returned with {}", status); + } + } + + std::io::stdin().read_line(&mut buf).expect("Input failed"); + let input = buf.chars().next().unwrap() as char; + + if input == 'Y' || input == 'y' || no_confirm { + let status = command.status()?; + + if !status.success() { + println!("systemctl: returned with {}", status); + } + } else { + println!("{}", Red.paint(&format!("{}", cancel_msg))); } Ok(()) } diff --git a/asus-nb/Cargo.toml b/asus-nb/Cargo.toml index 541c7a71..753c66cb 100644 --- a/asus-nb/Cargo.toml +++ b/asus-nb/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "asus-nb" -version = "2.0.1" +version = "2.0.2" license = "MPL-2.0" readme = "README.md" authors = ["Luke "] diff --git a/asus-nb/src/core_dbus.rs b/asus-nb/src/core_dbus.rs index 10093bd0..1e4e4c02 100644 --- a/asus-nb/src/core_dbus.rs +++ b/asus-nb/src/core_dbus.rs @@ -2,7 +2,6 @@ use super::*; use crate::fancy::KeyColourArray; use crate::profile::ProfileEvent; use ctrl_gfx::vendors::GfxVendors; -use dbus::channel::Sender; use dbus::{blocking::Connection, Message}; use std::error::Error; use std::sync::{ @@ -11,10 +10,17 @@ use std::sync::{ }; use std::{thread, time::Duration}; -use crate::dbus_gfx::{OrgAsuslinuxDaemonNotifyGfx, OrgAsuslinuxDaemonNotifyAction}; -use crate::dbus_ledmode::OrgAsuslinuxDaemonNotifyLed; -use crate::dbus_profile::OrgAsuslinuxDaemonNotifyProfile; -use crate::dbus_charge::OrgAsuslinuxDaemonNotifyCharge; +use crate::dbus_charge::{OrgAsuslinuxDaemonNotifyCharge, OrgAsuslinuxDaemon as OrgAsuslinuxDaemonCharge}; +use crate::dbus_gfx::{ + OrgAsuslinuxDaemon as OrgAsuslinuxDaemonGfx, OrgAsuslinuxDaemonNotifyAction, + OrgAsuslinuxDaemonNotifyGfx, +}; +use crate::dbus_ledmode::{ + OrgAsuslinuxDaemon as OrgAsuslinuxDaemonLed, OrgAsuslinuxDaemonNotifyLed, +}; +use crate::dbus_profile::{ + OrgAsuslinuxDaemon as OrgAsuslinuxDaemonProfile, OrgAsuslinuxDaemonNotifyProfile, +}; // Signals separated out pub struct CtrlSignals { @@ -111,7 +117,7 @@ impl CtrlSignals { let _x = proxy.match_signal( move |sig: OrgAsuslinuxDaemonNotifyCharge, _: &Connection, _: &Message| { if let Ok(mut lock) = charge_res1.lock() { - *lock = Some(sig.limit); + *lock = Some(sig.limit); } true }, @@ -176,11 +182,12 @@ impl AuraDbusClient { #[inline] pub fn init_effect(&self) -> Result<(), Box> { let mode = AuraModes::PerKey(vec![vec![]]); - let mut msg = - Message::new_method_call(DBUS_NAME, "/org/asuslinux/Led", DBUS_IFACE, "SetLedMode")? - .append1(serde_json::to_string(&mode)?); - msg.set_no_reply(true); - self.connection.send(msg).unwrap(); + let proxy = self.connection.with_proxy( + "org.asuslinux.Daemon", + "/org/asuslinux/Led", + Duration::from_millis(5000), + ); + proxy.set_led_mode(&serde_json::to_string(&mode)?)?; Ok(()) } @@ -199,13 +206,12 @@ impl AuraDbusClient { vecs.push(v.to_vec()); } let mode = AuraModes::PerKey(vecs); - let mut msg = - Message::new_method_call(DBUS_NAME, "/org/asuslinux/Led", DBUS_IFACE, "SetLedMode")? - .append1(serde_json::to_string(&mode)?); - msg.set_no_reply(true); - self.connection.send(msg).unwrap(); + + self.write_keyboard_leds(&mode)?; + thread::sleep(Duration::from_micros(self.block_time)); self.connection.process(Duration::from_micros(500))?; + if self.stop.load(Ordering::Relaxed) { println!("Keyboard backlight was changed, exiting"); std::process::exit(1) @@ -215,35 +221,56 @@ impl AuraDbusClient { #[inline] pub fn write_keyboard_leds(&self, mode: &AuraModes) -> Result<(), Box> { - let mut msg = - Message::new_method_call(DBUS_NAME, "/org/asuslinux/Led", DBUS_IFACE, "SetLedMode")? - .append1(serde_json::to_string(mode)?); - msg.set_no_reply(true); - self.connection.send(msg).unwrap(); + let proxy = self.connection.with_proxy( + "org.asuslinux.Daemon", + "/org/asuslinux/Led", + Duration::from_millis(5000), + ); + proxy.set_led_mode(&serde_json::to_string(mode)?)?; + Ok(()) + } + + #[inline] + pub fn get_gfx_pwr(&self) -> Result> { + let proxy = self.connection.with_proxy( + "org.asuslinux.Daemon", + "/org/asuslinux/Gfx", + Duration::from_millis(5000), + ); + let x = proxy.power().unwrap(); + Ok(x) + } + + #[inline] + pub fn get_gfx_mode(&self) -> Result> { + let proxy = self.connection.with_proxy( + "org.asuslinux.Daemon", + "/org/asuslinux/Gfx", + Duration::from_millis(5000), + ); + let x = proxy.vendor().unwrap(); + Ok(x) + } + + #[inline] + pub fn write_gfx_mode(&self, vendor: GfxVendors) -> Result<(), Box> { + let proxy = self.connection.with_proxy( + "org.asuslinux.Daemon", + "/org/asuslinux/Gfx", + Duration::from_millis(5000), + ); + proxy.set_vendor(<&str>::from(&vendor))?; Ok(()) } #[inline] pub fn write_fan_mode(&self, level: u8) -> Result<(), Box> { - let mut msg = Message::new_method_call( - DBUS_NAME, + let proxy = self.connection.with_proxy( + "org.asuslinux.Daemon", "/org/asuslinux/Profile", - DBUS_IFACE, - "SetProfile", - )? - .append1(serde_json::to_string(&ProfileEvent::ChangeMode(level))?); - msg.set_no_reply(true); - self.connection.send(msg).unwrap(); - Ok(()) - } - - #[inline] - pub fn write_gfx_mode(&self, vendor: GfxVendors) -> Result<(), Box> { - let mut msg = - Message::new_method_call(DBUS_NAME, "/org/asuslinux/Gfx", DBUS_IFACE, "SetVendor")? - .append1(<&str>::from(&vendor)); - msg.set_no_reply(true); - self.connection.send(msg).unwrap(); + Duration::from_millis(5000), + ); + proxy.set_profile(&serde_json::to_string(&ProfileEvent::ChangeMode(level))?)?; Ok(()) } @@ -252,25 +279,23 @@ impl AuraDbusClient { &self, cmd: &ProfileEvent, ) -> Result<(), Box> { - let mut msg = Message::new_method_call( - DBUS_NAME, + let proxy = self.connection.with_proxy( + "org.asuslinux.Daemon", "/org/asuslinux/Profile", - DBUS_IFACE, - "SetProfile", - )? - .append1(serde_json::to_string(cmd)?); - msg.set_no_reply(true); - self.connection.send(msg).unwrap(); + Duration::from_millis(5000), + ); + proxy.set_profile(&serde_json::to_string(cmd)?)?; Ok(()) } #[inline] pub fn write_charge_limit(&self, level: u8) -> Result<(), Box> { - let mut msg = - Message::new_method_call(DBUS_NAME, "/org/asuslinux/Charge", DBUS_IFACE, "SetLimit")? - .append1(level); - msg.set_no_reply(true); - self.connection.send(msg).unwrap(); + let proxy = self.connection.with_proxy( + "org.asuslinux.Daemon", + "/org/asuslinux/Charge", + Duration::from_millis(5000), + ); + proxy.set_limit(level)?; Ok(()) } diff --git a/asus-nb/src/dbus_gfx.rs b/asus-nb/src/dbus_gfx.rs index c227fcba..ef74da62 100644 --- a/asus-nb/src/dbus_gfx.rs +++ b/asus-nb/src/dbus_gfx.rs @@ -5,11 +5,23 @@ use dbus::arg; use dbus::blocking; pub trait OrgAsuslinuxDaemon { + fn vendor(&self) -> Result; + fn power(&self) -> Result; fn set_vendor(&self, vendor: &str) -> Result<(), dbus::Error>; } impl<'a, T: blocking::BlockingSender, C: ::std::ops::Deref> OrgAsuslinuxDaemon for blocking::Proxy<'a, C> { + fn vendor(&self) -> Result { + self.method_call("org.asuslinux.Daemon", "Vendor", ()) + .and_then(|r: (String, )| Ok(r.0, )) + } + + fn power(&self) -> Result { + self.method_call("org.asuslinux.Daemon", "Power", ()) + .and_then(|r: (String, )| Ok(r.0, )) + } + fn set_vendor(&self, vendor: &str) -> Result<(), dbus::Error> { self.method_call("org.asuslinux.Daemon", "SetVendor", (vendor, )) } diff --git a/ctrl-gfx/Cargo.toml b/ctrl-gfx/Cargo.toml index fd9f6d6f..db44b8fe 100644 --- a/ctrl-gfx/Cargo.toml +++ b/ctrl-gfx/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ctrl-gfx" -version = "2.0.0" +version = "2.1.0" license = "MPL-2.0" readme = "README.md" authors = ["Luke "] diff --git a/ctrl-gfx/src/ctrl_gfx.rs b/ctrl-gfx/src/ctrl_gfx.rs index d62d655e..667350d9 100644 --- a/ctrl-gfx/src/ctrl_gfx.rs +++ b/ctrl-gfx/src/ctrl_gfx.rs @@ -14,8 +14,8 @@ use crate::{error::GfxError, system::*}; pub struct CtrlGraphics { bus: PciBus, - amd: Vec, - intel: Vec, + _amd: Vec, + _intel: Vec, nvidia: Vec, #[allow(dead_code)] other: Vec, @@ -23,6 +23,8 @@ pub struct CtrlGraphics { } trait Dbus { + fn vendor(&self) -> String; + fn power(&self) -> String; fn set_vendor(&mut self, vendor: String); fn notify_gfx(&self, vendor: &str) -> zbus::Result<()>; fn notify_action(&self, action: &str) -> zbus::Result<()>; @@ -34,6 +36,18 @@ use std::convert::TryInto; #[cfg(feature = "use-zbus")] #[dbus_interface(name = "org.asuslinux.Daemon")] impl Dbus for CtrlGraphics { + fn vendor(&self) -> String { + Self::get_vendor() + .map_err(|err| format!("Get vendor failed: {}", err)) + .unwrap() + } + + fn power(&self) -> String { + Self::get_runtime_status() + .map_err(|err| format!("Get power status failed: {}", err)) + .unwrap() + } + fn set_vendor(&mut self, vendor: String) { if let Ok(tmp) = GfxVendors::from_str(&vendor) { let action = self.set(tmp).unwrap_or_else(|err| { @@ -113,17 +127,18 @@ impl CtrlGraphics { cmd.arg("-u"); initfs_cmd = Some(cmd); info!("Using initramfs update command 'update-initramfs'"); - } else if Path::new(DRACUT_PATH).exists() { - let mut cmd = Command::new("dracut"); - cmd.arg("-f"); - initfs_cmd = Some(cmd); - info!("Using initramfs update command 'dracut'"); } + // } else if Path::new(DRACUT_PATH).exists() { + // let mut cmd = Command::new("dracut"); + // cmd.arg("-f"); + // initfs_cmd = Some(cmd); + // info!("Using initramfs update command 'dracut'"); + // } Ok(CtrlGraphics { bus, - amd, - intel, + _amd: amd, + _intel: intel, nvidia, other, initfs_cmd, @@ -143,9 +158,9 @@ impl CtrlGraphics { Ok(()) } - fn can_switch(&self) -> bool { - !self.nvidia.is_empty() && (!self.intel.is_empty() || !self.amd.is_empty()) - } + // 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) @@ -305,11 +320,17 @@ 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_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))?; + Ok(buf) } fn set_power(&self, power: bool) -> Result<(), GfxError> { diff --git a/ctrl-gfx/src/lib.rs b/ctrl-gfx/src/lib.rs index ee22c8ae..a7e1e96e 100644 --- a/ctrl-gfx/src/lib.rs +++ b/ctrl-gfx/src/lib.rs @@ -9,7 +9,7 @@ pub mod system; const PRIME_DISCRETE_PATH: &str = "/etc/prime-discrete"; const MODPROBE_PATH: &str = "/etc/modprobe.d/asusd.conf"; const INITRAMFS_PATH: &str = "/usr/sbin/update-initramfs"; -const DRACUT_PATH: &str = "/usr/bin/dracut"; +//const DRACUT_PATH: &str = "/usr/bin/dracut"; static MODPROBE_NVIDIA: &[u8] = MODPROBE_HYBRID; @@ -54,4 +54,5 @@ static PRIMARY_GPU_NVIDIA: &[u8] = br#" Option "PrimaryGPU" "true""#; static PRIMARY_GPU_END: &[u8] = br#" -EndSection"#; \ No newline at end of file +EndSection"#; + diff --git a/data/90-nvidia-pm.rules b/data/90-asusd-nvidia-pm.rules similarity index 100% rename from data/90-nvidia-pm.rules rename to data/90-asusd-nvidia-pm.rules diff --git a/data/asusd-alt.service b/data/asusd-alt.service new file mode 100644 index 00000000..a1f260cf --- /dev/null +++ b/data/asusd-alt.service @@ -0,0 +1,12 @@ +[Unit] +Description=ASUS Notebook Control +After=basic.target syslog.target + +[Service] +ExecStart=/usr/bin/asusd +Restart=on-failure +Type=dbus +BusName=org.asuslinux.Daemon + +[Install] +WantedBy=multi-user.target \ No newline at end of file