Major update to supergfx and others

This commit is contained in:
Luke D. Jones
2021-08-26 11:43:47 +12:00
parent 60b7f3be69
commit 498e604531
33 changed files with 535 additions and 278 deletions

15
Cargo.lock generated
View File

@@ -40,6 +40,7 @@ dependencies = [
"rog_types", "rog_types",
"serde_json", "serde_json",
"supergfxctl", "supergfxctl",
"zbus",
] ]
[[package]] [[package]]
@@ -57,7 +58,7 @@ dependencies = [
"rog_types", "rog_types",
"supergfxctl", "supergfxctl",
"tinybmp", "tinybmp",
"yansi-term", "zbus",
] ]
[[package]] [[package]]
@@ -221,7 +222,6 @@ dependencies = [
"serde", "serde",
"serde_derive", "serde_derive",
"serde_json", "serde_json",
"supergfxctl",
"sysfs-class", "sysfs-class",
"toml", "toml",
"udev", "udev",
@@ -1070,6 +1070,8 @@ dependencies = [
name = "supergfxctl" name = "supergfxctl"
version = "1.1.0" version = "1.1.0"
dependencies = [ dependencies = [
"env_logger",
"gumdrop",
"log", "log",
"logind-zbus", "logind-zbus",
"serde", "serde",
@@ -1314,15 +1316,6 @@ dependencies = [
"bitflags 0.9.1", "bitflags 0.9.1",
] ]
[[package]]
name = "yansi-term"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe5c30ade05e61656247b2e334a031dfd0cc466fadef865bdcdea8d537951bf1"
dependencies = [
"winapi",
]
[[package]] [[package]]
name = "zbus" name = "zbus"
version = "1.9.1" version = "1.9.1"

View File

@@ -15,6 +15,8 @@ BIN_C := asusctl
BIN_D := asusd BIN_D := asusd
BIN_U := asusd-user BIN_U := asusd-user
BIN_N := asus-notify BIN_N := asus-notify
BIN_SD := supergfxd
BIN_SC := supergfxctl
LEDCFG := asusd-ledmodes.toml LEDCFG := asusd-ledmodes.toml
X11CFG := 90-nvidia-screen-G05.conf X11CFG := 90-nvidia-screen-G05.conf
PMRULES := 90-asusd-nvidia-pm.rules PMRULES := 90-asusd-nvidia-pm.rules
@@ -45,14 +47,15 @@ install:
$(INSTALL_PROGRAM) "./target/release/$(BIN_D)" "$(DESTDIR)$(bindir)/$(BIN_D)" $(INSTALL_PROGRAM) "./target/release/$(BIN_D)" "$(DESTDIR)$(bindir)/$(BIN_D)"
$(INSTALL_PROGRAM) "./target/release/$(BIN_U)" "$(DESTDIR)$(bindir)/$(BIN_U)" $(INSTALL_PROGRAM) "./target/release/$(BIN_U)" "$(DESTDIR)$(bindir)/$(BIN_U)"
$(INSTALL_PROGRAM) "./target/release/$(BIN_N)" "$(DESTDIR)$(bindir)/$(BIN_N)" $(INSTALL_PROGRAM) "./target/release/$(BIN_N)" "$(DESTDIR)$(bindir)/$(BIN_N)"
$(INSTALL_DATA) "./data/$(PMRULES)" "$(DESTDIR)$(libdir)/udev/rules.d/$(PMRULES)"
$(INSTALL_DATA) "./data/$(BIN_D).rules" "$(DESTDIR)$(libdir)/udev/rules.d/99-$(BIN_D).rules" $(INSTALL_DATA) "./data/$(BIN_D).rules" "$(DESTDIR)$(libdir)/udev/rules.d/99-$(BIN_D).rules"
$(INSTALL_DATA) "./data/$(LEDCFG)" "$(DESTDIR)/etc/asusd/$(LEDCFG)" $(INSTALL_DATA) "./data/$(LEDCFG)" "$(DESTDIR)/etc/asusd/$(LEDCFG)"
$(INSTALL_DATA) "./data/$(BIN_D).conf" "$(DESTDIR)$(datarootdir)/dbus-1/system.d/$(BIN_D).conf" $(INSTALL_DATA) "./data/$(BIN_D).conf" "$(DESTDIR)$(datarootdir)/dbus-1/system.d/$(BIN_D).conf"
$(INSTALL_DATA) "./data/$(X11CFG)" "$(DESTDIR)$(datarootdir)/X11/xorg.conf.d/$(X11CFG)"
$(INSTALL_DATA) "./data/$(BIN_D).service" "$(DESTDIR)$(libdir)/systemd/system/$(BIN_D).service" $(INSTALL_DATA) "./data/$(BIN_D).service" "$(DESTDIR)$(libdir)/systemd/system/$(BIN_D).service"
$(INSTALL_DATA) "./data/$(BIN_N).service" "$(DESTDIR)$(libdir)/systemd/user/$(BIN_N).service" $(INSTALL_DATA) "./data/$(BIN_N).service" "$(DESTDIR)$(libdir)/systemd/user/$(BIN_N).service"
$(INSTALL_DATA) "./data/$(BIN_U).service" "$(DESTDIR)$(libdir)/systemd/user/$(BIN_U).service" $(INSTALL_DATA) "./data/$(BIN_U).service" "$(DESTDIR)$(libdir)/systemd/user/$(BIN_U).service"
$(INSTALL_DATA) "./data/icons/asus_notif_yellow.png" "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_yellow.png" $(INSTALL_DATA) "./data/icons/asus_notif_yellow.png" "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_yellow.png"
$(INSTALL_DATA) "./data/icons/asus_notif_green.png" "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_green.png" $(INSTALL_DATA) "./data/icons/asus_notif_green.png" "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_green.png"
$(INSTALL_DATA) "./data/icons/asus_notif_red.png" "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_red.png" $(INSTALL_DATA) "./data/icons/asus_notif_red.png" "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_red.png"
@@ -63,10 +66,18 @@ install:
$(INSTALL_DATA) "./data/icons/scalable/gpu-nvidia.svg" "$(DESTDIR)$(datarootdir)/icons/hicolor/scalable/status/gpu-nvidia.svg" $(INSTALL_DATA) "./data/icons/scalable/gpu-nvidia.svg" "$(DESTDIR)$(datarootdir)/icons/hicolor/scalable/status/gpu-nvidia.svg"
$(INSTALL_DATA) "./data/icons/scalable/gpu-vfio.svg" "$(DESTDIR)$(datarootdir)/icons/hicolor/scalable/status/gpu-vfio.svg" $(INSTALL_DATA) "./data/icons/scalable/gpu-vfio.svg" "$(DESTDIR)$(datarootdir)/icons/hicolor/scalable/status/gpu-vfio.svg"
$(INSTALL_DATA) "./data/icons/scalable/notification-reboot.svg" "$(DESTDIR)$(datarootdir)/icons/hicolor/scalable/status/notification-reboot.svg" $(INSTALL_DATA) "./data/icons/scalable/notification-reboot.svg" "$(DESTDIR)$(datarootdir)/icons/hicolor/scalable/status/notification-reboot.svg"
$(INSTALL_DATA) "./data/_asusctl" "$(DESTDIR)$(zshcpl)/_asusctl" $(INSTALL_DATA) "./data/_asusctl" "$(DESTDIR)$(zshcpl)/_asusctl"
$(INSTALL_DATA) "./data/completions/asusctl.fish" "$(DESTDIR)$(datarootdir)/fish/vendor_completions.d/asusctl.fish" $(INSTALL_DATA) "./data/completions/asusctl.fish" "$(DESTDIR)$(datarootdir)/fish/vendor_completions.d/asusctl.fish"
cd data && find "./anime" -type f -exec install -Dm 755 "{}" "$(DESTDIR)$(datarootdir)/asusd/{}" \; cd data && find "./anime" -type f -exec install -Dm 755 "{}" "$(DESTDIR)$(datarootdir)/asusd/{}" \;
$(INSTALL_PROGRAM) "./target/release/$(BIN_SD)" "$(DESTDIR)$(bindir)/$(BIN_SD)"
$(INSTALL_PROGRAM) "./target/release/$(BIN_SC)" "$(DESTDIR)$(bindir)/$(BIN_SC)"
$(INSTALL_DATA) "./supergfx/data/$(BIN_SD).service" "$(DESTDIR)$(libdir)/systemd/system/$(BIN_SD).service"
$(INSTALL_DATA) "./supergfx/data/org.supergfxctl.Daemon.conf" "$(DESTDIR)$(datarootdir)/dbus-1/system.d/org.supergfxctl.Daemon.conf"
$(INSTALL_DATA) "./supergfx/data/$(X11CFG)" "$(DESTDIR)$(datarootdir)/X11/xorg.conf.d/$(X11CFG)"
$(INSTALL_DATA) "./supergfx/data/$(PMRULES)" "$(DESTDIR)$(libdir)/udev/rules.d/$(PMRULES)"
uninstall: uninstall:
rm -f "$(DESTDIR)$(bindir)/$(BIN_C)" rm -f "$(DESTDIR)$(bindir)/$(BIN_C)"
rm -f "$(DESTDIR)$(bindir)/$(BIN_D)" rm -f "$(DESTDIR)$(bindir)/$(BIN_D)"
@@ -90,6 +101,10 @@ uninstall:
rm -f "$(DESTDIR)$(zshcpl)/_asusctl" rm -f "$(DESTDIR)$(zshcpl)/_asusctl"
rm -f "$(DESTDIR)$(datarootdir)/fish/vendor_completions.d/asusctl.fish" rm -f "$(DESTDIR)$(datarootdir)/fish/vendor_completions.d/asusctl.fish"
rm -rf "$(DESTDIR)$(datarootdir)/asusd" rm -rf "$(DESTDIR)$(datarootdir)/asusd"
rm -f "$(DESTDIR)$(bindir)/$(BIN_SC)"
rm -f "$(DESTDIR)$(bindir)/$(BIN_SD)"
rm -f "$(DESTDIR)$(libdir)/systemd/system/$(BIN_SD).service"
rm -f "$(DESTDIR)$(datarootdir)/dbus-1/system.d/org.supergfxctl.Daemon.conf"
update: update:
cargo update cargo update

View File

@@ -7,6 +7,7 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
zbus = "^1.9"
# serialisation # serialisation
serde_json = "^1.0" serde_json = "^1.0"
rog_dbus = { path = "../rog-dbus" } rog_dbus = { path = "../rog-dbus" }

View File

@@ -2,11 +2,14 @@ use notify_rust::{Hint, Notification, NotificationHandle};
use rog_aura::AuraEffect; use rog_aura::AuraEffect;
use rog_dbus::{DbusProxies, Signals}; use rog_dbus::{DbusProxies, Signals};
use rog_profiles::Profile; use rog_profiles::Profile;
use supergfxctl::gfx_vendors::{GfxRequiredUserAction, GfxVendors};
use std::error::Error; use std::error::Error;
use std::process; use std::sync::mpsc::channel;
use std::thread::sleep; use std::thread::sleep;
use std::time::Duration; use std::time::Duration;
use std::{process, thread};
use supergfxctl::gfx_vendors::{GfxRequiredUserAction, GfxVendors};
use supergfxctl::zbus_proxy::GfxProxy;
use zbus::Connection;
const NOTIF_HEADER: &str = "ROG Control"; const NOTIF_HEADER: &str = "ROG Control";
@@ -42,6 +45,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let recv = proxies.setup_recv(conn); let recv = proxies.setup_recv(conn);
let mut err_count = 0; let mut err_count = 0;
gfx_thread()?;
loop { loop {
sleep(Duration::from_millis(100)); sleep(Duration::from_millis(100));
if let Err(err) = recv.next_signal() { if let Err(err) = recv.next_signal() {
@@ -67,23 +73,57 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
if let Ok(data) = signals.charge.try_recv() { if let Ok(data) = signals.charge.try_recv() {
notify!(do_charge_notif, last_notification, &data); notify!(do_charge_notif, last_notification, &data);
} }
if let Ok(data) = signals.gfx_vendor.try_recv() { }
}
fn gfx_thread() -> Result<(), Box<dyn std::error::Error>> {
let mut last_notification: Option<NotificationHandle> = None;
let conn = Connection::new_system()?;
let proxy = GfxProxy::new(&conn)?;
let (tx1, rx1) = channel();
proxy.connect_notify_gfx(tx1)?;
let (tx2, rx2) = channel();
proxy.connect_notify_action(tx2)?;
thread::spawn(move || loop {
if proxy
.next_signal()
.map_err(|e| println!("Error: {}", e))
.is_err()
{
break;
}
if let Ok(data) = rx1.try_recv() {
notify!(do_gfx_notif, last_notification, &data); notify!(do_gfx_notif, last_notification, &data);
} }
if let Ok(data) = signals.gfx_action.try_recv() {
if let Ok(data) = rx2.try_recv() {
match data { match data {
GfxRequiredUserAction::Logout | GfxRequiredUserAction::Reboot => { GfxRequiredUserAction::Logout | GfxRequiredUserAction::Reboot => {
do_gfx_action_notif(&data)?; do_gfx_action_notif(&data)
.map_err(|e| {
println!("Error: {}", e);
})
.ok();
} }
GfxRequiredUserAction::Integrated => { GfxRequiredUserAction::Integrated => {
base_notification!( base_notification!(
"You must be in integrated mode first to switch to the requested mode" "You must be in integrated mode first to switch to the requested mode"
)?; )
.map_err(|e| {
println!("Error: {}", e);
})
.ok();
} }
GfxRequiredUserAction::None => {} GfxRequiredUserAction::None => {}
} }
} }
} });
Ok(())
} }
fn do_thermal_notif(profile: &Profile) -> Result<NotificationHandle, Box<dyn Error>> { fn do_thermal_notif(profile: &Profile) -> Result<NotificationHandle, Box<dyn Error>> {

View File

@@ -7,6 +7,7 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
zbus = "^1.9.1"
rog_anime = { path = "../rog-anime" } rog_anime = { path = "../rog-anime" }
rog_aura = { path = "../rog-aura" } rog_aura = { path = "../rog-aura" }
rog_dbus = { path = "../rog-dbus" } rog_dbus = { path = "../rog-dbus" }
@@ -14,7 +15,6 @@ rog_profiles = { path = "../rog-profiles" }
rog_types = { path = "../rog-types" } rog_types = { path = "../rog-types" }
daemon = { path = "../daemon" } daemon = { path = "../daemon" }
gumdrop = "^0.8" gumdrop = "^0.8"
yansi-term = "^0.1"
supergfxctl = { path = "../supergfx" } supergfxctl = { path = "../supergfx" }
[dev-dependencies] [dev-dependencies]

View File

@@ -9,16 +9,17 @@ use profiles_cli::ProfileCommand;
use rog_anime::{AnimeDataBuffer, AnimeImage, Vec2, ANIME_DATA_LEN}; use rog_anime::{AnimeDataBuffer, AnimeImage, Vec2, ANIME_DATA_LEN};
use rog_aura::{self, AuraEffect}; use rog_aura::{self, AuraEffect};
use rog_dbus::RogDbusClient; use rog_dbus::RogDbusClient;
use rog_types::{ use rog_types::supported::{
supported::{ AnimeSupportedFunctions, LedSupportedFunctions, PlatformProfileFunctions,
AnimeSupportedFunctions, LedSupportedFunctions, PlatformProfileFunctions, RogBiosSupportedFunctions,
RogBiosSupportedFunctions,
},
}; };
use supergfxctl::gfx_vendors::{GfxPower, GfxRequiredUserAction, GfxVendors}; use std::{env::args, path::Path, sync::mpsc::channel};
use std::{env::args, path::Path}; use supergfxctl::{
use yansi_term::Colour::Green; gfx_vendors::{GfxRequiredUserAction, GfxVendors},
use yansi_term::Colour::Red; special::{get_asus_gsync_gfx_mode, has_asus_gsync_gfx_mode},
zbus_proxy::GfxProxy,
};
use zbus::Connection;
#[derive(Default, Options)] #[derive(Default, Options)]
struct CliStart { struct CliStart {
@@ -152,7 +153,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
match parsed.command { match parsed.command {
Some(CliCommand::LedMode(mode)) => handle_led_mode(&dbus, &supported.keyboard_led, &mode)?, Some(CliCommand::LedMode(mode)) => handle_led_mode(&dbus, &supported.keyboard_led, &mode)?,
Some(CliCommand::Profile(cmd)) => handle_profile(&dbus, &supported.platform_profile, &cmd)?, Some(CliCommand::Profile(cmd)) => handle_profile(&dbus, &supported.platform_profile, &cmd)?,
Some(CliCommand::Graphics(cmd)) => do_gfx(&dbus, &supported.rog_bios_ctrl, cmd)?, Some(CliCommand::Graphics(cmd)) => do_gfx(cmd)?,
Some(CliCommand::Anime(cmd)) => handle_anime(&dbus, &supported.anime_ctrl, &cmd)?, Some(CliCommand::Anime(cmd)) => handle_anime(&dbus, &supported.anime_ctrl, &cmd)?,
Some(CliCommand::Bios(cmd)) => handle_bios_option(&dbus, &supported.rog_bios_ctrl, &cmd)?, Some(CliCommand::Bios(cmd)) => handle_bios_option(&dbus, &supported.rog_bios_ctrl, &cmd)?,
None => { None => {
@@ -190,62 +191,67 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
Ok(()) Ok(())
} }
fn do_gfx( fn do_gfx(command: GraphicsCommand) -> Result<(), Box<dyn std::error::Error>> {
dbus: &RogDbusClient,
supported: &RogBiosSupportedFunctions,
command: GraphicsCommand,
) -> Result<(), Box<dyn std::error::Error>> {
if command.mode.is_none() && !command.get && !command.pow && !command.force || command.help { if command.mode.is_none() && !command.get && !command.pow && !command.force || command.help {
println!("{}", command.self_usage()); println!("{}", command.self_usage());
} }
let conn = Connection::new_system()?;
let proxy = GfxProxy::new(&conn)?;
let (tx, rx) = channel();
proxy.connect_notify_action(tx)?;
if let Some(mode) = command.mode { if let Some(mode) = command.mode {
if supported.dedicated_gfx_toggle && dbus.proxies().rog_bios().get_dedicated_gfx()? == 1 { if has_asus_gsync_gfx_mode() && get_asus_gsync_gfx_mode()? == 1 {
println!("You can not change modes until you turn dedicated/G-Sync off and reboot"); println!("You can not change modes until you turn dedicated/G-Sync off and reboot");
std::process::exit(-1); std::process::exit(-1);
} }
println!("If anything fails check `journalctl -b -u asusd`\n"); println!("If anything fails check `journalctl -b -u asusd`\n");
dbus.proxies().gfx().gfx_write_mode(&mode).map_err(|err|{ proxy.gfx_write_mode(&mode).map_err(|err|{
println!("Graphics mode change error. You may be in an invalid state."); println!("Graphics mode change error. You may be in an invalid state.");
println!("Check mode with `asusctl graphics -g` and switch to opposite\nmode to correct it, e.g: if integrated, switch to hybrid, or if nvidia, switch to integrated.\n"); println!("Check mode with `asusctl graphics -g` and switch to opposite\nmode to correct it, e.g: if integrated, switch to hybrid, or if nvidia, switch to integrated.\n");
err err
})?; })?;
let res = dbus.gfx_wait_changed()?;
match res { loop {
GfxRequiredUserAction::Integrated => { proxy.next_signal()?;
println!(
"You must change to Integrated before you can change to {}", if let Ok(res) = rx.try_recv() {
<&str>::from(mode) match res {
); GfxRequiredUserAction::Integrated => {
} println!(
GfxRequiredUserAction::Logout | GfxRequiredUserAction::Reboot => { "You must change to Integrated before you can change to {}",
println!( <&str>::from(mode)
"Graphics mode changed to {}. User action required is: {}", );
<&str>::from(mode), }
<&str>::from(&res) GfxRequiredUserAction::Logout | GfxRequiredUserAction::Reboot => {
); println!(
} "Graphics mode changed to {}. User action required is: {}",
GfxRequiredUserAction::None => { <&str>::from(mode),
println!("Graphics mode changed to {}", <&str>::from(mode)); <&str>::from(&res)
);
}
GfxRequiredUserAction::None => {
println!("Graphics mode changed to {}", <&str>::from(mode));
}
}
} }
std::process::exit(0)
} }
std::process::exit(0)
} }
if command.get { if command.get {
let res = dbus.proxies().gfx().gfx_get_mode()?; let res = proxy.gfx_get_mode()?;
println!("Current graphics mode: {}", <&str>::from(res)); println!("Current graphics mode: {}", <&str>::from(res));
} }
if command.pow { if command.pow {
let res = dbus.proxies().gfx().gfx_get_pwr()?; let res = proxy.gfx_get_pwr()?;
match res { println!("Current power status: {}", <&str>::from(&res));
GfxPower::Active => {
println!("Current power status: {}", Red.paint(<&str>::from(&res)))
}
_ => println!("Current power status: {}", Green.paint(<&str>::from(&res))),
}
} }
Ok(()) Ok(())
} }

View File

@@ -23,7 +23,6 @@ rog_aura = { path = "../rog-aura" }
rog_types = { path = "../rog-types" } rog_types = { path = "../rog-types" }
rog_profiles = { path = "../rog-profiles" } rog_profiles = { path = "../rog-profiles" }
rog_dbus = { path = "../rog-dbus" } rog_dbus = { path = "../rog-dbus" }
supergfxctl = { path = "../supergfx" }
rusb = "^0.8" rusb = "^0.8"
udev = "^0.6" udev = "^0.6"

View File

@@ -3,7 +3,6 @@ use serde_derive::{Deserialize, Serialize};
use std::fs::{File, OpenOptions}; use std::fs::{File, OpenOptions};
use std::io::{Read, Write}; use std::io::{Read, Write};
use crate::config_old::*;
use crate::VERSION; use crate::VERSION;
pub static CONFIG_PATH: &str = "/etc/asusd/asusd.conf"; pub static CONFIG_PATH: &str = "/etc/asusd/asusd.conf";
@@ -36,9 +35,6 @@ impl Config {
config = Self::new(); config = Self::new();
} else if let Ok(data) = serde_json::from_str(&buf) { } else if let Ok(data) = serde_json::from_str(&buf) {
config = data; config = data;
} else if let Ok(data) = serde_json::from_str::<ConfigV352>(&buf) {
config = data.into_current();
info!("Updated config version to: {}", VERSION);
} else { } else {
warn!("Could not deserialise {}", CONFIG_PATH); warn!("Could not deserialise {}", CONFIG_PATH);
panic!("Please remove {} then restart asusd", CONFIG_PATH); panic!("Please remove {} then restart asusd", CONFIG_PATH);

View File

@@ -1,53 +0,0 @@
use serde_derive::{Deserialize, Serialize};
use supergfxctl::gfx_vendors::GfxVendors;
use std::collections::BTreeMap;
use crate::config::Config;
#[derive(Deserialize, Serialize)]
pub struct ConfigV352 {
pub gfx_mode: GfxVendors,
pub gfx_last_mode: GfxVendors,
pub gfx_managed: bool,
pub gfx_vfio_enable: bool,
pub gfx_save_compute_vfio: bool,
pub active_profile: String,
pub toggle_profiles: Vec<String>,
#[serde(skip)]
pub curr_fan_mode: u8,
pub bat_charge_limit: u8,
pub power_profiles: BTreeMap<String, ProfileV317>,
}
impl ConfigV352 {
pub(crate) fn into_current(self) -> Config {
Config {
bat_charge_limit: self.bat_charge_limit,
}
}
}
#[derive(Deserialize, Serialize)]
pub struct ConfigV372 {
pub gfx_mode: GfxVendors,
/// Only for informational purposes.
#[serde(skip)]
pub gfx_tmp_mode: Option<GfxVendors>,
pub gfx_managed: bool,
pub gfx_vfio_enable: bool,
pub active_profile: String,
pub toggle_profiles: Vec<String>,
#[serde(skip)]
pub curr_fan_mode: u8,
pub bat_charge_limit: u8,
pub power_profiles: BTreeMap<String, ProfileV317>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ProfileV317 {
pub min_percentage: u8,
pub max_percentage: u8,
pub turbo: bool,
pub fan_preset: u8,
pub fan_curve: Option<()>,
}

View File

@@ -40,19 +40,23 @@ impl GetSupported for CtrlPlatformProfile {
fn get_supported() -> Self::A { fn get_supported() -> Self::A {
if !Profile::is_platform_profile_supported() { if !Profile::is_platform_profile_supported() {
warn!(r#" warn!(
r#"
platform_profile kernel interface not found, your laptop does not support this, or the iterface is missing. platform_profile kernel interface not found, your laptop does not support this, or the iterface is missing.
To enable profile support you require a kernel with the following patch applied: To enable profile support you require a kernel with the following patch applied:
https://lkml.org/lkml/2021/8/18/1022 https://lkml.org/lkml/2021/8/18/1022
"#); "#
);
} }
if !FanCurves::is_fan_curves_supported() { if !FanCurves::is_fan_curves_supported() {
info!(r#" info!(
r#"
fan curves kernel interface not found, your laptop does not support this, or the iterface is missing. fan curves kernel interface not found, your laptop does not support this, or the iterface is missing.
To enable fan-curve support you require a kernel with the following patch applied: To enable fan-curve support you require a kernel with the following patch applied:
https://lkml.org/lkml/2021/8/20/232 https://lkml.org/lkml/2021/8/20/232
Please note that as of 24/08/2021 this is not final. Please note that as of 24/08/2021 this is not final.
"#); "#
);
} }
PlatformProfileFunctions { PlatformProfileFunctions {
platform_profile: Profile::is_platform_profile_supported(), platform_profile: Profile::is_platform_profile_supported(),

View File

@@ -1,5 +1,6 @@
use daemon::ctrl_anime::config::AnimeConfig; use daemon::ctrl_anime::config::AnimeConfig;
use daemon::ctrl_anime::zbus::CtrlAnimeZbus; use daemon::ctrl_anime::zbus::CtrlAnimeZbus;
use daemon::ctrl_anime::*;
use daemon::ctrl_aura::config::AuraConfig; use daemon::ctrl_aura::config::AuraConfig;
use daemon::ctrl_aura::controller::{ use daemon::ctrl_aura::controller::{
CtrlKbdLed, CtrlKbdLedReloader, CtrlKbdLedTask, CtrlKbdLedZbus, CtrlKbdLed, CtrlKbdLedReloader, CtrlKbdLedTask, CtrlKbdLedZbus,
@@ -10,15 +11,11 @@ use daemon::ctrl_profiles::controller::CtrlPlatformTask;
use daemon::{ use daemon::{
config::Config, ctrl_supported::SupportedFunctions, laptops::print_board_info, GetSupported, config::Config, ctrl_supported::SupportedFunctions, laptops::print_board_info, GetSupported,
}; };
use daemon::{ctrl_anime::*};
use daemon::{ use daemon::{
ctrl_profiles::{controller::CtrlPlatformProfile, zbus::ProfileZbus}, ctrl_profiles::{controller::CtrlPlatformProfile, zbus::ProfileZbus},
laptops::LaptopLedData, laptops::LaptopLedData,
}; };
use supergfxctl::config::GfxConfig;
use supergfxctl::controller::CtrlGraphics;
use supergfxctl::gfx_vendors::GfxVendors;
use ::zbus::{fdo, Connection, ObjectServer}; use ::zbus::{fdo, Connection, ObjectServer};
use daemon::{CtrlTask, Reloadable, ZbusAdd}; use daemon::{CtrlTask, Reloadable, ZbusAdd};
use log::LevelFilter; use log::LevelFilter;
@@ -34,7 +31,6 @@ use daemon::ctrl_rog_bios::CtrlRogBios;
use zvariant::ObjectPath; use zvariant::ObjectPath;
static PROFILE_CONFIG_PATH: &str = "/etc/asusd/profile.conf"; static PROFILE_CONFIG_PATH: &str = "/etc/asusd/profile.conf";
static GFX_CONFIG_PATH: &str = "/etc/asusd/supergfx.conf";
pub fn main() -> Result<(), Box<dyn std::error::Error>> { pub fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut logger = env_logger::Builder::new(); let mut logger = env_logger::Builder::new();
@@ -86,10 +82,6 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
let config = Config::load(); let config = Config::load();
let config = Arc::new(Mutex::new(config)); let config = Arc::new(Mutex::new(config));
let gfx_config = GfxConfig::load(GFX_CONFIG_PATH.into());
let enable_gfx_switching = gfx_config.gfx_managed;
let gfx_config = Arc::new(Mutex::new(gfx_config));
supported.add_to_server(&mut object_server); supported.add_to_server(&mut object_server);
match CtrlRogBios::new(config.clone()) { match CtrlRogBios::new(config.clone()) {
@@ -105,7 +97,7 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
} }
} }
match CtrlCharge::new(config.clone()) { match CtrlCharge::new(config) {
Ok(mut ctrl) => { Ok(mut ctrl) => {
// Do a reload of any settings // Do a reload of any settings
ctrl.reload() ctrl.reload()
@@ -173,48 +165,6 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
} }
} }
// Graphics switching requires some checks on boot specifically for g-sync capable laptops
if enable_gfx_switching {
match CtrlGraphics::new(gfx_config.clone()) {
Ok(mut ctrl) => {
// 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(config) = gfx_config.lock() {
if ded == 1 {
warn!("Dedicated GFX toggle is on but driver mode is not nvidia \nSetting to nvidia driver mode");
let devices = ctrl.devices();
let bus = ctrl.bus();
CtrlGraphics::do_mode_setup_tasks(
GfxVendors::Nvidia,
false,
&devices,
&bus,
)?;
} else if ded == 0 {
info!("Dedicated GFX toggle is off");
let devices = ctrl.devices();
let bus = ctrl.bus();
CtrlGraphics::do_mode_setup_tasks(
config.gfx_mode,
false,
&devices,
&bus,
)?;
}
}
}
}
ctrl.reload()
.unwrap_or_else(|err| error!("Gfx controller: {}", err));
ctrl.add_to_server(&mut object_server);
}
Err(err) => {
error!("Gfx control: {}", err);
}
}
}
// TODO: implement messaging between threads to check fails // TODO: implement messaging between threads to check fails
// Run tasks // Run tasks

View File

@@ -1,6 +1,4 @@
use rog_profiles::error::ProfileError; use rog_profiles::error::ProfileError;
use rog_types::error::GraphicsError;
use supergfxctl::error::GfxError;
use std::convert::From; use std::convert::From;
use std::fmt; use std::fmt;
@@ -19,7 +17,6 @@ pub enum RogError {
MissingFunction(String), MissingFunction(String),
MissingLedBrightNode(String, std::io::Error), MissingLedBrightNode(String, std::io::Error),
ReloadFail(String), ReloadFail(String),
GfxSwitching(GfxError),
Profiles(ProfileError), Profiles(ProfileError),
Initramfs(String), Initramfs(String),
Modprobe(String), Modprobe(String),
@@ -44,7 +41,6 @@ impl fmt::Display for RogError {
RogError::MissingFunction(deets) => write!(f, "Missing functionality: {}", 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::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), RogError::ReloadFail(deets) => write!(f, "Task error: {}", deets),
RogError::GfxSwitching(deets) => write!(f, "Graphics switching error: {}", deets),
RogError::Profiles(deets) => write!(f, "Profile error: {}", deets), RogError::Profiles(deets) => write!(f, "Profile error: {}", deets),
RogError::Initramfs(detail) => write!(f, "Initiramfs error: {}", detail), RogError::Initramfs(detail) => write!(f, "Initiramfs error: {}", detail),
RogError::Modprobe(detail) => write!(f, "Modprobe error: {}", detail), RogError::Modprobe(detail) => write!(f, "Modprobe error: {}", detail),
@@ -56,15 +52,6 @@ impl fmt::Display for RogError {
impl std::error::Error for RogError {} impl std::error::Error for RogError {}
impl From<GraphicsError> for RogError {
fn from(err: GraphicsError) -> Self {
match err {
GraphicsError::ParseVendor => RogError::GfxSwitching(GfxError::ParseVendor),
GraphicsError::ParsePower => RogError::GfxSwitching(GfxError::ParsePower),
}
}
}
impl From<ProfileError> for RogError { impl From<ProfileError> for RogError {
fn from(err: ProfileError) -> Self { fn from(err: ProfileError) -> Self {
RogError::Profiles(err) RogError::Profiles(err)

View File

@@ -1,7 +1,6 @@
#![deny(unused_must_use)] #![deny(unused_must_use)]
/// Configuration loading, saving /// Configuration loading, saving
pub mod config; pub mod config;
pub(crate) mod config_old;
/// Control of AniMe matrix display /// Control of AniMe matrix display
pub mod ctrl_anime; pub mod ctrl_anime;
/// Keyboard LED brightness control, RGB, and LED display modes /// Keyboard LED brightness control, RGB, and LED display modes

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

BIN
data/anime/asus/music/Diamond.gif Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

BIN
data/anime/asus/trend/Hero.gif Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

View File

@@ -1,10 +1,10 @@
pub static DBUS_NAME: &str = "org.asuslinux.Daemon"; pub static DBUS_NAME: &str = "org.asuslinux.Daemon";
pub static DBUS_NAME_GFX: &str = "org.supergfxctl.Daemon";
pub static DBUS_PATH: &str = "/org/asuslinux/Daemon"; pub static DBUS_PATH: &str = "/org/asuslinux/Daemon";
pub static DBUS_IFACE: &str = "org.asuslinux.Daemon"; pub static DBUS_IFACE: &str = "org.asuslinux.Daemon";
pub mod zbus_anime; pub mod zbus_anime;
pub mod zbus_charge; pub mod zbus_charge;
pub mod zbus_gfx;
pub mod zbus_led; pub mod zbus_led;
pub mod zbus_profile; pub mod zbus_profile;
pub mod zbus_rogbios; pub mod zbus_rogbios;
@@ -13,7 +13,6 @@ pub mod zbus_supported;
use rog_anime::AnimePowerStates; use rog_anime::AnimePowerStates;
use rog_aura::{AuraEffect, LedPowerStates}; use rog_aura::{AuraEffect, LedPowerStates};
use rog_profiles::Profile; use rog_profiles::Profile;
use supergfxctl::gfx_vendors::{GfxRequiredUserAction, GfxVendors};
use std::sync::mpsc::{channel, Receiver}; use std::sync::mpsc::{channel, Receiver};
use zbus::{Connection, Result, SignalReceiver}; use zbus::{Connection, Result, SignalReceiver};
@@ -21,7 +20,6 @@ pub static VERSION: &str = env!("CARGO_PKG_VERSION");
pub struct DbusProxies<'a> { pub struct DbusProxies<'a> {
anime: zbus_anime::AnimeProxy<'a>, anime: zbus_anime::AnimeProxy<'a>,
charge: zbus_charge::ChargeProxy<'a>, charge: zbus_charge::ChargeProxy<'a>,
gfx: zbus_gfx::GfxProxy<'a>,
led: zbus_led::LedProxy<'a>, led: zbus_led::LedProxy<'a>,
profile: zbus_profile::ProfileProxy<'a>, profile: zbus_profile::ProfileProxy<'a>,
rog_bios: zbus_rogbios::RogBiosProxy<'a>, rog_bios: zbus_rogbios::RogBiosProxy<'a>,
@@ -38,7 +36,6 @@ impl<'a> DbusProxies<'a> {
anime: zbus_anime::AnimeProxy::new(&conn)?, anime: zbus_anime::AnimeProxy::new(&conn)?,
led: zbus_led::LedProxy::new(&conn)?, led: zbus_led::LedProxy::new(&conn)?,
charge: zbus_charge::ChargeProxy::new(&conn)?, charge: zbus_charge::ChargeProxy::new(&conn)?,
gfx: zbus_gfx::GfxProxy::new(&conn)?,
profile: zbus_profile::ProfileProxy::new(&conn)?, profile: zbus_profile::ProfileProxy::new(&conn)?,
rog_bios: zbus_rogbios::RogBiosProxy::new(&conn)?, rog_bios: zbus_rogbios::RogBiosProxy::new(&conn)?,
supported: zbus_supported::SupportProxy::new(&conn)?, supported: zbus_supported::SupportProxy::new(&conn)?,
@@ -52,7 +49,6 @@ impl<'a> DbusProxies<'a> {
recv.receive_for(self.anime.proxy()); recv.receive_for(self.anime.proxy());
recv.receive_for(self.led.proxy()); recv.receive_for(self.led.proxy());
recv.receive_for(self.charge.proxy()); recv.receive_for(self.charge.proxy());
recv.receive_for(self.gfx.proxy());
recv.receive_for(self.profile.proxy()); recv.receive_for(self.profile.proxy());
recv.receive_for(self.rog_bios.proxy()); recv.receive_for(self.rog_bios.proxy());
recv.receive_for(self.supported.proxy()); recv.receive_for(self.supported.proxy());
@@ -67,10 +63,6 @@ impl<'a> DbusProxies<'a> {
&self.charge &self.charge
} }
pub fn gfx(&self) -> &zbus_gfx::GfxProxy<'a> {
&self.gfx
}
pub fn led(&self) -> &zbus_led::LedProxy<'a> { pub fn led(&self) -> &zbus_led::LedProxy<'a> {
&self.led &self.led
} }
@@ -90,8 +82,6 @@ impl<'a> DbusProxies<'a> {
// Signals separated out // Signals separated out
pub struct Signals { pub struct Signals {
pub gfx_vendor: Receiver<GfxVendors>,
pub gfx_action: Receiver<GfxRequiredUserAction>,
pub profile: Receiver<Profile>, pub profile: Receiver<Profile>,
pub led_mode: Receiver<AuraEffect>, pub led_mode: Receiver<AuraEffect>,
pub led_power_state: Receiver<LedPowerStates>, pub led_power_state: Receiver<LedPowerStates>,
@@ -105,16 +95,6 @@ impl Signals {
#[inline] #[inline]
pub fn new(proxies: &DbusProxies) -> Result<Self> { pub fn new(proxies: &DbusProxies) -> Result<Self> {
Ok(Signals { Ok(Signals {
gfx_vendor: {
let (tx, rx) = channel();
proxies.gfx.connect_notify_gfx(tx)?;
rx
},
gfx_action: {
let (tx, rx) = channel();
proxies.gfx.connect_notify_action(tx)?;
rx
},
profile: { profile: {
let (tx, rx) = channel(); let (tx, rx) = channel();
proxies.profile.connect_notify_profile(tx)?; proxies.profile.connect_notify_profile(tx)?;
@@ -182,26 +162,9 @@ impl<'a> RogDbusClient<'a> {
recv.receive_for(self.proxies.anime.proxy()); recv.receive_for(self.proxies.anime.proxy());
recv.receive_for(self.proxies.led.proxy()); recv.receive_for(self.proxies.led.proxy());
recv.receive_for(self.proxies.charge.proxy()); recv.receive_for(self.proxies.charge.proxy());
recv.receive_for(self.proxies.gfx.proxy());
recv.receive_for(self.proxies.profile.proxy()); recv.receive_for(self.proxies.profile.proxy());
recv.receive_for(self.proxies.rog_bios.proxy()); recv.receive_for(self.proxies.rog_bios.proxy());
recv.receive_for(self.proxies.supported.proxy()); recv.receive_for(self.proxies.supported.proxy());
recv recv
} }
/*
* GFX
*/
pub fn gfx_wait_changed(&self) -> Result<GfxRequiredUserAction> {
loop {
if let Ok(res) = self.proxies.gfx.proxy().next_signal() {
if res.is_none() {
if let Ok(stuff) = self.signals.gfx_action.try_recv() {
return Ok(stuff);
}
// return Ok("Failed for unknown reason".to_owned());
}
}
}
}
} }

View File

@@ -1,20 +0,0 @@
use std::error::Error;
use std::fmt;
#[derive(Debug)]
pub enum GraphicsError {
ParseVendor,
ParsePower,
}
impl fmt::Display for GraphicsError {
// This trait requires `fmt` with this exact signature.
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
GraphicsError::ParseVendor => write!(f, "Could not parse vendor name"),
GraphicsError::ParsePower => write!(f, "Could not parse dGPU power status"),
}
}
}
impl Error for GraphicsError {}

View File

@@ -8,6 +8,4 @@ pub static DBUS_IFACE: &str = "org.asuslinux.Daemon";
pub mod supported; pub mod supported;
pub mod error;
pub static VERSION: &str = env!("CARGO_PKG_VERSION"); pub static VERSION: &str = env!("CARGO_PKG_VERSION");

View File

@@ -12,6 +12,26 @@ keywords = ["graphics", "nvidia", "switching"]
edition = "2018" edition = "2018"
exclude = ["data"] exclude = ["data"]
[features]
daemon = ["env_logger"]
cli = ["gumdrop"]
default = ["daemon", "cli"]
[lib]
name = "supergfxctl"
path = "src/lib.rs"
[[bin]]
name = "supergfxd"
path = "src/daemon.rs"
required-features = ["daemon"]
[[bin]]
name = "supergfxctl"
path = "src/cli.rs"
required-features = ["cli"]
default-features = ["cli"]
[dependencies] [dependencies]
serde = "^1.0" serde = "^1.0"
serde_derive = "^1.0" serde_derive = "^1.0"
@@ -23,4 +43,7 @@ zvariant = "^2.8"
zvariant_derive = "^2.8" zvariant_derive = "^2.8"
logind-zbus = "^0.7.1" logind-zbus = "^0.7.1"
sysfs-class = "^0.1.2" sysfs-class = "^0.1.2"
env_logger = { version = "^0.8", optional = true }
gumdrop = { version = "^0.8", optional = true }

74
supergfx/Makefile Normal file
View File

@@ -0,0 +1,74 @@
VERSION := $(shell grep -Pm1 'version = "(\d.\d.\d)"' daemon/Cargo.toml | cut -d'"' -f2)
INSTALL = install
INSTALL_PROGRAM = ${INSTALL} -D -m 0755
INSTALL_DATA = ${INSTALL} -D -m 0644
prefix = /usr
exec_prefix = $(prefix)
bindir = $(exec_prefix)/bin
datarootdir = $(prefix)/share
libdir = $(exec_prefix)/lib
BIN_SD := supergfxd
BIN_SC := supergfxctl
X11CFG := 90-nvidia-screen-G05.conf
PMRULES := 90-asusd-nvidia-pm.rules
SRC := Cargo.toml Cargo.lock Makefile $(shell find -type f -wholename '**/src/*.rs')
DEBUG ?= 0
ifeq ($(DEBUG),0)
ARGS += --release
TARGET = release
endif
VENDORED ?= 0
ifeq ($(VENDORED),1)
ARGS += --frozen
endif
all: build
clean:
cargo clean
distclean:
rm -rf .cargo vendor vendor.tar.xz
install:
$(INSTALL_PROGRAM) "./target/release/$(BIN_SD)" "$(DESTDIR)$(bindir)/$(BIN_SD)"
$(INSTALL_PROGRAM) "./target/release/$(BIN_SC)" "$(DESTDIR)$(bindir)/$(BIN_SC)"
$(INSTALL_DATA) "./data/$(BIN_SD).service" "$(DESTDIR)$(libdir)/systemd/system/$(BIN_SD).service"
$(INSTALL_DATA) "./data/org.supergfxctl.Daemon.conf" "$(DESTDIR)$(datarootdir)/dbus-1/system.d/org.supergfxctl.Daemon.conf"
$(INSTALL_DATA) "./data/$(X11CFG)" "$(DESTDIR)$(datarootdir)/X11/xorg.conf.d/$(X11CFG)"
$(INSTALL_DATA) "./data/$(PMRULES)" "$(DESTDIR)$(libdir)/udev/rules.d/$(PMRULES)"
uninstall:
rm -f "$(DESTDIR)$(bindir)/$(BIN_SC)"
rm -f "$(DESTDIR)$(bindir)/$(BIN_SD)"
rm -f "$(DESTDIR)$(libdir)/systemd/system/$(BIN_SD).service"
rm -f "$(DESTDIR)$(datarootdir)/dbus-1/system.d/org.supergfxctl.Daemon.conf"
rm -f "$(DESTDIR)$(datarootdir)/X11/xorg.conf.d/$(X11CFG)"
rm -f "$(DESTDIR)$(libdir)/udev/rules.d/$(PMRULES)"
update:
cargo update
vendor:
mkdir -p .cargo
cargo vendor | head -n -1 > .cargo/config
echo 'directory = "vendor"' >> .cargo/config
mv .cargo/config ./cargo-config
rm -rf .cargo
tar pcfJ vendor_asusctl_$(VERSION).tar.xz vendor
rm -rf vendor
build:
ifeq ($(VENDORED),1)
@echo "version = $(VERSION)"
tar pxf vendor_asusctl_$(VERSION).tar.xz
endif
cargo build $(ARGS)
.PHONY: all clean distclean install uninstall update build

View File

@@ -0,0 +1,26 @@
<!DOCTYPE busconfig PUBLIC
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<policy group="adm">
<allow send_destination="org.supergfxctl.Daemon"/>
<allow receive_sender="org.supergfxctl.Daemon"/>
</policy>
<policy group="sudo">
<allow send_destination="org.supergfxctl.Daemon"/>
<allow receive_sender="org.supergfxctl.Daemon"/>
</policy>
<policy group="users">
<allow send_destination="org.supergfxctl.Daemon"/>
<allow receive_sender="org.supergfxctl.Daemon"/>
</policy>
<policy group="wheel">
<allow send_destination="org.supergfxctl.Daemon"/>
<allow receive_sender="org.supergfxctl.Daemon"/>
</policy>
<policy user="root">
<allow own="org.supergfxctl.Daemon"/>
<allow send_destination="org.supergfxctl.Daemon"/>
<allow receive_sender="org.supergfxctl.Daemon"/>
</policy>
</busconfig>

View File

@@ -0,0 +1,16 @@
[Unit]
Description=SUPERGFX
StartLimitInterval=200
StartLimitBurst=2
Before=display-manager.service
[Service]
Environment=IS_SUPERGFX_SERVICE=1
ExecStart=/usr/bin/supergfxd
Restart=on-failure
Restart=always
RestartSec=1
Type=dbus
BusName=org.supergfxctl.Daemon
SELinuxContext=system_u:system_r:unconfined_t:s0
#SELinuxContext=system_u:object_r:modules_object_t:s0

105
supergfx/src/cli.rs Normal file
View File

@@ -0,0 +1,105 @@
use std::{env::args, sync::mpsc::channel};
use supergfxctl::{
gfx_vendors::{GfxRequiredUserAction, GfxVendors},
special::{get_asus_gsync_gfx_mode, has_asus_gsync_gfx_mode},
zbus_proxy::GfxProxy,
};
use gumdrop::Options;
use zbus::Connection;
#[derive(Default, Options)]
struct CliStart {
#[options(help = "print help message")]
help: bool,
#[options(
meta = "",
help = "Set graphics mode: <nvidia, hybrid, compute, integrated>"
)]
mode: Option<GfxVendors>,
#[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<dyn std::error::Error>> {
let args: Vec<String> = args().skip(1).collect();
match CliStart::parse_args_default(&args) {
Ok(command) => {
do_gfx(command)?;
}
Err(err) => {
eprintln!("source {}", err);
std::process::exit(2);
}
}
Ok(())
}
fn do_gfx(command: CliStart) -> Result<(), Box<dyn std::error::Error>> {
if command.mode.is_none() && !command.get && !command.pow && !command.force || command.help {
println!("{}", command.self_usage());
}
let conn = Connection::new_system()?;
let proxy = GfxProxy::new(&conn)?;
let (tx, rx) = channel();
proxy.connect_notify_action(tx)?;
if let Some(mode) = command.mode {
if has_asus_gsync_gfx_mode() && get_asus_gsync_gfx_mode()? == 1 {
println!("You can not change modes until you turn dedicated/G-Sync off and reboot");
std::process::exit(-1);
}
println!("If anything fails check `journalctl -b -u supergfxd`\n");
proxy.gfx_write_mode(&mode).map_err(|err|{
println!("Graphics mode change error. You may be in an invalid state.");
println!("Check mode with `-g` and switch to opposite\nmode to correct it, e.g: if integrated, switch to hybrid, or if nvidia, switch to integrated.\n");
err
})?;
loop {
proxy.next_signal()?;
if let Ok(res) = rx.try_recv() {
match res {
GfxRequiredUserAction::Integrated => {
println!(
"You must change to Integrated before you can change to {}",
<&str>::from(mode)
);
}
GfxRequiredUserAction::Logout | GfxRequiredUserAction::Reboot => {
println!(
"Graphics mode changed to {}. User action required is: {}",
<&str>::from(mode),
<&str>::from(&res)
);
}
GfxRequiredUserAction::None => {
println!("Graphics mode changed to {}", <&str>::from(mode));
}
}
}
std::process::exit(0)
}
}
if command.get {
let res = proxy.gfx_get_mode()?;
println!("Current graphics mode: {}", <&str>::from(res));
}
if command.pow {
let res = proxy.gfx_get_pwr()?;
println!("Current power status: {}", <&str>::from(&res));
}
Ok(())
}

105
supergfx/src/daemon.rs Normal file
View File

@@ -0,0 +1,105 @@
use std::{
env,
error::Error,
sync::{Arc, Mutex},
};
use log::{error, info, warn, LevelFilter};
use std::io::Write;
use supergfxctl::{
config::GfxConfig,
controller::CtrlGraphics,
error::GfxError,
gfx_vendors::GfxVendors,
special::{get_asus_gsync_gfx_mode, has_asus_gsync_gfx_mode},
DBUS_DEST_NAME, GFX_CONFIG_PATH,
};
use zbus::{fdo, Connection, ObjectServer};
pub fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut logger = env_logger::Builder::new();
logger
.target(env_logger::Target::Stdout)
.format(|buf, record| writeln!(buf, "{}: {}", record.level(), record.args()))
.filter(None, LevelFilter::Info)
.init();
let is_service = match env::var_os("IS_SUPERGFX_SERVICE") {
Some(val) => val == "1",
None => false,
};
if !is_service {
println!("supergfxd schould be only run from the right systemd service");
println!(
"do not run in your terminal, if you need an logs please use journalctl -b -u supergfxd"
);
println!("supergfxd will now exit");
return Ok(());
}
start_daemon()
}
fn start_daemon() -> Result<(), Box<dyn Error>> {
// Start zbus server
let connection = Connection::new_system()?;
fdo::DBusProxy::new(&connection)?.request_name(
DBUS_DEST_NAME,
fdo::RequestNameFlags::ReplaceExisting.into(),
)?;
let mut object_server = ObjectServer::new(&connection);
let config = GfxConfig::load(GFX_CONFIG_PATH.into());
let enable_gfx_switching = config.gfx_managed;
let config = Arc::new(Mutex::new(config));
// Graphics switching requires some checks on boot specifically for g-sync capable laptops
if enable_gfx_switching {
match CtrlGraphics::new(config.clone()) {
Ok(mut ctrl) => {
// Need to check if a laptop has the dedicated gfx switch
if has_asus_gsync_gfx_mode() {
do_asus_laptop_checks(&ctrl, config)?;
}
ctrl.reload()
.unwrap_or_else(|err| error!("Gfx controller: {}", err));
ctrl.add_to_server(&mut object_server);
}
Err(err) => {
error!("Gfx control: {}", err);
}
}
}
// Loop to check errors and iterate zbus server
loop {
if let Err(err) = object_server.try_handle_next() {
error!("{}", err);
}
}
}
fn do_asus_laptop_checks(
ctrl: &CtrlGraphics,
config: Arc<Mutex<GfxConfig>>,
) -> Result<(), GfxError> {
if let Ok(ded) = get_asus_gsync_gfx_mode() {
if let Ok(config) = config.lock() {
if ded == 1 {
warn!("Dedicated GFX toggle is on but driver mode is not nvidia \nSetting to nvidia driver mode");
let devices = ctrl.devices();
let bus = ctrl.bus();
CtrlGraphics::do_mode_setup_tasks(GfxVendors::Nvidia, false, &devices, &bus)?;
} else if ded == 0 {
info!("Dedicated GFX toggle is off");
let devices = ctrl.devices();
let bus = ctrl.bus();
CtrlGraphics::do_mode_setup_tasks(config.gfx_mode, false, &devices, &bus)?;
}
}
}
Ok(())
}

View File

@@ -69,4 +69,4 @@ impl From<std::io::Error> for GfxError {
fn from(err: std::io::Error) -> Self { fn from(err: std::io::Error) -> Self {
GfxError::Io(err) GfxError::Io(err)
} }
} }

View File

@@ -1,12 +1,17 @@
pub mod error;
pub mod config; pub mod config;
pub mod gfx_vendors;
pub mod controller; pub mod controller;
pub mod system; pub mod error;
pub mod gfx_vendors;
/// Special-case functions for check/read/write of key functions on unique laptops /// Special-case functions for check/read/write of key functions on unique laptops
/// such as the G-Sync mode available on some ASUS ROG laptops /// such as the G-Sync mode available on some ASUS ROG laptops
pub(crate) mod special; pub mod special;
pub mod zbus; pub mod system;
pub mod zbus_iface;
pub mod zbus_proxy;
pub const GFX_CONFIG_PATH: &str = "/etc/supergfxd.conf";
pub const DBUS_DEST_NAME: &str = "org.supergfxctl.Daemon";
pub const DBUS_IFACE_PATH: &str = "/org/supergfxctl/Gfx";
const NVIDIA_DRIVERS: [&str; 4] = ["nvidia_drm", "nvidia_modeset", "nvidia_uvm", "nvidia"]; const NVIDIA_DRIVERS: [&str; 4] = ["nvidia_drm", "nvidia_modeset", "nvidia_uvm", "nvidia"];

View File

@@ -5,11 +5,11 @@ use crate::error::GfxError;
static ASUS_SWITCH_GRAPHIC_MODE: &str = static ASUS_SWITCH_GRAPHIC_MODE: &str =
"/sys/firmware/efi/efivars/AsusSwitchGraphicMode-607005d5-3f75-4b2e-98f0-85ba66797a3e"; "/sys/firmware/efi/efivars/AsusSwitchGraphicMode-607005d5-3f75-4b2e-98f0-85ba66797a3e";
pub(crate) fn has_asus_gsync_gfx_mode() -> bool { pub fn has_asus_gsync_gfx_mode() -> bool {
Path::new(ASUS_SWITCH_GRAPHIC_MODE).exists() Path::new(ASUS_SWITCH_GRAPHIC_MODE).exists()
} }
pub(crate) fn get_asus_gsync_gfx_mode() -> Result<i8, GfxError> { pub fn get_asus_gsync_gfx_mode() -> Result<i8, GfxError> {
let path = ASUS_SWITCH_GRAPHIC_MODE; let path = ASUS_SWITCH_GRAPHIC_MODE;
let mut file = OpenOptions::new() let mut file = OpenOptions::new()
.read(true) .read(true)
@@ -22,4 +22,4 @@ pub(crate) fn get_asus_gsync_gfx_mode() -> Result<i8, GfxError> {
let idx = data.len() - 1; let idx = data.len() - 1;
Ok(data[idx] as i8) Ok(data[idx] as i8)
} }

View File

@@ -1,12 +1,15 @@
use ::zbus::dbus_interface;
use log::{error, info, warn}; use log::{error, info, warn};
use zvariant::ObjectPath; use zvariant::ObjectPath;
use ::zbus::dbus_interface;
use crate::gfx_vendors::{GfxPower, GfxRequiredUserAction, GfxVendors}; use crate::{
gfx_vendors::{GfxPower, GfxRequiredUserAction, GfxVendors},
DBUS_IFACE_PATH,
};
use super::controller::CtrlGraphics; use super::controller::CtrlGraphics;
#[dbus_interface(name = "org.asuslinux.Daemon")] #[dbus_interface(name = "org.supergfxctl.Daemon")]
impl CtrlGraphics { impl CtrlGraphics {
fn vendor(&self) -> zbus::fdo::Result<GfxVendors> { fn vendor(&self) -> zbus::fdo::Result<GfxVendors> {
self.get_gfx_mode().map_err(|err| { self.get_gfx_mode().map_err(|err| {
@@ -28,10 +31,13 @@ impl CtrlGraphics {
error!("GFX: {}", err); error!("GFX: {}", err);
zbus::fdo::Error::Failed(format!("GFX fail: {}", err)) zbus::fdo::Error::Failed(format!("GFX fail: {}", err))
})?; })?;
self.notify_gfx(&vendor)
.unwrap_or_else(|err| warn!("GFX: {}", err));
self.notify_action(&msg) self.notify_action(&msg)
.unwrap_or_else(|err| warn!("GFX: {}", err)); .unwrap_or_else(|err| warn!("GFX: {}", err));
self.notify_gfx(&vendor)
.unwrap_or_else(|err| warn!("GFX: {}", err));
Ok(msg) Ok(msg)
} }
@@ -45,7 +51,7 @@ impl CtrlGraphics {
impl CtrlGraphics { impl CtrlGraphics {
pub fn add_to_server(self, server: &mut zbus::ObjectServer) { pub fn add_to_server(self, server: &mut zbus::ObjectServer) {
server server
.at(&ObjectPath::from_str_unchecked("/org/asuslinux/Gfx"), self) .at(&ObjectPath::from_str_unchecked(DBUS_IFACE_PATH), self)
.map_err(|err| { .map_err(|err| {
warn!("GFX: CtrlGraphics: add_to_server {}", err); warn!("GFX: CtrlGraphics: add_to_server {}", err);
err err

View File

@@ -1,7 +1,7 @@
//! # DBus interface proxy for: `org.asuslinux.Gfx` //! # DBus interface proxy for: `org.asuslinux.Gfx`
//! //!
//! This code was generated by `zbus-xmlgen` `1.0.0` from DBus introspection data. //! This code was generated by `zbus-xmlgen` `1.0.0` from DBus introspection data.
//! Source: `Interface '/org/asuslinux/Gfx' from service 'org.asuslinux.Daemon' on system bus`. //! Source: `Interface '/org/supergfxctl/Gfx' from service 'org.asuslinux.Daemon' on system bus`.
//! //!
//! You may prefer to adapt it, instead of using it verbatim. //! You may prefer to adapt it, instead of using it verbatim.
//! //!
@@ -19,15 +19,16 @@
//! //!
//! …consequently `zbus-xmlgen` did not generate code for the above interfaces. //! …consequently `zbus-xmlgen` did not generate code for the above interfaces.
use std::sync::mpsc::Sender; use std::sync::mpsc::{Receiver, Sender};
use supergfxctl::gfx_vendors::{GfxPower, GfxRequiredUserAction, GfxVendors}; use zbus::{dbus_proxy, Connection, Message, Result};
use zbus::{dbus_proxy, Connection, Result};
#[dbus_proxy( use crate::{
interface = "org.asuslinux.Daemon", gfx_vendors::{GfxPower, GfxRequiredUserAction, GfxVendors},
default_path = "/org/asuslinux/Gfx" DBUS_IFACE_PATH,
)] };
#[dbus_proxy(interface = "org.supergfxctl.Daemon")]
trait Daemon { trait Daemon {
/// Power method /// Power method
fn power(&self) -> zbus::Result<GfxPower>; fn power(&self) -> zbus::Result<GfxPower>;
@@ -47,12 +48,25 @@ trait Daemon {
fn notify_gfx(&self, vendor: GfxVendors) -> zbus::Result<()>; fn notify_gfx(&self, vendor: GfxVendors) -> zbus::Result<()>;
} }
pub struct GfxProxy<'a>(DaemonProxy<'a>); pub struct GfxProxy<'a>(pub DaemonProxy<'a>);
impl<'a> GfxProxy<'a> { impl<'a> GfxProxy<'a> {
#[inline] #[inline]
pub fn new(conn: &Connection) -> Result<Self> { pub fn new(conn: &Connection) -> Result<Self> {
Ok(GfxProxy(DaemonProxy::new(conn)?)) let proxy = DaemonProxy::new_for(conn, "org.supergfxctl.Daemon", DBUS_IFACE_PATH)?;
Ok(GfxProxy(proxy))
}
#[inline]
pub fn new_for(conn: &Connection, destination: &'a str, path: &'a str) -> Result<Self> {
let proxy = DaemonProxy::new_for(conn, destination, path)?;
Ok(GfxProxy(proxy))
}
#[inline]
pub fn new_for_owned(conn: Connection, destination: String, path: String) -> Result<Self> {
let proxy = DaemonProxy::new_for_owned(conn, destination, path)?;
Ok(GfxProxy(proxy))
} }
#[inline] #[inline]
@@ -95,4 +109,9 @@ impl<'a> GfxProxy<'a> {
Ok(()) Ok(())
}) })
} }
#[inline]
pub fn next_signal(&self) -> Result<Option<Message>> {
self.0.next_signal()
}
} }