mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 38d047cb8a | |||
| 1d977199f3 | |||
| 5041019d77 | |||
| aa3835d3b3 | |||
| 678505811d | |||
| a925cbaed5 | |||
| 7d2201d873 | |||
| c0c1608d44 | |||
| 7bc6c83a04 | |||
| 3f0df82f2d | |||
| 328ff0251b | |||
| c52582a413 | |||
| 3aa6eee306 | |||
| 7d47faba0e | |||
| f6fb477898 | |||
| 8963960d4b | |||
| ef973f676b | |||
| 812f9ea30e | |||
| ff843b1241 | |||
| 59e7af149d | |||
| 6f14c85287 | |||
| ac0dec4dbf | |||
| e3d192412e | |||
| 9fadb6db30 | |||
| f8a1b71866 | |||
| c0a55acba7 | |||
| 4f232de634 | |||
| d351ebdaa0 | |||
| ab195e1d84 |
@@ -6,6 +6,44 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
# [4.0.6] - 2021-11-01
|
||||
### Changed
|
||||
- Fix CLI for bios toggles
|
||||
### Added
|
||||
- Extra commands for AniMe: pixel-image, gif, pixel-gif
|
||||
|
||||
# [4.0.5] - 2021-10-27
|
||||
### Changed
|
||||
- Convert fan curve percentage to 0-255 expected by kernel driver only if '%' char is used, otherwise the expected range for fan power is 0-255
|
||||
- Use correct error in daemon for invalid charging limit
|
||||
- Enforce charging limit values in range 20-100
|
||||
### Added
|
||||
- LED modes for G513QR
|
||||
|
||||
# [4.0.4] - 2021-10-02
|
||||
### Changed
|
||||
- Add missing Profile commands
|
||||
- Spawn tasks on individual threads to prevent blocking
|
||||
- Don't force fan-curve default on reload
|
||||
- Begin obsoleting the graphics switch command in favour of supergfxctl
|
||||
- Slim down the notification daemon to pure ASUS notifications
|
||||
|
||||
# [4.0.3] - 2021-09-16
|
||||
### Changed
|
||||
- Don't show fan-curve warning if fan-curve available
|
||||
- Add G713QR to Strix led-modes
|
||||
- Fix part of CLI fan-curve control
|
||||
|
||||
# [4.0.2] - 2021-09-14
|
||||
### Changed
|
||||
- Backup old configs to *-old if parse fails
|
||||
- Prevent some types of crashes related to unpatched kernels
|
||||
- Add better help for graphics errors
|
||||
- Add better help for asusctl general errors
|
||||
- Implement fan-curve dbus API
|
||||
- Implement partial fan-curve control via CLI tool
|
||||
+ Set fan curve for profile + fan gpu/cpu
|
||||
|
||||
# [4.0.1] - 2021-09-11
|
||||
### Changed
|
||||
- Fix asusd-ledmodes.toml
|
||||
|
||||
Generated
+188
-188
@@ -39,13 +39,12 @@ dependencies = [
|
||||
"rog_profiles",
|
||||
"rog_supported",
|
||||
"serde_json",
|
||||
"supergfxctl",
|
||||
"zbus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "asusctl"
|
||||
version = "4.0.0"
|
||||
version = "4.0.6"
|
||||
dependencies = [
|
||||
"daemon",
|
||||
"gif",
|
||||
@@ -56,9 +55,9 @@ dependencies = [
|
||||
"rog_dbus",
|
||||
"rog_profiles",
|
||||
"rog_supported",
|
||||
"supergfxctl",
|
||||
"sysfs-class",
|
||||
"tinybmp",
|
||||
"toml",
|
||||
"zbus",
|
||||
]
|
||||
|
||||
@@ -106,15 +105,9 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "0.9.1"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
|
||||
[[package]]
|
||||
name = "blake2b_simd"
|
||||
@@ -147,15 +140,9 @@ checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.69"
|
||||
version = "1.0.71"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
@@ -191,6 +178,12 @@ dependencies = [
|
||||
"cache-padded",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const-sha1"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb58b6451e8c2a812ad979ed1d83378caa5e927eef2622017a45f251457c2c9d"
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.1.5"
|
||||
@@ -203,13 +196,13 @@ version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "daemon"
|
||||
version = "4.0.1"
|
||||
version = "4.0.6"
|
||||
dependencies = [
|
||||
"env_logger",
|
||||
"log",
|
||||
@@ -254,8 +247,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.75",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -306,8 +299,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "946ee94e3dbf58fdd324f9ce245c7b238d46a66f00e86a020b71996349e46cce"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.75",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -334,9 +327,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.16"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1adc00f486adfc9ce99f77d717836f0c5aa84965eb0b4f051f4e83f7cab53f8b"
|
||||
checksum = "a12aa0eb539080d55c3f2d45a67c3b58b6b0773c1a3ca2dfec66d58c97fd66ca"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
@@ -349,9 +342,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.16"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74ed2411805f6e4e3d9bc904c95d5d423b89b3b25dc0250aa74729de20629ff9"
|
||||
checksum = "5da6ba8c3bb3c165d3c7319fc1cc8304facf1fb8db99c5de877183c08a273888"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
@@ -359,15 +352,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.16"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af51b1b4a7fdff033703db39de8802c673eb91855f2e0d47dcf3bf2c0ef01f99"
|
||||
checksum = "88d1c26957f23603395cd326b0ffe64124b818f4449552f960d815cfba83a53d"
|
||||
|
||||
[[package]]
|
||||
name = "futures-executor"
|
||||
version = "0.3.16"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4d0d535a57b87e1ae31437b892713aee90cd2d7b0ee48727cd11fc72ef54761c"
|
||||
checksum = "45025be030969d763025784f7f355043dc6bc74093e4ecc5000ca4dc50d8745c"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-task",
|
||||
@@ -376,9 +369,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "futures-io"
|
||||
version = "0.3.16"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b0e06c393068f3a6ef246c75cdca793d6a46347e75286933e5e75fd2fd11582"
|
||||
checksum = "522de2a0fe3e380f1bc577ba0474108faf3f6b18321dbf60b3b9c39a75073377"
|
||||
|
||||
[[package]]
|
||||
name = "futures-lite"
|
||||
@@ -397,34 +390,34 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "futures-macro"
|
||||
version = "0.3.16"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c54913bae956fb8df7f4dc6fc90362aa72e69148e3f39041fbe8742d21e0ac57"
|
||||
checksum = "18e4a4b95cea4b4ccbcf1c5675ca7c4ee4e9e75eb79944d07defde18068f79bb"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"proc-macro-hack",
|
||||
"proc-macro2",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.75",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-sink"
|
||||
version = "0.3.16"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0f30aaa67363d119812743aa5f33c201a7a66329f97d1a887022971feea4b53"
|
||||
checksum = "36ea153c13024fe480590b3e3d4cad89a0cfacecc24577b68f86c6ced9c2bc11"
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.16"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbe54a98670017f3be909561f6ad13e810d9a51f3f061b902062ca3da80799f2"
|
||||
checksum = "1d3d00f4eddb73e498a54394f228cd55853bdf059259e8e7bc6e69d408892e99"
|
||||
|
||||
[[package]]
|
||||
name = "futures-util"
|
||||
version = "0.3.16"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67eb846bfd58e44a8481a00049e82c43e0ccb5d61f8dc071057cb19249dd4d78"
|
||||
checksum = "36568465210a3a6ee45e1f165136d68671471a501e632e9a98d96872222b5481"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"futures-channel",
|
||||
@@ -447,7 +440,7 @@ version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi 0.9.0+wasi-snapshot-preview1",
|
||||
]
|
||||
@@ -458,16 +451,16 @@ version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi 0.10.2+wasi-snapshot-preview1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gif"
|
||||
version = "0.11.2"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a668f699973d0f573d15749b7002a9ac9e1f9c6b220e7b165601334c173d8de"
|
||||
checksum = "c3a7187e78088aead22ceedeee99779455b23fc231fe13ec443f99bb71694e5b"
|
||||
dependencies = [
|
||||
"color_quant",
|
||||
"weezl",
|
||||
@@ -498,8 +491,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "915ef07c710d84733522461de2a734d4d62a3fd39a4d4f404c2f385ef8618d05"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.75",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
|
||||
dependencies = [
|
||||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -519,11 +521,11 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.10"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bee0328b1209d157ef001c94dd85b4f8f64139adb0eac2659f4b08382b2f474d"
|
||||
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -540,9 +542,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.101"
|
||||
version = "0.2.105"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3cb00336871be5ed2c8ed44b60ae9959dc5b9f08539422ed43f09e34ecaeba21"
|
||||
checksum = "869d572136620d55835903746bcb5cdc54cb2851fd0aeec53220b4bb65ef3013"
|
||||
|
||||
[[package]]
|
||||
name = "libudev-sys"
|
||||
@@ -572,7 +574,7 @@ version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -616,6 +618,15 @@ version = "2.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.4.4"
|
||||
@@ -638,15 +649,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.17.0"
|
||||
version = "0.20.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363"
|
||||
checksum = "f5e06129fb611568ef4e868c14b326274959aa70ff7776e9d55323531c374945"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"bitflags",
|
||||
"cc",
|
||||
"cfg-if 0.1.10",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"void",
|
||||
"memoffset",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -661,9 +672,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "notify-rust"
|
||||
version = "4.5.2"
|
||||
version = "4.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a2ca742cd7268b60c35828d318357f0b1bb9b82088e157ccf3013eb3ce70247"
|
||||
checksum = "825e9c9efdcb4d14920f72e2ef329b4dae0219791834c000c42c1475dad341f8"
|
||||
dependencies = [
|
||||
"mac-notification-sys",
|
||||
"serde",
|
||||
@@ -759,9 +770,9 @@ checksum = "bea9d5c668f13b4a1b97d848780e00cfabf76eb83538129c264c0c6d6a968047"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.19"
|
||||
version = "0.3.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
|
||||
checksum = "12295df4f294471248581bc09bef3c38a5e46f1e36d6a37353621a0c6c357e1f"
|
||||
|
||||
[[package]]
|
||||
name = "png_pong"
|
||||
@@ -779,7 +790,7 @@ version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92341d779fa34ea8437ef4d82d440d5e1ce3f3ff7f824aa64424cd481f9a1f25"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"log",
|
||||
"wepoll-ffi",
|
||||
@@ -797,9 +808,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-crate"
|
||||
version = "1.0.0"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41fdbd1df62156fbc5945f4762632564d7d038153091c3fcf1067f6aef7cff92"
|
||||
checksum = "1ebace6889caf889b4d3f76becee12e90353f2b8c7d875534a71e5742f8f6f83"
|
||||
dependencies = [
|
||||
"thiserror",
|
||||
"toml",
|
||||
@@ -819,24 +830,18 @@ checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.28"
|
||||
version = "1.0.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612"
|
||||
checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43"
|
||||
dependencies = [
|
||||
"unicode-xid 0.2.2",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.3.15"
|
||||
version = "1.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
|
||||
checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
@@ -853,7 +858,7 @@ version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -896,7 +901,7 @@ checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
|
||||
|
||||
[[package]]
|
||||
name = "rog_anime"
|
||||
version = "1.1.0"
|
||||
version = "1.3.0"
|
||||
dependencies = [
|
||||
"gif",
|
||||
"glam",
|
||||
@@ -920,13 +925,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rog_dbus"
|
||||
version = "4.0.0"
|
||||
version = "4.0.2"
|
||||
dependencies = [
|
||||
"rog_anime",
|
||||
"rog_aura",
|
||||
"rog_profiles",
|
||||
"rog_supported",
|
||||
"supergfxctl",
|
||||
"zbus",
|
||||
"zbus_macros",
|
||||
"zvariant",
|
||||
@@ -934,7 +938,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rog_profiles"
|
||||
version = "1.0.1"
|
||||
version = "1.1.3"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_derive",
|
||||
@@ -990,29 +994,29 @@ checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.129"
|
||||
version = "1.0.130"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d1f72836d2aa753853178eda473a3b9d8e4eefdaf20523b919677e6de489f8f1"
|
||||
checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.129"
|
||||
version = "1.0.130"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e57ae87ad533d9a56427558b516d0adac283614e347abf85b0dc0cbbf0a249f3"
|
||||
checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.75",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.66"
|
||||
version = "1.0.68"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "336b10da19a12ad094b59d870ebde26a45402e5b470add4b5fd03c5048a32127"
|
||||
checksum = "0f690853975602e1bfe1ccbf50504d67174e3bcf340f23b5ea9992e0587a52d8"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
@@ -1026,21 +1030,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "98d0516900518c29efa217c298fa1f4e6c6ffc85ae29fd7f4ee48f176e1a9ed5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.75",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.4"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c307a32c1c5c437f38c7fd45d753050587732ba8628319fbdf12a7e289ccc590"
|
||||
checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5"
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.4.1"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "765f090f0e423d2b55843402a07915add955e7d60657db13707a159727326cad"
|
||||
checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
@@ -1054,65 +1058,34 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "strum"
|
||||
version = "0.8.0"
|
||||
version = "0.21.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ca6e4730f517e041e547ffe23d29daab8de6b73af4b6ae2a002108169f5e7da"
|
||||
checksum = "aaf86bbcfd1fa9670b7a129f64fc0c9fcbbfe4f1bc4210e9e98fe71ffc12cde2"
|
||||
dependencies = [
|
||||
"strum_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strum_macros"
|
||||
version = "0.8.0"
|
||||
version = "0.21.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3384590878eb0cab3b128e844412e2d010821e7e091211b9d87324173ada7db8"
|
||||
checksum = "d06aaeeee809dbc59eb4556183dd927df67db1540de5be8d3ec0b6636358a5ec"
|
||||
dependencies = [
|
||||
"quote 0.3.15",
|
||||
"syn 0.11.11",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "supergfxctl"
|
||||
version = "2.0.0"
|
||||
source = "git+https://gitlab.com/asus-linux/supergfxctl.git?tag=2.0.0#3f040cd3ec334242631122cd038aa361cc860be6"
|
||||
dependencies = [
|
||||
"log",
|
||||
"logind-zbus",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"sysfs-class",
|
||||
"zbus",
|
||||
"zvariant",
|
||||
"zvariant_derive",
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "0.11.11"
|
||||
version = "1.0.81"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
|
||||
dependencies = [
|
||||
"quote 0.3.15",
|
||||
"synom",
|
||||
"unicode-xid 0.0.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.75"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7f58f7e8eaa0009c5fec437aabf511bd9933e4b2d7407bd05273c01a8906ea7"
|
||||
checksum = "f2afee18b8beb5a596ecb4a2dce128c719b4ba399d34126b9e4396e3f9860966"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.9",
|
||||
"unicode-xid 0.2.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synom"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
|
||||
dependencies = [
|
||||
"unicode-xid 0.0.4",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1135,22 +1108,22 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.26"
|
||||
version = "1.0.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93119e4feac1cbe6c798c34d3a53ea0026b0b1de6a120deef895137c0529bfe2"
|
||||
checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.26"
|
||||
version = "1.0.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "060d69a0afe7796bf42e9e2ff91f5ee691fb15c53d38b4b62a9a53eb23164745"
|
||||
checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.75",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1193,10 +1166,10 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.0.4"
|
||||
name = "unicode-segmentation"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
|
||||
checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
@@ -1216,12 +1189,6 @@ version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
|
||||
|
||||
[[package]]
|
||||
name = "void"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||
|
||||
[[package]]
|
||||
name = "waker-fn"
|
||||
version = "1.1.0"
|
||||
@@ -1287,41 +1254,73 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "winrt"
|
||||
version = "0.4.0"
|
||||
name = "windows"
|
||||
version = "0.21.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7e30cba82e22b083dc5a422c2ee77e20dc7927271a0dc981360c57c1453cb48d"
|
||||
checksum = "b8f5f8d2ea79bf690bbee453fd4a1516ae426e5d5c7215d96cc0c3dc134fc4a0"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
"const-sha1",
|
||||
"windows_gen",
|
||||
"windows_macros",
|
||||
"windows_reader",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winrt-notification"
|
||||
version = "0.2.4"
|
||||
name = "windows_gen"
|
||||
version = "0.21.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57790eb281688a4682dab44df2a1ba8b78373233bd71cb291c3e75fecb1a01c4"
|
||||
checksum = "7e6994f42f8481387778cc608407d6703410672d57f32a66009419d7a18aa912"
|
||||
dependencies = [
|
||||
"windows_quote",
|
||||
"windows_reader",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_macros"
|
||||
version = "0.21.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81cc2357b1b03c19f056cb0e6d06011f80f54beadb4e36aee2ca98493c7cfc3c"
|
||||
dependencies = [
|
||||
"syn",
|
||||
"windows_gen",
|
||||
"windows_quote",
|
||||
"windows_reader",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_quote"
|
||||
version = "0.21.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7cf987b5288c15e1997226848f78f3ed3ef8b78dcfd71a201c8c8684163a7e4d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_reader"
|
||||
version = "0.21.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "237b53e8b40766ea7db5da0d8c6c1442d21d0429f0ee7500d7b5688967bd9d7b"
|
||||
|
||||
[[package]]
|
||||
name = "winrt-notification"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0cc832b8c66c42b3ee6b625c124fe2d0b3ff7fb2cec18b28926e9c4bfdb72da"
|
||||
dependencies = [
|
||||
"strum",
|
||||
"strum_macros",
|
||||
"winapi",
|
||||
"winrt",
|
||||
"windows",
|
||||
"xml-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xml-rs"
|
||||
version = "0.6.1"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1945e12e16b951721d7976520b0832496ef79c31602c7a29d950de79ba74621"
|
||||
dependencies = [
|
||||
"bitflags 0.9.1",
|
||||
]
|
||||
checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3"
|
||||
|
||||
[[package]]
|
||||
name = "zbus"
|
||||
version = "1.9.1"
|
||||
version = "1.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2326acc379a3ac4e34b794089f5bdb17086bf29a5fdf619b7b4cc772dc2e9dad"
|
||||
checksum = "e5983c3d035549ab80db67c844ec83ed271f7c1f2546fd9577c594d34c1b6c85"
|
||||
dependencies = [
|
||||
"async-io",
|
||||
"byteorder",
|
||||
@@ -1342,24 +1341,25 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zbus_macros"
|
||||
version = "1.9.1"
|
||||
version = "1.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a482c56029e48681b89b92b5db3c446db0915e8dd1052c0328a574eda38d5f93"
|
||||
checksum = "bce54ac7b2150a2fa21ad5842a7470ce2288158d7da1f9bfda8ad455a1c59a97"
|
||||
dependencies = [
|
||||
"proc-macro-crate 0.1.5",
|
||||
"proc-macro2",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.75",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zvariant"
|
||||
version = "2.8.0"
|
||||
version = "2.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa4b785b8b32b0f8433b4474e6bb4ea77b37c1960e84d7598e01dd199b2b23ef"
|
||||
checksum = "e1a9373dead84d640ccf5798f2928917e6aa1ab3f130751406bb13e0a9dd9913"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"enumflags2",
|
||||
"libc",
|
||||
"serde",
|
||||
"static_assertions",
|
||||
"zvariant_derive",
|
||||
@@ -1367,12 +1367,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zvariant_derive"
|
||||
version = "2.8.0"
|
||||
version = "2.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b42af4ee88fb928781391216c34be77ec7cdb3546042b2947ce38d86aa5f37dd"
|
||||
checksum = "46ee71e0e88747ec582d290dbe98ff7907ff28770c7a35f16da41e5e6f1f4fa3"
|
||||
dependencies = [
|
||||
"proc-macro-crate 1.0.0",
|
||||
"proc-macro-crate 1.1.0",
|
||||
"proc-macro2",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.75",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
@@ -63,7 +63,7 @@ will probably suffer another rename once it becomes generic enough to do so.
|
||||
|
||||
Requirements are rust >= 1.47 installed from rustup.io if the distro provided version is too old, and `make`.
|
||||
|
||||
**Ubuntu*:** `apt install libclang-dev libudev-dev`
|
||||
**Ubuntu:** `apt install libclang-dev libudev-dev`
|
||||
|
||||
**fedora:** `dnf install clang-devel systemd-devel`
|
||||
|
||||
|
||||
@@ -14,9 +14,8 @@ rog_dbus = { path = "../rog-dbus" }
|
||||
rog_aura = { path = "../rog-aura" }
|
||||
rog_supported = { path = "../rog-supported" }
|
||||
rog_profiles = { path = "../rog-profiles" }
|
||||
supergfxctl = { git = "https://gitlab.com/asus-linux/supergfxctl.git", tag = "2.0.0" }
|
||||
|
||||
[dependencies.notify-rust]
|
||||
version = "^4.3"
|
||||
default-features = false
|
||||
features = ["z"]
|
||||
features = ["z"]
|
||||
|
||||
@@ -3,13 +3,8 @@ use rog_aura::AuraEffect;
|
||||
use rog_dbus::{DbusProxies, Signals};
|
||||
use rog_profiles::Profile;
|
||||
use std::error::Error;
|
||||
use std::sync::mpsc::channel;
|
||||
use std::thread::sleep;
|
||||
use std::time::Duration;
|
||||
use std::{process, thread};
|
||||
use supergfxctl::gfx_vendors::{GfxRequiredUserAction, GfxVendors};
|
||||
use supergfxctl::zbus_proxy::GfxProxy;
|
||||
use zbus::Connection;
|
||||
|
||||
const NOTIF_HEADER: &str = "ROG Control";
|
||||
|
||||
@@ -37,7 +32,6 @@ macro_rules! base_notification {
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("asus-notify version {}", env!("CARGO_PKG_VERSION"));
|
||||
println!(" rog-dbus version {}", rog_dbus::VERSION);
|
||||
println!("supergfxctl version {}", supergfxctl::VERSION);
|
||||
|
||||
let (proxies, conn) = DbusProxies::new()?;
|
||||
let signals = Signals::new(&proxies)?;
|
||||
@@ -47,8 +41,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let recv = proxies.setup_recv(conn);
|
||||
let mut err_count = 0;
|
||||
|
||||
gfx_thread()?;
|
||||
|
||||
loop {
|
||||
sleep(Duration::from_millis(100));
|
||||
if let Err(err) = recv.next_signal() {
|
||||
@@ -77,56 +69,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
}
|
||||
}
|
||||
|
||||
fn gfx_thread() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut last_notification: Option<NotificationHandle> = None;
|
||||
|
||||
let conn = Connection::new_system()?;
|
||||
let proxy = GfxProxy::new(&conn)?;
|
||||
|
||||
let (tx1, rx1) = channel();
|
||||
proxy.connect_notify_gfx(tx1)?;
|
||||
|
||||
let (tx2, rx2) = channel();
|
||||
proxy.connect_notify_action(tx2)?;
|
||||
|
||||
thread::spawn(move || loop {
|
||||
if proxy
|
||||
.next_signal()
|
||||
.map_err(|e| println!("Error: {}", e))
|
||||
.is_err()
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if let Ok(data) = rx1.try_recv() {
|
||||
notify!(do_gfx_notif, last_notification, &data);
|
||||
}
|
||||
|
||||
if let Ok(data) = rx2.try_recv() {
|
||||
match data {
|
||||
GfxRequiredUserAction::Logout | GfxRequiredUserAction::Reboot => {
|
||||
do_gfx_action_notif(&data)
|
||||
.map_err(|e| {
|
||||
println!("Error: {}", e);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
GfxRequiredUserAction::Integrated => {
|
||||
base_notification!(
|
||||
"You must be in integrated mode first to switch to the requested mode"
|
||||
)
|
||||
.map_err(|e| {
|
||||
println!("Error: {}", e);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
GfxRequiredUserAction::None => {}
|
||||
}
|
||||
}
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn do_thermal_notif(profile: &Profile) -> Result<NotificationHandle, Box<dyn Error>> {
|
||||
let icon = match profile {
|
||||
Profile::Balanced => "asus_notif_yellow",
|
||||
@@ -159,52 +101,3 @@ fn do_led_notif(ledmode: &AuraEffect) -> Result<NotificationHandle, notify_rust:
|
||||
fn do_charge_notif(limit: &u8) -> Result<NotificationHandle, notify_rust::error::Error> {
|
||||
base_notification!(&format!("Battery charge limit changed to {}", limit))
|
||||
}
|
||||
|
||||
fn do_gfx_notif(vendor: &GfxVendors) -> Result<NotificationHandle, notify_rust::error::Error> {
|
||||
let icon = match vendor {
|
||||
GfxVendors::Nvidia => "/usr/share/icons/hicolor/scalable/status/gpu-nvidia.svg",
|
||||
GfxVendors::Integrated => "/usr/share/icons/hicolor/scalable/status/gpu-integrated.svg",
|
||||
GfxVendors::Compute => "/usr/share/icons/hicolor/scalable/status/gpu-compute.svg",
|
||||
GfxVendors::Vfio => "/usr/share/icons/hicolor/scalable/status/gpu-vfio.svg",
|
||||
GfxVendors::Hybrid => "/usr/share/icons/hicolor/scalable/status/gpu-hybrid.svg",
|
||||
};
|
||||
Notification::new()
|
||||
.summary(NOTIF_HEADER)
|
||||
.body(&format!(
|
||||
"Graphics mode changed to {}",
|
||||
<&str>::from(vendor)
|
||||
))
|
||||
.timeout(2000)
|
||||
.icon(icon)
|
||||
.show()
|
||||
}
|
||||
|
||||
fn do_gfx_action_notif(vendor: &GfxRequiredUserAction) -> Result<(), notify_rust::error::Error> {
|
||||
let mut notif = Notification::new()
|
||||
.summary(NOTIF_HEADER)
|
||||
.timeout(2000)
|
||||
.urgency(notify_rust::Urgency::Critical)
|
||||
.icon("/usr/share/icons/hicolor/scalable/status/notification-reboot.svg")
|
||||
.finalize();
|
||||
|
||||
if matches!(vendor, GfxRequiredUserAction::Logout) {
|
||||
notif.action("logout", "Logout now?");
|
||||
} else if matches!(vendor, GfxRequiredUserAction::Reboot) {
|
||||
notif.action("reboot", "Reboot now?");
|
||||
}
|
||||
|
||||
notif.body("Graphics mode changed");
|
||||
notif.show()?.wait_for_action(|action| match action {
|
||||
"logout" => {
|
||||
process::Command::new("gnome-session-quit").spawn().ok();
|
||||
}
|
||||
"reboot" => {
|
||||
process::Command::new("systemctl")
|
||||
.arg("reboot")
|
||||
.spawn()
|
||||
.ok();
|
||||
}
|
||||
_ => (),
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "asusctl"
|
||||
version = "4.0.0"
|
||||
version = "4.0.6"
|
||||
authors = ["Luke D Jones <luke@ljones.dev>"]
|
||||
edition = "2018"
|
||||
|
||||
@@ -15,7 +15,7 @@ rog_profiles = { path = "../rog-profiles" }
|
||||
rog_supported = { path = "../rog-supported" }
|
||||
daemon = { path = "../daemon" }
|
||||
gumdrop = "^0.8"
|
||||
supergfxctl = { git = "https://gitlab.com/asus-linux/supergfxctl.git", tag = "2.0.0" }
|
||||
toml = "^0.5.8"
|
||||
|
||||
sysfs-class = "^0.1.2"
|
||||
|
||||
@@ -23,4 +23,4 @@ sysfs-class = "^0.1.2"
|
||||
tinybmp = "^0.2.3"
|
||||
glam = "0.14.0"
|
||||
rog_dbus = { path = "../rog-dbus" }
|
||||
gif = "^0.11.2"
|
||||
gif = "^0.11.2"
|
||||
|
||||
+66
-57
@@ -1,54 +1,4 @@
|
||||
use gumdrop::Options;
|
||||
use rog_aura::error::Error;
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum AnimeStatusValue {
|
||||
On,
|
||||
Off,
|
||||
}
|
||||
impl FromStr for AnimeStatusValue {
|
||||
type Err = Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let s = s.to_lowercase();
|
||||
match s.as_str() {
|
||||
"on" => Ok(AnimeStatusValue::On),
|
||||
"off" => Ok(AnimeStatusValue::Off),
|
||||
_ => {
|
||||
print!("Invalid argument, must be one of: on, off");
|
||||
Err(Error::ParseAnime)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
impl From<AnimeStatusValue> for bool {
|
||||
fn from(value: AnimeStatusValue) -> Self {
|
||||
match value {
|
||||
AnimeStatusValue::On => true,
|
||||
AnimeStatusValue::Off => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Options)]
|
||||
pub struct AnimeLeds {
|
||||
#[options(help = "print help message")]
|
||||
help: bool,
|
||||
#[options(
|
||||
no_long,
|
||||
required,
|
||||
short = "b",
|
||||
meta = "",
|
||||
help = "set all leds brightness value"
|
||||
)]
|
||||
led_brightness: u8,
|
||||
}
|
||||
impl AnimeLeds {
|
||||
pub fn led_brightness(&self) -> u8 {
|
||||
self.led_brightness
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Options)]
|
||||
pub struct AnimeCommand {
|
||||
@@ -56,21 +6,30 @@ pub struct AnimeCommand {
|
||||
pub help: bool,
|
||||
#[options(
|
||||
meta = "",
|
||||
help = "turn on/off the panel (accept/reject write requests)"
|
||||
help = "enable/disable the panel LEDs (does not erase last image)"
|
||||
)]
|
||||
pub turn: Option<AnimeStatusValue>,
|
||||
#[options(meta = "", help = "turn on/off the panel at boot (with Asus effect)")]
|
||||
pub boot: Option<AnimeStatusValue>,
|
||||
pub enable: Option<bool>,
|
||||
#[options(
|
||||
meta = "",
|
||||
help = "enable/disable system animations (boot/sleep/shutdown)"
|
||||
)]
|
||||
pub boot_enable: Option<bool>,
|
||||
#[options(meta = "", help = "set global AniMe brightness value")]
|
||||
pub brightness: Option<f32>,
|
||||
#[options(command)]
|
||||
pub command: Option<AnimeActions>,
|
||||
}
|
||||
|
||||
#[derive(Options)]
|
||||
pub enum AnimeActions {
|
||||
#[options(help = "change all leds brightness")]
|
||||
Leds(AnimeLeds),
|
||||
#[options(help = "display an image png")]
|
||||
#[options(help = "display a PNG image")]
|
||||
Image(AnimeImage),
|
||||
#[options(help = "display a diagonal/pixel-perfect PNG")]
|
||||
PixelImage(AnimeImageDiagonal),
|
||||
#[options(help = "display an animated GIF")]
|
||||
Gif(AnimeGif),
|
||||
#[options(help = "display an animated diagonal/pixel-perfect GIF")]
|
||||
PixelGif(AnimeGifDiagonal),
|
||||
}
|
||||
|
||||
#[derive(Options)]
|
||||
@@ -90,3 +49,53 @@ pub struct AnimeImage {
|
||||
#[options(meta = "", default = "1.0", help = "brightness 0.0-1.0")]
|
||||
pub bright: f32,
|
||||
}
|
||||
|
||||
#[derive(Options)]
|
||||
pub struct AnimeImageDiagonal {
|
||||
#[options(help = "print help message")]
|
||||
pub help: bool,
|
||||
#[options(meta = "", help = "full path to the png to display")]
|
||||
pub path: String,
|
||||
#[options(meta = "", default = "1.0", help = "brightness 0.0-1.0")]
|
||||
pub bright: f32,
|
||||
}
|
||||
|
||||
#[derive(Options)]
|
||||
pub struct AnimeGif {
|
||||
#[options(help = "print help message")]
|
||||
pub help: bool,
|
||||
#[options(meta = "", help = "full path to the png to display")]
|
||||
pub path: String,
|
||||
#[options(meta = "", default = "1.0", help = "scale 1.0 == normal")]
|
||||
pub scale: f32,
|
||||
#[options(meta = "", default = "0.0", help = "x position (float)")]
|
||||
pub x_pos: f32,
|
||||
#[options(meta = "", default = "0.0", help = "y position (float)")]
|
||||
pub y_pos: f32,
|
||||
#[options(meta = "", default = "0.0", help = "the angle in radians")]
|
||||
pub angle: f32,
|
||||
#[options(meta = "", default = "1.0", help = "brightness 0.0-1.0")]
|
||||
pub bright: f32,
|
||||
#[options(
|
||||
meta = "",
|
||||
default = "1",
|
||||
help = "how many loops to play - 0 is infinite"
|
||||
)]
|
||||
pub loops: u32,
|
||||
}
|
||||
|
||||
#[derive(Options)]
|
||||
pub struct AnimeGifDiagonal {
|
||||
#[options(help = "print help message")]
|
||||
pub help: bool,
|
||||
#[options(meta = "", help = "full path to the png to display")]
|
||||
pub path: String,
|
||||
#[options(meta = "", default = "1.0", help = "brightness 0.0-1.0")]
|
||||
pub bright: f32,
|
||||
#[options(
|
||||
meta = "",
|
||||
default = "1",
|
||||
help = "how many loops to play - 0 is infinite"
|
||||
)]
|
||||
pub loops: u32,
|
||||
}
|
||||
|
||||
+6
-16
@@ -1,10 +1,9 @@
|
||||
use crate::{
|
||||
anime_cli::AnimeCommand,
|
||||
aura_cli::{LedBrightness, SetAuraBuiltin},
|
||||
profiles_cli::ProfileCommand,
|
||||
profiles_cli::{FanCurveCommand, ProfileCommand},
|
||||
};
|
||||
use gumdrop::Options;
|
||||
use supergfxctl::gfx_vendors::GfxVendors;
|
||||
|
||||
#[derive(Default, Options)]
|
||||
pub struct CliStart {
|
||||
@@ -20,7 +19,7 @@ pub struct CliStart {
|
||||
pub next_kbd_bright: bool,
|
||||
#[options(help = "Toggle to previous keyboard brightness")]
|
||||
pub prev_kbd_bright: bool,
|
||||
#[options(meta = "", help = "<20-100>")]
|
||||
#[options(meta = "", help = "Set your battery charge limit <20-100>")]
|
||||
pub chg_limit: Option<u8>,
|
||||
#[options(command)]
|
||||
pub command: Option<CliCommand>,
|
||||
@@ -30,9 +29,11 @@ pub struct CliStart {
|
||||
pub enum CliCommand {
|
||||
#[options(help = "Set the keyboard lighting from built-in modes")]
|
||||
LedMode(LedModeCommand),
|
||||
#[options(help = "Create and configure profiles")]
|
||||
#[options(help = "Set or select platform_profile")]
|
||||
Profile(ProfileCommand),
|
||||
#[options(help = "Set the graphics mode")]
|
||||
#[options(help = "Set, select, or modify fan curves if supported")]
|
||||
FanCurve(FanCurveCommand),
|
||||
#[options(help = "Set the graphics mode (obsoleted by supergfxctl)")]
|
||||
Graphics(GraphicsCommand),
|
||||
#[options(name = "anime", help = "Manage AniMe Matrix")]
|
||||
Anime(AnimeCommand),
|
||||
@@ -66,17 +67,6 @@ pub struct LedModeCommand {
|
||||
pub struct GraphicsCommand {
|
||||
#[options(help = "print help message")]
|
||||
pub help: bool,
|
||||
#[options(
|
||||
meta = "",
|
||||
help = "Set graphics mode: <nvidia, hybrid, compute, integrated>"
|
||||
)]
|
||||
pub mode: Option<GfxVendors>,
|
||||
#[options(help = "Get the current mode")]
|
||||
pub get: bool,
|
||||
#[options(help = "Get the current power status")]
|
||||
pub pow: bool,
|
||||
#[options(help = "Do not ask for confirmation")]
|
||||
pub force: bool,
|
||||
}
|
||||
|
||||
#[derive(Options, Debug)]
|
||||
|
||||
+266
-137
@@ -1,31 +1,29 @@
|
||||
mod anime_cli;
|
||||
mod aura_cli;
|
||||
mod cli_opts;
|
||||
mod profiles_cli;
|
||||
use std::process::Command;
|
||||
use std::thread::sleep;
|
||||
use std::{env::args, path::Path};
|
||||
|
||||
use crate::aura_cli::{LedBrightness, SetAuraBuiltin};
|
||||
use crate::cli_opts::*;
|
||||
use anime_cli::{AnimeActions, AnimeCommand};
|
||||
use gumdrop::{Opt, Options};
|
||||
use profiles_cli::ProfileCommand;
|
||||
use rog_anime::{AnimeDataBuffer, AnimeImage, Vec2, ANIME_DATA_LEN};
|
||||
|
||||
use anime_cli::{AnimeActions, AnimeCommand};
|
||||
use profiles_cli::{FanCurveCommand, ProfileCommand};
|
||||
use rog_anime::{AnimTime, AnimeDataBuffer, AnimeDiagonal, AnimeGif, AnimeImage, Vec2};
|
||||
use rog_aura::{self, AuraEffect};
|
||||
use rog_dbus::RogDbusClient;
|
||||
use rog_profiles::error::ProfileError;
|
||||
use rog_supported::SupportedFunctions;
|
||||
use rog_supported::{
|
||||
AnimeSupportedFunctions, LedSupportedFunctions, PlatformProfileFunctions,
|
||||
RogBiosSupportedFunctions,
|
||||
};
|
||||
use std::{env::args, path::Path, sync::mpsc::channel};
|
||||
use supergfxctl::{
|
||||
gfx_vendors::GfxRequiredUserAction,
|
||||
special::{get_asus_gsync_gfx_mode, has_asus_gsync_gfx_mode},
|
||||
zbus_proxy::GfxProxy,
|
||||
};
|
||||
use zbus::Connection;
|
||||
|
||||
const PLEASE: &str =
|
||||
"Please use `systemctl status asusd` and `journalctl -b -u asusd` for more information";
|
||||
use crate::aura_cli::{LedBrightness, SetAuraBuiltin};
|
||||
use crate::cli_opts::*;
|
||||
|
||||
mod anime_cli;
|
||||
mod aura_cli;
|
||||
mod cli_opts;
|
||||
mod profiles_cli;
|
||||
|
||||
const CONFIG_ADVICE: &str = "A config file need to be removed so a new one can be generated";
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
@@ -49,50 +47,48 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
}
|
||||
}
|
||||
|
||||
let (dbus, _) = RogDbusClient::new().map_err(|e| {
|
||||
println!("\nIs asusd running?\n");
|
||||
println!("{}", PLEASE);
|
||||
println!("{}\n", CONFIG_ADVICE);
|
||||
e
|
||||
})?;
|
||||
let (dbus, _) = RogDbusClient::new()
|
||||
.map_err(|e| {
|
||||
print_error_help(Box::new(e), None);
|
||||
std::process::exit(3);
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let supported = dbus
|
||||
.proxies()
|
||||
.supported()
|
||||
.get_supported_functions()
|
||||
.map_err(|e| {
|
||||
println!("\nIs asusd running?\n");
|
||||
println!("{}", PLEASE);
|
||||
println!("{}\n", CONFIG_ADVICE);
|
||||
e
|
||||
})?;
|
||||
print_error_help(Box::new(e), None);
|
||||
std::process::exit(4);
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
if parsed.version {
|
||||
print_versions();
|
||||
println!();
|
||||
print_laptop_info();
|
||||
println!("{}\n", PLEASE);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if let Err(err) = do_parsed(&parsed, &supported, &dbus) {
|
||||
print_error_help(err, &supported);
|
||||
print_error_help(err, Some(&supported));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn print_error_help(err: Box<dyn std::error::Error>, supported: &SupportedFunctions) {
|
||||
println!("Error: {}\n", err);
|
||||
print_versions();
|
||||
println!();
|
||||
print_laptop_info();
|
||||
println!();
|
||||
println!("Supported laptop functions:\n\n{}", supported);
|
||||
println!();
|
||||
println!("{}", PLEASE);
|
||||
println!("The above may give some indication that an option is not supported");
|
||||
println!("or that a config file must be removed or fixed");
|
||||
fn print_error_help(err: Box<dyn std::error::Error>, supported: Option<&SupportedFunctions>) {
|
||||
if do_diagnose("asusd") {
|
||||
println!("\nError: {}\n", err);
|
||||
print_versions();
|
||||
println!();
|
||||
print_laptop_info();
|
||||
if let Some(supported) = supported {
|
||||
println!();
|
||||
println!("Supported laptop functions:\n\n{}", supported);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn print_versions() {
|
||||
@@ -105,7 +101,6 @@ fn print_versions() {
|
||||
println!(" rog-dbus v{}", rog_dbus::VERSION);
|
||||
println!(" rog-profiles v{}", rog_profiles::VERSION);
|
||||
println!("rog-supported v{}", rog_supported::VERSION);
|
||||
println!(" supergfxctl v{}", supergfxctl::VERSION);
|
||||
}
|
||||
|
||||
fn print_laptop_info() {
|
||||
@@ -117,6 +112,30 @@ fn print_laptop_info() {
|
||||
println!("Board name: {}", board_name.trim());
|
||||
}
|
||||
|
||||
fn do_diagnose(name: &str) -> bool {
|
||||
if name != "asusd" && !check_systemd_unit_enabled(name) {
|
||||
println!(
|
||||
"\n\x1b[0;31m{} is not enabled, enable it with `systemctl enable {}\x1b[0m",
|
||||
name, name
|
||||
);
|
||||
return true;
|
||||
} else if !check_systemd_unit_active(name) {
|
||||
println!(
|
||||
"\n\x1b[0;31m{} is not running, start it with `systemctl start {}\x1b[0m",
|
||||
name, name
|
||||
);
|
||||
return true;
|
||||
} else {
|
||||
println!("\nSome error happened (sorry)");
|
||||
println!(
|
||||
"Please use `systemctl status {}` and `journalctl -b -u {}` for more information",
|
||||
name, name
|
||||
);
|
||||
println!("{}", CONFIG_ADVICE);
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn do_parsed(
|
||||
parsed: &CliStart,
|
||||
supported: &SupportedFunctions,
|
||||
@@ -125,7 +144,10 @@ fn do_parsed(
|
||||
match &parsed.command {
|
||||
Some(CliCommand::LedMode(mode)) => handle_led_mode(dbus, &supported.keyboard_led, mode)?,
|
||||
Some(CliCommand::Profile(cmd)) => handle_profile(dbus, &supported.platform_profile, cmd)?,
|
||||
Some(CliCommand::Graphics(cmd)) => do_gfx(cmd)?,
|
||||
Some(CliCommand::FanCurve(cmd)) => {
|
||||
handle_fan_curve(dbus, &supported.platform_profile, cmd)?
|
||||
}
|
||||
Some(CliCommand::Graphics(_)) => do_gfx()?,
|
||||
Some(CliCommand::Anime(cmd)) => handle_anime(dbus, &supported.anime_ctrl, cmd)?,
|
||||
Some(CliCommand::Bios(cmd)) => handle_bios_option(dbus, &supported.rog_bios_ctrl, cmd)?,
|
||||
None => {
|
||||
@@ -149,7 +171,7 @@ fn do_parsed(
|
||||
match brightness.level() {
|
||||
None => {
|
||||
let level = dbus.proxies().led().get_led_brightness()?;
|
||||
println!("Current keyboard led brightness: {}", level.to_string());
|
||||
println!("Current keyboard led brightness: {}", level);
|
||||
}
|
||||
Some(level) => dbus
|
||||
.proxies()
|
||||
@@ -177,67 +199,9 @@ fn do_parsed(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn do_gfx(command: &GraphicsCommand) -> Result<(), Box<dyn std::error::Error>> {
|
||||
if command.mode.is_none() && !command.get && !command.pow && !command.force || command.help {
|
||||
println!("{}", command.self_usage());
|
||||
}
|
||||
|
||||
let conn = Connection::new_system()?;
|
||||
let proxy = GfxProxy::new(&conn)?;
|
||||
|
||||
let (tx, rx) = channel();
|
||||
proxy.connect_notify_action(tx)?;
|
||||
|
||||
if let Some(mode) = command.mode {
|
||||
if has_asus_gsync_gfx_mode() && get_asus_gsync_gfx_mode()? == 1 {
|
||||
println!("You can not change modes until you turn dedicated/G-Sync off and reboot");
|
||||
std::process::exit(-1);
|
||||
}
|
||||
|
||||
println!("If anything fails check `journalctl -b -u asusd`\n");
|
||||
|
||||
proxy.gfx_write_mode(&mode).map_err(|err|{
|
||||
println!("Graphics mode change error. You may be in an invalid state.");
|
||||
println!("Check mode with `asusctl graphics -g` and switch to opposite\nmode to correct it, e.g: if integrated, switch to hybrid, or if nvidia, switch to integrated.\n");
|
||||
err
|
||||
})?;
|
||||
|
||||
loop {
|
||||
proxy.next_signal()?;
|
||||
|
||||
if let Ok(res) = rx.try_recv() {
|
||||
match res {
|
||||
GfxRequiredUserAction::Integrated => {
|
||||
println!(
|
||||
"You must change to Integrated before you can change to {}",
|
||||
<&str>::from(mode)
|
||||
);
|
||||
}
|
||||
GfxRequiredUserAction::Logout | GfxRequiredUserAction::Reboot => {
|
||||
println!(
|
||||
"Graphics mode changed to {}. User action required is: {}",
|
||||
<&str>::from(mode),
|
||||
<&str>::from(&res)
|
||||
);
|
||||
}
|
||||
GfxRequiredUserAction::None => {
|
||||
println!("Graphics mode changed to {}", <&str>::from(mode));
|
||||
}
|
||||
}
|
||||
}
|
||||
std::process::exit(0)
|
||||
}
|
||||
}
|
||||
|
||||
if command.get {
|
||||
let res = proxy.gfx_get_mode()?;
|
||||
println!("Current graphics mode: {}", <&str>::from(res));
|
||||
}
|
||||
if command.pow {
|
||||
let res = proxy.gfx_get_pwr()?;
|
||||
println!("Current power status: {}", <&str>::from(&res));
|
||||
}
|
||||
|
||||
fn do_gfx() -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("Please use supergfxctl for graphics switching. supergfxctl is the result of making asusctl graphics switching generic so all laptops can use it");
|
||||
println!("This command will be removed in future");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -246,28 +210,28 @@ fn handle_anime(
|
||||
_supported: &AnimeSupportedFunctions,
|
||||
cmd: &AnimeCommand,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
if (cmd.command.is_none() && cmd.boot.is_none() && cmd.turn.is_none()) || cmd.help {
|
||||
if (cmd.command.is_none()
|
||||
&& cmd.enable.is_none()
|
||||
&& cmd.boot_enable.is_none()
|
||||
&& cmd.brightness.is_none())
|
||||
|| cmd.help
|
||||
{
|
||||
println!("Missing arg or command\n\n{}", cmd.self_usage());
|
||||
if let Some(lst) = cmd.self_command_list() {
|
||||
println!("\n{}", lst);
|
||||
}
|
||||
}
|
||||
if let Some(anime_turn) = cmd.turn {
|
||||
dbus.proxies().anime().set_led_power(anime_turn.into())?
|
||||
if let Some(anime_turn) = cmd.enable {
|
||||
dbus.proxies().anime().set_on_off(anime_turn)?
|
||||
}
|
||||
if let Some(anime_boot) = cmd.boot {
|
||||
dbus.proxies()
|
||||
.anime()
|
||||
.set_system_animations(anime_boot.into())?
|
||||
if let Some(anime_boot) = cmd.boot_enable {
|
||||
dbus.proxies().anime().set_boot_on_off(anime_boot)?
|
||||
}
|
||||
if let Some(bright) = cmd.brightness {
|
||||
dbus.proxies().anime().set_brightness(bright as f32)?
|
||||
}
|
||||
if let Some(action) = cmd.command.as_ref() {
|
||||
match action {
|
||||
AnimeActions::Leds(anime_leds) => {
|
||||
let data = AnimeDataBuffer::from_vec(
|
||||
[anime_leds.led_brightness(); ANIME_DATA_LEN].to_vec(),
|
||||
);
|
||||
dbus.proxies().anime().write(data)?;
|
||||
}
|
||||
AnimeActions::Image(image) => {
|
||||
if image.help_requested() || image.path.is_empty() {
|
||||
println!("Missing arg or command\n\n{}", image.self_usage());
|
||||
@@ -289,6 +253,82 @@ fn handle_anime(
|
||||
.anime()
|
||||
.write(<AnimeDataBuffer>::from(&matrix))?;
|
||||
}
|
||||
AnimeActions::PixelImage(image) => {
|
||||
if image.help_requested() || image.path.is_empty() {
|
||||
println!("Missing arg or command\n\n{}", image.self_usage());
|
||||
if let Some(lst) = image.self_command_list() {
|
||||
println!("\n{}", lst);
|
||||
}
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
let matrix = AnimeDiagonal::from_png(Path::new(&image.path), None, image.bright)?;
|
||||
|
||||
dbus.proxies()
|
||||
.anime()
|
||||
.write(<AnimeDataBuffer>::from(&matrix))?;
|
||||
}
|
||||
AnimeActions::Gif(gif) => {
|
||||
if gif.help_requested() || gif.path.is_empty() {
|
||||
println!("Missing arg or command\n\n{}", gif.self_usage());
|
||||
if let Some(lst) = gif.self_command_list() {
|
||||
println!("\n{}", lst);
|
||||
}
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
let matrix = AnimeGif::from_gif(
|
||||
Path::new(&gif.path),
|
||||
gif.scale,
|
||||
gif.angle,
|
||||
Vec2::new(gif.x_pos, gif.y_pos),
|
||||
AnimTime::Count(1),
|
||||
gif.bright,
|
||||
)?;
|
||||
|
||||
let mut loops = gif.loops as i32;
|
||||
loop {
|
||||
for frame in matrix.frames() {
|
||||
dbus.proxies().anime().write(frame.frame().clone())?;
|
||||
sleep(frame.delay());
|
||||
}
|
||||
if loops >= 0 {
|
||||
loops -= 1;
|
||||
}
|
||||
if loops == 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
AnimeActions::PixelGif(gif) => {
|
||||
if gif.help_requested() || gif.path.is_empty() {
|
||||
println!("Missing arg or command\n\n{}", gif.self_usage());
|
||||
if let Some(lst) = gif.self_command_list() {
|
||||
println!("\n{}", lst);
|
||||
}
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
let matrix = AnimeGif::from_diagonal_gif(
|
||||
Path::new(&gif.path),
|
||||
AnimTime::Count(1),
|
||||
gif.bright,
|
||||
)?;
|
||||
|
||||
let mut loops = gif.loops as i32;
|
||||
loop {
|
||||
for frame in matrix.frames() {
|
||||
dbus.proxies().anime().write(frame.frame().clone())?;
|
||||
sleep(frame.delay());
|
||||
}
|
||||
if loops >= 0 {
|
||||
loops -= 1;
|
||||
}
|
||||
if loops == 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
@@ -375,39 +415,104 @@ fn handle_profile(
|
||||
supported: &PlatformProfileFunctions,
|
||||
cmd: &ProfileCommand,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("Warning: Profiles should work fine but now depend on power-profiles-daemon v0.9+");
|
||||
println!("Warning: Fan-curve support is coming in a 4.1.x release");
|
||||
if !cmd.next && !cmd.list {
|
||||
if !supported.fan_curves {
|
||||
println!("Profiles not supported by either this kernel or by the laptop.");
|
||||
return Err(ProfileError::NotSupported.into());
|
||||
}
|
||||
|
||||
println!("Warning: Profiles now depend on power-profiles-daemon v0.9+ which may not be in your install");
|
||||
println!(" If you have unexpected behaviour or have only two profiles in your desktop control");
|
||||
println!(" you need to manually install from https://gitlab.freedesktop.org/hadess/power-profiles-daemon");
|
||||
println!(" Fedora and Arch distros will get the update soon...\n");
|
||||
if !cmd.next && !cmd.list && cmd.profile_set.is_none() && !cmd.profile_get {
|
||||
if !cmd.help {
|
||||
println!("Missing arg or command\n");
|
||||
}
|
||||
let usage: Vec<String> = ProfileCommand::usage()
|
||||
.lines()
|
||||
.map(|s| s.to_string())
|
||||
.collect();
|
||||
for line in usage
|
||||
.iter()
|
||||
.filter(|line| !line.contains("--curve") || supported.fan_curves)
|
||||
{
|
||||
println!("{}", line);
|
||||
}
|
||||
println!("{}", ProfileCommand::usage());
|
||||
|
||||
if let Some(lst) = cmd.self_command_list() {
|
||||
println!("\n{}", lst);
|
||||
}
|
||||
|
||||
// println!("Note: turbo, frequency, fan preset and fan curve options will apply to");
|
||||
// println!(" to the currently active profile unless a profile name is specified");
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
if cmd.next {
|
||||
dbus.proxies().profile().next_profile()?;
|
||||
} else if let Some(profile) = cmd.profile_set {
|
||||
dbus.proxies().profile().set_active_profile(profile)?;
|
||||
}
|
||||
|
||||
if cmd.list {
|
||||
let res = dbus.proxies().profile().profiles()?;
|
||||
res.iter().for_each(|p| println!("{:?}", p));
|
||||
}
|
||||
|
||||
if cmd.profile_get {
|
||||
let res = dbus.proxies().profile().active_profile()?;
|
||||
println!("Active profile is {:?}", res);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_fan_curve(
|
||||
dbus: &RogDbusClient,
|
||||
supported: &PlatformProfileFunctions,
|
||||
cmd: &FanCurveCommand,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
if !supported.fan_curves {
|
||||
println!("Fan-curves not supported by either this kernel or by the laptop.");
|
||||
return Err(ProfileError::NotSupported.into());
|
||||
}
|
||||
|
||||
if !cmd.get_enabled && !cmd.default && cmd.mod_profile.is_none() {
|
||||
if !cmd.help {
|
||||
println!("Missing arg or command\n");
|
||||
}
|
||||
println!("{}", FanCurveCommand::usage());
|
||||
|
||||
if let Some(lst) = cmd.self_command_list() {
|
||||
println!("\n{}", lst);
|
||||
}
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
if (cmd.enabled.is_some() || cmd.fan.is_some() || cmd.data.is_some())
|
||||
&& cmd.mod_profile.is_none()
|
||||
{
|
||||
println!("--enabled, --fan, and --data options require --mod-profile");
|
||||
std::process::exit(666);
|
||||
}
|
||||
|
||||
if cmd.get_enabled {
|
||||
let res = dbus.proxies().profile().enabled_fan_profiles()?;
|
||||
println!("{:?}", res);
|
||||
}
|
||||
|
||||
if cmd.default {
|
||||
dbus.proxies().profile().set_active_curve_to_defaults()?;
|
||||
}
|
||||
|
||||
if let Some(profile) = cmd.mod_profile {
|
||||
if cmd.enabled.is_none() && cmd.data.is_none() {
|
||||
let data = dbus.proxies().profile().fan_curve_data(profile)?;
|
||||
let data = toml::to_string(&data)?;
|
||||
println!("\nFan curves for {:?}\n\n{}", profile, data);
|
||||
}
|
||||
|
||||
if let Some(enabled) = cmd.enabled {
|
||||
dbus.proxies()
|
||||
.profile()
|
||||
.set_fan_curve_enabled(profile, enabled)?;
|
||||
}
|
||||
|
||||
if let Some(mut curve) = cmd.data.clone() {
|
||||
let fan = cmd.fan.unwrap_or_default();
|
||||
curve.set_fan(fan);
|
||||
dbus.proxies().profile().set_fan_curve(curve, profile)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -431,8 +536,8 @@ fn handle_bios_option(
|
||||
.collect();
|
||||
|
||||
for line in usage.iter().filter(|line| {
|
||||
!line.contains("sound") && !supported.post_sound_toggle
|
||||
|| !line.contains("GPU") && !supported.dedicated_gfx_toggle
|
||||
line.contains("sound") && supported.post_sound_toggle
|
||||
|| line.contains("GPU") && supported.dedicated_gfx_toggle
|
||||
}) {
|
||||
println!("{}", line);
|
||||
}
|
||||
@@ -464,3 +569,27 @@ fn handle_bios_option(
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn check_systemd_unit_active(name: &str) -> bool {
|
||||
if let Ok(out) = Command::new("systemctl")
|
||||
.arg("is-active")
|
||||
.arg(name)
|
||||
.output()
|
||||
{
|
||||
let buf = String::from_utf8_lossy(&out.stdout);
|
||||
return !buf.contains("inactive") && !buf.contains("failed");
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn check_systemd_unit_enabled(name: &str) -> bool {
|
||||
if let Ok(out) = Command::new("systemctl")
|
||||
.arg("is-enabled")
|
||||
.arg(name)
|
||||
.output()
|
||||
{
|
||||
let buf = String::from_utf8_lossy(&out.stdout);
|
||||
return buf.contains("enabled");
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use gumdrop::Options;
|
||||
use rog_profiles::{fan_curve_set::CurveData, FanCurvePU, Profile};
|
||||
|
||||
#[derive(Debug, Clone, Options)]
|
||||
pub struct ProfileCommand {
|
||||
@@ -8,4 +9,43 @@ pub struct ProfileCommand {
|
||||
pub next: bool,
|
||||
#[options(help = "list available profiles")]
|
||||
pub list: bool,
|
||||
|
||||
#[options(help = "get profile")]
|
||||
pub profile_get: bool,
|
||||
#[options(meta = "", help = "set the active profile")]
|
||||
pub profile_set: Option<Profile>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Options)]
|
||||
pub struct FanCurveCommand {
|
||||
#[options(help = "print help message")]
|
||||
pub help: bool,
|
||||
|
||||
#[options(help = "get enabled fan profiles")]
|
||||
pub get_enabled: bool,
|
||||
#[options(help = "set the active profile's fan curve to default")]
|
||||
pub default: bool,
|
||||
|
||||
#[options(
|
||||
meta = "",
|
||||
help = "profile to modify fan-curve for. Shows data if no options provided"
|
||||
)]
|
||||
pub mod_profile: Option<Profile>,
|
||||
#[options(
|
||||
meta = "",
|
||||
help = "enable or disable <true/false> fan curve. `mod-profile` required"
|
||||
)]
|
||||
pub enabled: Option<bool>,
|
||||
#[options(
|
||||
meta = "",
|
||||
help = "select fan <cpu/gpu> to modify. `mod-profile` required"
|
||||
)]
|
||||
pub fan: Option<FanCurvePU>,
|
||||
|
||||
#[options(
|
||||
meta = "",
|
||||
help = "data format = 30c:1%,49c:2%,59c:3%,69c:4%,79c:31%,89c:49%,99c:56%,109c:58%.
|
||||
`--mod-profile` required. If '%' is omitted the fan range is 0-255"
|
||||
)]
|
||||
pub data: Option<CurveData>,
|
||||
}
|
||||
|
||||
@@ -353,13 +353,13 @@ impl CtrlAnime<'static> {
|
||||
pub fn set_state(&mut self, on: bool) -> zbus::fdo::Result<()> {
|
||||
// Operations here need to be in specific order
|
||||
if on {
|
||||
self.client.proxies().anime().set_led_power(on)?;
|
||||
self.client.proxies().anime().set_on_off(on)?;
|
||||
// Let the inner loop run
|
||||
self.inner_early_return.store(false, Ordering::SeqCst);
|
||||
} else {
|
||||
// Must make the inner run loop return early
|
||||
self.inner_early_return.store(true, Ordering::SeqCst);
|
||||
self.client.proxies().anime().set_led_power(on)?;
|
||||
self.client.proxies().anime().set_on_off(on)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "daemon"
|
||||
version = "4.0.1"
|
||||
version = "4.0.6"
|
||||
license = "MPL-2.0"
|
||||
readme = "README.md"
|
||||
authors = ["Luke <luke@ljones.dev>"]
|
||||
|
||||
+12
-2
@@ -34,8 +34,18 @@ impl Config {
|
||||
} else if let Ok(data) = serde_json::from_str(&buf) {
|
||||
config = data;
|
||||
} else {
|
||||
warn!("Could not deserialise {}", CONFIG_PATH);
|
||||
panic!("Please remove {} then restart asusd", CONFIG_PATH);
|
||||
warn!(
|
||||
"Could not deserialise {}.\nWill rename to {}-old and recreate config",
|
||||
CONFIG_PATH, CONFIG_PATH
|
||||
);
|
||||
let cfg_old = CONFIG_PATH.to_string() + "-old";
|
||||
std::fs::rename(CONFIG_PATH, cfg_old).unwrap_or_else(|err| {
|
||||
panic!(
|
||||
"Could not rename. Please remove {} then restart service: Error {}",
|
||||
CONFIG_PATH, err
|
||||
)
|
||||
});
|
||||
config = Self::new();
|
||||
}
|
||||
} else {
|
||||
config = Self::new()
|
||||
|
||||
@@ -166,11 +166,17 @@ impl AnimeConfig {
|
||||
info!("Updated config version to: {}", VERSION);
|
||||
return config;
|
||||
}
|
||||
AnimeConfig::write_backup(buf);
|
||||
warn!(
|
||||
"Could not deserialise {}. Backed up as *-old",
|
||||
ANIME_CONFIG_PATH
|
||||
"Could not deserialise {}.\nWill rename to {}-old and recreate config",
|
||||
ANIME_CONFIG_PATH, ANIME_CONFIG_PATH
|
||||
);
|
||||
let cfg_old = ANIME_CONFIG_PATH.to_string() + "-old";
|
||||
std::fs::rename(ANIME_CONFIG_PATH, cfg_old).unwrap_or_else(|err| {
|
||||
panic!(
|
||||
"Could not rename. Please remove {} then restart service: Error {}",
|
||||
ANIME_CONFIG_PATH, err
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
AnimeConfig::create_default(&mut file)
|
||||
@@ -246,12 +252,4 @@ impl AnimeConfig {
|
||||
file.write_all(json.as_bytes())
|
||||
.unwrap_or_else(|err| error!("Could not write config: {}", err));
|
||||
}
|
||||
|
||||
fn write_backup(buf: String) {
|
||||
let mut path = ANIME_CONFIG_PATH.to_string();
|
||||
path.push_str("-old");
|
||||
let mut file = File::create(&path).expect("Couldn't overwrite config");
|
||||
file.write_all(buf.as_bytes())
|
||||
.unwrap_or_else(|err| error!("Could not write config: {}", err));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ use ::zbus::Connection;
|
||||
use log::{error, info, warn};
|
||||
use logind_zbus::ManagerProxy;
|
||||
use rog_anime::{
|
||||
error::AnimeError,
|
||||
usb::{
|
||||
pkt_for_apply, pkt_for_flush, pkt_for_set_boot, pkt_for_set_on, pkts_for_init, PROD_ID,
|
||||
VENDOR_ID,
|
||||
@@ -181,15 +182,20 @@ impl CtrlAnime {
|
||||
for action in actions.iter() {
|
||||
match action {
|
||||
ActionData::Animation(frames) => {
|
||||
if rog_anime::run_animation(frames, thread_exit.clone(), &|frame| {
|
||||
if let Ok(lock) = inner.try_lock() {
|
||||
lock.write_data_buffer(frame);
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
.map_err(|err| warn!("rog_anime::run_animation: {}", err))
|
||||
.is_err()
|
||||
{
|
||||
if let Err(err) = rog_anime::run_animation(
|
||||
frames,
|
||||
thread_exit.clone(),
|
||||
&|frame| {
|
||||
inner
|
||||
.try_lock()
|
||||
.map(|lock| lock.write_data_buffer(frame))
|
||||
.map_err(|err| {
|
||||
warn!("rog_anime::run_animation: {}", err);
|
||||
AnimeError::NoFrames
|
||||
})
|
||||
},
|
||||
) {
|
||||
warn!("rog_anime::run_animation: {}", err);
|
||||
break 'main;
|
||||
};
|
||||
|
||||
|
||||
@@ -105,8 +105,17 @@ impl AuraConfig {
|
||||
info!("Updated AuraConfig version");
|
||||
return config;
|
||||
}
|
||||
warn!("Could not deserialise {}", AURA_CONFIG_PATH);
|
||||
panic!("Please remove {} then restart asusd", AURA_CONFIG_PATH);
|
||||
warn!(
|
||||
"Could not deserialise {}.\nWill rename to {}-old and recreate config",
|
||||
AURA_CONFIG_PATH, AURA_CONFIG_PATH
|
||||
);
|
||||
let cfg_old = AURA_CONFIG_PATH.to_string() + "-old";
|
||||
std::fs::rename(AURA_CONFIG_PATH, cfg_old).unwrap_or_else(|err| {
|
||||
panic!(
|
||||
"Could not rename. Please remove {} then restart service: Error {}",
|
||||
AURA_CONFIG_PATH, err
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
AuraConfig::create_default(&mut file, supported_led_modes)
|
||||
|
||||
@@ -30,7 +30,10 @@ pub struct CtrlCharge {
|
||||
|
||||
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
||||
impl CtrlCharge {
|
||||
pub fn set_limit(&mut self, limit: u8) {
|
||||
pub fn set_limit(&mut self, limit: u8) -> Result<(), RogError> {
|
||||
if !(20..=100).contains(&limit) {
|
||||
return Err(RogError::ChargeLimit(limit));
|
||||
}
|
||||
if let Ok(mut config) = self.config.try_lock() {
|
||||
self.set(limit, &mut config)
|
||||
.map_err(|err| {
|
||||
@@ -45,6 +48,7 @@ impl CtrlCharge {
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn limit(&self) -> i8 {
|
||||
@@ -106,10 +110,7 @@ impl CtrlCharge {
|
||||
|
||||
pub(super) fn set(&self, limit: u8, config: &mut Config) -> Result<(), RogError> {
|
||||
if !(20..=100).contains(&limit) {
|
||||
warn!(
|
||||
"Unable to set battery charge limit, must be between 20-100: requested {}",
|
||||
limit
|
||||
);
|
||||
return Err(RogError::ChargeLimit(limit));
|
||||
}
|
||||
|
||||
let path = Self::get_battery_path()?;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use log::{error, warn};
|
||||
use rog_profiles::fan_curve_set::FanCurveSet;
|
||||
use rog_profiles::{FanCurveProfiles, Profile};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::fs::{File, OpenOptions};
|
||||
@@ -17,20 +16,22 @@ pub struct ProfileConfig {
|
||||
|
||||
impl ProfileConfig {
|
||||
fn new(config_path: String) -> Self {
|
||||
let mut platform = ProfileConfig {
|
||||
Self {
|
||||
config_path,
|
||||
active_profile: Profile::get_active_profile().unwrap_or(Profile::Balanced),
|
||||
active_profile: Profile::Balanced,
|
||||
fan_curves: None,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(res) = FanCurveSet::is_supported() {
|
||||
pub fn set_defaults_and_save(&mut self) {
|
||||
self.active_profile = Profile::get_active_profile().unwrap_or(Profile::Balanced);
|
||||
if let Ok(res) = FanCurveProfiles::is_supported() {
|
||||
if res {
|
||||
let curves = FanCurveProfiles::default();
|
||||
platform.fan_curves = Some(curves);
|
||||
self.fan_curves = Some(curves);
|
||||
}
|
||||
}
|
||||
|
||||
platform
|
||||
self.write();
|
||||
}
|
||||
|
||||
pub fn load(config_path: String) -> Self {
|
||||
@@ -45,17 +46,29 @@ impl ProfileConfig {
|
||||
if let Ok(read_len) = file.read_to_string(&mut buf) {
|
||||
if read_len == 0 {
|
||||
config = Self::new(config_path);
|
||||
config.set_defaults_and_save();
|
||||
} else if let Ok(data) = toml::from_str(&buf) {
|
||||
config = data;
|
||||
config.config_path = config_path;
|
||||
} else {
|
||||
warn!("Could not deserialise {}", config_path);
|
||||
panic!("Please remove {} then restart service", config_path);
|
||||
warn!(
|
||||
"Could not deserialise {}.\nWill rename to {}-old and recreate config",
|
||||
config_path, config_path
|
||||
);
|
||||
let cfg_old = config_path.clone() + "-old";
|
||||
std::fs::rename(config_path.clone(), cfg_old).unwrap_or_else(|err| {
|
||||
panic!(
|
||||
"Could not rename. Please remove {} then restart service: Error {}",
|
||||
config_path, err
|
||||
)
|
||||
});
|
||||
config = Self::new(config_path);
|
||||
config.set_defaults_and_save();
|
||||
}
|
||||
} else {
|
||||
config = Self::new(config_path)
|
||||
config = Self::new(config_path);
|
||||
config.set_defaults_and_save();
|
||||
}
|
||||
config.write();
|
||||
config
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use crate::error::RogError;
|
||||
use crate::GetSupported;
|
||||
use crate::{CtrlTask, GetSupported};
|
||||
use log::{info, warn};
|
||||
use rog_profiles::error::ProfileError;
|
||||
use rog_profiles::fan_curve_set::FanCurveSet;
|
||||
use rog_profiles::Profile;
|
||||
use rog_profiles::{FanCurveProfiles, Profile};
|
||||
use rog_supported::PlatformProfileFunctions;
|
||||
use udev::Device;
|
||||
|
||||
use super::config::ProfileConfig;
|
||||
|
||||
pub struct CtrlPlatformProfile {
|
||||
pub config: ProfileConfig,
|
||||
pub fan_device: Option<Device>,
|
||||
}
|
||||
|
||||
impl GetSupported for CtrlPlatformProfile {
|
||||
@@ -28,13 +27,13 @@ https://lkml.org/lkml/2021/8/18/1022
|
||||
);
|
||||
}
|
||||
|
||||
let res = FanCurveSet::is_supported();
|
||||
let res = FanCurveProfiles::is_supported();
|
||||
let mut fan_curve_supported = res.is_err();
|
||||
if let Ok(r) = res {
|
||||
fan_curve_supported = r;
|
||||
};
|
||||
|
||||
if fan_curve_supported {
|
||||
if !fan_curve_supported {
|
||||
info!(
|
||||
r#"
|
||||
fan curves kernel interface not found, your laptop does not support this, or the interface is missing.
|
||||
@@ -55,9 +54,12 @@ Please note that as of 24/08/2021 this is not final.
|
||||
impl crate::Reloadable for CtrlPlatformProfile {
|
||||
/// Fetch the active profile and use that to set all related components up
|
||||
fn reload(&mut self) -> Result<(), RogError> {
|
||||
if let Some(curves) = &self.config.fan_curves {
|
||||
if let Ok(mut device) = FanCurveSet::get_device() {
|
||||
curves.write_to_platform(self.config.active_profile, &mut device);
|
||||
if let Some(curves) = &mut self.config.fan_curves {
|
||||
if let Ok(mut device) = FanCurveProfiles::get_device() {
|
||||
// There is a possibility that the curve was default zeroed, so this call initialises
|
||||
// the data from system read and we need to save it after
|
||||
curves.write_profile_curve_to_platform(self.config.active_profile, &mut device)?;
|
||||
self.config.write();
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
@@ -65,30 +67,20 @@ impl crate::Reloadable for CtrlPlatformProfile {
|
||||
}
|
||||
|
||||
impl CtrlPlatformProfile {
|
||||
pub fn new(mut config: ProfileConfig, fan_device: Option<Device>) -> Result<Self, RogError> {
|
||||
pub fn new(config: ProfileConfig) -> Result<Self, RogError> {
|
||||
if Profile::is_platform_profile_supported() {
|
||||
info!("Device has profile control available");
|
||||
|
||||
if let Some(ref device) = fan_device {
|
||||
let profile = config.active_profile;
|
||||
config
|
||||
.fan_curves
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.read_from_dev_profile(profile, device);
|
||||
if FanCurveProfiles::get_device().is_ok() {
|
||||
info!("Device has fan curves available");
|
||||
}
|
||||
config.write();
|
||||
|
||||
return Ok(CtrlPlatformProfile { config, fan_device });
|
||||
return Ok(CtrlPlatformProfile { config });
|
||||
}
|
||||
|
||||
Err(ProfileError::NotSupported.into())
|
||||
}
|
||||
|
||||
pub fn get_device(&self) -> Option<Device> {
|
||||
self.fan_device.clone()
|
||||
}
|
||||
|
||||
pub fn save_config(&self) {
|
||||
self.config.write();
|
||||
}
|
||||
@@ -96,8 +88,6 @@ impl CtrlPlatformProfile {
|
||||
/// Toggle to next profile in list. This will first read the config, switch, then write out
|
||||
pub(super) fn set_next_profile(&mut self) -> Result<(), RogError> {
|
||||
// Read first just incase the user has modified the config before calling this
|
||||
self.config.read();
|
||||
|
||||
match self.config.active_profile {
|
||||
Profile::Balanced => {
|
||||
Profile::set_profile(Profile::Performance)?;
|
||||
@@ -112,9 +102,50 @@ impl CtrlPlatformProfile {
|
||||
self.config.active_profile = Profile::Balanced;
|
||||
}
|
||||
}
|
||||
self.write_profile_curve_to_platform()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
self.config.write();
|
||||
/// Set the curve for the active profile active
|
||||
pub(super) fn write_profile_curve_to_platform(&mut self) -> Result<(), RogError> {
|
||||
if let Some(curves) = &mut self.config.fan_curves {
|
||||
if let Ok(mut device) = FanCurveProfiles::get_device() {
|
||||
curves.write_profile_curve_to_platform(self.config.active_profile, &mut device)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(super) fn set_active_curve_to_defaults(&mut self) -> Result<(), RogError> {
|
||||
if let Some(curves) = self.config.fan_curves.as_mut() {
|
||||
if let Ok(mut device) = FanCurveProfiles::get_device() {
|
||||
curves.set_active_curve_to_defaults(self.config.active_profile, &mut device)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CtrlProfileTask {
|
||||
ctrl: Arc<Mutex<CtrlPlatformProfile>>,
|
||||
}
|
||||
|
||||
impl CtrlProfileTask {
|
||||
pub fn new(ctrl: Arc<Mutex<CtrlPlatformProfile>>) -> Self {
|
||||
Self { ctrl }
|
||||
}
|
||||
}
|
||||
|
||||
impl CtrlTask for CtrlProfileTask {
|
||||
fn do_task(&self) -> Result<(), RogError> {
|
||||
if let Ok(ref mut lock) = self.ctrl.try_lock() {
|
||||
let new_profile = Profile::get_active_profile().unwrap();
|
||||
if new_profile != lock.config.active_profile {
|
||||
lock.config.active_profile = new_profile;
|
||||
lock.write_profile_curve_to_platform()?;
|
||||
lock.save_config();
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,11 +35,13 @@ impl ProfileZbus {
|
||||
))
|
||||
}
|
||||
|
||||
/// Toggle to next platform_profile. Names provided by `Profiles`
|
||||
/// Toggle to next platform_profile. Names provided by `Profiles`.
|
||||
/// If fan-curves are supported will also activate a fan curve for profile.
|
||||
fn next_profile(&mut self) {
|
||||
if let Ok(mut ctrl) = self.inner.try_lock() {
|
||||
ctrl.set_next_profile()
|
||||
.unwrap_or_else(|err| warn!("{}", err));
|
||||
ctrl.save_config();
|
||||
}
|
||||
self.do_notification();
|
||||
}
|
||||
@@ -61,9 +63,12 @@ impl ProfileZbus {
|
||||
// Read first just incase the user has modified the config before calling this
|
||||
ctrl.config.read();
|
||||
Profile::set_profile(profile)
|
||||
.map_err(|e| warn!("Profile::set_profile, {}", e))
|
||||
.map_err(|e| warn!("set_profile, {}", e))
|
||||
.ok();
|
||||
ctrl.config.active_profile = profile;
|
||||
ctrl.write_profile_curve_to_platform()
|
||||
.map_err(|e| warn!("write_profile_curve_to_platform, {}", e))
|
||||
.ok();
|
||||
|
||||
ctrl.save_config();
|
||||
}
|
||||
@@ -84,14 +89,23 @@ impl ProfileZbus {
|
||||
))
|
||||
}
|
||||
|
||||
/// Get a list of profiles that have fan-curves enabled.
|
||||
fn set_enabled_fan_profiles(&mut self, profiles: Vec<Profile>) -> zbus::fdo::Result<()> {
|
||||
/// Set a profile fan curve enabled status. Will also activate a fan curve if in the
|
||||
/// same profile mode
|
||||
fn set_fan_curve_enabled(&mut self, profile: Profile, enabled: bool) -> zbus::fdo::Result<()> {
|
||||
if let Ok(mut ctrl) = self.inner.try_lock() {
|
||||
ctrl.config.read();
|
||||
if let Some(curves) = &mut ctrl.config.fan_curves {
|
||||
curves.set_enabled_curve_profiles(profiles);
|
||||
}
|
||||
return Err(Error::Failed(UNSUPPORTED_MSG.to_string()));
|
||||
return if let Some(curves) = &mut ctrl.config.fan_curves {
|
||||
curves.set_profile_curve_enabled(profile, enabled);
|
||||
|
||||
ctrl.write_profile_curve_to_platform()
|
||||
.map_err(|e| warn!("write_profile_curve_to_platform, {}", e))
|
||||
.ok();
|
||||
|
||||
ctrl.save_config();
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::Failed(UNSUPPORTED_MSG.to_string()))
|
||||
};
|
||||
}
|
||||
Err(Error::Failed(
|
||||
"Failed to get enabled fan curve names".to_string(),
|
||||
@@ -99,46 +113,51 @@ impl ProfileZbus {
|
||||
}
|
||||
|
||||
/// Get the fan-curve data for the currently active Profile
|
||||
fn active_fan_curve_data(&mut self) -> zbus::fdo::Result<FanCurveSet> {
|
||||
fn fan_curve_data(&mut self, profile: Profile) -> zbus::fdo::Result<FanCurveSet> {
|
||||
if let Ok(mut ctrl) = self.inner.try_lock() {
|
||||
ctrl.config.read();
|
||||
if let Some(curves) = &ctrl.config.fan_curves {
|
||||
return Ok((*curves.get_active_fan_curves()).clone());
|
||||
let curve = curves.get_fan_curves_for(profile);
|
||||
return Ok(curve.clone());
|
||||
}
|
||||
return Err(Error::Failed(UNSUPPORTED_MSG.to_string()));
|
||||
}
|
||||
Err(Error::Failed("Failed to get fan curve data".to_string()))
|
||||
}
|
||||
|
||||
/// Get fan-curve data for each Profile as an array of objects
|
||||
fn fan_curves(&self) -> zbus::fdo::Result<Vec<FanCurveSet>> {
|
||||
/// Set the fan curve for the specified profile.
|
||||
/// Will also activate the fan curve if the user is in the same mode.
|
||||
fn set_fan_curve(&self, profile: Profile, curve: CurveData) -> zbus::fdo::Result<()> {
|
||||
if let Ok(mut ctrl) = self.inner.try_lock() {
|
||||
ctrl.config.read();
|
||||
if let Some(curves) = &ctrl.config.fan_curves {
|
||||
return Ok(curves.get_all_fan_curves());
|
||||
}
|
||||
return Err(Error::Failed(UNSUPPORTED_MSG.to_string()));
|
||||
}
|
||||
Err(Error::Failed("Failed to get all fan curves".to_string()))
|
||||
}
|
||||
|
||||
/// Set this fan-curve data
|
||||
fn set_fan_curve(&self, curve: CurveData) -> zbus::fdo::Result<()> {
|
||||
if let Ok(mut ctrl) = self.inner.try_lock() {
|
||||
ctrl.config.read();
|
||||
let profile = ctrl.config.active_profile;
|
||||
if let Some(mut device) = ctrl.get_device() {
|
||||
if let Some(curves) = &mut ctrl.config.fan_curves {
|
||||
curves.write_and_set_fan_curve(curve, profile, &mut device);
|
||||
}
|
||||
if let Some(curves) = &mut ctrl.config.fan_curves {
|
||||
curves
|
||||
.save_fan_curve(curve, profile)
|
||||
.map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?;
|
||||
} else {
|
||||
return Err(Error::Failed(UNSUPPORTED_MSG.to_string()));
|
||||
}
|
||||
|
||||
ctrl.write_profile_curve_to_platform()
|
||||
.map_err(|e| warn!("Profile::set_profile, {}", e))
|
||||
.ok();
|
||||
ctrl.save_config();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Err(Error::Failed("Failed to set fan curves".to_string()))
|
||||
/// Reset the stored (self) and device curve to the defaults of the platform.
|
||||
///
|
||||
/// Each platform_profile has a different default and the defualt can be read
|
||||
/// only for the currently active profile.
|
||||
fn set_active_curve_to_defaults(&self) -> zbus::fdo::Result<()> {
|
||||
if let Ok(mut ctrl) = self.inner.try_lock() {
|
||||
ctrl.config.read();
|
||||
ctrl.set_active_curve_to_defaults()
|
||||
.map_err(|e| warn!("Profile::set_active_curve_to_defaults, {}", e))
|
||||
.ok();
|
||||
ctrl.save_config();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[dbus_interface(signal)]
|
||||
|
||||
+56
-51
@@ -1,3 +1,15 @@
|
||||
use std::error::Error;
|
||||
use std::io::Write;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
use std::thread::sleep;
|
||||
use std::time::Duration;
|
||||
use std::{env, thread};
|
||||
|
||||
use ::zbus::{fdo, Connection, ObjectServer};
|
||||
use log::LevelFilter;
|
||||
use log::{error, info, warn};
|
||||
|
||||
use daemon::ctrl_anime::config::AnimeConfig;
|
||||
use daemon::ctrl_anime::zbus::CtrlAnimeZbus;
|
||||
use daemon::ctrl_anime::*;
|
||||
@@ -7,6 +19,9 @@ use daemon::ctrl_aura::controller::{
|
||||
};
|
||||
use daemon::ctrl_charge::CtrlCharge;
|
||||
use daemon::ctrl_profiles::config::ProfileConfig;
|
||||
use daemon::ctrl_profiles::controller::CtrlProfileTask;
|
||||
use daemon::ctrl_rog_bios::CtrlRogBios;
|
||||
use daemon::error::RogError;
|
||||
use daemon::{
|
||||
config::Config, ctrl_supported::SupportedFunctions, laptops::print_board_info, GetSupported,
|
||||
};
|
||||
@@ -14,20 +29,9 @@ use daemon::{
|
||||
ctrl_profiles::{controller::CtrlPlatformProfile, zbus::ProfileZbus},
|
||||
laptops::LaptopLedData,
|
||||
};
|
||||
|
||||
use ::zbus::{fdo, Connection, ObjectServer};
|
||||
use daemon::{CtrlTask, Reloadable, ZbusAdd};
|
||||
use log::LevelFilter;
|
||||
use log::{error, info, warn};
|
||||
use rog_dbus::DBUS_NAME;
|
||||
use rog_profiles::fan_curve_set::FanCurveSet;
|
||||
use std::env;
|
||||
use std::error::Error;
|
||||
use std::io::Write;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
|
||||
use daemon::ctrl_rog_bios::CtrlRogBios;
|
||||
use rog_profiles::Profile;
|
||||
|
||||
static PROFILE_CONFIG_PATH: &str = "/etc/asusd/profile.conf";
|
||||
|
||||
@@ -70,8 +74,6 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
|
||||
print_board_info();
|
||||
println!("{}", serde_json::to_string_pretty(&supported)?);
|
||||
|
||||
// Collect tasks for task thread
|
||||
let mut tasks: Vec<Box<dyn CtrlTask + Send>> = Vec::new();
|
||||
// Start zbus server
|
||||
let connection = Connection::new_system()?;
|
||||
let fdo_connection = fdo::DBusProxy::new(&connection)?;
|
||||
@@ -108,23 +110,32 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
|
||||
}
|
||||
}
|
||||
|
||||
let fan_device = if let Ok(res) = FanCurveSet::get_device() {
|
||||
Some(res)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let profile_config = ProfileConfig::load(PROFILE_CONFIG_PATH.into());
|
||||
match CtrlPlatformProfile::new(profile_config, fan_device) {
|
||||
Ok(mut ctrl) => {
|
||||
ctrl.reload()
|
||||
.unwrap_or_else(|err| warn!("Profile control: {}", err));
|
||||
if Profile::is_platform_profile_supported() {
|
||||
let profile_config = ProfileConfig::load(PROFILE_CONFIG_PATH.into());
|
||||
match CtrlPlatformProfile::new(profile_config) {
|
||||
Ok(mut ctrl) => {
|
||||
ctrl.reload()
|
||||
.unwrap_or_else(|err| warn!("Profile control: {}", err));
|
||||
|
||||
let tmp = Arc::new(Mutex::new(ctrl));
|
||||
ProfileZbus::new(tmp).add_to_server(&mut object_server);
|
||||
}
|
||||
Err(err) => {
|
||||
error!("Profile control: {}", err);
|
||||
let tmp = Arc::new(Mutex::new(ctrl));
|
||||
ProfileZbus::new(tmp.clone()).add_to_server(&mut object_server);
|
||||
|
||||
let task = CtrlProfileTask::new(tmp);
|
||||
thread::Builder::new().name("profile tasks".into()).spawn(
|
||||
move || -> Result<(), RogError> {
|
||||
loop {
|
||||
task.do_task()?;
|
||||
sleep(Duration::from_millis(100));
|
||||
}
|
||||
},
|
||||
)?;
|
||||
}
|
||||
Err(err) => {
|
||||
error!("Profile control: {}", err);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
warn!("platform_profile support not found. This requires kernel 5.15.x or the patch applied: https://lkml.org/lkml/2021/8/18/1022");
|
||||
}
|
||||
|
||||
match CtrlAnime::new(AnimeConfig::load()) {
|
||||
@@ -139,7 +150,14 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
|
||||
let zbus = CtrlAnimeZbus(inner.clone());
|
||||
zbus.add_to_server(&mut object_server);
|
||||
|
||||
tasks.push(Box::new(CtrlAnimeTask::new(inner)));
|
||||
let task = CtrlAnimeTask::new(inner);
|
||||
thread::Builder::new().name("anime tasks".into()).spawn(
|
||||
move || -> Result<(), RogError> {
|
||||
loop {
|
||||
task.do_task()?;
|
||||
}
|
||||
},
|
||||
)?;
|
||||
}
|
||||
Err(err) => {
|
||||
error!("AniMe control: {}", err);
|
||||
@@ -158,39 +176,26 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
|
||||
.unwrap_or_else(|err| warn!("Keyboard LED control: {}", err));
|
||||
|
||||
CtrlKbdLedZbus::new(inner.clone()).add_to_server(&mut object_server);
|
||||
|
||||
let task = CtrlKbdLedTask::new(inner);
|
||||
tasks.push(Box::new(task));
|
||||
thread::Builder::new().name("keyboard tasks".into()).spawn(
|
||||
move || -> Result<(), RogError> {
|
||||
loop {
|
||||
task.do_task()?;
|
||||
}
|
||||
},
|
||||
)?;
|
||||
}
|
||||
Err(err) => {
|
||||
error!("Keyboard control: {}", err);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: implement messaging between threads to check fails
|
||||
|
||||
// Run tasks
|
||||
let handle = std::thread::Builder::new()
|
||||
.name("asusd watch".to_string())
|
||||
.spawn(move || loop {
|
||||
std::thread::sleep(std::time::Duration::from_millis(100));
|
||||
|
||||
for ctrl in tasks.iter() {
|
||||
ctrl.do_task()
|
||||
.map_err(|err| {
|
||||
warn!("do_task error: {}", err);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
});
|
||||
|
||||
// Request dbus name after finishing initalizing all functions
|
||||
fdo_connection.request_name(DBUS_NAME, fdo::RequestNameFlags::ReplaceExisting.into())?;
|
||||
|
||||
// Loop to check errors and iterate zbus server
|
||||
loop {
|
||||
if let Err(err) = &handle {
|
||||
error!("{}", err);
|
||||
}
|
||||
if let Err(err) = object_server.try_handle_next() {
|
||||
error!("{}", err);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ pub enum RogError {
|
||||
Modprobe(String),
|
||||
Io(std::io::Error),
|
||||
Zbus(zbus::Error),
|
||||
ChargeLimit(u8),
|
||||
}
|
||||
|
||||
impl fmt::Display for RogError {
|
||||
@@ -46,6 +47,7 @@ impl fmt::Display for RogError {
|
||||
RogError::Modprobe(detail) => write!(f, "Modprobe error: {}", detail),
|
||||
RogError::Io(detail) => write!(f, "std::io error: {}", detail),
|
||||
RogError::Zbus(detail) => write!(f, "Zbus error: {}", detail),
|
||||
RogError::ChargeLimit(value) => write!(f, "Invalid charging limit, not in range 20-100%: {}", value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ pub mod laptops;
|
||||
/// Fetch all supported functions for the laptop
|
||||
pub mod ctrl_supported;
|
||||
|
||||
mod error;
|
||||
pub mod error;
|
||||
|
||||
use crate::error::RogError;
|
||||
use config::Config;
|
||||
|
||||
@@ -42,14 +42,14 @@ per_key = false
|
||||
|
||||
[[led_data]]
|
||||
prod_family = "ROG Strix"
|
||||
board_names = ["G531GW", "G533QR", "G733QS", "G733QR"]
|
||||
board_names = ["G531GW", "G533QR", "G533QS", "G733QS", "G733QR", "G513QR", "G713QR"]
|
||||
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Star", "Rain", "Highlight", "Laser", "Ripple", "Pulse", "Comet", "Flash"]
|
||||
multizone = false
|
||||
per_key = true
|
||||
|
||||
[[led_data]]
|
||||
prod_family = "ROG Strix"
|
||||
board_names = ["GX531", "G512LV", "G712LV", "G712LW", "G513IH", "G513QY"]
|
||||
board_names = ["GX531", "G512LV", "G712LV", "G712LW", "G513IH", "G513QY", "G713QM"]
|
||||
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Pulse"]
|
||||
multizone = true
|
||||
per_key = false
|
||||
@@ -123,4 +123,11 @@ prod_family = "ROG Zephyrus Duo 15 SE"
|
||||
board_names = ["GX551Q"]
|
||||
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Pulse"]
|
||||
multizone = false
|
||||
per_key = true
|
||||
per_key = true
|
||||
|
||||
[[led_data]]
|
||||
prod_family = "ROG Flow X13"
|
||||
board_names = ["GV301QH", "GV301QE"]
|
||||
standard = ["Static", "Breathe", "Pulse"]
|
||||
multizone = false
|
||||
per_key = false
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "rog_anime"
|
||||
version = "1.1.0"
|
||||
version = "1.3.0"
|
||||
license = "MPL-2.0"
|
||||
readme = "README.md"
|
||||
authors = ["Luke <luke@ljones.dev>"]
|
||||
|
||||
@@ -88,7 +88,7 @@ pub struct AnimeGif(Vec<AnimeFrame>, AnimTime);
|
||||
impl AnimeGif {
|
||||
/// Create an animation using the 74x36 ASUS gif format
|
||||
#[inline]
|
||||
pub fn create_diagonal_gif(
|
||||
pub fn from_diagonal_gif(
|
||||
file_name: &Path,
|
||||
duration: AnimTime,
|
||||
brightness: f32,
|
||||
@@ -130,7 +130,7 @@ impl AnimeGif {
|
||||
|
||||
/// Create an animation using the 74x36 ASUS gif format from a png
|
||||
#[inline]
|
||||
pub fn create_diagonal_png(
|
||||
pub fn from_diagonal_png(
|
||||
file_name: &Path,
|
||||
duration: AnimTime,
|
||||
brightness: f32,
|
||||
@@ -159,7 +159,7 @@ impl AnimeGif {
|
||||
/// Create an animation using a gif of any size. This method must precompute the
|
||||
/// result.
|
||||
#[inline]
|
||||
pub fn create_png_gif(
|
||||
pub fn from_gif(
|
||||
file_name: &Path,
|
||||
scale: f32,
|
||||
angle: f32,
|
||||
@@ -231,7 +231,7 @@ impl AnimeGif {
|
||||
/// will be 1 second long. If `AnimTime::Cycles` is specified for `duration` then this can
|
||||
/// be considered how many seconds the image will show for.
|
||||
#[inline]
|
||||
pub fn create_png_static(
|
||||
pub fn from_png(
|
||||
file_name: &Path,
|
||||
scale: f32,
|
||||
angle: f32,
|
||||
|
||||
@@ -69,7 +69,7 @@ impl ActionData {
|
||||
file,
|
||||
time,
|
||||
brightness,
|
||||
} => ActionData::Animation(AnimeGif::create_diagonal_gif(file, *time, *brightness)?),
|
||||
} => ActionData::Animation(AnimeGif::from_diagonal_gif(file, *time, *brightness)?),
|
||||
ActionLoader::AsusImage {
|
||||
file,
|
||||
time,
|
||||
@@ -80,9 +80,7 @@ impl ActionData {
|
||||
let data = <AnimeDataBuffer>::from(&image);
|
||||
ActionData::Image(Box::new(data))
|
||||
}
|
||||
_ => {
|
||||
ActionData::Animation(AnimeGif::create_diagonal_png(file, *time, *brightness)?)
|
||||
}
|
||||
_ => ActionData::Animation(AnimeGif::from_diagonal_png(file, *time, *brightness)?),
|
||||
},
|
||||
ActionLoader::ImageAnimation {
|
||||
file,
|
||||
@@ -94,7 +92,7 @@ impl ActionData {
|
||||
} => {
|
||||
if let Some(ext) = file.extension() {
|
||||
if ext.to_string_lossy().to_lowercase() == "png" {
|
||||
return Ok(ActionData::Animation(AnimeGif::create_png_static(
|
||||
return Ok(ActionData::Animation(AnimeGif::from_png(
|
||||
file,
|
||||
*scale,
|
||||
*angle,
|
||||
@@ -104,7 +102,7 @@ impl ActionData {
|
||||
)?));
|
||||
}
|
||||
}
|
||||
ActionData::Animation(AnimeGif::create_png_gif(
|
||||
ActionData::Animation(AnimeGif::from_gif(
|
||||
file,
|
||||
*scale,
|
||||
*angle,
|
||||
@@ -129,7 +127,7 @@ impl ActionData {
|
||||
let data = <AnimeDataBuffer>::from(&image);
|
||||
ActionData::Image(Box::new(data))
|
||||
}
|
||||
_ => ActionData::Animation(AnimeGif::create_png_static(
|
||||
_ => ActionData::Animation(AnimeGif::from_png(
|
||||
file,
|
||||
*scale,
|
||||
*angle,
|
||||
|
||||
+1
-2
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "rog_dbus"
|
||||
version = "4.0.0"
|
||||
version = "4.0.2"
|
||||
license = "MPL-2.0"
|
||||
readme = "README.md"
|
||||
authors = ["Luke <luke@ljones.dev>"]
|
||||
@@ -14,7 +14,6 @@ rog_anime = { path = "../rog-anime" }
|
||||
rog_aura = { path = "../rog-aura" }
|
||||
rog_profiles = { path = "../rog-profiles" }
|
||||
rog_supported = { path = "../rog-supported" }
|
||||
supergfxctl = { git = "https://gitlab.com/asus-linux/supergfxctl.git", tag = "2.0.0" }
|
||||
zbus = "^1.9"
|
||||
zbus_macros = "^1.9"
|
||||
zvariant = "^2.8"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
pub static DBUS_NAME: &str = "org.asuslinux.Daemon";
|
||||
pub static DBUS_NAME_GFX: &str = "org.supergfxctl.Daemon";
|
||||
pub static DBUS_PATH: &str = "/org/asuslinux/Daemon";
|
||||
pub static DBUS_IFACE: &str = "org.asuslinux.Daemon";
|
||||
|
||||
|
||||
@@ -45,18 +45,23 @@ impl<'a> AnimeProxy<'a> {
|
||||
&self.0
|
||||
}
|
||||
|
||||
/// Set whether the AniMe will show boot, suspend, or off animations
|
||||
#[inline]
|
||||
pub fn set_system_animations(&self, on: bool) -> Result<()> {
|
||||
self.0.set_boot_on_off(on)
|
||||
}
|
||||
|
||||
/// Set whether the AniMe is displaying images/data
|
||||
#[inline]
|
||||
pub fn set_led_power(&self, on: bool) -> Result<()> {
|
||||
pub fn set_on_off(&self, on: bool) -> Result<()> {
|
||||
self.0.set_on_off(on)
|
||||
}
|
||||
|
||||
/// Set the global AniMe brightness
|
||||
pub fn set_brightness(&self, bright: f32) -> Result<()> {
|
||||
self.0.set_brightness(bright)
|
||||
}
|
||||
|
||||
/// Set whether the AniMe will show boot, suspend, or off animations
|
||||
#[inline]
|
||||
pub fn set_boot_on_off(&self, on: bool) -> Result<()> {
|
||||
self.0.set_boot_on_off(on)
|
||||
}
|
||||
|
||||
/// Writes a data stream of length. Will force system thread to exit until it is restarted
|
||||
#[inline]
|
||||
pub fn write(&self, input: AnimeDataBuffer) -> Result<()> {
|
||||
|
||||
@@ -21,7 +21,10 @@
|
||||
|
||||
use std::sync::mpsc::Sender;
|
||||
|
||||
use rog_profiles::{fan_curve_set::FanCurveSet, Profile};
|
||||
use rog_profiles::{
|
||||
fan_curve_set::{CurveData, FanCurveSet},
|
||||
Profile,
|
||||
};
|
||||
use zbus::{dbus_proxy, Connection, Result};
|
||||
|
||||
#[dbus_proxy(
|
||||
@@ -29,29 +32,37 @@ use zbus::{dbus_proxy, Connection, Result};
|
||||
default_path = "/org/asuslinux/Profile"
|
||||
)]
|
||||
trait Daemon {
|
||||
/// Get the active `Profile` data
|
||||
fn active_fan_curve_data(&self) -> zbus::Result<FanCurveSet>;
|
||||
/// Get the fan-curve data for the currently active Profile
|
||||
fn fan_curve_data(&self, profile: Profile) -> zbus::Result<FanCurveSet>;
|
||||
|
||||
/// Profile, get the active profile
|
||||
/// Fetch the active profile name
|
||||
fn active_profile(&self) -> zbus::Result<Profile>;
|
||||
|
||||
/// Get enabled fan curves
|
||||
/// Get a list of profiles that have fan-curves enabled.
|
||||
fn enabled_fan_profiles(&self) -> zbus::Result<Vec<Profile>>;
|
||||
|
||||
/// Get all fan curve data
|
||||
fn fan_curves(&self) -> zbus::Result<Vec<FanCurveSet>>;
|
||||
|
||||
/// NextProfile method
|
||||
/// Toggle to next platform_profile. Names provided by `Profiles`.
|
||||
/// If fan-curves are supported will also activate a fan curve for profile.
|
||||
fn next_profile(&self) -> zbus::Result<()>;
|
||||
|
||||
/// Profiles method
|
||||
/// Fetch profile names
|
||||
fn profiles(&self) -> zbus::Result<Vec<Profile>>;
|
||||
|
||||
/// Set the specific profile as active
|
||||
/// Set this platform_profile name as active
|
||||
fn set_active_profile(&self, profile: Profile) -> zbus::Result<()>;
|
||||
|
||||
/// Set a fan curve. If a field is empty then the exisiting saved curve is used
|
||||
fn set_fan_curve(&self, curve: FanCurveSet) -> zbus::Result<()>;
|
||||
/// Set a profile fan curve enabled status. Will also activate a fan curve.
|
||||
fn set_fan_curve_enabled(&self, profile: Profile, enabled: bool) -> zbus::Result<()>;
|
||||
|
||||
/// Set the fan curve for the specified profile, or the profile the user is
|
||||
/// currently in if profile == None. Will also activate the fan curve.
|
||||
fn set_fan_curve(&self, profile: Profile, curve: CurveData) -> zbus::Result<()>;
|
||||
|
||||
/// Reset the stored (self) and device curve to the defaults of the platform.
|
||||
///
|
||||
/// Each platform_profile has a different default and the defualt can be read
|
||||
/// only for the currently active profile.
|
||||
fn set_active_curve_to_defaults(&self) -> zbus::Result<()>;
|
||||
|
||||
/// NotifyProfile signal
|
||||
#[dbus_proxy(signal)]
|
||||
@@ -72,8 +83,18 @@ impl<'a> ProfileProxy<'a> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn profiles(&self) -> Result<Vec<Profile>> {
|
||||
self.0.profiles()
|
||||
pub fn active_profile(&self) -> zbus::Result<Profile> {
|
||||
self.0.active_profile()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn enabled_fan_profiles(&self) -> zbus::Result<Vec<Profile>> {
|
||||
self.0.enabled_fan_profiles()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn fan_curve_data(&self, profile: Profile) -> zbus::Result<FanCurveSet> {
|
||||
self.0.fan_curve_data(profile)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -81,6 +102,31 @@ impl<'a> ProfileProxy<'a> {
|
||||
self.0.next_profile()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn profiles(&self) -> Result<Vec<Profile>> {
|
||||
self.0.profiles()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_active_profile(&self, profile: Profile) -> zbus::Result<()> {
|
||||
self.0.set_active_profile(profile)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_fan_curve_enabled(&self, profile: Profile, enabled: bool) -> zbus::Result<()> {
|
||||
self.0.set_fan_curve_enabled(profile, enabled)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_fan_curve(&self, curve: CurveData, profile: Profile) -> zbus::Result<()> {
|
||||
self.0.set_fan_curve(profile, curve)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_active_curve_to_defaults(&self) -> zbus::Result<()> {
|
||||
self.0.set_active_curve_to_defaults()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn connect_notify_profile(&self, send: Sender<Profile>) -> zbus::fdo::Result<()> {
|
||||
self.0.connect_notify_profile(move |data| {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "rog_profiles"
|
||||
version = "1.0.1"
|
||||
version = "1.1.3"
|
||||
authors = ["Luke D. Jones <luke@ljones.dev>"]
|
||||
edition = "2018"
|
||||
|
||||
|
||||
@@ -8,7 +8,12 @@ pub enum ProfileError {
|
||||
NotSupported,
|
||||
NotFound(String),
|
||||
Io(std::io::Error),
|
||||
//Zbus(zbus::Error),
|
||||
ParseProfileName,
|
||||
ParseFanCurveDigit(std::num::ParseIntError),
|
||||
/// (pwm/temp, prev, next)
|
||||
ParseFanCurvePrevHigher(&'static str, u8, u8),
|
||||
ParseFanCurvePercentOver100(u8),
|
||||
// Zbus(zbus::Error),
|
||||
}
|
||||
|
||||
impl fmt::Display for ProfileError {
|
||||
@@ -21,7 +26,18 @@ impl fmt::Display for ProfileError {
|
||||
ProfileError::NotSupported => write!(f, "Not supported"),
|
||||
ProfileError::NotFound(deets) => write!(f, "Not found: {}", deets),
|
||||
ProfileError::Io(detail) => write!(f, "std::io error: {}", detail),
|
||||
//Error::Zbus(detail) => write!(f, "Zbus error: {}", detail),
|
||||
ProfileError::ParseProfileName => write!(f, "Invalid profile name"),
|
||||
ProfileError::ParseFanCurveDigit(e) => {
|
||||
write!(f, "Could not parse number to 0-255: {}", e)
|
||||
}
|
||||
ProfileError::ParseFanCurvePrevHigher(part, prev, next) => write!(
|
||||
f,
|
||||
"Invalid {}, previous value {} is higher than next value {}",
|
||||
part, prev, next
|
||||
),
|
||||
ProfileError::ParseFanCurvePercentOver100(value) => {
|
||||
write!(f, "Invalid percentage, {} is higher than 100", value)
|
||||
} // Error::Zbus(detail) => write!(f, "Zbus error: {}", detail),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,24 +4,24 @@ use udev::Device;
|
||||
#[cfg(feature = "dbus")]
|
||||
use zvariant_derive::Type;
|
||||
|
||||
use crate::{error::ProfileError, write_to_fan, FanCurvePU};
|
||||
use crate::{error::ProfileError, FanCurvePU};
|
||||
|
||||
pub fn pwm_str(fan: char, index: char) -> String {
|
||||
pub(crate) fn pwm_str(fan: char, index: usize) -> String {
|
||||
let mut buf = "pwm1_auto_point1_pwm".to_string();
|
||||
unsafe {
|
||||
let tmp = buf.as_bytes_mut();
|
||||
tmp[3] = fan as u8;
|
||||
tmp[15] = index as u8;
|
||||
tmp[15] = char::from_digit(index as u32 + 1, 10).unwrap() as u8;
|
||||
}
|
||||
buf
|
||||
}
|
||||
|
||||
pub fn temp_str(fan: char, index: char) -> String {
|
||||
pub(crate) fn temp_str(fan: char, index: usize) -> String {
|
||||
let mut buf = "pwm1_auto_point1_temp".to_string();
|
||||
unsafe {
|
||||
let tmp = buf.as_bytes_mut();
|
||||
tmp[3] = fan as u8;
|
||||
tmp[15] = index as u8;
|
||||
tmp[15] = char::from_digit(index as u32 + 1, 10).unwrap() as u8;
|
||||
}
|
||||
buf
|
||||
}
|
||||
@@ -29,22 +29,152 @@ pub fn temp_str(fan: char, index: char) -> String {
|
||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||
#[derive(Deserialize, Serialize, Default, Debug, Clone)]
|
||||
pub struct CurveData {
|
||||
pub fan: FanCurvePU,
|
||||
pub pwm: [u8; 8],
|
||||
pub temp: [u8; 8],
|
||||
pub(crate) fan: FanCurvePU,
|
||||
pub(crate) pwm: [u8; 8],
|
||||
pub(crate) temp: [u8; 8],
|
||||
}
|
||||
|
||||
impl std::str::FromStr for CurveData {
|
||||
type Err = ProfileError;
|
||||
|
||||
/// Parse a string to the correct values that the fan curve kernel driver expects
|
||||
///
|
||||
/// If the fan curve is given with percentage char '%' then the fan power values are converted
|
||||
/// otherwise the expected fan power range is 0-255.
|
||||
///
|
||||
/// Temperature range is 0-255 in degrees C. You don't want to be setting over 100.
|
||||
fn from_str(input: &str) -> Result<Self, Self::Err> {
|
||||
let mut temp = [0u8; 8];
|
||||
let mut pwm = [0u8; 8];
|
||||
let mut temp_prev = 0;
|
||||
let mut pwm_prev = 0;
|
||||
let mut percentages = false;
|
||||
|
||||
for (index, value) in input.split(',').enumerate() {
|
||||
for (select, num) in value.splitn(2, |c| c == 'c' || c == ':').enumerate() {
|
||||
if num.contains('%') {
|
||||
percentages = true;
|
||||
}
|
||||
let r = num.trim_matches(|c| c == 'c' || c == ':' || c == '%');
|
||||
let r = r.parse::<u8>().map_err(ProfileError::ParseFanCurveDigit)?;
|
||||
|
||||
if select == 0 {
|
||||
if temp_prev > r {
|
||||
return Err(ProfileError::ParseFanCurvePrevHigher(
|
||||
"temperature",
|
||||
temp_prev,
|
||||
r,
|
||||
));
|
||||
}
|
||||
temp_prev = r;
|
||||
temp[index] = r;
|
||||
} else {
|
||||
let mut p = r;
|
||||
if percentages {
|
||||
p *= 255 / 100;
|
||||
if p > 100 {
|
||||
return Err(ProfileError::ParseFanCurvePercentOver100(r));
|
||||
}
|
||||
}
|
||||
if pwm_prev > p {
|
||||
return Err(ProfileError::ParseFanCurvePrevHigher(
|
||||
"percentage",
|
||||
pwm_prev,
|
||||
p,
|
||||
));
|
||||
}
|
||||
pwm_prev = p;
|
||||
pwm[index] = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(Self {
|
||||
fan: FanCurvePU::CPU,
|
||||
pwm,
|
||||
temp,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl CurveData {
|
||||
pub fn set_fan(&mut self, fan: FanCurvePU) {
|
||||
self.fan = fan;
|
||||
}
|
||||
|
||||
fn set_val_from_attr(tmp: &str, device: &Device, buf: &mut [u8; 8]) {
|
||||
if let Some(n) = tmp.chars().nth(15) {
|
||||
let i = n.to_digit(10).unwrap() as usize;
|
||||
let d = device.attribute_value(tmp).unwrap();
|
||||
let d: u8 = d.to_string_lossy().parse().unwrap();
|
||||
buf[i - 1] = d;
|
||||
}
|
||||
}
|
||||
|
||||
fn read_from_device(&mut self, device: &Device) {
|
||||
for attr in device.attributes() {
|
||||
let tmp = attr.name().to_string_lossy();
|
||||
if tmp.starts_with("pwm1") && tmp.ends_with("_temp") {
|
||||
Self::set_val_from_attr(tmp.as_ref(), device, &mut self.temp)
|
||||
}
|
||||
if tmp.starts_with("pwm1") && tmp.ends_with("_pwm") {
|
||||
Self::set_val_from_attr(tmp.as_ref(), device, &mut self.pwm)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn init_if_zeroed(&mut self, device: &mut Device) -> std::io::Result<()> {
|
||||
if self.pwm == [0u8; 8] && self.temp == [0u8; 8] {
|
||||
// Need to reset the device to defaults to get the proper profile defaults
|
||||
match self.fan {
|
||||
FanCurvePU::CPU => device.set_attribute_value("pwm1_enable", "3")?,
|
||||
FanCurvePU::GPU => device.set_attribute_value("pwm2_enable", "3")?,
|
||||
};
|
||||
self.read_from_device(device);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Write this curve to the device fan specified by `self.fan`
|
||||
fn write_to_device(&self, device: &mut Device, enable: bool) -> std::io::Result<()> {
|
||||
let pwm_num = match self.fan {
|
||||
FanCurvePU::CPU => '1',
|
||||
FanCurvePU::GPU => '2',
|
||||
};
|
||||
let enable = if enable { "1" } else { "2" };
|
||||
|
||||
for (index, out) in self.pwm.iter().enumerate() {
|
||||
let pwm = pwm_str(pwm_num, index);
|
||||
device.set_attribute_value(&pwm, &out.to_string())?;
|
||||
}
|
||||
|
||||
for (index, out) in self.temp.iter().enumerate() {
|
||||
let temp = temp_str(pwm_num, index);
|
||||
device.set_attribute_value(&temp, &out.to_string())?;
|
||||
}
|
||||
|
||||
// Enable must be done *after* all points are written
|
||||
match self.fan {
|
||||
FanCurvePU::CPU => device.set_attribute_value("pwm1_enable", enable)?,
|
||||
FanCurvePU::GPU => device.set_attribute_value("pwm2_enable", enable)?,
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// A `FanCurveSet` contains both CPU and GPU fan curve data
|
||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||
pub struct FanCurveSet {
|
||||
pub cpu: CurveData,
|
||||
pub gpu: CurveData,
|
||||
pub(crate) enabled: bool,
|
||||
pub(crate) cpu: CurveData,
|
||||
pub(crate) gpu: CurveData,
|
||||
}
|
||||
|
||||
impl Default for FanCurveSet {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
enabled: false,
|
||||
cpu: CurveData {
|
||||
fan: FanCurvePU::CPU,
|
||||
pwm: [0u8; 8],
|
||||
@@ -60,80 +190,71 @@ impl Default for FanCurveSet {
|
||||
}
|
||||
|
||||
impl FanCurveSet {
|
||||
pub fn get_device() -> Result<Device, ProfileError> {
|
||||
let mut enumerator = udev::Enumerator::new()?;
|
||||
enumerator.match_subsystem("hwmon")?;
|
||||
|
||||
for device in enumerator.scan_devices().unwrap() {
|
||||
if device.parent_with_subsystem("platform").unwrap().is_some() {
|
||||
if let Some(name) = device.attribute_value("name") {
|
||||
if name == "asus_custom_fan_curve" {
|
||||
return Ok(device);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(ProfileError::NotSupported)
|
||||
pub(crate) fn read_cpu_from_device(&mut self, device: &Device) {
|
||||
self.cpu.read_from_device(device);
|
||||
}
|
||||
|
||||
pub fn is_supported() -> Result<bool, ProfileError> {
|
||||
if Self::get_device().is_ok() {
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
Ok(false)
|
||||
pub(crate) fn read_gpu_from_device(&mut self, device: &Device) {
|
||||
self.gpu.read_from_device(device);
|
||||
}
|
||||
|
||||
pub fn new() -> Result<(Self, Device), ProfileError> {
|
||||
if let Ok(device) = Self::get_device() {
|
||||
let mut fans = Self {
|
||||
cpu: CurveData::default(),
|
||||
gpu: CurveData::default(),
|
||||
};
|
||||
|
||||
fans.cpu.fan = FanCurvePU::CPU;
|
||||
fans.cpu.fan = FanCurvePU::GPU;
|
||||
|
||||
fans.read_from_device(&device);
|
||||
|
||||
return Ok((fans, device));
|
||||
}
|
||||
|
||||
Err(ProfileError::NotSupported)
|
||||
pub(crate) fn write_cpu_fan(&mut self, device: &mut Device) -> std::io::Result<()> {
|
||||
self.cpu.init_if_zeroed(device)?;
|
||||
self.cpu.write_to_device(device, self.enabled)
|
||||
}
|
||||
|
||||
fn set_val_from_attr(tmp: &str, device: &Device, buf: &mut [u8; 8]) {
|
||||
if let Some(n) = tmp.chars().nth(15) {
|
||||
let i = n.to_digit(10).unwrap() as usize;
|
||||
let d = device.attribute_value(tmp).unwrap();
|
||||
let d: u8 = d.to_string_lossy().parse().unwrap();
|
||||
buf[i - 1] = d;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_from_device(&mut self, device: &Device) {
|
||||
for attr in device.attributes() {
|
||||
let tmp = attr.name().to_string_lossy();
|
||||
if tmp.starts_with("pwm1") && tmp.ends_with("_temp") {
|
||||
Self::set_val_from_attr(tmp.as_ref(), device, &mut self.cpu.temp)
|
||||
}
|
||||
if tmp.starts_with("pwm1") && tmp.ends_with("_pwm") {
|
||||
Self::set_val_from_attr(tmp.as_ref(), device, &mut self.cpu.pwm)
|
||||
}
|
||||
if tmp.starts_with("pwm2") && tmp.ends_with("_temp") {
|
||||
Self::set_val_from_attr(tmp.as_ref(), device, &mut self.gpu.temp)
|
||||
}
|
||||
if tmp.starts_with("pwm2") && tmp.ends_with("_pwm") {
|
||||
Self::set_val_from_attr(tmp.as_ref(), device, &mut self.gpu.pwm)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_cpu_fan(&self, device: &mut Device) {
|
||||
write_to_fan(&self.cpu, '1', device);
|
||||
}
|
||||
|
||||
pub fn write_gpu_fan(&self, device: &mut Device) {
|
||||
write_to_fan(&self.gpu, '2', device);
|
||||
pub(crate) fn write_gpu_fan(&mut self, device: &mut Device) -> std::io::Result<()> {
|
||||
self.gpu.init_if_zeroed(device)?;
|
||||
self.gpu.write_to_device(device, self.enabled)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::str::FromStr;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn curve_data_from_str() {
|
||||
let curve =
|
||||
CurveData::from_str("30c:1%,49c:2%,59c:3%,69c:4%,79c:31%,89c:49%,99c:56%,109c:58%")
|
||||
.unwrap();
|
||||
assert_eq!(curve.fan, FanCurvePU::CPU);
|
||||
assert_eq!(curve.temp, [30, 49, 59, 69, 79, 89, 99, 109]);
|
||||
assert_eq!(curve.pwm, [1, 2, 3, 4, 31, 49, 56, 58]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn curve_data_from_str_simple() {
|
||||
let curve = CurveData::from_str("30:1,49:2,59:3,69:4,79:31,89:49,99:56,109:58").unwrap();
|
||||
assert_eq!(curve.fan, FanCurvePU::CPU);
|
||||
assert_eq!(curve.temp, [30, 49, 59, 69, 79, 89, 99, 109]);
|
||||
assert_eq!(curve.pwm, [1, 2, 3, 4, 31, 49, 56, 58]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn curve_data_from_str_invalid_pwm() {
|
||||
let curve =
|
||||
CurveData::from_str("30c:4%,49c:2%,59c:3%,69c:4%,79c:31%,89c:49%,99c:56%,109c:58%");
|
||||
assert!(&curve.is_err());
|
||||
assert!(matches!(
|
||||
curve,
|
||||
Err(ProfileError::ParseFanCurvePrevHigher(_, _, _))
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_pwm_str() {
|
||||
assert_eq!(pwm_str('1', 0), "pwm1_auto_point1_pwm");
|
||||
assert_eq!(pwm_str('1', 4), "pwm1_auto_point5_pwm");
|
||||
assert_eq!(pwm_str('1', 7), "pwm1_auto_point8_pwm");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_temp_str() {
|
||||
assert_eq!(temp_str('1', 0), "pwm1_auto_point1_temp");
|
||||
assert_eq!(temp_str('1', 4), "pwm1_auto_point5_temp");
|
||||
assert_eq!(temp_str('1', 7), "pwm1_auto_point8_temp");
|
||||
}
|
||||
}
|
||||
|
||||
+121
-70
@@ -38,7 +38,7 @@ pub fn find_fan_curve_node() -> Result<Option<Device>, ProfileError> {
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||
#[derive(Deserialize, Serialize, Debug, Clone, Copy)]
|
||||
#[derive(Deserialize, Serialize, Debug, PartialEq, Clone, Copy)]
|
||||
pub enum Profile {
|
||||
Balanced,
|
||||
Performance,
|
||||
@@ -51,10 +51,7 @@ impl Profile {
|
||||
}
|
||||
|
||||
pub fn get_active_profile() -> Result<Profile, ProfileError> {
|
||||
let mut file = OpenOptions::new()
|
||||
.read(true)
|
||||
.open(&PLATFORM_PROFILE)
|
||||
.unwrap_or_else(|_| panic!("{} not found", &PLATFORM_PROFILE));
|
||||
let mut file = OpenOptions::new().read(true).open(&PLATFORM_PROFILE)?;
|
||||
|
||||
let mut buf = String::new();
|
||||
file.read_to_string(&mut buf)?;
|
||||
@@ -62,10 +59,7 @@ impl Profile {
|
||||
}
|
||||
|
||||
pub fn get_profile_names() -> Result<Vec<Profile>, ProfileError> {
|
||||
let mut file = OpenOptions::new()
|
||||
.read(true)
|
||||
.open(&PLATFORM_PROFILES)
|
||||
.unwrap_or_else(|_| panic!("{} not found", &PLATFORM_PROFILES));
|
||||
let mut file = OpenOptions::new().read(true).open(&PLATFORM_PROFILES)?;
|
||||
|
||||
let mut buf = String::new();
|
||||
file.read_to_string(&mut buf)?;
|
||||
@@ -73,10 +67,7 @@ impl Profile {
|
||||
}
|
||||
|
||||
pub fn set_profile(profile: Profile) -> Result<(), ProfileError> {
|
||||
let mut file = OpenOptions::new()
|
||||
.write(true)
|
||||
.open(PLATFORM_PROFILE)
|
||||
.unwrap_or_else(|_| panic!("{} not found", PLATFORM_PROFILE));
|
||||
let mut file = OpenOptions::new().write(true).open(PLATFORM_PROFILE)?;
|
||||
|
||||
file.write_all(<&str>::from(profile).as_bytes())?;
|
||||
Ok(())
|
||||
@@ -110,8 +101,21 @@ impl From<&str> for Profile {
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for Profile {
|
||||
type Err = ProfileError;
|
||||
|
||||
fn from_str(profile: &str) -> Result<Self, Self::Err> {
|
||||
match profile.to_ascii_lowercase().trim() {
|
||||
"balanced" => Ok(Profile::Balanced),
|
||||
"performance" => Ok(Profile::Performance),
|
||||
"quiet" => Ok(Profile::Quiet),
|
||||
_ => Err(ProfileError::ParseProfileName),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||
#[derive(Deserialize, Serialize, Debug, Clone, Copy)]
|
||||
#[derive(Deserialize, Serialize, Debug, PartialEq, Clone, Copy)]
|
||||
pub enum FanCurvePU {
|
||||
CPU,
|
||||
GPU,
|
||||
@@ -126,27 +130,63 @@ impl From<FanCurvePU> for &str {
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for FanCurvePU {
|
||||
type Err = ProfileError;
|
||||
|
||||
fn from_str(fan: &str) -> Result<Self, Self::Err> {
|
||||
match fan.to_ascii_lowercase().trim() {
|
||||
"cpu" => Ok(FanCurvePU::CPU),
|
||||
"gpu" => Ok(FanCurvePU::GPU),
|
||||
_ => Err(ProfileError::ParseProfileName),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for FanCurvePU {
|
||||
fn default() -> Self {
|
||||
Self::CPU
|
||||
}
|
||||
}
|
||||
|
||||
/// Main purpose of `FanCurves` is to enable retoring state on system boot
|
||||
/// Main purpose of `FanCurves` is to enable restoring state on system boot
|
||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||
#[derive(Deserialize, Serialize, Debug, Default)]
|
||||
pub struct FanCurveProfiles {
|
||||
enabled: Vec<Profile>,
|
||||
balanced: FanCurveSet,
|
||||
performance: FanCurveSet,
|
||||
quiet: FanCurveSet,
|
||||
}
|
||||
|
||||
impl FanCurveProfiles {
|
||||
pub fn get_device() -> Result<Device, ProfileError> {
|
||||
let mut enumerator = udev::Enumerator::new()?;
|
||||
enumerator.match_subsystem("hwmon")?;
|
||||
|
||||
for device in enumerator.scan_devices()? {
|
||||
if device.parent_with_subsystem("platform")?.is_some() {
|
||||
if let Some(name) = device.attribute_value("name") {
|
||||
if name == "asus_custom_fan_curve" {
|
||||
return Ok(device);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(ProfileError::NotSupported)
|
||||
}
|
||||
|
||||
pub fn is_supported() -> Result<bool, ProfileError> {
|
||||
if Self::get_device().is_ok() {
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
///
|
||||
pub fn read_from_dev_profile(&mut self, profile: Profile, device: &Device) {
|
||||
let mut tmp = FanCurveSet::default();
|
||||
tmp.read_from_device(device);
|
||||
tmp.read_cpu_from_device(device);
|
||||
tmp.read_gpu_from_device(device);
|
||||
match profile {
|
||||
Profile::Balanced => self.balanced = tmp,
|
||||
Profile::Performance => self.performance = tmp,
|
||||
@@ -154,22 +194,69 @@ impl FanCurveProfiles {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_to_platform(&self, profile: Profile, device: &mut Device) {
|
||||
/// Reset the stored (self) and device curve to the defaults of the platform.
|
||||
///
|
||||
/// Each platform_profile has a different default and the defualt can be read
|
||||
/// only for the currently active profile.
|
||||
pub fn set_active_curve_to_defaults(
|
||||
&mut self,
|
||||
profile: Profile,
|
||||
device: &mut Device,
|
||||
) -> std::io::Result<()> {
|
||||
// Do reset
|
||||
device.set_attribute_value("pwm1_enable", "3")?;
|
||||
device.set_attribute_value("pwm2_enable", "3")?;
|
||||
// Then read
|
||||
let mut tmp = FanCurveSet::default();
|
||||
tmp.read_cpu_from_device(device);
|
||||
tmp.read_gpu_from_device(device);
|
||||
match profile {
|
||||
Profile::Balanced => self.balanced = tmp,
|
||||
Profile::Performance => self.performance = tmp,
|
||||
Profile::Quiet => self.quiet = tmp,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Write the curves for the selected profile to the device. If the curve is
|
||||
/// in the enabled list it will become active. If the curve is zeroed it will be initialised
|
||||
/// to a default read from the system.
|
||||
// TODO: Make this return an error if curve is zeroed
|
||||
pub fn write_profile_curve_to_platform(
|
||||
&mut self,
|
||||
profile: Profile,
|
||||
device: &mut Device,
|
||||
) -> std::io::Result<()> {
|
||||
let fans = match profile {
|
||||
Profile::Balanced => &self.balanced,
|
||||
Profile::Performance => &self.performance,
|
||||
Profile::Quiet => &self.quiet,
|
||||
Profile::Balanced => &mut self.balanced,
|
||||
Profile::Performance => &mut self.performance,
|
||||
Profile::Quiet => &mut self.quiet,
|
||||
};
|
||||
fans.write_cpu_fan(device);
|
||||
fans.write_gpu_fan(device);
|
||||
fans.write_cpu_fan(device)?;
|
||||
fans.write_gpu_fan(device)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_enabled_curve_profiles(&self) -> &[Profile] {
|
||||
&self.enabled
|
||||
pub fn get_enabled_curve_profiles(&self) -> Vec<Profile> {
|
||||
let mut tmp = Vec::new();
|
||||
if self.balanced.enabled {
|
||||
tmp.push(Profile::Balanced);
|
||||
}
|
||||
if self.performance.enabled {
|
||||
tmp.push(Profile::Performance);
|
||||
}
|
||||
if self.quiet.enabled {
|
||||
tmp.push(Profile::Quiet);
|
||||
}
|
||||
tmp
|
||||
}
|
||||
|
||||
pub fn set_enabled_curve_profiles(&mut self, profiles: Vec<Profile>) {
|
||||
self.enabled = profiles
|
||||
pub fn set_profile_curve_enabled(&mut self, profile: Profile, enabled: bool) {
|
||||
match profile {
|
||||
Profile::Balanced => self.balanced.enabled = enabled,
|
||||
Profile::Performance => self.performance.enabled = enabled,
|
||||
Profile::Quiet => self.quiet.enabled = enabled,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_all_fan_curves(&self) -> Vec<FanCurveSet> {
|
||||
@@ -180,11 +267,11 @@ impl FanCurveProfiles {
|
||||
]
|
||||
}
|
||||
|
||||
pub fn get_active_fan_curves(&self) -> &FanCurveSet {
|
||||
match Profile::get_active_profile().unwrap() {
|
||||
Profile::Balanced => &self.balanced,
|
||||
Profile::Performance => &self.performance,
|
||||
Profile::Quiet => &self.quiet,
|
||||
pub fn get_active_fan_curves(&self) -> Result<&FanCurveSet, ProfileError> {
|
||||
match Profile::get_active_profile()? {
|
||||
Profile::Balanced => Ok(&self.balanced),
|
||||
Profile::Performance => Ok(&self.performance),
|
||||
Profile::Quiet => Ok(&self.quiet),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,16 +300,7 @@ impl FanCurveProfiles {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_and_set_fan_curve(
|
||||
&mut self,
|
||||
curve: CurveData,
|
||||
profile: Profile,
|
||||
device: &mut Device,
|
||||
) {
|
||||
match curve.fan {
|
||||
FanCurvePU::CPU => write_to_fan(&curve, '1', device),
|
||||
FanCurvePU::GPU => write_to_fan(&curve, '2', device),
|
||||
}
|
||||
pub fn save_fan_curve(&mut self, curve: CurveData, profile: Profile) -> std::io::Result<()> {
|
||||
match profile {
|
||||
Profile::Balanced => match curve.fan {
|
||||
FanCurvePU::CPU => self.balanced.cpu = curve,
|
||||
@@ -237,33 +315,6 @@ impl FanCurveProfiles {
|
||||
FanCurvePU::GPU => self.quiet.gpu = curve,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_to_fan(curve: &CurveData, pwm_num: char, device: &mut Device) {
|
||||
let mut pwm = "pwmN_auto_pointN_pwm".to_string();
|
||||
|
||||
for (index, out) in curve.pwm.iter().enumerate() {
|
||||
unsafe {
|
||||
let buf = pwm.as_bytes_mut();
|
||||
buf[3] = pwm_num as u8;
|
||||
// Should be quite safe to unwrap as we're not going over 8
|
||||
buf[15] = char::from_digit(index as u32 + 1, 10).unwrap() as u8;
|
||||
}
|
||||
let out = out.to_string();
|
||||
device.set_attribute_value(&pwm, &out).unwrap();
|
||||
}
|
||||
|
||||
let mut pwm = "pwmN_auto_pointN_temp".to_string();
|
||||
|
||||
for (index, out) in curve.temp.iter().enumerate() {
|
||||
unsafe {
|
||||
let buf = pwm.as_bytes_mut();
|
||||
buf[3] = pwm_num as u8;
|
||||
// Should be quite safe to unwrap as we're not going over 8
|
||||
buf[15] = char::from_digit(index as u32 + 1, 10).unwrap() as u8;
|
||||
}
|
||||
let out = out.to_string();
|
||||
device.set_attribute_value(&pwm, &out).unwrap();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user