mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-01-22 17:33:19 +01:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b3a555cab9 | ||
|
|
cf13b4f71b |
11
CHANGELOG.md
11
CHANGELOG.md
@@ -6,6 +6,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
# [2.2.1] - 2021-01-27
|
||||
### Added
|
||||
- Add ROG Zephyrus M15 LED config
|
||||
### Changed
|
||||
- Bugfixes
|
||||
- Fix reboot/restartx status for GFX switching
|
||||
- Update readme
|
||||
- Change CLI arg tag for fan modes
|
||||
- Make dracut include the nvidia modules in initramfs
|
||||
|
||||
# [2.2.0] - 2021-01-26
|
||||
### Added
|
||||
- Dbus command to fetch all supported functions of the laptop. That is, all the
|
||||
@@ -13,7 +23,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- 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`
|
||||
|
||||
4
Cargo.lock
generated
4
Cargo.lock
generated
@@ -29,7 +29,7 @@ checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
|
||||
|
||||
[[package]]
|
||||
name = "asus-nb"
|
||||
version = "2.2.0"
|
||||
version = "2.2.1"
|
||||
dependencies = [
|
||||
"dbus",
|
||||
"gumdrop",
|
||||
@@ -45,7 +45,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "asus-nb-ctrl"
|
||||
version = "2.2.0"
|
||||
version = "2.2.1"
|
||||
dependencies = [
|
||||
"asus-nb",
|
||||
"env_logger",
|
||||
|
||||
13
README.md
13
README.md
@@ -7,6 +7,10 @@ but can also be used with non-asus laptops with reduced features.
|
||||
|
||||
This app is developed and tested on fedora only. Support is not provided for Arch or Arch based distros.
|
||||
|
||||
**NOTICE:**
|
||||
The following is *not* required for 5.11 kernel versions, as this version includes
|
||||
all the required patches.
|
||||
---
|
||||
This program requires the kernel patch [here](https://www.spinics.net/lists/linux-input/msg68977.html) to be applied.
|
||||
Alternatively you may use the dkms module for 'hid-asus-rog` from one of the
|
||||
repositories [here](https://download.opensuse.org/repositories/home:/luke_nukem:/asus/).
|
||||
@@ -53,13 +57,17 @@ will probably suffer another rename once it becomes generic enough to do so.
|
||||
- [X] Set battery charge limit (with kernel supporting this)
|
||||
- [X] Fancy fan control on G14 + G15 thanks to @Yarn1
|
||||
- [X] Graphics mode switching between iGPU, dGPU, and On-Demand
|
||||
- [X] Toggle bios setting for boot/POST sound
|
||||
- [X] Toggle bios setting for "dedicated gfx" mode on supported laptops (g-sync)
|
||||
|
||||
# FUNCTIONS
|
||||
|
||||
## 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.
|
||||
in the config with `"manage_gfx": false,`. Additionally there is an extra setting
|
||||
for laptops capable of g-sync dedicated gfx mode to enable the graphics switching
|
||||
to switch on dedicated gfx for "nvidia" mode.
|
||||
|
||||
The CLI option for this does not require root until it asks for it, and provides
|
||||
instructions.
|
||||
@@ -79,7 +87,8 @@ If you have installed the Nvidia driver manually you will require the
|
||||
### 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.
|
||||
to stop dracut including the nvidia modules in the ramdisk. This is espeically
|
||||
true if you manually installed the nvidia drivers.
|
||||
|
||||
```
|
||||
# filename /etc/dracut.conf.d/90-nvidia-dracut-G05.conf
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "asus-nb-ctrl"
|
||||
version = "2.2.0"
|
||||
version = "2.2.1"
|
||||
license = "MPL-2.0"
|
||||
readme = "README.md"
|
||||
authors = ["Luke <luke@ljones.dev>"]
|
||||
|
||||
@@ -132,7 +132,7 @@ impl crate::ZbusAdd for DbusFanAndCpu {
|
||||
server
|
||||
.at(&"/org/asuslinux/Profile".try_into().unwrap(), self)
|
||||
.map_err(|err| {
|
||||
warn!("DbusFanAndCpu: {}", err);
|
||||
warn!("DbusFanAndCpu: add_to_server {}", err);
|
||||
err
|
||||
})
|
||||
.ok();
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
use std::error;
|
||||
use std::fmt;
|
||||
|
||||
use crate::error::RogError;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum GfxError {
|
||||
ParseVendor,
|
||||
@@ -28,3 +30,9 @@ impl fmt::Display for GfxError {
|
||||
}
|
||||
|
||||
impl error::Error for GfxError {}
|
||||
|
||||
impl From<GfxError> for RogError {
|
||||
fn from(err: GfxError) -> Self {
|
||||
RogError::GfxSwitching(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ 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 std::{sync::Arc, sync::Mutex};
|
||||
use sysfs_class::{PciDevice, SysClass};
|
||||
use system::{GraphicsDevice, Module, PciBus};
|
||||
use vendors::{GfxCtrlAction, GfxVendors};
|
||||
@@ -66,6 +66,31 @@ impl Dbus for CtrlGraphics {
|
||||
fn notify_action(&self, action: &str) -> zbus::Result<()> {}
|
||||
}
|
||||
|
||||
impl ZbusAdd for CtrlGraphics {
|
||||
fn add_to_server(self, server: &mut zbus::ObjectServer) {
|
||||
server
|
||||
.at(
|
||||
&"/org/asuslinux/Gfx"
|
||||
.try_into()
|
||||
.expect("Couldn't add to zbus"),
|
||||
self,
|
||||
)
|
||||
.map_err(|err| {
|
||||
warn!("CtrlGraphics: add_to_server {}", err);
|
||||
err
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
|
||||
impl Reloadable for CtrlGraphics {
|
||||
fn reload(&mut self) -> Result<(), RogError> {
|
||||
self.auto_power()?;
|
||||
info!("Reloaded gfx mode: {:?}", CtrlGraphics::get_vendor()?);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl CtrlGraphics {
|
||||
pub fn new(config: Arc<Mutex<Config>>) -> std::io::Result<CtrlGraphics> {
|
||||
let bus = PciBus::new()?;
|
||||
@@ -125,13 +150,12 @@ 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,
|
||||
@@ -144,26 +168,7 @@ impl CtrlGraphics {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn add_to_server(self, server: &mut zbus::ObjectServer) {
|
||||
server
|
||||
.at(
|
||||
&"/org/asuslinux/Gfx".try_into().expect("Some fail here"),
|
||||
self,
|
||||
)
|
||||
.map_err(|err| {
|
||||
warn!("CtrlGraphics: add_to_server {}", err);
|
||||
err
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
|
||||
pub fn reload(&mut self) -> Result<(), Box<dyn Error>> {
|
||||
self.auto_power()?;
|
||||
info!("Reloaded gfx mode: {:?}", CtrlGraphics::get_vendor()?);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_prime_discrete() -> Result<String, GfxError> {
|
||||
fn get_prime_discrete() -> Result<String, RogError> {
|
||||
let s = std::fs::read_to_string(PRIME_DISCRETE_PATH)
|
||||
.map_err(|err| GfxError::Read(PRIME_DISCRETE_PATH.into(), err))?
|
||||
.trim()
|
||||
@@ -171,14 +176,14 @@ impl CtrlGraphics {
|
||||
Ok(s)
|
||||
}
|
||||
|
||||
fn set_prime_discrete(mode: &str) -> Result<(), GfxError> {
|
||||
fn set_prime_discrete(mode: &str) -> Result<(), RogError> {
|
||||
std::fs::write(PRIME_DISCRETE_PATH, mode)
|
||||
.map_err(|err| GfxError::Read(PRIME_DISCRETE_PATH.into(), err))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Associated method to get which vendor mode is set
|
||||
pub fn get_vendor() -> Result<String, GfxError> {
|
||||
pub fn get_vendor() -> Result<String, RogError> {
|
||||
let mode = match Self::get_prime_discrete() {
|
||||
Ok(m) => m,
|
||||
Err(_) => "nvidia".to_string(),
|
||||
@@ -214,14 +219,32 @@ impl CtrlGraphics {
|
||||
Ok(vendor)
|
||||
}
|
||||
|
||||
pub fn is_switching_prime_modes(vendor: &GfxVendors) -> Result<bool, GfxError> {
|
||||
fn is_switching_prime_modes(&self, vendor: &GfxVendors) -> Result<bool, RogError> {
|
||||
let prev_mode = GfxVendors::from_str(&Self::get_vendor()?)?;
|
||||
let x = (prev_mode == GfxVendors::Hybrid || prev_mode == GfxVendors::Nvidia)
|
||||
&& (*vendor == GfxVendors::Hybrid || *vendor == GfxVendors::Nvidia);
|
||||
Ok(x)
|
||||
if prev_mode == GfxVendors::Integrated
|
||||
&& (*vendor == GfxVendors::Hybrid || *vendor == GfxVendors::Nvidia)
|
||||
{
|
||||
return Ok(true);
|
||||
}
|
||||
if (prev_mode == GfxVendors::Hybrid || prev_mode == GfxVendors::Nvidia)
|
||||
&& *vendor == GfxVendors::Integrated
|
||||
{
|
||||
return Ok(true);
|
||||
}
|
||||
if let Ok(config) = self.config.clone().try_lock() {
|
||||
if CtrlRogBios::has_dedicated_gfx_toggle() && config.gfx_nv_mode_is_dedicated {
|
||||
if prev_mode == GfxVendors::Hybrid && *vendor == GfxVendors::Nvidia {
|
||||
return Ok(true);
|
||||
}
|
||||
if *vendor == GfxVendors::Hybrid && prev_mode == GfxVendors::Nvidia {
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
pub fn set_gfx_config(vendor: GfxVendors) -> Result<(), GfxError> {
|
||||
pub fn set_gfx_config(vendor: GfxVendors) -> Result<(), RogError> {
|
||||
let mode = if vendor == GfxVendors::Hybrid {
|
||||
"on-demand\n"
|
||||
} else if vendor == GfxVendors::Nvidia {
|
||||
@@ -305,7 +328,11 @@ impl CtrlGraphics {
|
||||
}
|
||||
|
||||
/// Write out config files if required, enable/disable relevant services, and update the ramdisk
|
||||
pub fn set(&mut self, vendor: GfxVendors) -> Result<String, GfxError> {
|
||||
fn set(&mut self, vendor: GfxVendors) -> Result<String, RogError> {
|
||||
// Switching from hybrid to/from nvidia shouldn't require a ramdisk update
|
||||
// or a reboot.
|
||||
let reboot = self.is_switching_prime_modes(&vendor)?;
|
||||
|
||||
if CtrlRogBios::has_dedicated_gfx_toggle() {
|
||||
if let Ok(config) = self.config.clone().try_lock() {
|
||||
// Switch to dedicated if config says to do so
|
||||
@@ -322,40 +349,44 @@ impl CtrlGraphics {
|
||||
}
|
||||
}
|
||||
|
||||
// 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)?;
|
||||
Self::set_gfx_config(vendor.clone())?;
|
||||
|
||||
let mut required_action = GfxCtrlAction::None;
|
||||
if !no_reboot {
|
||||
if reboot {
|
||||
info!("Updating initramfs");
|
||||
if let Some(cmd) = self.initfs_cmd.as_mut() {
|
||||
// If switching to Nvidia dedicated we need these modules included
|
||||
if Path::new(DRACUT_PATH).exists() && vendor == GfxVendors::Nvidia {
|
||||
cmd.arg("--add-drivers");
|
||||
cmd.arg("nvidia nvidia-drm nvidia-modeset nvidia-uvm");
|
||||
info!("System uses dracut, forcing nvidia modules to be included in init");
|
||||
}
|
||||
|
||||
let status = cmd
|
||||
.status()
|
||||
.map_err(|err| GfxError::Write(format!("{:?}", cmd), err))?;
|
||||
if !status.success() {
|
||||
error!("Ram disk update failed");
|
||||
return Ok("Ram disk update failed".into());
|
||||
} else {
|
||||
info!("Successfully updated iniramfs");
|
||||
}
|
||||
}
|
||||
required_action = GfxCtrlAction::Reboot;
|
||||
} else if no_reboot {
|
||||
} else if !reboot {
|
||||
required_action = GfxCtrlAction::RestartX;
|
||||
}
|
||||
|
||||
Ok(required_action.into())
|
||||
}
|
||||
|
||||
pub fn get_runtime_status() -> Result<String, GfxError> {
|
||||
fn get_runtime_status() -> Result<String, RogError> {
|
||||
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> {
|
||||
fn set_power(&self, power: bool) -> Result<(), RogError> {
|
||||
if power {
|
||||
info!("Enabling graphics power");
|
||||
self.bus
|
||||
@@ -377,7 +408,7 @@ impl CtrlGraphics {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn auto_power(&self) -> Result<(), GfxError> {
|
||||
fn auto_power(&self) -> Result<(), RogError> {
|
||||
let vendor = CtrlGraphics::get_vendor()?;
|
||||
self.set_power(vendor != "integrated")
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ use asus_nb::{
|
||||
fancy::KeyColourArray,
|
||||
LED_MSG_LEN,
|
||||
};
|
||||
use log::{info, warn};
|
||||
use log::{error, info, warn};
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::{Read, Write};
|
||||
use std::sync::Arc;
|
||||
@@ -91,6 +91,9 @@ impl crate::ZbusAdd for DbusKbdBacklight {
|
||||
fn add_to_server(self, server: &mut zbus::ObjectServer) {
|
||||
server
|
||||
.at(&"/org/asuslinux/Led".try_into().unwrap(), self)
|
||||
.map_err(|err| {
|
||||
error!("DbusKbdBacklight: add_to_server {}", err);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
@@ -281,8 +284,16 @@ impl CtrlKbdBacklight {
|
||||
let ctrl = CtrlKbdBacklight {
|
||||
// Using `ok` here so we can continue without keyboard features but
|
||||
// still get brightness control at least... maybe...
|
||||
led_node: Self::get_node_failover(id_product, None, Self::scan_led_node).ok(),
|
||||
kbd_node: Self::get_node_failover(id_product, condev_iface, Self::scan_kbd_node).ok(),
|
||||
led_node: Some(Self::get_node_failover(
|
||||
id_product,
|
||||
None,
|
||||
Self::scan_led_node,
|
||||
)?),
|
||||
kbd_node: Some(Self::get_node_failover(
|
||||
id_product,
|
||||
condev_iface,
|
||||
Self::scan_kbd_node,
|
||||
)?),
|
||||
// TODO: Check for existance
|
||||
bright_node: Self::get_kbd_bright_path()?.to_owned(),
|
||||
supported_modes,
|
||||
|
||||
@@ -112,7 +112,7 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
|
||||
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)?;
|
||||
CtrlGraphics::set_gfx_config(GfxVendors::Nvidia)?;
|
||||
} else if ded == 0 {
|
||||
info!("Dedicated GFX toggle is off");
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ use rog_fan_curve::CurveError;
|
||||
use std::convert::From;
|
||||
use std::fmt;
|
||||
|
||||
use crate::ctrl_gfx::error::GfxError;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum RogError {
|
||||
ParseFanLevel,
|
||||
@@ -21,6 +23,7 @@ pub enum RogError {
|
||||
MissingFunction(String),
|
||||
MissingLedBrightNode(String, std::io::Error),
|
||||
ReloadFail(String),
|
||||
GfxSwitching(GfxError),
|
||||
}
|
||||
|
||||
impl fmt::Display for RogError {
|
||||
@@ -43,6 +46,7 @@ impl fmt::Display for RogError {
|
||||
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),
|
||||
RogError::GfxSwitching(deets) => write!(f, "Graphics switching error: {}", deets),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +21,11 @@ struct CLIStart {
|
||||
show_supported: bool,
|
||||
#[options(meta = "", help = "<off, low, med, high>")]
|
||||
kbd_bright: Option<LedBrightness>,
|
||||
#[options(meta = "", help = "<silent, normal, boost>")]
|
||||
pwr_profile: Option<FanLevel>,
|
||||
#[options(
|
||||
meta = "",
|
||||
help = "<silent, normal, boost>, set fan mode independent of profile"
|
||||
)]
|
||||
fan_mode: Option<FanLevel>,
|
||||
#[options(meta = "", help = "<20-100>")]
|
||||
chg_limit: Option<u8>,
|
||||
#[options(command)]
|
||||
@@ -246,7 +249,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
None => {
|
||||
if (!parsed.show_supported
|
||||
&& parsed.kbd_bright.is_none()
|
||||
&& parsed.pwr_profile.is_none()
|
||||
&& parsed.fan_mode.is_none()
|
||||
&& parsed.chg_limit.is_none())
|
||||
|| parsed.help
|
||||
{
|
||||
@@ -272,7 +275,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("Supported laptop functions:\n{}", dat.to_string());
|
||||
}
|
||||
|
||||
if let Some(fan_level) = parsed.pwr_profile {
|
||||
if let Some(fan_level) = parsed.fan_mode {
|
||||
dbus_client.write_fan_mode(fan_level.into())?;
|
||||
}
|
||||
if let Some(chg_limit) = parsed.chg_limit {
|
||||
@@ -319,7 +322,10 @@ fn do_gfx(
|
||||
)?;
|
||||
std::process::exit(1)
|
||||
}
|
||||
_ => std::process::exit(-1),
|
||||
_ => {
|
||||
println!("{}", Red.paint(&format!("\n{}\n", res.as_str())),);
|
||||
std::process::exit(-1);
|
||||
}
|
||||
}
|
||||
std::process::exit(-1)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "asus-nb"
|
||||
version = "2.2.0"
|
||||
version = "2.2.1"
|
||||
license = "MPL-2.0"
|
||||
readme = "README.md"
|
||||
authors = ["Luke <luke@ljones.dev>"]
|
||||
|
||||
@@ -8,6 +8,11 @@ prod_family = "Zephyrus M"
|
||||
board_names = ["GU502GV"]
|
||||
led_modes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 255]
|
||||
|
||||
[[led_modes]]
|
||||
prod_family = "ROG Zephyrus M15"
|
||||
board_names = ["GU502LW"]
|
||||
led_modes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 255]
|
||||
|
||||
[[led_modes]]
|
||||
prod_family = "Zephyrus"
|
||||
board_names = ["GM501GM", "GX531"]
|
||||
|
||||
Reference in New Issue
Block a user