Compare commits

...

4 Commits

Author SHA1 Message Date
Luke Jones b3a555cab9 Merge branch 'fluke/asus_bios_settings' into 'next'
Bugfixes and improvements

Closes #48

See merge request asus-linux/asus-nb-ctrl!17
2021-01-27 01:16:39 +00:00
Luke cf13b4f71b Bugfixes and improvements
- fix CLI feedback for reboot/restartx. Update readme
- dracut force driver include for nvidia dedicated
- change fan-mode CLI tag

Closes #48
2021-01-27 14:13:02 +13:00
Luke Jones cd0b9fe350 Merge branch 'fluke/asus_bios_settings' into 'next'
Fluke/asus bios settings

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