diff --git a/MANUAL.md b/MANUAL.md index 47cff9c7..746ce308 100644 --- a/MANUAL.md +++ b/MANUAL.md @@ -16,57 +16,15 @@ but can also be used with non-asus laptops with reduced features. The functionality that `asusd` exposes is: -- graphics switching - anime control - led keyboard control (aura) - charge limiting - bios/efivar control -- profiles (fan/cpu) +- power profile switching +- fan curves (if supported, this is auto-detected) each of these will be detailed in sections. -### Graphics switching - -`asusd` can switch graphics modes between: -- `integrated`, uses the iGPU only and force-disables the dGPU -- `compute`, enables Nvidia without Xorg. Useful for ML/Cuda -- `hybrid`, enables Nvidia prime-offload mode -- `nvidia`, uses the Nvidia gpu only -- `vfio`, binds the Nvidia gpu to vfio for VM pass-through - -Switching to/from Hybrid and Nvidia modes requires a logout only (no reboot). Switching between integrated/compute/vfio does not require a logout and is instant. - -#### Required actions in distro - -**Rebootless note:** You must edit `/etc/default/grub` to remove `nvidia-drm.modeset=1` -from the line `GRUB_CMDLINE_LINUX=` and then recreate your grub config. In fedora -you can do this with `sudo grub2-mkconfig -o /etc/grub2.cfg` - other distro may be -similar but with a different config location. It's possible that graphics driver updates -may change this. - -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/` - -#### Config options - -1. `"gfx_mode": "",`: MODE can be -2. `"gfx_last_mode": "Nvidia",`: currently unused -3. `"gfx_managed": true,`: enable or disable graphics switching controller -4. `"gfx_vfio_enable": false,`: enable vfio switching for Nvidia GPU passthrough -5. `"gfx_save_compute_vfio": false,`: wether or not to save the vfio state (so it sticks between boots) - -#### Graphics switching notes - -**G-Sync note:** Some laptops are capable of using the dGPU as the sole GPU in the system which is generally to enable g-sync on the laptop display panel. This is controlled by the bios/efivar control and will be covered in that section. - -**vfio note:** The vfio modules *must not* be compiled into the kernel, they need -to be separate modules. If you don't plan to use vfio mode then you can ignore this -otherwise you may need a custom built kernel. - ### AniMe control Controller for the fancy AniMe matrix display on the lid of some machines. This controller is a work in progress. @@ -139,55 +97,27 @@ These options are not written to the config file as they are stored in efivars. ### Profiles -Profiles provide a method setting up various basic CPU and fan settings in profile blocks which can then be switched between or cycled through. The CPU controls so far are: +asusctl can support setting a power profile via platform_profile drivers. This requires [power-profiles-daemon](https://gitlab.freedesktop.org/hadess/power-profiles-daemon) v0.9.0 minimum. It also requires the kernel patch for platform_profile support to be applied form [here](https://lkml.org/lkml/2021/8/18/1022) - this patch is included in the "rog" kernels we build for fedora and arch, and will hit kernel 5.15 upstream. -- Min/Max percentage of CPU frequency (Intel only for now) -- CPU turbo boost enable or disable -- Fan presets. These are 0: Normal, 1: Boost, 2: Silent. -- Fan curves, override fan-preset. AMD only. - -#### Config options - -Example: -```json - "toggle_profiles": [ - "normal", - "boost", - "silent" - ], - "power_profiles": { - "boost": { - "min_percentage": 0, - "max_percentage": 100, - "turbo": true, - "fan_preset": 1, - "fan_curve": null - }, - "normal": { - "min_percentage": 0, - "max_percentage": 100, - "turbo": true, - "fan_preset": 0, - "fan_curve": null - }, - "silent": { - "min_percentage": 0, - "max_percentage": 100, - "turbo": true, - "fan_preset": 2, - "fan_curve": null - } - } -``` - -1. `"toggle_profiles": [],`: these are the profile names that will be cycled through when using a provided next/prev dbus method. -2. `"power_profiles": {}`: all the available profiles. +A common use of asusctl is to bind the `fn+f5` (fan) key to `asusctl profile -n` to cycle through the 3 profiles: +1. Balanced +2. Performance +3. Quiet #### Fan curves -**fan_curve note:** This is a WIP. Currently it relies on `acpi_call` kernel module which is ancient and hacky, not intended for this purpose. A proper kernel driver is in progress. +Fan curve support requires a laptop that supports it (this is detected automatically) and the kernel patch from [here](https://lkml.org/lkml/2021/8/29/50) which is still in review as of 29/09/21. As with Profiles, this is included in the kernels we build, and will hit 5.15 kernel upstream. -See [this document](https://github.com/cronosun/atrofac/blob/master/ADVANCED.md#limits) for details on the string format required, e.g, `"fan_curve": "30c:0%,40c:5%,50c:10%,60c:20%,70c:35%,80c:55%,90c:65%,100c:65%"`. +The fan curve format can be of varying formats: + +- `30c:0%,40c:5%,50c:10%,60c:20%,70c:35%,80c:55%,90c:65%,100c:65%"` +- `30:0,40:5,50:10,60:20,70:35,80:55,90:65,100:65"` +- `30 0,40 5,50 10,60 20,70 35,80 55,90 65,100 65"` +- `30 0 40 5 50 10 60 20 70 35 80 55 90 65 100 65"` + +the order must always be the same "temperature:percentage", lowest from left to rigth being highest. + +The config file is located at `/etc/asusd/profile.conf` and is self-descriptive. On first run it is populated with the system EC defaults. ### Support controller diff --git a/asusctl/src/cli_opts.rs b/asusctl/src/cli_opts.rs new file mode 100644 index 00000000..32fcbed9 --- /dev/null +++ b/asusctl/src/cli_opts.rs @@ -0,0 +1,102 @@ +use crate::{ + anime_cli::AnimeCommand, + aura_cli::{LedBrightness, SetAuraBuiltin}, + profiles_cli::ProfileCommand, +}; +use gumdrop::Options; +use supergfxctl::gfx_vendors::GfxVendors; + +#[derive(Default, Options)] +pub struct CliStart { + #[options(help_flag, help = "print help message")] + pub help: bool, + #[options(help = "show program version number")] + pub version: bool, + #[options(help = "show supported functions of this laptop")] + pub show_supported: bool, + #[options(meta = "", help = "")] + pub kbd_bright: Option, + #[options(help = "Toggle to next keyboard brightness")] + pub next_kbd_bright: bool, + #[options(help = "Toggle to previous keyboard brightness")] + pub prev_kbd_bright: bool, + #[options(meta = "", help = "<20-100>")] + pub chg_limit: Option, + #[options(command)] + pub command: Option, +} + +#[derive(Options)] +pub 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), + #[options(name = "anime", help = "Manage AniMe Matrix")] + Anime(AnimeCommand), + #[options(help = "Change bios settings")] + Bios(BiosCommand), +} + +#[derive(Options)] +pub struct LedModeCommand { + #[options(help = "print help message")] + pub help: bool, + #[options(help = "switch to next aura mode")] + pub next_mode: bool, + #[options(help = "switch to previous aura mode")] + pub prev_mode: bool, + #[options( + meta = "", + help = "set the keyboard LED to enabled while the device is awake" + )] + pub awake_enable: Option, + #[options( + meta = "", + help = "set the keyboard LED suspend animation to enabled while the device is suspended" + )] + pub sleep_enable: Option, + #[options(command)] + pub command: Option, +} + +#[derive(Options)] +pub struct GraphicsCommand { + #[options(help = "print help message")] + pub help: bool, + #[options( + meta = "", + help = "Set graphics mode: " + )] + pub mode: Option, + #[options(help = "Get the current mode")] + pub get: bool, + #[options(help = "Get the current power status")] + pub pow: bool, + #[options(help = "Do not ask for confirmation")] + pub force: bool, +} + +#[derive(Options, Debug)] +pub struct BiosCommand { + #[options(help = "print help message")] + pub help: bool, + #[options( + meta = "", + no_long, + help = "set bios POST sound: asusctl -p " + )] + pub post_sound_set: Option, + #[options(no_long, help = "read bios POST sound")] + pub post_sound_get: bool, + #[options( + meta = "", + no_long, + help = "activate dGPU dedicated/G-Sync: asusctl -d , reboot required" + )] + pub dedicated_gfx_set: Option, + #[options(no_long, help = "get GPU mode")] + pub dedicated_gfx_get: bool, +} diff --git a/asusctl/src/main.rs b/asusctl/src/main.rs index 072a25cc..c8dc6b68 100644 --- a/asusctl/src/main.rs +++ b/asusctl/src/main.rs @@ -1,8 +1,10 @@ mod anime_cli; mod aura_cli; +mod cli_opts; mod profiles_cli; use crate::aura_cli::{LedBrightness, SetAuraBuiltin}; +use crate::cli_opts::*; use anime_cli::{AnimeActions, AnimeCommand}; use gumdrop::{Opt, Options}; use profiles_cli::ProfileCommand; @@ -16,106 +18,15 @@ use rog_supported::{ }; use std::{env::args, path::Path, sync::mpsc::channel}; use supergfxctl::{ - gfx_vendors::{GfxRequiredUserAction, GfxVendors}, + gfx_vendors::GfxRequiredUserAction, special::{get_asus_gsync_gfx_mode, has_asus_gsync_gfx_mode}, zbus_proxy::GfxProxy, }; use zbus::Connection; -#[derive(Default, Options)] -struct CliStart { - #[options(help_flag, help = "print help message")] - help: bool, - #[options(help = "show program version number")] - version: bool, - #[options(help = "show supported functions of this laptop")] - show_supported: bool, - #[options(meta = "", help = "")] - kbd_bright: Option, - #[options(help = "Toggle to next keyboard brightness")] - next_kbd_bright: bool, - #[options(help = "Toggle to previous keyboard brightness")] - prev_kbd_bright: bool, - #[options(meta = "", help = "<20-100>")] - chg_limit: Option, - #[options(command)] - command: Option, -} - -#[derive(Options)] -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), - #[options(name = "anime", help = "Manage AniMe Matrix")] - Anime(AnimeCommand), - #[options(help = "Change bios settings")] - Bios(BiosCommand), -} - -#[derive(Options)] -struct LedModeCommand { - #[options(help = "print help message")] - help: bool, - #[options(help = "switch to next aura mode")] - next_mode: bool, - #[options(help = "switch to previous aura mode")] - prev_mode: bool, - #[options( - meta = "", - help = "set the keyboard LED to enabled while the device is awake" - )] - awake_enable: Option, - #[options( - meta = "", - help = "set the keyboard LED suspend animation to enabled while the device is suspended" - )] - sleep_enable: Option, - #[options(command)] - command: Option, -} - -#[derive(Options)] -struct GraphicsCommand { - #[options(help = "print help message")] - help: bool, - #[options( - meta = "", - 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, -} - -#[derive(Options, Debug)] -struct BiosCommand { - #[options(help = "print help message")] - help: bool, - #[options( - meta = "", - no_long, - help = "set bios POST sound: asusctl -p " - )] - post_sound_set: Option, - #[options(no_long, help = "read bios POST sound")] - post_sound_get: bool, - #[options( - meta = "", - no_long, - help = "activate dGPU dedicated/G-Sync: asusctl -d , reboot required" - )] - dedicated_gfx_set: Option, - #[options(no_long, help = "get GPU mode")] - dedicated_gfx_get: bool, -} +const PLEASE: &str = + "Please use `systemctl status asusd` and `journalctl -b -u asusd` for more information"; +const CONFIG_ADVICE: &str = "A config file need to be removed so a new one can be generated"; fn main() -> Result<(), Box> { let args: Vec = args().skip(1).collect(); @@ -138,41 +49,54 @@ fn main() -> Result<(), Box> { } } - let (dbus, _) = RogDbusClient::new()?; + let (dbus, _) = RogDbusClient::new().map_err(|e| { + println!("\nIs asusd running?\n"); + println!("{}", PLEASE); + println!("{}\n", CONFIG_ADVICE); + e + })?; let supported = dbus .proxies() .supported() .get_supported_functions() .map_err(|e| { - println!("\nIs asusd running?\n\n{}", e); - println!(); - println!("Please use `journalctl -b -u asusd` and `systemctl status asusd` for more information"); + println!("\nIs asusd running?\n"); + println!("{}", PLEASE); + println!("{}\n", CONFIG_ADVICE); e })?; if parsed.version { print_versions(); + println!(); + print_laptop_info(); + println!("{}\n", PLEASE); return Ok(()); } if let Err(err) = do_parsed(&parsed, &supported, &dbus) { - println!("Error: {}", err); - println!(); - print_versions(); - println!(); - print_laptop_info(); - println!(); - println!("Supported laptop functions:\n\n{}", supported); - println!(); - println!("Please use `journalctl -b -u asusd` and `systemctl status asusd` for more information") + print_error_help(err, &supported); } Ok(()) } +fn print_error_help(err: Box, supported: &SupportedFunctions) { + println!("Error: {}\n", err); + print_versions(); + println!(); + print_laptop_info(); + println!(); + println!("Supported laptop functions:\n\n{}", supported); + println!(); + println!("{}", PLEASE); + println!("The above may give some indication that an option is not supported"); + println!("or that a config file must be removed or fixed"); +} + fn print_versions() { - println!("\nApp and daemon versions:"); + println!("App and daemon versions:"); println!(" asusctl v{}", env!("CARGO_PKG_VERSION")); println!(" asusd v{}", daemon::VERSION); println!("\nComponent crate versions:"); diff --git a/rog-profiles/src/lib.rs b/rog-profiles/src/lib.rs index 5d20051d..23f18a83 100644 --- a/rog-profiles/src/lib.rs +++ b/rog-profiles/src/lib.rs @@ -128,7 +128,7 @@ pub struct FanCurve { #[cfg_attr(feature = "dbus", derive(Type))] #[derive(Deserialize, Serialize, Debug)] pub struct FanCurves { - active_curves: Vec, + enabled: Vec, balanced: FanCurve, performance: FanCurve, quiet: FanCurve, @@ -137,7 +137,7 @@ pub struct FanCurves { impl Default for FanCurves { fn default() -> Self { let mut curves = Self { - active_curves: Default::default(), + enabled: Default::default(), balanced: Default::default(), performance: Default::default(), quiet: Default::default(), @@ -188,7 +188,7 @@ impl FanCurves { } pub fn get_enabled_curve_names(&self) -> &[Profile] { - &self.active_curves + &self.enabled } pub fn get_all_fan_curves(&self) -> Vec {