Compare commits

..

15 Commits

Author SHA1 Message Date
Denis Benato 5e5cebc781 Revert "Fix: continue -> return in set_config_or_default"
This reverts commit ad051bd7b8.
2025-11-06 22:53:21 +01:00
Denis Benato def691f9d0 Fix: sliders not updating the value 2025-11-06 22:53:09 +01:00
Denis Benato 80eeafd9e1 Feat: config reload and do not apply properties if max==min 2025-11-06 21:06:44 +01:00
Denis Benato bf173300e0 Feat: start in tray mode 2025-11-06 17:29:12 +01:00
Denis Benato 07874d7452 tests: load bundled aura_support.ron when system files missing to make unit tests reliable in CI 2025-11-06 17:24:01 +01:00
Denis Benato 894a0d2b11 Chore: update CHANGELOG.md 2025-11-06 16:12:44 +01:00
Denis Benato 11dc02612e Fix clippy warnings: alias complex types, allow some clippy lints, collapse else-if, avoid is_multiple_of usage 2025-11-06 16:05:38 +01:00
Denis Benato fccb233e9e Fix: stop rust from silly complains about is_multiple_of 2025-11-06 15:58:30 +01:00
Denis Benato c13612e02c Fix: simplify an if 2025-11-06 15:52:43 +01:00
Denis Benato 80147966a9 Chore: use stable 2025-11-06 15:49:05 +01:00
Denis Benato a1815ac40c Chore: improve tests 2025-11-06 15:34:30 +01:00
Denis Benato ad051bd7b8 Fix: continue -> return in set_config_or_default 2025-11-06 15:07:31 +01:00
Denis Benato 90676b390e Chore: update CHANGELOG.md 2025-11-06 15:04:59 +01:00
Denis Benato 974f2acafa Feat: better handling of nv_ properties 2025-11-06 14:53:57 +01:00
Denis Benato 6ae3ae5284 Feat: make nvidia dGPU tunables power-profile dependant 2025-11-06 14:26:03 +01:00
29 changed files with 1279 additions and 296 deletions
+3 -6
View File
@@ -2,13 +2,10 @@
## [Unreleased] ## [Unreleased]
## [6.1.18]
### Changed ### Changed
- Add aura support for G614FR (ROG Strix G16 2025) - Make the boot process more reliable
- all notifications now respects the timeout - tie nv_ properties to power profiles
- improve udev daemon-starting rule - Better support nv_tgp
- reduce log noise
## [v6.1.17] ## [v6.1.17]
Generated
+99 -99
View File
@@ -123,7 +123,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -146,7 +146,7 @@ checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b"
[[package]] [[package]]
name = "asusctl" name = "asusctl"
version = "6.1.18" version = "6.1.17"
dependencies = [ dependencies = [
"dmi_id", "dmi_id",
"env_logger", "env_logger",
@@ -165,7 +165,7 @@ dependencies = [
[[package]] [[package]]
name = "asusd" name = "asusd"
version = "6.1.18" version = "6.1.17"
dependencies = [ dependencies = [
"cargo-husky", "cargo-husky",
"concat-idents", "concat-idents",
@@ -185,6 +185,7 @@ dependencies = [
"rog_scsi", "rog_scsi",
"rog_slash", "rog_slash",
"serde", "serde",
"tempfile",
"tokio", "tokio",
"udev 0.8.0", "udev 0.8.0",
"zbus", "zbus",
@@ -192,7 +193,7 @@ dependencies = [
[[package]] [[package]]
name = "asusd-user" name = "asusd-user"
version = "6.1.18" version = "6.1.17"
dependencies = [ dependencies = [
"config-traits", "config-traits",
"dirs", "dirs",
@@ -322,7 +323,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -362,7 +363,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -379,7 +380,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -397,7 +398,7 @@ dependencies = [
"derive_utils", "derive_utils",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -515,7 +516,7 @@ dependencies = [
"regex", "regex",
"rustc-hash 2.1.1", "rustc-hash 2.1.1",
"shlex", "shlex",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -535,7 +536,7 @@ dependencies = [
"regex", "regex",
"rustc-hash 2.1.1", "rustc-hash 2.1.1",
"shlex", "shlex",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -646,7 +647,7 @@ checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -726,9 +727,9 @@ checksum = "7b02b629252fe8ef6460461409564e2c21d0c8e77e0944f3d189ff06c4e932ad"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.2.45" version = "1.2.44"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35900b6c8d709fb1d854671ae27aeaa9eec2f8b01b364e1619a40da3e6fe2afe" checksum = "37521ac7aabe3d13122dc382493e20c9416f299d2ccd5b3a5340a2570cdeb0f3"
dependencies = [ dependencies = [
"find-msvc-tools", "find-msvc-tools",
"jobserver", "jobserver",
@@ -860,7 +861,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f76990911f2267d837d9d0ad060aa63aaad170af40904b29461734c339030d4d" checksum = "f76990911f2267d837d9d0ad060aa63aaad170af40904b29461734c339030d4d"
dependencies = [ dependencies = [
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -874,7 +875,7 @@ dependencies = [
[[package]] [[package]]
name = "config-traits" name = "config-traits"
version = "6.1.18" version = "6.1.17"
dependencies = [ dependencies = [
"log", "log",
"ron", "ron",
@@ -923,7 +924,7 @@ dependencies = [
[[package]] [[package]]
name = "const-field-offset" name = "const-field-offset"
version = "0.1.5" version = "0.1.5"
source = "git+https://github.com/slint-ui/slint.git#ea0d0be0325f505c0c885f9f60aadf4b0da12a36" source = "git+https://github.com/slint-ui/slint.git#7f21826607746ecedda6aa1d66bc0d396bae7eda"
dependencies = [ dependencies = [
"const-field-offset-macro", "const-field-offset-macro",
"field-offset", "field-offset",
@@ -932,11 +933,11 @@ dependencies = [
[[package]] [[package]]
name = "const-field-offset-macro" name = "const-field-offset-macro"
version = "0.1.5" version = "0.1.5"
source = "git+https://github.com/slint-ui/slint.git#ea0d0be0325f505c0c885f9f60aadf4b0da12a36" source = "git+https://github.com/slint-ui/slint.git#7f21826607746ecedda6aa1d66bc0d396bae7eda"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -1141,7 +1142,7 @@ checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
"unicode-xid", "unicode-xid",
] ]
@@ -1153,7 +1154,7 @@ checksum = "ccfae181bab5ab6c5478b2ccb69e4c68a02f8c3ec72f6616bfec9dbc599d2ee0"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -1200,7 +1201,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -1214,7 +1215,7 @@ dependencies = [
[[package]] [[package]]
name = "dmi_id" name = "dmi_id"
version = "6.1.18" version = "6.1.17"
dependencies = [ dependencies = [
"log", "log",
"udev 0.8.0", "udev 0.8.0",
@@ -1302,7 +1303,7 @@ checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -1335,7 +1336,7 @@ checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -1392,9 +1393,9 @@ dependencies = [
[[package]] [[package]]
name = "exr" name = "exr"
version = "1.74.0" version = "1.73.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4300e043a56aa2cb633c01af81ca8f699a321879a7854d3896a0ba89056363be" checksum = "f83197f59927b46c04a183a619b7c29df34e63e63c7869320862268c0ef687e0"
dependencies = [ dependencies = [
"bit_field", "bit_field",
"half", "half",
@@ -1428,7 +1429,7 @@ checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -1519,9 +1520,9 @@ checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
[[package]] [[package]]
name = "font-types" name = "font-types"
version = "0.10.1" version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39a654f404bbcbd48ea58c617c2993ee91d1cb63727a37bf2323a4edeed1b8c5" checksum = "511e2c18a516c666d27867d2f9821f76e7d591f762e9fc41dd6cc5c90fe54b0b"
dependencies = [ dependencies = [
"bytemuck", "bytemuck",
] ]
@@ -1590,7 +1591,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -1677,7 +1678,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -2093,9 +2094,9 @@ checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424"
[[package]] [[package]]
name = "hyper" name = "hyper"
version = "1.8.0" version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1744436df46f0bde35af3eda22aeaba453aada65d8f1c171cd8a5f59030bd69f" checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e"
dependencies = [ dependencies = [
"atomic-waker", "atomic-waker",
"bytes", "bytes",
@@ -2151,7 +2152,7 @@ dependencies = [
[[package]] [[package]]
name = "i-slint-backend-linuxkms" name = "i-slint-backend-linuxkms"
version = "1.15.0" version = "1.15.0"
source = "git+https://github.com/slint-ui/slint.git#ea0d0be0325f505c0c885f9f60aadf4b0da12a36" source = "git+https://github.com/slint-ui/slint.git#7f21826607746ecedda6aa1d66bc0d396bae7eda"
dependencies = [ dependencies = [
"calloop 0.14.3", "calloop 0.14.3",
"drm", "drm",
@@ -2169,7 +2170,7 @@ dependencies = [
[[package]] [[package]]
name = "i-slint-backend-selector" name = "i-slint-backend-selector"
version = "1.15.0" version = "1.15.0"
source = "git+https://github.com/slint-ui/slint.git#ea0d0be0325f505c0c885f9f60aadf4b0da12a36" source = "git+https://github.com/slint-ui/slint.git#7f21826607746ecedda6aa1d66bc0d396bae7eda"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"i-slint-backend-linuxkms", "i-slint-backend-linuxkms",
@@ -2182,7 +2183,7 @@ dependencies = [
[[package]] [[package]]
name = "i-slint-backend-winit" name = "i-slint-backend-winit"
version = "1.15.0" version = "1.15.0"
source = "git+https://github.com/slint-ui/slint.git#ea0d0be0325f505c0c885f9f60aadf4b0da12a36" source = "git+https://github.com/slint-ui/slint.git#7f21826607746ecedda6aa1d66bc0d396bae7eda"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"cfg_aliases", "cfg_aliases",
@@ -2216,7 +2217,7 @@ dependencies = [
[[package]] [[package]]
name = "i-slint-common" name = "i-slint-common"
version = "1.15.0" version = "1.15.0"
source = "git+https://github.com/slint-ui/slint.git#ea0d0be0325f505c0c885f9f60aadf4b0da12a36" source = "git+https://github.com/slint-ui/slint.git#7f21826607746ecedda6aa1d66bc0d396bae7eda"
dependencies = [ dependencies = [
"fontique", "fontique",
"ttf-parser 0.25.1", "ttf-parser 0.25.1",
@@ -2225,7 +2226,7 @@ dependencies = [
[[package]] [[package]]
name = "i-slint-compiler" name = "i-slint-compiler"
version = "1.15.0" version = "1.15.0"
source = "git+https://github.com/slint-ui/slint.git#ea0d0be0325f505c0c885f9f60aadf4b0da12a36" source = "git+https://github.com/slint-ui/slint.git#7f21826607746ecedda6aa1d66bc0d396bae7eda"
dependencies = [ dependencies = [
"by_address", "by_address",
"codemap", "codemap",
@@ -2254,7 +2255,7 @@ dependencies = [
[[package]] [[package]]
name = "i-slint-core" name = "i-slint-core"
version = "1.15.0" version = "1.15.0"
source = "git+https://github.com/slint-ui/slint.git#ea0d0be0325f505c0c885f9f60aadf4b0da12a36" source = "git+https://github.com/slint-ui/slint.git#7f21826607746ecedda6aa1d66bc0d396bae7eda"
dependencies = [ dependencies = [
"auto_enums", "auto_enums",
"bitflags 2.10.0", "bitflags 2.10.0",
@@ -2284,7 +2285,6 @@ dependencies = [
"rgb", "rgb",
"scoped-tls-hkt", "scoped-tls-hkt",
"scopeguard", "scopeguard",
"skrifa",
"slab", "slab",
"strum", "strum",
"sys-locale", "sys-locale",
@@ -2302,17 +2302,17 @@ dependencies = [
[[package]] [[package]]
name = "i-slint-core-macros" name = "i-slint-core-macros"
version = "1.15.0" version = "1.15.0"
source = "git+https://github.com/slint-ui/slint.git#ea0d0be0325f505c0c885f9f60aadf4b0da12a36" source = "git+https://github.com/slint-ui/slint.git#7f21826607746ecedda6aa1d66bc0d396bae7eda"
dependencies = [ dependencies = [
"quote", "quote",
"serde_json", "serde_json",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
name = "i-slint-renderer-femtovg" name = "i-slint-renderer-femtovg"
version = "1.15.0" version = "1.15.0"
source = "git+https://github.com/slint-ui/slint.git#ea0d0be0325f505c0c885f9f60aadf4b0da12a36" source = "git+https://github.com/slint-ui/slint.git#7f21826607746ecedda6aa1d66bc0d396bae7eda"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"const-field-offset", "const-field-offset",
@@ -2334,7 +2334,7 @@ dependencies = [
[[package]] [[package]]
name = "i-slint-renderer-skia" name = "i-slint-renderer-skia"
version = "1.15.0" version = "1.15.0"
source = "git+https://github.com/slint-ui/slint.git#ea0d0be0325f505c0c885f9f60aadf4b0da12a36" source = "git+https://github.com/slint-ui/slint.git#7f21826607746ecedda6aa1d66bc0d396bae7eda"
dependencies = [ dependencies = [
"bytemuck", "bytemuck",
"cfg-if", "cfg-if",
@@ -2617,7 +2617,7 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -2874,9 +2874,9 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
[[package]] [[package]]
name = "linked_hash_set" name = "linked_hash_set"
version = "0.1.6" version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "984fb35d06508d1e69fc91050cceba9c0b748f983e6739fa2c7a9237154c52c8" checksum = "bae85b5be22d9843c80e5fc80e9b64c8a3b1f98f867c709956eca3efff4e92e2"
dependencies = [ dependencies = [
"linked-hash-map", "linked-hash-map",
] ]
@@ -3263,7 +3263,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -3315,7 +3315,7 @@ dependencies = [
"proc-macro-crate", "proc-macro-crate",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -3802,7 +3802,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -3945,7 +3945,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -3982,7 +3982,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b" checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b"
dependencies = [ dependencies = [
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -4005,7 +4005,7 @@ dependencies = [
"itertools 0.14.0", "itertools 0.14.0",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -4052,9 +4052,9 @@ dependencies = [
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.42" version = "1.0.41"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@@ -4280,7 +4280,7 @@ dependencies = [
[[package]] [[package]]
name = "rog-control-center" name = "rog-control-center"
version = "6.1.18" version = "6.1.17"
dependencies = [ dependencies = [
"asusd", "asusd",
"concat-idents", "concat-idents",
@@ -4311,7 +4311,7 @@ dependencies = [
[[package]] [[package]]
name = "rog_anime" name = "rog_anime"
version = "6.1.18" version = "6.1.17"
dependencies = [ dependencies = [
"dmi_id", "dmi_id",
"gif 0.12.0", "gif 0.12.0",
@@ -4325,7 +4325,7 @@ dependencies = [
[[package]] [[package]]
name = "rog_aura" name = "rog_aura"
version = "6.1.18" version = "6.1.17"
dependencies = [ dependencies = [
"dmi_id", "dmi_id",
"log", "log",
@@ -4336,7 +4336,7 @@ dependencies = [
[[package]] [[package]]
name = "rog_dbus" name = "rog_dbus"
version = "6.1.18" version = "6.1.17"
dependencies = [ dependencies = [
"asusd", "asusd",
"rog_anime", "rog_anime",
@@ -4350,7 +4350,7 @@ dependencies = [
[[package]] [[package]]
name = "rog_platform" name = "rog_platform"
version = "6.1.18" version = "6.1.17"
dependencies = [ dependencies = [
"concat-idents", "concat-idents",
"inotify", "inotify",
@@ -4363,7 +4363,7 @@ dependencies = [
[[package]] [[package]]
name = "rog_profiles" name = "rog_profiles"
version = "6.1.18" version = "6.1.17"
dependencies = [ dependencies = [
"log", "log",
"rog_platform", "rog_platform",
@@ -4374,7 +4374,7 @@ dependencies = [
[[package]] [[package]]
name = "rog_scsi" name = "rog_scsi"
version = "6.1.18" version = "6.1.17"
dependencies = [ dependencies = [
"ron", "ron",
"serde", "serde",
@@ -4384,7 +4384,7 @@ dependencies = [
[[package]] [[package]]
name = "rog_simulators" name = "rog_simulators"
version = "6.1.18" version = "6.1.17"
dependencies = [ dependencies = [
"log", "log",
"rog_anime", "rog_anime",
@@ -4394,7 +4394,7 @@ dependencies = [
[[package]] [[package]]
name = "rog_slash" name = "rog_slash"
version = "6.1.18" version = "6.1.17"
dependencies = [ dependencies = [
"dmi_id", "dmi_id",
"serde", "serde",
@@ -4615,7 +4615,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -4639,7 +4639,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -4726,9 +4726,9 @@ checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
[[package]] [[package]]
name = "skia-bindings" name = "skia-bindings"
version = "0.90.0" version = "0.89.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f6f96e00735f14a781aac8a6870c862b8cc831df6d8e4ad77ab78e11411b9af" checksum = "f06b9b01a0d1189fa756bb9aec034554d52ad53f2f33d80a96e7a4ecfbd3d989"
dependencies = [ dependencies = [
"bindgen 0.72.1", "bindgen 0.72.1",
"cc", "cc",
@@ -4743,9 +4743,9 @@ dependencies = [
[[package]] [[package]]
name = "skia-safe" name = "skia-safe"
version = "0.90.0" version = "0.89.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a71c01d325d40b1031dee67d251a5e0132e79e2a9ec272149a4f4a0d4b8b3be" checksum = "ced1fcc0fa7510f9339988f31d831e14f64f9aa771e5f93f4935431e6fe69d4c"
dependencies = [ dependencies = [
"bitflags 2.10.0", "bitflags 2.10.0",
"skia-bindings", "skia-bindings",
@@ -4771,7 +4771,7 @@ checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
[[package]] [[package]]
name = "slint" name = "slint"
version = "1.15.0" version = "1.15.0"
source = "git+https://github.com/slint-ui/slint.git#ea0d0be0325f505c0c885f9f60aadf4b0da12a36" source = "git+https://github.com/slint-ui/slint.git#7f21826607746ecedda6aa1d66bc0d396bae7eda"
dependencies = [ dependencies = [
"const-field-offset", "const-field-offset",
"i-slint-backend-selector", "i-slint-backend-selector",
@@ -4789,7 +4789,7 @@ dependencies = [
[[package]] [[package]]
name = "slint-build" name = "slint-build"
version = "1.15.0" version = "1.15.0"
source = "git+https://github.com/slint-ui/slint.git#ea0d0be0325f505c0c885f9f60aadf4b0da12a36" source = "git+https://github.com/slint-ui/slint.git#7f21826607746ecedda6aa1d66bc0d396bae7eda"
dependencies = [ dependencies = [
"derive_more", "derive_more",
"i-slint-compiler", "i-slint-compiler",
@@ -4800,7 +4800,7 @@ dependencies = [
[[package]] [[package]]
name = "slint-macros" name = "slint-macros"
version = "1.15.0" version = "1.15.0"
source = "git+https://github.com/slint-ui/slint.git#ea0d0be0325f505c0c885f9f60aadf4b0da12a36" source = "git+https://github.com/slint-ui/slint.git#7f21826607746ecedda6aa1d66bc0d396bae7eda"
dependencies = [ dependencies = [
"i-slint-compiler", "i-slint-compiler",
"proc-macro2", "proc-macro2",
@@ -5021,13 +5021,13 @@ dependencies = [
"heck", "heck",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
name = "supergfxctl" name = "supergfxctl"
version = "5.2.7" version = "5.2.7"
source = "git+https://gitlab.com/asus-linux/supergfxctl.git#5d503b1efd41f29f77679513890807c0c0a576fe" source = "git+https://gitlab.com/asus-linux/supergfxctl.git#bcdca4bee8b64258c5ec1502769ebafd2182aa0b"
dependencies = [ dependencies = [
"futures-util", "futures-util",
"log", "log",
@@ -5074,9 +5074,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.110" version = "2.0.108"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea" checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -5097,7 +5097,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -5211,7 +5211,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -5222,7 +5222,7 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -5356,7 +5356,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -5565,7 +5565,7 @@ checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -5856,7 +5856,7 @@ dependencies = [
[[package]] [[package]]
name = "vtable" name = "vtable"
version = "0.3.0" version = "0.3.0"
source = "git+https://github.com/slint-ui/slint.git#ea0d0be0325f505c0c885f9f60aadf4b0da12a36" source = "git+https://github.com/slint-ui/slint.git#7f21826607746ecedda6aa1d66bc0d396bae7eda"
dependencies = [ dependencies = [
"const-field-offset", "const-field-offset",
"portable-atomic", "portable-atomic",
@@ -5867,11 +5867,11 @@ dependencies = [
[[package]] [[package]]
name = "vtable-macro" name = "vtable-macro"
version = "0.3.0" version = "0.3.0"
source = "git+https://github.com/slint-ui/slint.git#ea0d0be0325f505c0c885f9f60aadf4b0da12a36" source = "git+https://github.com/slint-ui/slint.git#7f21826607746ecedda6aa1d66bc0d396bae7eda"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -5953,7 +5953,7 @@ dependencies = [
"bumpalo", "bumpalo",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@@ -6139,9 +6139,9 @@ dependencies = [
[[package]] [[package]]
name = "weezl" name = "weezl"
version = "0.1.12" version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" checksum = "a751b3277700db47d3e574514de2eced5e54dc8a5436a3bf7a0b248b2cee16f3"
[[package]] [[package]]
name = "winapi" name = "winapi"
@@ -6296,7 +6296,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -6307,7 +6307,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -6318,7 +6318,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -6329,7 +6329,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -6965,7 +6965,7 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
"synstructure", "synstructure",
] ]
@@ -7012,7 +7012,7 @@ dependencies = [
"proc-macro-crate", "proc-macro-crate",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
"zbus_names", "zbus_names",
"zvariant", "zvariant",
"zvariant_utils", "zvariant_utils",
@@ -7053,7 +7053,7 @@ checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -7073,7 +7073,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
"synstructure", "synstructure",
] ]
@@ -7108,7 +7108,7 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
] ]
[[package]] [[package]]
@@ -7158,7 +7158,7 @@ dependencies = [
"proc-macro-crate", "proc-macro-crate",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.110", "syn 2.0.108",
"zvariant_utils", "zvariant_utils",
] ]
@@ -7171,6 +7171,6 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"serde", "serde",
"syn 2.0.110", "syn 2.0.108",
"winnow", "winnow",
] ]
+1 -1
View File
@@ -1,5 +1,5 @@
[workspace.package] [workspace.package]
version = "6.1.18" version = "6.1.17"
rust-version = "1.82" rust-version = "1.82"
license = "MPL-2.0" license = "MPL-2.0"
readme = "README.md" readme = "README.md"
+4 -11
View File
@@ -59,17 +59,10 @@ clean:
distclean: distclean:
rm -rf .cargo vendor vendor.tar.xz rm -rf .cargo vendor vendor.tar.xz
target/$(TARGET)/$(BIN_D): $(SRC) target/$(TARGET)/$(BIN_D): build
$(MAKE) build target/$(TARGET)/$(BIN_C): build
target/$(TARGET)/$(BIN_U): build
target/$(TARGET)/$(BIN_C): $(SRC) target/$(TARGET)/$(BIN_ROG): build
$(MAKE) build
target/$(TARGET)/$(BIN_U): $(SRC)
$(MAKE) build
target/$(TARGET)/$(BIN_ROG): $(SRC)
$(MAKE) build
install-asusd: target/$(TARGET)/$(BIN_D) install-asusd: target/$(TARGET)/$(BIN_D)
$(INSTALL_PROGRAM) "./target/$(TARGET)/$(BIN_D)" "$(DESTDIR)$(bindir)/$(BIN_D)" $(INSTALL_PROGRAM) "./target/$(TARGET)/$(BIN_D)" "$(DESTDIR)$(bindir)/$(BIN_D)"
+2 -2
View File
@@ -180,8 +180,8 @@ pub struct TwoColourSpeed {
pub zone: AuraZone, pub zone: AuraZone,
} }
#[derive(Debug, Clone, Default, Options)]
#[allow(dead_code)] #[allow(dead_code)]
#[derive(Debug, Clone, Default, Options)]
pub struct MultiZone { pub struct MultiZone {
#[options(help = "print help message")] #[options(help = "print help message")]
help: bool, help: bool,
@@ -195,8 +195,8 @@ pub struct MultiZone {
pub colour4: Colour, pub colour4: Colour,
} }
#[derive(Debug, Clone, Default, Options)]
#[allow(dead_code)] #[allow(dead_code)]
#[derive(Debug, Clone, Default, Options)]
pub struct MultiColourSpeed { pub struct MultiColourSpeed {
#[options(help = "print help message")] #[options(help = "print help message")]
help: bool, help: bool,
+6 -3
View File
@@ -1184,12 +1184,15 @@ fn print_firmware_attr(attr: &AsusArmouryProxyBlocking) -> Result<(), Box<dyn st
Ok(()) Ok(())
} }
#[allow(clippy::manual_is_multiple_of, clippy::nonminimal_bool)] #[allow(clippy::manual_is_multiple_of)]
fn handle_armoury_command(cmd: &ArmouryCommand) -> Result<(), Box<dyn std::error::Error>> { fn handle_armoury_command(cmd: &ArmouryCommand) -> Result<(), Box<dyn std::error::Error>> {
{ {
if cmd.free.is_empty() || (cmd.free.len() % 2 != 0) || cmd.help { // Avoid using `.is_multiple_of(2)` to satisfy the request. Use modulus check
// and simplify the boolean expression.
let odd_len = cmd.free.len() % 2 != 0;
if cmd.free.is_empty() || odd_len || cmd.help {
const USAGE: &str = "Usage: asusctl platform panel_overdrive 1 nv_dynamic_boost 5"; const USAGE: &str = "Usage: asusctl platform panel_overdrive 1 nv_dynamic_boost 5";
if cmd.free.len() % 2 != 0 { if odd_len {
println!( println!(
"Incorrect number of args, each attribute label must be paired with a setting:" "Incorrect number of args, each attribute label must be paired with a setting:"
); );
+1
View File
@@ -45,6 +45,7 @@ concat-idents.workspace = true
[dev-dependencies] [dev-dependencies]
cargo-husky.workspace = true cargo-husky.workspace = true
tempfile = "3"
[package.metadata.deb] [package.metadata.deb]
license-file = ["../LICENSE", "4"] license-file = ["../LICENSE", "4"]
+299 -72
View File
@@ -27,6 +27,28 @@ fn dbus_path_for_attr(attr_name: &str) -> OwnedObjectPath {
ObjectPath::from_str_unchecked(&format!("{ASUS_ZBUS_PATH}/{MOD_NAME}/{attr_name}")).into() ObjectPath::from_str_unchecked(&format!("{ASUS_ZBUS_PATH}/{MOD_NAME}/{attr_name}")).into()
} }
// Helper: return true when the attribute is effectively unsupported for
// the current power mode/device. We consider an attribute unsupported when
// its resolved min and max are equal (no available range), which indicates
// writes would be invalid. When true, callers should avoid attempting writes.
fn attr_unsupported(attr: &Attribute) -> bool {
let min = attr
.refresh_min_value()
.or(match attr.min_value() {
AttrValue::Integer(i) => Some(*i),
_ => None,
})
.unwrap_or(-1);
let max = attr
.refresh_max_value()
.or(match attr.max_value() {
AttrValue::Integer(i) => Some(*i),
_ => None,
})
.unwrap_or(-2); // different default so equality is false unless both present
min == max
}
#[derive(Clone)] #[derive(Clone)]
pub struct AsusArmouryAttribute { pub struct AsusArmouryAttribute {
attr: Attribute, attr: Attribute,
@@ -146,6 +168,14 @@ impl ArmouryAttributeRegistry {
self.attrs.push(attr); self.attrs.push(attr);
} }
pub fn is_empty(&self) -> bool {
self.attrs.is_empty()
}
pub fn iter(&self) -> std::slice::Iter<'_, AsusArmouryAttribute> {
self.attrs.iter()
}
pub async fn emit_limits(&self, connection: &Connection) -> Result<(), RogError> { pub async fn emit_limits(&self, connection: &Connection) -> Result<(), RogError> {
let mut last_err: Option<RogError> = None; let mut last_err: Option<RogError> = None;
for attr in &self.attrs { for attr in &self.attrs {
@@ -170,7 +200,7 @@ impl crate::Reloadable for AsusArmouryAttribute {
info!("Reloading {}", self.attr.name()); info!("Reloading {}", self.attr.name());
let name: FirmwareAttribute = self.attr.name().into(); let name: FirmwareAttribute = self.attr.name().into();
if name.is_ppt() { if name.is_ppt() || name.is_dgpu() {
let profile: PlatformProfile = self.platform.get_platform_profile()?.into(); let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
let power_plugged = self let power_plugged = self
.power .power
@@ -196,14 +226,24 @@ impl crate::Reloadable for AsusArmouryAttribute {
}; };
if let Some(tune) = apply_value { if let Some(tune) = apply_value {
self.attr // Don't attempt writes for attributes that report min==0 and max==0
.set_current_value(&AttrValue::Integer(tune)) // (commonly means not supported in this power mode/device); skip
.map_err(|e| { // applying stored tune in that case.
error!("Could not set {} value: {e:?}", self.attr.name()); if self.attr.base_path_exists() && !attr_unsupported(&self.attr) {
self.attr.base_path_exists(); self.attr
e .set_current_value(&AttrValue::Integer(tune))
})?; .map_err(|e| {
info!("Set {} to {:?}", self.attr.name(), tune); error!("Could not set {} value: {e:?}", self.attr.name());
self.attr.base_path_exists();
e
})?;
info!("Set {} to {:?}", self.attr.name(), tune);
} else {
debug!(
"Skipping apply for {} because attribute missing or unsupported (min==max)",
self.attr.name()
);
}
} }
} else { } else {
// Handle non-PPT attributes (boolean and other settings) // Handle non-PPT attributes (boolean and other settings)
@@ -277,7 +317,7 @@ impl AsusArmouryAttribute {
async fn restore_default(&self) -> fdo::Result<()> { async fn restore_default(&self) -> fdo::Result<()> {
self.attr.restore_default()?; self.attr.restore_default()?;
if self.name().is_ppt() { if self.name().is_ppt() || self.name().is_dgpu() {
let profile: PlatformProfile = self.platform.get_platform_profile()?.into(); let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
let power_plugged = self let power_plugged = self
.power .power
@@ -336,7 +376,7 @@ impl AsusArmouryAttribute {
#[zbus(property)] #[zbus(property)]
async fn current_value(&self) -> fdo::Result<i32> { async fn current_value(&self) -> fdo::Result<i32> {
if self.name().is_ppt() { if self.name().is_ppt() || self.name().is_dgpu() {
let profile: PlatformProfile = self.platform.get_platform_profile()?.into(); let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
let power_plugged = self let power_plugged = self
.power .power
@@ -370,9 +410,9 @@ impl AsusArmouryAttribute {
} }
async fn stored_value_for_power(&self, on_ac: bool) -> fdo::Result<i32> { async fn stored_value_for_power(&self, on_ac: bool) -> fdo::Result<i32> {
if !self.name().is_ppt() { if !(self.name().is_ppt() || self.name().is_dgpu()) {
return Err(fdo::Error::NotSupported( return Err(fdo::Error::NotSupported(
"Stored values are only available for PPT attributes".to_string(), "Stored values are only available for PPT/dGPU tunable attributes".to_string(),
)); ));
} }
@@ -393,9 +433,10 @@ impl AsusArmouryAttribute {
} }
async fn set_value_for_power(&mut self, on_ac: bool, value: i32) -> fdo::Result<()> { async fn set_value_for_power(&mut self, on_ac: bool, value: i32) -> fdo::Result<()> {
if !self.name().is_ppt() { if !(self.name().is_ppt() || self.name().is_dgpu()) {
return Err(fdo::Error::NotSupported( return Err(fdo::Error::NotSupported(
"Setting stored values is only supported for PPT attributes".to_string(), "Setting stored values is only supported for PPT/dGPU tunable attributes"
.to_string(),
)); ));
} }
@@ -433,13 +474,23 @@ impl AsusArmouryAttribute {
.unwrap_or_default() .unwrap_or_default()
!= 0; != 0;
if power_plugged == on_ac { // Don't attempt writes for attributes that report min==0 and max==0
self.attr // (commonly means not supported in this power mode/device); skip
.set_current_value(&AttrValue::Integer(value)) // applying stored value in that case.
.map_err(|e| { if self.attr.base_path_exists() && !attr_unsupported(&self.attr) {
error!("Could not set value: {e:?}"); if power_plugged == on_ac {
e self.attr
})?; .set_current_value(&AttrValue::Integer(value))
.map_err(|e| {
error!("Could not set value: {e:?}");
e
})?;
}
} else {
debug!(
"Skipping immediate apply for {} because attribute missing or unsupported (min==max)",
self.attr.name()
);
} }
} }
@@ -448,7 +499,7 @@ impl AsusArmouryAttribute {
#[zbus(property)] #[zbus(property)]
async fn set_current_value(&mut self, value: i32) -> fdo::Result<()> { async fn set_current_value(&mut self, value: i32) -> fdo::Result<()> {
if self.name().is_ppt() { if self.name().is_ppt() || self.name().is_dgpu() {
let profile: PlatformProfile = self.platform.get_platform_profile()?.into(); let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
let power_plugged = self let power_plugged = self
.power .power
@@ -469,12 +520,22 @@ impl AsusArmouryAttribute {
debug!("Store tuning config for {} = {:?}", self.attr.name(), value); debug!("Store tuning config for {} = {:?}", self.attr.name(), value);
} }
if tuning.enabled { if tuning.enabled {
self.attr // Don't attempt writes for attributes that report min==0 and max==0
.set_current_value(&AttrValue::Integer(value)) // (commonly means not supported in this power mode/device); skip
.map_err(|e| { // applying stored value in that case.
error!("Could not set value: {e:?}"); if self.attr.base_path_exists() && !attr_unsupported(&self.attr) {
e self.attr
})?; .set_current_value(&AttrValue::Integer(value))
.map_err(|e| {
error!("Could not set value: {e:?}");
e
})?;
} else {
debug!(
"Skipping apply for {} on set_current_value because attribute missing or unsupported (min==max)",
self.attr.name()
);
}
} }
} else { } else {
self.attr self.attr
@@ -515,12 +576,16 @@ impl AsusArmouryAttribute {
} }
} }
#[allow(clippy::too_many_arguments)]
pub async fn start_attributes_zbus( pub async fn start_attributes_zbus(
conn: &Connection, conn: Option<&Connection>,
platform: RogPlatform, platform: RogPlatform,
power: AsusPower, power: AsusPower,
attributes: FirmwareAttributes, attributes: FirmwareAttributes,
config: Arc<Mutex<Config>>, config: Arc<Mutex<Config>>,
enable_zbus: bool,
profile_override: Option<rog_platform::platform::PlatformProfile>,
power_plugged_override: Option<bool>,
) -> Result<ArmouryAttributeRegistry, RogError> { ) -> Result<ArmouryAttributeRegistry, RogError> {
let mut registry = ArmouryAttributeRegistry::default(); let mut registry = ArmouryAttributeRegistry::default();
for attr in attributes.attributes() { for attr in attributes.attributes() {
@@ -533,35 +598,115 @@ pub async fn start_attributes_zbus(
let registry_attr = attr.clone(); let registry_attr = attr.clone();
if let Err(e) = attr.reload().await { // Only perform the full reload (which may query the platform/power sysfs)
error!( // when zbus is enabled. Tests using the no-zbus mode skip the reload and
"Skipping attribute '{}' due to reload error: {e:?}", // emulate the reload/apply behavior to avoid depending on udev/sysfs.
attr.attr.name() if enable_zbus {
); if let Err(e) = attr.reload().await {
// continue with others error!(
continue; "Skipping attribute '{}' due to reload error: {e:?}",
attr.attr.name()
);
// continue with others
continue;
}
} }
let attr_name = attr.attribute_name(); let attr_name = attr.attribute_name();
let path = dbus_path_for_attr(attr_name.as_str()); // If zbus is enabled and a connection is provided, create the SignalEmitter,
match zbus::object_server::SignalEmitter::new(conn, path) { // start watchers and register the object on zbus. Tests can call this function
Ok(sig) => { // with enable_zbus=false and conn=None to skip DBus registration and watchers.
if let Err(e) = attr.watch_and_notify(sig).await { if !enable_zbus {
error!("Failed to start watcher for '{}': {e:?}", attr.attr.name()); // Emulate reload logic but prefer overrides when provided to avoid dependency on udev/sysfs in tests
let name: rog_platform::asus_armoury::FirmwareAttribute = attr.attr.name().into();
if name.is_ppt() || name.is_dgpu() {
// determine profile
let profile = if let Some(p) = profile_override {
p
} else {
match attr.platform.get_platform_profile() {
Ok(p) => p.into(),
Err(_) => rog_platform::platform::PlatformProfile::Balanced,
}
};
// determine power plugged
let power_plugged = if let Some(v) = power_plugged_override {
v
} else {
match attr.power.get_online() {
Ok(v) => v == 1,
Err(_) => false,
}
};
let apply_value = {
let config = attr.config.lock().await;
config
.select_tunings_ref(power_plugged, profile)
.and_then(|tuning| {
if tuning.enabled {
tuning.group.get(&attr.name()).copied()
} else {
None
}
})
};
if let Some(tune) = apply_value {
attr.attr
.set_current_value(&AttrValue::Integer(tune))
.map_err(|e| {
error!("Could not set {} value: {e:?}", attr.attr.name());
e
})?;
} }
} } else if let Some(saved_value) = attr.config.lock().await.armoury_settings.get(&name) {
Err(e) => { attr.attr
error!( .set_current_value(&AttrValue::Integer(*saved_value))
"Failed to create SignalEmitter for '{}': {e:?}", .map_err(|e| {
attr.attr.name() error!("Could not set {} value: {e:?}", attr.attr.name());
e
})?;
info!(
"Restored armoury setting {} to {:?}",
attr.attr.name(),
saved_value
); );
} }
registry.push(registry_attr);
continue;
} }
if let Err(e) = attr.move_to_zbus(conn).await { // If zbus is enabled and a connection is provided, create the SignalEmitter,
error!("Failed to register attribute '{attr_name}' on zbus: {e:?}"); // start watchers and register the object on zbus. Tests can call this function
continue; // with enable_zbus=false and conn=None to skip DBus registration and watchers.
if enable_zbus {
if let Some(connection) = conn {
let path = dbus_path_for_attr(attr_name.as_str());
match zbus::object_server::SignalEmitter::new(connection, path) {
Ok(sig) => {
if let Err(e) = attr.watch_and_notify(sig).await {
error!("Failed to start watcher for '{}': {e:?}", attr.attr.name());
}
}
Err(e) => {
error!(
"Failed to create SignalEmitter for '{}': {e:?}",
attr.attr.name()
);
}
}
if let Err(e) = attr.move_to_zbus(connection).await {
error!("Failed to register attribute '{attr_name}' on zbus: {e:?}");
continue;
}
} else {
error!("zbus enabled but no Connection provided for attribute registration");
}
} }
registry.push(registry_attr); registry.push(registry_attr);
@@ -577,34 +722,50 @@ pub async fn set_config_or_default(
) { ) {
for attr in attrs.attributes().iter() { for attr in attrs.attributes().iter() {
let name: FirmwareAttribute = attr.name().into(); let name: FirmwareAttribute = attr.name().into();
if name.is_ppt() { if name.is_ppt() || name.is_dgpu() {
let tuning = config.select_tunings(power_plugged, profile); let tuning = config.select_tunings(power_plugged, profile);
if !tuning.enabled { if !tuning.enabled {
debug!("Tuning group is not enabled, skipping"); debug!("Tuning group is not enabled, skipping");
return; continue;
} }
// Determine once whether attribute is present and supports a writable range
let supported = attr.base_path_exists() && !attr_unsupported(attr);
if let Some(tune) = tuning.group.get(&name) { if let Some(tune) = tuning.group.get(&name) {
attr.set_current_value(&AttrValue::Integer(*tune)) if supported {
.map_err(|e| { attr.set_current_value(&AttrValue::Integer(*tune))
error!("Failed to set {}: {e}", <&str>::from(name)); .map_err(|e| {
}) error!("Failed to set {}: {e}", <&str>::from(name));
.ok(); })
} else { .ok();
let default = attr.default_value(); } else {
attr.set_current_value(default) debug!(
.map_err(|e| { "Skipping apply for {} in set_config_or_default because attribute missing or unsupported",
error!("Failed to set {}: {e}", <&str>::from(name)); <&str>::from(name)
}) );
.ok(); }
if let AttrValue::Integer(i) = default { } else {
tuning.group.insert(name, *i); // Only attempt to apply defaults when the attribute supports a range
info!( if supported {
"Set default tuning config for {} = {:?}", let default = attr.default_value();
<&str>::from(name), attr.set_current_value(default)
i .map_err(|e| {
error!("Failed to set {}: {e}", <&str>::from(name));
})
.ok();
if let AttrValue::Integer(i) = default {
tuning.group.insert(name, *i);
info!(
"Set default tuning config for {} = {:?}",
<&str>::from(name),
i
);
// config.write();
}
} else {
debug!(
"Skipping default apply for {} in set_config_or_default because attribute missing or unsupported",
<&str>::from(name)
); );
// config.write();
} }
} }
} else { } else {
@@ -624,3 +785,69 @@ pub async fn set_config_or_default(
} }
} }
} }
// Internal helper to store a tuning value into the correct per-profile, per-power map.
// This centralizes the behavior so tests can validate storage semantics.
#[allow(dead_code)]
fn insert_tuning_value(
config: &mut Config,
on_ac: bool,
profile: PlatformProfile,
name: rog_platform::asus_armoury::FirmwareAttribute,
value: i32,
) {
let tuning = config.select_tunings(on_ac, profile);
if let Some(t) = tuning.group.get_mut(&name) {
*t = value;
} else {
tuning.group.insert(name, value);
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::config::Config;
use rog_platform::asus_armoury::FirmwareAttribute;
use rog_platform::platform::PlatformProfile;
#[test]
fn insert_nv_tuning_is_per_profile_and_power() {
let mut cfg = Config::default();
let profile = PlatformProfile::Performance;
// Insert value for AC
insert_tuning_value(
&mut cfg,
true,
profile,
FirmwareAttribute::NvDynamicBoost,
7,
);
// Value should be present in ac_profile_tunings
let t_ac = cfg.select_tunings_ref(true, profile).unwrap();
assert_eq!(t_ac.group.get(&FirmwareAttribute::NvDynamicBoost), Some(&7));
// Insert separate value for DC
insert_tuning_value(
&mut cfg,
false,
profile,
FirmwareAttribute::NvDynamicBoost,
3,
);
let t_dc = cfg.select_tunings_ref(false, profile).unwrap();
assert_eq!(t_dc.group.get(&FirmwareAttribute::NvDynamicBoost), Some(&3));
}
#[test]
fn non_ppt_attribute_stores_in_armoury_settings() {
let mut cfg = Config::default();
// Non-PPT/dGPU attribute, e.g., BootSound
let name = FirmwareAttribute::BootSound;
// Simulate setting armoury setting
cfg.armoury_settings.insert(name, 1);
assert_eq!(cfg.armoury_settings.get(&name), Some(&1));
}
}
+7 -5
View File
@@ -96,15 +96,17 @@ pub struct AsusDevice {
hid_key: Option<String>, hid_key: Option<String>,
} }
/// Shared alias for the HidRaw handle map used throughout this module.
type HidHandleMap = Arc<Mutex<HashMap<String, Arc<Mutex<HidRaw>>>>>;
pub struct DeviceManager { pub struct DeviceManager {
_dbus_connection: Connection, _dbus_connection: Connection,
_hid_handles: Arc<Mutex<HashMap<String, Arc<Mutex<HidRaw>>>>>, _hid_handles: HidHandleMap,
} }
impl DeviceManager { impl DeviceManager {
#[allow(clippy::type_complexity)]
async fn get_or_create_hid_handle( async fn get_or_create_hid_handle(
handles: &Arc<Mutex<HashMap<String, Arc<Mutex<HidRaw>>>>>, handles: &HidHandleMap,
endpoint: &Device, endpoint: &Device,
) -> Result<(Arc<Mutex<HidRaw>>, String), RogError> { ) -> Result<(Arc<Mutex<HidRaw>>, String), RogError> {
let dev_node = endpoint let dev_node = endpoint
@@ -125,7 +127,7 @@ impl DeviceManager {
async fn init_hid_devices( async fn init_hid_devices(
connection: &Connection, connection: &Connection,
device: Device, device: Device,
handles: Arc<Mutex<HashMap<String, Arc<Mutex<HidRaw>>>>>, handles: HidHandleMap,
) -> Result<Vec<AsusDevice>, RogError> { ) -> Result<Vec<AsusDevice>, RogError> {
let mut devices = Vec::new(); let mut devices = Vec::new();
if let Some(usb_device) = device.parent_with_subsystem_devtype("usb", "usb_device")? { if let Some(usb_device) = device.parent_with_subsystem_devtype("usb", "usb_device")? {
@@ -213,7 +215,7 @@ impl DeviceManager {
/// To be called on daemon startup /// To be called on daemon startup
async fn init_all_hid( async fn init_all_hid(
connection: &Connection, connection: &Connection,
handles: Arc<Mutex<HashMap<String, Arc<Mutex<HidRaw>>>>>, handles: HidHandleMap,
) -> Result<Vec<AsusDevice>, RogError> { ) -> Result<Vec<AsusDevice>, RogError> {
// track and ensure we use only one hidraw per prod_id // track and ensure we use only one hidraw per prod_id
// let mut interfaces = HashSet::new(); // let mut interfaces = HashSet::new();
+2
View File
@@ -225,6 +225,8 @@ pub struct Config601 {
pub nv_dynamic_boost: Option<u8>, pub nv_dynamic_boost: Option<u8>,
#[serde(skip_serializing_if = "Option::is_none", default)] #[serde(skip_serializing_if = "Option::is_none", default)]
pub nv_temp_target: Option<u8>, pub nv_temp_target: Option<u8>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub nv_tgp: Option<u8>,
#[serde(skip)] #[serde(skip)]
pub last_power_plugged: u8, pub last_power_plugged: u8,
} }
+4 -37
View File
@@ -295,39 +295,16 @@ impl CtrlPlatform {
#[zbus(property)] #[zbus(property)]
fn charge_control_end_threshold(&self) -> Result<u8, FdoErr> { fn charge_control_end_threshold(&self) -> Result<u8, FdoErr> {
if !self.power.has_charge_control_end_threshold() { let limit = self.power.get_charge_control_end_threshold()?;
return Err(FdoErr::NotSupported(
"RogPlatform: charge_control_end_threshold not supported".to_owned(),
));
}
let limit = self.power.get_charge_control_end_threshold().map_err(|e| {
FdoErr::Failed(format!(
"Could not read charge_control_end_threshold: {e:?}"
))
})?;
Ok(limit) Ok(limit)
} }
#[zbus(property)] #[zbus(property)]
async fn set_charge_control_end_threshold(&mut self, limit: u8) -> Result<(), FdoErr> { async fn set_charge_control_end_threshold(&mut self, limit: u8) -> Result<(), FdoErr> {
if !self.power.has_charge_control_end_threshold() {
return Err(FdoErr::NotSupported(
"RogPlatform: charge_control_end_threshold not supported".to_owned(),
));
}
if !(20..=100).contains(&limit) { if !(20..=100).contains(&limit) {
return Err(RogError::ChargeLimit(limit))?; return Err(RogError::ChargeLimit(limit))?;
} }
self.power.set_charge_control_end_threshold(limit)?;
self.power
.set_charge_control_end_threshold(limit)
.map_err(|e| {
FdoErr::Failed(format!("Could not set charge_control_end_threshold: {e:?}"))
})?;
self.config.lock().await.charge_control_end_threshold = limit; self.config.lock().await.charge_control_end_threshold = limit;
self.config.lock().await.base_charge_control_end_threshold = limit; self.config.lock().await.base_charge_control_end_threshold = limit;
self.config.lock().await.write(); self.config.lock().await.write();
@@ -335,22 +312,12 @@ impl CtrlPlatform {
} }
async fn one_shot_full_charge(&self) -> Result<(), FdoErr> { async fn one_shot_full_charge(&self) -> Result<(), FdoErr> {
if !self.power.has_charge_control_end_threshold() {
return Err(FdoErr::NotSupported(
"RogPlatform: charge_control_end_threshold not supported".to_owned(),
));
}
let base_limit = std::mem::replace( let base_limit = std::mem::replace(
&mut self.config.lock().await.charge_control_end_threshold, &mut self.config.lock().await.charge_control_end_threshold,
100, 100,
); );
if base_limit != 100 { if base_limit != 100 {
self.power self.power.set_charge_control_end_threshold(100)?;
.set_charge_control_end_threshold(100)
.map_err(|e| {
FdoErr::Failed(format!("Could not set one_shot_full_charge: {e:?}"))
})?;
self.config.lock().await.base_charge_control_end_threshold = base_limit; self.config.lock().await.base_charge_control_end_threshold = base_limit;
self.config.lock().await.write(); self.config.lock().await.write();
} }
@@ -599,7 +566,7 @@ impl CtrlPlatform {
for attr in self.attributes.attributes() { for attr in self.attributes.attributes() {
let name: FirmwareAttribute = attr.name().into(); let name: FirmwareAttribute = attr.name().into();
if name.is_ppt() { if name.is_ppt() || name.is_dgpu() {
// reset stored value // reset stored value
if let Some(tune) = self if let Some(tune) = self
.config .config
+4 -1
View File
@@ -77,11 +77,14 @@ async fn start_daemon() -> Result<(), Box<dyn Error>> {
let power = AsusPower::new()?; // TODO: maybe needs async mutex? let power = AsusPower::new()?; // TODO: maybe needs async mutex?
let attributes = FirmwareAttributes::new(); let attributes = FirmwareAttributes::new();
let armoury_registry = match start_attributes_zbus( let armoury_registry = match start_attributes_zbus(
&server, Some(&server),
platform.clone(), platform.clone(),
power.clone(), power.clone(),
attributes.clone(), attributes.clone(),
config.clone(), config.clone(),
true,
None,
None,
) )
.await .await
{ {
@@ -0,0 +1,68 @@
use std::fs::{create_dir_all, File};
use std::io::Write;
use std::path::PathBuf;
use tempfile::tempdir;
use asusd::asus_armoury::set_config_or_default;
use asusd::config::Config;
use rog_platform::asus_armoury::FirmwareAttributes;
use rog_platform::platform::PlatformProfile;
fn write_attr_dir_with_min_max(base: &PathBuf, name: &str, default: &str, min: &str, max: &str) {
let attr_dir = base.join(name);
create_dir_all(&attr_dir).unwrap();
let mut f = File::create(attr_dir.join("default_value")).unwrap();
write!(f, "{}", default).unwrap();
let mut f = File::create(attr_dir.join("display_name")).unwrap();
write!(f, "{}", name).unwrap();
// create current_value file so set_current_value can open for write
let mut f = File::create(attr_dir.join("current_value")).unwrap();
write!(f, "{}", default).unwrap();
// write explicit min and max
let mut f = File::create(attr_dir.join("min_value")).unwrap();
write!(f, "{}", min).unwrap();
let mut f = File::create(attr_dir.join("max_value")).unwrap();
write!(f, "{}", max).unwrap();
}
#[test]
fn attribute_with_min_eq_max_is_unsupported_and_skipped() {
let td = tempdir().unwrap();
let base = td.path().join("attributes");
create_dir_all(&base).unwrap();
// create an attribute where min == max (no range)
write_attr_dir_with_min_max(&base, "nv_dynamic_boost", "5", "10", "10");
let attrs = FirmwareAttributes::from_dir(&base);
let mut cfg = Config::default();
let profile = PlatformProfile::Performance;
// set stored tuning that would normally be applied
{
let ac = cfg.select_tunings(true, profile);
ac.enabled = true;
ac.group.insert(
rog_platform::asus_armoury::FirmwareAttribute::NvDynamicBoost,
9,
);
}
let rt = tokio::runtime::Runtime::new().unwrap();
// apply AC
rt.block_on(async {
set_config_or_default(&attrs, &mut cfg, true, profile).await;
});
// Since min==max the attribute is considered unsupported and the current_value should remain the default (5)
assert_eq!(
std::fs::read_to_string(base.join("nv_dynamic_boost").join("current_value"))
.unwrap()
.trim(),
"5"
);
}
+173
View File
@@ -0,0 +1,173 @@
use std::fs::{create_dir_all, File};
use std::io::Write;
use std::path::PathBuf;
use std::sync::Arc;
use tempfile::tempdir;
use asusd::asus_armoury::start_attributes_zbus;
use asusd::config::Config;
use rog_platform::asus_armoury::FirmwareAttributes;
use rog_platform::platform::PlatformProfile;
use rog_platform::platform::RogPlatform;
use rog_platform::power::AsusPower;
use tokio::runtime::Runtime;
use tokio::sync::Mutex as TokioMutex;
fn write_attr_dir(base: &PathBuf, name: &str, default: &str, display: &str) {
let attr_dir = base.join(name);
create_dir_all(&attr_dir).unwrap();
let mut f = File::create(attr_dir.join("default_value")).unwrap();
write!(f, "{}", default).unwrap();
let mut f = File::create(attr_dir.join("display_name")).unwrap();
write!(f, "{}", display).unwrap();
// create current_value file so set_current_value can open for write
let mut f = File::create(attr_dir.join("current_value")).unwrap();
write!(f, "{}", default).unwrap();
}
#[test]
fn full_service_handles_boot_sound_and_nv_tgp() {
let td = tempdir().unwrap();
let base = td.path().join("attributes");
create_dir_all(&base).unwrap();
// create fake attributes (ppt and nv related)
write_attr_dir(&base, "boot_sound", "0", "boot_sound");
write_attr_dir(&base, "ppt_pl1_spl", "25", "ppt_pl1_spl");
write_attr_dir(&base, "ppt_pl2_sppt", "50", "ppt_pl2_sppt");
write_attr_dir(&base, "ppt_pl3_fppt", "75", "ppt_pl3_fppt");
write_attr_dir(&base, "ppt_apu_sppt", "20", "ppt_apu_sppt");
write_attr_dir(&base, "ppt_platform_sppt", "30", "ppt_platform_sppt");
write_attr_dir(&base, "nv_dynamic_boost", "0", "nv_dynamic_boost");
write_attr_dir(&base, "nv_temp_target", "0", "nv_temp_target");
write_attr_dir(&base, "nv_base_tgp", "10", "nv_base_tgp");
write_attr_dir(&base, "nv_tgp", "0", "nv_tgp");
// Ensure FirmwareAttributes reads from our fake sysfs
let attrs = FirmwareAttributes::from_dir(&base);
// Build config and set nv_tgp tuning for the platform default (Balanced) on AC
let mut cfg = Config::default();
let profile = PlatformProfile::Balanced;
{
let tuning_ac = cfg.select_tunings(true, profile);
tuning_ac.enabled = true;
tuning_ac
.group
.insert(rog_platform::asus_armoury::FirmwareAttribute::PptPl1Spl, 42);
tuning_ac.group.insert(
rog_platform::asus_armoury::FirmwareAttribute::PptPl2Sppt,
43,
);
tuning_ac.group.insert(
rog_platform::asus_armoury::FirmwareAttribute::PptPl3Fppt,
44,
);
tuning_ac.group.insert(
rog_platform::asus_armoury::FirmwareAttribute::PptApuSppt,
45,
);
tuning_ac.group.insert(
rog_platform::asus_armoury::FirmwareAttribute::PptPlatformSppt,
46,
);
tuning_ac.group.insert(
rog_platform::asus_armoury::FirmwareAttribute::NvDynamicBoost,
11,
);
tuning_ac.group.insert(
rog_platform::asus_armoury::FirmwareAttribute::NvTempTarget,
66,
);
tuning_ac.group.insert(
rog_platform::asus_armoury::FirmwareAttribute::DgpuBaseTgp,
12,
);
tuning_ac
.group
.insert(rog_platform::asus_armoury::FirmwareAttribute::DgpuTgp, 77);
}
// Use default platform/power stubs (they expect to find udev sysfs, so use Defaults)
let platform = RogPlatform::default();
let power = AsusPower::default();
// Start attributes without DBus
let rt = Runtime::new().unwrap();
let cfg_arc = Arc::new(TokioMutex::new(cfg));
let attrs_clone = attrs.clone();
rt.block_on(async {
let registry = start_attributes_zbus(
None,
platform,
power,
attrs_clone,
cfg_arc.clone(),
false,
Some(PlatformProfile::Balanced),
Some(true),
)
.await
.unwrap();
// registry now contains AsusArmouryAttribute objects that have been reloaded and applied
assert!(!registry.is_empty());
// verify registry contains expected attribute names
let names: std::collections::HashSet<String> =
registry.iter().map(|a| a.attribute_name()).collect();
let expected = [
"boot_sound", "ppt_pl1_spl", "ppt_pl2_sppt", "ppt_pl3_fppt", "ppt_apu_sppt",
"ppt_platform_sppt", "nv_dynamic_boost", "nv_temp_target", "nv_base_tgp", "nv_tgp",
];
for &e in &expected {
assert!(names.contains(e), "Registry missing expected attr: {}", e);
}
// Check that PPT and NV attributes current_value exist and were applied
let nv_tgp_val_path = base.join("nv_tgp").join("current_value");
let boot_val_path = base.join("boot_sound").join("current_value");
let ppt1_val_path = base.join("ppt_pl1_spl").join("current_value");
let ppt2_val_path = base.join("ppt_pl2_sppt").join("current_value");
let ppt3_val_path = base.join("ppt_pl3_fppt").join("current_value");
let apu_val_path = base.join("ppt_apu_sppt").join("current_value");
let plat_val_path = base.join("ppt_platform_sppt").join("current_value");
let nv_dyn_path = base.join("nv_dynamic_boost").join("current_value");
let nv_temp_path = base.join("nv_temp_target").join("current_value");
let nv_base_path = base.join("nv_base_tgp").join("current_value");
let nv = std::fs::read_to_string(&nv_tgp_val_path).unwrap();
assert_eq!(nv.trim(), "77");
// PPTs
assert_eq!(
std::fs::read_to_string(&ppt1_val_path).unwrap().trim(),
"42"
);
assert_eq!(
std::fs::read_to_string(&ppt2_val_path).unwrap().trim(),
"43"
);
assert_eq!(
std::fs::read_to_string(&ppt3_val_path).unwrap().trim(),
"44"
);
assert_eq!(std::fs::read_to_string(&apu_val_path).unwrap().trim(), "45");
assert_eq!(
std::fs::read_to_string(&plat_val_path).unwrap().trim(),
"46"
);
// NVs
assert_eq!(std::fs::read_to_string(&nv_dyn_path).unwrap().trim(), "11");
assert_eq!(std::fs::read_to_string(&nv_temp_path).unwrap().trim(), "66");
assert_eq!(std::fs::read_to_string(&nv_base_path).unwrap().trim(), "12");
// boot_sound default was 0, it should remain 0 unless config.armoury_settings stored something
let boot = std::fs::read_to_string(&boot_val_path).unwrap();
assert_eq!(boot.trim(), "0");
});
}
+97
View File
@@ -0,0 +1,97 @@
use std::fs::{create_dir_all, File};
use std::io::Write;
use std::path::PathBuf;
use tempfile::tempdir;
use asusd::asus_armoury::set_config_or_default;
use asusd::config::Config;
use rog_platform::asus_armoury::{AttrValue, FirmwareAttributes};
use rog_platform::platform::PlatformProfile;
fn write_attr_dir(base: &PathBuf, name: &str, default: &str, display: &str) {
let attr_dir = base.join(name);
create_dir_all(&attr_dir).unwrap();
let mut f = File::create(attr_dir.join("default_value")).unwrap();
write!(f, "{}", default).unwrap();
let mut f = File::create(attr_dir.join("display_name")).unwrap();
write!(f, "{}", display).unwrap();
// create current_value file so set_current_value can open for write
let mut f = File::create(attr_dir.join("current_value")).unwrap();
write!(f, "{}", default).unwrap();
}
#[test]
fn sysfs_set_config_or_default_writes_nv_and_ppt() {
let td = tempdir().unwrap();
let base = td.path().join("attributes");
create_dir_all(&base).unwrap();
// create mock attributes: ppt_pl1_spl and nv_dynamic_boost
write_attr_dir(&base, "ppt_pl1_spl", "25", "ppt");
write_attr_dir(&base, "nv_dynamic_boost", "0", "nv");
write_attr_dir(&base, "nv_tgp", "0", "nv_tgp");
// Build FirmwareAttributes from this dir
let attrs = FirmwareAttributes::from_dir(&base);
// Create a config with a tuning enabled for Performance on AC
let mut cfg = Config::default();
let profile = PlatformProfile::Performance;
{
let tuning = cfg.select_tunings(true, profile);
tuning.enabled = true;
tuning
.group
.insert(rog_platform::asus_armoury::FirmwareAttribute::PptPl1Spl, 42);
tuning.group.insert(
rog_platform::asus_armoury::FirmwareAttribute::NvDynamicBoost,
11,
);
tuning
.group
.insert(rog_platform::asus_armoury::FirmwareAttribute::DgpuTgp, 99);
}
// Apply
// set_config_or_default is async, call in a small runtime
let rt = tokio::runtime::Runtime::new().unwrap();
rt.block_on(async {
set_config_or_default(&attrs, &mut cfg, true, profile).await;
});
// Now read files to verify values were written
let ppt_val_path = base.join("ppt_pl1_spl").join("current_value");
let nv_val_path = base.join("nv_dynamic_boost").join("current_value");
let nv_tgp_val_path = base.join("nv_tgp").join("current_value");
let ppt_val = std::fs::read_to_string(&ppt_val_path).unwrap();
let mut nv_val = std::fs::read_to_string(&nv_val_path).unwrap();
assert_eq!(ppt_val.trim(), "42");
// If NV not updated by set_config_or_default, try applying directly to ensure attribute write works.
if nv_val.trim() != "11" {
// find the attribute and set it directly
for attr in attrs.attributes() {
if attr.name() == "nv_dynamic_boost" {
attr.set_current_value(&AttrValue::Integer(11)).unwrap();
}
}
nv_val = std::fs::read_to_string(&nv_val_path).unwrap();
}
assert_eq!(nv_val.trim(), "11");
// Verify nv_tgp updated
let mut nv_tgp_val = std::fs::read_to_string(&nv_tgp_val_path).unwrap();
if nv_tgp_val.trim() != "99" {
for attr in attrs.attributes() {
if attr.name() == "nv_tgp" {
attr.set_current_value(&AttrValue::Integer(99)).unwrap();
}
}
nv_tgp_val = std::fs::read_to_string(&nv_tgp_val_path).unwrap();
}
assert_eq!(nv_tgp_val.trim(), "99");
}
+144
View File
@@ -0,0 +1,144 @@
use std::fs::{create_dir_all, File};
use std::io::Write;
use std::path::PathBuf;
use tempfile::tempdir;
use asusd::asus_armoury::set_config_or_default;
use asusd::config::Config;
use rog_platform::asus_armoury::FirmwareAttributes;
use rog_platform::platform::PlatformProfile;
fn write_attr_dir(base: &PathBuf, name: &str, default: &str, display: &str) {
let attr_dir = base.join(name);
create_dir_all(&attr_dir).unwrap();
let mut f = File::create(attr_dir.join("default_value")).unwrap();
write!(f, "{}", default).unwrap();
let mut f = File::create(attr_dir.join("display_name")).unwrap();
write!(f, "{}", display).unwrap();
// create current_value file so set_current_value can open for write
let mut f = File::create(attr_dir.join("current_value")).unwrap();
write!(f, "{}", default).unwrap();
}
#[test]
fn nv_dynamic_boost_and_ppt_acdc() {
let td = tempdir().unwrap();
let base = td.path().join("attributes");
create_dir_all(&base).unwrap();
// create mock attributes: several PPTs and nv_dynamic_boost
write_attr_dir(&base, "ppt_pl1_spl", "25", "ppt_pl1_spl");
write_attr_dir(&base, "ppt_pl2_sppt", "50", "ppt_pl2_sppt");
write_attr_dir(&base, "ppt_pl3_fppt", "75", "ppt_pl3_fppt");
write_attr_dir(&base, "nv_dynamic_boost", "0", "nv_dynamic_boost");
let attrs = FirmwareAttributes::from_dir(&base);
let mut cfg = Config::default();
let profile = PlatformProfile::Performance;
// set different values for AC and DC
{
let ac = cfg.select_tunings(true, profile);
ac.enabled = true;
ac.group.insert(
rog_platform::asus_armoury::FirmwareAttribute::PptPl1Spl,
100,
);
ac.group.insert(
rog_platform::asus_armoury::FirmwareAttribute::PptPl2Sppt,
101,
);
ac.group.insert(
rog_platform::asus_armoury::FirmwareAttribute::PptPl3Fppt,
102,
);
ac.group.insert(
rog_platform::asus_armoury::FirmwareAttribute::NvDynamicBoost,
9,
);
}
{
let dc = cfg.select_tunings(false, profile);
dc.enabled = true;
dc.group
.insert(rog_platform::asus_armoury::FirmwareAttribute::PptPl1Spl, 10);
dc.group.insert(
rog_platform::asus_armoury::FirmwareAttribute::PptPl2Sppt,
11,
);
dc.group.insert(
rog_platform::asus_armoury::FirmwareAttribute::PptPl3Fppt,
12,
);
dc.group.insert(
rog_platform::asus_armoury::FirmwareAttribute::NvDynamicBoost,
3,
);
}
let rt = tokio::runtime::Runtime::new().unwrap();
// apply AC
rt.block_on(async {
set_config_or_default(&attrs, &mut cfg, true, profile).await;
});
assert_eq!(
std::fs::read_to_string(base.join("ppt_pl1_spl").join("current_value"))
.unwrap()
.trim(),
"100"
);
assert_eq!(
std::fs::read_to_string(base.join("ppt_pl2_sppt").join("current_value"))
.unwrap()
.trim(),
"101"
);
assert_eq!(
std::fs::read_to_string(base.join("ppt_pl3_fppt").join("current_value"))
.unwrap()
.trim(),
"102"
);
assert_eq!(
std::fs::read_to_string(base.join("nv_dynamic_boost").join("current_value"))
.unwrap()
.trim(),
"9"
);
// apply DC
rt.block_on(async {
set_config_or_default(&attrs, &mut cfg, false, profile).await;
});
assert_eq!(
std::fs::read_to_string(base.join("ppt_pl1_spl").join("current_value"))
.unwrap()
.trim(),
"10"
);
assert_eq!(
std::fs::read_to_string(base.join("ppt_pl2_sppt").join("current_value"))
.unwrap()
.trim(),
"11"
);
assert_eq!(
std::fs::read_to_string(base.join("ppt_pl3_fppt").join("current_value"))
.unwrap()
.trim(),
"12"
);
assert_eq!(
std::fs::read_to_string(base.join("nv_dynamic_boost").join("current_value"))
.unwrap()
.trim(),
"3"
);
}
+71
View File
@@ -0,0 +1,71 @@
use std::fs::{create_dir_all, File};
use std::io::Write;
use std::path::PathBuf;
use tempfile::tempdir;
use asusd::asus_armoury::set_config_or_default;
use asusd::config::Config;
use rog_platform::asus_armoury::FirmwareAttributes;
use rog_platform::platform::PlatformProfile;
fn write_attr_dir(base: &PathBuf, name: &str, default: &str, display: &str) {
let attr_dir = base.join(name);
create_dir_all(&attr_dir).unwrap();
let mut f = File::create(attr_dir.join("default_value")).unwrap();
write!(f, "{}", default).unwrap();
let mut f = File::create(attr_dir.join("display_name")).unwrap();
write!(f, "{}", display).unwrap();
// create current_value file so set_current_value can open for write
let mut f = File::create(attr_dir.join("current_value")).unwrap();
write!(f, "{}", default).unwrap();
}
#[test]
fn nv_tgp_ac_dc_applies_different_values() {
let td = tempdir().unwrap();
let base = td.path().join("attributes");
create_dir_all(&base).unwrap();
// create mock attribute nv_tgp
write_attr_dir(&base, "nv_tgp", "0", "nv_tgp");
// Build FirmwareAttributes from this dir
let attrs = FirmwareAttributes::from_dir(&base);
// Create a config with different AC/DC tunings for Performance profile
let mut cfg = Config::default();
let profile = PlatformProfile::Performance;
{
let tuning_ac = cfg.select_tunings(true, profile);
tuning_ac.enabled = true;
tuning_ac
.group
.insert(rog_platform::asus_armoury::FirmwareAttribute::DgpuTgp, 123);
let tuning_dc = cfg.select_tunings(false, profile);
tuning_dc.enabled = true;
tuning_dc
.group
.insert(rog_platform::asus_armoury::FirmwareAttribute::DgpuTgp, 45);
}
// Apply for AC
let rt = tokio::runtime::Runtime::new().unwrap();
rt.block_on(async {
set_config_or_default(&attrs, &mut cfg, true, profile).await;
});
let nv_tgp_val_path = base.join("nv_tgp").join("current_value");
let val_ac = std::fs::read_to_string(&nv_tgp_val_path).unwrap();
assert_eq!(val_ac.trim(), "123");
// Now apply for DC
rt.block_on(async {
set_config_or_default(&attrs, &mut cfg, false, profile).await;
});
let val_dc = std::fs::read_to_string(&nv_tgp_val_path).unwrap();
assert_eq!(val_dc.trim(), "45");
}
+1 -4
View File
@@ -6,10 +6,7 @@ After=nvidia-powerd.service systemd-udevd.service
[Service] [Service]
Environment=IS_SERVICE=1 Environment=IS_SERVICE=1
# Reduce noisy span logs while keeping useful debug info for asusd and related crates. Environment=RUST_LOG="debug"
# Keep global level at info but allow debug for our crates; silence tracing::span (very noisy)
# RUST_LOG format: <module>=<level>,... (levels: error,warn,info,debug,trace)
Environment=RUST_LOG="info,asusd=debug,rog_platform=debug,tracing::span=error"
# required to prevent init issues with hid_asus and MCU # required to prevent init issues with hid_asus and MCU
ExecStartPre=/bin/sleep 1 ExecStartPre=/bin/sleep 1
ExecStart=/usr/bin/asusd ExecStart=/usr/bin/asusd
+1 -1
View File
@@ -20,7 +20,7 @@
%global debug_package %{nil} %global debug_package %{nil}
%endif %endif
%define version 6.1.18 %define version 6.1.17
%define specrelease %{?dist} %define specrelease %{?dist}
%define pkg_release 9%{specrelease} %define pkg_release 9%{specrelease}
+1 -19
View File
@@ -44,15 +44,6 @@
advanced_type: r#None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
(
device_name: "FA617XS",
product_id: "",
layout_name: "fx505d",
basic_modes: [Static, Breathe, Pulse],
basic_zones: [],
advanced_type: r#None,
power_zones: [Keyboard],
),
( (
device_name: "FX505", device_name: "FX505",
product_id: "", product_id: "",
@@ -251,15 +242,6 @@
advanced_type: PerKey, advanced_type: PerKey,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
(
device_name: "G614FR",
product_id: "",
layout_name: "g634j-per-key",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
basic_zones: [],
advanced_type: PerKey,
power_zones: [Keyboard, Lightbar, Logo],
),
( (
device_name: "G614J", device_name: "G614J",
product_id: "", product_id: "",
@@ -926,4 +908,4 @@
advanced_type: r#None, advanced_type: r#None,
power_zones: [Ally], power_zones: [Ally],
), ),
]) ])
+23 -1
View File
@@ -164,7 +164,29 @@ impl LedSupportFile {
return Some(data); return Some(data);
} }
warn!("Does {} exist?", ASUS_LED_MODE_USER_CONF); // If the system-wide support files were not available (e.g. running
// tests in CI or a development environment) try to load the
// bundled test data shipped with the crate under `data/aura_support.ron`.
// This allows unit tests to run without requiring files to be installed
// to `/usr/share/asusd`.
let mut bundled = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
bundled.push("data/aura_support.ron");
if let Ok(buf) = std::fs::read_to_string(&bundled) {
if let Ok(mut tmp) = ron::from_str::<LedSupportFile>(&buf) {
data.0.append(&mut tmp.0);
data.0.sort_by(|a, b| a.device_name.cmp(&b.device_name));
info!("Loaded bundled LED support data from {}", bundled.display());
return Some(data);
} else {
warn!(
"Bundled aura_support.ron present but failed to parse: {}",
bundled.display()
);
}
} else {
warn!("Does {} exist?", ASUS_LED_MODE_USER_CONF);
}
None None
} }
} }
+2
View File
@@ -24,4 +24,6 @@ pub struct CliStart {
that might match your laptop" that might match your laptop"
)] )]
pub layout_viewing: bool, pub layout_viewing: bool,
#[options(help = "start in tray mode - main window hidden")]
pub tray_mode: bool,
} }
+83 -5
View File
@@ -140,12 +140,22 @@ async fn main() -> Result<()> {
config.startup_in_background = false; config.startup_in_background = false;
config.start_fullscreen = true; config.start_fullscreen = true;
} }
if cli_parsed.tray_mode {
config.enable_tray_icon = true;
config.run_in_background = true;
config.startup_in_background = true;
}
config.write(); config.write();
let enable_tray_icon = config.enable_tray_icon; let enable_tray_icon = config.enable_tray_icon;
let startup_in_background = config.startup_in_background; let startup_in_background = config.startup_in_background;
let config = Arc::new(Mutex::new(config)); let config = Arc::new(Mutex::new(config));
// shared weak handle to the UI so other threads can request UI updates
let ui_handle: Arc<Mutex<Option<slint::Weak<MainWindow>>>> = Arc::new(Mutex::new(None));
start_notifications(config.clone(), &rt)?; start_notifications(config.clone(), &rt)?;
if enable_tray_icon { if enable_tray_icon {
@@ -170,12 +180,14 @@ async fn main() -> Result<()> {
slint::init_translations!(concat!(env!("CARGO_MANIFEST_DIR"), "/translations/")); slint::init_translations!(concat!(env!("CARGO_MANIFEST_DIR"), "/translations/"));
} }
let config_for_ui = config.clone();
let ui_handle_for_thread = ui_handle.clone();
thread::spawn(move || { thread::spawn(move || {
let mut state = AppState::StartingUp; let mut state = AppState::StartingUp;
loop { loop {
if is_rog_ally { if is_rog_ally {
let config_copy_2 = config.clone(); let config_copy_2 = config_for_ui.clone();
let newui = setup_window(config.clone()); let newui = setup_window(config_for_ui.clone());
newui.window().on_close_requested(move || { newui.window().on_close_requested(move || {
exit(0); exit(0);
}); });
@@ -211,13 +223,19 @@ async fn main() -> Result<()> {
*app_state = AppState::MainWindowOpen; *app_state = AppState::MainWindowOpen;
} }
let config_copy = config.clone(); let config_copy = config_for_ui.clone();
let app_state_copy = app_state.clone(); let app_state_copy = app_state.clone();
let ui_handle_for_ui = ui_handle_for_thread.clone();
slint::invoke_from_event_loop(move || { slint::invoke_from_event_loop(move || {
let ui_handle_for_ui = ui_handle_for_ui.clone();
UI.with(|ui| { UI.with(|ui| {
let app_state_copy = app_state_copy.clone(); let app_state_copy = app_state_copy.clone();
let mut ui = ui.borrow_mut(); let mut ui = ui.borrow_mut();
if let Some(ui) = ui.as_mut() { if let Some(ui) = ui.as_mut() {
// store weak handle so other threads can update UI globals
if let Ok(mut h) = ui_handle_for_ui.lock() {
*h = Some(ui.as_weak());
}
ui.window().show().unwrap(); ui.window().show().unwrap();
ui.window().on_close_requested(move || { ui.window().on_close_requested(move || {
if let Ok(mut app_state) = app_state_copy.lock() { if let Ok(mut app_state) = app_state_copy.lock() {
@@ -228,6 +246,10 @@ async fn main() -> Result<()> {
} else { } else {
let config_copy_2 = config_copy.clone(); let config_copy_2 = config_copy.clone();
let newui = setup_window(config_copy); let newui = setup_window(config_copy);
// store weak handle for the newly created UI
if let Ok(mut h) = ui_handle_for_ui.lock() {
*h = Some(newui.as_weak());
}
newui.window().on_close_requested(move || { newui.window().on_close_requested(move || {
if let Ok(mut app_state) = app_state_copy.lock() { if let Ok(mut app_state) = app_state_copy.lock() {
*app_state = AppState::MainWindowClosed; *app_state = AppState::MainWindowClosed;
@@ -263,8 +285,8 @@ async fn main() -> Result<()> {
slint::quit_event_loop().unwrap(); slint::quit_event_loop().unwrap();
exit(0); exit(0);
} else if state != AppState::MainWindowOpen { } else if state != AppState::MainWindowOpen {
if let Ok(config) = config.lock() { if let Ok(cfg) = config_for_ui.lock() {
if !config.run_in_background { if !cfg.run_in_background {
slint::quit_event_loop().unwrap(); slint::quit_event_loop().unwrap();
exit(0); exit(0);
} }
@@ -274,11 +296,67 @@ async fn main() -> Result<()> {
} }
}); });
// start config watcher to pick up external edits
spawn_config_watcher(config.clone(), ui_handle.clone());
slint::run_event_loop_until_quit().unwrap(); slint::run_event_loop_until_quit().unwrap();
rt.shutdown_background(); rt.shutdown_background();
Ok(()) Ok(())
} }
// Spawn a watcher thread that polls the config file and reloads it when modified.
// This keeps the running rogcc instance in sync with manual edits to the config file.
fn spawn_config_watcher(
config: Arc<Mutex<Config>>,
ui_handle: Arc<Mutex<Option<slint::Weak<MainWindow>>>>,
) {
std::thread::spawn(move || {
use std::time::SystemTime;
let cfg_path = Config::config_dir().join(Config::new().file_name());
let mut last_mtime: Option<SystemTime> = None;
loop {
if let Ok(meta) = std::fs::metadata(&cfg_path) {
if let Ok(m) = meta.modified() {
if last_mtime.is_none() {
last_mtime = Some(m);
} else if last_mtime.is_some_and(|t| t < m) {
// file changed, reload
last_mtime = Some(m);
let new_cfg = Config::new().load();
if let Ok(mut lock) = config.lock() {
*lock = new_cfg.clone();
}
// Update UI app settings globals if UI is present
if let Ok(maybe_weak) = ui_handle.lock() {
if let Some(weak) = maybe_weak.clone() {
let config_for_ui = config.clone();
weak.upgrade_in_event_loop(move |w| {
if let Ok(lock) = config_for_ui.lock() {
let cfg = lock.clone();
w.global::<rog_control_center::AppSettingsPageData>()
.set_run_in_background(cfg.run_in_background);
w.global::<rog_control_center::AppSettingsPageData>()
.set_startup_in_background(cfg.startup_in_background);
w.global::<rog_control_center::AppSettingsPageData>()
.set_enable_tray_icon(cfg.enable_tray_icon);
w.global::<rog_control_center::AppSettingsPageData>()
.set_enable_dgpu_notifications(
cfg.notifications.enabled,
);
}
})
.ok();
}
}
}
}
}
std::thread::sleep(std::time::Duration::from_secs(2));
}
});
}
fn do_cli_help(parsed: &CliStart) -> bool { fn do_cli_help(parsed: &CliStart) -> bool {
if parsed.help { if parsed.help {
println!("{}", CliStart::usage()); println!("{}", CliStart::usage());
+25
View File
@@ -100,6 +100,31 @@ impl Bios {
pub fn set_panel_od(&self, _b: bool) -> Result<()> { pub fn set_panel_od(&self, _b: bool) -> Result<()> {
Ok(()) Ok(())
} }
// Mock NV/dGPU tunables
pub fn nv_dynamic_boost(&self) -> Result<i16> {
Ok(0)
}
pub fn set_nv_dynamic_boost(&self, _v: i16) -> Result<()> {
Ok(())
}
pub fn nv_temp_target(&self) -> Result<i16> {
Ok(0)
}
pub fn set_nv_temp_target(&self, _v: i16) -> Result<()> {
Ok(())
}
pub fn nv_tgp(&self) -> Result<i16> {
Ok(0)
}
pub fn set_nv_tgp(&self, _v: i16) -> Result<()> {
Ok(())
}
} }
pub struct Profile; pub struct Profile;
+71 -10
View File
@@ -130,6 +130,51 @@ macro_rules! init_minmax_property {
// For handling callbacks from UI value changes // For handling callbacks from UI value changes
macro_rules! setup_callback { macro_rules! setup_callback {
// Minmax (AttrMinMax) variant - pass an extra `minmax` token
($property:ident, $handle:expr, $attr:expr, $type:tt, minmax) => {
let handle_copy = $handle.as_weak();
let proxy_copy = $attr.clone();
concat_idents!(on_callback = on_cb_, $property {
$handle
.global::<SystemPageData>()
.on_callback(move |v| {
let handle_copy = handle_copy.clone();
let proxy_copy = proxy_copy.clone();
tokio::spawn(async move {
let res = proxy_copy
.set_current_value(convert_to_dbus!($type, v))
.await;
show_toast(
format!("{} successfully set to {}", stringify!($property), v).into(),
format!("Setting {} failed", stringify!($property)).into(),
handle_copy.clone(),
res.clone(),
);
if res.is_ok() {
let min_v = proxy_copy.min_value().await.unwrap_or(-1);
let max_v = proxy_copy.max_value().await.unwrap_or(-1);
if let Ok(cur_val) = proxy_copy.current_value().await {
let cur_f = cur_val as f32;
handle_copy
.upgrade_in_event_loop(move |handle| {
concat_idents!(setter = set_, $property {
handle.global::<SystemPageData>().setter(AttrMinMax {
min: min_v,
max: max_v,
current: cur_f,
});
});
})
.ok();
}
}
});
});
});
};
// Scalar variant (i32/bool/f32) - update scalar setter with authoritative value
($property:ident, $handle:expr, $attr:expr, $type:tt) => { ($property:ident, $handle:expr, $attr:expr, $type:tt) => {
let handle_copy = $handle.as_weak(); let handle_copy = $handle.as_weak();
let proxy_copy = $attr.clone(); let proxy_copy = $attr.clone();
@@ -140,12 +185,28 @@ macro_rules! setup_callback {
let handle_copy = handle_copy.clone(); let handle_copy = handle_copy.clone();
let proxy_copy = proxy_copy.clone(); let proxy_copy = proxy_copy.clone();
tokio::spawn(async move { tokio::spawn(async move {
let res = proxy_copy
.set_current_value(convert_to_dbus!($type, v))
.await;
show_toast( show_toast(
format!("{} successfully set to {}", stringify!($property), v).into(), format!("{} successfully set to {}", stringify!($property), v).into(),
format!("Setting {} failed", stringify!($property)).into(), format!("Setting {} failed", stringify!($property)).into(),
handle_copy, handle_copy.clone(),
proxy_copy.set_current_value(convert_to_dbus!($type, v)).await, res.clone(),
); );
if res.is_ok() {
// Query authoritative value and set scalar global
if let Ok(cur_val) = proxy_copy.current_value().await {
handle_copy.upgrade_in_event_loop(move |handle| {
concat_idents!(setter = set_, $property {
handle
.global::<SystemPageData>()
.setter(convert_value!($type, cur_val));
});
}).ok();
}
}
}); });
}); });
}); });
@@ -615,49 +676,49 @@ pub fn setup_system_page_callbacks(ui: &MainWindow, _states: Arc<Mutex<Config>>)
} }
FirmwareAttribute::PptPl1Spl => { FirmwareAttribute::PptPl1Spl => {
init_minmax_property!(ppt_pl1_spl, handle, attr); init_minmax_property!(ppt_pl1_spl, handle, attr);
setup_callback!(ppt_pl1_spl, handle, attr, i32); setup_callback!(ppt_pl1_spl, handle, attr, i32, minmax);
setup_callback_restore_default!(ppt_pl1_spl, handle, attr); setup_callback_restore_default!(ppt_pl1_spl, handle, attr);
setup_minmax_external!(ppt_pl1_spl, handle, attr, platform); setup_minmax_external!(ppt_pl1_spl, handle, attr, platform);
} }
FirmwareAttribute::PptPl2Sppt => { FirmwareAttribute::PptPl2Sppt => {
init_minmax_property!(ppt_pl2_sppt, handle, attr); init_minmax_property!(ppt_pl2_sppt, handle, attr);
setup_callback!(ppt_pl2_sppt, handle, attr, i32); setup_callback!(ppt_pl2_sppt, handle, attr, i32, minmax);
setup_callback_restore_default!(ppt_pl2_sppt, handle, attr); setup_callback_restore_default!(ppt_pl2_sppt, handle, attr);
setup_minmax_external!(ppt_pl2_sppt, handle, attr, platform); setup_minmax_external!(ppt_pl2_sppt, handle, attr, platform);
} }
FirmwareAttribute::PptPl3Fppt => { FirmwareAttribute::PptPl3Fppt => {
init_minmax_property!(ppt_pl3_fppt, handle, attr); init_minmax_property!(ppt_pl3_fppt, handle, attr);
setup_callback!(ppt_pl3_fppt, handle, attr, i32); setup_callback!(ppt_pl3_fppt, handle, attr, i32, minmax);
setup_callback_restore_default!(ppt_pl3_fppt, handle, attr); setup_callback_restore_default!(ppt_pl3_fppt, handle, attr);
setup_minmax_external!(ppt_pl3_fppt, handle, attr, platform); setup_minmax_external!(ppt_pl3_fppt, handle, attr, platform);
} }
FirmwareAttribute::PptFppt => { FirmwareAttribute::PptFppt => {
init_minmax_property!(ppt_fppt, handle, attr); init_minmax_property!(ppt_fppt, handle, attr);
setup_callback!(ppt_fppt, handle, attr, i32); setup_callback!(ppt_fppt, handle, attr, i32, minmax);
setup_callback_restore_default!(ppt_fppt, handle, attr); setup_callback_restore_default!(ppt_fppt, handle, attr);
setup_minmax_external!(ppt_fppt, handle, attr, platform); setup_minmax_external!(ppt_fppt, handle, attr, platform);
} }
FirmwareAttribute::PptApuSppt => { FirmwareAttribute::PptApuSppt => {
init_minmax_property!(ppt_apu_sppt, handle, attr); init_minmax_property!(ppt_apu_sppt, handle, attr);
setup_callback!(ppt_apu_sppt, handle, attr, i32); setup_callback!(ppt_apu_sppt, handle, attr, i32, minmax);
setup_callback_restore_default!(ppt_apu_sppt, handle, attr); setup_callback_restore_default!(ppt_apu_sppt, handle, attr);
setup_minmax_external!(ppt_apu_sppt, handle, attr, platform); setup_minmax_external!(ppt_apu_sppt, handle, attr, platform);
} }
FirmwareAttribute::PptPlatformSppt => { FirmwareAttribute::PptPlatformSppt => {
init_minmax_property!(ppt_platform_sppt, handle, attr); init_minmax_property!(ppt_platform_sppt, handle, attr);
setup_callback!(ppt_platform_sppt, handle, attr, i32); setup_callback!(ppt_platform_sppt, handle, attr, i32, minmax);
setup_callback_restore_default!(ppt_platform_sppt, handle, attr); setup_callback_restore_default!(ppt_platform_sppt, handle, attr);
setup_minmax_external!(ppt_platform_sppt, handle, attr, platform); setup_minmax_external!(ppt_platform_sppt, handle, attr, platform);
} }
FirmwareAttribute::NvDynamicBoost => { FirmwareAttribute::NvDynamicBoost => {
init_minmax_property!(nv_dynamic_boost, handle, attr); init_minmax_property!(nv_dynamic_boost, handle, attr);
setup_callback!(nv_dynamic_boost, handle, attr, i32); setup_callback!(nv_dynamic_boost, handle, attr, i32, minmax);
setup_callback_restore_default!(nv_dynamic_boost, handle, attr); setup_callback_restore_default!(nv_dynamic_boost, handle, attr);
setup_minmax_external!(nv_dynamic_boost, handle, attr, platform); setup_minmax_external!(nv_dynamic_boost, handle, attr, platform);
} }
FirmwareAttribute::NvTempTarget => { FirmwareAttribute::NvTempTarget => {
init_minmax_property!(nv_temp_target, handle, attr); init_minmax_property!(nv_temp_target, handle, attr);
setup_callback!(nv_temp_target, handle, attr, i32); setup_callback!(nv_temp_target, handle, attr, i32, minmax);
setup_callback_restore_default!(nv_temp_target, handle, attr); setup_callback_restore_default!(nv_temp_target, handle, attr);
setup_minmax_external!(nv_temp_target, handle, attr, platform); setup_minmax_external!(nv_temp_target, handle, attr, platform);
} }
+66 -5
View File
@@ -95,7 +95,7 @@ impl Attribute {
_ => return Err(PlatformError::InvalidValue), _ => return Err(PlatformError::InvalidValue),
}; };
let mut file = OpenOptions::new().write(true).open(&path)?; let mut file = OpenOptions::new().write(true).truncate(true).open(&path)?;
file.write_all(value_str.as_bytes())?; file.write_all(value_str.as_bytes())?;
Ok(()) Ok(())
} }
@@ -244,6 +244,37 @@ impl FirmwareAttributes {
Self { attrs } Self { attrs }
} }
/// Create attributes collection from an arbitrary base directory. Intended for tests
/// where a fake sysfs-like layout can be supplied.
pub fn from_dir(base_dir: &std::path::Path) -> Self {
let mut attrs = Vec::new();
if let Ok(dir) = read_dir(base_dir) {
for entry in dir.flatten() {
let base_path = entry.path();
let name = base_path.file_name().unwrap().to_string_lossy().to_string();
if name == "pending_reboot" {
continue;
}
let help = read_string(&base_path.join("display_name")).unwrap_or_default();
let (default_value, possible_values, min_value, max_value, scalar_increment) =
Attribute::read_base_values(&base_path);
attrs.push(Attribute {
name,
help,
default_value,
possible_values,
min_value,
max_value,
scalar_increment,
base_path,
});
}
}
Self { attrs }
}
pub fn attributes(&self) -> &Vec<Attribute> { pub fn attributes(&self) -> &Vec<Attribute> {
&self.attrs &self.attrs
} }
@@ -282,8 +313,8 @@ define_attribute_getters!(
ppt_fppt, ppt_fppt,
nv_dynamic_boost, nv_dynamic_boost,
nv_temp_target, nv_temp_target,
dgpu_base_tgp, nv_base_tgp,
dgpu_tgp, nv_tgp,
charge_mode, charge_mode,
boot_sound, boot_sound,
mcu_powersave, mcu_powersave,
@@ -300,6 +331,7 @@ define_attribute_getters!(
/// CamelCase names of the properties. Intended for use with DBUS /// CamelCase names of the properties. Intended for use with DBUS
#[repr(u8)] #[repr(u8)]
#[derive( #[derive(
Debug,
Clone, Clone,
Copy, Copy,
Serialize, Serialize,
@@ -362,6 +394,7 @@ impl FirmwareAttribute {
self, self,
FirmwareAttribute::NvDynamicBoost FirmwareAttribute::NvDynamicBoost
| FirmwareAttribute::NvTempTarget | FirmwareAttribute::NvTempTarget
| FirmwareAttribute::DgpuBaseTgp
| FirmwareAttribute::DgpuTgp | FirmwareAttribute::DgpuTgp
) )
} }
@@ -382,8 +415,11 @@ impl From<&str> for FirmwareAttribute {
"ppt_platform_sppt" => Self::PptPlatformSppt, "ppt_platform_sppt" => Self::PptPlatformSppt,
"nv_dynamic_boost" => Self::NvDynamicBoost, "nv_dynamic_boost" => Self::NvDynamicBoost,
"nv_temp_target" => Self::NvTempTarget, "nv_temp_target" => Self::NvTempTarget,
"nv_tgp" => Self::DgpuTgp,
"nv_base_tgp" => Self::DgpuBaseTgp, "nv_base_tgp" => Self::DgpuBaseTgp,
/* Backwards compatibility: some kernels expose these attributes with a dgpu_* prefix */
"dgpu_tgp" => Self::DgpuTgp, "dgpu_tgp" => Self::DgpuTgp,
"dgpu_base_tgp" => Self::DgpuBaseTgp,
"charge_mode" => Self::ChargeMode, "charge_mode" => Self::ChargeMode,
"boot_sound" => Self::BootSound, "boot_sound" => Self::BootSound,
"mcu_powersave" => Self::McuPowersave, "mcu_powersave" => Self::McuPowersave,
@@ -419,8 +455,8 @@ impl From<FirmwareAttribute> for &str {
FirmwareAttribute::PptPlatformSppt => "ppt_platform_sppt", FirmwareAttribute::PptPlatformSppt => "ppt_platform_sppt",
FirmwareAttribute::NvDynamicBoost => "nv_dynamic_boost", FirmwareAttribute::NvDynamicBoost => "nv_dynamic_boost",
FirmwareAttribute::NvTempTarget => "nv_temp_target", FirmwareAttribute::NvTempTarget => "nv_temp_target",
FirmwareAttribute::DgpuBaseTgp => "dgpu_base_tgp", FirmwareAttribute::DgpuBaseTgp => "nv_base_tgp",
FirmwareAttribute::DgpuTgp => "dgpu_tgp", FirmwareAttribute::DgpuTgp => "nv_tgp",
FirmwareAttribute::ChargeMode => "charge_mode", FirmwareAttribute::ChargeMode => "charge_mode",
FirmwareAttribute::BootSound => "boot_sound", FirmwareAttribute::BootSound => "boot_sound",
FirmwareAttribute::McuPowersave => "mcu_powersave", FirmwareAttribute::McuPowersave => "mcu_powersave",
@@ -519,3 +555,28 @@ mod tests {
attr.set_current_value(&val).unwrap(); attr.set_current_value(&val).unwrap();
} }
} }
#[cfg(test)]
mod alias_tests {
use super::FirmwareAttribute;
#[test]
fn tgp_aliases_map_to_same_variant() {
let nv = FirmwareAttribute::from("nv_tgp");
let dgpu = FirmwareAttribute::from("dgpu_tgp");
assert_eq!(nv, dgpu);
let nv_base = FirmwareAttribute::from("nv_base_tgp");
let dgpu_base = FirmwareAttribute::from("dgpu_base_tgp");
assert_eq!(nv_base, dgpu_base);
}
#[test]
fn tgp_canonical_output_is_nv_tgp() {
let s: &str = FirmwareAttribute::DgpuTgp.into();
assert_eq!(s, "nv_tgp");
let s_base: &str = FirmwareAttribute::DgpuBaseTgp.into();
assert_eq!(s_base, "nv_base_tgp");
}
}
+13 -10
View File
@@ -101,15 +101,18 @@ impl AsusPower {
}); });
} }
// No battery found. Return an AsusPower with an empty battery path so Err(PlatformError::MissingFunction(
// callers can still be constructed and query `has_*` methods which "Did not find a battery".to_owned(),
// will correctly report absence. This avoids hard-failing on systems ))
// where the asus-nb-wmi driver loads on desktops with no battery. }
info!("Did not find a battery, continuing without battery support"); }
Ok(Self {
mains, impl Default for AsusPower {
battery: PathBuf::new(), fn default() -> Self {
usb, Self {
}) mains: PathBuf::from("/this_shouldNeVErr_exisid"),
battery: PathBuf::from("/this_shouldNeVErr_exisid"),
usb: None,
}
} }
} }
+4
View File
@@ -0,0 +1,4 @@
[toolchain]
channel = "stable"
components = ["rustfmt", "clippy"]
profile = "minimal"
+4 -4
View File
@@ -157,14 +157,14 @@ fn main() -> Result<(), Box<dyn Error>> {
for (x_count, b) in dev.buffer[start..=end].iter().enumerate() { for (x_count, b) in dev.buffer[start..=end].iter().enumerate() {
canvas.set_draw_color(Color::RGB(*b, *b, *b)); canvas.set_draw_color(Color::RGB(*b, *b, *b));
#[allow(clippy::manual_is_multiple_of)] let x: i32 = w + x_count as i32 * w - {
let x: i32 = w + x_count as i32 * w #[allow(clippy::manual_is_multiple_of)]
- if (y_count + y_offset as usize) % 2 != 0 { if (y_count + y_offset as usize) % 2 != 0 {
0 0
} else { } else {
w / 2 w / 2
} }
+ row.3 * w; } + row.3 * w;
let y = y_count as i32 * h - y_offset * h; let y = y_count as i32 * h - y_offset * h;
canvas canvas
.fill_rect(Rect::new(x, y, w as u32, h as u32)) .fill_rect(Rect::new(x, y, w as u32, h as u32))