Compare commits

...

46 Commits

Author SHA1 Message Date
Luke D. Jones ba40c3f739 Update dependencies 2021-12-19 21:01:47 +13:00
Luke D. Jones 31eff037a2 Bump to version 4.0.7 2021-12-19 21:00:58 +13:00
Luke D. Jones 630dee0b2a Update notes in CLI tool 2021-12-19 20:57:50 +13:00
Luke Jones 9110f06ed5 Update README.md
Remove whitespace and rustup from fedora build section
2021-12-17 21:18:00 +00:00
Luke Jones 2b0eceaa9d Merge branch 'main' into 'main'
Update of README for building and installing

See merge request asus-linux/asusctl!93
2021-12-17 21:16:56 +00:00
Peter Ross c96e1babe5 Update README.md 2021-12-16 15:23:08 +00:00
Peter Ross 9388cbde5d Update README.md 2021-12-16 15:16:35 +00:00
Luke D. Jones e739cddd6a Update patch links 2021-12-04 16:04:56 +13:00
Luke Jones 8cee6e0fc4 Remove Ubuntu repo instructions 2021-11-14 21:51:56 +00:00
Luke Jones bcf516afeb Merge branch 'sonnyp-main-patch-01923' into 'main'
Update kernel support for Linux 5.15

See merge request asus-linux/asusctl!88
2021-11-12 00:23:54 +00:00
Luke Jones b0e3e81b7f Merge branch 'fix/platform-functions/profile-support' into 'main'
Fix incorrect power profile support validation.

See merge request asus-linux/asusctl!89
2021-11-12 00:23:22 +00:00
Luke Jones ce6a1215a3 Merge branch 'LordVicky-main-patch-24845' into 'main'
Update asusd-ledmodes.toml to support Asus Rog Strix G15 G513QE

See merge request asus-linux/asusctl!90
2021-11-12 00:22:51 +00:00
LordVicky f54c1dc7d0 Fix typo 2021-11-09 07:32:39 +00:00
LordVicky 43aaae8d47 Update asusd-ledmodes.toml to support Asus Rog Strix G15 G513QE 2021-11-09 07:28:57 +00:00
Alexander Narsudinov ca463a2944 Fix incorrect power profile support validation.
Before this patch power profile support validation used wrong flag from PlatformProfileFunctions struct.
2021-11-07 15:11:31 +03:00
Sonny Piers 20e22589dc Update kernel support for Linux 5.15 2021-11-04 11:47:47 +00:00
Luke D. Jones 38d047cb8a Update changelog 2021-11-01 16:03:40 +13:00
Luke D. Jones 1d977199f3 Fix cli for bios/g-sync 2021-11-01 10:57:40 +13:00
Luke Jones 5041019d77 Merge branch 'fluke/anime-cli' into 'main'
Fluke/anime cli

See merge request asus-linux/asusctl!87
2021-10-30 20:28:36 +00:00
Luke D. Jones aa3835d3b3 Bump versions 2021-10-31 09:24:07 +13:00
Luke D. Jones 678505811d Add additional anime cli commands for image types 2021-10-28 23:43:50 +13:00
Luke D. Jones a925cbaed5 Bump version 2021-10-27 23:19:31 +13:00
Luke Jones 7d2201d873 Merge branch 'fluke/bugfixes' into 'main'
Add led modes for G513QR

Closes #144 and #143

See merge request asus-linux/asusctl!86
2021-10-27 10:18:31 +00:00
Luke D. Jones c0c1608d44 Update deps 2021-10-27 23:15:25 +13:00
Luke D. Jones 7bc6c83a04 Check and pass error if charge limit not in 20-100 range
Closes #144
2021-10-27 23:04:44 +13:00
Luke D. Jones 3f0df82f2d Parse percentages in fan curve only if '%' provided otherwise range is 0-255 2021-10-27 22:42:32 +13:00
Luke D. Jones 328ff0251b Add led modes for G513QR
Closes #143
2021-10-27 22:35:48 +13:00
Luke Jones c52582a413 Merge branch 'fluke/bugfixes' into 'main'
Bugfixes

Closes #139 and #140

See merge request asus-linux/asusctl!85
2021-10-02 07:34:55 +00:00
Luke D. Jones 3aa6eee306 Bugfixes
- Spawn tasks on individual threads
- Don't force a default of fan-curve on reload
- Add missing profile commands
- Begin obsoleting the graphics switch command in favour of supergfxctl
- Slim down the notification daemon to pure ASUS notifications

Bad behaviour in fan-curve new function that was forcing a re-init
to default on reload. Remove this and only save config again after
loading the config file and writing a curve (hidden side effect of
write is that a zeroed array is defaulted to read-from-system - this
needs to be changed too).

Closes #140, #139
2021-10-02 20:31:14 +13:00
Luke Jones 7d47faba0e Merge branch 'plasma-logout' into 'main'
Add kde logout prompt as fallback to gnome-session-quit

See merge request asus-linux/asusctl!82
2021-09-21 08:07:43 +00:00
Luke Jones f6fb477898 Merge branch 'main' into 'main'
Updated asusd-ledmodes.toml with ROG Strix G713QM

See merge request asus-linux/asusctl!83
2021-09-21 08:06:59 +00:00
Abhijith M 8963960d4b Updated asusd-ledmodes.toml with ROG Strix G713QM 2021-09-21 02:09:53 +00:00
Janghyub Seo ef973f676b Add kde logout prompt as fallback to gnome-session-quit 2021-09-19 02:13:11 +09:00
Luke D. Jones 812f9ea30e Add lock update 2021-09-16 22:38:09 +12:00
Luke Jones ff843b1241 Merge branch 'main' into 'main'
Add G533QS to supported models

See merge request asus-linux/asusctl!81
2021-09-16 10:30:09 +00:00
George Dumitrescu 59e7af149d Add G533QS to supported models 2021-09-16 10:07:48 +03:00
Luke D. Jones 6f14c85287 Revert supergfxctl deps to git 2021-09-16 16:03:41 +12:00
Luke D. Jones ac0dec4dbf Bump daemon version for release 2021-09-16 11:20:17 +12:00
Luke D. Jones e3d192412e Bugfixes 2021-09-16 11:19:05 +12:00
Luke Jones 9fadb6db30 Merge branch 'necessary129-main-patch-69023' into 'main'
Add another Strix G17 model

See merge request asus-linux/asusctl!80
2021-09-15 00:06:31 +00:00
Shamil K f8a1b71866 Add another Strix G17 model 2021-09-14 12:00:04 +00:00
Luke Jones c0a55acba7 Merge branch 'main' into 'main'
Adding ROG Flow X13 to LED modes known devices

See merge request asus-linux/asusctl!79
2021-09-14 11:45:56 +00:00
Joseph Ferano 4f232de634 Adding ROG Flow X13 to LED modes known devices 2021-09-14 18:05:42 +07:00
Luke Jones d351ebdaa0 Merge branch 'fluke/fan_curves_v13' into 'main'
Fluke/fan curves v13

See merge request asus-linux/asusctl!78
2021-09-14 02:55:51 +00:00
Luke D. Jones ab195e1d84 Fan curve enablement
- Add CtrlProfileTask
- Add method to reset active profile curve to platform default
- Wrap the zbus methods for profiles + fan curves
- Enable CLI args for fan curves
- CLI mod and save curves
2021-09-14 14:52:15 +12:00
Luke D. Jones 7041d77256 Fix asusd-ledmodes.toml 2021-09-11 17:03:32 +12:00
36 changed files with 1329 additions and 920 deletions
+48
View File
@@ -6,6 +6,54 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
# [4.0.7] - 2021-12-19
### Changed
- Fix incorrect power-profile validation
- Update asusd-ledmodes.toml to support Asus Rog Strix G15 G513QE (@LordVicky)
- Update patch notes and links
# [4.0.6] - 2021-11-01
### Changed
- Fix CLI for bios toggles
### Added
- Extra commands for AniMe: pixel-image, gif, pixel-gif
# [4.0.5] - 2021-10-27
### Changed
- Convert fan curve percentage to 0-255 expected by kernel driver only if '%' char is used, otherwise the expected range for fan power is 0-255
- Use correct error in daemon for invalid charging limit
- Enforce charging limit values in range 20-100
### Added
- LED modes for G513QR
# [4.0.4] - 2021-10-02
### Changed
- Add missing Profile commands
- Spawn tasks on individual threads to prevent blocking
- Don't force fan-curve default on reload
- Begin obsoleting the graphics switch command in favour of supergfxctl
- Slim down the notification daemon to pure ASUS notifications
# [4.0.3] - 2021-09-16
### Changed
- Don't show fan-curve warning if fan-curve available
- Add G713QR to Strix led-modes
- Fix part of CLI fan-curve control
# [4.0.2] - 2021-09-14
### Changed
- Backup old configs to *-old if parse fails
- Prevent some types of crashes related to unpatched kernels
- Add better help for graphics errors
- Add better help for asusctl general errors
- Implement fan-curve dbus API
- Implement partial fan-curve control via CLI tool
+ Set fan curve for profile + fan gpu/cpu
# [4.0.1] - 2021-09-11
### Changed
- Fix asusd-ledmodes.toml
# [4.0.0] - 2021-09-10 # [4.0.0] - 2021-09-10
### Added ### Added
- AniMe: - AniMe:
Generated
+184 -217
View File
@@ -39,13 +39,12 @@ dependencies = [
"rog_profiles", "rog_profiles",
"rog_supported", "rog_supported",
"serde_json", "serde_json",
"supergfxctl",
"zbus", "zbus",
] ]
[[package]] [[package]]
name = "asusctl" name = "asusctl"
version = "4.0.0" version = "4.0.7"
dependencies = [ dependencies = [
"daemon", "daemon",
"gif", "gif",
@@ -56,9 +55,9 @@ dependencies = [
"rog_dbus", "rog_dbus",
"rog_profiles", "rog_profiles",
"rog_supported", "rog_supported",
"supergfxctl",
"sysfs-class", "sysfs-class",
"tinybmp", "tinybmp",
"toml",
"zbus", "zbus",
] ]
@@ -106,15 +105,9 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "0.9.1" version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]] [[package]]
name = "blake2b_simd" name = "blake2b_simd"
@@ -141,21 +134,15 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]] [[package]]
name = "cache-padded" name = "cache-padded"
version = "1.1.1" version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba" checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.69" version = "1.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2" checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee"
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
@@ -203,13 +190,13 @@ version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if",
"lazy_static", "lazy_static",
] ]
[[package]] [[package]]
name = "daemon" name = "daemon"
version = "4.0.0" version = "4.0.7"
dependencies = [ dependencies = [
"env_logger", "env_logger",
"log", "log",
@@ -254,8 +241,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.9", "quote",
"syn 1.0.75", "syn",
] ]
[[package]] [[package]]
@@ -306,8 +293,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "946ee94e3dbf58fdd324f9ce245c7b238d46a66f00e86a020b71996349e46cce" checksum = "946ee94e3dbf58fdd324f9ce245c7b238d46a66f00e86a020b71996349e46cce"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.9", "quote",
"syn 1.0.75", "syn",
] ]
[[package]] [[package]]
@@ -325,18 +312,18 @@ dependencies = [
[[package]] [[package]]
name = "fastrand" name = "fastrand"
version = "1.5.0" version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b394ed3d285a429378d3b384b9eb1285267e7df4b166df24b7a6939a04dc392e" checksum = "779d043b6a0b90cc4c0ed7ee380a6504394cee7efd7db050e3774eee387324b2"
dependencies = [ dependencies = [
"instant", "instant",
] ]
[[package]] [[package]]
name = "futures" name = "futures"
version = "0.3.16" version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1adc00f486adfc9ce99f77d717836f0c5aa84965eb0b4f051f4e83f7cab53f8b" checksum = "28560757fe2bb34e79f907794bb6b22ae8b0e5c669b638a1132f2592b19035b4"
dependencies = [ dependencies = [
"futures-channel", "futures-channel",
"futures-core", "futures-core",
@@ -349,9 +336,9 @@ dependencies = [
[[package]] [[package]]
name = "futures-channel" name = "futures-channel"
version = "0.3.16" version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74ed2411805f6e4e3d9bc904c95d5d423b89b3b25dc0250aa74729de20629ff9" checksum = "ba3dda0b6588335f360afc675d0564c17a77a2bda81ca178a4b6081bd86c7f0b"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"futures-sink", "futures-sink",
@@ -359,15 +346,15 @@ dependencies = [
[[package]] [[package]]
name = "futures-core" name = "futures-core"
version = "0.3.16" version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af51b1b4a7fdff033703db39de8802c673eb91855f2e0d47dcf3bf2c0ef01f99" checksum = "d0c8ff0461b82559810cdccfde3215c3f373807f5e5232b71479bff7bb2583d7"
[[package]] [[package]]
name = "futures-executor" name = "futures-executor"
version = "0.3.16" version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d0d535a57b87e1ae31437b892713aee90cd2d7b0ee48727cd11fc72ef54761c" checksum = "29d6d2ff5bb10fb95c85b8ce46538a2e5f5e7fdc755623a7d4529ab8a4ed9d2a"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"futures-task", "futures-task",
@@ -376,9 +363,9 @@ dependencies = [
[[package]] [[package]]
name = "futures-io" name = "futures-io"
version = "0.3.16" version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b0e06c393068f3a6ef246c75cdca793d6a46347e75286933e5e75fd2fd11582" checksum = "b1f9d34af5a1aac6fb380f735fe510746c38067c5bf16c7fd250280503c971b2"
[[package]] [[package]]
name = "futures-lite" name = "futures-lite"
@@ -397,36 +384,33 @@ dependencies = [
[[package]] [[package]]
name = "futures-macro" name = "futures-macro"
version = "0.3.16" version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c54913bae956fb8df7f4dc6fc90362aa72e69148e3f39041fbe8742d21e0ac57" checksum = "6dbd947adfffb0efc70599b3ddcf7b5597bb5fa9e245eb99f62b3a5f7bb8bd3c"
dependencies = [ dependencies = [
"autocfg",
"proc-macro-hack",
"proc-macro2", "proc-macro2",
"quote 1.0.9", "quote",
"syn 1.0.75", "syn",
] ]
[[package]] [[package]]
name = "futures-sink" name = "futures-sink"
version = "0.3.16" version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0f30aaa67363d119812743aa5f33c201a7a66329f97d1a887022971feea4b53" checksum = "e3055baccb68d74ff6480350f8d6eb8fcfa3aa11bdc1a1ae3afdd0514617d508"
[[package]] [[package]]
name = "futures-task" name = "futures-task"
version = "0.3.16" version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbe54a98670017f3be909561f6ad13e810d9a51f3f061b902062ca3da80799f2" checksum = "6ee7c6485c30167ce4dfb83ac568a849fe53274c831081476ee13e0dce1aad72"
[[package]] [[package]]
name = "futures-util" name = "futures-util"
version = "0.3.16" version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67eb846bfd58e44a8481a00049e82c43e0ccb5d61f8dc071057cb19249dd4d78" checksum = "d9b5cf40b47a271f77a8b1bec03ca09044d99d2372c0de244e66430761127164"
dependencies = [ dependencies = [
"autocfg",
"futures-channel", "futures-channel",
"futures-core", "futures-core",
"futures-io", "futures-io",
@@ -436,8 +420,6 @@ dependencies = [
"memchr", "memchr",
"pin-project-lite", "pin-project-lite",
"pin-utils", "pin-utils",
"proc-macro-hack",
"proc-macro-nested",
"slab", "slab",
] ]
@@ -447,7 +429,7 @@ version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if",
"libc", "libc",
"wasi 0.9.0+wasi-snapshot-preview1", "wasi 0.9.0+wasi-snapshot-preview1",
] ]
@@ -458,16 +440,16 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if",
"libc", "libc",
"wasi 0.10.2+wasi-snapshot-preview1", "wasi 0.10.2+wasi-snapshot-preview1",
] ]
[[package]] [[package]]
name = "gif" name = "gif"
version = "0.11.2" version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a668f699973d0f573d15749b7002a9ac9e1f9c6b220e7b165601334c173d8de" checksum = "c3a7187e78088aead22ceedeee99779455b23fc231fe13ec443f99bb71694e5b"
dependencies = [ dependencies = [
"color_quant", "color_quant",
"weezl", "weezl",
@@ -498,8 +480,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "915ef07c710d84733522461de2a734d4d62a3fd39a4d4f404c2f385ef8618d05" checksum = "915ef07c710d84733522461de2a734d4d62a3fd39a4d4f404c2f385ef8618d05"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.9", "quote",
"syn 1.0.75", "syn",
]
[[package]]
name = "heck"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
dependencies = [
"unicode-segmentation",
] ]
[[package]] [[package]]
@@ -519,18 +510,18 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]] [[package]]
name = "instant" name = "instant"
version = "0.1.10" version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bee0328b1209d157ef001c94dd85b4f8f64139adb0eac2659f4b08382b2f474d" checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if",
] ]
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "0.4.8" version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
@@ -540,9 +531,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.101" version = "0.2.112"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3cb00336871be5ed2c8ed44b60ae9959dc5b9f08539422ed43f09e34ecaeba21" checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125"
[[package]] [[package]]
name = "libudev-sys" name = "libudev-sys"
@@ -572,7 +563,7 @@ version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if",
] ]
[[package]] [[package]]
@@ -616,6 +607,15 @@ version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
[[package]]
name = "memoffset"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
dependencies = [
"autocfg",
]
[[package]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.4.4" version = "0.4.4"
@@ -638,15 +638,15 @@ dependencies = [
[[package]] [[package]]
name = "nix" name = "nix"
version = "0.17.0" version = "0.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363" checksum = "f5e06129fb611568ef4e868c14b326274959aa70ff7776e9d55323531c374945"
dependencies = [ dependencies = [
"bitflags 1.3.2", "bitflags",
"cc", "cc",
"cfg-if 0.1.10", "cfg-if",
"libc", "libc",
"void", "memoffset",
] ]
[[package]] [[package]]
@@ -661,9 +661,9 @@ dependencies = [
[[package]] [[package]]
name = "notify-rust" name = "notify-rust"
version = "4.5.2" version = "4.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a2ca742cd7268b60c35828d318357f0b1bb9b82088e157ccf3013eb3ce70247" checksum = "ca6ebab865e67efdd7182a88d76cadbdd2a8d02d1c7a4e16bb7c234016a12cac"
dependencies = [ dependencies = [
"mac-notification-sys", "mac-notification-sys",
"serde", "serde",
@@ -729,9 +729,9 @@ dependencies = [
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.8.0" version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
[[package]] [[package]]
name = "parking" name = "parking"
@@ -759,9 +759,9 @@ checksum = "bea9d5c668f13b4a1b97d848780e00cfabf76eb83538129c264c0c6d6a968047"
[[package]] [[package]]
name = "pkg-config" name = "pkg-config"
version = "0.3.19" version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe"
[[package]] [[package]]
name = "png_pong" name = "png_pong"
@@ -775,11 +775,11 @@ dependencies = [
[[package]] [[package]]
name = "polling" name = "polling"
version = "2.1.0" 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 = "92341d779fa34ea8437ef4d82d440d5e1ce3f3ff7f824aa64424cd481f9a1f25" checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if",
"libc", "libc",
"log", "log",
"wepoll-ffi", "wepoll-ffi",
@@ -797,46 +797,28 @@ dependencies = [
[[package]] [[package]]
name = "proc-macro-crate" name = "proc-macro-crate"
version = "1.0.0" version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41fdbd1df62156fbc5945f4762632564d7d038153091c3fcf1067f6aef7cff92" checksum = "1ebace6889caf889b4d3f76becee12e90353f2b8c7d875534a71e5742f8f6f83"
dependencies = [ dependencies = [
"thiserror", "thiserror",
"toml", "toml",
] ]
[[package]]
name = "proc-macro-hack"
version = "0.5.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
[[package]]
name = "proc-macro-nested"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.28" version = "1.0.34"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612" checksum = "2f84e92c0f7c9d58328b85a78557813e4bd845130db68d7184635344399423b1"
dependencies = [ dependencies = [
"unicode-xid 0.2.2", "unicode-xid",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "0.3.15" version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"
[[package]]
name = "quote"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@@ -853,7 +835,7 @@ version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
dependencies = [ dependencies = [
"bitflags 1.3.2", "bitflags",
] ]
[[package]] [[package]]
@@ -896,7 +878,7 @@ checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
[[package]] [[package]]
name = "rog_anime" name = "rog_anime"
version = "1.1.0" version = "1.3.0"
dependencies = [ dependencies = [
"gif", "gif",
"glam", "glam",
@@ -920,13 +902,12 @@ dependencies = [
[[package]] [[package]]
name = "rog_dbus" name = "rog_dbus"
version = "4.0.0" version = "4.0.2"
dependencies = [ dependencies = [
"rog_anime", "rog_anime",
"rog_aura", "rog_aura",
"rog_profiles", "rog_profiles",
"rog_supported", "rog_supported",
"supergfxctl",
"zbus", "zbus",
"zbus_macros", "zbus_macros",
"zvariant", "zvariant",
@@ -934,7 +915,7 @@ dependencies = [
[[package]] [[package]]
name = "rog_profiles" name = "rog_profiles"
version = "1.0.0" version = "1.1.3"
dependencies = [ dependencies = [
"serde", "serde",
"serde_derive", "serde_derive",
@@ -978,9 +959,9 @@ dependencies = [
[[package]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.5" version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
[[package]] [[package]]
name = "scoped-tls" name = "scoped-tls"
@@ -990,29 +971,29 @@ checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.129" version = "1.0.132"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d1f72836d2aa753853178eda473a3b9d8e4eefdaf20523b919677e6de489f8f1" checksum = "8b9875c23cf305cd1fd7eb77234cbb705f21ea6a72c637a5c6db5fe4b8e7f008"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.129" version = "1.0.132"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e57ae87ad533d9a56427558b516d0adac283614e347abf85b0dc0cbbf0a249f3" checksum = "ecc0db5cb2556c0e558887d9bbdcf6ac4471e83ff66cf696e5419024d1606276"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.9", "quote",
"syn 1.0.75", "syn",
] ]
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.66" version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "336b10da19a12ad094b59d870ebde26a45402e5b470add4b5fd03c5048a32127" checksum = "bcbd0344bc6533bc7ec56df11d42fb70f1b912351c0825ccb7211b59d8af7cf5"
dependencies = [ dependencies = [
"itoa", "itoa",
"ryu", "ryu",
@@ -1026,21 +1007,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98d0516900518c29efa217c298fa1f4e6c6ffc85ae29fd7f4ee48f176e1a9ed5" checksum = "98d0516900518c29efa217c298fa1f4e6c6ffc85ae29fd7f4ee48f176e1a9ed5"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.9", "quote",
"syn 1.0.75", "syn",
] ]
[[package]] [[package]]
name = "slab" name = "slab"
version = "0.4.4" version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c307a32c1c5c437f38c7fd45d753050587732ba8628319fbdf12a7e289ccc590" checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5"
[[package]] [[package]]
name = "socket2" name = "socket2"
version = "0.4.1" version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "765f090f0e423d2b55843402a07915add955e7d60657db13707a159727326cad" checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516"
dependencies = [ dependencies = [
"libc", "libc",
"winapi", "winapi",
@@ -1054,65 +1035,34 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]] [[package]]
name = "strum" name = "strum"
version = "0.8.0" version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ca6e4730f517e041e547ffe23d29daab8de6b73af4b6ae2a002108169f5e7da" checksum = "f7ac893c7d471c8a21f31cfe213ec4f6d9afeed25537c772e08ef3f005f8729e"
dependencies = [
"strum_macros",
]
[[package]] [[package]]
name = "strum_macros" name = "strum_macros"
version = "0.8.0" version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3384590878eb0cab3b128e844412e2d010821e7e091211b9d87324173ada7db8" checksum = "339f799d8b549e3744c7ac7feb216383e4005d94bdb22561b3ab8f3b808ae9fb"
dependencies = [ dependencies = [
"quote 0.3.15", "heck",
"syn 0.11.11", "proc-macro2",
] "quote",
"syn",
[[package]]
name = "supergfxctl"
version = "2.0.0"
source = "git+https://gitlab.com/asus-linux/supergfxctl.git?tag=2.0.0#3f040cd3ec334242631122cd038aa361cc860be6"
dependencies = [
"log",
"logind-zbus",
"serde",
"serde_derive",
"serde_json",
"sysfs-class",
"zbus",
"zvariant",
"zvariant_derive",
] ]
[[package]] [[package]]
name = "syn" name = "syn"
version = "0.11.11" version = "1.0.82"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59"
dependencies = [
"quote 0.3.15",
"synom",
"unicode-xid 0.0.4",
]
[[package]]
name = "syn"
version = "1.0.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7f58f7e8eaa0009c5fec437aabf511bd9933e4b2d7407bd05273c01a8906ea7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.9", "quote",
"unicode-xid 0.2.2", "unicode-xid",
]
[[package]]
name = "synom"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
dependencies = [
"unicode-xid 0.0.4",
] ]
[[package]] [[package]]
@@ -1135,22 +1085,22 @@ dependencies = [
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.26" version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93119e4feac1cbe6c798c34d3a53ea0026b0b1de6a120deef895137c0529bfe2" checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.26" version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "060d69a0afe7796bf42e9e2ff91f5ee691fb15c53d38b4b62a9a53eb23164745" checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.9", "quote",
"syn 1.0.75", "syn",
] ]
[[package]] [[package]]
@@ -1193,10 +1143,10 @@ dependencies = [
] ]
[[package]] [[package]]
name = "unicode-xid" name = "unicode-segmentation"
version = "0.0.4" version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
[[package]] [[package]]
name = "unicode-xid" name = "unicode-xid"
@@ -1216,12 +1166,6 @@ version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
[[package]]
name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
[[package]] [[package]]
name = "waker-fn" name = "waker-fn"
version = "1.1.0" version = "1.1.0"
@@ -1287,41 +1231,63 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]] [[package]]
name = "winrt" name = "windows"
version = "0.4.0" version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e30cba82e22b083dc5a422c2ee77e20dc7927271a0dc981360c57c1453cb48d" checksum = "a9f39345ae0c8ab072c0ac7fe8a8b411636aa34f89be19ddd0d9226544f13944"
dependencies = [ dependencies = [
"winapi", "windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_msvc",
] ]
[[package]] [[package]]
name = "winrt-notification" name = "windows_i686_gnu"
version = "0.2.4" version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57790eb281688a4682dab44df2a1ba8b78373233bd71cb291c3e75fecb1a01c4" checksum = "c0866510a3eca9aed73a077490bbbf03e5eaac4e1fd70849d89539e5830501fd"
[[package]]
name = "windows_i686_msvc"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf0ffed56b7e9369a29078d2ab3aaeceea48eb58999d2cff3aa2494a275b95c6"
[[package]]
name = "windows_x86_64_gnu"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "384a173630588044205a2993b6864a2f56e5a8c1e7668c07b93ec18cf4888dc4"
[[package]]
name = "windows_x86_64_msvc"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bd8f062d8ca5446358159d79a90be12c543b3a965c847c8f3eedf14b321d399"
[[package]]
name = "winrt-notification"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eda101fb8e034a25f3d50a0714d7ca4f234a4fc7bc57427f6d81040db0ccbe6a"
dependencies = [ dependencies = [
"strum", "strum",
"strum_macros", "windows",
"winapi",
"winrt",
"xml-rs", "xml-rs",
] ]
[[package]] [[package]]
name = "xml-rs" name = "xml-rs"
version = "0.6.1" version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1945e12e16b951721d7976520b0832496ef79c31602c7a29d950de79ba74621" checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3"
dependencies = [
"bitflags 0.9.1",
]
[[package]] [[package]]
name = "zbus" name = "zbus"
version = "1.9.1" version = "1.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2326acc379a3ac4e34b794089f5bdb17086bf29a5fdf619b7b4cc772dc2e9dad" checksum = "e5983c3d035549ab80db67c844ec83ed271f7c1f2546fd9577c594d34c1b6c85"
dependencies = [ dependencies = [
"async-io", "async-io",
"byteorder", "byteorder",
@@ -1342,24 +1308,25 @@ dependencies = [
[[package]] [[package]]
name = "zbus_macros" name = "zbus_macros"
version = "1.9.1" version = "1.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a482c56029e48681b89b92b5db3c446db0915e8dd1052c0328a574eda38d5f93" checksum = "bce54ac7b2150a2fa21ad5842a7470ce2288158d7da1f9bfda8ad455a1c59a97"
dependencies = [ dependencies = [
"proc-macro-crate 0.1.5", "proc-macro-crate 0.1.5",
"proc-macro2", "proc-macro2",
"quote 1.0.9", "quote",
"syn 1.0.75", "syn",
] ]
[[package]] [[package]]
name = "zvariant" name = "zvariant"
version = "2.8.0" version = "2.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa4b785b8b32b0f8433b4474e6bb4ea77b37c1960e84d7598e01dd199b2b23ef" checksum = "a68c7b55f2074489b7e8e07d2d0a6ee6b4f233867a653c664d8020ba53692525"
dependencies = [ dependencies = [
"byteorder", "byteorder",
"enumflags2", "enumflags2",
"libc",
"serde", "serde",
"static_assertions", "static_assertions",
"zvariant_derive", "zvariant_derive",
@@ -1367,12 +1334,12 @@ dependencies = [
[[package]] [[package]]
name = "zvariant_derive" name = "zvariant_derive"
version = "2.8.0" version = "2.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b42af4ee88fb928781391216c34be77ec7cdb3546042b2947ce38d86aa5f37dd" checksum = "e4ca5e22593eb4212382d60d26350065bf2a02c34b85bc850474a74b589a3de9"
dependencies = [ dependencies = [
"proc-macro-crate 1.0.0", "proc-macro-crate 1.1.0",
"proc-macro2", "proc-macro2",
"quote 1.0.9", "quote",
"syn 1.0.75", "syn",
] ]
+2 -2
View File
@@ -97,7 +97,7 @@ These options are not written to the config file as they are stored in efivars.
### Profiles ### Profiles
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. 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.10.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 merged to 5.15 kernel upstream.
A common use of asusctl is to bind the `fn+f5` (fan) key to `asusctl profile -n` to cycle through the 3 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 1. Balanced
@@ -106,7 +106,7 @@ A common use of asusctl is to bind the `fn+f5` (fan) key to `asusctl profile -n`
#### Fan curves #### Fan curves
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. Fan curve support requires a laptop that supports it (this is detected automatically) and the kernel patch from [here](https://lkml.org/lkml/2021/10/23/250) which is accepted for the 5.17 kernel release .
The fan curve format can be of varying formats: The fan curve format can be of varying formats:
+18 -23
View File
@@ -5,10 +5,11 @@
`asusd` is a utility for Linux to control many aspects of various ASUS laptops `asusd` is a utility for Linux to control many aspects of various ASUS laptops
but can also be used with non-asus laptops with reduced features. but can also be used with non-asus laptops with reduced features.
## Kernel patches required ## Kernel support
1. https://lkml.org/lkml/2021/8/20/232 **The minimum supported kernel version is 5.15**
2. https://lkml.org/lkml/2021/8/18/1022
Fan curve control on laptops with this feature require [this patch](https://lkml.org/lkml/2021/10/23/250) whcih has been merged for 5.17 upstream.
## Goals ## Goals
@@ -24,10 +25,6 @@ supported (while asusd might still run fine on them). For best support use fedor
Point 4? asusd currently uses a tiny fraction of cpu time, and less than 1Mb of ram, the way Point 4? asusd currently uses a tiny fraction of cpu time, and less than 1Mb of ram, the way
a system-level daemon should. a system-level daemon should.
**NOTICE:**
Various patches are required for keyboard support. See [this post](https://asus-linux.org/blog/updates-2021-05-06/) for details on status and which kernels will have which patches.
## Discord ## Discord
[Discord server link](https://discord.gg/4ZKGd7Un5t) [Discord server link](https://discord.gg/4ZKGd7Un5t)
@@ -61,27 +58,25 @@ will probably suffer another rename once it becomes generic enough to do so.
# BUILDING # BUILDING
Requirements are rust >= 1.47 installed from rustup.io if the distro provided version is too old, and `make`. Requirements are rust >= 1.57 installed from rustup.io if the distro provided version is too old, and `make`.
**Ubuntu*:** `apt install libclang-dev libudev-dev` **Ubuntu (unsuported):**
`apt install libclang-dev libudev-dev`
`curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh`
`make`
`sudo make install`
**fedora:** `dnf install clang-devel systemd-devel` **fedora:**
`dnf install clang-devel systemd-devel`
`make`
`sudo make install`
## Installing ## Installing
- Fedora copr = https://copr.fedorainfracloud.org/coprs/lukenukem/asus-linux/
- openSUSE = https://download.opensuse.org/repositories/home:/luke_nukem:/asus/
- Ubuntu = not supported due to packaging woes, but you can build and install on your own.
Download repositories are available [here](https://download.opensuse.org/repositories/home:/luke_nukem:/asus/) for the latest versions of Fedora, Ubuntu, and openSUSE. =======
### Ubuntu
sudo su -c "echo 'deb https://download.opensuse.org/repositories/home:/luke_nukem:/asus/xUbuntu_21.04/ /' > /etc/apt/sources.list.d/luke_nukem.list"
curl -fsSL https://download.opensuse.org/repositories/home:/luke_nukem:/asus/xUbuntu_21.04/Release.key | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/home_luke_nukem.gpg > /dev/null
sudo apt-get update
sudo apt-get install asusctl dkms-hid-asus-rog
---
Run `make` then `sudo make install` then reboot.
The default init method is to use the udev rule, this ensures that the service is The default init method is to use the udev rule, this ensures that the service is
started when the device is initialised and ready. started when the device is initialised and ready.
-1
View File
@@ -14,7 +14,6 @@ rog_dbus = { path = "../rog-dbus" }
rog_aura = { path = "../rog-aura" } rog_aura = { path = "../rog-aura" }
rog_supported = { path = "../rog-supported" } rog_supported = { path = "../rog-supported" }
rog_profiles = { path = "../rog-profiles" } rog_profiles = { path = "../rog-profiles" }
supergfxctl = { git = "https://gitlab.com/asus-linux/supergfxctl.git", tag = "2.0.0" }
[dependencies.notify-rust] [dependencies.notify-rust]
version = "^4.3" version = "^4.3"
-107
View File
@@ -3,13 +3,8 @@ use rog_aura::AuraEffect;
use rog_dbus::{DbusProxies, Signals}; use rog_dbus::{DbusProxies, Signals};
use rog_profiles::Profile; use rog_profiles::Profile;
use std::error::Error; use std::error::Error;
use std::sync::mpsc::channel;
use std::thread::sleep; use std::thread::sleep;
use std::time::Duration; use std::time::Duration;
use std::{process, thread};
use supergfxctl::gfx_vendors::{GfxRequiredUserAction, GfxVendors};
use supergfxctl::zbus_proxy::GfxProxy;
use zbus::Connection;
const NOTIF_HEADER: &str = "ROG Control"; const NOTIF_HEADER: &str = "ROG Control";
@@ -37,7 +32,6 @@ macro_rules! base_notification {
fn main() -> Result<(), Box<dyn std::error::Error>> { fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("asus-notify version {}", env!("CARGO_PKG_VERSION")); println!("asus-notify version {}", env!("CARGO_PKG_VERSION"));
println!(" rog-dbus version {}", rog_dbus::VERSION); println!(" rog-dbus version {}", rog_dbus::VERSION);
println!("supergfxctl version {}", supergfxctl::VERSION);
let (proxies, conn) = DbusProxies::new()?; let (proxies, conn) = DbusProxies::new()?;
let signals = Signals::new(&proxies)?; let signals = Signals::new(&proxies)?;
@@ -47,8 +41,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let recv = proxies.setup_recv(conn); let recv = proxies.setup_recv(conn);
let mut err_count = 0; let mut err_count = 0;
gfx_thread()?;
loop { loop {
sleep(Duration::from_millis(100)); sleep(Duration::from_millis(100));
if let Err(err) = recv.next_signal() { if let Err(err) = recv.next_signal() {
@@ -77,56 +69,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
} }
} }
fn gfx_thread() -> Result<(), Box<dyn std::error::Error>> {
let mut last_notification: Option<NotificationHandle> = None;
let conn = Connection::new_system()?;
let proxy = GfxProxy::new(&conn)?;
let (tx1, rx1) = channel();
proxy.connect_notify_gfx(tx1)?;
let (tx2, rx2) = channel();
proxy.connect_notify_action(tx2)?;
thread::spawn(move || loop {
if proxy
.next_signal()
.map_err(|e| println!("Error: {}", e))
.is_err()
{
break;
}
if let Ok(data) = rx1.try_recv() {
notify!(do_gfx_notif, last_notification, &data);
}
if let Ok(data) = rx2.try_recv() {
match data {
GfxRequiredUserAction::Logout | GfxRequiredUserAction::Reboot => {
do_gfx_action_notif(&data)
.map_err(|e| {
println!("Error: {}", e);
})
.ok();
}
GfxRequiredUserAction::Integrated => {
base_notification!(
"You must be in integrated mode first to switch to the requested mode"
)
.map_err(|e| {
println!("Error: {}", e);
})
.ok();
}
GfxRequiredUserAction::None => {}
}
}
});
Ok(())
}
fn do_thermal_notif(profile: &Profile) -> Result<NotificationHandle, Box<dyn Error>> { fn do_thermal_notif(profile: &Profile) -> Result<NotificationHandle, Box<dyn Error>> {
let icon = match profile { let icon = match profile {
Profile::Balanced => "asus_notif_yellow", Profile::Balanced => "asus_notif_yellow",
@@ -159,52 +101,3 @@ fn do_led_notif(ledmode: &AuraEffect) -> Result<NotificationHandle, notify_rust:
fn do_charge_notif(limit: &u8) -> Result<NotificationHandle, notify_rust::error::Error> { fn do_charge_notif(limit: &u8) -> Result<NotificationHandle, notify_rust::error::Error> {
base_notification!(&format!("Battery charge limit changed to {}", limit)) base_notification!(&format!("Battery charge limit changed to {}", limit))
} }
fn do_gfx_notif(vendor: &GfxVendors) -> Result<NotificationHandle, notify_rust::error::Error> {
let icon = match vendor {
GfxVendors::Nvidia => "/usr/share/icons/hicolor/scalable/status/gpu-nvidia.svg",
GfxVendors::Integrated => "/usr/share/icons/hicolor/scalable/status/gpu-integrated.svg",
GfxVendors::Compute => "/usr/share/icons/hicolor/scalable/status/gpu-compute.svg",
GfxVendors::Vfio => "/usr/share/icons/hicolor/scalable/status/gpu-vfio.svg",
GfxVendors::Hybrid => "/usr/share/icons/hicolor/scalable/status/gpu-hybrid.svg",
};
Notification::new()
.summary(NOTIF_HEADER)
.body(&format!(
"Graphics mode changed to {}",
<&str>::from(vendor)
))
.timeout(2000)
.icon(icon)
.show()
}
fn do_gfx_action_notif(vendor: &GfxRequiredUserAction) -> Result<(), notify_rust::error::Error> {
let mut notif = Notification::new()
.summary(NOTIF_HEADER)
.timeout(2000)
.urgency(notify_rust::Urgency::Critical)
.icon("/usr/share/icons/hicolor/scalable/status/notification-reboot.svg")
.finalize();
if matches!(vendor, GfxRequiredUserAction::Logout) {
notif.action("logout", "Logout now?");
} else if matches!(vendor, GfxRequiredUserAction::Reboot) {
notif.action("reboot", "Reboot now?");
}
notif.body("Graphics mode changed");
notif.show()?.wait_for_action(|action| match action {
"logout" => {
process::Command::new("gnome-session-quit").spawn().ok();
}
"reboot" => {
process::Command::new("systemctl")
.arg("reboot")
.spawn()
.ok();
}
_ => (),
});
Ok(())
}
+2 -2
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "asusctl" name = "asusctl"
version = "4.0.0" version = "4.0.7"
authors = ["Luke D Jones <luke@ljones.dev>"] authors = ["Luke D Jones <luke@ljones.dev>"]
edition = "2018" edition = "2018"
@@ -15,7 +15,7 @@ rog_profiles = { path = "../rog-profiles" }
rog_supported = { path = "../rog-supported" } rog_supported = { path = "../rog-supported" }
daemon = { path = "../daemon" } daemon = { path = "../daemon" }
gumdrop = "^0.8" gumdrop = "^0.8"
supergfxctl = { git = "https://gitlab.com/asus-linux/supergfxctl.git", tag = "2.0.0" } toml = "^0.5.8"
sysfs-class = "^0.1.2" sysfs-class = "^0.1.2"
+66 -57
View File
@@ -1,54 +1,4 @@
use gumdrop::Options; use gumdrop::Options;
use rog_aura::error::Error;
use std::str::FromStr;
#[derive(Copy, Clone, Debug)]
pub enum AnimeStatusValue {
On,
Off,
}
impl FromStr for AnimeStatusValue {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let s = s.to_lowercase();
match s.as_str() {
"on" => Ok(AnimeStatusValue::On),
"off" => Ok(AnimeStatusValue::Off),
_ => {
print!("Invalid argument, must be one of: on, off");
Err(Error::ParseAnime)
}
}
}
}
impl From<AnimeStatusValue> for bool {
fn from(value: AnimeStatusValue) -> Self {
match value {
AnimeStatusValue::On => true,
AnimeStatusValue::Off => false,
}
}
}
#[derive(Options)]
pub struct AnimeLeds {
#[options(help = "print help message")]
help: bool,
#[options(
no_long,
required,
short = "b",
meta = "",
help = "set all leds brightness value"
)]
led_brightness: u8,
}
impl AnimeLeds {
pub fn led_brightness(&self) -> u8 {
self.led_brightness
}
}
#[derive(Options)] #[derive(Options)]
pub struct AnimeCommand { pub struct AnimeCommand {
@@ -56,21 +6,30 @@ pub struct AnimeCommand {
pub help: bool, pub help: bool,
#[options( #[options(
meta = "", meta = "",
help = "turn on/off the panel (accept/reject write requests)" help = "enable/disable the panel LEDs (does not erase last image)"
)] )]
pub turn: Option<AnimeStatusValue>, pub enable: Option<bool>,
#[options(meta = "", help = "turn on/off the panel at boot (with Asus effect)")] #[options(
pub boot: Option<AnimeStatusValue>, meta = "",
help = "enable/disable system animations (boot/sleep/shutdown)"
)]
pub boot_enable: Option<bool>,
#[options(meta = "", help = "set global AniMe brightness value")]
pub brightness: Option<f32>,
#[options(command)] #[options(command)]
pub command: Option<AnimeActions>, pub command: Option<AnimeActions>,
} }
#[derive(Options)] #[derive(Options)]
pub enum AnimeActions { pub enum AnimeActions {
#[options(help = "change all leds brightness")] #[options(help = "display a PNG image")]
Leds(AnimeLeds),
#[options(help = "display an image png")]
Image(AnimeImage), Image(AnimeImage),
#[options(help = "display a diagonal/pixel-perfect PNG")]
PixelImage(AnimeImageDiagonal),
#[options(help = "display an animated GIF")]
Gif(AnimeGif),
#[options(help = "display an animated diagonal/pixel-perfect GIF")]
PixelGif(AnimeGifDiagonal),
} }
#[derive(Options)] #[derive(Options)]
@@ -90,3 +49,53 @@ pub struct AnimeImage {
#[options(meta = "", default = "1.0", help = "brightness 0.0-1.0")] #[options(meta = "", default = "1.0", help = "brightness 0.0-1.0")]
pub bright: f32, pub bright: f32,
} }
#[derive(Options)]
pub struct AnimeImageDiagonal {
#[options(help = "print help message")]
pub help: bool,
#[options(meta = "", help = "full path to the png to display")]
pub path: String,
#[options(meta = "", default = "1.0", help = "brightness 0.0-1.0")]
pub bright: f32,
}
#[derive(Options)]
pub struct AnimeGif {
#[options(help = "print help message")]
pub help: bool,
#[options(meta = "", help = "full path to the png to display")]
pub path: String,
#[options(meta = "", default = "1.0", help = "scale 1.0 == normal")]
pub scale: f32,
#[options(meta = "", default = "0.0", help = "x position (float)")]
pub x_pos: f32,
#[options(meta = "", default = "0.0", help = "y position (float)")]
pub y_pos: f32,
#[options(meta = "", default = "0.0", help = "the angle in radians")]
pub angle: f32,
#[options(meta = "", default = "1.0", help = "brightness 0.0-1.0")]
pub bright: f32,
#[options(
meta = "",
default = "1",
help = "how many loops to play - 0 is infinite"
)]
pub loops: u32,
}
#[derive(Options)]
pub struct AnimeGifDiagonal {
#[options(help = "print help message")]
pub help: bool,
#[options(meta = "", help = "full path to the png to display")]
pub path: String,
#[options(meta = "", default = "1.0", help = "brightness 0.0-1.0")]
pub bright: f32,
#[options(
meta = "",
default = "1",
help = "how many loops to play - 0 is infinite"
)]
pub loops: u32,
}
+6 -16
View File
@@ -1,10 +1,9 @@
use crate::{ use crate::{
anime_cli::AnimeCommand, anime_cli::AnimeCommand,
aura_cli::{LedBrightness, SetAuraBuiltin}, aura_cli::{LedBrightness, SetAuraBuiltin},
profiles_cli::ProfileCommand, profiles_cli::{FanCurveCommand, ProfileCommand},
}; };
use gumdrop::Options; use gumdrop::Options;
use supergfxctl::gfx_vendors::GfxVendors;
#[derive(Default, Options)] #[derive(Default, Options)]
pub struct CliStart { pub struct CliStart {
@@ -20,7 +19,7 @@ pub struct CliStart {
pub next_kbd_bright: bool, pub next_kbd_bright: bool,
#[options(help = "Toggle to previous keyboard brightness")] #[options(help = "Toggle to previous keyboard brightness")]
pub prev_kbd_bright: bool, pub prev_kbd_bright: bool,
#[options(meta = "", help = "<20-100>")] #[options(meta = "", help = "Set your battery charge limit <20-100>")]
pub chg_limit: Option<u8>, pub chg_limit: Option<u8>,
#[options(command)] #[options(command)]
pub command: Option<CliCommand>, pub command: Option<CliCommand>,
@@ -30,9 +29,11 @@ pub struct CliStart {
pub enum CliCommand { pub enum CliCommand {
#[options(help = "Set the keyboard lighting from built-in modes")] #[options(help = "Set the keyboard lighting from built-in modes")]
LedMode(LedModeCommand), LedMode(LedModeCommand),
#[options(help = "Create and configure profiles")] #[options(help = "Set or select platform_profile")]
Profile(ProfileCommand), Profile(ProfileCommand),
#[options(help = "Set the graphics mode")] #[options(help = "Set, select, or modify fan curves if supported")]
FanCurve(FanCurveCommand),
#[options(help = "Set the graphics mode (obsoleted by supergfxctl)")]
Graphics(GraphicsCommand), Graphics(GraphicsCommand),
#[options(name = "anime", help = "Manage AniMe Matrix")] #[options(name = "anime", help = "Manage AniMe Matrix")]
Anime(AnimeCommand), Anime(AnimeCommand),
@@ -66,17 +67,6 @@ pub struct LedModeCommand {
pub struct GraphicsCommand { pub struct GraphicsCommand {
#[options(help = "print help message")] #[options(help = "print help message")]
pub help: bool, pub help: bool,
#[options(
meta = "",
help = "Set graphics mode: <nvidia, hybrid, compute, integrated>"
)]
pub mode: Option<GfxVendors>,
#[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)] #[derive(Options, Debug)]
+265 -137
View File
@@ -1,31 +1,29 @@
mod anime_cli; use std::process::Command;
mod aura_cli; use std::thread::sleep;
mod cli_opts; use std::{env::args, path::Path};
mod profiles_cli;
use crate::aura_cli::{LedBrightness, SetAuraBuiltin};
use crate::cli_opts::*;
use anime_cli::{AnimeActions, AnimeCommand};
use gumdrop::{Opt, Options}; use gumdrop::{Opt, Options};
use profiles_cli::ProfileCommand;
use rog_anime::{AnimeDataBuffer, AnimeImage, Vec2, ANIME_DATA_LEN}; use anime_cli::{AnimeActions, AnimeCommand};
use profiles_cli::{FanCurveCommand, ProfileCommand};
use rog_anime::{AnimTime, AnimeDataBuffer, AnimeDiagonal, AnimeGif, AnimeImage, Vec2};
use rog_aura::{self, AuraEffect}; use rog_aura::{self, AuraEffect};
use rog_dbus::RogDbusClient; use rog_dbus::RogDbusClient;
use rog_profiles::error::ProfileError;
use rog_supported::SupportedFunctions; use rog_supported::SupportedFunctions;
use rog_supported::{ use rog_supported::{
AnimeSupportedFunctions, LedSupportedFunctions, PlatformProfileFunctions, AnimeSupportedFunctions, LedSupportedFunctions, PlatformProfileFunctions,
RogBiosSupportedFunctions, RogBiosSupportedFunctions,
}; };
use std::{env::args, path::Path, sync::mpsc::channel};
use supergfxctl::{
gfx_vendors::GfxRequiredUserAction,
special::{get_asus_gsync_gfx_mode, has_asus_gsync_gfx_mode},
zbus_proxy::GfxProxy,
};
use zbus::Connection;
const PLEASE: &str = use crate::aura_cli::{LedBrightness, SetAuraBuiltin};
"Please use `systemctl status asusd` and `journalctl -b -u asusd` for more information"; use crate::cli_opts::*;
mod anime_cli;
mod aura_cli;
mod cli_opts;
mod profiles_cli;
const CONFIG_ADVICE: &str = "A config file need to be removed so a new one can be generated"; const CONFIG_ADVICE: &str = "A config file need to be removed so a new one can be generated";
fn main() -> Result<(), Box<dyn std::error::Error>> { fn main() -> Result<(), Box<dyn std::error::Error>> {
@@ -49,50 +47,48 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
} }
} }
let (dbus, _) = RogDbusClient::new().map_err(|e| { let (dbus, _) = RogDbusClient::new()
println!("\nIs asusd running?\n"); .map_err(|e| {
println!("{}", PLEASE); print_error_help(Box::new(e), None);
println!("{}\n", CONFIG_ADVICE); std::process::exit(3);
e })
})?; .unwrap();
let supported = dbus let supported = dbus
.proxies() .proxies()
.supported() .supported()
.get_supported_functions() .get_supported_functions()
.map_err(|e| { .map_err(|e| {
println!("\nIs asusd running?\n"); print_error_help(Box::new(e), None);
println!("{}", PLEASE); std::process::exit(4);
println!("{}\n", CONFIG_ADVICE); })
e .unwrap();
})?;
if parsed.version { if parsed.version {
print_versions(); print_versions();
println!(); println!();
print_laptop_info(); print_laptop_info();
println!("{}\n", PLEASE);
return Ok(()); return Ok(());
} }
if let Err(err) = do_parsed(&parsed, &supported, &dbus) { if let Err(err) = do_parsed(&parsed, &supported, &dbus) {
print_error_help(err, &supported); print_error_help(err, Some(&supported));
} }
Ok(()) Ok(())
} }
fn print_error_help(err: Box<dyn std::error::Error>, supported: &SupportedFunctions) { fn print_error_help(err: Box<dyn std::error::Error>, supported: Option<&SupportedFunctions>) {
println!("Error: {}\n", err); if do_diagnose("asusd") {
print_versions(); println!("\nError: {}\n", err);
println!(); print_versions();
print_laptop_info(); println!();
println!(); print_laptop_info();
println!("Supported laptop functions:\n\n{}", supported); if let Some(supported) = supported {
println!(); println!();
println!("{}", PLEASE); println!("Supported laptop functions:\n\n{}", supported);
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() { fn print_versions() {
@@ -105,7 +101,6 @@ fn print_versions() {
println!(" rog-dbus v{}", rog_dbus::VERSION); println!(" rog-dbus v{}", rog_dbus::VERSION);
println!(" rog-profiles v{}", rog_profiles::VERSION); println!(" rog-profiles v{}", rog_profiles::VERSION);
println!("rog-supported v{}", rog_supported::VERSION); println!("rog-supported v{}", rog_supported::VERSION);
println!(" supergfxctl v{}", supergfxctl::VERSION);
} }
fn print_laptop_info() { fn print_laptop_info() {
@@ -117,6 +112,30 @@ fn print_laptop_info() {
println!("Board name: {}", board_name.trim()); println!("Board name: {}", board_name.trim());
} }
fn do_diagnose(name: &str) -> bool {
if name != "asusd" && !check_systemd_unit_enabled(name) {
println!(
"\n\x1b[0;31m{} is not enabled, enable it with `systemctl enable {}\x1b[0m",
name, name
);
return true;
} else if !check_systemd_unit_active(name) {
println!(
"\n\x1b[0;31m{} is not running, start it with `systemctl start {}\x1b[0m",
name, name
);
return true;
} else {
println!("\nSome error happened (sorry)");
println!(
"Please use `systemctl status {}` and `journalctl -b -u {}` for more information",
name, name
);
println!("{}", CONFIG_ADVICE);
}
false
}
fn do_parsed( fn do_parsed(
parsed: &CliStart, parsed: &CliStart,
supported: &SupportedFunctions, supported: &SupportedFunctions,
@@ -125,7 +144,10 @@ fn do_parsed(
match &parsed.command { match &parsed.command {
Some(CliCommand::LedMode(mode)) => handle_led_mode(dbus, &supported.keyboard_led, mode)?, Some(CliCommand::LedMode(mode)) => handle_led_mode(dbus, &supported.keyboard_led, mode)?,
Some(CliCommand::Profile(cmd)) => handle_profile(dbus, &supported.platform_profile, cmd)?, Some(CliCommand::Profile(cmd)) => handle_profile(dbus, &supported.platform_profile, cmd)?,
Some(CliCommand::Graphics(cmd)) => do_gfx(cmd)?, Some(CliCommand::FanCurve(cmd)) => {
handle_fan_curve(dbus, &supported.platform_profile, cmd)?
}
Some(CliCommand::Graphics(_)) => do_gfx()?,
Some(CliCommand::Anime(cmd)) => handle_anime(dbus, &supported.anime_ctrl, cmd)?, Some(CliCommand::Anime(cmd)) => handle_anime(dbus, &supported.anime_ctrl, cmd)?,
Some(CliCommand::Bios(cmd)) => handle_bios_option(dbus, &supported.rog_bios_ctrl, cmd)?, Some(CliCommand::Bios(cmd)) => handle_bios_option(dbus, &supported.rog_bios_ctrl, cmd)?,
None => { None => {
@@ -149,7 +171,7 @@ fn do_parsed(
match brightness.level() { match brightness.level() {
None => { None => {
let level = dbus.proxies().led().get_led_brightness()?; let level = dbus.proxies().led().get_led_brightness()?;
println!("Current keyboard led brightness: {}", level.to_string()); println!("Current keyboard led brightness: {}", level);
} }
Some(level) => dbus Some(level) => dbus
.proxies() .proxies()
@@ -177,67 +199,9 @@ fn do_parsed(
Ok(()) Ok(())
} }
fn do_gfx(command: &GraphicsCommand) -> Result<(), Box<dyn std::error::Error>> { fn do_gfx() -> Result<(), Box<dyn std::error::Error>> {
if command.mode.is_none() && !command.get && !command.pow && !command.force || command.help { println!("Please use supergfxctl for graphics switching. supergfxctl is the result of making asusctl graphics switching generic so all laptops can use it");
println!("{}", command.self_usage()); println!("This command will be removed in future");
}
let conn = Connection::new_system()?;
let proxy = GfxProxy::new(&conn)?;
let (tx, rx) = channel();
proxy.connect_notify_action(tx)?;
if let Some(mode) = command.mode {
if has_asus_gsync_gfx_mode() && get_asus_gsync_gfx_mode()? == 1 {
println!("You can not change modes until you turn dedicated/G-Sync off and reboot");
std::process::exit(-1);
}
println!("If anything fails check `journalctl -b -u asusd`\n");
proxy.gfx_write_mode(&mode).map_err(|err|{
println!("Graphics mode change error. You may be in an invalid state.");
println!("Check mode with `asusctl graphics -g` and switch to opposite\nmode to correct it, e.g: if integrated, switch to hybrid, or if nvidia, switch to integrated.\n");
err
})?;
loop {
proxy.next_signal()?;
if let Ok(res) = rx.try_recv() {
match res {
GfxRequiredUserAction::Integrated => {
println!(
"You must change to Integrated before you can change to {}",
<&str>::from(mode)
);
}
GfxRequiredUserAction::Logout | GfxRequiredUserAction::Reboot => {
println!(
"Graphics mode changed to {}. User action required is: {}",
<&str>::from(mode),
<&str>::from(&res)
);
}
GfxRequiredUserAction::None => {
println!("Graphics mode changed to {}", <&str>::from(mode));
}
}
}
std::process::exit(0)
}
}
if command.get {
let res = proxy.gfx_get_mode()?;
println!("Current graphics mode: {}", <&str>::from(res));
}
if command.pow {
let res = proxy.gfx_get_pwr()?;
println!("Current power status: {}", <&str>::from(&res));
}
Ok(()) Ok(())
} }
@@ -246,28 +210,28 @@ fn handle_anime(
_supported: &AnimeSupportedFunctions, _supported: &AnimeSupportedFunctions,
cmd: &AnimeCommand, cmd: &AnimeCommand,
) -> Result<(), Box<dyn std::error::Error>> { ) -> Result<(), Box<dyn std::error::Error>> {
if (cmd.command.is_none() && cmd.boot.is_none() && cmd.turn.is_none()) || cmd.help { if (cmd.command.is_none()
&& cmd.enable.is_none()
&& cmd.boot_enable.is_none()
&& cmd.brightness.is_none())
|| cmd.help
{
println!("Missing arg or command\n\n{}", cmd.self_usage()); println!("Missing arg or command\n\n{}", cmd.self_usage());
if let Some(lst) = cmd.self_command_list() { if let Some(lst) = cmd.self_command_list() {
println!("\n{}", lst); println!("\n{}", lst);
} }
} }
if let Some(anime_turn) = cmd.turn { if let Some(anime_turn) = cmd.enable {
dbus.proxies().anime().set_led_power(anime_turn.into())? dbus.proxies().anime().set_on_off(anime_turn)?
} }
if let Some(anime_boot) = cmd.boot { if let Some(anime_boot) = cmd.boot_enable {
dbus.proxies() dbus.proxies().anime().set_boot_on_off(anime_boot)?
.anime() }
.set_system_animations(anime_boot.into())? if let Some(bright) = cmd.brightness {
dbus.proxies().anime().set_brightness(bright as f32)?
} }
if let Some(action) = cmd.command.as_ref() { if let Some(action) = cmd.command.as_ref() {
match action { match action {
AnimeActions::Leds(anime_leds) => {
let data = AnimeDataBuffer::from_vec(
[anime_leds.led_brightness(); ANIME_DATA_LEN].to_vec(),
);
dbus.proxies().anime().write(data)?;
}
AnimeActions::Image(image) => { AnimeActions::Image(image) => {
if image.help_requested() || image.path.is_empty() { if image.help_requested() || image.path.is_empty() {
println!("Missing arg or command\n\n{}", image.self_usage()); println!("Missing arg or command\n\n{}", image.self_usage());
@@ -289,6 +253,82 @@ fn handle_anime(
.anime() .anime()
.write(<AnimeDataBuffer>::from(&matrix))?; .write(<AnimeDataBuffer>::from(&matrix))?;
} }
AnimeActions::PixelImage(image) => {
if image.help_requested() || image.path.is_empty() {
println!("Missing arg or command\n\n{}", image.self_usage());
if let Some(lst) = image.self_command_list() {
println!("\n{}", lst);
}
std::process::exit(1);
}
let matrix = AnimeDiagonal::from_png(Path::new(&image.path), None, image.bright)?;
dbus.proxies()
.anime()
.write(<AnimeDataBuffer>::from(&matrix))?;
}
AnimeActions::Gif(gif) => {
if gif.help_requested() || gif.path.is_empty() {
println!("Missing arg or command\n\n{}", gif.self_usage());
if let Some(lst) = gif.self_command_list() {
println!("\n{}", lst);
}
std::process::exit(1);
}
let matrix = AnimeGif::from_gif(
Path::new(&gif.path),
gif.scale,
gif.angle,
Vec2::new(gif.x_pos, gif.y_pos),
AnimTime::Count(1),
gif.bright,
)?;
let mut loops = gif.loops as i32;
loop {
for frame in matrix.frames() {
dbus.proxies().anime().write(frame.frame().clone())?;
sleep(frame.delay());
}
if loops >= 0 {
loops -= 1;
}
if loops == 0 {
break;
}
}
}
AnimeActions::PixelGif(gif) => {
if gif.help_requested() || gif.path.is_empty() {
println!("Missing arg or command\n\n{}", gif.self_usage());
if let Some(lst) = gif.self_command_list() {
println!("\n{}", lst);
}
std::process::exit(1);
}
let matrix = AnimeGif::from_diagonal_gif(
Path::new(&gif.path),
AnimTime::Count(1),
gif.bright,
)?;
let mut loops = gif.loops as i32;
loop {
for frame in matrix.frames() {
dbus.proxies().anime().write(frame.frame().clone())?;
sleep(frame.delay());
}
if loops >= 0 {
loops -= 1;
}
if loops == 0 {
break;
}
}
}
} }
} }
Ok(()) Ok(())
@@ -375,39 +415,103 @@ fn handle_profile(
supported: &PlatformProfileFunctions, supported: &PlatformProfileFunctions,
cmd: &ProfileCommand, cmd: &ProfileCommand,
) -> Result<(), Box<dyn std::error::Error>> { ) -> Result<(), Box<dyn std::error::Error>> {
println!("Warning: Profiles should work fine but now depend on power-profiles-daemon v0.9+"); if !supported.platform_profile {
println!("Warning: Fan-curve support is coming in a 4.1.x release"); println!("Profiles not supported by either this kernel or by the laptop.");
if !cmd.next && !cmd.list { return Err(ProfileError::NotSupported.into());
}
if !cmd.next && !cmd.list && cmd.profile_set.is_none() && !cmd.profile_get {
if !cmd.help { if !cmd.help {
println!("Missing arg or command\n"); println!("Missing arg or command\n");
} }
let usage: Vec<String> = ProfileCommand::usage() println!("{}", ProfileCommand::usage());
.lines()
.map(|s| s.to_string())
.collect();
for line in usage
.iter()
.filter(|line| !line.contains("--curve") || supported.fan_curves)
{
println!("{}", line);
}
if let Some(lst) = cmd.self_command_list() { if let Some(lst) = cmd.self_command_list() {
println!("\n{}", lst); println!("\n{}", lst);
} }
// println!("Note: turbo, frequency, fan preset and fan curve options will apply to");
// println!(" to the currently active profile unless a profile name is specified");
std::process::exit(1); std::process::exit(1);
} }
if cmd.next { if cmd.next {
dbus.proxies().profile().next_profile()?; dbus.proxies().profile().next_profile()?;
} else if let Some(profile) = cmd.profile_set {
dbus.proxies().profile().set_active_profile(profile)?;
} }
if cmd.list { if cmd.list {
let res = dbus.proxies().profile().profiles()?; let res = dbus.proxies().profile().profiles()?;
res.iter().for_each(|p| println!("{:?}", p)); res.iter().for_each(|p| println!("{:?}", p));
} }
if cmd.profile_get {
let res = dbus.proxies().profile().active_profile()?;
println!("Active profile is {:?}", res);
}
Ok(())
}
fn handle_fan_curve(
dbus: &RogDbusClient,
supported: &PlatformProfileFunctions,
cmd: &FanCurveCommand,
) -> Result<(), Box<dyn std::error::Error>> {
if !supported.fan_curves {
println!("Fan-curves not supported by either this kernel or by the laptop.");
println!(
"This requires kernel 5.17 (unlreleased) or the fan curve patch listed in the readme."
);
return Err(ProfileError::NotSupported.into());
}
if !cmd.get_enabled && !cmd.default && cmd.mod_profile.is_none() {
if !cmd.help {
println!("Missing arg or command\n");
}
println!("{}", FanCurveCommand::usage());
if let Some(lst) = cmd.self_command_list() {
println!("\n{}", lst);
}
std::process::exit(1);
}
if (cmd.enabled.is_some() || cmd.fan.is_some() || cmd.data.is_some())
&& cmd.mod_profile.is_none()
{
println!("--enabled, --fan, and --data options require --mod-profile");
std::process::exit(666);
}
if cmd.get_enabled {
let res = dbus.proxies().profile().enabled_fan_profiles()?;
println!("{:?}", res);
}
if cmd.default {
dbus.proxies().profile().set_active_curve_to_defaults()?;
}
if let Some(profile) = cmd.mod_profile {
if cmd.enabled.is_none() && cmd.data.is_none() {
let data = dbus.proxies().profile().fan_curve_data(profile)?;
let data = toml::to_string(&data)?;
println!("\nFan curves for {:?}\n\n{}", profile, data);
}
if let Some(enabled) = cmd.enabled {
dbus.proxies()
.profile()
.set_fan_curve_enabled(profile, enabled)?;
}
if let Some(mut curve) = cmd.data.clone() {
let fan = cmd.fan.unwrap_or_default();
curve.set_fan(fan);
dbus.proxies().profile().set_fan_curve(curve, profile)?;
}
}
Ok(()) Ok(())
} }
@@ -431,8 +535,8 @@ fn handle_bios_option(
.collect(); .collect();
for line in usage.iter().filter(|line| { for line in usage.iter().filter(|line| {
!line.contains("sound") && !supported.post_sound_toggle line.contains("sound") && supported.post_sound_toggle
|| !line.contains("GPU") && !supported.dedicated_gfx_toggle || line.contains("GPU") && supported.dedicated_gfx_toggle
}) { }) {
println!("{}", line); println!("{}", line);
} }
@@ -464,3 +568,27 @@ fn handle_bios_option(
} }
Ok(()) Ok(())
} }
fn check_systemd_unit_active(name: &str) -> bool {
if let Ok(out) = Command::new("systemctl")
.arg("is-active")
.arg(name)
.output()
{
let buf = String::from_utf8_lossy(&out.stdout);
return !buf.contains("inactive") && !buf.contains("failed");
}
false
}
fn check_systemd_unit_enabled(name: &str) -> bool {
if let Ok(out) = Command::new("systemctl")
.arg("is-enabled")
.arg(name)
.output()
{
let buf = String::from_utf8_lossy(&out.stdout);
return buf.contains("enabled");
}
false
}
+40
View File
@@ -1,4 +1,5 @@
use gumdrop::Options; use gumdrop::Options;
use rog_profiles::{fan_curve_set::CurveData, FanCurvePU, Profile};
#[derive(Debug, Clone, Options)] #[derive(Debug, Clone, Options)]
pub struct ProfileCommand { pub struct ProfileCommand {
@@ -8,4 +9,43 @@ pub struct ProfileCommand {
pub next: bool, pub next: bool,
#[options(help = "list available profiles")] #[options(help = "list available profiles")]
pub list: bool, pub list: bool,
#[options(help = "get profile")]
pub profile_get: bool,
#[options(meta = "", help = "set the active profile")]
pub profile_set: Option<Profile>,
}
#[derive(Debug, Clone, Options)]
pub struct FanCurveCommand {
#[options(help = "print help message")]
pub help: bool,
#[options(help = "get enabled fan profiles")]
pub get_enabled: bool,
#[options(help = "set the active profile's fan curve to default")]
pub default: bool,
#[options(
meta = "",
help = "profile to modify fan-curve for. Shows data if no options provided"
)]
pub mod_profile: Option<Profile>,
#[options(
meta = "",
help = "enable or disable <true/false> fan curve. `mod-profile` required"
)]
pub enabled: Option<bool>,
#[options(
meta = "",
help = "select fan <cpu/gpu> to modify. `mod-profile` required"
)]
pub fan: Option<FanCurvePU>,
#[options(
meta = "",
help = "data format = 30c:1%,49c:2%,59c:3%,69c:4%,79c:31%,89c:49%,99c:56%,109c:58%.
`--mod-profile` required. If '%' is omitted the fan range is 0-255"
)]
pub data: Option<CurveData>,
} }
+2 -2
View File
@@ -353,13 +353,13 @@ impl CtrlAnime<'static> {
pub fn set_state(&mut self, on: bool) -> zbus::fdo::Result<()> { pub fn set_state(&mut self, on: bool) -> zbus::fdo::Result<()> {
// Operations here need to be in specific order // Operations here need to be in specific order
if on { if on {
self.client.proxies().anime().set_led_power(on)?; self.client.proxies().anime().set_on_off(on)?;
// Let the inner loop run // Let the inner loop run
self.inner_early_return.store(false, Ordering::SeqCst); self.inner_early_return.store(false, Ordering::SeqCst);
} else { } else {
// Must make the inner run loop return early // Must make the inner run loop return early
self.inner_early_return.store(true, Ordering::SeqCst); self.inner_early_return.store(true, Ordering::SeqCst);
self.client.proxies().anime().set_led_power(on)?; self.client.proxies().anime().set_on_off(on)?;
} }
Ok(()) Ok(())
} }
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "daemon" name = "daemon"
version = "4.0.0" version = "4.0.7"
license = "MPL-2.0" license = "MPL-2.0"
readme = "README.md" readme = "README.md"
authors = ["Luke <luke@ljones.dev>"] authors = ["Luke <luke@ljones.dev>"]
+12 -2
View File
@@ -34,8 +34,18 @@ impl Config {
} else if let Ok(data) = serde_json::from_str(&buf) { } else if let Ok(data) = serde_json::from_str(&buf) {
config = data; config = data;
} else { } else {
warn!("Could not deserialise {}", CONFIG_PATH); warn!(
panic!("Please remove {} then restart asusd", CONFIG_PATH); "Could not deserialise {}.\nWill rename to {}-old and recreate config",
CONFIG_PATH, CONFIG_PATH
);
let cfg_old = CONFIG_PATH.to_string() + "-old";
std::fs::rename(CONFIG_PATH, cfg_old).unwrap_or_else(|err| {
panic!(
"Could not rename. Please remove {} then restart service: Error {}",
CONFIG_PATH, err
)
});
config = Self::new();
} }
} else { } else {
config = Self::new() config = Self::new()
+9 -11
View File
@@ -166,11 +166,17 @@ impl AnimeConfig {
info!("Updated config version to: {}", VERSION); info!("Updated config version to: {}", VERSION);
return config; return config;
} }
AnimeConfig::write_backup(buf);
warn!( warn!(
"Could not deserialise {}. Backed up as *-old", "Could not deserialise {}.\nWill rename to {}-old and recreate config",
ANIME_CONFIG_PATH ANIME_CONFIG_PATH, ANIME_CONFIG_PATH
); );
let cfg_old = ANIME_CONFIG_PATH.to_string() + "-old";
std::fs::rename(ANIME_CONFIG_PATH, cfg_old).unwrap_or_else(|err| {
panic!(
"Could not rename. Please remove {} then restart service: Error {}",
ANIME_CONFIG_PATH, err
)
});
} }
} }
AnimeConfig::create_default(&mut file) AnimeConfig::create_default(&mut file)
@@ -246,12 +252,4 @@ impl AnimeConfig {
file.write_all(json.as_bytes()) file.write_all(json.as_bytes())
.unwrap_or_else(|err| error!("Could not write config: {}", err)); .unwrap_or_else(|err| error!("Could not write config: {}", err));
} }
fn write_backup(buf: String) {
let mut path = ANIME_CONFIG_PATH.to_string();
path.push_str("-old");
let mut file = File::create(&path).expect("Couldn't overwrite config");
file.write_all(buf.as_bytes())
.unwrap_or_else(|err| error!("Could not write config: {}", err));
}
} }
+15 -9
View File
@@ -5,6 +5,7 @@ use ::zbus::Connection;
use log::{error, info, warn}; use log::{error, info, warn};
use logind_zbus::ManagerProxy; use logind_zbus::ManagerProxy;
use rog_anime::{ use rog_anime::{
error::AnimeError,
usb::{ usb::{
pkt_for_apply, pkt_for_flush, pkt_for_set_boot, pkt_for_set_on, pkts_for_init, PROD_ID, pkt_for_apply, pkt_for_flush, pkt_for_set_boot, pkt_for_set_on, pkts_for_init, PROD_ID,
VENDOR_ID, VENDOR_ID,
@@ -181,15 +182,20 @@ impl CtrlAnime {
for action in actions.iter() { for action in actions.iter() {
match action { match action {
ActionData::Animation(frames) => { ActionData::Animation(frames) => {
if rog_anime::run_animation(frames, thread_exit.clone(), &|frame| { if let Err(err) = rog_anime::run_animation(
if let Ok(lock) = inner.try_lock() { frames,
lock.write_data_buffer(frame); thread_exit.clone(),
} &|frame| {
Ok(()) inner
}) .try_lock()
.map_err(|err| warn!("rog_anime::run_animation: {}", err)) .map(|lock| lock.write_data_buffer(frame))
.is_err() .map_err(|err| {
{ warn!("rog_anime::run_animation: {}", err);
AnimeError::NoFrames
})
},
) {
warn!("rog_anime::run_animation: {}", err);
break 'main; break 'main;
}; };
+11 -2
View File
@@ -105,8 +105,17 @@ impl AuraConfig {
info!("Updated AuraConfig version"); info!("Updated AuraConfig version");
return config; return config;
} }
warn!("Could not deserialise {}", AURA_CONFIG_PATH); warn!(
panic!("Please remove {} then restart asusd", AURA_CONFIG_PATH); "Could not deserialise {}.\nWill rename to {}-old and recreate config",
AURA_CONFIG_PATH, AURA_CONFIG_PATH
);
let cfg_old = AURA_CONFIG_PATH.to_string() + "-old";
std::fs::rename(AURA_CONFIG_PATH, cfg_old).unwrap_or_else(|err| {
panic!(
"Could not rename. Please remove {} then restart service: Error {}",
AURA_CONFIG_PATH, err
)
});
} }
} }
AuraConfig::create_default(&mut file, supported_led_modes) AuraConfig::create_default(&mut file, supported_led_modes)
+6 -5
View File
@@ -30,7 +30,10 @@ pub struct CtrlCharge {
#[dbus_interface(name = "org.asuslinux.Daemon")] #[dbus_interface(name = "org.asuslinux.Daemon")]
impl CtrlCharge { impl CtrlCharge {
pub fn set_limit(&mut self, limit: u8) { pub fn set_limit(&mut self, limit: u8) -> Result<(), RogError> {
if !(20..=100).contains(&limit) {
return Err(RogError::ChargeLimit(limit));
}
if let Ok(mut config) = self.config.try_lock() { if let Ok(mut config) = self.config.try_lock() {
self.set(limit, &mut config) self.set(limit, &mut config)
.map_err(|err| { .map_err(|err| {
@@ -45,6 +48,7 @@ impl CtrlCharge {
}) })
.ok(); .ok();
} }
Ok(())
} }
pub fn limit(&self) -> i8 { pub fn limit(&self) -> i8 {
@@ -106,10 +110,7 @@ impl CtrlCharge {
pub(super) fn set(&self, limit: u8, config: &mut Config) -> Result<(), RogError> { pub(super) fn set(&self, limit: u8, config: &mut Config) -> Result<(), RogError> {
if !(20..=100).contains(&limit) { if !(20..=100).contains(&limit) {
warn!( return Err(RogError::ChargeLimit(limit));
"Unable to set battery charge limit, must be between 20-100: requested {}",
limit
);
} }
let path = Self::get_battery_path()?; let path = Self::get_battery_path()?;
+25 -12
View File
@@ -1,5 +1,4 @@
use log::{error, warn}; use log::{error, warn};
use rog_profiles::fan_curve_set::FanCurveSet;
use rog_profiles::{FanCurveProfiles, Profile}; use rog_profiles::{FanCurveProfiles, Profile};
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use std::fs::{File, OpenOptions}; use std::fs::{File, OpenOptions};
@@ -17,20 +16,22 @@ pub struct ProfileConfig {
impl ProfileConfig { impl ProfileConfig {
fn new(config_path: String) -> Self { fn new(config_path: String) -> Self {
let mut platform = ProfileConfig { Self {
config_path, config_path,
active_profile: Profile::get_active_profile().unwrap_or(Profile::Balanced), active_profile: Profile::Balanced,
fan_curves: None, fan_curves: None,
}; }
}
if let Ok(res) = FanCurveSet::is_supported() { pub fn set_defaults_and_save(&mut self) {
self.active_profile = Profile::get_active_profile().unwrap_or(Profile::Balanced);
if let Ok(res) = FanCurveProfiles::is_supported() {
if res { if res {
let curves = FanCurveProfiles::default(); let curves = FanCurveProfiles::default();
platform.fan_curves = Some(curves); self.fan_curves = Some(curves);
} }
} }
self.write();
platform
} }
pub fn load(config_path: String) -> Self { pub fn load(config_path: String) -> Self {
@@ -45,17 +46,29 @@ impl ProfileConfig {
if let Ok(read_len) = file.read_to_string(&mut buf) { if let Ok(read_len) = file.read_to_string(&mut buf) {
if read_len == 0 { if read_len == 0 {
config = Self::new(config_path); config = Self::new(config_path);
config.set_defaults_and_save();
} else if let Ok(data) = toml::from_str(&buf) { } else if let Ok(data) = toml::from_str(&buf) {
config = data; config = data;
config.config_path = config_path; config.config_path = config_path;
} else { } else {
warn!("Could not deserialise {}", config_path); warn!(
panic!("Please remove {} then restart service", config_path); "Could not deserialise {}.\nWill rename to {}-old and recreate config",
config_path, config_path
);
let cfg_old = config_path.clone() + "-old";
std::fs::rename(config_path.clone(), cfg_old).unwrap_or_else(|err| {
panic!(
"Could not rename. Please remove {} then restart service: Error {}",
config_path, err
)
});
config = Self::new(config_path);
config.set_defaults_and_save();
} }
} else { } else {
config = Self::new(config_path) config = Self::new(config_path);
config.set_defaults_and_save();
} }
config.write();
config config
} }
+61 -31
View File
@@ -1,17 +1,16 @@
use std::sync::{Arc, Mutex};
use crate::error::RogError; use crate::error::RogError;
use crate::GetSupported; use crate::{CtrlTask, GetSupported};
use log::{info, warn}; use log::{info, warn};
use rog_profiles::error::ProfileError; use rog_profiles::error::ProfileError;
use rog_profiles::fan_curve_set::FanCurveSet; use rog_profiles::{FanCurveProfiles, Profile};
use rog_profiles::Profile;
use rog_supported::PlatformProfileFunctions; use rog_supported::PlatformProfileFunctions;
use udev::Device;
use super::config::ProfileConfig; use super::config::ProfileConfig;
pub struct CtrlPlatformProfile { pub struct CtrlPlatformProfile {
pub config: ProfileConfig, pub config: ProfileConfig,
pub fan_device: Option<Device>,
} }
impl GetSupported for CtrlPlatformProfile { impl GetSupported for CtrlPlatformProfile {
@@ -22,25 +21,24 @@ impl GetSupported for CtrlPlatformProfile {
warn!( warn!(
r#" r#"
platform_profile kernel interface not found, your laptop does not support this, or the interface is missing. platform_profile kernel interface not found, your laptop does not support this, or the interface is missing.
To enable profile support you require a kernel with the following patch applied: To enable profile support you require a kernel version 5.15.2 minimum.
https://lkml.org/lkml/2021/8/18/1022
"# "#
); );
} }
let res = FanCurveSet::is_supported(); let res = FanCurveProfiles::is_supported();
let mut fan_curve_supported = res.is_err(); let mut fan_curve_supported = res.is_err();
if let Ok(r) = res { if let Ok(r) = res {
fan_curve_supported = r; fan_curve_supported = r;
}; };
if fan_curve_supported { if !fan_curve_supported {
info!( info!(
r#" r#"
fan curves kernel interface not found, your laptop does not support this, or the interface is missing. fan curves kernel interface not found, your laptop does not support this, or the interface is missing.
To enable fan-curve support you require a kernel with the following patch applied: To enable fan-curve support you require a kernel with the following patch applied:
https://lkml.org/lkml/2021/8/20/232 https://lkml.org/lkml/2021/10/23/250
Please note that as of 24/08/2021 this is not final. This patch has been accepted upstream for 5.17 kernel release.
"# "#
); );
} }
@@ -55,9 +53,12 @@ Please note that as of 24/08/2021 this is not final.
impl crate::Reloadable for CtrlPlatformProfile { impl crate::Reloadable for CtrlPlatformProfile {
/// Fetch the active profile and use that to set all related components up /// Fetch the active profile and use that to set all related components up
fn reload(&mut self) -> Result<(), RogError> { fn reload(&mut self) -> Result<(), RogError> {
if let Some(curves) = &self.config.fan_curves { if let Some(curves) = &mut self.config.fan_curves {
if let Ok(mut device) = FanCurveSet::get_device() { if let Ok(mut device) = FanCurveProfiles::get_device() {
curves.write_to_platform(self.config.active_profile, &mut device); // There is a possibility that the curve was default zeroed, so this call initialises
// the data from system read and we need to save it after
curves.write_profile_curve_to_platform(self.config.active_profile, &mut device)?;
self.config.write();
} }
} }
Ok(()) Ok(())
@@ -65,30 +66,20 @@ impl crate::Reloadable for CtrlPlatformProfile {
} }
impl CtrlPlatformProfile { impl CtrlPlatformProfile {
pub fn new(mut config: ProfileConfig, fan_device: Option<Device>) -> Result<Self, RogError> { pub fn new(config: ProfileConfig) -> Result<Self, RogError> {
if Profile::is_platform_profile_supported() { if Profile::is_platform_profile_supported() {
info!("Device has profile control available"); info!("Device has profile control available");
if let Some(ref device) = fan_device { if FanCurveProfiles::get_device().is_ok() {
let profile = config.active_profile; info!("Device has fan curves available");
config
.fan_curves
.as_mut()
.unwrap()
.read_from_dev_profile(profile, device);
} }
config.write();
return Ok(CtrlPlatformProfile { config, fan_device }); return Ok(CtrlPlatformProfile { config });
} }
Err(ProfileError::NotSupported.into()) Err(ProfileError::NotSupported.into())
} }
pub fn get_device(&self) -> Option<Device> {
self.fan_device.clone()
}
pub fn save_config(&self) { pub fn save_config(&self) {
self.config.write(); self.config.write();
} }
@@ -96,8 +87,6 @@ impl CtrlPlatformProfile {
/// Toggle to next profile in list. This will first read the config, switch, then write out /// Toggle to next profile in list. This will first read the config, switch, then write out
pub(super) fn set_next_profile(&mut self) -> Result<(), RogError> { pub(super) fn set_next_profile(&mut self) -> Result<(), RogError> {
// Read first just incase the user has modified the config before calling this // Read first just incase the user has modified the config before calling this
self.config.read();
match self.config.active_profile { match self.config.active_profile {
Profile::Balanced => { Profile::Balanced => {
Profile::set_profile(Profile::Performance)?; Profile::set_profile(Profile::Performance)?;
@@ -112,9 +101,50 @@ impl CtrlPlatformProfile {
self.config.active_profile = Profile::Balanced; self.config.active_profile = Profile::Balanced;
} }
} }
self.write_profile_curve_to_platform()?;
Ok(())
}
self.config.write(); /// Set the curve for the active profile active
pub(super) fn write_profile_curve_to_platform(&mut self) -> Result<(), RogError> {
if let Some(curves) = &mut self.config.fan_curves {
if let Ok(mut device) = FanCurveProfiles::get_device() {
curves.write_profile_curve_to_platform(self.config.active_profile, &mut device)?;
}
}
Ok(())
}
pub(super) fn set_active_curve_to_defaults(&mut self) -> Result<(), RogError> {
if let Some(curves) = self.config.fan_curves.as_mut() {
if let Ok(mut device) = FanCurveProfiles::get_device() {
curves.set_active_curve_to_defaults(self.config.active_profile, &mut device)?;
}
}
Ok(())
}
}
pub struct CtrlProfileTask {
ctrl: Arc<Mutex<CtrlPlatformProfile>>,
}
impl CtrlProfileTask {
pub fn new(ctrl: Arc<Mutex<CtrlPlatformProfile>>) -> Self {
Self { ctrl }
}
}
impl CtrlTask for CtrlProfileTask {
fn do_task(&self) -> Result<(), RogError> {
if let Ok(ref mut lock) = self.ctrl.try_lock() {
let new_profile = Profile::get_active_profile().unwrap();
if new_profile != lock.config.active_profile {
lock.config.active_profile = new_profile;
lock.write_profile_curve_to_platform()?;
lock.save_config();
}
}
Ok(()) Ok(())
} }
} }
+50 -31
View File
@@ -35,11 +35,13 @@ impl ProfileZbus {
)) ))
} }
/// Toggle to next platform_profile. Names provided by `Profiles` /// Toggle to next platform_profile. Names provided by `Profiles`.
/// If fan-curves are supported will also activate a fan curve for profile.
fn next_profile(&mut self) { fn next_profile(&mut self) {
if let Ok(mut ctrl) = self.inner.try_lock() { if let Ok(mut ctrl) = self.inner.try_lock() {
ctrl.set_next_profile() ctrl.set_next_profile()
.unwrap_or_else(|err| warn!("{}", err)); .unwrap_or_else(|err| warn!("{}", err));
ctrl.save_config();
} }
self.do_notification(); self.do_notification();
} }
@@ -61,9 +63,12 @@ impl ProfileZbus {
// Read first just incase the user has modified the config before calling this // Read first just incase the user has modified the config before calling this
ctrl.config.read(); ctrl.config.read();
Profile::set_profile(profile) Profile::set_profile(profile)
.map_err(|e| warn!("Profile::set_profile, {}", e)) .map_err(|e| warn!("set_profile, {}", e))
.ok(); .ok();
ctrl.config.active_profile = profile; ctrl.config.active_profile = profile;
ctrl.write_profile_curve_to_platform()
.map_err(|e| warn!("write_profile_curve_to_platform, {}", e))
.ok();
ctrl.save_config(); ctrl.save_config();
} }
@@ -84,14 +89,23 @@ impl ProfileZbus {
)) ))
} }
/// Get a list of profiles that have fan-curves enabled. /// Set a profile fan curve enabled status. Will also activate a fan curve if in the
fn set_enabled_fan_profiles(&mut self, profiles: Vec<Profile>) -> zbus::fdo::Result<()> { /// same profile mode
fn set_fan_curve_enabled(&mut self, profile: Profile, enabled: bool) -> zbus::fdo::Result<()> {
if let Ok(mut ctrl) = self.inner.try_lock() { if let Ok(mut ctrl) = self.inner.try_lock() {
ctrl.config.read(); ctrl.config.read();
if let Some(curves) = &mut ctrl.config.fan_curves { return if let Some(curves) = &mut ctrl.config.fan_curves {
curves.set_enabled_curve_profiles(profiles); curves.set_profile_curve_enabled(profile, enabled);
}
return Err(Error::Failed(UNSUPPORTED_MSG.to_string())); ctrl.write_profile_curve_to_platform()
.map_err(|e| warn!("write_profile_curve_to_platform, {}", e))
.ok();
ctrl.save_config();
Ok(())
} else {
Err(Error::Failed(UNSUPPORTED_MSG.to_string()))
};
} }
Err(Error::Failed( Err(Error::Failed(
"Failed to get enabled fan curve names".to_string(), "Failed to get enabled fan curve names".to_string(),
@@ -99,46 +113,51 @@ impl ProfileZbus {
} }
/// Get the fan-curve data for the currently active Profile /// Get the fan-curve data for the currently active Profile
fn active_fan_curve_data(&mut self) -> zbus::fdo::Result<FanCurveSet> { fn fan_curve_data(&mut self, profile: Profile) -> zbus::fdo::Result<FanCurveSet> {
if let Ok(mut ctrl) = self.inner.try_lock() { if let Ok(mut ctrl) = self.inner.try_lock() {
ctrl.config.read(); ctrl.config.read();
if let Some(curves) = &ctrl.config.fan_curves { if let Some(curves) = &ctrl.config.fan_curves {
return Ok((*curves.get_active_fan_curves()).clone()); let curve = curves.get_fan_curves_for(profile);
return Ok(curve.clone());
} }
return Err(Error::Failed(UNSUPPORTED_MSG.to_string())); return Err(Error::Failed(UNSUPPORTED_MSG.to_string()));
} }
Err(Error::Failed("Failed to get fan curve data".to_string())) Err(Error::Failed("Failed to get fan curve data".to_string()))
} }
/// Get fan-curve data for each Profile as an array of objects /// Set the fan curve for the specified profile.
fn fan_curves(&self) -> zbus::fdo::Result<Vec<FanCurveSet>> { /// Will also activate the fan curve if the user is in the same mode.
fn set_fan_curve(&self, profile: Profile, curve: CurveData) -> zbus::fdo::Result<()> {
if let Ok(mut ctrl) = self.inner.try_lock() { if let Ok(mut ctrl) = self.inner.try_lock() {
ctrl.config.read(); ctrl.config.read();
if let Some(curves) = &ctrl.config.fan_curves { if let Some(curves) = &mut ctrl.config.fan_curves {
return Ok(curves.get_all_fan_curves()); curves
} .save_fan_curve(curve, profile)
return Err(Error::Failed(UNSUPPORTED_MSG.to_string())); .map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?;
}
Err(Error::Failed("Failed to get all fan curves".to_string()))
}
/// Set this fan-curve data
fn set_fan_curve(&self, curve: CurveData) -> zbus::fdo::Result<()> {
if let Ok(mut ctrl) = self.inner.try_lock() {
ctrl.config.read();
let profile = ctrl.config.active_profile;
if let Some(mut device) = ctrl.get_device() {
if let Some(curves) = &mut ctrl.config.fan_curves {
curves.write_and_set_fan_curve(curve, profile, &mut device);
}
} else { } else {
return Err(Error::Failed(UNSUPPORTED_MSG.to_string())); return Err(Error::Failed(UNSUPPORTED_MSG.to_string()));
} }
ctrl.write_profile_curve_to_platform()
.map_err(|e| warn!("Profile::set_profile, {}", e))
.ok();
ctrl.save_config(); ctrl.save_config();
} }
Ok(())
}
Err(Error::Failed("Failed to set fan curves".to_string())) /// Reset the stored (self) and device curve to the defaults of the platform.
///
/// Each platform_profile has a different default and the defualt can be read
/// only for the currently active profile.
fn set_active_curve_to_defaults(&self) -> zbus::fdo::Result<()> {
if let Ok(mut ctrl) = self.inner.try_lock() {
ctrl.config.read();
ctrl.set_active_curve_to_defaults()
.map_err(|e| warn!("Profile::set_active_curve_to_defaults, {}", e))
.ok();
ctrl.save_config();
}
Ok(())
} }
#[dbus_interface(signal)] #[dbus_interface(signal)]
+56 -51
View File
@@ -1,3 +1,15 @@
use std::error::Error;
use std::io::Write;
use std::sync::Arc;
use std::sync::Mutex;
use std::thread::sleep;
use std::time::Duration;
use std::{env, thread};
use ::zbus::{fdo, Connection, ObjectServer};
use log::LevelFilter;
use log::{error, info, warn};
use daemon::ctrl_anime::config::AnimeConfig; use daemon::ctrl_anime::config::AnimeConfig;
use daemon::ctrl_anime::zbus::CtrlAnimeZbus; use daemon::ctrl_anime::zbus::CtrlAnimeZbus;
use daemon::ctrl_anime::*; use daemon::ctrl_anime::*;
@@ -7,6 +19,9 @@ use daemon::ctrl_aura::controller::{
}; };
use daemon::ctrl_charge::CtrlCharge; use daemon::ctrl_charge::CtrlCharge;
use daemon::ctrl_profiles::config::ProfileConfig; use daemon::ctrl_profiles::config::ProfileConfig;
use daemon::ctrl_profiles::controller::CtrlProfileTask;
use daemon::ctrl_rog_bios::CtrlRogBios;
use daemon::error::RogError;
use daemon::{ use daemon::{
config::Config, ctrl_supported::SupportedFunctions, laptops::print_board_info, GetSupported, config::Config, ctrl_supported::SupportedFunctions, laptops::print_board_info, GetSupported,
}; };
@@ -14,20 +29,9 @@ use daemon::{
ctrl_profiles::{controller::CtrlPlatformProfile, zbus::ProfileZbus}, ctrl_profiles::{controller::CtrlPlatformProfile, zbus::ProfileZbus},
laptops::LaptopLedData, laptops::LaptopLedData,
}; };
use ::zbus::{fdo, Connection, ObjectServer};
use daemon::{CtrlTask, Reloadable, ZbusAdd}; use daemon::{CtrlTask, Reloadable, ZbusAdd};
use log::LevelFilter;
use log::{error, info, warn};
use rog_dbus::DBUS_NAME; use rog_dbus::DBUS_NAME;
use rog_profiles::fan_curve_set::FanCurveSet; use rog_profiles::Profile;
use std::env;
use std::error::Error;
use std::io::Write;
use std::sync::Arc;
use std::sync::Mutex;
use daemon::ctrl_rog_bios::CtrlRogBios;
static PROFILE_CONFIG_PATH: &str = "/etc/asusd/profile.conf"; static PROFILE_CONFIG_PATH: &str = "/etc/asusd/profile.conf";
@@ -70,8 +74,6 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
print_board_info(); print_board_info();
println!("{}", serde_json::to_string_pretty(&supported)?); println!("{}", serde_json::to_string_pretty(&supported)?);
// Collect tasks for task thread
let mut tasks: Vec<Box<dyn CtrlTask + Send>> = Vec::new();
// Start zbus server // Start zbus server
let connection = Connection::new_system()?; let connection = Connection::new_system()?;
let fdo_connection = fdo::DBusProxy::new(&connection)?; let fdo_connection = fdo::DBusProxy::new(&connection)?;
@@ -108,23 +110,32 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
} }
} }
let fan_device = if let Ok(res) = FanCurveSet::get_device() { if Profile::is_platform_profile_supported() {
Some(res) let profile_config = ProfileConfig::load(PROFILE_CONFIG_PATH.into());
} else { match CtrlPlatformProfile::new(profile_config) {
None Ok(mut ctrl) => {
}; ctrl.reload()
let profile_config = ProfileConfig::load(PROFILE_CONFIG_PATH.into()); .unwrap_or_else(|err| warn!("Profile control: {}", err));
match CtrlPlatformProfile::new(profile_config, fan_device) {
Ok(mut ctrl) => {
ctrl.reload()
.unwrap_or_else(|err| warn!("Profile control: {}", err));
let tmp = Arc::new(Mutex::new(ctrl)); let tmp = Arc::new(Mutex::new(ctrl));
ProfileZbus::new(tmp).add_to_server(&mut object_server); ProfileZbus::new(tmp.clone()).add_to_server(&mut object_server);
}
Err(err) => { let task = CtrlProfileTask::new(tmp);
error!("Profile control: {}", err); thread::Builder::new().name("profile tasks".into()).spawn(
move || -> Result<(), RogError> {
loop {
task.do_task()?;
sleep(Duration::from_millis(100));
}
},
)?;
}
Err(err) => {
error!("Profile control: {}", err);
}
} }
} else {
warn!("platform_profile support not found. This requires kernel 5.15.x or the patch applied: https://lkml.org/lkml/2021/8/18/1022");
} }
match CtrlAnime::new(AnimeConfig::load()) { match CtrlAnime::new(AnimeConfig::load()) {
@@ -139,7 +150,14 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
let zbus = CtrlAnimeZbus(inner.clone()); let zbus = CtrlAnimeZbus(inner.clone());
zbus.add_to_server(&mut object_server); zbus.add_to_server(&mut object_server);
tasks.push(Box::new(CtrlAnimeTask::new(inner))); let task = CtrlAnimeTask::new(inner);
thread::Builder::new().name("anime tasks".into()).spawn(
move || -> Result<(), RogError> {
loop {
task.do_task()?;
}
},
)?;
} }
Err(err) => { Err(err) => {
error!("AniMe control: {}", err); error!("AniMe control: {}", err);
@@ -158,39 +176,26 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
.unwrap_or_else(|err| warn!("Keyboard LED control: {}", err)); .unwrap_or_else(|err| warn!("Keyboard LED control: {}", err));
CtrlKbdLedZbus::new(inner.clone()).add_to_server(&mut object_server); CtrlKbdLedZbus::new(inner.clone()).add_to_server(&mut object_server);
let task = CtrlKbdLedTask::new(inner); let task = CtrlKbdLedTask::new(inner);
tasks.push(Box::new(task)); thread::Builder::new().name("keyboard tasks".into()).spawn(
move || -> Result<(), RogError> {
loop {
task.do_task()?;
}
},
)?;
} }
Err(err) => { Err(err) => {
error!("Keyboard control: {}", err); error!("Keyboard control: {}", err);
} }
} }
// TODO: implement messaging between threads to check fails
// Run tasks
let handle = std::thread::Builder::new()
.name("asusd watch".to_string())
.spawn(move || loop {
std::thread::sleep(std::time::Duration::from_millis(100));
for ctrl in tasks.iter() {
ctrl.do_task()
.map_err(|err| {
warn!("do_task error: {}", err);
})
.ok();
}
});
// Request dbus name after finishing initalizing all functions // Request dbus name after finishing initalizing all functions
fdo_connection.request_name(DBUS_NAME, fdo::RequestNameFlags::ReplaceExisting.into())?; fdo_connection.request_name(DBUS_NAME, fdo::RequestNameFlags::ReplaceExisting.into())?;
// Loop to check errors and iterate zbus server // Loop to check errors and iterate zbus server
loop { loop {
if let Err(err) = &handle {
error!("{}", err);
}
if let Err(err) = object_server.try_handle_next() { if let Err(err) = object_server.try_handle_next() {
error!("{}", err); error!("{}", err);
} }
+2
View File
@@ -22,6 +22,7 @@ pub enum RogError {
Modprobe(String), Modprobe(String),
Io(std::io::Error), Io(std::io::Error),
Zbus(zbus::Error), Zbus(zbus::Error),
ChargeLimit(u8),
} }
impl fmt::Display for RogError { impl fmt::Display for RogError {
@@ -46,6 +47,7 @@ impl fmt::Display for RogError {
RogError::Modprobe(detail) => write!(f, "Modprobe error: {}", detail), RogError::Modprobe(detail) => write!(f, "Modprobe error: {}", detail),
RogError::Io(detail) => write!(f, "std::io error: {}", detail), RogError::Io(detail) => write!(f, "std::io error: {}", detail),
RogError::Zbus(detail) => write!(f, "Zbus error: {}", detail), RogError::Zbus(detail) => write!(f, "Zbus error: {}", detail),
RogError::ChargeLimit(value) => write!(f, "Invalid charging limit, not in range 20-100%: {}", value),
} }
} }
} }
+1 -1
View File
@@ -27,7 +27,7 @@ pub mod laptops;
/// Fetch all supported functions for the laptop /// Fetch all supported functions for the laptop
pub mod ctrl_supported; pub mod ctrl_supported;
mod error; pub mod error;
use crate::error::RogError; use crate::error::RogError;
use config::Config; use config::Config;
+19 -4
View File
@@ -42,14 +42,14 @@ per_key = false
[[led_data]] [[led_data]]
prod_family = "ROG Strix" prod_family = "ROG Strix"
board_names = ["G531GW", "G533QR", "G733QS", "G733QR"] board_names = ["G531GW", "G533QR", "G533QS", "G733QS", "G733QR", "G513QR", "G713QR"]
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Star", "Rain", "Highlight", "Laser", "Ripple", "Pulse", "Comet", "Flash"] standard = ["Static", "Breathe", "Strobe", "Rainbow", "Star", "Rain", "Highlight", "Laser", "Ripple", "Pulse", "Comet", "Flash"]
multizone = false multizone = false
per_key = true per_key = true
[[led_data]] [[led_data]]
prod_family = "ROG Strix" prod_family = "ROG Strix"
board_names = ["GX531", "G512LV", "G712LV", "G712LW", "G513IH", "G513QY"] board_names = ["G513QE", "GX531", "G512LV", "G712LV", "G712LW", "G513IH", "G513QY", "G713QM"]
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Pulse"] standard = ["Static", "Breathe", "Strobe", "Rainbow", "Pulse"]
multizone = true multizone = true
per_key = false per_key = false
@@ -96,6 +96,14 @@ standard = ["Static", "Breathe", "Pulse"]
multizone = false multizone = false
per_key = false per_key = false
# GA503QE at higher priority (first match) than GA503Q
[[led_data]]
prod_family = "ROG Zephyrus G15"
board_names = ["GA503QE"]
standard = ["Static", "Breathe", "Pulse"]
multizone = false
per_key = false
[[led_data]] [[led_data]]
prod_family = "ROG Zephyrus G15" prod_family = "ROG Zephyrus G15"
board_names = ["GA503Q"] board_names = ["GA503Q"]
@@ -112,7 +120,14 @@ per_key = true
[[led_data]] [[led_data]]
prod_family = "ROG Zephyrus Duo 15 SE" prod_family = "ROG Zephyrus Duo 15 SE"
board_name = ["GX551Q"] board_names = ["GX551Q"]
standard ["Static", "Breathe", "Pulse", "Rainbow", "Strobe"] standard = ["Static", "Breathe", "Strobe", "Rainbow", "Pulse"]
multizone = false multizone = false
per_key = true per_key = true
[[led_data]]
prod_family = "ROG Flow X13"
board_names = ["GV301QH", "GV301QE"]
standard = ["Static", "Breathe", "Pulse"]
multizone = false
per_key = false
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "rog_anime" name = "rog_anime"
version = "1.1.0" version = "1.3.0"
license = "MPL-2.0" license = "MPL-2.0"
readme = "README.md" readme = "README.md"
authors = ["Luke <luke@ljones.dev>"] authors = ["Luke <luke@ljones.dev>"]
+4 -4
View File
@@ -88,7 +88,7 @@ pub struct AnimeGif(Vec<AnimeFrame>, AnimTime);
impl AnimeGif { impl AnimeGif {
/// Create an animation using the 74x36 ASUS gif format /// Create an animation using the 74x36 ASUS gif format
#[inline] #[inline]
pub fn create_diagonal_gif( pub fn from_diagonal_gif(
file_name: &Path, file_name: &Path,
duration: AnimTime, duration: AnimTime,
brightness: f32, brightness: f32,
@@ -130,7 +130,7 @@ impl AnimeGif {
/// Create an animation using the 74x36 ASUS gif format from a png /// Create an animation using the 74x36 ASUS gif format from a png
#[inline] #[inline]
pub fn create_diagonal_png( pub fn from_diagonal_png(
file_name: &Path, file_name: &Path,
duration: AnimTime, duration: AnimTime,
brightness: f32, brightness: f32,
@@ -159,7 +159,7 @@ impl AnimeGif {
/// Create an animation using a gif of any size. This method must precompute the /// Create an animation using a gif of any size. This method must precompute the
/// result. /// result.
#[inline] #[inline]
pub fn create_png_gif( pub fn from_gif(
file_name: &Path, file_name: &Path,
scale: f32, scale: f32,
angle: f32, angle: f32,
@@ -231,7 +231,7 @@ impl AnimeGif {
/// will be 1 second long. If `AnimTime::Cycles` is specified for `duration` then this can /// will be 1 second long. If `AnimTime::Cycles` is specified for `duration` then this can
/// be considered how many seconds the image will show for. /// be considered how many seconds the image will show for.
#[inline] #[inline]
pub fn create_png_static( pub fn from_png(
file_name: &Path, file_name: &Path,
scale: f32, scale: f32,
angle: f32, angle: f32,
+5 -7
View File
@@ -69,7 +69,7 @@ impl ActionData {
file, file,
time, time,
brightness, brightness,
} => ActionData::Animation(AnimeGif::create_diagonal_gif(file, *time, *brightness)?), } => ActionData::Animation(AnimeGif::from_diagonal_gif(file, *time, *brightness)?),
ActionLoader::AsusImage { ActionLoader::AsusImage {
file, file,
time, time,
@@ -80,9 +80,7 @@ impl ActionData {
let data = <AnimeDataBuffer>::from(&image); let data = <AnimeDataBuffer>::from(&image);
ActionData::Image(Box::new(data)) ActionData::Image(Box::new(data))
} }
_ => { _ => ActionData::Animation(AnimeGif::from_diagonal_png(file, *time, *brightness)?),
ActionData::Animation(AnimeGif::create_diagonal_png(file, *time, *brightness)?)
}
}, },
ActionLoader::ImageAnimation { ActionLoader::ImageAnimation {
file, file,
@@ -94,7 +92,7 @@ impl ActionData {
} => { } => {
if let Some(ext) = file.extension() { if let Some(ext) = file.extension() {
if ext.to_string_lossy().to_lowercase() == "png" { if ext.to_string_lossy().to_lowercase() == "png" {
return Ok(ActionData::Animation(AnimeGif::create_png_static( return Ok(ActionData::Animation(AnimeGif::from_png(
file, file,
*scale, *scale,
*angle, *angle,
@@ -104,7 +102,7 @@ impl ActionData {
)?)); )?));
} }
} }
ActionData::Animation(AnimeGif::create_png_gif( ActionData::Animation(AnimeGif::from_gif(
file, file,
*scale, *scale,
*angle, *angle,
@@ -129,7 +127,7 @@ impl ActionData {
let data = <AnimeDataBuffer>::from(&image); let data = <AnimeDataBuffer>::from(&image);
ActionData::Image(Box::new(data)) ActionData::Image(Box::new(data))
} }
_ => ActionData::Animation(AnimeGif::create_png_static( _ => ActionData::Animation(AnimeGif::from_png(
file, file,
*scale, *scale,
*angle, *angle,
+1 -2
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "rog_dbus" name = "rog_dbus"
version = "4.0.0" version = "4.0.2"
license = "MPL-2.0" license = "MPL-2.0"
readme = "README.md" readme = "README.md"
authors = ["Luke <luke@ljones.dev>"] authors = ["Luke <luke@ljones.dev>"]
@@ -14,7 +14,6 @@ rog_anime = { path = "../rog-anime" }
rog_aura = { path = "../rog-aura" } rog_aura = { path = "../rog-aura" }
rog_profiles = { path = "../rog-profiles" } rog_profiles = { path = "../rog-profiles" }
rog_supported = { path = "../rog-supported" } rog_supported = { path = "../rog-supported" }
supergfxctl = { git = "https://gitlab.com/asus-linux/supergfxctl.git", tag = "2.0.0" }
zbus = "^1.9" zbus = "^1.9"
zbus_macros = "^1.9" zbus_macros = "^1.9"
zvariant = "^2.8" zvariant = "^2.8"
-1
View File
@@ -1,5 +1,4 @@
pub static DBUS_NAME: &str = "org.asuslinux.Daemon"; pub static DBUS_NAME: &str = "org.asuslinux.Daemon";
pub static DBUS_NAME_GFX: &str = "org.supergfxctl.Daemon";
pub static DBUS_PATH: &str = "/org/asuslinux/Daemon"; pub static DBUS_PATH: &str = "/org/asuslinux/Daemon";
pub static DBUS_IFACE: &str = "org.asuslinux.Daemon"; pub static DBUS_IFACE: &str = "org.asuslinux.Daemon";
+12 -7
View File
@@ -45,18 +45,23 @@ impl<'a> AnimeProxy<'a> {
&self.0 &self.0
} }
/// Set whether the AniMe will show boot, suspend, or off animations
#[inline]
pub fn set_system_animations(&self, on: bool) -> Result<()> {
self.0.set_boot_on_off(on)
}
/// Set whether the AniMe is displaying images/data /// Set whether the AniMe is displaying images/data
#[inline] #[inline]
pub fn set_led_power(&self, on: bool) -> Result<()> { pub fn set_on_off(&self, on: bool) -> Result<()> {
self.0.set_on_off(on) self.0.set_on_off(on)
} }
/// Set the global AniMe brightness
pub fn set_brightness(&self, bright: f32) -> Result<()> {
self.0.set_brightness(bright)
}
/// Set whether the AniMe will show boot, suspend, or off animations
#[inline]
pub fn set_boot_on_off(&self, on: bool) -> Result<()> {
self.0.set_boot_on_off(on)
}
/// Writes a data stream of length. Will force system thread to exit until it is restarted /// Writes a data stream of length. Will force system thread to exit until it is restarted
#[inline] #[inline]
pub fn write(&self, input: AnimeDataBuffer) -> Result<()> { pub fn write(&self, input: AnimeDataBuffer) -> Result<()> {
+61 -15
View File
@@ -21,7 +21,10 @@
use std::sync::mpsc::Sender; use std::sync::mpsc::Sender;
use rog_profiles::{fan_curve_set::FanCurveSet, Profile}; use rog_profiles::{
fan_curve_set::{CurveData, FanCurveSet},
Profile,
};
use zbus::{dbus_proxy, Connection, Result}; use zbus::{dbus_proxy, Connection, Result};
#[dbus_proxy( #[dbus_proxy(
@@ -29,29 +32,37 @@ use zbus::{dbus_proxy, Connection, Result};
default_path = "/org/asuslinux/Profile" default_path = "/org/asuslinux/Profile"
)] )]
trait Daemon { trait Daemon {
/// Get the active `Profile` data /// Get the fan-curve data for the currently active Profile
fn active_fan_curve_data(&self) -> zbus::Result<FanCurveSet>; fn fan_curve_data(&self, profile: Profile) -> zbus::Result<FanCurveSet>;
/// Profile, get the active profile /// Fetch the active profile name
fn active_profile(&self) -> zbus::Result<Profile>; fn active_profile(&self) -> zbus::Result<Profile>;
/// Get enabled fan curves /// Get a list of profiles that have fan-curves enabled.
fn enabled_fan_profiles(&self) -> zbus::Result<Vec<Profile>>; fn enabled_fan_profiles(&self) -> zbus::Result<Vec<Profile>>;
/// Get all fan curve data /// Toggle to next platform_profile. Names provided by `Profiles`.
fn fan_curves(&self) -> zbus::Result<Vec<FanCurveSet>>; /// If fan-curves are supported will also activate a fan curve for profile.
/// NextProfile method
fn next_profile(&self) -> zbus::Result<()>; fn next_profile(&self) -> zbus::Result<()>;
/// Profiles method /// Fetch profile names
fn profiles(&self) -> zbus::Result<Vec<Profile>>; fn profiles(&self) -> zbus::Result<Vec<Profile>>;
/// Set the specific profile as active /// Set this platform_profile name as active
fn set_active_profile(&self, profile: Profile) -> zbus::Result<()>; fn set_active_profile(&self, profile: Profile) -> zbus::Result<()>;
/// Set a fan curve. If a field is empty then the exisiting saved curve is used /// Set a profile fan curve enabled status. Will also activate a fan curve.
fn set_fan_curve(&self, curve: FanCurveSet) -> zbus::Result<()>; fn set_fan_curve_enabled(&self, profile: Profile, enabled: bool) -> zbus::Result<()>;
/// Set the fan curve for the specified profile, or the profile the user is
/// currently in if profile == None. Will also activate the fan curve.
fn set_fan_curve(&self, profile: Profile, curve: CurveData) -> zbus::Result<()>;
/// Reset the stored (self) and device curve to the defaults of the platform.
///
/// Each platform_profile has a different default and the defualt can be read
/// only for the currently active profile.
fn set_active_curve_to_defaults(&self) -> zbus::Result<()>;
/// NotifyProfile signal /// NotifyProfile signal
#[dbus_proxy(signal)] #[dbus_proxy(signal)]
@@ -72,8 +83,18 @@ impl<'a> ProfileProxy<'a> {
} }
#[inline] #[inline]
pub fn profiles(&self) -> Result<Vec<Profile>> { pub fn active_profile(&self) -> zbus::Result<Profile> {
self.0.profiles() self.0.active_profile()
}
#[inline]
pub fn enabled_fan_profiles(&self) -> zbus::Result<Vec<Profile>> {
self.0.enabled_fan_profiles()
}
#[inline]
pub fn fan_curve_data(&self, profile: Profile) -> zbus::Result<FanCurveSet> {
self.0.fan_curve_data(profile)
} }
#[inline] #[inline]
@@ -81,6 +102,31 @@ impl<'a> ProfileProxy<'a> {
self.0.next_profile() self.0.next_profile()
} }
#[inline]
pub fn profiles(&self) -> Result<Vec<Profile>> {
self.0.profiles()
}
#[inline]
pub fn set_active_profile(&self, profile: Profile) -> zbus::Result<()> {
self.0.set_active_profile(profile)
}
#[inline]
pub fn set_fan_curve_enabled(&self, profile: Profile, enabled: bool) -> zbus::Result<()> {
self.0.set_fan_curve_enabled(profile, enabled)
}
#[inline]
pub fn set_fan_curve(&self, curve: CurveData, profile: Profile) -> zbus::Result<()> {
self.0.set_fan_curve(profile, curve)
}
#[inline]
pub fn set_active_curve_to_defaults(&self) -> zbus::Result<()> {
self.0.set_active_curve_to_defaults()
}
#[inline] #[inline]
pub fn connect_notify_profile(&self, send: Sender<Profile>) -> zbus::fdo::Result<()> { pub fn connect_notify_profile(&self, send: Sender<Profile>) -> zbus::fdo::Result<()> {
self.0.connect_notify_profile(move |data| { self.0.connect_notify_profile(move |data| {
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "rog_profiles" name = "rog_profiles"
version = "1.0.0" version = "1.1.3"
authors = ["Luke D. Jones <luke@ljones.dev>"] authors = ["Luke D. Jones <luke@ljones.dev>"]
edition = "2018" edition = "2018"
+18 -2
View File
@@ -8,7 +8,12 @@ pub enum ProfileError {
NotSupported, NotSupported,
NotFound(String), NotFound(String),
Io(std::io::Error), Io(std::io::Error),
//Zbus(zbus::Error), ParseProfileName,
ParseFanCurveDigit(std::num::ParseIntError),
/// (pwm/temp, prev, next)
ParseFanCurvePrevHigher(&'static str, u8, u8),
ParseFanCurvePercentOver100(u8),
// Zbus(zbus::Error),
} }
impl fmt::Display for ProfileError { impl fmt::Display for ProfileError {
@@ -21,7 +26,18 @@ impl fmt::Display for ProfileError {
ProfileError::NotSupported => write!(f, "Not supported"), ProfileError::NotSupported => write!(f, "Not supported"),
ProfileError::NotFound(deets) => write!(f, "Not found: {}", deets), ProfileError::NotFound(deets) => write!(f, "Not found: {}", deets),
ProfileError::Io(detail) => write!(f, "std::io error: {}", detail), ProfileError::Io(detail) => write!(f, "std::io error: {}", detail),
//Error::Zbus(detail) => write!(f, "Zbus error: {}", detail), ProfileError::ParseProfileName => write!(f, "Invalid profile name"),
ProfileError::ParseFanCurveDigit(e) => {
write!(f, "Could not parse number to 0-255: {}", e)
}
ProfileError::ParseFanCurvePrevHigher(part, prev, next) => write!(
f,
"Invalid {}, previous value {} is higher than next value {}",
part, prev, next
),
ProfileError::ParseFanCurvePercentOver100(value) => {
write!(f, "Invalid percentage, {} is higher than 100", value)
} // Error::Zbus(detail) => write!(f, "Zbus error: {}", detail),
} }
} }
} }
+200 -79
View File
@@ -4,24 +4,24 @@ use udev::Device;
#[cfg(feature = "dbus")] #[cfg(feature = "dbus")]
use zvariant_derive::Type; use zvariant_derive::Type;
use crate::{error::ProfileError, write_to_fan, FanCurvePU}; use crate::{error::ProfileError, FanCurvePU};
pub fn pwm_str(fan: char, index: char) -> String { pub(crate) fn pwm_str(fan: char, index: usize) -> String {
let mut buf = "pwm1_auto_point1_pwm".to_string(); let mut buf = "pwm1_auto_point1_pwm".to_string();
unsafe { unsafe {
let tmp = buf.as_bytes_mut(); let tmp = buf.as_bytes_mut();
tmp[3] = fan as u8; tmp[3] = fan as u8;
tmp[15] = index as u8; tmp[15] = char::from_digit(index as u32 + 1, 10).unwrap() as u8;
} }
buf buf
} }
pub fn temp_str(fan: char, index: char) -> String { pub(crate) fn temp_str(fan: char, index: usize) -> String {
let mut buf = "pwm1_auto_point1_temp".to_string(); let mut buf = "pwm1_auto_point1_temp".to_string();
unsafe { unsafe {
let tmp = buf.as_bytes_mut(); let tmp = buf.as_bytes_mut();
tmp[3] = fan as u8; tmp[3] = fan as u8;
tmp[15] = index as u8; tmp[15] = char::from_digit(index as u32 + 1, 10).unwrap() as u8;
} }
buf buf
} }
@@ -29,22 +29,152 @@ pub fn temp_str(fan: char, index: char) -> String {
#[cfg_attr(feature = "dbus", derive(Type))] #[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Deserialize, Serialize, Default, Debug, Clone)] #[derive(Deserialize, Serialize, Default, Debug, Clone)]
pub struct CurveData { pub struct CurveData {
pub fan: FanCurvePU, pub(crate) fan: FanCurvePU,
pub pwm: [u8; 8], pub(crate) pwm: [u8; 8],
pub temp: [u8; 8], pub(crate) temp: [u8; 8],
}
impl std::str::FromStr for CurveData {
type Err = ProfileError;
/// Parse a string to the correct values that the fan curve kernel driver expects
///
/// If the fan curve is given with percentage char '%' then the fan power values are converted
/// otherwise the expected fan power range is 0-255.
///
/// Temperature range is 0-255 in degrees C. You don't want to be setting over 100.
fn from_str(input: &str) -> Result<Self, Self::Err> {
let mut temp = [0u8; 8];
let mut pwm = [0u8; 8];
let mut temp_prev = 0;
let mut pwm_prev = 0;
let mut percentages = false;
for (index, value) in input.split(',').enumerate() {
for (select, num) in value.splitn(2, |c| c == 'c' || c == ':').enumerate() {
if num.contains('%') {
percentages = true;
}
let r = num.trim_matches(|c| c == 'c' || c == ':' || c == '%');
let r = r.parse::<u8>().map_err(ProfileError::ParseFanCurveDigit)?;
if select == 0 {
if temp_prev > r {
return Err(ProfileError::ParseFanCurvePrevHigher(
"temperature",
temp_prev,
r,
));
}
temp_prev = r;
temp[index] = r;
} else {
let mut p = r;
if percentages {
p *= 255 / 100;
if p > 100 {
return Err(ProfileError::ParseFanCurvePercentOver100(r));
}
}
if pwm_prev > p {
return Err(ProfileError::ParseFanCurvePrevHigher(
"percentage",
pwm_prev,
p,
));
}
pwm_prev = p;
pwm[index] = p;
}
}
}
Ok(Self {
fan: FanCurvePU::CPU,
pwm,
temp,
})
}
}
impl CurveData {
pub fn set_fan(&mut self, fan: FanCurvePU) {
self.fan = fan;
}
fn set_val_from_attr(tmp: &str, device: &Device, buf: &mut [u8; 8]) {
if let Some(n) = tmp.chars().nth(15) {
let i = n.to_digit(10).unwrap() as usize;
let d = device.attribute_value(tmp).unwrap();
let d: u8 = d.to_string_lossy().parse().unwrap();
buf[i - 1] = d;
}
}
fn read_from_device(&mut self, device: &Device) {
for attr in device.attributes() {
let tmp = attr.name().to_string_lossy();
if tmp.starts_with("pwm1") && tmp.ends_with("_temp") {
Self::set_val_from_attr(tmp.as_ref(), device, &mut self.temp)
}
if tmp.starts_with("pwm1") && tmp.ends_with("_pwm") {
Self::set_val_from_attr(tmp.as_ref(), device, &mut self.pwm)
}
}
}
fn init_if_zeroed(&mut self, device: &mut Device) -> std::io::Result<()> {
if self.pwm == [0u8; 8] && self.temp == [0u8; 8] {
// Need to reset the device to defaults to get the proper profile defaults
match self.fan {
FanCurvePU::CPU => device.set_attribute_value("pwm1_enable", "3")?,
FanCurvePU::GPU => device.set_attribute_value("pwm2_enable", "3")?,
};
self.read_from_device(device);
}
Ok(())
}
/// Write this curve to the device fan specified by `self.fan`
fn write_to_device(&self, device: &mut Device, enable: bool) -> std::io::Result<()> {
let pwm_num = match self.fan {
FanCurvePU::CPU => '1',
FanCurvePU::GPU => '2',
};
let enable = if enable { "1" } else { "2" };
for (index, out) in self.pwm.iter().enumerate() {
let pwm = pwm_str(pwm_num, index);
device.set_attribute_value(&pwm, &out.to_string())?;
}
for (index, out) in self.temp.iter().enumerate() {
let temp = temp_str(pwm_num, index);
device.set_attribute_value(&temp, &out.to_string())?;
}
// Enable must be done *after* all points are written
match self.fan {
FanCurvePU::CPU => device.set_attribute_value("pwm1_enable", enable)?,
FanCurvePU::GPU => device.set_attribute_value("pwm2_enable", enable)?,
};
Ok(())
}
} }
/// A `FanCurveSet` contains both CPU and GPU fan curve data /// A `FanCurveSet` contains both CPU and GPU fan curve data
#[cfg_attr(feature = "dbus", derive(Type))] #[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Deserialize, Serialize, Debug, Clone)] #[derive(Deserialize, Serialize, Debug, Clone)]
pub struct FanCurveSet { pub struct FanCurveSet {
pub cpu: CurveData, pub(crate) enabled: bool,
pub gpu: CurveData, pub(crate) cpu: CurveData,
pub(crate) gpu: CurveData,
} }
impl Default for FanCurveSet { impl Default for FanCurveSet {
fn default() -> Self { fn default() -> Self {
Self { Self {
enabled: false,
cpu: CurveData { cpu: CurveData {
fan: FanCurvePU::CPU, fan: FanCurvePU::CPU,
pwm: [0u8; 8], pwm: [0u8; 8],
@@ -60,80 +190,71 @@ impl Default for FanCurveSet {
} }
impl FanCurveSet { impl FanCurveSet {
pub fn get_device() -> Result<Device, ProfileError> { pub(crate) fn read_cpu_from_device(&mut self, device: &Device) {
let mut enumerator = udev::Enumerator::new()?; self.cpu.read_from_device(device);
enumerator.match_subsystem("hwmon")?;
for device in enumerator.scan_devices().unwrap() {
if device.parent_with_subsystem("platform").unwrap().is_some() {
if let Some(name) = device.attribute_value("name") {
if name == "asus_custom_fan_curve" {
return Ok(device);
}
}
}
}
Err(ProfileError::NotSupported)
} }
pub fn is_supported() -> Result<bool, ProfileError> { pub(crate) fn read_gpu_from_device(&mut self, device: &Device) {
if Self::get_device().is_ok() { self.gpu.read_from_device(device);
return Ok(true);
}
Ok(false)
} }
pub fn new() -> Result<(Self, Device), ProfileError> { pub(crate) fn write_cpu_fan(&mut self, device: &mut Device) -> std::io::Result<()> {
if let Ok(device) = Self::get_device() { self.cpu.init_if_zeroed(device)?;
let mut fans = Self { self.cpu.write_to_device(device, self.enabled)
cpu: CurveData::default(),
gpu: CurveData::default(),
};
fans.cpu.fan = FanCurvePU::CPU;
fans.cpu.fan = FanCurvePU::GPU;
fans.read_from_device(&device);
return Ok((fans, device));
}
Err(ProfileError::NotSupported)
} }
fn set_val_from_attr(tmp: &str, device: &Device, buf: &mut [u8; 8]) { pub(crate) fn write_gpu_fan(&mut self, device: &mut Device) -> std::io::Result<()> {
if let Some(n) = tmp.chars().nth(15) { self.gpu.init_if_zeroed(device)?;
let i = n.to_digit(10).unwrap() as usize; self.gpu.write_to_device(device, self.enabled)
let d = device.attribute_value(tmp).unwrap(); }
let d: u8 = d.to_string_lossy().parse().unwrap(); }
buf[i - 1] = d;
} #[cfg(test)]
} mod tests {
use std::str::FromStr;
pub fn read_from_device(&mut self, device: &Device) {
for attr in device.attributes() { use super::*;
let tmp = attr.name().to_string_lossy();
if tmp.starts_with("pwm1") && tmp.ends_with("_temp") { #[test]
Self::set_val_from_attr(tmp.as_ref(), device, &mut self.cpu.temp) fn curve_data_from_str() {
} let curve =
if tmp.starts_with("pwm1") && tmp.ends_with("_pwm") { CurveData::from_str("30c:1%,49c:2%,59c:3%,69c:4%,79c:31%,89c:49%,99c:56%,109c:58%")
Self::set_val_from_attr(tmp.as_ref(), device, &mut self.cpu.pwm) .unwrap();
} assert_eq!(curve.fan, FanCurvePU::CPU);
if tmp.starts_with("pwm2") && tmp.ends_with("_temp") { assert_eq!(curve.temp, [30, 49, 59, 69, 79, 89, 99, 109]);
Self::set_val_from_attr(tmp.as_ref(), device, &mut self.gpu.temp) assert_eq!(curve.pwm, [1, 2, 3, 4, 31, 49, 56, 58]);
} }
if tmp.starts_with("pwm2") && tmp.ends_with("_pwm") {
Self::set_val_from_attr(tmp.as_ref(), device, &mut self.gpu.pwm) #[test]
} fn curve_data_from_str_simple() {
} let curve = CurveData::from_str("30:1,49:2,59:3,69:4,79:31,89:49,99:56,109:58").unwrap();
} assert_eq!(curve.fan, FanCurvePU::CPU);
assert_eq!(curve.temp, [30, 49, 59, 69, 79, 89, 99, 109]);
pub fn write_cpu_fan(&self, device: &mut Device) { assert_eq!(curve.pwm, [1, 2, 3, 4, 31, 49, 56, 58]);
write_to_fan(&self.cpu, '1', device); }
}
#[test]
pub fn write_gpu_fan(&self, device: &mut Device) { fn curve_data_from_str_invalid_pwm() {
write_to_fan(&self.gpu, '2', device); let curve =
CurveData::from_str("30c:4%,49c:2%,59c:3%,69c:4%,79c:31%,89c:49%,99c:56%,109c:58%");
assert!(&curve.is_err());
assert!(matches!(
curve,
Err(ProfileError::ParseFanCurvePrevHigher(_, _, _))
));
}
#[test]
fn check_pwm_str() {
assert_eq!(pwm_str('1', 0), "pwm1_auto_point1_pwm");
assert_eq!(pwm_str('1', 4), "pwm1_auto_point5_pwm");
assert_eq!(pwm_str('1', 7), "pwm1_auto_point8_pwm");
}
#[test]
fn check_temp_str() {
assert_eq!(temp_str('1', 0), "pwm1_auto_point1_temp");
assert_eq!(temp_str('1', 4), "pwm1_auto_point5_temp");
assert_eq!(temp_str('1', 7), "pwm1_auto_point8_temp");
} }
} }
+121 -73
View File
@@ -38,7 +38,7 @@ pub fn find_fan_curve_node() -> Result<Option<Device>, ProfileError> {
} }
#[cfg_attr(feature = "dbus", derive(Type))] #[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Deserialize, Serialize, Debug, Clone, Copy)] #[derive(Deserialize, Serialize, Debug, PartialEq, Clone, Copy)]
pub enum Profile { pub enum Profile {
Balanced, Balanced,
Performance, Performance,
@@ -51,10 +51,7 @@ impl Profile {
} }
pub fn get_active_profile() -> Result<Profile, ProfileError> { pub fn get_active_profile() -> Result<Profile, ProfileError> {
let mut file = OpenOptions::new() let mut file = OpenOptions::new().read(true).open(&PLATFORM_PROFILE)?;
.read(true)
.open(&PLATFORM_PROFILE)
.unwrap_or_else(|_| panic!("{} not found", &PLATFORM_PROFILE));
let mut buf = String::new(); let mut buf = String::new();
file.read_to_string(&mut buf)?; file.read_to_string(&mut buf)?;
@@ -62,10 +59,7 @@ impl Profile {
} }
pub fn get_profile_names() -> Result<Vec<Profile>, ProfileError> { pub fn get_profile_names() -> Result<Vec<Profile>, ProfileError> {
let mut file = OpenOptions::new() let mut file = OpenOptions::new().read(true).open(&PLATFORM_PROFILES)?;
.read(true)
.open(&PLATFORM_PROFILES)
.unwrap_or_else(|_| panic!("{} not found", &PLATFORM_PROFILES));
let mut buf = String::new(); let mut buf = String::new();
file.read_to_string(&mut buf)?; file.read_to_string(&mut buf)?;
@@ -73,10 +67,7 @@ impl Profile {
} }
pub fn set_profile(profile: Profile) -> Result<(), ProfileError> { pub fn set_profile(profile: Profile) -> Result<(), ProfileError> {
let mut file = OpenOptions::new() let mut file = OpenOptions::new().write(true).open(PLATFORM_PROFILE)?;
.write(true)
.open(PLATFORM_PROFILE)
.unwrap_or_else(|_| panic!("{} not found", PLATFORM_PROFILE));
file.write_all(<&str>::from(profile).as_bytes())?; file.write_all(<&str>::from(profile).as_bytes())?;
Ok(()) Ok(())
@@ -110,8 +101,21 @@ impl From<&str> for Profile {
} }
} }
impl std::str::FromStr for Profile {
type Err = ProfileError;
fn from_str(profile: &str) -> Result<Self, Self::Err> {
match profile.to_ascii_lowercase().trim() {
"balanced" => Ok(Profile::Balanced),
"performance" => Ok(Profile::Performance),
"quiet" => Ok(Profile::Quiet),
_ => Err(ProfileError::ParseProfileName),
}
}
}
#[cfg_attr(feature = "dbus", derive(Type))] #[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Deserialize, Serialize, Debug, Clone, Copy)] #[derive(Deserialize, Serialize, Debug, PartialEq, Clone, Copy)]
pub enum FanCurvePU { pub enum FanCurvePU {
CPU, CPU,
GPU, GPU,
@@ -126,27 +130,63 @@ impl From<FanCurvePU> for &str {
} }
} }
impl std::str::FromStr for FanCurvePU {
type Err = ProfileError;
fn from_str(fan: &str) -> Result<Self, Self::Err> {
match fan.to_ascii_lowercase().trim() {
"cpu" => Ok(FanCurvePU::CPU),
"gpu" => Ok(FanCurvePU::GPU),
_ => Err(ProfileError::ParseProfileName),
}
}
}
impl Default for FanCurvePU { impl Default for FanCurvePU {
fn default() -> Self { fn default() -> Self {
Self::CPU Self::CPU
} }
} }
/// Main purpose of `FanCurves` is to enable retoring state on system boot /// Main purpose of `FanCurves` is to enable restoring state on system boot
#[cfg_attr(feature = "dbus", derive(Type))] #[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Deserialize, Serialize, Debug, Default)] #[derive(Deserialize, Serialize, Debug, Default)]
pub struct FanCurveProfiles { pub struct FanCurveProfiles {
enabled: Vec<Profile>,
balanced: FanCurveSet, balanced: FanCurveSet,
performance: FanCurveSet, performance: FanCurveSet,
quiet: FanCurveSet, quiet: FanCurveSet,
} }
impl FanCurveProfiles { impl FanCurveProfiles {
pub fn get_device() -> Result<Device, ProfileError> {
let mut enumerator = udev::Enumerator::new()?;
enumerator.match_subsystem("hwmon")?;
for device in enumerator.scan_devices()? {
if device.parent_with_subsystem("platform")?.is_some() {
if let Some(name) = device.attribute_value("name") {
if name == "asus_custom_fan_curve" {
return Ok(device);
}
}
}
}
Err(ProfileError::NotSupported)
}
pub fn is_supported() -> Result<bool, ProfileError> {
if Self::get_device().is_ok() {
return Ok(true);
}
Ok(false)
}
/// ///
pub fn read_from_dev_profile(&mut self, profile: Profile, device: &Device) { pub fn read_from_dev_profile(&mut self, profile: Profile, device: &Device) {
let mut tmp = FanCurveSet::default(); let mut tmp = FanCurveSet::default();
tmp.read_from_device(device); tmp.read_cpu_from_device(device);
tmp.read_gpu_from_device(device);
match profile { match profile {
Profile::Balanced => self.balanced = tmp, Profile::Balanced => self.balanced = tmp,
Profile::Performance => self.performance = tmp, Profile::Performance => self.performance = tmp,
@@ -154,22 +194,69 @@ impl FanCurveProfiles {
} }
} }
pub fn write_to_platform(&self, profile: Profile, device: &mut Device) { /// Reset the stored (self) and device curve to the defaults of the platform.
///
/// Each platform_profile has a different default and the defualt can be read
/// only for the currently active profile.
pub fn set_active_curve_to_defaults(
&mut self,
profile: Profile,
device: &mut Device,
) -> std::io::Result<()> {
// Do reset
device.set_attribute_value("pwm1_enable", "3")?;
device.set_attribute_value("pwm2_enable", "3")?;
// Then read
let mut tmp = FanCurveSet::default();
tmp.read_cpu_from_device(device);
tmp.read_gpu_from_device(device);
match profile {
Profile::Balanced => self.balanced = tmp,
Profile::Performance => self.performance = tmp,
Profile::Quiet => self.quiet = tmp,
}
Ok(())
}
/// Write the curves for the selected profile to the device. If the curve is
/// in the enabled list it will become active. If the curve is zeroed it will be initialised
/// to a default read from the system.
// TODO: Make this return an error if curve is zeroed
pub fn write_profile_curve_to_platform(
&mut self,
profile: Profile,
device: &mut Device,
) -> std::io::Result<()> {
let fans = match profile { let fans = match profile {
Profile::Balanced => &self.balanced, Profile::Balanced => &mut self.balanced,
Profile::Performance => &self.performance, Profile::Performance => &mut self.performance,
Profile::Quiet => &self.quiet, Profile::Quiet => &mut self.quiet,
}; };
fans.write_cpu_fan(device); fans.write_cpu_fan(device)?;
fans.write_gpu_fan(device); fans.write_gpu_fan(device)?;
Ok(())
} }
pub fn get_enabled_curve_profiles(&self) -> &[Profile] { pub fn get_enabled_curve_profiles(&self) -> Vec<Profile> {
&self.enabled let mut tmp = Vec::new();
if self.balanced.enabled {
tmp.push(Profile::Balanced);
}
if self.performance.enabled {
tmp.push(Profile::Performance);
}
if self.quiet.enabled {
tmp.push(Profile::Quiet);
}
tmp
} }
pub fn set_enabled_curve_profiles(&mut self, profiles: Vec<Profile>) { pub fn set_profile_curve_enabled(&mut self, profile: Profile, enabled: bool) {
self.enabled = profiles match profile {
Profile::Balanced => self.balanced.enabled = enabled,
Profile::Performance => self.performance.enabled = enabled,
Profile::Quiet => self.quiet.enabled = enabled,
}
} }
pub fn get_all_fan_curves(&self) -> Vec<FanCurveSet> { pub fn get_all_fan_curves(&self) -> Vec<FanCurveSet> {
@@ -180,11 +267,11 @@ impl FanCurveProfiles {
] ]
} }
pub fn get_active_fan_curves(&self) -> &FanCurveSet { pub fn get_active_fan_curves(&self) -> Result<&FanCurveSet, ProfileError> {
match Profile::get_active_profile().unwrap() { match Profile::get_active_profile()? {
Profile::Balanced => &self.balanced, Profile::Balanced => Ok(&self.balanced),
Profile::Performance => &self.performance, Profile::Performance => Ok(&self.performance),
Profile::Quiet => &self.quiet, Profile::Quiet => Ok(&self.quiet),
} }
} }
@@ -213,16 +300,7 @@ impl FanCurveProfiles {
} }
} }
pub fn write_and_set_fan_curve( pub fn save_fan_curve(&mut self, curve: CurveData, profile: Profile) -> std::io::Result<()> {
&mut self,
curve: CurveData,
profile: Profile,
device: &mut Device,
) {
match curve.fan {
FanCurvePU::CPU => write_to_fan(&curve, '1', device),
FanCurvePU::GPU => write_to_fan(&curve, '2', device),
}
match profile { match profile {
Profile::Balanced => match curve.fan { Profile::Balanced => match curve.fan {
FanCurvePU::CPU => self.balanced.cpu = curve, FanCurvePU::CPU => self.balanced.cpu = curve,
@@ -237,36 +315,6 @@ impl FanCurveProfiles {
FanCurvePU::GPU => self.quiet.gpu = curve, FanCurvePU::GPU => self.quiet.gpu = curve,
}, },
} }
} Ok(())
}
pub fn write_to_fan(curve: &CurveData, pwm_num: char, device: &mut Device) {
let mut pwm = "pwmN_auto_pointN_pwm".to_string();
dbg!(&device);
for (index, out) in curve.pwm.iter().enumerate() {
unsafe {
let buf = pwm.as_bytes_mut();
buf[3] = pwm_num as u8;
// Should be quite safe to unwrap as we're not going over 8
buf[15] = char::from_digit(index as u32 + 1, 10).unwrap() as u8;
}
let out = out.to_string();
dbg!(&pwm);
dbg!(&out);
device.set_attribute_value(&pwm, &out).unwrap();
}
let mut pwm = "pwmN_auto_pointN_temp".to_string();
for (index, out) in curve.temp.iter().enumerate() {
unsafe {
let buf = pwm.as_bytes_mut();
buf[3] = pwm_num as u8;
// Should be quite safe to unwrap as we're not going over 8
buf[15] = char::from_digit(index as u32 + 1, 10).unwrap() as u8;
}
let out = out.to_string();
device.set_attribute_value(&pwm, &out).unwrap();
} }
} }