mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
Compare commits
61 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 301c532b65 | |||
| df7ae4d014 | |||
| 96ceef1bdb | |||
| bc72b93625 | |||
| 03b338bdfa | |||
| 7a51cd1c70 | |||
| 0449a4b06b | |||
| bc46fa2b1e | |||
| 759ddeb270 | |||
| 538e111e78 | |||
| 45ab568f7a | |||
| b32089843a | |||
| d960aacf4f | |||
| 1c48ab227d | |||
| 6528ec95c2 | |||
| 53ee6015d0 | |||
| ad150903af | |||
| c29afaf751 | |||
| cec4016862 | |||
| c697d94a00 | |||
| 35438e2e77 | |||
| 716b524d70 | |||
| cffd5672b2 | |||
| 82bb032336 | |||
| ae4f7f9949 | |||
| 875ff6d354 | |||
| 842fa48fac | |||
| 8a63dce85f | |||
| 01386599f4 | |||
| 4310b4b742 | |||
| 89f4dd6ec4 | |||
| 85e0b79fb9 | |||
| fba5f26f7e | |||
| 90b0fc434d | |||
| 6743d5bc78 | |||
| def0259d24 | |||
| a678f54f59 | |||
| ebe7e61355 | |||
| bda58c9695 | |||
| e335133bf8 | |||
| 47432524e1 | |||
| 707b3bcc2d | |||
| 60014b8a40 | |||
| 2e4ce27f6b | |||
| b8384c55c3 | |||
| dfe1f02101 | |||
| 7c2fb0be81 | |||
| b05f680650 | |||
| 2a9a436f9c | |||
| 0d6faf3fda | |||
| aede000218 | |||
| 176ab0a639 | |||
| 4efb2caa56 | |||
| 6f81f86483 | |||
| b64b8a38e4 | |||
| ff56170ac5 | |||
| 733f1f827e | |||
| ac903a05da | |||
| 838e6f789b | |||
| d462393e8b | |||
| e98cf8d50b |
@@ -6,6 +6,78 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
# [3.2.2] - 2021-03-23
|
||||||
|
### Changed
|
||||||
|
- Fix brightness control, again, for non-RGB keyboards
|
||||||
|
|
||||||
|
# [3.2.1] - 2021-03-21
|
||||||
|
### Changed
|
||||||
|
- Fix brightness control
|
||||||
|
- Large cleanup of code relating to LED controls
|
||||||
|
|
||||||
|
# [3.2.0] - 2021-03-21
|
||||||
|
### Changed
|
||||||
|
- Refactor keyboard LED handling
|
||||||
|
- Added --list for profiles (Thanks @aqez)
|
||||||
|
- Added --remove for profiles (Thanks @aqez)
|
||||||
|
- Added a graphics mode: vfio. This attaches Nvidia devices to vfio module.
|
||||||
|
### Broken
|
||||||
|
- Per-key LED modes, which need thinking about how to go ahead with for future
|
||||||
|
|
||||||
|
# [3.1.7] - 2021-03-11
|
||||||
|
### Changed
|
||||||
|
- Refactor many parts of daemon
|
||||||
|
- Switch out session monitoring to logind-zbus
|
||||||
|
|
||||||
|
# [3.1.6] - 2021-03-11
|
||||||
|
### Changed
|
||||||
|
- Graphics switching will now wait until all users logged out before switching
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Further tweaks to gfx switching
|
||||||
|
- More logging on gfx switching
|
||||||
|
- Filter bios help according to supported modes
|
||||||
|
- Prevent gfx mode switching if in dedicated/G-Sync mode
|
||||||
|
|
||||||
|
# [3.1.4] - 2021-03-10
|
||||||
|
### Changed
|
||||||
|
- Notify through dbus if user changes profile manually
|
||||||
|
- Better help on CLI, show help only for supported items
|
||||||
|
- Bugfix to gfx switcher
|
||||||
|
|
||||||
|
# [3.1.3] - 2021-03-10
|
||||||
|
### Changed
|
||||||
|
- Hotfix: gracefully handle removing modules in use caused by display-manager not
|
||||||
|
fully shutdown at the time of trying to remove modules. It will now retry every
|
||||||
|
250ms per module
|
||||||
|
|
||||||
|
# [3.1.2] - 2021-03-10
|
||||||
|
### Changed
|
||||||
|
- Test and create /etc/X11/xorg.conf.d/ if it doesn't exist
|
||||||
|
- Hotfix to better report module issues
|
||||||
|
|
||||||
|
# [3.1.1] - 2021-03-10
|
||||||
|
### Changed
|
||||||
|
- Add missing nvidia module nvidia_uvm to gfx ctrl list
|
||||||
|
|
||||||
|
# [3.1.0] - 2021-03-09
|
||||||
|
### Added
|
||||||
|
- GU502LU led-modes
|
||||||
|
### Changed
|
||||||
|
- Graphics switching is now rebootless, the daemon will now restart the
|
||||||
|
display-manager to switch modes instead. Caveats are:
|
||||||
|
+ There is no confirmation from the daemon, the program issuing the command
|
||||||
|
must confirm the request.
|
||||||
|
+ systemd only
|
||||||
|
- Laptops with dedicated Nvidia mode:
|
||||||
|
+ You still must reboot for the bios to switch modes
|
||||||
|
+ On boot if dedicated mode is active then asusd will update the required configs
|
||||||
|
to put display-manager in nvidia mode
|
||||||
|
|
||||||
|
# [3.0.0] - 2021-02-22
|
||||||
|
### Added
|
||||||
|
- G531GD led modes
|
||||||
|
|
||||||
# [3.0.0] - 2021-02-14
|
# [3.0.0] - 2021-02-14
|
||||||
### Changed
|
### Changed
|
||||||
- Write set+apply after each array in multizone
|
- Write set+apply after each array in multizone
|
||||||
|
|||||||
Generated
+273
-115
@@ -33,8 +33,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "asusctl"
|
name = "asusctl"
|
||||||
version = "3.0.0"
|
version = "3.1.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"daemon",
|
||||||
"gumdrop",
|
"gumdrop",
|
||||||
"rog_dbus",
|
"rog_dbus",
|
||||||
"rog_types",
|
"rog_types",
|
||||||
@@ -63,6 +64,15 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "async-lock"
|
||||||
|
version = "2.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1996609732bde4a9988bc42125f55f2af5f3c36370e27c778d5191a4a1b63bfb"
|
||||||
|
dependencies = [
|
||||||
|
"event-listener",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atty"
|
name = "atty"
|
||||||
version = "0.2.14"
|
version = "0.2.14"
|
||||||
@@ -117,9 +127,9 @@ checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.4.2"
|
version = "1.4.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b"
|
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cache-padded"
|
name = "cache-padded"
|
||||||
@@ -129,9 +139,9 @@ checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.66"
|
version = "1.0.67"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48"
|
checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
@@ -175,9 +185,9 @@ checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-utils"
|
name = "crossbeam-utils"
|
||||||
version = "0.8.1"
|
version = "0.8.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d"
|
checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
@@ -186,11 +196,12 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "daemon"
|
name = "daemon"
|
||||||
version = "3.0.0"
|
version = "3.2.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"intel-pstate",
|
"intel-pstate",
|
||||||
"log",
|
"log",
|
||||||
|
"logind-zbus",
|
||||||
"rog_dbus",
|
"rog_dbus",
|
||||||
"rog_fan_curve",
|
"rog_fan_curve",
|
||||||
"rog_types",
|
"rog_types",
|
||||||
@@ -201,7 +212,7 @@ dependencies = [
|
|||||||
"sysfs-class",
|
"sysfs-class",
|
||||||
"toml",
|
"toml",
|
||||||
"udev",
|
"udev",
|
||||||
"zbus",
|
"zbus 2.0.0-beta.3",
|
||||||
"zvariant",
|
"zvariant",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -212,8 +223,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
|
checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote 1.0.8",
|
"quote 1.0.9",
|
||||||
"syn 1.0.60",
|
"syn 1.0.64",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -244,15 +255,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "946ee94e3dbf58fdd324f9ce245c7b238d46a66f00e86a020b71996349e46cce"
|
checksum = "946ee94e3dbf58fdd324f9ce245c7b238d46a66f00e86a020b71996349e46cce"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote 1.0.8",
|
"quote 1.0.9",
|
||||||
"syn 1.0.60",
|
"syn 1.0.64",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "env_logger"
|
name = "env_logger"
|
||||||
version = "0.8.2"
|
version = "0.8.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f26ecb66b4bdca6c1409b40fb255eefc2bd4f6d135dab3c3124f80ffa2a9661e"
|
checksum = "17392a012ea30ef05a610aa97dfb49496e71c9f676b27879922ea5bdf60d9d3f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atty",
|
"atty",
|
||||||
"humantime",
|
"humantime",
|
||||||
@@ -269,12 +280,18 @@ checksum = "22deed3a8124cff5fa835713fa105621e43bbdc46690c3a6b68328a012d350d4"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-error",
|
"proc-macro-error",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote 1.0.8",
|
"quote 1.0.9",
|
||||||
"rustversion",
|
"rustversion",
|
||||||
"syn 1.0.60",
|
"syn 1.0.64",
|
||||||
"synstructure",
|
"synstructure",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "event-listener"
|
||||||
|
version = "2.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fastrand"
|
name = "fastrand"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
@@ -286,9 +303,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures"
|
name = "futures"
|
||||||
version = "0.3.12"
|
version = "0.3.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "da9052a1a50244d8d5aa9bf55cbc2fb6f357c86cc52e46c62ed390a7180cf150"
|
checksum = "7f55667319111d593ba876406af7c409c0ebb44dc4be6132a783ccf163ea14c1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
@@ -301,9 +318,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-channel"
|
name = "futures-channel"
|
||||||
version = "0.3.12"
|
version = "0.3.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f2d31b7ec7efab6eefc7c57233bb10b847986139d88cc2f5a02a1ae6871a1846"
|
checksum = "8c2dd2df839b57db9ab69c2c9d8f3e8c81984781937fe2807dc6dcf3b2ad2939"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-sink",
|
"futures-sink",
|
||||||
@@ -311,15 +328,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-core"
|
name = "futures-core"
|
||||||
version = "0.3.12"
|
version = "0.3.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "79e5145dde8da7d1b3892dad07a9c98fc04bc39892b1ecc9692cf53e2b780a65"
|
checksum = "15496a72fabf0e62bdc3df11a59a3787429221dd0710ba8ef163d6f7a9112c94"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-executor"
|
name = "futures-executor"
|
||||||
version = "0.3.12"
|
version = "0.3.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e9e59fdc009a4b3096bf94f740a0f2424c082521f20a9b08c5c07c48d90fd9b9"
|
checksum = "891a4b7b96d84d5940084b2a37632dd65deeae662c114ceaa2c879629c9c0ad1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-task",
|
"futures-task",
|
||||||
@@ -328,9 +345,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-io"
|
name = "futures-io"
|
||||||
version = "0.3.12"
|
version = "0.3.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "28be053525281ad8259d47e4de5de657b25e7bac113458555bb4b70bc6870500"
|
checksum = "d71c2c65c57704c32f5241c1223167c2c3294fd34ac020c807ddbe6db287ba59"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-lite"
|
name = "futures-lite"
|
||||||
@@ -349,36 +366,33 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-macro"
|
name = "futures-macro"
|
||||||
version = "0.3.12"
|
version = "0.3.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c287d25add322d9f9abdcdc5927ca398917996600182178774032e9f8258fedd"
|
checksum = "ea405816a5139fb39af82c2beb921d52143f556038378d6db21183a5c37fbfb7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-hack",
|
"proc-macro-hack",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote 1.0.8",
|
"quote 1.0.9",
|
||||||
"syn 1.0.60",
|
"syn 1.0.64",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-sink"
|
name = "futures-sink"
|
||||||
version = "0.3.12"
|
version = "0.3.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "caf5c69029bda2e743fddd0582d1083951d65cc9539aebf8812f36c3491342d6"
|
checksum = "85754d98985841b7d4f5e8e6fbfa4a4ac847916893ec511a2917ccd8525b8bb3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-task"
|
name = "futures-task"
|
||||||
version = "0.3.12"
|
version = "0.3.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "13de07eb8ea81ae445aca7b69f5f7bf15d7bf4912d8ca37d6645c77ae8a58d86"
|
checksum = "fa189ef211c15ee602667a6fcfe1c1fd9e07d42250d2156382820fba33c9df80"
|
||||||
dependencies = [
|
|
||||||
"once_cell",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-util"
|
name = "futures-util"
|
||||||
version = "0.3.12"
|
version = "0.3.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "632a8cd0f2a4b3fdea1657f08bde063848c3bd00f9bbf6e256b8be78802e624b"
|
checksum = "1812c7ab8aedf8d6f2701a43e1243acdbcc2b36ab26e2ad421eb99ac963d96d1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
@@ -405,6 +419,17 @@ dependencies = [
|
|||||||
"wasi 0.9.0+wasi-snapshot-preview1",
|
"wasi 0.9.0+wasi-snapshot-preview1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 1.0.0",
|
||||||
|
"libc",
|
||||||
|
"wasi 0.10.2+wasi-snapshot-preview1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gumdrop"
|
name = "gumdrop"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
@@ -421,8 +446,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "915ef07c710d84733522461de2a734d4d62a3fd39a4d4f404c2f385ef8618d05"
|
checksum = "915ef07c710d84733522461de2a734d4d62a3fd39a4d4f404c2f385ef8618d05"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote 1.0.8",
|
"quote 1.0.9",
|
||||||
"syn 1.0.60",
|
"syn 1.0.64",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -434,6 +459,12 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hex"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "humantime"
|
name = "humantime"
|
||||||
version = "2.1.0"
|
version = "2.1.0"
|
||||||
@@ -473,9 +504,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.85"
|
version = "0.2.90"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7ccac4b00700875e6a07c6cde370d44d32fa01c5a65cdd2fca6858c479d28bb3"
|
checksum = "ba4aede83fc3617411dc6993bc8c70919750c1c257c6ca6a502aed6e0e2394ae"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libudev-sys"
|
name = "libudev-sys"
|
||||||
@@ -508,6 +539,20 @@ dependencies = [
|
|||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "logind-zbus"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6671f6cf88b63e9d63009f4f6f8826fcc265c51a9977e4c7dc1263d743e0dfbb"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"zbus 2.0.0-beta.3",
|
||||||
|
"zbus_macros 2.0.0-beta.3",
|
||||||
|
"zvariant",
|
||||||
|
"zvariant_derive",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mac-notification-sys"
|
name = "mac-notification-sys"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
@@ -537,12 +582,12 @@ checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nb-connect"
|
name = "nb-connect"
|
||||||
version = "1.0.2"
|
version = "1.0.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8123a81538e457d44b933a02faf885d3fe8408806b23fa700e8f01c6c3a98998"
|
checksum = "670361df1bc2399ee1ff50406a0d422587dd3bb0da596e1978fe8e05dabddf4f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"winapi",
|
"socket2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -558,6 +603,18 @@ dependencies = [
|
|||||||
"void",
|
"void",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nix"
|
||||||
|
version = "0.19.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b2ccba0cfe4fdf15982d1674c69b1fd80bad427d293849982668dfe454bd61f2"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.2.1",
|
||||||
|
"cc",
|
||||||
|
"cfg-if 1.0.0",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nom"
|
name = "nom"
|
||||||
version = "5.1.2"
|
version = "5.1.2"
|
||||||
@@ -570,14 +627,14 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "notify-rust"
|
name = "notify-rust"
|
||||||
version = "4.2.2"
|
version = "4.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "95a3a5dd7b4b415b112ce0fae1988f3e6dee90a96918bf3950b5f2289b19a04b"
|
checksum = "00c16afe17474a42a59062f3409a63160c63d41985b25e9e613400685b839cb6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"mac-notification-sys",
|
"mac-notification-sys",
|
||||||
"serde",
|
"serde",
|
||||||
"winrt-notification",
|
"winrt-notification",
|
||||||
"zbus",
|
"zbus 1.8.0",
|
||||||
"zvariant",
|
"zvariant",
|
||||||
"zvariant_derive",
|
"zvariant_derive",
|
||||||
]
|
]
|
||||||
@@ -638,9 +695,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.5.2"
|
version = "1.7.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0"
|
checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking"
|
name = "parking"
|
||||||
@@ -650,9 +707,9 @@ checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project-lite"
|
name = "pin-project-lite"
|
||||||
version = "0.2.4"
|
version = "0.2.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "439697af366c49a6d0a010c56a0d97685bc140ce0d377b13a2ea2aa42d64a827"
|
checksum = "dc0e1f259c92177c30a4c9d177246edd0a3568b25756a977d0632cf8fa37e905"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-utils"
|
name = "pin-utils"
|
||||||
@@ -679,6 +736,12 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ppv-lite86"
|
||||||
|
version = "0.2.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-crate"
|
name = "proc-macro-crate"
|
||||||
version = "0.1.5"
|
version = "0.1.5"
|
||||||
@@ -696,8 +759,8 @@ checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-error-attr",
|
"proc-macro-error-attr",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote 1.0.8",
|
"quote 1.0.9",
|
||||||
"syn 1.0.60",
|
"syn 1.0.64",
|
||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -708,7 +771,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote 1.0.8",
|
"quote 1.0.9",
|
||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -741,13 +804,53 @@ checksum = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.8"
|
version = "1.0.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df"
|
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.8.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"rand_chacha",
|
||||||
|
"rand_core",
|
||||||
|
"rand_hc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_chacha"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
|
||||||
|
dependencies = [
|
||||||
|
"ppv-lite86",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.6.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom 0.2.2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_hc"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.1.57"
|
version = "0.1.57"
|
||||||
@@ -760,28 +863,27 @@ version = "0.3.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d"
|
checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom",
|
"getrandom 0.1.16",
|
||||||
"redox_syscall",
|
"redox_syscall",
|
||||||
"rust-argon2",
|
"rust-argon2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.4.3"
|
version = "1.4.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a"
|
checksum = "957056ecddbeba1b26965114e191d2e8589ce74db242b6ea25fc4062427a5c19"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
"regex-syntax",
|
"regex-syntax",
|
||||||
"thread_local",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-syntax"
|
name = "regex-syntax"
|
||||||
version = "0.6.22"
|
version = "0.6.23"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581"
|
checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rog_dbus"
|
name = "rog_dbus"
|
||||||
@@ -790,23 +892,23 @@ dependencies = [
|
|||||||
"rog_fan_curve",
|
"rog_fan_curve",
|
||||||
"rog_types",
|
"rog_types",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"zbus",
|
"zbus 1.8.0",
|
||||||
"zbus_macros",
|
"zbus_macros 1.8.0",
|
||||||
"zvariant",
|
"zvariant",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rog_fan_curve"
|
name = "rog_fan_curve"
|
||||||
version = "0.1.7"
|
version = "0.1.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c71cfe91a717104796aeefea4e98ce5cefb11f2bb5dd10bba865dd4ae86273cb"
|
checksum = "d083149d6e2681d05882e7ff557dec07211a6349f6de9446073b2c7dfd81e2f2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rog_types"
|
name = "rog_types"
|
||||||
version = "3.0.0"
|
version = "3.1.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gumdrop",
|
"gumdrop",
|
||||||
"rog_fan_curve",
|
"rog_fan_curve",
|
||||||
@@ -858,29 +960,29 @@ checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.123"
|
version = "1.0.124"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "92d5161132722baa40d802cc70b15262b98258453e85e5d1d365c757c73869ae"
|
checksum = "bd761ff957cb2a45fbb9ab3da6512de9de55872866160b23c25f1a841e99d29f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.123"
|
version = "1.0.124"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9391c295d64fc0abb2c556bad848f33cb8296276b1ad2677d1ae1ace4f258f31"
|
checksum = "1800f7693e94e186f5e25a28291ae1570da908aff7d97a095dec1e56ff99069b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote 1.0.8",
|
"quote 1.0.9",
|
||||||
"syn 1.0.60",
|
"syn 1.0.64",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.61"
|
version = "1.0.64"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4fceb2595057b6891a4ee808f70054bd2d12f0e97f1cbb78689b59f676df325a"
|
checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"ryu",
|
"ryu",
|
||||||
@@ -894,16 +996,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "2dc6b7951b17b051f3210b063f12cc17320e2fe30ae05b0fe2a3abb068551c76"
|
checksum = "2dc6b7951b17b051f3210b063f12cc17320e2fe30ae05b0fe2a3abb068551c76"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote 1.0.8",
|
"quote 1.0.9",
|
||||||
"syn 1.0.60",
|
"syn 1.0.64",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha1"
|
||||||
|
version = "0.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "slab"
|
name = "slab"
|
||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
|
checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "slotmap"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ab3003725ae562cf995f3dc82bb99e70926e09000396816765bb6d7adbe740b1"
|
||||||
|
dependencies = [
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smart-default"
|
name = "smart-default"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
@@ -911,8 +1028,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "133659a15339456eeeb07572eb02a91c91e9815e9cbc89566944d2c8d3efdbf6"
|
checksum = "133659a15339456eeeb07572eb02a91c91e9815e9cbc89566944d2c8d3efdbf6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote 1.0.8",
|
"quote 1.0.9",
|
||||||
"syn 1.0.60",
|
"syn 1.0.64",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "socket2"
|
||||||
|
version = "0.3.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 1.0.0",
|
||||||
|
"libc",
|
||||||
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -944,12 +1072,12 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.60"
|
version = "1.0.64"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081"
|
checksum = "3fd9d1e9976102a03c542daa2eff1b43f9d72306342f3f8b3ed5fb8908195d6f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote 1.0.8",
|
"quote 1.0.9",
|
||||||
"unicode-xid 0.2.1",
|
"unicode-xid 0.2.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -969,8 +1097,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701"
|
checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote 1.0.8",
|
"quote 1.0.9",
|
||||||
"syn 1.0.60",
|
"syn 1.0.64",
|
||||||
"unicode-xid 0.2.1",
|
"unicode-xid 0.2.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -992,23 +1120,13 @@ dependencies = [
|
|||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "thread_local"
|
|
||||||
version = "1.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d8208a331e1cb318dd5bd76951d2b8fc48ca38a69f5f4e4af1b6a9f8c6236915"
|
|
||||||
dependencies = [
|
|
||||||
"once_cell",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time"
|
name = "time"
|
||||||
version = "0.1.44"
|
version = "0.1.43"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
|
checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"wasi 0.10.0+wasi-snapshot-preview1",
|
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1067,9 +1185,9 @@ checksum = "eafc1b9b2dfc6f5529177b62cf806484db55b32dc7c9658a118e11bbeb33061d"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.2"
|
version = "0.9.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
|
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "void"
|
name = "void"
|
||||||
@@ -1091,9 +1209,9 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.10.0+wasi-snapshot-preview1"
|
version = "0.10.2+wasi-snapshot-preview1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
|
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wepoll-sys"
|
name = "wepoll-sys"
|
||||||
@@ -1146,9 +1264,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winrt-notification"
|
name = "winrt-notification"
|
||||||
version = "0.2.2"
|
version = "0.2.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6c31a65da50d792c6f9bd2e3216249566c4fb1d2d34f9b7d2d66d2e93f62a242"
|
checksum = "57790eb281688a4682dab44df2a1ba8b78373233bd71cb291c3e75fecb1a01c4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"strum",
|
"strum",
|
||||||
"strum_macros",
|
"strum_macros",
|
||||||
@@ -1188,13 +1306,41 @@ dependencies = [
|
|||||||
"fastrand",
|
"fastrand",
|
||||||
"futures",
|
"futures",
|
||||||
"nb-connect",
|
"nb-connect",
|
||||||
"nix",
|
"nix 0.17.0",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"polling",
|
"polling",
|
||||||
"scoped-tls",
|
"scoped-tls",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_repr",
|
"serde_repr",
|
||||||
"zbus_macros",
|
"zbus_macros 1.8.0",
|
||||||
|
"zvariant",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zbus"
|
||||||
|
version = "2.0.0-beta.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3e1e656194618d167524f97e88ff9bf87f2b1e8bf58f357b2a7abfdff8cc85c9"
|
||||||
|
dependencies = [
|
||||||
|
"async-io",
|
||||||
|
"async-lock",
|
||||||
|
"byteorder",
|
||||||
|
"derivative",
|
||||||
|
"enumflags2",
|
||||||
|
"event-listener",
|
||||||
|
"futures-core",
|
||||||
|
"futures-sink",
|
||||||
|
"futures-util",
|
||||||
|
"hex",
|
||||||
|
"nix 0.19.1",
|
||||||
|
"once_cell",
|
||||||
|
"rand",
|
||||||
|
"scoped-tls",
|
||||||
|
"serde",
|
||||||
|
"serde_repr",
|
||||||
|
"sha1",
|
||||||
|
"slotmap",
|
||||||
|
"zbus_macros 2.0.0-beta.3",
|
||||||
"zvariant",
|
"zvariant",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1206,15 +1352,27 @@ checksum = "87cc141cda72384bef359badf1808e391d3968f9299e8f3c3cbb78dafa1e0930"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-crate",
|
"proc-macro-crate",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote 1.0.8",
|
"quote 1.0.9",
|
||||||
"syn 1.0.60",
|
"syn 1.0.64",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zbus_macros"
|
||||||
|
version = "2.0.0-beta.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fcd4cb372bc2cade3f2323e4104112dceb6819f5dd9afa98515b4e821d232932"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro-crate",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote 1.0.9",
|
||||||
|
"syn 1.0.64",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zvariant"
|
name = "zvariant"
|
||||||
version = "2.5.0"
|
version = "2.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2fc67d552ac18ccd9e440f062f5b32c46776f96073122a8da2fe0c533833a213"
|
checksum = "678e7262502a135f49b1ece65010526649be7ee68acb80e1fc5377fc71fef878"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"enumflags2",
|
"enumflags2",
|
||||||
@@ -1224,12 +1382,12 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zvariant_derive"
|
name = "zvariant_derive"
|
||||||
version = "2.5.0"
|
version = "2.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "eaee686340b5bff077d52423d8cc4f0f7cb323fe3f31ef676b8a3a2810bc53c5"
|
checksum = "27d7c34325a35020b94343389cc9391e0f8ac245cca9155429c4022d93141241"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-crate",
|
"proc-macro-crate",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote 1.0.8",
|
"quote 1.0.9",
|
||||||
"syn 1.0.60",
|
"syn 1.0.64",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ install:
|
|||||||
$(INSTALL_DATA) "./data/icons/asus_notif_green.png" "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_green.png"
|
$(INSTALL_DATA) "./data/icons/asus_notif_green.png" "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_green.png"
|
||||||
$(INSTALL_DATA) "./data/icons/asus_notif_red.png" "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_red.png"
|
$(INSTALL_DATA) "./data/icons/asus_notif_red.png" "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_red.png"
|
||||||
$(INSTALL_DATA) "./data/_asusctl" "$(DESTDIR)$(zshcpl)/_asusctl"
|
$(INSTALL_DATA) "./data/_asusctl" "$(DESTDIR)$(zshcpl)/_asusctl"
|
||||||
|
$(INSTALL_DATA) "./data/completions/asusctl.fish" "$(DESTDIR)$(datarootdir)/fish/vendor_completions.d/asusctl.fish"
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
rm -f "$(DESTDIR)$(bindir)/$(BIN_C)"
|
rm -f "$(DESTDIR)$(bindir)/$(BIN_C)"
|
||||||
@@ -70,6 +71,7 @@ uninstall:
|
|||||||
rm -r "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_green.png"
|
rm -r "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_green.png"
|
||||||
rm -r "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_red.png"
|
rm -r "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_red.png"
|
||||||
rm -f "$(DESTDIR)$(zshcpl)/_asusctl"
|
rm -f "$(DESTDIR)$(zshcpl)/_asusctl"
|
||||||
|
rm -f "$(DESTDIR)$(datarootdir)/fish/vendor_completions.d/asusctl.fish"
|
||||||
|
|
||||||
update:
|
update:
|
||||||
cargo update
|
cargo update
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# ASUS NB Ctrl
|
# ASUS NB Ctrl
|
||||||
|
|
||||||
|
[](https://www.paypal.com/donate/?hosted_button_id=4V2DEPS7K6APC) - [Asus Linux Website](https://asus-linux.org/)
|
||||||
|
|
||||||
`asusd` is a utility for Linux to control many aspects of various ASUS laptops
|
`asusd` is a utility for Linux to control many aspects of various ASUS laptops
|
||||||
but can also be used with non-asus laptops with reduced features.
|
but can also be used with non-asus laptops with reduced features.
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,10 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
if let Some(notif) = last_gfx_notif.take() {
|
if let Some(notif) = last_gfx_notif.take() {
|
||||||
notif.close();
|
notif.close();
|
||||||
}
|
}
|
||||||
let x = do_notif(&format!("Graphics mode changed to {}", vendor))?;
|
let x = do_notif(&format!(
|
||||||
|
"Graphics mode changed to {}",
|
||||||
|
<&str>::from(vendor)
|
||||||
|
))?;
|
||||||
last_gfx_notif = Some(x);
|
last_gfx_notif = Some(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -67,7 +70,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
}
|
}
|
||||||
let x = do_notif(&format!(
|
let x = do_notif(&format!(
|
||||||
"Keyboard LED mode changed to {}",
|
"Keyboard LED mode changed to {}",
|
||||||
<&str>::from(&ledmode)
|
ledmode.mode_name()
|
||||||
))?;
|
))?;
|
||||||
last_led_notif = Some(x);
|
last_led_notif = Some(x);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "asusctl"
|
name = "asusctl"
|
||||||
version = "3.0.0"
|
version = "3.1.4"
|
||||||
authors = ["Luke D Jones <luke@ljones.dev>"]
|
authors = ["Luke D Jones <luke@ljones.dev>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
@@ -11,6 +11,7 @@ edition = "2018"
|
|||||||
serde_json = "^1.0"
|
serde_json = "^1.0"
|
||||||
rog_dbus = { path = "../rog-dbus" }
|
rog_dbus = { path = "../rog-dbus" }
|
||||||
rog_types = { path = "../rog-types" }
|
rog_types = { path = "../rog-types" }
|
||||||
|
daemon = { path = "../daemon" }
|
||||||
gumdrop = "^0.8"
|
gumdrop = "^0.8"
|
||||||
yansi-term = "^0.1"
|
yansi-term = "^0.1"
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use rog_dbus::AuraDbusClient;
|
use rog_dbus::AuraDbusClient;
|
||||||
use rog_types::fancy::{GX502Layout, Key, KeyColourArray, KeyLayout};
|
use rog_types::aura_perkey::{GX502Layout, Key, KeyColourArray, KeyLayout};
|
||||||
use std::collections::LinkedList;
|
use std::collections::LinkedList;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use rog_dbus::AuraDbusClient;
|
use rog_dbus::AuraDbusClient;
|
||||||
use rog_types::fancy::{GX502Layout, KeyColourArray, KeyLayout};
|
use rog_types::aura_perkey::{GX502Layout, KeyColourArray, KeyLayout};
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let (dbus, _) = AuraDbusClient::new()?;
|
let (dbus, _) = AuraDbusClient::new()?;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use rog_dbus::AuraDbusClient;
|
use rog_dbus::AuraDbusClient;
|
||||||
use rog_types::fancy::{GX502Layout, Key, KeyColourArray, KeyLayout};
|
use rog_types::aura_perkey::{GX502Layout, Key, KeyColourArray, KeyLayout};
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let (dbus, _) = AuraDbusClient::new()?;
|
let (dbus, _) = AuraDbusClient::new()?;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use rog_dbus::AuraDbusClient;
|
use rog_dbus::AuraDbusClient;
|
||||||
use rog_types::fancy::{Key, KeyColourArray};
|
use rog_types::aura_perkey::{Key, KeyColourArray};
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let (dbus, _) = AuraDbusClient::new()?;
|
let (dbus, _) = AuraDbusClient::new()?;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use rog_dbus::AuraDbusClient;
|
use rog_dbus::AuraDbusClient;
|
||||||
use rog_types::fancy::{GX502Layout, KeyColourArray, KeyLayout};
|
use rog_types::aura_perkey::{GX502Layout, KeyColourArray, KeyLayout};
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let (dbus, _) = AuraDbusClient::new()?;
|
let (dbus, _) = AuraDbusClient::new()?;
|
||||||
|
|||||||
@@ -0,0 +1,330 @@
|
|||||||
|
use gumdrop::Options;
|
||||||
|
use rog_types::{
|
||||||
|
aura_modes::{AuraEffect, AuraModeNum, AuraZone, Colour, Direction, Speed},
|
||||||
|
error::AuraError,
|
||||||
|
};
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
#[derive(Options)]
|
||||||
|
pub struct LedBrightness {
|
||||||
|
level: Option<u32>,
|
||||||
|
}
|
||||||
|
impl LedBrightness {
|
||||||
|
pub fn new(level: Option<u32>) -> Self {
|
||||||
|
LedBrightness { level }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn level(&self) -> Option<u32> {
|
||||||
|
self.level
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl FromStr for LedBrightness {
|
||||||
|
type Err = AuraError;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
let s = s.to_lowercase();
|
||||||
|
match s.as_str() {
|
||||||
|
"off" => Ok(LedBrightness { level: Some(0x00) }),
|
||||||
|
"low" => Ok(LedBrightness { level: Some(0x01) }),
|
||||||
|
"med" => Ok(LedBrightness { level: Some(0x02) }),
|
||||||
|
"high" => Ok(LedBrightness { level: Some(0x03) }),
|
||||||
|
_ => {
|
||||||
|
print!("Invalid argument, must be one of: off, low, med, high");
|
||||||
|
Err(AuraError::ParseBrightness)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl ToString for LedBrightness {
|
||||||
|
fn to_string(&self) -> String {
|
||||||
|
let s = match self.level {
|
||||||
|
Some(0x00) => "low",
|
||||||
|
Some(0x01) => "med",
|
||||||
|
Some(0x02) => "high",
|
||||||
|
_ => "unknown",
|
||||||
|
};
|
||||||
|
s.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Options, Default)]
|
||||||
|
pub struct SingleSpeed {
|
||||||
|
#[options(help = "print help message")]
|
||||||
|
help: bool,
|
||||||
|
#[options(no_long, meta = "WORD", help = "set the speed: low, med, high")]
|
||||||
|
pub speed: Speed,
|
||||||
|
}
|
||||||
|
#[derive(Debug, Clone, Options, Default)]
|
||||||
|
pub struct SingleSpeedDirection {
|
||||||
|
#[options(help = "print help message")]
|
||||||
|
help: bool,
|
||||||
|
#[options(no_long, meta = "", help = "set the direction: up, down, left, right")]
|
||||||
|
pub direction: Direction,
|
||||||
|
#[options(no_long, meta = "", help = "set the speed: low, med, high")]
|
||||||
|
pub speed: Speed,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default, Options)]
|
||||||
|
pub struct SingleColour {
|
||||||
|
#[options(help = "print help message")]
|
||||||
|
help: bool,
|
||||||
|
#[options(no_long, meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||||
|
pub colour: Colour,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default, Options)]
|
||||||
|
pub struct SingleColourSpeed {
|
||||||
|
#[options(help = "print help message")]
|
||||||
|
help: bool,
|
||||||
|
#[options(no_long, meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||||
|
pub colour: Colour,
|
||||||
|
#[options(no_long, meta = "", help = "set the speed: low, med, high")]
|
||||||
|
pub speed: Speed,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Options, Default)]
|
||||||
|
pub struct TwoColourSpeed {
|
||||||
|
#[options(help = "print help message")]
|
||||||
|
help: bool,
|
||||||
|
#[options(no_long, meta = "", help = "set the first RGB value e.g, ff00ff")]
|
||||||
|
pub colour: Colour,
|
||||||
|
#[options(no_long, meta = "", help = "set the second RGB value e.g, ff00ff")]
|
||||||
|
pub colour2: Colour,
|
||||||
|
#[options(no_long, meta = "", help = "set the speed: low, med, high")]
|
||||||
|
pub speed: Speed,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default, Options)]
|
||||||
|
pub struct MultiColour {
|
||||||
|
#[options(help = "print help message")]
|
||||||
|
help: bool,
|
||||||
|
#[options(short = "a", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||||
|
pub colour1: Colour,
|
||||||
|
#[options(short = "b", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||||
|
pub colour2: Colour,
|
||||||
|
#[options(short = "c", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||||
|
pub colour3: Colour,
|
||||||
|
#[options(short = "d", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||||
|
pub colour4: Colour,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default, Options)]
|
||||||
|
pub struct MultiColourSpeed {
|
||||||
|
#[options(help = "print help message")]
|
||||||
|
help: bool,
|
||||||
|
#[options(short = "a", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||||
|
pub colour1: Colour,
|
||||||
|
#[options(short = "b", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||||
|
pub colour2: Colour,
|
||||||
|
#[options(short = "c", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||||
|
pub colour3: Colour,
|
||||||
|
#[options(short = "d", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||||
|
pub colour4: Colour,
|
||||||
|
#[options(no_long, meta = "", help = "set the speed: low, med, high")]
|
||||||
|
pub speed: Speed,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Byte value for setting the built-in mode.
|
||||||
|
///
|
||||||
|
/// Enum corresponds to the required integer value
|
||||||
|
#[derive(Options)]
|
||||||
|
pub enum SetAuraBuiltin {
|
||||||
|
#[options(help = "set a single static colour")]
|
||||||
|
Static(SingleColour),
|
||||||
|
#[options(help = "pulse between one or two colours")]
|
||||||
|
Breathe(TwoColourSpeed),
|
||||||
|
#[options(help = "strobe through all colours")]
|
||||||
|
Strobe(SingleSpeed),
|
||||||
|
#[options(help = "rainbow cycling in one of four directions")]
|
||||||
|
Rainbow(SingleSpeedDirection),
|
||||||
|
#[options(help = "rain pattern mimicking raindrops")]
|
||||||
|
Star(TwoColourSpeed),
|
||||||
|
#[options(help = "rain pattern of three preset colours")]
|
||||||
|
Rain(SingleSpeed),
|
||||||
|
#[options(help = "pressed keys are highlighted to fade")]
|
||||||
|
Highlight(SingleColourSpeed),
|
||||||
|
#[options(help = "pressed keys generate horizontal laser")]
|
||||||
|
Laser(SingleColourSpeed),
|
||||||
|
#[options(help = "pressed keys ripple outwards like a splash")]
|
||||||
|
Ripple(SingleColourSpeed),
|
||||||
|
#[options(help = "set a rapid pulse")]
|
||||||
|
Pulse(SingleColour),
|
||||||
|
#[options(help = "set a vertical line zooming from left")]
|
||||||
|
Comet(SingleColour),
|
||||||
|
#[options(help = "set a wide vertical line zooming from left")]
|
||||||
|
Flash(SingleColour),
|
||||||
|
#[options(help = "4-zone multi-colour")]
|
||||||
|
MultiStatic(MultiColour),
|
||||||
|
#[options(help = "4-zone multi-colour breathing")]
|
||||||
|
MultiBreathe(MultiColourSpeed),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for SetAuraBuiltin {
|
||||||
|
fn default() -> Self {
|
||||||
|
SetAuraBuiltin::Static(SingleColour::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&SingleColour> for AuraEffect {
|
||||||
|
fn from(aura: &SingleColour) -> Self {
|
||||||
|
Self {
|
||||||
|
colour1: aura.colour,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&SingleSpeed> for AuraEffect {
|
||||||
|
fn from(aura: &SingleSpeed) -> Self {
|
||||||
|
Self {
|
||||||
|
speed: aura.speed,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&SingleColourSpeed> for AuraEffect {
|
||||||
|
fn from(aura: &SingleColourSpeed) -> Self {
|
||||||
|
Self {
|
||||||
|
colour1: aura.colour,
|
||||||
|
speed: aura.speed,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&TwoColourSpeed> for AuraEffect {
|
||||||
|
fn from(aura: &TwoColourSpeed) -> Self {
|
||||||
|
Self {
|
||||||
|
colour1: aura.colour,
|
||||||
|
colour2: aura.colour2,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&SingleSpeedDirection> for AuraEffect {
|
||||||
|
fn from(aura: &SingleSpeedDirection) -> Self {
|
||||||
|
Self {
|
||||||
|
speed: aura.speed,
|
||||||
|
direction: aura.direction,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&SetAuraBuiltin> for AuraEffect {
|
||||||
|
fn from(aura: &SetAuraBuiltin) -> Self {
|
||||||
|
match aura {
|
||||||
|
SetAuraBuiltin::Static(x) => {
|
||||||
|
let mut data: AuraEffect = x.into();
|
||||||
|
data.mode = AuraModeNum::Static;
|
||||||
|
data
|
||||||
|
}
|
||||||
|
SetAuraBuiltin::Breathe(x) => {
|
||||||
|
let mut data: AuraEffect = x.into();
|
||||||
|
data.mode = AuraModeNum::Breathe;
|
||||||
|
data
|
||||||
|
}
|
||||||
|
SetAuraBuiltin::Strobe(x) => {
|
||||||
|
let mut data: AuraEffect = x.into();
|
||||||
|
data.mode = AuraModeNum::Strobe;
|
||||||
|
data
|
||||||
|
}
|
||||||
|
SetAuraBuiltin::Rainbow(x) => {
|
||||||
|
let mut data: AuraEffect = x.into();
|
||||||
|
data.mode = AuraModeNum::Rainbow;
|
||||||
|
data
|
||||||
|
}
|
||||||
|
SetAuraBuiltin::Star(x) => {
|
||||||
|
let mut data: AuraEffect = x.into();
|
||||||
|
data.mode = AuraModeNum::Star;
|
||||||
|
data
|
||||||
|
}
|
||||||
|
SetAuraBuiltin::Rain(x) => {
|
||||||
|
let mut data: AuraEffect = x.into();
|
||||||
|
data.mode = AuraModeNum::Rain;
|
||||||
|
data
|
||||||
|
}
|
||||||
|
SetAuraBuiltin::Highlight(x) => {
|
||||||
|
let mut data: AuraEffect = x.into();
|
||||||
|
data.mode = AuraModeNum::Highlight;
|
||||||
|
data
|
||||||
|
}
|
||||||
|
SetAuraBuiltin::Laser(x) => {
|
||||||
|
let mut data: AuraEffect = x.into();
|
||||||
|
data.mode = AuraModeNum::Laser;
|
||||||
|
data
|
||||||
|
}
|
||||||
|
SetAuraBuiltin::Ripple(x) => {
|
||||||
|
let mut data: AuraEffect = x.into();
|
||||||
|
data.mode = AuraModeNum::Ripple;
|
||||||
|
data
|
||||||
|
}
|
||||||
|
SetAuraBuiltin::Pulse(x) => {
|
||||||
|
let mut data: AuraEffect = x.into();
|
||||||
|
data.mode = AuraModeNum::Pulse;
|
||||||
|
data
|
||||||
|
}
|
||||||
|
SetAuraBuiltin::Comet(x) => {
|
||||||
|
let mut data: AuraEffect = x.into();
|
||||||
|
data.mode = AuraModeNum::Comet;
|
||||||
|
data
|
||||||
|
}
|
||||||
|
SetAuraBuiltin::Flash(x) => {
|
||||||
|
let mut data: AuraEffect = x.into();
|
||||||
|
data.mode = AuraModeNum::Flash;
|
||||||
|
data
|
||||||
|
}
|
||||||
|
_ => AuraEffect::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&SetAuraBuiltin> for Vec<AuraEffect> {
|
||||||
|
fn from(aura: &SetAuraBuiltin) -> Vec<AuraEffect> {
|
||||||
|
let mut zones = vec![AuraEffect::default(); 4];
|
||||||
|
match aura {
|
||||||
|
SetAuraBuiltin::MultiStatic(data) => {
|
||||||
|
zones[0].mode = AuraModeNum::Static;
|
||||||
|
zones[0].zone = AuraZone::One;
|
||||||
|
zones[0].colour1 = data.colour1;
|
||||||
|
|
||||||
|
zones[1].mode = AuraModeNum::Static;
|
||||||
|
zones[1].zone = AuraZone::Two;
|
||||||
|
zones[1].colour1 = data.colour2;
|
||||||
|
|
||||||
|
zones[2].mode = AuraModeNum::Static;
|
||||||
|
zones[2].zone = AuraZone::Three;
|
||||||
|
zones[2].colour1 = data.colour3;
|
||||||
|
|
||||||
|
zones[3].mode = AuraModeNum::Static;
|
||||||
|
zones[3].zone = AuraZone::Four;
|
||||||
|
zones[3].colour1 = data.colour4;
|
||||||
|
}
|
||||||
|
SetAuraBuiltin::MultiBreathe(data) => {
|
||||||
|
zones[0].mode = AuraModeNum::Breathe;
|
||||||
|
zones[0].zone = AuraZone::One;
|
||||||
|
zones[0].colour1 = data.colour1;
|
||||||
|
zones[0].speed = data.speed;
|
||||||
|
|
||||||
|
zones[1].mode = AuraModeNum::Breathe;
|
||||||
|
zones[1].zone = AuraZone::Two;
|
||||||
|
zones[1].colour1 = data.colour2;
|
||||||
|
zones[1].speed = data.speed;
|
||||||
|
|
||||||
|
zones[2].mode = AuraModeNum::Breathe;
|
||||||
|
zones[2].zone = AuraZone::Three;
|
||||||
|
zones[2].colour1 = data.colour3;
|
||||||
|
zones[2].speed = data.speed;
|
||||||
|
|
||||||
|
zones[3].mode = AuraModeNum::Breathe;
|
||||||
|
zones[3].zone = AuraZone::Four;
|
||||||
|
zones[3].colour1 = data.colour4;
|
||||||
|
zones[3].speed = data.speed;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
zones
|
||||||
|
}
|
||||||
|
}
|
||||||
+282
-171
@@ -1,12 +1,20 @@
|
|||||||
|
mod aura_cli;
|
||||||
|
|
||||||
|
use crate::aura_cli::{LedBrightness, SetAuraBuiltin};
|
||||||
|
use daemon::{
|
||||||
|
ctrl_fan_cpu::FanCpuSupportedFunctions, ctrl_leds::LedSupportedFunctions,
|
||||||
|
ctrl_rog_bios::RogBiosSupportedFunctions, ctrl_supported::SupportedFunctions,
|
||||||
|
};
|
||||||
use gumdrop::{Opt, Options};
|
use gumdrop::{Opt, Options};
|
||||||
use rog_dbus::AuraDbusClient;
|
use rog_dbus::AuraDbusClient;
|
||||||
use rog_types::{
|
use rog_types::{
|
||||||
anime_matrix::{AniMeDataBuffer, FULL_PANE_LEN},
|
anime_matrix::{AniMeDataBuffer, FULL_PANE_LEN},
|
||||||
cli_options::{AniMeActions, AniMeStatusValue, LedBrightness, SetAuraBuiltin},
|
aura_modes::{self, AuraEffect, AuraModeNum},
|
||||||
|
cli_options::{AniMeActions, AniMeStatusValue},
|
||||||
gfx_vendors::GfxVendors,
|
gfx_vendors::GfxVendors,
|
||||||
profile::{FanLevel, ProfileCommand, ProfileEvent},
|
profile::{FanLevel, ProfileCommand, ProfileEvent},
|
||||||
};
|
};
|
||||||
use std::{env::args, process::Command};
|
use std::env::args;
|
||||||
use yansi_term::Colour::Green;
|
use yansi_term::Colour::Green;
|
||||||
use yansi_term::Colour::Red;
|
use yansi_term::Colour::Red;
|
||||||
|
|
||||||
@@ -93,19 +101,22 @@ struct AniMeCommand {
|
|||||||
struct BiosCommand {
|
struct BiosCommand {
|
||||||
#[options(help = "print help message")]
|
#[options(help = "print help message")]
|
||||||
help: bool,
|
help: bool,
|
||||||
#[options(meta = "", no_long, help = "toggle bios POST sound")]
|
#[options(meta = "", no_long, help = "set bios POST sound <true/false>")]
|
||||||
post_sound_set: Option<bool>,
|
post_sound_set: Option<bool>,
|
||||||
#[options(no_long, help = "read bios POST sound")]
|
#[options(no_long, help = "read bios POST sound")]
|
||||||
post_sound_get: bool,
|
post_sound_get: bool,
|
||||||
#[options(meta = "", no_long, help = "toggle GPU to/from dedicated mode")]
|
#[options(
|
||||||
|
meta = "",
|
||||||
|
no_long,
|
||||||
|
help = "activate dGPU dedicated/G-Sync <true/false>"
|
||||||
|
)]
|
||||||
dedicated_gfx_set: Option<bool>,
|
dedicated_gfx_set: Option<bool>,
|
||||||
#[options(no_long, help = "get GPU mode")]
|
#[options(no_long, help = "get GPU mode")]
|
||||||
dedicated_gfx_get: bool,
|
dedicated_gfx_get: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut args: Vec<String> = args().collect();
|
let args: Vec<String> = args().skip(1).collect();
|
||||||
args.remove(0);
|
|
||||||
|
|
||||||
let parsed: CLIStart;
|
let parsed: CLIStart;
|
||||||
let missing_argument_k = gumdrop::Error::missing_argument(Opt::Short('k'));
|
let missing_argument_k = gumdrop::Error::missing_argument(Opt::Short('k'));
|
||||||
@@ -125,65 +136,28 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if parsed.help_requested() {
|
let (dbus, _) = AuraDbusClient::new()?;
|
||||||
// As help option don't work with `parse_args_default`
|
|
||||||
// we will call `parse_args_default_or_exit` instead
|
let supported_tmp = dbus.proxies().supported().get_supported_functions()?;
|
||||||
CLIStart::parse_args_default_or_exit();
|
let supported = serde_json::from_str::<SupportedFunctions>(&supported_tmp)?;
|
||||||
|
|
||||||
|
if parsed.help {
|
||||||
|
print_supported_help(&supported, &parsed);
|
||||||
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if parsed.version {
|
if parsed.version {
|
||||||
println!(" asusctl version {}", env!("CARGO_PKG_VERSION"));
|
println!(" asusctl v{}", env!("CARGO_PKG_VERSION"));
|
||||||
println!(" rog-dbus version {}", rog_dbus::VERSION);
|
println!(" rog-dbus v{}", rog_dbus::VERSION);
|
||||||
println!("rog-types version {}", rog_types::VERSION);
|
println!("rog-types v{}", rog_types::VERSION);
|
||||||
|
println!(" daemon v{}", daemon::VERSION);
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let (dbus, _) = AuraDbusClient::new()?;
|
|
||||||
|
|
||||||
match parsed.command {
|
match parsed.command {
|
||||||
Some(CliCommand::LedMode(mode)) => {
|
Some(CliCommand::LedMode(mode)) => handle_led_mode(&dbus, &supported.keyboard_led, &mode)?,
|
||||||
if (mode.command.is_none() && !mode.prev_mode && !mode.next_mode) || mode.help {
|
Some(CliCommand::Profile(cmd)) => handle_profile(&dbus, &supported.fan_cpu_ctrl, &cmd)?,
|
||||||
println!("Missing arg or command\n\n{}", mode.self_usage());
|
Some(CliCommand::Graphics(cmd)) => do_gfx(&dbus, &supported.rog_bios_ctrl, cmd)?,
|
||||||
if let Some(lst) = mode.self_command_list() {
|
|
||||||
println!("\n{}", lst);
|
|
||||||
}
|
|
||||||
println!("\nHelp can also be requested on modes, e.g: static --help");
|
|
||||||
}
|
|
||||||
if mode.next_mode && mode.prev_mode {
|
|
||||||
println!("Please specify either next or previous")
|
|
||||||
}
|
|
||||||
if mode.next_mode {
|
|
||||||
dbus.proxies().led().next_led_mode()?;
|
|
||||||
} else if mode.prev_mode {
|
|
||||||
dbus.proxies().led().prev_led_mode()?;
|
|
||||||
} else if let Some(command) = mode.command {
|
|
||||||
dbus.proxies().led().set_led_mode(&command.into())?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some(CliCommand::Profile(cmd)) => {
|
|
||||||
if (!cmd.next
|
|
||||||
&& !cmd.create
|
|
||||||
&& cmd.curve.is_none()
|
|
||||||
&& cmd.max_percentage.is_none()
|
|
||||||
&& cmd.min_percentage.is_none()
|
|
||||||
&& cmd.preset.is_none()
|
|
||||||
&& cmd.profile.is_none()
|
|
||||||
&& cmd.turbo.is_none())
|
|
||||||
|| cmd.help
|
|
||||||
{
|
|
||||||
println!("Missing arg or command\n\n{}", cmd.self_usage());
|
|
||||||
if let Some(lst) = cmd.self_command_list() {
|
|
||||||
println!("\n{}", lst);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if cmd.next {
|
|
||||||
dbus.proxies().profile().next_fan()?;
|
|
||||||
} else {
|
|
||||||
dbus.proxies()
|
|
||||||
.profile()
|
|
||||||
.write_command(&ProfileEvent::Cli(cmd))?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some(CliCommand::Graphics(cmd)) => do_gfx(cmd, &dbus)?,
|
|
||||||
Some(CliCommand::AniMe(cmd)) => {
|
Some(CliCommand::AniMe(cmd)) => {
|
||||||
if (cmd.command.is_none() && cmd.boot.is_none() && cmd.turn.is_none()) || cmd.help {
|
if (cmd.command.is_none() && cmd.boot.is_none() && cmd.turn.is_none()) || cmd.help {
|
||||||
println!("Missing arg or command\n\n{}", cmd.self_usage());
|
println!("Missing arg or command\n\n{}", cmd.self_usage());
|
||||||
@@ -207,42 +181,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(CliCommand::Bios(cmd)) => {
|
Some(CliCommand::Bios(cmd)) => handle_bios_option(&dbus, &supported.rog_bios_ctrl, &cmd)?,
|
||||||
if (cmd.dedicated_gfx_set.is_none()
|
|
||||||
&& !cmd.dedicated_gfx_get
|
|
||||||
&& cmd.post_sound_set.is_none()
|
|
||||||
&& !cmd.post_sound_get)
|
|
||||||
|| cmd.help
|
|
||||||
{
|
|
||||||
println!("Missing arg or command\n\n{}", cmd.self_usage());
|
|
||||||
if let Some(lst) = cmd.self_command_list() {
|
|
||||||
println!("\n{}", lst);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(opt) = cmd.post_sound_set {
|
|
||||||
dbus.proxies().rog_bios().set_post_sound(opt)?;
|
|
||||||
}
|
|
||||||
if cmd.post_sound_get {
|
|
||||||
let res = if dbus.proxies().rog_bios().get_post_sound()? == 1 {
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
};
|
|
||||||
println!("Bios POST sound on: {}", res);
|
|
||||||
}
|
|
||||||
if let Some(opt) = cmd.dedicated_gfx_set {
|
|
||||||
dbus.proxies().rog_bios().set_dedicated_gfx(opt)?;
|
|
||||||
}
|
|
||||||
if cmd.dedicated_gfx_get {
|
|
||||||
let res = if dbus.proxies().rog_bios().get_dedicated_gfx()? == 1 {
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
};
|
|
||||||
println!("Bios dedicated GPU on: {}", res);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => {
|
None => {
|
||||||
if (!parsed.show_supported
|
if (!parsed.show_supported
|
||||||
&& parsed.kbd_bright.is_none()
|
&& parsed.kbd_bright.is_none()
|
||||||
@@ -263,13 +202,16 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
let level = dbus.proxies().led().get_led_brightness()?;
|
let level = dbus.proxies().led().get_led_brightness()?;
|
||||||
println!("Current keyboard led brightness: {}", level.to_string());
|
println!("Current keyboard led brightness: {}", level.to_string());
|
||||||
}
|
}
|
||||||
Some(level) => dbus.proxies().led().set_brightness(level)?,
|
Some(level) => dbus
|
||||||
|
.proxies()
|
||||||
|
.led()
|
||||||
|
.set_led_brightness(<aura_modes::LedBrightness>::from(level))?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if parsed.show_supported {
|
if parsed.show_supported {
|
||||||
let dat = dbus.proxies().supported().get_supported_functions()?;
|
let dat = dbus.proxies().supported().get_supported_functions()?;
|
||||||
println!("Supported laptop functions:\n{}", dat.to_string());
|
println!("Supported laptop functions:\n{}", dat);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(fan_level) = parsed.fan_mode {
|
if let Some(fan_level) = parsed.fan_mode {
|
||||||
@@ -281,97 +223,266 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_gfx(
|
fn print_supported_help(supported: &SupportedFunctions, parsed: &CLIStart) {
|
||||||
command: GraphicsCommand,
|
// As help option don't work with `parse_args_default`
|
||||||
dbus_client: &AuraDbusClient,
|
// we will call `parse_args_default_or_exit` instead
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
let usage: Vec<String> = parsed.self_usage().lines().map(|s| s.to_string()).collect();
|
||||||
if let Some(mode) = command.mode {
|
for line in usage.iter().filter(|line| {
|
||||||
println!("Updating settings, please wait...");
|
if line.contains("--fan-mode") && !supported.fan_cpu_ctrl.stock_fan_modes {
|
||||||
println!("If this takes longer than 30s, ctrl+c then check `journalctl -b -u asusd`");
|
return false;
|
||||||
|
|
||||||
dbus_client
|
|
||||||
.proxies()
|
|
||||||
.gfx()
|
|
||||||
.gfx_write_mode(<&str>::from(&mode).into())?;
|
|
||||||
let res = dbus_client.gfx_wait_changed()?;
|
|
||||||
match res.as_str() {
|
|
||||||
"reboot" => {
|
|
||||||
println!(
|
|
||||||
"{}",
|
|
||||||
Green.paint("\nGraphics vendor mode changed successfully\n"),
|
|
||||||
);
|
|
||||||
do_gfx_action(
|
|
||||||
command.force,
|
|
||||||
Command::new("systemctl").arg("reboot").arg("-i"),
|
|
||||||
"Reboot Linux PC",
|
|
||||||
"Please reboot when ready",
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
"restartx" => {
|
|
||||||
println!(
|
|
||||||
"{}",
|
|
||||||
Green.paint("\nGraphics vendor mode changed successfully\n")
|
|
||||||
);
|
|
||||||
do_gfx_action(
|
|
||||||
command.force,
|
|
||||||
Command::new("systemctl")
|
|
||||||
.arg("restart")
|
|
||||||
.arg("display-manager.service"),
|
|
||||||
"Restart display-manager server",
|
|
||||||
"Please restart display-manager when ready",
|
|
||||||
)?;
|
|
||||||
std::process::exit(1)
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
println!("{}", Red.paint(&format!("\n{}\n", res.as_str())),);
|
|
||||||
std::process::exit(-1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
std::process::exit(-1)
|
if line.contains("--chg-limit") && !supported.charge_ctrl.charge_level_set {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}) {
|
||||||
|
println!("{}", line);
|
||||||
|
}
|
||||||
|
|
||||||
|
// command strings are in order of the struct
|
||||||
|
let commands: Vec<String> = CliCommand::usage().lines().map(|s| s.to_string()).collect();
|
||||||
|
println!("\nCommands available");
|
||||||
|
for line in commands.iter().filter(|line| {
|
||||||
|
if line.contains("profile")
|
||||||
|
&& !supported.fan_cpu_ctrl.stock_fan_modes
|
||||||
|
&& !supported.fan_cpu_ctrl.fan_curve_set
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if line.contains("led-mode") && supported.keyboard_led.stock_led_modes.is_none() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if line.contains("bios")
|
||||||
|
&& (!supported.rog_bios_ctrl.dedicated_gfx_toggle
|
||||||
|
|| !supported.rog_bios_ctrl.post_sound_toggle)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if line.contains("anime") && !supported.anime_ctrl.0 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}) {
|
||||||
|
println!("{}", line);
|
||||||
|
}
|
||||||
|
|
||||||
|
if !supported.fan_cpu_ctrl.stock_fan_modes {
|
||||||
|
println!("Note: Fan mode control is not supported by this laptop");
|
||||||
|
}
|
||||||
|
if !supported.charge_ctrl.charge_level_set {
|
||||||
|
println!("Note: Charge control is not supported by this laptop");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_gfx(
|
||||||
|
dbus: &AuraDbusClient,
|
||||||
|
supported: &RogBiosSupportedFunctions,
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(mode) = command.mode {
|
||||||
|
if supported.dedicated_gfx_toggle && dbus.proxies().rog_bios().get_dedicated_gfx()? == 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");
|
||||||
|
|
||||||
|
dbus.proxies().gfx().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
|
||||||
|
})?;
|
||||||
|
let res = dbus.gfx_wait_changed()?;
|
||||||
|
println!(
|
||||||
|
"Graphics mode changed to {}. User action required is: {}",
|
||||||
|
<&str>::from(mode),
|
||||||
|
<&str>::from(&res)
|
||||||
|
);
|
||||||
|
std::process::exit(0)
|
||||||
}
|
}
|
||||||
if command.get {
|
if command.get {
|
||||||
let res = dbus_client.proxies().gfx().gfx_get_mode()?;
|
let res = dbus.proxies().gfx().gfx_get_mode()?;
|
||||||
println!("Current graphics mode: {}", res);
|
println!("Current graphics mode: {}", <&str>::from(res));
|
||||||
}
|
}
|
||||||
if command.pow {
|
if command.pow {
|
||||||
let res = dbus_client.proxies().gfx().gfx_get_pwr()?;
|
let res = dbus.proxies().gfx().gfx_get_pwr()?;
|
||||||
if res.contains("active") {
|
if res.contains("active") {
|
||||||
println!("Current power status: {}", Red.paint(&format!("{}", res)));
|
println!("Current power status: {}", Red.paint(&res));
|
||||||
} else {
|
} else {
|
||||||
println!("Current power status: {}", Green.paint(&format!("{}", res)));
|
println!("Current power status: {}", Green.paint(&res));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_gfx_action(
|
fn handle_led_mode(
|
||||||
no_confirm: bool,
|
dbus: &AuraDbusClient,
|
||||||
command: &mut Command,
|
supported: &LedSupportedFunctions,
|
||||||
ask_msg: &str,
|
mode: &LedModeCommand,
|
||||||
cancel_msg: &str,
|
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
println!("{}? y/n", ask_msg);
|
if mode.command.is_none() && !mode.prev_mode && !mode.next_mode {
|
||||||
|
if !mode.help {
|
||||||
let mut buf = String::new();
|
println!("Missing arg or command\n");
|
||||||
if no_confirm {
|
|
||||||
let status = command.status()?;
|
|
||||||
|
|
||||||
if !status.success() {
|
|
||||||
println!("systemctl: returned with {}", status);
|
|
||||||
}
|
}
|
||||||
|
println!("{}\n", mode.self_usage());
|
||||||
|
println!("Commands available");
|
||||||
|
|
||||||
|
let commands: Vec<String> = LedModeCommand::command_list()
|
||||||
|
.unwrap()
|
||||||
|
.lines()
|
||||||
|
.map(|s| s.to_string())
|
||||||
|
.collect();
|
||||||
|
for command in commands.iter().filter(|mode| {
|
||||||
|
if let Some(modes) = supported.stock_led_modes.as_ref() {
|
||||||
|
return modes.contains(&<AuraModeNum>::from(mode.as_str()));
|
||||||
|
}
|
||||||
|
if supported.multizone_led_mode {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}) {
|
||||||
|
println!("{}", command);
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("\nHelp can also be requested on modes, e.g: static --help");
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::io::stdin().read_line(&mut buf).expect("Input failed");
|
if mode.next_mode && mode.prev_mode {
|
||||||
let input = buf.chars().next().unwrap() as char;
|
println!("Please specify either next or previous");
|
||||||
|
return Ok(());
|
||||||
if input == 'Y' || input == 'y' || no_confirm {
|
}
|
||||||
let status = command.status()?;
|
if mode.next_mode {
|
||||||
|
dbus.proxies().led().next_led_mode()?;
|
||||||
if !status.success() {
|
} else if mode.prev_mode {
|
||||||
println!("systemctl: returned with {}", status);
|
dbus.proxies().led().prev_led_mode()?;
|
||||||
|
} else if let Some(mode) = mode.command.as_ref() {
|
||||||
|
if mode.help_requested() {
|
||||||
|
println!("{}", mode.self_usage());
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
match mode {
|
||||||
|
SetAuraBuiltin::MultiStatic(_) | SetAuraBuiltin::MultiBreathe(_) => {
|
||||||
|
let zones = <Vec<AuraEffect>>::from(mode);
|
||||||
|
for eff in zones {
|
||||||
|
dbus.proxies().led().set_led_mode(&eff)?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => dbus
|
||||||
|
.proxies()
|
||||||
|
.led()
|
||||||
|
.set_led_mode(&<AuraEffect>::from(mode))?,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_profile(
|
||||||
|
dbus: &AuraDbusClient,
|
||||||
|
supported: &FanCpuSupportedFunctions,
|
||||||
|
cmd: &ProfileCommand,
|
||||||
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
if !cmd.next
|
||||||
|
&& !cmd.create
|
||||||
|
&& !cmd.list
|
||||||
|
&& cmd.remove.is_none()
|
||||||
|
&& cmd.curve.is_none()
|
||||||
|
&& cmd.max_percentage.is_none()
|
||||||
|
&& cmd.min_percentage.is_none()
|
||||||
|
&& cmd.fan_preset.is_none()
|
||||||
|
&& cmd.profile.is_none()
|
||||||
|
&& cmd.turbo.is_none()
|
||||||
|
{
|
||||||
|
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_curve_set)
|
||||||
|
{
|
||||||
|
println!("{}", line);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(lst) = cmd.self_command_list() {
|
||||||
|
println!("\n{}", lst);
|
||||||
|
}
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmd.next {
|
||||||
|
dbus.proxies().profile().next_fan()?;
|
||||||
|
} else if cmd.list {
|
||||||
|
let profile_names = dbus.proxies().profile().profile_names()?;
|
||||||
|
println!("Available profiles are {}", profile_names);
|
||||||
|
} else if let Some(profile) = &cmd.remove {
|
||||||
|
dbus.proxies().profile().remove(profile)?
|
||||||
|
} else {
|
||||||
|
dbus.proxies()
|
||||||
|
.profile()
|
||||||
|
.write_command(&ProfileEvent::Cli(cmd.clone()))?
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_bios_option(
|
||||||
|
dbus: &AuraDbusClient,
|
||||||
|
supported: &RogBiosSupportedFunctions,
|
||||||
|
cmd: &BiosCommand,
|
||||||
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
{
|
||||||
|
if (cmd.dedicated_gfx_set.is_none()
|
||||||
|
&& !cmd.dedicated_gfx_get
|
||||||
|
&& cmd.post_sound_set.is_none()
|
||||||
|
&& !cmd.post_sound_get)
|
||||||
|
|| cmd.help
|
||||||
|
{
|
||||||
|
println!("Missing arg or command\n");
|
||||||
|
|
||||||
|
let usage: Vec<String> = BiosCommand::usage()
|
||||||
|
.lines()
|
||||||
|
.map(|s| s.to_string())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
for line in usage.iter().filter(|line| {
|
||||||
|
!(line.contains("sound") && !supported.post_sound_toggle)
|
||||||
|
|| !(line.contains("GPU") && !supported.dedicated_gfx_toggle)
|
||||||
|
}) {
|
||||||
|
println!("{}", line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(opt) = cmd.post_sound_set {
|
||||||
|
dbus.proxies().rog_bios().set_post_sound(opt)?;
|
||||||
|
}
|
||||||
|
if cmd.post_sound_get {
|
||||||
|
let res = dbus.proxies().rog_bios().get_post_sound()? == 1;
|
||||||
|
println!("Bios POST sound on: {}", res);
|
||||||
|
}
|
||||||
|
if let Some(opt) = cmd.dedicated_gfx_set {
|
||||||
|
println!("Rebuilding initrd to include drivers");
|
||||||
|
dbus.proxies().rog_bios().set_dedicated_gfx(opt)?;
|
||||||
|
println!("The mode change is not active until you reboot, on boot the bios will make the required change");
|
||||||
|
if opt {
|
||||||
|
println!(
|
||||||
|
"NOTE: on reboot your display manager will be forced to use Nvidia drivers"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
println!("NOTE: after reboot you can then select regular graphics modes");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if cmd.dedicated_gfx_get {
|
||||||
|
let res = dbus.proxies().rog_bios().get_dedicated_gfx()? == 1;
|
||||||
|
println!("Bios dedicated GPU on: {}", res);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
println!("{}", Red.paint(&format!("{}", cancel_msg)));
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-3
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "daemon"
|
name = "daemon"
|
||||||
version = "3.0.0"
|
version = "3.2.2"
|
||||||
license = "MPL-2.0"
|
license = "MPL-2.0"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
authors = ["Luke <luke@ljones.dev>"]
|
authors = ["Luke <luke@ljones.dev>"]
|
||||||
@@ -27,8 +27,9 @@ udev = "^0.6"
|
|||||||
log = "^0.4"
|
log = "^0.4"
|
||||||
env_logger = "^0.8"
|
env_logger = "^0.8"
|
||||||
|
|
||||||
zbus = "^1.8"
|
zbus = "^2.0.0-beta.3"
|
||||||
zvariant = "^2.4"
|
zvariant = "^2.5"
|
||||||
|
logind-zbus = "*"
|
||||||
|
|
||||||
# serialisation
|
# serialisation
|
||||||
serde = "^1.0"
|
serde = "^1.0"
|
||||||
|
|||||||
+26
-107
@@ -1,90 +1,26 @@
|
|||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
use rog_fan_curve::Curve;
|
use rog_fan_curve::Curve;
|
||||||
use rog_types::aura_modes::AuraModes;
|
use rog_types::gfx_vendors::GfxVendors;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::fs::{File, OpenOptions};
|
use std::fs::{File, OpenOptions};
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
|
|
||||||
|
use crate::config_old::*;
|
||||||
use crate::VERSION;
|
use crate::VERSION;
|
||||||
|
|
||||||
pub static CONFIG_PATH: &str = "/etc/asusd/asusd.conf";
|
pub static CONFIG_PATH: &str = "/etc/asusd/asusd.conf";
|
||||||
|
pub static AURA_CONFIG_PATH: &str = "/etc/asusd/asusd.conf";
|
||||||
/// for parsing old v2.1.2 config
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
struct ConfigV212 {
|
|
||||||
gfx_managed: bool,
|
|
||||||
bat_charge_limit: u8,
|
|
||||||
active_profile: String,
|
|
||||||
toggle_profiles: Vec<String>,
|
|
||||||
power_profiles: BTreeMap<String, Profile>,
|
|
||||||
power_profile: u8,
|
|
||||||
kbd_led_brightness: u8,
|
|
||||||
kbd_backlight_mode: u8,
|
|
||||||
kbd_backlight_modes: Vec<AuraModes>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ConfigV212 {
|
|
||||||
fn into_current(self) -> Config {
|
|
||||||
Config {
|
|
||||||
gfx_managed: self.gfx_managed,
|
|
||||||
gfx_nv_mode_is_dedicated: true,
|
|
||||||
active_profile: self.active_profile,
|
|
||||||
toggle_profiles: self.toggle_profiles,
|
|
||||||
curr_fan_mode: self.power_profile,
|
|
||||||
bat_charge_limit: self.bat_charge_limit,
|
|
||||||
kbd_led_brightness: self.kbd_led_brightness,
|
|
||||||
kbd_backlight_mode: self.kbd_backlight_mode,
|
|
||||||
kbd_backlight_modes: self.kbd_backlight_modes,
|
|
||||||
power_profiles: self.power_profiles,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// for parsing old v2.2.2 config
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
struct ConfigV222 {
|
|
||||||
gfx_managed: bool,
|
|
||||||
bat_charge_limit: u8,
|
|
||||||
active_profile: String,
|
|
||||||
toggle_profiles: Vec<String>,
|
|
||||||
power_profiles: BTreeMap<String, Profile>,
|
|
||||||
power_profile: u8,
|
|
||||||
kbd_led_brightness: u8,
|
|
||||||
kbd_backlight_mode: u8,
|
|
||||||
kbd_backlight_modes: Vec<AuraModes>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ConfigV222 {
|
|
||||||
fn into_current(self) -> Config {
|
|
||||||
Config {
|
|
||||||
gfx_managed: self.gfx_managed,
|
|
||||||
gfx_nv_mode_is_dedicated: true,
|
|
||||||
active_profile: self.active_profile,
|
|
||||||
toggle_profiles: self.toggle_profiles,
|
|
||||||
curr_fan_mode: self.power_profile,
|
|
||||||
bat_charge_limit: self.bat_charge_limit,
|
|
||||||
kbd_led_brightness: self.kbd_led_brightness,
|
|
||||||
kbd_backlight_mode: self.kbd_backlight_mode,
|
|
||||||
kbd_backlight_modes: self.kbd_backlight_modes,
|
|
||||||
power_profiles: self.power_profiles,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
|
pub gfx_mode: GfxVendors,
|
||||||
pub gfx_managed: bool,
|
pub gfx_managed: bool,
|
||||||
pub gfx_nv_mode_is_dedicated: bool,
|
|
||||||
pub active_profile: String,
|
pub active_profile: String,
|
||||||
pub toggle_profiles: Vec<String>,
|
pub toggle_profiles: Vec<String>,
|
||||||
// TODO: remove power_profile
|
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub curr_fan_mode: u8,
|
pub curr_fan_mode: u8,
|
||||||
pub bat_charge_limit: u8,
|
pub bat_charge_limit: u8,
|
||||||
pub kbd_led_brightness: u8,
|
|
||||||
pub kbd_backlight_mode: u8,
|
|
||||||
pub kbd_backlight_modes: Vec<AuraModes>,
|
|
||||||
pub power_profiles: BTreeMap<String, Profile>,
|
pub power_profiles: BTreeMap<String, Profile>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,15 +32,12 @@ impl Default for Config {
|
|||||||
pwr.insert("silent".into(), Profile::new(0, 100, true, 2, None));
|
pwr.insert("silent".into(), Profile::new(0, 100, true, 2, None));
|
||||||
|
|
||||||
Config {
|
Config {
|
||||||
|
gfx_mode: GfxVendors::Hybrid,
|
||||||
gfx_managed: true,
|
gfx_managed: true,
|
||||||
gfx_nv_mode_is_dedicated: true,
|
|
||||||
active_profile: "normal".into(),
|
active_profile: "normal".into(),
|
||||||
toggle_profiles: vec!["normal".into(), "boost".into(), "silent".into()],
|
toggle_profiles: vec!["normal".into(), "boost".into(), "silent".into()],
|
||||||
curr_fan_mode: 0,
|
curr_fan_mode: 0,
|
||||||
bat_charge_limit: 100,
|
bat_charge_limit: 100,
|
||||||
kbd_led_brightness: 1,
|
|
||||||
kbd_backlight_mode: 0,
|
|
||||||
kbd_backlight_modes: Vec::new(),
|
|
||||||
power_profiles: pwr,
|
power_profiles: pwr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -112,23 +45,35 @@ impl Default for Config {
|
|||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
/// `load` will attempt to read the config, and panic if the dir is missing
|
/// `load` will attempt to read the config, and panic if the dir is missing
|
||||||
pub fn load(supported_led_modes: &[u8]) -> Self {
|
pub fn load() -> Self {
|
||||||
let mut file = OpenOptions::new()
|
let mut file = OpenOptions::new()
|
||||||
.read(true)
|
.read(true)
|
||||||
.write(true)
|
.write(true)
|
||||||
.create(true)
|
.create(true)
|
||||||
.open(&CONFIG_PATH)
|
.open(&CONFIG_PATH)
|
||||||
.expect(&format!(
|
.unwrap_or_else(|_| {
|
||||||
"The file {} or directory /etc/asusd/ is missing",
|
panic!(
|
||||||
CONFIG_PATH
|
"The file {} or directory /etc/asusd/ is missing",
|
||||||
)); // okay to cause panic here
|
CONFIG_PATH
|
||||||
|
)
|
||||||
|
}); // okay to cause panic here
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
if let Ok(read_len) = file.read_to_string(&mut buf) {
|
if let Ok(read_len) = file.read_to_string(&mut buf) {
|
||||||
if read_len == 0 {
|
if read_len == 0 {
|
||||||
return Config::create_default(&mut file, &supported_led_modes);
|
return Config::create_default(&mut file);
|
||||||
} else {
|
} else {
|
||||||
if let Ok(data) = serde_json::from_str(&buf) {
|
if let Ok(data) = serde_json::from_str(&buf) {
|
||||||
return data;
|
return data;
|
||||||
|
} else if let Ok(data) = serde_json::from_str::<ConfigV317>(&buf) {
|
||||||
|
let config = data.into_current();
|
||||||
|
config.write();
|
||||||
|
info!("Updated config version to: {}", VERSION);
|
||||||
|
return config;
|
||||||
|
} else if let Ok(data) = serde_json::from_str::<ConfigV301>(&buf) {
|
||||||
|
let config = data.into_current();
|
||||||
|
config.write();
|
||||||
|
info!("Updated config version to: {}", VERSION);
|
||||||
|
return config;
|
||||||
} else if let Ok(data) = serde_json::from_str::<ConfigV222>(&buf) {
|
} else if let Ok(data) = serde_json::from_str::<ConfigV222>(&buf) {
|
||||||
let config = data.into_current();
|
let config = data.into_current();
|
||||||
config.write();
|
config.write();
|
||||||
@@ -144,17 +89,11 @@ impl Config {
|
|||||||
panic!("Please remove {} then restart asusd", CONFIG_PATH);
|
panic!("Please remove {} then restart asusd", CONFIG_PATH);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Config::create_default(&mut file, &supported_led_modes)
|
Config::create_default(&mut file)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_default(file: &mut File, supported_led_modes: &[u8]) -> Self {
|
fn create_default(file: &mut File) -> Self {
|
||||||
// create a default config here
|
let config = Config::default();
|
||||||
let mut config = Config::default();
|
|
||||||
|
|
||||||
for n in supported_led_modes {
|
|
||||||
config.kbd_backlight_modes.push(AuraModes::from(*n))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Should be okay to unwrap this as is since it is a Default
|
// Should be okay to unwrap this as is since it is a Default
|
||||||
let json = serde_json::to_string_pretty(&config).unwrap();
|
let json = serde_json::to_string_pretty(&config).unwrap();
|
||||||
file.write_all(json.as_bytes())
|
file.write_all(json.as_bytes())
|
||||||
@@ -196,26 +135,6 @@ impl Config {
|
|||||||
file.write_all(json.as_bytes())
|
file.write_all(json.as_bytes())
|
||||||
.unwrap_or_else(|err| error!("Could not write config: {}", err));
|
.unwrap_or_else(|err| error!("Could not write config: {}", err));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_mode_data(&mut self, mode: AuraModes) {
|
|
||||||
let byte: u8 = (&mode).into();
|
|
||||||
for (index, n) in self.kbd_backlight_modes.iter().enumerate() {
|
|
||||||
if byte == u8::from(n) {
|
|
||||||
// Consume it, OMNOMNOMNOM
|
|
||||||
self.kbd_backlight_modes[index] = mode;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_led_mode_data(&self, num: u8) -> Option<&AuraModes> {
|
|
||||||
for mode in &self.kbd_backlight_modes {
|
|
||||||
if u8::from(mode) == num {
|
|
||||||
return Some(mode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
|
|||||||
@@ -0,0 +1,148 @@
|
|||||||
|
use crate::laptops::LaptopLedData;
|
||||||
|
use log::{error, info, warn};
|
||||||
|
use rog_types::aura_modes::{AuraEffect, AuraModeNum, AuraMultiZone, AuraZone, LedBrightness};
|
||||||
|
use serde_derive::{Deserialize, Serialize};
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
use std::fs::{File, OpenOptions};
|
||||||
|
use std::io::{Read, Write};
|
||||||
|
|
||||||
|
pub static AURA_CONFIG_PATH: &str = "/etc/asusd/aura.conf";
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
|
pub struct AuraConfigV320 {
|
||||||
|
pub brightness: u32,
|
||||||
|
pub current_mode: AuraModeNum,
|
||||||
|
pub builtins: BTreeMap<AuraModeNum, AuraEffect>,
|
||||||
|
pub multizone: Option<AuraMultiZone>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AuraConfigV320 {
|
||||||
|
pub(crate) fn into_current(self) -> AuraConfig {
|
||||||
|
AuraConfig {
|
||||||
|
brightness: <LedBrightness>::from(self.brightness),
|
||||||
|
current_mode: self.current_mode,
|
||||||
|
builtins: self.builtins,
|
||||||
|
multizone: self.multizone,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
|
pub struct AuraConfig {
|
||||||
|
pub brightness: LedBrightness,
|
||||||
|
pub current_mode: AuraModeNum,
|
||||||
|
pub builtins: BTreeMap<AuraModeNum, AuraEffect>,
|
||||||
|
pub multizone: Option<AuraMultiZone>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for AuraConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
AuraConfig {
|
||||||
|
brightness: LedBrightness::Med,
|
||||||
|
current_mode: AuraModeNum::Static,
|
||||||
|
builtins: BTreeMap::new(),
|
||||||
|
multizone: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AuraConfig {
|
||||||
|
/// `load` will attempt to read the config, and panic if the dir is missing
|
||||||
|
pub fn load(supported_led_modes: &LaptopLedData) -> Self {
|
||||||
|
let mut file = OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.write(true)
|
||||||
|
.create(true)
|
||||||
|
.open(&AURA_CONFIG_PATH)
|
||||||
|
.unwrap_or_else(|_| {
|
||||||
|
panic!(
|
||||||
|
"The file {} or directory /etc/asusd/ is missing",
|
||||||
|
AURA_CONFIG_PATH
|
||||||
|
)
|
||||||
|
}); // okay to cause panic here
|
||||||
|
let mut buf = String::new();
|
||||||
|
if let Ok(read_len) = file.read_to_string(&mut buf) {
|
||||||
|
if read_len == 0 {
|
||||||
|
return AuraConfig::create_default(&mut file, &supported_led_modes);
|
||||||
|
} else {
|
||||||
|
if let Ok(data) = serde_json::from_str(&buf) {
|
||||||
|
return data;
|
||||||
|
} else if let Ok(data) = serde_json::from_str::<AuraConfigV320>(&buf) {
|
||||||
|
let config = data.into_current();
|
||||||
|
config.write();
|
||||||
|
info!("Updated AuraConfig version");
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
warn!("Could not deserialise {}", AURA_CONFIG_PATH);
|
||||||
|
panic!("Please remove {} then restart asusd", AURA_CONFIG_PATH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AuraConfig::create_default(&mut file, &supported_led_modes)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_default(file: &mut File, support_data: &LaptopLedData) -> Self {
|
||||||
|
// create a default config here
|
||||||
|
let mut config = AuraConfig::default();
|
||||||
|
|
||||||
|
for n in &support_data.standard {
|
||||||
|
config
|
||||||
|
.builtins
|
||||||
|
.insert(*n, AuraEffect::default_with_mode(*n));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should be okay to unwrap this as is since it is a Default
|
||||||
|
let json = serde_json::to_string(&config).unwrap();
|
||||||
|
file.write_all(json.as_bytes())
|
||||||
|
.unwrap_or_else(|_| panic!("Could not write {}", AURA_CONFIG_PATH));
|
||||||
|
config
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read(&mut self) {
|
||||||
|
let mut file = OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.open(&AURA_CONFIG_PATH)
|
||||||
|
.unwrap_or_else(|err| panic!("Error reading {}: {}", AURA_CONFIG_PATH, err));
|
||||||
|
let mut buf = String::new();
|
||||||
|
if let Ok(l) = file.read_to_string(&mut buf) {
|
||||||
|
if l == 0 {
|
||||||
|
warn!("File is empty {}", AURA_CONFIG_PATH);
|
||||||
|
} else {
|
||||||
|
let x: AuraConfig = serde_json::from_str(&buf)
|
||||||
|
.unwrap_or_else(|_| panic!("Could not deserialise {}", AURA_CONFIG_PATH));
|
||||||
|
*self = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write(&self) {
|
||||||
|
let mut file = File::create(AURA_CONFIG_PATH).expect("Couldn't overwrite config");
|
||||||
|
let json = serde_json::to_string_pretty(self).expect("Parse config to JSON failed");
|
||||||
|
file.write_all(json.as_bytes())
|
||||||
|
.unwrap_or_else(|err| error!("Could not write config: {}", err));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Multipurpose, will accecpt AuraEffect with zones and put in the correct store
|
||||||
|
pub fn set_builtin(&mut self, effect: AuraEffect) {
|
||||||
|
match effect.zone() {
|
||||||
|
AuraZone::None => {
|
||||||
|
self.builtins.insert(*effect.mode(), effect);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
if let Some(multi) = self.multizone.as_mut() {
|
||||||
|
multi.set(effect)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_multizone(&self, aura_type: AuraModeNum) -> Option<&[AuraEffect; 4]> {
|
||||||
|
if let Some(multi) = &self.multizone {
|
||||||
|
if aura_type == AuraModeNum::Static {
|
||||||
|
return Some(multi.static_());
|
||||||
|
} else if aura_type == AuraModeNum::Breathe {
|
||||||
|
return Some(multi.breathe());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
use rog_types::{aura_modes::AuraEffect, gfx_vendors::GfxVendors};
|
||||||
|
use serde_derive::{Deserialize, Serialize};
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
|
use crate::config::{Config, Profile};
|
||||||
|
|
||||||
|
/// for parsing old v2.1.2 config
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub(crate) struct ConfigV212 {
|
||||||
|
gfx_managed: bool,
|
||||||
|
bat_charge_limit: u8,
|
||||||
|
active_profile: String,
|
||||||
|
toggle_profiles: Vec<String>,
|
||||||
|
power_profiles: BTreeMap<String, Profile>,
|
||||||
|
power_profile: u8,
|
||||||
|
kbd_led_brightness: u8,
|
||||||
|
kbd_backlight_mode: u8,
|
||||||
|
kbd_backlight_modes: Vec<AuraEffect>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConfigV212 {
|
||||||
|
pub(crate) fn into_current(self) -> Config {
|
||||||
|
Config {
|
||||||
|
gfx_mode: GfxVendors::Hybrid,
|
||||||
|
gfx_managed: self.gfx_managed,
|
||||||
|
active_profile: self.active_profile,
|
||||||
|
toggle_profiles: self.toggle_profiles,
|
||||||
|
curr_fan_mode: self.power_profile,
|
||||||
|
bat_charge_limit: self.bat_charge_limit,
|
||||||
|
power_profiles: self.power_profiles,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// for parsing old v2.2.2 config
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub(crate) struct ConfigV222 {
|
||||||
|
gfx_managed: bool,
|
||||||
|
bat_charge_limit: u8,
|
||||||
|
active_profile: String,
|
||||||
|
toggle_profiles: Vec<String>,
|
||||||
|
power_profiles: BTreeMap<String, Profile>,
|
||||||
|
power_profile: u8,
|
||||||
|
kbd_led_brightness: u8,
|
||||||
|
kbd_backlight_mode: u8,
|
||||||
|
kbd_backlight_modes: Vec<AuraEffect>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConfigV222 {
|
||||||
|
pub(crate) fn into_current(self) -> Config {
|
||||||
|
Config {
|
||||||
|
gfx_mode: GfxVendors::Hybrid,
|
||||||
|
gfx_managed: self.gfx_managed,
|
||||||
|
active_profile: self.active_profile,
|
||||||
|
toggle_profiles: self.toggle_profiles,
|
||||||
|
curr_fan_mode: self.power_profile,
|
||||||
|
bat_charge_limit: self.bat_charge_limit,
|
||||||
|
power_profiles: self.power_profiles,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// for parsing old v3.0.1 config
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
|
pub(crate) struct ConfigV301 {
|
||||||
|
pub gfx_managed: bool,
|
||||||
|
pub gfx_nv_mode_is_dedicated: bool,
|
||||||
|
pub active_profile: String,
|
||||||
|
pub toggle_profiles: Vec<String>,
|
||||||
|
// TODO: remove power_profile
|
||||||
|
#[serde(skip)]
|
||||||
|
pub curr_fan_mode: u8,
|
||||||
|
pub bat_charge_limit: u8,
|
||||||
|
pub kbd_led_brightness: u8,
|
||||||
|
pub kbd_backlight_mode: u8,
|
||||||
|
pub kbd_backlight_modes: Vec<AuraEffect>,
|
||||||
|
pub power_profiles: BTreeMap<String, Profile>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConfigV301 {
|
||||||
|
pub(crate) fn into_current(self) -> Config {
|
||||||
|
Config {
|
||||||
|
gfx_mode: GfxVendors::Hybrid,
|
||||||
|
gfx_managed: self.gfx_managed,
|
||||||
|
active_profile: self.active_profile,
|
||||||
|
toggle_profiles: self.toggle_profiles,
|
||||||
|
curr_fan_mode: self.curr_fan_mode,
|
||||||
|
bat_charge_limit: self.bat_charge_limit,
|
||||||
|
power_profiles: self.power_profiles,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// for parsing old v3.1.7 config
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
|
pub(crate) struct ConfigV317 {
|
||||||
|
pub gfx_mode: GfxVendors,
|
||||||
|
pub gfx_managed: bool,
|
||||||
|
pub active_profile: String,
|
||||||
|
pub toggle_profiles: Vec<String>,
|
||||||
|
#[serde(skip)]
|
||||||
|
pub curr_fan_mode: u8,
|
||||||
|
pub bat_charge_limit: u8,
|
||||||
|
pub kbd_led_brightness: u8,
|
||||||
|
pub kbd_backlight_mode: u8,
|
||||||
|
#[serde(skip)]
|
||||||
|
pub kbd_backlight_modes: Option<bool>,
|
||||||
|
pub power_profiles: BTreeMap<String, Profile>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConfigV317 {
|
||||||
|
pub(crate) fn into_current(self) -> Config {
|
||||||
|
Config {
|
||||||
|
gfx_mode: GfxVendors::Hybrid,
|
||||||
|
gfx_managed: self.gfx_managed,
|
||||||
|
active_profile: self.active_profile,
|
||||||
|
toggle_profiles: self.toggle_profiles,
|
||||||
|
curr_fan_mode: self.curr_fan_mode,
|
||||||
|
bat_charge_limit: self.bat_charge_limit,
|
||||||
|
power_profiles: self.power_profiles,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,7 +21,6 @@ use rog_types::{
|
|||||||
error::AuraError,
|
error::AuraError,
|
||||||
};
|
};
|
||||||
use rusb::{Device, DeviceHandle};
|
use rusb::{Device, DeviceHandle};
|
||||||
use std::convert::TryInto;
|
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use zbus::dbus_interface;
|
use zbus::dbus_interface;
|
||||||
@@ -30,7 +29,7 @@ use crate::GetSupported;
|
|||||||
|
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct AnimeSupportedFunctions(bool);
|
pub struct AnimeSupportedFunctions(pub bool);
|
||||||
|
|
||||||
impl GetSupported for CtrlAnimeDisplay {
|
impl GetSupported for CtrlAnimeDisplay {
|
||||||
type A = AnimeSupportedFunctions;
|
type A = AnimeSupportedFunctions;
|
||||||
@@ -60,7 +59,7 @@ pub trait Dbus {
|
|||||||
impl crate::ZbusAdd for CtrlAnimeDisplay {
|
impl crate::ZbusAdd for CtrlAnimeDisplay {
|
||||||
fn add_to_server(self, server: &mut zbus::ObjectServer) {
|
fn add_to_server(self, server: &mut zbus::ObjectServer) {
|
||||||
server
|
server
|
||||||
.at(&"/org/asuslinux/Anime".try_into().unwrap(), self)
|
.at("/org/asuslinux/Anime", self)
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
warn!("CtrlAnimeDisplay: add_to_server {}", err);
|
warn!("CtrlAnimeDisplay: add_to_server {}", err);
|
||||||
err
|
err
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ use crate::{config::Config, error::RogError, GetSupported};
|
|||||||
//use crate::dbus::DbusEvents;
|
//use crate::dbus::DbusEvents;
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use std::convert::TryInto;
|
|
||||||
use std::fs::OpenOptions;
|
use std::fs::OpenOptions;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
@@ -64,7 +63,7 @@ impl CtrlCharge {
|
|||||||
impl crate::ZbusAdd for CtrlCharge {
|
impl crate::ZbusAdd for CtrlCharge {
|
||||||
fn add_to_server(self, server: &mut zbus::ObjectServer) {
|
fn add_to_server(self, server: &mut zbus::ObjectServer) {
|
||||||
server
|
server
|
||||||
.at(&"/org/asuslinux/Charge".try_into().unwrap(), self)
|
.at("/org/asuslinux/Charge", self)
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
warn!("CtrlCharge: add_to_server {}", err);
|
warn!("CtrlCharge: add_to_server {}", err);
|
||||||
err
|
err
|
||||||
|
|||||||
@@ -6,13 +6,12 @@ use crate::{
|
|||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
use rog_types::profile::{FanLevel, ProfileEvent};
|
use rog_types::profile::{FanLevel, ProfileEvent};
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use std::convert::TryInto;
|
|
||||||
use std::fs::OpenOptions;
|
use std::fs::OpenOptions;
|
||||||
use std::io::{Read, Write};
|
use std::io::Write;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use zbus::dbus_interface;
|
use zbus::{dbus_interface, fdo::Error};
|
||||||
|
|
||||||
static FAN_TYPE_1_PATH: &str = "/sys/devices/platform/asus-nb-wmi/throttle_thermal_policy";
|
static FAN_TYPE_1_PATH: &str = "/sys/devices/platform/asus-nb-wmi/throttle_thermal_policy";
|
||||||
static FAN_TYPE_2_PATH: &str = "/sys/devices/platform/asus-nb-wmi/fan_boost_mode";
|
static FAN_TYPE_2_PATH: &str = "/sys/devices/platform/asus-nb-wmi/fan_boost_mode";
|
||||||
@@ -62,7 +61,12 @@ impl DbusFanAndCpu {
|
|||||||
cfg.read();
|
cfg.read();
|
||||||
ctrl.handle_profile_event(&event, &mut cfg)
|
ctrl.handle_profile_event(&event, &mut cfg)
|
||||||
.unwrap_or_else(|err| warn!("{}", err));
|
.unwrap_or_else(|err| warn!("{}", err));
|
||||||
self.notify_profile(&cfg.active_profile).unwrap_or(());
|
if let Some(profile) = cfg.power_profiles.get(&cfg.active_profile) {
|
||||||
|
if let Ok(json) = serde_json::to_string(profile) {
|
||||||
|
self.notify_profile(&json)
|
||||||
|
.unwrap_or_else(|err| warn!("{}", err));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -72,6 +76,7 @@ impl DbusFanAndCpu {
|
|||||||
fn next_profile(&mut self) {
|
fn next_profile(&mut self) {
|
||||||
if let Ok(mut ctrl) = self.inner.try_lock() {
|
if let Ok(mut ctrl) = self.inner.try_lock() {
|
||||||
if let Ok(mut cfg) = ctrl.config.clone().try_lock() {
|
if let Ok(mut cfg) = ctrl.config.clone().try_lock() {
|
||||||
|
cfg.read();
|
||||||
ctrl.do_next_profile(&mut cfg)
|
ctrl.do_next_profile(&mut cfg)
|
||||||
.unwrap_or_else(|err| warn!("{}", err));
|
.unwrap_or_else(|err| warn!("{}", err));
|
||||||
if let Some(profile) = cfg.power_profiles.get(&cfg.active_profile) {
|
if let Some(profile) = cfg.power_profiles.get(&cfg.active_profile) {
|
||||||
@@ -122,6 +127,54 @@ impl DbusFanAndCpu {
|
|||||||
"Failed".to_string()
|
"Failed".to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn profile_names(&self) -> String {
|
||||||
|
if let Ok(ctrl) = self.inner.try_lock() {
|
||||||
|
if let Ok(mut cfg) = ctrl.config.try_lock() {
|
||||||
|
cfg.read();
|
||||||
|
|
||||||
|
let profile_names: String = cfg
|
||||||
|
.power_profiles
|
||||||
|
.keys()
|
||||||
|
.cloned()
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join(", ");
|
||||||
|
|
||||||
|
return profile_names;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"Failed".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove(&self, profile: &str) -> zbus::fdo::Result<()> {
|
||||||
|
if let Ok(ctrl) = self.inner.try_lock() {
|
||||||
|
if let Ok(mut cfg) = ctrl.config.try_lock() {
|
||||||
|
cfg.read();
|
||||||
|
|
||||||
|
if !cfg.power_profiles.contains_key(profile) {
|
||||||
|
return Err(Error::Failed("Invalid profile specified".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.power_profiles.keys().len() == 1 {
|
||||||
|
return Err(Error::Failed("Cannot delete the last profile".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.active_profile == *profile {
|
||||||
|
return Err(Error::Failed(
|
||||||
|
"Cannot delete the active profile".to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg.power_profiles.remove(profile);
|
||||||
|
cfg.write();
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Err(Error::Failed("Failed to lock configuration".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
#[dbus_interface(signal)]
|
#[dbus_interface(signal)]
|
||||||
fn notify_profile(&self, profile: &str) -> zbus::Result<()> {}
|
fn notify_profile(&self, profile: &str) -> zbus::Result<()> {}
|
||||||
}
|
}
|
||||||
@@ -129,7 +182,7 @@ impl DbusFanAndCpu {
|
|||||||
impl crate::ZbusAdd for DbusFanAndCpu {
|
impl crate::ZbusAdd for DbusFanAndCpu {
|
||||||
fn add_to_server(self, server: &mut zbus::ObjectServer) {
|
fn add_to_server(self, server: &mut zbus::ObjectServer) {
|
||||||
server
|
server
|
||||||
.at(&"/org/asuslinux/Profile".try_into().unwrap(), self)
|
.at("/org/asuslinux/Profile", self)
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
warn!("DbusFanAndCpu: add_to_server {}", err);
|
warn!("DbusFanAndCpu: add_to_server {}", err);
|
||||||
err
|
err
|
||||||
@@ -258,7 +311,7 @@ impl CtrlFanAndCPU {
|
|||||||
if let Some(max_perc) = command.max_percentage {
|
if let Some(max_perc) = command.max_percentage {
|
||||||
profile.max_percentage = max_perc;
|
profile.max_percentage = max_perc;
|
||||||
}
|
}
|
||||||
if let Some(ref preset) = command.preset {
|
if let Some(ref preset) = command.fan_preset {
|
||||||
profile.fan_preset = preset.into();
|
profile.fan_preset = preset.into();
|
||||||
}
|
}
|
||||||
if let Some(ref curve) = command.curve {
|
if let Some(ref curve) = command.curve {
|
||||||
|
|||||||
@@ -1,17 +1,15 @@
|
|||||||
use std::error;
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::{error, process::ExitStatus};
|
||||||
|
|
||||||
use crate::error::RogError;
|
use crate::error::RogError;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum GfxError {
|
pub enum GfxError {
|
||||||
ParseVendor,
|
ParseVendor,
|
||||||
Path(String, std::io::Error),
|
|
||||||
Read(String, std::io::Error),
|
|
||||||
Write(String, std::io::Error),
|
|
||||||
Module(String, std::io::Error),
|
|
||||||
Bus(String, std::io::Error),
|
Bus(String, std::io::Error),
|
||||||
Command(String, std::io::Error),
|
DisplayManagerAction(String, ExitStatus),
|
||||||
|
DisplayManagerTimeout(String),
|
||||||
|
GsyncModeActive,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for GfxError {
|
impl fmt::Display for GfxError {
|
||||||
@@ -19,12 +17,17 @@ impl fmt::Display for GfxError {
|
|||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
GfxError::ParseVendor => write!(f, "Could not parse vendor name"),
|
GfxError::ParseVendor => write!(f, "Could not parse vendor name"),
|
||||||
GfxError::Path(path, error) => write!(f, "Path {}: {}", path, error),
|
|
||||||
GfxError::Read(path, error) => write!(f, "Read {}: {}", path, error),
|
|
||||||
GfxError::Write(path, error) => write!(f, "Write {}: {}", path, error),
|
|
||||||
GfxError::Module(func, error) => write!(f, "Module error: {}: {}", func, error),
|
|
||||||
GfxError::Bus(func, error) => write!(f, "Bus error: {}: {}", func, error),
|
GfxError::Bus(func, error) => write!(f, "Bus error: {}: {}", func, error),
|
||||||
GfxError::Command(func, error) => write!(f, "Command exec error: {}: {}", func, error),
|
GfxError::DisplayManagerAction(action, status) => {
|
||||||
|
write!(f, "Display-manager action {} failed: {}", action, status)
|
||||||
|
}
|
||||||
|
GfxError::DisplayManagerTimeout(state) => {
|
||||||
|
write!(f, "Timed out waiting for display-manager {} state", state)
|
||||||
|
}
|
||||||
|
GfxError::GsyncModeActive => write!(
|
||||||
|
f,
|
||||||
|
"Can not switch gfx modes when dedicated/G-Sync mode is active"
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+484
-258
@@ -2,19 +2,24 @@ use ctrl_gfx::error::GfxError;
|
|||||||
use ctrl_gfx::*;
|
use ctrl_gfx::*;
|
||||||
use ctrl_rog_bios::CtrlRogBios;
|
use ctrl_rog_bios::CtrlRogBios;
|
||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
use rog_types::gfx_vendors::{GfxCtrlAction, GfxVendors};
|
use logind_zbus::{
|
||||||
use std::io::Write;
|
types::{SessionClass, SessionInfo, SessionType},
|
||||||
use std::iter::FromIterator;
|
ManagerProxy, SessionProxy,
|
||||||
use std::path::Path;
|
};
|
||||||
use std::process::Command;
|
use rog_types::gfx_vendors::{GfxRequiredUserAction, GfxVendors};
|
||||||
use std::str::FromStr;
|
use std::sync::mpsc;
|
||||||
|
use std::{io::Write, ops::Add, path::Path, time::Instant};
|
||||||
|
use std::{iter::FromIterator, thread::JoinHandle};
|
||||||
|
use std::{process::Command, thread::sleep, time::Duration};
|
||||||
use std::{sync::Arc, sync::Mutex};
|
use std::{sync::Arc, sync::Mutex};
|
||||||
use sysfs_class::{PciDevice, SysClass};
|
use sysfs_class::{PciDevice, SysClass};
|
||||||
use system::{GraphicsDevice, Module, PciBus};
|
use system::{GraphicsDevice, PciBus};
|
||||||
use zbus::dbus_interface;
|
use zbus::{dbus_interface, Connection};
|
||||||
|
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
|
const THREAD_TIMEOUT_MSG: &str = "GFX: thread time exceeded 3 minutes, exiting";
|
||||||
|
|
||||||
pub struct CtrlGraphics {
|
pub struct CtrlGraphics {
|
||||||
bus: PciBus,
|
bus: PciBus,
|
||||||
_amd: Vec<GraphicsDevice>,
|
_amd: Vec<GraphicsDevice>,
|
||||||
@@ -22,61 +27,57 @@ pub struct CtrlGraphics {
|
|||||||
nvidia: Vec<GraphicsDevice>,
|
nvidia: Vec<GraphicsDevice>,
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
other: Vec<GraphicsDevice>,
|
other: Vec<GraphicsDevice>,
|
||||||
initfs_cmd: Option<Command>,
|
|
||||||
config: Arc<Mutex<Config>>,
|
config: Arc<Mutex<Config>>,
|
||||||
|
thread_kill: Arc<Mutex<Option<mpsc::Sender<bool>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Dbus {
|
trait Dbus {
|
||||||
fn vendor(&self) -> String;
|
fn vendor(&self) -> zbus::fdo::Result<GfxVendors>;
|
||||||
fn power(&self) -> String;
|
fn power(&self) -> String;
|
||||||
fn set_vendor(&mut self, vendor: String);
|
fn set_vendor(&mut self, vendor: GfxVendors) -> zbus::fdo::Result<GfxRequiredUserAction>;
|
||||||
fn notify_gfx(&self, vendor: &str) -> zbus::Result<()>;
|
fn notify_gfx(&self, vendor: &GfxVendors) -> zbus::Result<()>;
|
||||||
fn notify_action(&self, action: &str) -> zbus::Result<()>;
|
fn notify_action(&self, action: &GfxRequiredUserAction) -> zbus::Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
use std::convert::TryInto;
|
|
||||||
|
|
||||||
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
||||||
impl Dbus for CtrlGraphics {
|
impl Dbus for CtrlGraphics {
|
||||||
fn vendor(&self) -> String {
|
fn vendor(&self) -> zbus::fdo::Result<GfxVendors> {
|
||||||
Self::get_vendor().unwrap_or_else(|err| format!("Get vendor failed: {}", err))
|
self.get_gfx_mode().map_err(|err| {
|
||||||
|
error!("GFX: {}", err);
|
||||||
|
zbus::fdo::Error::Failed(format!("GFX fail: {}", err))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn power(&self) -> String {
|
fn power(&self) -> String {
|
||||||
Self::get_runtime_status().unwrap_or_else(|err| format!("Get power status failed: {}", err))
|
Self::get_runtime_status().unwrap_or_else(|err| format!("Get power status failed: {}", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_vendor(&mut self, vendor: String) {
|
fn set_vendor(&mut self, vendor: GfxVendors) -> zbus::fdo::Result<GfxRequiredUserAction> {
|
||||||
if let Ok(tmp) = GfxVendors::from_str(&vendor) {
|
info!("GFX: Switching gfx mode to {}", <&str>::from(vendor));
|
||||||
let action = self.set(tmp).unwrap_or_else(|err| {
|
let msg = self.set_gfx_config(vendor).map_err(|err| {
|
||||||
warn!("{}", err);
|
error!("GFX: {}", err);
|
||||||
format!("Failed: {}", err.to_string())
|
zbus::fdo::Error::Failed(format!("GFX fail: {}", err))
|
||||||
});
|
})?;
|
||||||
self.notify_gfx(&vendor)
|
self.notify_gfx(&vendor)
|
||||||
.unwrap_or_else(|err| warn!("{}", err));
|
.unwrap_or_else(|err| warn!("GFX: {}", err));
|
||||||
self.notify_action(&action)
|
self.notify_action(&msg)
|
||||||
.unwrap_or_else(|err| warn!("{}", err));
|
.unwrap_or_else(|err| warn!("GFX: {}", err));
|
||||||
}
|
Ok(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[dbus_interface(signal)]
|
#[dbus_interface(signal)]
|
||||||
fn notify_gfx(&self, vendor: &str) -> zbus::Result<()> {}
|
fn notify_gfx(&self, vendor: &GfxVendors) -> zbus::Result<()> {}
|
||||||
|
|
||||||
#[dbus_interface(signal)]
|
#[dbus_interface(signal)]
|
||||||
fn notify_action(&self, action: &str) -> zbus::Result<()> {}
|
fn notify_action(&self, action: &GfxRequiredUserAction) -> zbus::Result<()> {}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ZbusAdd for CtrlGraphics {
|
impl ZbusAdd for CtrlGraphics {
|
||||||
fn add_to_server(self, server: &mut zbus::ObjectServer) {
|
fn add_to_server(self, server: &mut zbus::ObjectServer) {
|
||||||
server
|
server
|
||||||
.at(
|
.at("/org/asuslinux/Gfx", self)
|
||||||
&"/org/asuslinux/Gfx"
|
|
||||||
.try_into()
|
|
||||||
.expect("Couldn't add to zbus"),
|
|
||||||
self,
|
|
||||||
)
|
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
warn!("CtrlGraphics: add_to_server {}", err);
|
warn!("GFX: CtrlGraphics: add_to_server {}", err);
|
||||||
err
|
err
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
@@ -86,7 +87,7 @@ impl ZbusAdd for CtrlGraphics {
|
|||||||
impl Reloadable for CtrlGraphics {
|
impl Reloadable for CtrlGraphics {
|
||||||
fn reload(&mut self) -> Result<(), RogError> {
|
fn reload(&mut self) -> Result<(), RogError> {
|
||||||
self.auto_power()?;
|
self.auto_power()?;
|
||||||
info!("Reloaded gfx mode: {:?}", CtrlGraphics::get_vendor()?);
|
info!("GFX: Reloaded gfx mode: {:?}", self.get_gfx_mode()?);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,7 +96,7 @@ impl CtrlGraphics {
|
|||||||
pub fn new(config: Arc<Mutex<Config>>) -> std::io::Result<CtrlGraphics> {
|
pub fn new(config: Arc<Mutex<Config>>) -> std::io::Result<CtrlGraphics> {
|
||||||
let bus = PciBus::new()?;
|
let bus = PciBus::new()?;
|
||||||
|
|
||||||
info!("Rescanning PCI bus");
|
info!("GFX: Rescanning PCI bus");
|
||||||
bus.rescan()?;
|
bus.rescan()?;
|
||||||
|
|
||||||
let devs = PciDevice::all()?;
|
let devs = PciDevice::all()?;
|
||||||
@@ -106,7 +107,7 @@ impl CtrlGraphics {
|
|||||||
for func in devs.iter() {
|
for func in devs.iter() {
|
||||||
if let Some(func_slot) = func.id().split('.').next() {
|
if let Some(func_slot) = func.id().split('.').next() {
|
||||||
if func_slot == parent_slot {
|
if func_slot == parent_slot {
|
||||||
info!("{}: Function for {}", func.id(), parent.id());
|
info!("GFX: {}: Function for {}", func.id(), parent.id());
|
||||||
functions.push(func.clone());
|
functions.push(func.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -124,185 +125,74 @@ impl CtrlGraphics {
|
|||||||
if 0x03 == (c >> 16) & 0xFF {
|
if 0x03 == (c >> 16) & 0xFF {
|
||||||
match dev.vendor()? {
|
match dev.vendor()? {
|
||||||
0x1002 => {
|
0x1002 => {
|
||||||
info!("{}: AMD graphics", dev.id());
|
info!("GFX: {}: AMD graphics", dev.id());
|
||||||
amd.push(GraphicsDevice::new(dev.id().to_owned(), functions(&dev)));
|
amd.push(GraphicsDevice::new(dev.id().to_owned(), functions(&dev)));
|
||||||
}
|
}
|
||||||
0x10DE => {
|
0x10DE => {
|
||||||
info!("{}: NVIDIA graphics", dev.id());
|
info!("GFX: {}: NVIDIA graphics", dev.id());
|
||||||
nvidia.push(GraphicsDevice::new(dev.id().to_owned(), functions(&dev)));
|
nvidia.push(GraphicsDevice::new(dev.id().to_owned(), functions(&dev)));
|
||||||
}
|
}
|
||||||
0x8086 => {
|
0x8086 => {
|
||||||
info!("{}: Intel graphics", dev.id());
|
info!("GFX: {}: Intel graphics", dev.id());
|
||||||
intel.push(GraphicsDevice::new(dev.id().to_owned(), functions(&dev)));
|
intel.push(GraphicsDevice::new(dev.id().to_owned(), functions(&dev)));
|
||||||
}
|
}
|
||||||
vendor => {
|
vendor => {
|
||||||
info!("{}: Other({:X}) graphics", dev.id(), vendor);
|
info!("GFX: {}: Other({:X}) graphics", dev.id(), vendor);
|
||||||
other.push(GraphicsDevice::new(dev.id().to_owned(), functions(&dev)));
|
other.push(GraphicsDevice::new(dev.id().to_owned(), functions(&dev)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut initfs_cmd = None;
|
|
||||||
|
|
||||||
if Path::new(INITRAMFS_PATH).exists() {
|
|
||||||
let mut cmd = Command::new("update-initramfs");
|
|
||||||
cmd.arg("-u");
|
|
||||||
initfs_cmd = Some(cmd);
|
|
||||||
info!("Using initramfs update command 'update-initramfs'");
|
|
||||||
} else if Path::new(DRACUT_PATH).exists() {
|
|
||||||
let mut cmd = Command::new("dracut");
|
|
||||||
cmd.arg("-f");
|
|
||||||
initfs_cmd = Some(cmd);
|
|
||||||
info!("Using initramfs update command 'dracut'");
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(CtrlGraphics {
|
Ok(CtrlGraphics {
|
||||||
bus,
|
bus,
|
||||||
_amd: amd,
|
_amd: amd,
|
||||||
_intel: intel,
|
_intel: intel,
|
||||||
nvidia,
|
nvidia,
|
||||||
other,
|
other,
|
||||||
initfs_cmd,
|
|
||||||
config,
|
config,
|
||||||
|
thread_kill: Arc::new(Mutex::new(None)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_prime_discrete() -> Result<String, RogError> {
|
pub fn bus(&self) -> PciBus {
|
||||||
let s = std::fs::read_to_string(PRIME_DISCRETE_PATH)
|
self.bus.clone()
|
||||||
.map_err(|err| GfxError::Read(PRIME_DISCRETE_PATH.into(), err))?
|
|
||||||
.trim()
|
|
||||||
.to_owned();
|
|
||||||
Ok(s)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_prime_discrete(mode: &str) -> Result<(), RogError> {
|
pub fn devices(&self) -> Vec<GraphicsDevice> {
|
||||||
std::fs::write(PRIME_DISCRETE_PATH, mode)
|
self.nvidia.clone()
|
||||||
.map_err(|err| GfxError::Read(PRIME_DISCRETE_PATH.into(), err))?;
|
}
|
||||||
Ok(())
|
|
||||||
|
/// Save the selected `Vendor` mode to config
|
||||||
|
fn save_gfx_mode(vendor: GfxVendors, config: Arc<Mutex<Config>>) {
|
||||||
|
if let Ok(mut config) = config.lock() {
|
||||||
|
config.gfx_mode = vendor;
|
||||||
|
config.write();
|
||||||
|
}
|
||||||
|
// TODO: Error here
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Associated method to get which vendor mode is set
|
/// Associated method to get which vendor mode is set
|
||||||
pub fn get_vendor() -> Result<String, RogError> {
|
pub fn get_gfx_mode(&self) -> Result<GfxVendors, RogError> {
|
||||||
let mode = match Self::get_prime_discrete() {
|
if let Ok(config) = self.config.lock() {
|
||||||
Ok(m) => m,
|
return Ok(config.gfx_mode);
|
||||||
Err(_) => "nvidia".to_string(),
|
}
|
||||||
};
|
// TODO: Error here
|
||||||
let modules = Module::all().map_err(|err| GfxError::Read("get_vendor".into(), err))?;
|
Ok(GfxVendors::Hybrid)
|
||||||
|
|
||||||
let driver_loaded = modules
|
|
||||||
.iter()
|
|
||||||
.any(|module| module.name == "nouveau" || module.name == "nvidia");
|
|
||||||
|
|
||||||
let vendor = if mode == "off" {
|
|
||||||
if driver_loaded {
|
|
||||||
info!("dGPU driver loaded for compute mode");
|
|
||||||
"compute".to_string()
|
|
||||||
} else {
|
|
||||||
info!("No dGPU driver loaded");
|
|
||||||
"integrated".to_string()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
info!("Assuming dGPU driver loaded");
|
|
||||||
if mode == "on-demand" {
|
|
||||||
"hybrid".to_string()
|
|
||||||
} else {
|
|
||||||
"nvidia".to_string()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(vendor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_switching_prime_modes(&self, vendor: &GfxVendors) -> Result<bool, RogError> {
|
fn get_runtime_status() -> Result<String, RogError> {
|
||||||
let prev_mode = GfxVendors::from_str(&Self::get_vendor()?)?;
|
const PATH: &str = "/sys/bus/pci/devices/0000:01:00.0/power/runtime_status";
|
||||||
if prev_mode == GfxVendors::Integrated
|
let buf = std::fs::read_to_string(PATH).map_err(|err| RogError::Read(PATH.into(), err))?;
|
||||||
&& (*vendor == GfxVendors::Hybrid || *vendor == GfxVendors::Nvidia)
|
Ok(buf)
|
||||||
{
|
|
||||||
return Ok(true);
|
|
||||||
}
|
|
||||||
if (prev_mode == GfxVendors::Hybrid || prev_mode == GfxVendors::Nvidia)
|
|
||||||
&& *vendor == GfxVendors::Integrated
|
|
||||||
{
|
|
||||||
return Ok(true);
|
|
||||||
}
|
|
||||||
if let Ok(config) = self.config.clone().try_lock() {
|
|
||||||
if CtrlRogBios::has_dedicated_gfx_toggle() && config.gfx_nv_mode_is_dedicated {
|
|
||||||
if prev_mode == GfxVendors::Hybrid && *vendor == GfxVendors::Nvidia {
|
|
||||||
return Ok(true);
|
|
||||||
}
|
|
||||||
if *vendor == GfxVendors::Hybrid && prev_mode == GfxVendors::Nvidia {
|
|
||||||
return Ok(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_gfx_config(vendor: GfxVendors) -> Result<(), RogError> {
|
fn toggle_fallback_service(vendor: GfxVendors) -> Result<(), RogError> {
|
||||||
let mode = if vendor == GfxVendors::Hybrid {
|
|
||||||
"on-demand\n"
|
|
||||||
} else if vendor == GfxVendors::Nvidia {
|
|
||||||
"on\n"
|
|
||||||
} else {
|
|
||||||
// Integrated or Compute
|
|
||||||
"off\n"
|
|
||||||
};
|
|
||||||
|
|
||||||
info!("Setting {} to {}", PRIME_DISCRETE_PATH, mode);
|
|
||||||
Self::set_prime_discrete(mode)?;
|
|
||||||
|
|
||||||
{
|
|
||||||
info!("Writing {}", MODPROBE_PATH);
|
|
||||||
|
|
||||||
let mut file = std::fs::OpenOptions::new()
|
|
||||||
.create(true)
|
|
||||||
.truncate(true)
|
|
||||||
.write(true)
|
|
||||||
.open(MODPROBE_PATH)
|
|
||||||
.map_err(|err| GfxError::Path(MODPROBE_PATH.into(), err))?;
|
|
||||||
|
|
||||||
let text = if vendor == GfxVendors::Hybrid {
|
|
||||||
MODPROBE_HYBRID
|
|
||||||
} else if vendor == GfxVendors::Compute {
|
|
||||||
MODPROBE_COMPUTE
|
|
||||||
} else if vendor == GfxVendors::Nvidia {
|
|
||||||
MODPROBE_NVIDIA
|
|
||||||
} else {
|
|
||||||
MODPROBE_INTEGRATED
|
|
||||||
};
|
|
||||||
|
|
||||||
file.write_all(text)
|
|
||||||
.and_then(|_| file.sync_all())
|
|
||||||
.map_err(|err| GfxError::Write(MODPROBE_PATH.into(), err))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
info!("Writing {}", PRIMARY_GPU_XORG_PATH);
|
|
||||||
|
|
||||||
// begin section for non-separated Nvidia xorg modules
|
|
||||||
// eg, not put in their own directory
|
|
||||||
let mut file = std::fs::OpenOptions::new()
|
|
||||||
.create(true)
|
|
||||||
.truncate(true)
|
|
||||||
.write(true)
|
|
||||||
.open(PRIMARY_GPU_XORG_PATH)
|
|
||||||
.map_err(|err| GfxError::Write(PRIMARY_GPU_XORG_PATH.into(), err))?;
|
|
||||||
|
|
||||||
let text = if vendor == GfxVendors::Nvidia {
|
|
||||||
[PRIMARY_GPU_BEGIN, PRIMARY_GPU_NVIDIA, PRIMARY_GPU_END].concat()
|
|
||||||
} else {
|
|
||||||
[PRIMARY_GPU_BEGIN, PRIMARY_GPU_END].concat()
|
|
||||||
};
|
|
||||||
|
|
||||||
file.write_all(&text)
|
|
||||||
.and_then(|_| file.sync_all())
|
|
||||||
.map_err(|err| GfxError::Write(MODPROBE_PATH.into(), err))?;
|
|
||||||
|
|
||||||
let action = if vendor == GfxVendors::Nvidia {
|
let action = if vendor == GfxVendors::Nvidia {
|
||||||
info!("Enabling nvidia-fallback.service");
|
info!("GFX: Enabling nvidia-fallback.service");
|
||||||
"enable"
|
"enable"
|
||||||
} else {
|
} else {
|
||||||
info!("Disabling nvidia-fallback.service");
|
info!("GFX: Disabling nvidia-fallback.service");
|
||||||
"disable"
|
"disable"
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -310,7 +200,7 @@ impl CtrlGraphics {
|
|||||||
.arg(action)
|
.arg(action)
|
||||||
.arg("nvidia-fallback.service")
|
.arg("nvidia-fallback.service")
|
||||||
.status()
|
.status()
|
||||||
.map_err(|err| GfxError::Command("systemctl".into(), err))?;
|
.map_err(|err| RogError::Command("systemctl".into(), err))?;
|
||||||
|
|
||||||
if !status.success() {
|
if !status.success() {
|
||||||
// Error is ignored in case this service is removed
|
// Error is ignored in case this service is removed
|
||||||
@@ -319,92 +209,428 @@ impl CtrlGraphics {
|
|||||||
status
|
status
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write out config files if required, enable/disable relevant services, and update the ramdisk
|
fn write_xorg_conf(vendor: GfxVendors) -> Result<(), RogError> {
|
||||||
fn set(&mut self, vendor: GfxVendors) -> Result<String, RogError> {
|
let text = if vendor == GfxVendors::Nvidia {
|
||||||
// Switching from hybrid to/from nvidia shouldn't require a ramdisk update
|
[PRIMARY_GPU_BEGIN, PRIMARY_GPU_NVIDIA, PRIMARY_GPU_END].concat()
|
||||||
// or a reboot.
|
|
||||||
let reboot = self.is_switching_prime_modes(&vendor)?;
|
|
||||||
|
|
||||||
if CtrlRogBios::has_dedicated_gfx_toggle() {
|
|
||||||
if let Ok(config) = self.config.clone().try_lock() {
|
|
||||||
// Switch to dedicated if config says to do so
|
|
||||||
if config.gfx_nv_mode_is_dedicated && vendor == GfxVendors::Nvidia {
|
|
||||||
CtrlRogBios::set_gfx_mode(true)
|
|
||||||
.unwrap_or_else(|err| warn!("Gfx controller: {}", err));
|
|
||||||
} else if let Ok(ded) = CtrlRogBios::get_gfx_mode() {
|
|
||||||
// otherwise if switching to non-Nvidia mode turn off dedicated mode
|
|
||||||
if ded == 1 && vendor != GfxVendors::Nvidia {
|
|
||||||
CtrlRogBios::set_gfx_mode(false)
|
|
||||||
.unwrap_or_else(|err| warn!("Gfx controller: {}", err));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Self::set_gfx_config(vendor.clone())?;
|
|
||||||
|
|
||||||
let mut required_action = GfxCtrlAction::None;
|
|
||||||
if reboot {
|
|
||||||
info!("Updating initramfs");
|
|
||||||
if let Some(cmd) = self.initfs_cmd.as_mut() {
|
|
||||||
// If switching to Nvidia dedicated we need these modules included
|
|
||||||
if Path::new(DRACUT_PATH).exists() && vendor == GfxVendors::Nvidia {
|
|
||||||
cmd.arg("--add-drivers");
|
|
||||||
cmd.arg("nvidia nvidia-drm nvidia-modeset nvidia-uvm");
|
|
||||||
info!("System uses dracut, forcing nvidia modules to be included in init");
|
|
||||||
}
|
|
||||||
|
|
||||||
let status = cmd
|
|
||||||
.status()
|
|
||||||
.map_err(|err| GfxError::Write(format!("{:?}", cmd), err))?;
|
|
||||||
if !status.success() {
|
|
||||||
error!("Ram disk update failed");
|
|
||||||
return Ok("Ram disk update failed".into());
|
|
||||||
} else {
|
|
||||||
info!("Successfully updated iniramfs");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
required_action = GfxCtrlAction::Reboot;
|
|
||||||
} else if !reboot {
|
|
||||||
required_action = GfxCtrlAction::RestartX;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(required_action.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_runtime_status() -> Result<String, RogError> {
|
|
||||||
const PATH: &str = "/sys/bus/pci/devices/0000:01:00.0/power/runtime_status";
|
|
||||||
let buf = std::fs::read_to_string(PATH).map_err(|err| GfxError::Read(PATH.into(), err))?;
|
|
||||||
Ok(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_power(&self, power: bool) -> Result<(), RogError> {
|
|
||||||
if power {
|
|
||||||
info!("Enabling graphics power");
|
|
||||||
self.bus
|
|
||||||
.rescan()
|
|
||||||
.map_err(|err| GfxError::Bus("bus rescan error".into(), err))?;
|
|
||||||
} else {
|
} else {
|
||||||
info!("Disabling graphics power");
|
[PRIMARY_GPU_BEGIN, PRIMARY_GPU_END].concat()
|
||||||
|
};
|
||||||
|
|
||||||
// Unbind NVIDIA graphics devices and their functions
|
if !Path::new(XORG_PATH).exists() {
|
||||||
let unbinds = self.nvidia.iter().map(|dev| dev.unbind());
|
std::fs::create_dir(XORG_PATH).map_err(|err| RogError::Write(XORG_PATH.into(), err))?;
|
||||||
|
}
|
||||||
|
|
||||||
// Remove NVIDIA graphics devices and their functions
|
let file = XORG_PATH.to_string().add(XORG_FILE);
|
||||||
let removes = self.nvidia.iter().map(|dev| dev.remove());
|
info!("GFX: Writing {}", file);
|
||||||
|
let mut file = std::fs::OpenOptions::new()
|
||||||
|
.create(true)
|
||||||
|
.truncate(true)
|
||||||
|
.write(true)
|
||||||
|
.open(&file)
|
||||||
|
.map_err(|err| RogError::Write(file, err))?;
|
||||||
|
|
||||||
Result::from_iter(unbinds.chain(removes))
|
file.write_all(&text)
|
||||||
.map_err(|err| GfxError::Command("device unbind error".into(), err))?;
|
.and_then(|_| file.sync_all())
|
||||||
|
.map_err(|err| RogError::Write(MODPROBE_PATH.into(), err))?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_vfio_conf(devices: &[GraphicsDevice]) -> Vec<u8> {
|
||||||
|
let mut vifo = MODPROBE_VFIO.to_vec();
|
||||||
|
for (d_count, dev) in devices.iter().enumerate() {
|
||||||
|
for (f_count, func) in dev.functions().iter().enumerate() {
|
||||||
|
let vendor = func.vendor().unwrap();
|
||||||
|
let device = func.device().unwrap();
|
||||||
|
unsafe {
|
||||||
|
vifo.append(format!("{:x}", vendor).as_mut_vec());
|
||||||
|
}
|
||||||
|
vifo.append(&mut vec![b':']);
|
||||||
|
unsafe {
|
||||||
|
vifo.append(format!("{:x}", device).as_mut_vec());
|
||||||
|
}
|
||||||
|
if f_count < dev.functions().len() - 1 {
|
||||||
|
vifo.append(&mut vec![b',']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if d_count < dev.functions().len() - 1 {
|
||||||
|
vifo.append(&mut vec![b',']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut conf = MODPROBE_INTEGRATED.to_vec();
|
||||||
|
conf.append(&mut vifo);
|
||||||
|
conf
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_modprobe_conf(vendor: GfxVendors, devices: &[GraphicsDevice]) -> Result<(), RogError> {
|
||||||
|
info!("GFX: Writing {}", MODPROBE_PATH);
|
||||||
|
let content = match vendor {
|
||||||
|
GfxVendors::Nvidia | GfxVendors::Hybrid | GfxVendors::Compute => MODPROBE_BASE.to_vec(),
|
||||||
|
GfxVendors::Vfio => Self::get_vfio_conf(devices),
|
||||||
|
// GfxVendors::Compute => {}
|
||||||
|
GfxVendors::Integrated => MODPROBE_INTEGRATED.to_vec(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut file = std::fs::OpenOptions::new()
|
||||||
|
.create(true)
|
||||||
|
.truncate(true)
|
||||||
|
.write(true)
|
||||||
|
.open(MODPROBE_PATH)
|
||||||
|
.map_err(|err| RogError::Path(MODPROBE_PATH.into(), err))?;
|
||||||
|
|
||||||
|
file.write_all(&content)
|
||||||
|
.and_then(|_| file.sync_all())
|
||||||
|
.map_err(|err| RogError::Write(MODPROBE_PATH.into(), err))?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unbind_remove_nvidia(devices: &[GraphicsDevice]) -> Result<(), RogError> {
|
||||||
|
// Unbind NVIDIA graphics devices and their functions
|
||||||
|
let unbinds = devices.iter().map(|dev| dev.unbind());
|
||||||
|
// Remove NVIDIA graphics devices and their functions
|
||||||
|
let removes = devices.iter().map(|dev| dev.remove());
|
||||||
|
Result::from_iter(unbinds.chain(removes))
|
||||||
|
.map_err(|err| RogError::Command("device unbind error".into(), err))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unbind_only(devices: &[GraphicsDevice]) -> Result<(), RogError> {
|
||||||
|
let unbinds = devices.iter().map(|dev| dev.unbind());
|
||||||
|
Result::from_iter(unbinds)
|
||||||
|
.map_err(|err| RogError::Command("device unbind error".into(), err))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_driver_action(driver: &str, action: &str) -> Result<(), RogError> {
|
||||||
|
let mut cmd = Command::new(action);
|
||||||
|
cmd.arg(driver);
|
||||||
|
|
||||||
|
let mut count = 0;
|
||||||
|
const MAX_TRIES: i32 = 6;
|
||||||
|
loop {
|
||||||
|
if count > MAX_TRIES {
|
||||||
|
let msg = format!("{} {} failed for unknown reason", action, driver);
|
||||||
|
error!("GFX: {}", msg);
|
||||||
|
return Ok(()); //Err(RogError::Modprobe(msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
let output = cmd
|
||||||
|
.output()
|
||||||
|
.map_err(|err| RogError::Command(format!("{:?}", cmd), err))?;
|
||||||
|
if !output.status.success() {
|
||||||
|
if output
|
||||||
|
.stderr
|
||||||
|
.ends_with("is not currently loaded\n".as_bytes())
|
||||||
|
{
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
if output.stderr.ends_with("Permission denied\n".as_bytes()) {
|
||||||
|
warn!(
|
||||||
|
"{} {} failed: {:?}",
|
||||||
|
action,
|
||||||
|
driver,
|
||||||
|
String::from_utf8_lossy(&output.stderr)
|
||||||
|
);
|
||||||
|
warn!("GFX: It may be safe to ignore the above error, run `lsmod |grep {}` to confirm modules loaded", driver);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
if count >= MAX_TRIES {
|
||||||
|
let msg = format!(
|
||||||
|
"{} {} failed: {:?}",
|
||||||
|
action,
|
||||||
|
driver,
|
||||||
|
String::from_utf8_lossy(&output.stderr)
|
||||||
|
);
|
||||||
|
return Err(RogError::Modprobe(msg));
|
||||||
|
}
|
||||||
|
} else if output.status.success() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
count += 1;
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(250));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_display_manager_action(action: &str) -> Result<(), RogError> {
|
||||||
|
let mut cmd = Command::new("systemctl");
|
||||||
|
cmd.arg(action);
|
||||||
|
cmd.arg(DISPLAY_MANAGER);
|
||||||
|
|
||||||
|
let status = cmd
|
||||||
|
.status()
|
||||||
|
.map_err(|err| RogError::Command(format!("{:?}", cmd), err))?;
|
||||||
|
if !status.success() {
|
||||||
|
let msg = format!(
|
||||||
|
"systemctl {} {} failed: {:?}",
|
||||||
|
action, DISPLAY_MANAGER, status
|
||||||
|
);
|
||||||
|
return Err(GfxError::DisplayManagerAction(msg, status).into());
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wait_display_manager_state(state: &str) -> Result<(), RogError> {
|
||||||
|
let mut cmd = Command::new("systemctl");
|
||||||
|
cmd.arg("is-active");
|
||||||
|
cmd.arg(DISPLAY_MANAGER);
|
||||||
|
|
||||||
|
let mut count = 0;
|
||||||
|
|
||||||
|
while count <= 5 {
|
||||||
|
let output = cmd
|
||||||
|
.output()
|
||||||
|
.map_err(|err| RogError::Command(format!("{:?}", cmd), err))?;
|
||||||
|
if output.stdout.starts_with(state.as_bytes()) {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(500));
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
Err(GfxError::DisplayManagerTimeout(state.into()).into())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Determine if we need to logout/thread. Integrated<->Vfio mode does not
|
||||||
|
/// require logout.
|
||||||
|
fn logout_required(&self, vendor: GfxVendors) -> GfxRequiredUserAction {
|
||||||
|
if let Ok(config) = self.config.lock() {
|
||||||
|
let current = config.gfx_mode;
|
||||||
|
if matches!(current, GfxVendors::Integrated | GfxVendors::Vfio)
|
||||||
|
&& matches!(vendor, GfxVendors::Integrated | GfxVendors::Vfio)
|
||||||
|
{
|
||||||
|
return GfxRequiredUserAction::None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GfxRequiredUserAction::Logout
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Write the config changes and add/remove drivers and devices depending
|
||||||
|
/// on selected mode:
|
||||||
|
///
|
||||||
|
/// Tasks:
|
||||||
|
/// - write xorg config
|
||||||
|
/// - write modprobe config
|
||||||
|
/// - rescan for devices
|
||||||
|
/// + add drivers
|
||||||
|
/// + or remove drivers and devices
|
||||||
|
///
|
||||||
|
/// The daemon needs direct access to this function when it detects that the
|
||||||
|
pub fn do_vendor_tasks(
|
||||||
|
vendor: GfxVendors,
|
||||||
|
devices: &[GraphicsDevice],
|
||||||
|
bus: &PciBus,
|
||||||
|
) -> Result<(), RogError> {
|
||||||
|
// Rescan before doing remove or add drivers
|
||||||
|
bus.rescan()?;
|
||||||
|
//
|
||||||
|
Self::write_xorg_conf(vendor)?;
|
||||||
|
// Write different modprobe to enable boot control to work
|
||||||
|
Self::write_modprobe_conf(vendor, devices)?;
|
||||||
|
|
||||||
|
match vendor {
|
||||||
|
GfxVendors::Nvidia | GfxVendors::Hybrid | GfxVendors::Compute => {
|
||||||
|
for driver in VFIO_DRIVERS.iter() {
|
||||||
|
Self::do_driver_action(driver, "rmmod")?;
|
||||||
|
}
|
||||||
|
for driver in NVIDIA_DRIVERS.iter() {
|
||||||
|
Self::do_driver_action(driver, "modprobe")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GfxVendors::Vfio => {
|
||||||
|
for driver in NVIDIA_DRIVERS.iter() {
|
||||||
|
Self::do_driver_action(driver, "rmmod")?;
|
||||||
|
}
|
||||||
|
Self::unbind_only(&devices)?;
|
||||||
|
Self::do_driver_action("vfio-pci", "modprobe")?;
|
||||||
|
}
|
||||||
|
GfxVendors::Integrated => {
|
||||||
|
for driver in VFIO_DRIVERS.iter() {
|
||||||
|
Self::do_driver_action(driver, "rmmod")?;
|
||||||
|
}
|
||||||
|
for driver in NVIDIA_DRIVERS.iter() {
|
||||||
|
Self::do_driver_action(driver, "rmmod")?;
|
||||||
|
}
|
||||||
|
Self::unbind_remove_nvidia(&devices)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn auto_power(&self) -> Result<(), RogError> {
|
fn graphical_session_alive(
|
||||||
let vendor = CtrlGraphics::get_vendor()?;
|
connection: &Connection,
|
||||||
self.set_power(vendor != "integrated")
|
sessions: &[SessionInfo],
|
||||||
|
) -> Result<bool, RogError> {
|
||||||
|
for session in sessions {
|
||||||
|
let session_proxy = SessionProxy::new(&connection, session)?;
|
||||||
|
if session_proxy.get_class()? == SessionClass::User {
|
||||||
|
match session_proxy.get_type()? {
|
||||||
|
SessionType::X11 | SessionType::Wayland | SessionType::MIR => {
|
||||||
|
//if session_proxy.get_active()? {
|
||||||
|
return Ok(true);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Spools until all user sessions are ended then switches to requested mode
|
||||||
|
fn fire_starter(
|
||||||
|
vendor: GfxVendors,
|
||||||
|
devices: Vec<GraphicsDevice>,
|
||||||
|
bus: PciBus,
|
||||||
|
thread_stop: mpsc::Receiver<bool>,
|
||||||
|
config: Arc<Mutex<Config>>,
|
||||||
|
) -> Result<String, RogError> {
|
||||||
|
info!("GFX: display-manager thread started");
|
||||||
|
|
||||||
|
const SLEEP_PERIOD: Duration = Duration::from_millis(100);
|
||||||
|
let start_time = Instant::now();
|
||||||
|
|
||||||
|
let connection = Connection::new_system()?;
|
||||||
|
let manager = ManagerProxy::new(&connection)?;
|
||||||
|
let mut sessions = manager.list_sessions()?;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let tmp = manager.list_sessions()?;
|
||||||
|
if !tmp.iter().eq(&sessions) {
|
||||||
|
warn!("GFX: Sessions list changed");
|
||||||
|
warn!("GFX: Old list:\n{:?}\nNew list:\n{:?}", &sessions, &tmp);
|
||||||
|
sessions = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !Self::graphical_session_alive(&connection, &sessions)? {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Ok(stop) = thread_stop.try_recv() {
|
||||||
|
if stop {
|
||||||
|
return Ok("Graphics mode change was cancelled".into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// exit if 3 minutes pass
|
||||||
|
if Instant::now().duration_since(start_time).as_secs() > 180 {
|
||||||
|
warn!("{}", THREAD_TIMEOUT_MSG);
|
||||||
|
return Ok(THREAD_TIMEOUT_MSG.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't spin at max speed
|
||||||
|
sleep(SLEEP_PERIOD);
|
||||||
|
}
|
||||||
|
|
||||||
|
info!("GFX: all graphical user sessions ended, continuing");
|
||||||
|
Self::do_display_manager_action("stop")?;
|
||||||
|
|
||||||
|
match Self::wait_display_manager_state("inactive") {
|
||||||
|
Ok(_) => info!("GFX: display-manager stopped"),
|
||||||
|
Err(err) => {
|
||||||
|
warn!("GFX: {}", err);
|
||||||
|
warn!("GFX: Retry stop display manager");
|
||||||
|
Self::do_display_manager_action("stop")?;
|
||||||
|
Self::wait_display_manager_state("inactive")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Self::do_vendor_tasks(vendor, &devices, &bus)?;
|
||||||
|
Self::do_display_manager_action("start")?;
|
||||||
|
|
||||||
|
if Self::wait_display_manager_state("active").is_err() {
|
||||||
|
error!("GFX: display-manager failed to start normally, attempting restart");
|
||||||
|
Self::do_display_manager_action("restart")?;
|
||||||
|
Self::wait_display_manager_state("active")?;
|
||||||
|
}
|
||||||
|
// Save selected mode in case of reboot
|
||||||
|
Self::save_gfx_mode(vendor, config);
|
||||||
|
info!("GFX: display-manager started");
|
||||||
|
|
||||||
|
let v: &str = vendor.into();
|
||||||
|
info!("GFX: Graphics mode changed to {} successfully", v);
|
||||||
|
Ok(format!("Graphics mode changed to {} successfully", v))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cancel_thread(&self) {
|
||||||
|
if let Ok(lock) = self.thread_kill.lock() {
|
||||||
|
if let Some(tx) = lock.as_ref() {
|
||||||
|
// Cancel the running thread
|
||||||
|
info!("GFX: Cancelling previous thread");
|
||||||
|
tx.send(true)
|
||||||
|
.map_err(|err| {
|
||||||
|
warn!("GFX: {}", err);
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The thread is used only in cases where a logout is required
|
||||||
|
fn setup_thread(&mut self, vendor: GfxVendors) {
|
||||||
|
let config = self.config.clone();
|
||||||
|
let devices = self.nvidia.clone();
|
||||||
|
let bus = self.bus.clone();
|
||||||
|
let (tx, rx) = mpsc::channel();
|
||||||
|
if let Ok(mut lock) = self.thread_kill.lock() {
|
||||||
|
*lock = Some(tx);
|
||||||
|
}
|
||||||
|
let killer = self.thread_kill.clone();
|
||||||
|
|
||||||
|
let _join: JoinHandle<()> = std::thread::spawn(move || {
|
||||||
|
Self::fire_starter(vendor, devices, bus, rx, config)
|
||||||
|
.map_err(|err| {
|
||||||
|
error!("GFX: {}", err);
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
// clear the tx/rx when done
|
||||||
|
if let Ok(mut lock) = killer.try_lock() {
|
||||||
|
*lock = None;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initiates a mode change by starting a thread that will wait until all
|
||||||
|
/// graphical sessions are exited before performing the tasks required
|
||||||
|
/// to switch modes.
|
||||||
|
///
|
||||||
|
/// For manually calling (not on boot/startup) via dbus
|
||||||
|
pub fn set_gfx_config(
|
||||||
|
&mut self,
|
||||||
|
vendor: GfxVendors,
|
||||||
|
) -> Result<GfxRequiredUserAction, RogError> {
|
||||||
|
if let Ok(gsync) = CtrlRogBios::get_gfx_mode() {
|
||||||
|
if gsync == 1 {
|
||||||
|
return Err(GfxError::GsyncModeActive.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Must always cancel any thread running
|
||||||
|
self.cancel_thread();
|
||||||
|
// determine which method we need here
|
||||||
|
let action_required = self.logout_required(vendor);
|
||||||
|
if matches!(action_required, GfxRequiredUserAction::Logout) {
|
||||||
|
// Yeah need the thread to check if all users are logged out
|
||||||
|
info!("GFX: mode change requires a logout to complete");
|
||||||
|
self.setup_thread(vendor);
|
||||||
|
} else {
|
||||||
|
// Okay cool, we can switch on/off vfio
|
||||||
|
info!("GFX: mode change does not require logout");
|
||||||
|
let devices = self.nvidia.clone();
|
||||||
|
let bus = self.bus.clone();
|
||||||
|
Self::do_vendor_tasks(vendor, &devices, &bus)?;
|
||||||
|
}
|
||||||
|
// TODO: undo if failed? Save last mode, catch errors...
|
||||||
|
Ok(action_required)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Used only on boot to set correct mode
|
||||||
|
fn auto_power(&mut self) -> Result<(), RogError> {
|
||||||
|
let vendor = self.get_gfx_mode()?;
|
||||||
|
let devices = self.nvidia.clone();
|
||||||
|
let bus = self.bus.clone();
|
||||||
|
Self::do_vendor_tasks(vendor, &devices, &bus)?;
|
||||||
|
Self::toggle_fallback_service(vendor)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+25
-23
@@ -4,49 +4,51 @@ pub mod gfx;
|
|||||||
|
|
||||||
pub mod system;
|
pub mod system;
|
||||||
|
|
||||||
const PRIME_DISCRETE_PATH: &str = "/etc/prime-discrete";
|
const NVIDIA_DRIVERS: [&str; 4] = ["nvidia_drm", "nvidia_modeset", "nvidia_uvm", "nvidia"];
|
||||||
|
|
||||||
|
const VFIO_DRIVERS: [&str; 5] = [
|
||||||
|
"vfio-pci",
|
||||||
|
"vfio_iommu_type1",
|
||||||
|
"vfio_virqfd",
|
||||||
|
"vfio_mdev",
|
||||||
|
"vfio",
|
||||||
|
];
|
||||||
|
|
||||||
|
const DISPLAY_MANAGER: &str = "display-manager.service";
|
||||||
|
|
||||||
const MODPROBE_PATH: &str = "/etc/modprobe.d/asusd.conf";
|
const MODPROBE_PATH: &str = "/etc/modprobe.d/asusd.conf";
|
||||||
const INITRAMFS_PATH: &str = "/usr/sbin/update-initramfs";
|
|
||||||
const DRACUT_PATH: &str = "/usr/bin/dracut";
|
|
||||||
|
|
||||||
static MODPROBE_NVIDIA: &[u8] = MODPROBE_HYBRID;
|
static MODPROBE_BASE: &[u8] = br#"# Automatically generated by asusd
|
||||||
|
# If you have issues with i2c_nvidia_gpu, copy the 2 lines below to a
|
||||||
static MODPROBE_HYBRID: &[u8] = br#"# Automatically generated by asusd
|
# new blacklist file and uncomment
|
||||||
blacklist i2c_nvidia_gpu
|
#blacklist i2c_nvidia_gpu
|
||||||
alias i2c_nvidia_gpu off
|
#alias i2c_nvidia_gpu off
|
||||||
|
blacklist nouveau
|
||||||
|
alias nouveau off
|
||||||
options nvidia NVreg_DynamicPowerManagement=0x02
|
options nvidia NVreg_DynamicPowerManagement=0x02
|
||||||
options nvidia-drm modeset=1
|
options nvidia-drm modeset=1
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
static MODPROBE_COMPUTE: &[u8] = br#"# Automatically generated by asusd
|
|
||||||
blacklist i2c_nvidia_gpu
|
|
||||||
alias i2c_nvidia_gpu off
|
|
||||||
options nvidia NVreg_DynamicPowerManagement=0x02
|
|
||||||
options nvidia-drm modeset=0
|
|
||||||
"#;
|
|
||||||
|
|
||||||
static MODPROBE_INTEGRATED: &[u8] = br#"# Automatically generated by asusd
|
static MODPROBE_INTEGRATED: &[u8] = br#"# Automatically generated by asusd
|
||||||
blacklist i2c_nvidia_gpu
|
blacklist i2c_nvidia_gpu
|
||||||
blacklist nouveau
|
|
||||||
blacklist nvidia
|
blacklist nvidia
|
||||||
blacklist nvidia-drm
|
blacklist nvidia-drm
|
||||||
blacklist nvidia-modeset
|
blacklist nvidia-modeset
|
||||||
alias i2c_nvidia_gpu off
|
blacklist nouveau
|
||||||
alias nouveau off
|
alias nouveau off
|
||||||
alias nvidia off
|
|
||||||
alias nvidia-drm off
|
|
||||||
alias nvidia-modeset off
|
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
const PRIMARY_GPU_XORG_PATH: &str = "/etc/X11/xorg.conf.d/90-nvidia-primary.conf";
|
static MODPROBE_VFIO: &[u8] = br#"options vfio-pci ids="#;
|
||||||
|
|
||||||
|
const XORG_FILE: &str = "90-nvidia-primary.conf";
|
||||||
|
const XORG_PATH: &str = "/etc/X11/xorg.conf.d/";
|
||||||
|
|
||||||
static PRIMARY_GPU_BEGIN: &[u8] = br#"# Automatically generated by asusd
|
static PRIMARY_GPU_BEGIN: &[u8] = br#"# Automatically generated by asusd
|
||||||
Section "OutputClass"
|
Section "OutputClass"
|
||||||
Identifier "nvidia"
|
Identifier "nvidia"
|
||||||
MatchDriver "nvidia-drm"
|
MatchDriver "nvidia-drm"
|
||||||
Driver "nvidia"
|
Driver "nvidia"
|
||||||
Option "AllowEmptyInitialConfiguration"
|
Option "AllowEmptyInitialConfiguration" "true""#;
|
||||||
Option "AllowExternalGpus""#;
|
|
||||||
|
|
||||||
static PRIMARY_GPU_NVIDIA: &[u8] = br#"
|
static PRIMARY_GPU_NVIDIA: &[u8] = br#"
|
||||||
Option "PrimaryGPU" "true""#;
|
Option "PrimaryGPU" "true""#;
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ impl Module {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct PciBus {
|
pub struct PciBus {
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
}
|
}
|
||||||
@@ -50,11 +51,13 @@ impl PciBus {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Will rescan the device tree, which adds all removed devices back
|
||||||
pub fn rescan(&self) -> io::Result<()> {
|
pub fn rescan(&self) -> io::Result<()> {
|
||||||
write(self.path.join("rescan"), "1")
|
write(self.path.join("rescan"), "1")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct GraphicsDevice {
|
pub struct GraphicsDevice {
|
||||||
_id: String,
|
_id: String,
|
||||||
functions: Vec<PciDevice>,
|
functions: Vec<PciDevice>,
|
||||||
@@ -69,6 +72,10 @@ impl GraphicsDevice {
|
|||||||
self.functions.iter().any(|func| func.path().exists())
|
self.functions.iter().any(|func| func.path().exists())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn functions(&self) -> &[PciDevice] {
|
||||||
|
&self.functions
|
||||||
|
}
|
||||||
|
|
||||||
pub fn unbind(&self) -> Result<(), std::io::Error> {
|
pub fn unbind(&self) -> Result<(), std::io::Error> {
|
||||||
for func in self.functions.iter() {
|
for func in self.functions.iter() {
|
||||||
if func.path().exists() {
|
if func.path().exists() {
|
||||||
@@ -95,6 +102,32 @@ impl GraphicsDevice {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn rebind(&self) -> Result<(), std::io::Error> {
|
||||||
|
for func in self.functions.iter() {
|
||||||
|
if func.path().exists() {
|
||||||
|
match func.driver() {
|
||||||
|
Ok(driver) => {
|
||||||
|
info!("{}: Binding {}", driver.id(), func.id());
|
||||||
|
unsafe {
|
||||||
|
driver.bind(&func).map_err(|err| {
|
||||||
|
error!("gfx bind: {}", err);
|
||||||
|
err
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err) => match err.kind() {
|
||||||
|
io::ErrorKind::NotFound => (),
|
||||||
|
_ => {
|
||||||
|
error!("gfx driver: {:?}, {}", func.path(), err);
|
||||||
|
return Err(err);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn remove(&self) -> Result<(), std::io::Error> {
|
pub fn remove(&self) -> Result<(), std::io::Error> {
|
||||||
for func in self.functions.iter() {
|
for func in self.functions.iter() {
|
||||||
if func.path().exists() {
|
if func.path().exists() {
|
||||||
|
|||||||
+189
-290
@@ -5,22 +5,20 @@ static LED_SET: [u8; 17] = [0x5d, 0xb5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
|||||||
static KBD_BRIGHT_PATH: &str = "/sys/class/leds/asus::kbd_backlight/brightness";
|
static KBD_BRIGHT_PATH: &str = "/sys/class/leds/asus::kbd_backlight/brightness";
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::Config,
|
config_aura::AuraConfig,
|
||||||
error::RogError,
|
error::RogError,
|
||||||
laptops::{match_laptop, HELP_ADDRESS},
|
laptops::{LaptopLedData, ASUS_KEYBOARD_DEVICES},
|
||||||
};
|
};
|
||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
use rog_types::{
|
use rog_types::{
|
||||||
aura_brightness_bytes,
|
aura_modes::{AuraEffect, AuraModeNum, LedBrightness},
|
||||||
aura_modes::{AuraModes, PER_KEY},
|
|
||||||
fancy::KeyColourArray,
|
|
||||||
LED_MSG_LEN,
|
LED_MSG_LEN,
|
||||||
};
|
};
|
||||||
use std::fs::OpenOptions;
|
use std::fs::OpenOptions;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
|
use std::path::Path;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use std::{convert::TryInto, path::Path};
|
|
||||||
use zbus::dbus_interface;
|
use zbus::dbus_interface;
|
||||||
|
|
||||||
use crate::GetSupported;
|
use crate::GetSupported;
|
||||||
@@ -29,7 +27,8 @@ use serde_derive::{Deserialize, Serialize};
|
|||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct LedSupportedFunctions {
|
pub struct LedSupportedFunctions {
|
||||||
pub brightness_set: bool,
|
pub brightness_set: bool,
|
||||||
pub stock_led_modes: Option<Vec<u8>>,
|
pub stock_led_modes: Option<Vec<AuraModeNum>>,
|
||||||
|
pub multizone_led_mode: bool,
|
||||||
pub per_key_led_mode: bool,
|
pub per_key_led_mode: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,22 +37,19 @@ impl GetSupported for CtrlKbdBacklight {
|
|||||||
|
|
||||||
fn get_supported() -> Self::A {
|
fn get_supported() -> Self::A {
|
||||||
// let mode = <&str>::from(&<AuraModes>::from(*mode));
|
// let mode = <&str>::from(&<AuraModes>::from(*mode));
|
||||||
let mut stock_led_modes = None;
|
let multizone_led_mode = false;
|
||||||
let mut per_key_led_mode = false;
|
let per_key_led_mode = false;
|
||||||
if let Some(laptop) = match_laptop() {
|
let laptop = LaptopLedData::get_data();
|
||||||
let modes = laptop.supported_modes().to_vec();
|
let stock_led_modes = if laptop.standard.is_empty() {
|
||||||
if modes.contains(&PER_KEY) {
|
None
|
||||||
per_key_led_mode = true;
|
} else {
|
||||||
let modes = modes.iter().filter(|x| **x != PER_KEY).copied().collect();
|
Some(laptop.standard)
|
||||||
stock_led_modes = Some(modes);
|
};
|
||||||
} else {
|
|
||||||
stock_led_modes = Some(modes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LedSupportedFunctions {
|
LedSupportedFunctions {
|
||||||
brightness_set: CtrlKbdBacklight::get_kbd_bright_path().is_ok(),
|
brightness_set: CtrlKbdBacklight::get_kbd_bright_path().is_some(),
|
||||||
stock_led_modes,
|
stock_led_modes,
|
||||||
|
multizone_led_mode,
|
||||||
per_key_led_mode,
|
per_key_led_mode,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -61,12 +57,10 @@ impl GetSupported for CtrlKbdBacklight {
|
|||||||
|
|
||||||
pub struct CtrlKbdBacklight {
|
pub struct CtrlKbdBacklight {
|
||||||
led_node: Option<String>,
|
led_node: Option<String>,
|
||||||
#[allow(dead_code)]
|
|
||||||
kbd_node: Option<String>,
|
|
||||||
pub bright_node: String,
|
pub bright_node: String,
|
||||||
supported_modes: Vec<u8>,
|
supported_modes: LaptopLedData,
|
||||||
flip_effect_write: bool,
|
flip_effect_write: bool,
|
||||||
config: Arc<Mutex<Config>>,
|
config: AuraConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DbusKbdBacklight {
|
pub struct DbusKbdBacklight {
|
||||||
@@ -88,7 +82,7 @@ trait Dbus {
|
|||||||
impl crate::ZbusAdd for DbusKbdBacklight {
|
impl crate::ZbusAdd for DbusKbdBacklight {
|
||||||
fn add_to_server(self, server: &mut zbus::ObjectServer) {
|
fn add_to_server(self, server: &mut zbus::ObjectServer) {
|
||||||
server
|
server
|
||||||
.at(&"/org/asuslinux/Led".try_into().unwrap(), self)
|
.at("/org/asuslinux/Led", self)
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
error!("DbusKbdBacklight: add_to_server {}", err);
|
error!("DbusKbdBacklight: add_to_server {}", err);
|
||||||
})
|
})
|
||||||
@@ -96,48 +90,42 @@ impl crate::ZbusAdd for DbusKbdBacklight {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The main interface for changing, reading, or notfying signals
|
||||||
|
///
|
||||||
|
/// LED commands are split between Brightness, Modes, Per-Key
|
||||||
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
||||||
impl DbusKbdBacklight {
|
impl DbusKbdBacklight {
|
||||||
fn set_led_mode(&mut self, data: String) {
|
fn set_brightness(&mut self, brightness: LedBrightness) {
|
||||||
if let Ok(data) = serde_json::from_str(&data) {
|
if let Ok(ctrl) = self.inner.try_lock() {
|
||||||
if let Ok(mut ctrl) = self.inner.try_lock() {
|
ctrl.set_brightness(brightness)
|
||||||
if let Ok(mut cfg) = ctrl.config.clone().try_lock() {
|
.map_err(|err| warn!("{}", err))
|
||||||
match &data {
|
.ok();
|
||||||
AuraModes::PerKey(_) => {
|
}
|
||||||
ctrl.do_command(data, &mut cfg)
|
}
|
||||||
.unwrap_or_else(|err| warn!("{}", err));
|
|
||||||
}
|
fn set_led_mode(&mut self, effect: AuraEffect) {
|
||||||
_ => {
|
if let Ok(mut ctrl) = self.inner.try_lock() {
|
||||||
if let Ok(json) = serde_json::to_string(&data) {
|
let mode_name = effect.mode_name();
|
||||||
match ctrl.do_command(data, &mut cfg) {
|
match ctrl.do_command(effect) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
self.notify_led(&json).ok();
|
self.notify_led(&mode_name).ok();
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
warn!("{}", err);
|
warn!("{}", err);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
warn!("SetKeyBacklight could not deserialise");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_led_mode(&self) {
|
fn next_led_mode(&self) {
|
||||||
if let Ok(mut ctrl) = self.inner.try_lock() {
|
if let Ok(mut ctrl) = self.inner.try_lock() {
|
||||||
if let Ok(mut cfg) = ctrl.config.clone().try_lock() {
|
ctrl.toggle_mode(false)
|
||||||
ctrl.toggle_mode(false, &mut cfg)
|
.unwrap_or_else(|err| warn!("{}", err));
|
||||||
.unwrap_or_else(|err| warn!("{}", err));
|
|
||||||
|
|
||||||
if let Some(mode) = cfg.get_led_mode_data(cfg.kbd_backlight_mode) {
|
if let Some(mode) = ctrl.config.builtins.get(&ctrl.config.current_mode) {
|
||||||
if let Ok(json) = serde_json::to_string(&mode) {
|
if let Ok(json) = serde_json::to_string(&mode) {
|
||||||
self.notify_led(&json)
|
self.notify_led(&json)
|
||||||
.unwrap_or_else(|err| warn!("{}", err));
|
.unwrap_or_else(|err| warn!("{}", err));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -145,40 +133,24 @@ impl DbusKbdBacklight {
|
|||||||
|
|
||||||
fn prev_led_mode(&self) {
|
fn prev_led_mode(&self) {
|
||||||
if let Ok(mut ctrl) = self.inner.try_lock() {
|
if let Ok(mut ctrl) = self.inner.try_lock() {
|
||||||
if let Ok(mut cfg) = ctrl.config.clone().try_lock() {
|
ctrl.toggle_mode(true)
|
||||||
ctrl.toggle_mode(true, &mut cfg)
|
.unwrap_or_else(|err| warn!("{}", err));
|
||||||
.unwrap_or_else(|err| warn!("{}", err));
|
|
||||||
|
|
||||||
if let Some(mode) = cfg.get_led_mode_data(cfg.kbd_backlight_mode) {
|
if let Some(mode) = ctrl.config.builtins.get(&ctrl.config.current_mode) {
|
||||||
if let Ok(json) = serde_json::to_string(&mode) {
|
if let Ok(json) = serde_json::to_string(&mode) {
|
||||||
self.notify_led(&json)
|
self.notify_led(&json)
|
||||||
.unwrap_or_else(|err| warn!("{}", err));
|
.unwrap_or_else(|err| warn!("{}", err));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the current mode data
|
/// Return the current mode data
|
||||||
|
#[dbus_interface(property)]
|
||||||
fn led_mode(&self) -> String {
|
fn led_mode(&self) -> String {
|
||||||
if let Ok(ctrl) = self.inner.try_lock() {
|
if let Ok(ctrl) = self.inner.try_lock() {
|
||||||
if let Ok(cfg) = ctrl.config.clone().try_lock() {
|
if let Some(mode) = ctrl.config.builtins.get(&ctrl.config.current_mode) {
|
||||||
if let Some(mode) = cfg.get_led_mode_data(cfg.kbd_backlight_mode) {
|
if let Ok(json) = serde_json::to_string(&mode) {
|
||||||
if let Ok(json) = serde_json::to_string(&mode) {
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
warn!("SetKeyBacklight could not deserialise");
|
|
||||||
"SetKeyBacklight could not deserialise".to_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return a list of available modes
|
|
||||||
fn led_modes(&self) -> String {
|
|
||||||
if let Ok(ctrl) = self.inner.try_lock() {
|
|
||||||
if let Ok(cfg) = ctrl.config.clone().try_lock() {
|
|
||||||
if let Ok(json) = serde_json::to_string(&cfg.kbd_backlight_modes) {
|
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -187,14 +159,25 @@ impl DbusKbdBacklight {
|
|||||||
"SetKeyBacklight could not deserialise".to_string()
|
"SetKeyBacklight could not deserialise".to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the current LED brightness
|
/// Return a list of available modes
|
||||||
fn led_brightness(&self) -> i8 {
|
#[dbus_interface(property)]
|
||||||
|
fn led_modes(&self) -> String {
|
||||||
if let Ok(ctrl) = self.inner.try_lock() {
|
if let Ok(ctrl) = self.inner.try_lock() {
|
||||||
if let Ok(cfg) = ctrl.config.clone().try_lock() {
|
if let Ok(json) = serde_json::to_string(&ctrl.config.builtins) {
|
||||||
return cfg.kbd_led_brightness as i8;
|
return json;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
warn!("SetKeyBacklight could not deserialise");
|
warn!("SetKeyBacklight could not deserialise");
|
||||||
|
"SetKeyBacklight could not serialise".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the current LED brightness
|
||||||
|
#[dbus_interface(property)]
|
||||||
|
fn led_brightness(&self) -> i8 {
|
||||||
|
if let Ok(ctrl) = self.inner.try_lock() {
|
||||||
|
return ctrl.get_brightness().map(|n| n as i8).unwrap_or(-1);
|
||||||
|
}
|
||||||
|
warn!("SetKeyBacklight could not serialise");
|
||||||
-1
|
-1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,44 +188,40 @@ impl DbusKbdBacklight {
|
|||||||
impl crate::Reloadable for CtrlKbdBacklight {
|
impl crate::Reloadable for CtrlKbdBacklight {
|
||||||
fn reload(&mut self) -> Result<(), RogError> {
|
fn reload(&mut self) -> Result<(), RogError> {
|
||||||
// set current mode (if any)
|
// set current mode (if any)
|
||||||
if let Ok(mut config) = self.config.clone().try_lock() {
|
if self.supported_modes.standard.len() > 1 {
|
||||||
if self.supported_modes.len() > 1 {
|
let current_mode = self.config.current_mode;
|
||||||
if self.supported_modes.contains(&config.kbd_backlight_mode) {
|
if self.supported_modes.standard.contains(&(current_mode)) {
|
||||||
let mode = config
|
let mode = self
|
||||||
.get_led_mode_data(config.kbd_backlight_mode)
|
.config
|
||||||
.ok_or(RogError::NotSupported)?
|
.builtins
|
||||||
.to_owned();
|
.get(¤t_mode)
|
||||||
self.write_mode(&mode)?;
|
.ok_or(RogError::NotSupported)?
|
||||||
info!("Reloaded last used mode");
|
.to_owned();
|
||||||
} else {
|
self.write_mode(&mode)?;
|
||||||
warn!(
|
info!("Reloaded last used mode");
|
||||||
"An unsupported mode was set: {}, reset to first mode available",
|
} else {
|
||||||
<&str>::from(&<AuraModes>::from(config.kbd_backlight_mode))
|
warn!(
|
||||||
);
|
"An unsupported mode was set: {}, reset to first mode available",
|
||||||
for (idx, mode) in config.kbd_backlight_modes.iter_mut().enumerate() {
|
<&str>::from(&self.config.current_mode)
|
||||||
if !self.supported_modes.contains(&mode.into()) {
|
);
|
||||||
config.kbd_backlight_modes.remove(idx);
|
self.config.builtins.remove(¤t_mode);
|
||||||
config.write();
|
self.config.current_mode = AuraModeNum::Static;
|
||||||
break;
|
// TODO: do a recursive call with a boxed dyn future later
|
||||||
}
|
let mode = self
|
||||||
}
|
.config
|
||||||
config.kbd_backlight_mode = self.supported_modes[0];
|
.builtins
|
||||||
// TODO: do a recursive call with a boxed dyn future later
|
.get(¤t_mode)
|
||||||
let mode = config
|
.ok_or(RogError::NotSupported)?
|
||||||
.get_led_mode_data(config.kbd_backlight_mode)
|
.to_owned();
|
||||||
.ok_or(RogError::NotSupported)?
|
self.write_mode(&mode)?;
|
||||||
.to_owned();
|
info!("Reloaded last used mode");
|
||||||
self.write_mode(&mode)?;
|
|
||||||
info!("Reloaded last used mode");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reload brightness
|
|
||||||
let bright = config.kbd_led_brightness;
|
|
||||||
let bytes = aura_brightness_bytes(bright);
|
|
||||||
self.write_bytes(&bytes)?;
|
|
||||||
info!("Reloaded last used brightness");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reload brightness
|
||||||
|
let bright = self.config.brightness;
|
||||||
|
self.set_brightness(bright)?;
|
||||||
|
info!("Reloaded last used brightness");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -262,12 +241,10 @@ impl crate::CtrlTask for CtrlKbdBacklight {
|
|||||||
file.read_exact(&mut buf)
|
file.read_exact(&mut buf)
|
||||||
.map_err(|err| RogError::Read("buffer".into(), err))?;
|
.map_err(|err| RogError::Read("buffer".into(), err))?;
|
||||||
if let Some(num) = char::from(buf[0]).to_digit(10) {
|
if let Some(num) = char::from(buf[0]).to_digit(10) {
|
||||||
if let Ok(mut config) = self.config.clone().try_lock() {
|
if self.config.brightness != num.into() {
|
||||||
if config.kbd_led_brightness != num as u8 {
|
self.config.read();
|
||||||
config.read();
|
self.config.brightness = num.into();
|
||||||
config.kbd_led_brightness = num as u8;
|
self.config.write();
|
||||||
config.write();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
@@ -277,46 +254,37 @@ impl crate::CtrlTask for CtrlKbdBacklight {
|
|||||||
|
|
||||||
impl CtrlKbdBacklight {
|
impl CtrlKbdBacklight {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(
|
pub fn new(supported_modes: LaptopLedData, config: AuraConfig) -> Result<Self, RogError> {
|
||||||
id_product: &str,
|
|
||||||
condev_iface: Option<&String>,
|
|
||||||
supported_modes: Vec<u8>,
|
|
||||||
config: Arc<Mutex<Config>>,
|
|
||||||
) -> Result<Self, RogError> {
|
|
||||||
// TODO: return error if *all* nodes are None
|
// TODO: return error if *all* nodes are None
|
||||||
let led_node = Self::get_node_failover(id_product, None, Self::scan_led_node).map_or_else(
|
let mut led_node = None;
|
||||||
|err| {
|
for prod in ASUS_KEYBOARD_DEVICES.iter() {
|
||||||
warn!("led_node: {}", err);
|
match Self::find_led_node(prod) {
|
||||||
None
|
Ok(node) => {
|
||||||
},
|
led_node = Some(node);
|
||||||
Some,
|
break;
|
||||||
);
|
}
|
||||||
|
Err(err) => warn!("led_node: {}", err),
|
||||||
let kbd_node = Self::get_node_failover(id_product, condev_iface, Self::scan_kbd_node)
|
}
|
||||||
.map_or_else(
|
}
|
||||||
|err| {
|
|
||||||
warn!("kbd_node: {}", err);
|
|
||||||
None
|
|
||||||
},
|
|
||||||
Some,
|
|
||||||
);
|
|
||||||
|
|
||||||
let bright_node = Self::get_kbd_bright_path();
|
let bright_node = Self::get_kbd_bright_path();
|
||||||
|
|
||||||
if led_node.is_none() && kbd_node.is_none() && Self::get_kbd_bright_path().is_err() {
|
if led_node.is_none() && bright_node.is_none() {
|
||||||
return Err(RogError::MissingFunction(
|
return Err(RogError::MissingFunction(
|
||||||
"All keyboard features missing, you may require a v5.11 series kernel or newer"
|
"All keyboard features missing, you may require a v5.11 series kernel or newer"
|
||||||
.into(),
|
.into(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if bright_node.is_none() {
|
||||||
|
return Err(RogError::MissingFunction(
|
||||||
|
"No brightness control, you may require a v5.11 series kernel or newer".into(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
let ctrl = CtrlKbdBacklight {
|
let ctrl = CtrlKbdBacklight {
|
||||||
// Using `ok` here so we can continue without keyboard features but
|
|
||||||
// still get brightness control at least... maybe...
|
|
||||||
led_node,
|
led_node,
|
||||||
kbd_node,
|
bright_node: bright_node.unwrap(), // If was none then we already returned above
|
||||||
// TODO: Check for existance
|
|
||||||
bright_node: bright_node?.to_owned(),
|
|
||||||
supported_modes,
|
supported_modes,
|
||||||
flip_effect_write: false,
|
flip_effect_write: false,
|
||||||
config,
|
config,
|
||||||
@@ -324,31 +292,47 @@ impl CtrlKbdBacklight {
|
|||||||
Ok(ctrl)
|
Ok(ctrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_kbd_bright_path() -> Result<&'static str, RogError> {
|
fn get_kbd_bright_path() -> Option<String> {
|
||||||
if Path::new(KBD_BRIGHT_PATH).exists() {
|
if Path::new(KBD_BRIGHT_PATH).exists() {
|
||||||
Ok(KBD_BRIGHT_PATH)
|
return Some(KBD_BRIGHT_PATH.to_string());
|
||||||
} else {
|
|
||||||
Err(RogError::MissingFunction(
|
|
||||||
"Keyboard features missing, you may require a v5.11 series kernel or newer".into(),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_node_failover(
|
pub fn get_brightness(&self) -> Result<u8, RogError> {
|
||||||
id_product: &str,
|
let mut file = OpenOptions::new()
|
||||||
iface: Option<&String>,
|
.read(true)
|
||||||
fun: fn(&str, Option<&String>) -> Result<String, RogError>,
|
.open(&self.bright_node)
|
||||||
) -> Result<String, RogError> {
|
.map_err(|err| match err.kind() {
|
||||||
match fun(id_product, iface) {
|
std::io::ErrorKind::NotFound => {
|
||||||
Ok(o) => return Ok(o),
|
RogError::MissingLedBrightNode((&self.bright_node).into(), err)
|
||||||
Err(e) => {
|
}
|
||||||
warn!("Looking for node: {}", e.to_string());
|
_ => RogError::Path((&self.bright_node).into(), err),
|
||||||
}
|
})?;
|
||||||
}
|
let mut buf = [0u8; 1];
|
||||||
Err(RogError::NotFound(format!("{}, {:?}", id_product, iface)))
|
file.read_exact(&mut buf)
|
||||||
|
.map_err(|err| RogError::Read("buffer".into(), err))?;
|
||||||
|
Ok(buf[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scan_led_node(id_product: &str, _: Option<&String>) -> Result<String, RogError> {
|
pub fn set_brightness(&self, brightness: LedBrightness) -> Result<(), RogError> {
|
||||||
|
let path = Path::new(&self.bright_node);
|
||||||
|
let mut file =
|
||||||
|
OpenOptions::new()
|
||||||
|
.write(true)
|
||||||
|
.open(&path)
|
||||||
|
.map_err(|err| match err.kind() {
|
||||||
|
std::io::ErrorKind::NotFound => {
|
||||||
|
RogError::MissingLedBrightNode((&self.bright_node).into(), err)
|
||||||
|
}
|
||||||
|
_ => RogError::Path((&self.bright_node).into(), err),
|
||||||
|
})?;
|
||||||
|
file.write_all(&[brightness.as_char_code()])
|
||||||
|
.map_err(|err| RogError::Read("buffer".into(), err))?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_led_node(id_product: &str) -> Result<String, RogError> {
|
||||||
let mut enumerator = udev::Enumerator::new().map_err(|err| {
|
let mut enumerator = udev::Enumerator::new().map_err(|err| {
|
||||||
warn!("{}", err);
|
warn!("{}", err);
|
||||||
RogError::Udev("enumerator failed".into(), err)
|
RogError::Udev("enumerator failed".into(), err)
|
||||||
@@ -381,59 +365,13 @@ impl CtrlKbdBacklight {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
warn!("Did not find a hidraw node for LED control, your device may be unsupported or require a kernel patch, see: {}", HELP_ADDRESS);
|
|
||||||
Err(RogError::MissingFunction(
|
Err(RogError::MissingFunction(
|
||||||
"ASUS LED device node not found".into(),
|
"ASUS LED device node not found".into(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scan_kbd_node(id_product: &str, iface: Option<&String>) -> Result<String, RogError> {
|
pub(crate) fn do_command(&mut self, mode: AuraEffect) -> Result<(), RogError> {
|
||||||
let mut enumerator = udev::Enumerator::new().map_err(|err| {
|
self.set_and_save(mode)
|
||||||
warn!("{}", err);
|
|
||||||
RogError::Udev("enumerator failed".into(), err)
|
|
||||||
})?;
|
|
||||||
enumerator.match_subsystem("input").map_err(|err| {
|
|
||||||
warn!("{}", err);
|
|
||||||
RogError::Udev("match_subsystem failed".into(), err)
|
|
||||||
})?;
|
|
||||||
enumerator
|
|
||||||
.match_property("ID_MODEL_ID", id_product)
|
|
||||||
.map_err(|err| {
|
|
||||||
warn!("{}", err);
|
|
||||||
RogError::Udev("match_property failed".into(), err)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
for device in enumerator
|
|
||||||
.scan_devices()
|
|
||||||
.map_err(|err| {
|
|
||||||
warn!("{}", err);
|
|
||||||
err
|
|
||||||
})
|
|
||||||
.map_err(|err| {
|
|
||||||
warn!("{}", err);
|
|
||||||
RogError::Udev("scan_devices failed".into(), err)
|
|
||||||
})?
|
|
||||||
{
|
|
||||||
if let Some(dev_node) = device.devnode() {
|
|
||||||
if let Some(inum) = device.property_value("ID_USB_INTERFACE_NUM") {
|
|
||||||
if let Some(iface) = iface {
|
|
||||||
if inum == iface.as_str() {
|
|
||||||
info!("Using device at: {:?} for keyboard polling", dev_node);
|
|
||||||
return Ok(dev_node.to_string_lossy().to_string());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
warn!("Did not find keyboard consumer device node, if expected functions are missing please file an issue at {}", HELP_ADDRESS);
|
|
||||||
Err(RogError::MissingFunction(
|
|
||||||
"ASUS keyboard 'Consumer Device' node not found".into(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn do_command(&mut self, mode: AuraModes, config: &mut Config) -> Result<(), RogError> {
|
|
||||||
self.set_and_save(mode, config)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Should only be used if the bytes you are writing are verified correct
|
/// Should only be used if the bytes you are writing are verified correct
|
||||||
@@ -470,100 +408,61 @@ impl CtrlKbdBacklight {
|
|||||||
///
|
///
|
||||||
/// This needs to be universal so that settings applied by dbus stick
|
/// This needs to be universal so that settings applied by dbus stick
|
||||||
#[inline]
|
#[inline]
|
||||||
fn set_and_save(&mut self, mode: AuraModes, config: &mut Config) -> Result<(), RogError> {
|
fn set_and_save(&mut self, mode: AuraEffect) -> Result<(), RogError> {
|
||||||
match mode {
|
self.config.read();
|
||||||
AuraModes::LedBrightness(n) => {
|
self.write_mode(&mode)?;
|
||||||
let bytes: [u8; LED_MSG_LEN] = (&mode).into();
|
self.config.current_mode = *mode.mode();
|
||||||
self.write_bytes(&bytes)?;
|
self.config.set_builtin(mode);
|
||||||
config.read();
|
self.config.write();
|
||||||
config.kbd_led_brightness = n;
|
|
||||||
config.write();
|
|
||||||
info!("LED brightness set to {:#?}", n);
|
|
||||||
}
|
|
||||||
AuraModes::PerKey(v) => {
|
|
||||||
if v.is_empty() || v[0].is_empty() {
|
|
||||||
let bytes = KeyColourArray::get_init_msg();
|
|
||||||
self.write_bytes(&bytes)?;
|
|
||||||
} else {
|
|
||||||
self.write_effect(&v)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
config.read();
|
|
||||||
let mode_num: u8 = u8::from(&mode);
|
|
||||||
self.write_mode(&mode)?;
|
|
||||||
config.kbd_backlight_mode = mode_num;
|
|
||||||
config.set_mode_data(mode);
|
|
||||||
config.write();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn toggle_mode(&mut self, reverse: bool, config: &mut Config) -> Result<(), RogError> {
|
fn toggle_mode(&mut self, reverse: bool) -> Result<(), RogError> {
|
||||||
let current = config.kbd_backlight_mode;
|
let current = self.config.current_mode;
|
||||||
if let Some(idx) = self.supported_modes.iter().position(|v| *v == current) {
|
if let Some(idx) = self
|
||||||
|
.supported_modes
|
||||||
|
.standard
|
||||||
|
.iter()
|
||||||
|
.position(|v| *v == current)
|
||||||
|
{
|
||||||
let mut idx = idx;
|
let mut idx = idx;
|
||||||
// goes past end of array
|
// goes past end of array
|
||||||
if reverse {
|
if reverse {
|
||||||
if idx == 0 {
|
if idx == 0 {
|
||||||
idx = self.supported_modes.len() - 1;
|
idx = self.supported_modes.standard.len() - 1;
|
||||||
} else {
|
} else {
|
||||||
idx -= 1;
|
idx -= 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
idx += 1;
|
idx += 1;
|
||||||
if idx == self.supported_modes.len() {
|
if idx == self.supported_modes.standard.len() {
|
||||||
idx = 0;
|
idx = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let next = self.supported_modes[idx];
|
let next = self.supported_modes.standard[idx];
|
||||||
|
|
||||||
config.read();
|
self.config.read();
|
||||||
if let Some(data) = config.get_led_mode_data(next) {
|
if let Some(data) = self.config.builtins.get(&next) {
|
||||||
self.write_mode(&data)?;
|
self.write_mode(&data)?;
|
||||||
config.kbd_backlight_mode = next;
|
self.config.current_mode = next;
|
||||||
}
|
}
|
||||||
config.write();
|
self.config.write();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn write_mode(&mut self, mode: &AuraModes) -> Result<(), RogError> {
|
fn write_mode(&self, mode: &AuraEffect) -> Result<(), RogError> {
|
||||||
let mode_num: u8 = u8::from(mode);
|
if !self.supported_modes.standard.contains(&mode.mode()) {
|
||||||
if !self.supported_modes.contains(&mode_num) {
|
|
||||||
return Err(RogError::NotSupported);
|
return Err(RogError::NotSupported);
|
||||||
}
|
}
|
||||||
match mode {
|
let bytes: [u8; LED_MSG_LEN] = mode.into();
|
||||||
AuraModes::PerKey(v) => {
|
self.write_bytes(&bytes)?;
|
||||||
if v.is_empty() || v[0].is_empty() {
|
self.write_bytes(&LED_SET)?;
|
||||||
let bytes = KeyColourArray::get_init_msg();
|
// Changes won't persist unless apply is set
|
||||||
self.write_bytes(&bytes)?;
|
self.write_bytes(&LED_APPLY)?;
|
||||||
} else {
|
|
||||||
self.write_effect(v)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AuraModes::MultiStatic(_) | AuraModes::MultiBreathe(_) => {
|
|
||||||
let bytes: [[u8; LED_MSG_LEN]; 4] = mode.into();
|
|
||||||
for array in bytes.iter() {
|
|
||||||
self.write_bytes(array)?;
|
|
||||||
}
|
|
||||||
self.write_bytes(&LED_SET)?;
|
|
||||||
// Changes won't persist unless apply is set
|
|
||||||
self.write_bytes(&LED_APPLY)?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
let bytes: [u8; LED_MSG_LEN] = mode.into();
|
|
||||||
self.write_bytes(&bytes)?;
|
|
||||||
self.write_bytes(&LED_SET)?;
|
|
||||||
// Changes won't persist unless apply is set
|
|
||||||
self.write_bytes(&LED_APPLY)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+106
-19
@@ -1,16 +1,18 @@
|
|||||||
use crate::{config::Config, ctrl_gfx::gfx::CtrlGraphics, error::RogError, GetSupported};
|
use crate::{config::Config, error::RogError, GetSupported};
|
||||||
//use crate::dbus::DbusEvents;
|
use log::{error, info, warn};
|
||||||
use log::{info, warn};
|
|
||||||
use rog_types::gfx_vendors::GfxVendors;
|
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use std::convert::TryInto;
|
|
||||||
use std::fs::OpenOptions;
|
use std::fs::OpenOptions;
|
||||||
|
use std::io::BufRead;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use std::process::Command;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use zbus::dbus_interface;
|
use zbus::dbus_interface;
|
||||||
|
|
||||||
|
const INITRAMFS_PATH: &str = "/usr/sbin/update-initramfs";
|
||||||
|
const DRACUT_PATH: &str = "/usr/bin/dracut";
|
||||||
|
|
||||||
static ASUS_SWITCH_GRAPHIC_MODE: &str =
|
static ASUS_SWITCH_GRAPHIC_MODE: &str =
|
||||||
"/sys/firmware/efi/efivars/AsusSwitchGraphicMode-607005d5-3f75-4b2e-98f0-85ba66797a3e";
|
"/sys/firmware/efi/efivars/AsusSwitchGraphicMode-607005d5-3f75-4b2e-98f0-85ba66797a3e";
|
||||||
static ASUS_POST_LOGO_SOUND: &str =
|
static ASUS_POST_LOGO_SOUND: &str =
|
||||||
@@ -40,7 +42,7 @@ impl GetSupported for CtrlRogBios {
|
|||||||
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
||||||
impl CtrlRogBios {
|
impl CtrlRogBios {
|
||||||
pub fn set_dedicated_graphic_mode(&mut self, dedicated: bool) {
|
pub fn set_dedicated_graphic_mode(&mut self, dedicated: bool) {
|
||||||
Self::set_gfx_mode(dedicated)
|
self.set_gfx_mode(dedicated)
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
warn!("CtrlRogBios: set_asus_switch_graphic_mode {}", err);
|
warn!("CtrlRogBios: set_asus_switch_graphic_mode {}", err);
|
||||||
err
|
err
|
||||||
@@ -99,7 +101,7 @@ impl CtrlRogBios {
|
|||||||
impl crate::ZbusAdd for CtrlRogBios {
|
impl crate::ZbusAdd for CtrlRogBios {
|
||||||
fn add_to_server(self, server: &mut zbus::ObjectServer) {
|
fn add_to_server(self, server: &mut zbus::ObjectServer) {
|
||||||
server
|
server
|
||||||
.at(&"/org/asuslinux/RogBios".try_into().unwrap(), self)
|
.at("/org/asuslinux/RogBios", self)
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
warn!("CtrlRogBios: add_to_server {}", err);
|
warn!("CtrlRogBios: add_to_server {}", err);
|
||||||
err
|
err
|
||||||
@@ -138,8 +140,6 @@ impl CtrlRogBios {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn set_path_mutable(path: &str) -> Result<(), RogError> {
|
fn set_path_mutable(path: &str) -> Result<(), RogError> {
|
||||||
use std::process::Command;
|
|
||||||
|
|
||||||
let output = Command::new("/usr/bin/chattr")
|
let output = Command::new("/usr/bin/chattr")
|
||||||
.arg("-i")
|
.arg("-i")
|
||||||
.arg(path)
|
.arg(path)
|
||||||
@@ -179,7 +179,7 @@ impl CtrlRogBios {
|
|||||||
Ok(data[idx] as i8)
|
Ok(data[idx] as i8)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn set_gfx_mode(dedicated: bool) -> Result<(), RogError> {
|
pub(super) fn set_gfx_mode(&self, dedicated: bool) -> Result<(), RogError> {
|
||||||
let path = ASUS_SWITCH_GRAPHIC_MODE;
|
let path = ASUS_SWITCH_GRAPHIC_MODE;
|
||||||
let mut file = OpenOptions::new()
|
let mut file = OpenOptions::new()
|
||||||
.read(true)
|
.read(true)
|
||||||
@@ -201,15 +201,17 @@ impl CtrlRogBios {
|
|||||||
file.write_all(&data)
|
file.write_all(&data)
|
||||||
.map_err(|err| RogError::Path(path.into(), err))?;
|
.map_err(|err| RogError::Path(path.into(), err))?;
|
||||||
|
|
||||||
if let Ok(ded) = CtrlRogBios::get_gfx_mode() {
|
self.update_initramfs(dedicated)?;
|
||||||
if let Ok(vendor) = CtrlGraphics::get_vendor() {
|
|
||||||
if ded == 1 && vendor != "nvidia" {
|
// if let Ok(ded) = CtrlRogBios::get_gfx_mode() {
|
||||||
warn!("Dedicated GFX toggle is on but driver mode is not nvidia \nSetting to nvidia driver mode");
|
// if let Ok(vendor) = CtrlGraphics::get_vendor() {
|
||||||
CtrlGraphics::set_gfx_config(GfxVendors::Nvidia)
|
// if ded == 1 && vendor != "nvidia" {
|
||||||
.unwrap_or_else(|err| warn!("Gfx controller: {}", err));
|
// warn!("Dedicated GFX toggle is on but driver mode is not nvidia \nSetting to nvidia driver mode");
|
||||||
}
|
// CtrlGraphics::set_gfx_config(&GfxVendors::Nvidia)
|
||||||
}
|
// .unwrap_or_else(|err| warn!("Gfx controller: {}", err));
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -254,4 +256,89 @@ impl CtrlRogBios {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// required for g-sync mode
|
||||||
|
fn update_initramfs(&self, dedicated: bool) -> Result<(), RogError> {
|
||||||
|
let mut initfs_cmd = None;
|
||||||
|
|
||||||
|
if Path::new(INITRAMFS_PATH).exists() {
|
||||||
|
let mut cmd = Command::new("update-initramfs");
|
||||||
|
cmd.arg("-u");
|
||||||
|
initfs_cmd = Some(cmd);
|
||||||
|
info!("Using initramfs update command 'update-initramfs'");
|
||||||
|
} else if Path::new(DRACUT_PATH).exists() {
|
||||||
|
let mut cmd = Command::new("dracut");
|
||||||
|
cmd.arg("-f");
|
||||||
|
cmd.arg("-q");
|
||||||
|
initfs_cmd = Some(cmd);
|
||||||
|
info!("Using initramfs update command 'dracut'");
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(mut cmd) = initfs_cmd {
|
||||||
|
info!("Updating initramfs");
|
||||||
|
|
||||||
|
// If switching to Nvidia dedicated we need these modules included
|
||||||
|
if Path::new(DRACUT_PATH).exists() && dedicated {
|
||||||
|
cmd.arg("--add-drivers");
|
||||||
|
cmd.arg("nvidia nvidia-drm nvidia-modeset nvidia-uvm");
|
||||||
|
info!("System uses dracut, forcing nvidia modules to be included in init");
|
||||||
|
} else if Path::new(INITRAMFS_PATH).exists() {
|
||||||
|
let modules = vec![
|
||||||
|
"nvidia\n",
|
||||||
|
"nvidia-drm\n",
|
||||||
|
"nvidia-modeset\n",
|
||||||
|
"nvidia-uvm\n",
|
||||||
|
];
|
||||||
|
|
||||||
|
let module_include = Path::new("/etc/initramfs-tools/modules");
|
||||||
|
|
||||||
|
if dedicated {
|
||||||
|
let mut file = std::fs::OpenOptions::new()
|
||||||
|
.append(true)
|
||||||
|
.open(module_include)
|
||||||
|
.map_err(|err| {
|
||||||
|
RogError::Write(module_include.to_string_lossy().to_string(), err)
|
||||||
|
})?;
|
||||||
|
// add nvidia modules to module_include
|
||||||
|
file.write_all(modules.concat().as_bytes()).unwrap();
|
||||||
|
} else {
|
||||||
|
let file = std::fs::OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.open(module_include)
|
||||||
|
.map_err(|err| {
|
||||||
|
RogError::Write(module_include.to_string_lossy().to_string(), err)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let mut buf = Vec::new();
|
||||||
|
// remove modules
|
||||||
|
for line in std::io::BufReader::new(file).lines() {
|
||||||
|
if let Ok(l) = line {
|
||||||
|
if !modules.contains(&l.as_ref()) {
|
||||||
|
buf.append(&mut l.as_bytes().to_vec());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let file = std::fs::OpenOptions::new()
|
||||||
|
.write(true)
|
||||||
|
.open(module_include)
|
||||||
|
.map_err(|err| {
|
||||||
|
RogError::Write(module_include.to_string_lossy().to_string(), err)
|
||||||
|
})?;
|
||||||
|
std::io::BufWriter::new(file).write_all(&buf).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let status = cmd
|
||||||
|
.status()
|
||||||
|
.map_err(|err| RogError::Write(format!("{:?}", cmd), err))?;
|
||||||
|
if !status.success() {
|
||||||
|
error!("Ram disk update failed");
|
||||||
|
return Err(RogError::Initramfs("Ram disk update failed".into()));
|
||||||
|
} else {
|
||||||
|
info!("Successfully updated initramfs");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
use std::convert::TryInto;
|
|
||||||
|
|
||||||
use log::warn;
|
use log::warn;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use zbus::dbus_interface;
|
use zbus::dbus_interface;
|
||||||
@@ -15,11 +13,11 @@ use crate::{
|
|||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct SupportedFunctions {
|
pub struct SupportedFunctions {
|
||||||
anime_ctrl: AnimeSupportedFunctions,
|
pub anime_ctrl: AnimeSupportedFunctions,
|
||||||
charge_ctrl: ChargeSupportedFunctions,
|
pub charge_ctrl: ChargeSupportedFunctions,
|
||||||
fan_cpu_ctrl: FanCpuSupportedFunctions,
|
pub fan_cpu_ctrl: FanCpuSupportedFunctions,
|
||||||
keyboard_led: LedSupportedFunctions,
|
pub keyboard_led: LedSupportedFunctions,
|
||||||
rog_bios_ctrl: RogBiosSupportedFunctions,
|
pub rog_bios_ctrl: RogBiosSupportedFunctions,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
||||||
@@ -32,7 +30,7 @@ impl SupportedFunctions {
|
|||||||
impl crate::ZbusAdd for SupportedFunctions {
|
impl crate::ZbusAdd for SupportedFunctions {
|
||||||
fn add_to_server(self, server: &mut zbus::ObjectServer) {
|
fn add_to_server(self, server: &mut zbus::ObjectServer) {
|
||||||
server
|
server
|
||||||
.at(&"/org/asuslinux/Supported".try_into().unwrap(), self)
|
.at("/org/asuslinux/Supported", self)
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
warn!("SupportedFunctions: add_to_server {}", err);
|
warn!("SupportedFunctions: add_to_server {}", err);
|
||||||
err
|
err
|
||||||
|
|||||||
+29
-39
@@ -1,11 +1,13 @@
|
|||||||
use daemon::ctrl_charge::CtrlCharge;
|
|
||||||
use daemon::ctrl_fan_cpu::{CtrlFanAndCPU, DbusFanAndCpu};
|
|
||||||
use daemon::ctrl_leds::{CtrlKbdBacklight, DbusKbdBacklight};
|
use daemon::ctrl_leds::{CtrlKbdBacklight, DbusKbdBacklight};
|
||||||
use daemon::laptops::match_laptop;
|
|
||||||
use daemon::{
|
use daemon::{
|
||||||
config::Config, ctrl_supported::SupportedFunctions, laptops::print_board_info, GetSupported,
|
config::Config, ctrl_supported::SupportedFunctions, laptops::print_board_info, GetSupported,
|
||||||
};
|
};
|
||||||
|
use daemon::{config_aura::AuraConfig, ctrl_charge::CtrlCharge};
|
||||||
use daemon::{ctrl_anime::CtrlAnimeDisplay, ctrl_gfx::gfx::CtrlGraphics};
|
use daemon::{ctrl_anime::CtrlAnimeDisplay, ctrl_gfx::gfx::CtrlGraphics};
|
||||||
|
use daemon::{
|
||||||
|
ctrl_fan_cpu::{CtrlFanAndCPU, DbusFanAndCpu},
|
||||||
|
laptops::LaptopLedData,
|
||||||
|
};
|
||||||
|
|
||||||
use daemon::{CtrlTask, Reloadable, ZbusAdd};
|
use daemon::{CtrlTask, Reloadable, ZbusAdd};
|
||||||
use log::LevelFilter;
|
use log::LevelFilter;
|
||||||
@@ -19,7 +21,6 @@ use std::sync::Mutex;
|
|||||||
|
|
||||||
use daemon::ctrl_rog_bios::CtrlRogBios;
|
use daemon::ctrl_rog_bios::CtrlRogBios;
|
||||||
use std::convert::Into;
|
use std::convert::Into;
|
||||||
use std::convert::TryInto;
|
|
||||||
use zbus::fdo;
|
use zbus::fdo;
|
||||||
use zbus::Connection;
|
use zbus::Connection;
|
||||||
|
|
||||||
@@ -31,9 +32,9 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
.filter(None, LevelFilter::Info)
|
.filter(None, LevelFilter::Info)
|
||||||
.init();
|
.init();
|
||||||
|
|
||||||
info!("daemon version {}", daemon::VERSION);
|
info!(" daemon v{}", daemon::VERSION);
|
||||||
info!(" rog-dbus version {}", rog_dbus::VERSION);
|
info!(" rog-dbus v{}", rog_dbus::VERSION);
|
||||||
info!("rog-types version {}", rog_types::VERSION);
|
info!("rog-types v{}", rog_types::VERSION);
|
||||||
|
|
||||||
start_daemon()?;
|
start_daemon()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -51,12 +52,9 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
|
|||||||
print_board_info();
|
print_board_info();
|
||||||
println!("{}", serde_json::to_string_pretty(&supported).unwrap());
|
println!("{}", serde_json::to_string_pretty(&supported).unwrap());
|
||||||
|
|
||||||
let laptop = match_laptop();
|
let config = Config::load();
|
||||||
let config = if let Some(laptop) = laptop.as_ref() {
|
let enable_gfx_switching = config.gfx_managed;
|
||||||
Config::load(laptop.supported_modes())
|
let config = Arc::new(Mutex::new(config));
|
||||||
} else {
|
|
||||||
Config::load(&[])
|
|
||||||
};
|
|
||||||
|
|
||||||
let connection = Connection::new_system()?;
|
let connection = Connection::new_system()?;
|
||||||
fdo::DBusProxy::new(&connection)?
|
fdo::DBusProxy::new(&connection)?
|
||||||
@@ -65,9 +63,6 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
|
|||||||
|
|
||||||
supported.add_to_server(&mut object_server);
|
supported.add_to_server(&mut object_server);
|
||||||
|
|
||||||
let enable_gfx_switching = config.gfx_managed;
|
|
||||||
let config = Arc::new(Mutex::new(config));
|
|
||||||
|
|
||||||
match CtrlRogBios::new(config.clone()) {
|
match CtrlRogBios::new(config.clone()) {
|
||||||
Ok(mut ctrl) => {
|
Ok(mut ctrl) => {
|
||||||
// Do a reload of any settings
|
// Do a reload of any settings
|
||||||
@@ -109,11 +104,12 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
|
|||||||
// Need to check if a laptop has the dedicated gfx switch
|
// Need to check if a laptop has the dedicated gfx switch
|
||||||
if CtrlRogBios::has_dedicated_gfx_toggle() {
|
if CtrlRogBios::has_dedicated_gfx_toggle() {
|
||||||
if let Ok(ded) = CtrlRogBios::get_gfx_mode() {
|
if let Ok(ded) = CtrlRogBios::get_gfx_mode() {
|
||||||
if let Ok(vendor) = CtrlGraphics::get_vendor() {
|
if let Ok(vendor) = ctrl.get_gfx_mode() {
|
||||||
if ded == 1 && vendor != "nvidia" {
|
if ded == 1 && vendor != GfxVendors::Nvidia {
|
||||||
error!("Dedicated GFX toggle is on but driver mode is not nvidia \nSetting to nvidia driver mode");
|
warn!("Dedicated GFX toggle is on but driver mode is not nvidia \nSetting to nvidia driver mode");
|
||||||
error!("You must reboot to enable Nvidia driver");
|
let devices = ctrl.devices();
|
||||||
CtrlGraphics::set_gfx_config(GfxVendors::Nvidia)?;
|
let bus = ctrl.bus();
|
||||||
|
CtrlGraphics::do_vendor_tasks(GfxVendors::Nvidia, &devices, &bus)?;
|
||||||
} else if ded == 0 {
|
} else if ded == 0 {
|
||||||
info!("Dedicated GFX toggle is off");
|
info!("Dedicated GFX toggle is off");
|
||||||
}
|
}
|
||||||
@@ -121,7 +117,7 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctrl.reload()
|
ctrl.reload()
|
||||||
.unwrap_or_else(|err| warn!("Gfx controller: {}", err));
|
.unwrap_or_else(|err| error!("Gfx controller: {}", err));
|
||||||
ctrl.add_to_server(&mut object_server);
|
ctrl.add_to_server(&mut object_server);
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
@@ -133,7 +129,7 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
|
|||||||
// Collect tasks for task thread
|
// Collect tasks for task thread
|
||||||
let mut tasks: Vec<Arc<Mutex<dyn CtrlTask + Send>>> = Vec::new();
|
let mut tasks: Vec<Arc<Mutex<dyn CtrlTask + Send>>> = Vec::new();
|
||||||
|
|
||||||
if let Ok(mut ctrl) = CtrlFanAndCPU::new(config.clone()).map_err(|err| {
|
if let Ok(mut ctrl) = CtrlFanAndCPU::new(config).map_err(|err| {
|
||||||
error!("Profile control: {}", err);
|
error!("Profile control: {}", err);
|
||||||
}) {
|
}) {
|
||||||
ctrl.reload()
|
ctrl.reload()
|
||||||
@@ -142,21 +138,15 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
|
|||||||
DbusFanAndCpu::new(tmp).add_to_server(&mut object_server);
|
DbusFanAndCpu::new(tmp).add_to_server(&mut object_server);
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(laptop) = laptop {
|
let laptop = LaptopLedData::get_data();
|
||||||
if let Ok(ctrl) = CtrlKbdBacklight::new(
|
let aura_config = AuraConfig::load(&laptop);
|
||||||
laptop.usb_product(),
|
if let Ok(ctrl) = CtrlKbdBacklight::new(laptop, aura_config).map_err(|err| {
|
||||||
laptop.condev_iface(),
|
error!("Keyboard control: {}", err);
|
||||||
laptop.supported_modes().to_owned(),
|
err
|
||||||
config,
|
}) {
|
||||||
)
|
let tmp = Arc::new(Mutex::new(ctrl));
|
||||||
.map_err(|err| {
|
DbusKbdBacklight::new(tmp.clone()).add_to_server(&mut object_server);
|
||||||
error!("Keyboard control: {}", err);
|
tasks.push(tmp);
|
||||||
err
|
|
||||||
}) {
|
|
||||||
let tmp = Arc::new(Mutex::new(ctrl));
|
|
||||||
DbusKbdBacklight::new(tmp.clone()).add_to_server(&mut object_server);
|
|
||||||
tasks.push(tmp);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: implement messaging between threads to check fails
|
// TODO: implement messaging between threads to check fails
|
||||||
@@ -179,7 +169,7 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
object_server
|
object_server
|
||||||
.with(&"/org/asuslinux/Charge".try_into()?, |obj: &CtrlCharge| {
|
.with("/org/asuslinux/Charge", |obj: &CtrlCharge| {
|
||||||
let x = obj.limit();
|
let x = obj.limit();
|
||||||
obj.notify_charge(x as u8)
|
obj.notify_charge(x as u8)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -25,6 +25,11 @@ pub enum RogError {
|
|||||||
MissingLedBrightNode(String, std::io::Error),
|
MissingLedBrightNode(String, std::io::Error),
|
||||||
ReloadFail(String),
|
ReloadFail(String),
|
||||||
GfxSwitching(GfxError),
|
GfxSwitching(GfxError),
|
||||||
|
Initramfs(String),
|
||||||
|
Modprobe(String),
|
||||||
|
Command(String, std::io::Error),
|
||||||
|
Io(std::io::Error),
|
||||||
|
Zbus(zbus::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for RogError {
|
impl fmt::Display for RogError {
|
||||||
@@ -48,6 +53,11 @@ impl fmt::Display for RogError {
|
|||||||
RogError::MissingLedBrightNode(path, error) => write!(f, "Led node at {} is missing, please check you have the required patch or dkms module installed: {}", path, error),
|
RogError::MissingLedBrightNode(path, error) => write!(f, "Led node at {} is missing, please check you have the required patch or dkms module installed: {}", path, error),
|
||||||
RogError::ReloadFail(deets) => write!(f, "Task error: {}", deets),
|
RogError::ReloadFail(deets) => write!(f, "Task error: {}", deets),
|
||||||
RogError::GfxSwitching(deets) => write!(f, "Graphics switching error: {}", deets),
|
RogError::GfxSwitching(deets) => write!(f, "Graphics switching error: {}", deets),
|
||||||
|
RogError::Initramfs(detail) => write!(f, "Initiramfs error: {}", detail),
|
||||||
|
RogError::Modprobe(detail) => write!(f, "Modprobe error: {}", detail),
|
||||||
|
RogError::Command(func, error) => write!(f, "Command exec error: {}: {}", func, error),
|
||||||
|
RogError::Io(detail) => write!(f, "std::io error: {}", detail),
|
||||||
|
RogError::Zbus(detail) => write!(f, "Zbus error: {}", detail),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,3 +83,15 @@ impl From<GraphicsError> for RogError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<zbus::Error> for RogError {
|
||||||
|
fn from(err: zbus::Error) -> Self {
|
||||||
|
RogError::Zbus(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<std::io::Error> for RogError {
|
||||||
|
fn from(err: std::io::Error) -> Self {
|
||||||
|
RogError::Io(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+51
-99
@@ -1,83 +1,11 @@
|
|||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
use rog_types::aura_modes::{AuraModes, BREATHING, STATIC};
|
use rog_types::aura_modes::AuraModeNum;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use std::fs::OpenOptions;
|
use std::fs::OpenOptions;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
pub static LEDMODE_CONFIG_PATH: &str = "/etc/asusd/asusd-ledmodes.toml";
|
pub const ASUS_LED_MODE_CONF: &str = "/etc/asusd/asusd-ledmodes.toml";
|
||||||
|
pub const ASUS_KEYBOARD_DEVICES: [&str; 4] = ["1866", "1869", "1854", "19b6"];
|
||||||
pub static HELP_ADDRESS: &str = "https://gitlab.com/asus-linux/asus-nb-ctrl";
|
|
||||||
|
|
||||||
static LAPTOP_DEVICES: [u16; 3] = [0x1866, 0x1869, 0x1854];
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct LaptopBase {
|
|
||||||
usb_product: String,
|
|
||||||
condev_iface: Option<String>, // required for finding the Consumer Device interface
|
|
||||||
supported_modes: Vec<u8>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LaptopBase {
|
|
||||||
pub fn usb_product(&self) -> &str {
|
|
||||||
&self.usb_product
|
|
||||||
}
|
|
||||||
pub fn condev_iface(&self) -> Option<&String> {
|
|
||||||
self.condev_iface.as_ref()
|
|
||||||
}
|
|
||||||
pub fn supported_modes(&self) -> &[u8] {
|
|
||||||
&self.supported_modes
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn match_laptop() -> Option<LaptopBase> {
|
|
||||||
for device in rusb::devices().expect("Couldn't get device").iter() {
|
|
||||||
let device_desc = device
|
|
||||||
.device_descriptor()
|
|
||||||
.expect("Couldn't get device descriptor");
|
|
||||||
if device_desc.vendor_id() == 0x0b05 {
|
|
||||||
if LAPTOP_DEVICES.contains(&device_desc.product_id()) {
|
|
||||||
let prod_str = format!("{:x?}", device_desc.product_id());
|
|
||||||
|
|
||||||
if device_desc.product_id() == 0x1854 {
|
|
||||||
let mut laptop = laptop(prod_str, None);
|
|
||||||
if laptop.supported_modes.is_empty() {
|
|
||||||
laptop.supported_modes = vec![STATIC, BREATHING];
|
|
||||||
}
|
|
||||||
return Some(laptop);
|
|
||||||
}
|
|
||||||
|
|
||||||
let laptop = laptop(prod_str, Some("02".to_owned()));
|
|
||||||
return Some(laptop);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
warn!(
|
|
||||||
"Unsupported laptop, please request support at {}",
|
|
||||||
HELP_ADDRESS
|
|
||||||
);
|
|
||||||
warn!("Continuing with minimal support");
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
fn laptop(prod: String, condev_iface: Option<String>) -> LaptopBase {
|
|
||||||
let dmi = sysfs_class::DmiId::default();
|
|
||||||
let board_name = dmi.board_name().expect("Could not get board_name");
|
|
||||||
let prod_family = dmi.product_family().expect("Could not get product_family");
|
|
||||||
|
|
||||||
let mut laptop = LaptopBase {
|
|
||||||
usb_product: prod,
|
|
||||||
condev_iface,
|
|
||||||
supported_modes: vec![],
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(modes) = LEDModeGroup::load_from_config() {
|
|
||||||
if let Some(led_modes) = modes.matcher(&prod_family, &board_name) {
|
|
||||||
laptop.supported_modes = led_modes;
|
|
||||||
return laptop;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
laptop
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn print_board_info() {
|
pub fn print_board_info() {
|
||||||
let dmi = sysfs_class::DmiId::default();
|
let dmi = sysfs_class::DmiId::default();
|
||||||
@@ -94,12 +22,12 @@ pub fn print_modes(supported_modes: &[u8]) {
|
|||||||
if !supported_modes.is_empty() {
|
if !supported_modes.is_empty() {
|
||||||
info!("Supported Keyboard LED modes are:");
|
info!("Supported Keyboard LED modes are:");
|
||||||
for mode in supported_modes {
|
for mode in supported_modes {
|
||||||
let mode = <&str>::from(&<AuraModes>::from(*mode));
|
let mode = <&str>::from(&<AuraModeNum>::from(*mode));
|
||||||
info!("- {}", mode);
|
info!("- {}", mode);
|
||||||
}
|
}
|
||||||
info!(
|
info!(
|
||||||
"If these modes are incorrect or missing please request support at {}",
|
"If these modes are incorrect you can edit {}",
|
||||||
HELP_ADDRESS
|
ASUS_LED_MODE_CONF
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
info!("No RGB control available");
|
info!("No RGB control available");
|
||||||
@@ -107,19 +35,50 @@ pub fn print_modes(supported_modes: &[u8]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
struct LEDModeGroup {
|
struct LedSupportFile {
|
||||||
led_modes: Vec<LEDModes>,
|
led_data: Vec<LaptopLedData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LEDModeGroup {
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||||
|
pub struct LaptopLedData {
|
||||||
|
pub prod_family: String,
|
||||||
|
pub board_names: Vec<String>,
|
||||||
|
pub standard: Vec<AuraModeNum>,
|
||||||
|
pub multizone: bool,
|
||||||
|
pub per_key: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LaptopLedData {
|
||||||
|
pub fn get_data() -> Self {
|
||||||
|
let dmi = sysfs_class::DmiId::default();
|
||||||
|
let board_name = dmi.board_name().expect("Could not get board_name");
|
||||||
|
let prod_family = dmi.product_family().expect("Could not get product_family");
|
||||||
|
|
||||||
|
if let Some(modes) = LedSupportFile::load_from_config() {
|
||||||
|
if let Some(data) = modes.matcher(&prod_family, &board_name) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
info!("Using generic LED control for keyboard brightness only");
|
||||||
|
LaptopLedData {
|
||||||
|
prod_family,
|
||||||
|
board_names: vec![board_name],
|
||||||
|
standard: vec![],
|
||||||
|
multizone: false,
|
||||||
|
per_key: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LedSupportFile {
|
||||||
/// Consumes the LEDModes
|
/// Consumes the LEDModes
|
||||||
fn matcher(self, prod_family: &str, board_name: &str) -> Option<Vec<u8>> {
|
fn matcher(self, prod_family: &str, board_name: &str) -> Option<LaptopLedData> {
|
||||||
for led_modes in self.led_modes {
|
for config in self.led_data {
|
||||||
if prod_family.contains(&led_modes.prod_family) {
|
if prod_family.contains(&config.prod_family) {
|
||||||
for board in led_modes.board_names {
|
for board in &config.board_names {
|
||||||
if board_name.contains(&board) {
|
if board_name.contains(board) {
|
||||||
info!("Matched to {} {}", led_modes.prod_family, board);
|
info!("Matched to {} {}", config.prod_family, board);
|
||||||
return Some(led_modes.led_modes);
|
return Some(config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -128,26 +87,19 @@ impl LEDModeGroup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn load_from_config() -> Option<Self> {
|
fn load_from_config() -> Option<Self> {
|
||||||
if let Ok(mut file) = OpenOptions::new().read(true).open(&LEDMODE_CONFIG_PATH) {
|
if let Ok(mut file) = OpenOptions::new().read(true).open(&ASUS_LED_MODE_CONF) {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
if let Ok(l) = file.read_to_string(&mut buf) {
|
if let Ok(l) = file.read_to_string(&mut buf) {
|
||||||
if l == 0 {
|
if l == 0 {
|
||||||
warn!("{} is empty", LEDMODE_CONFIG_PATH);
|
warn!("{} is empty", ASUS_LED_MODE_CONF);
|
||||||
} else {
|
} else {
|
||||||
return Some(toml::from_str(&buf).unwrap_or_else(|_| {
|
return Some(toml::from_str(&buf).unwrap_or_else(|_| {
|
||||||
panic!("Could not deserialise {}", LEDMODE_CONFIG_PATH)
|
panic!("Could not deserialise {}", ASUS_LED_MODE_CONF)
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
warn!("Does {} exist?", LEDMODE_CONFIG_PATH);
|
warn!("Does {} exist?", ASUS_LED_MODE_CONF);
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
|
||||||
struct LEDModes {
|
|
||||||
prod_family: String,
|
|
||||||
board_names: Vec<String>,
|
|
||||||
led_modes: Vec<u8>,
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#![deny(unused_must_use)]
|
#![deny(unused_must_use)]
|
||||||
/// Configuration loading, saving
|
/// Configuration loading, saving
|
||||||
pub mod config;
|
pub mod config;
|
||||||
|
pub mod config_aura;
|
||||||
|
pub(crate) mod config_old;
|
||||||
/// Control of AniMe matrix display
|
/// Control of AniMe matrix display
|
||||||
pub mod ctrl_anime;
|
pub mod ctrl_anime;
|
||||||
/// Control of battery charge level
|
/// Control of battery charge level
|
||||||
|
|||||||
+52
-23
@@ -1,54 +1,83 @@
|
|||||||
[[led_modes]]
|
[[led_data]]
|
||||||
prod_family = "Zephyrus S"
|
prod_family = "Zephyrus S"
|
||||||
board_names = ["GX502", "GX701", "G531", "GL531", "G532"]
|
board_names = ["GX502", "GX701", "G531", "GL531", "G532"]
|
||||||
led_modes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 255]
|
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Star", "Rain", "Highlight", "Laser", "Ripple", "Pulse", "Comet", "Flash"]
|
||||||
|
multizone = false
|
||||||
|
per_key = true
|
||||||
|
|
||||||
[[led_modes]]
|
[[led_data]]
|
||||||
prod_family = "Zephyrus M"
|
prod_family = "Zephyrus M"
|
||||||
board_names = ["GU502GV"]
|
board_names = ["GU502GV"]
|
||||||
led_modes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 255]
|
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Star", "Rain", "Highlight", "Laser", "Ripple", "Pulse", "Comet", "Flash"]
|
||||||
|
multizone = false
|
||||||
|
per_key = true
|
||||||
|
|
||||||
[[led_modes]]
|
[[led_data]]
|
||||||
prod_family = "ROG Zephyrus M15"
|
prod_family = "ROG Zephyrus M15"
|
||||||
board_names = ["GU502LW"]
|
board_names = ["GU502LW"]
|
||||||
led_modes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 255]
|
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Star", "Rain", "Highlight", "Laser", "Ripple", "Pulse", "Comet", "Flash"]
|
||||||
|
multizone = false
|
||||||
|
per_key = true
|
||||||
|
|
||||||
[[led_modes]]
|
[[led_data]]
|
||||||
|
prod_family = "ROG Zephyrus M15"
|
||||||
|
board_names = ["GU502LU"]
|
||||||
|
standard = ["Static", "Breathe", "Strobe", "Pulse"]
|
||||||
|
multizone = false
|
||||||
|
per_key = false
|
||||||
|
|
||||||
|
[[led_data]]
|
||||||
prod_family = "Zephyrus"
|
prod_family = "Zephyrus"
|
||||||
board_names = ["GM501GM", "GX531"]
|
board_names = ["GM501GM", "GX531"]
|
||||||
led_modes = [0, 1, 2, 3, 10, 13]
|
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Pulse"]
|
||||||
|
multizone = true
|
||||||
|
per_key = false
|
||||||
|
|
||||||
[[led_modes]]
|
[[led_data]]
|
||||||
prod_family = "ROG Strix"
|
prod_family = "ROG Strix"
|
||||||
board_names = ["G531GW"]
|
board_names = ["G531GW"]
|
||||||
led_modes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 255]
|
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Star", "Rain", "Highlight", "Laser", "Ripple", "Pulse", "Comet", "Flash"]
|
||||||
|
multizone = false
|
||||||
|
per_key = true
|
||||||
|
|
||||||
[[led_modes]]
|
[[led_data]]
|
||||||
prod_family = "ROG Strix"
|
prod_family = "ROG Strix"
|
||||||
board_names = ["GX531", "G512LV", "G712LV"]
|
board_names = ["GX531", "G512LV", "G712LV"]
|
||||||
led_modes = [0, 1, 2, 3, 10, 13, 14]
|
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Pulse"]
|
||||||
|
multizone = true
|
||||||
|
per_key = false
|
||||||
|
|
||||||
[[led_modes]]
|
[[led_data]]
|
||||||
prod_family = "ROG Strix"
|
prod_family = "ROG Strix"
|
||||||
board_names = ["G512LI", "G712LI"]
|
board_names = ["G512LI", "G712LI", "G531GD"]
|
||||||
led_modes = [0, 1, 2, 3, 10]
|
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Pulse"]
|
||||||
|
multizone = false
|
||||||
|
per_key = false
|
||||||
|
|
||||||
[[led_modes]]
|
[[led_data]]
|
||||||
prod_family = "Strix"
|
prod_family = "Strix"
|
||||||
board_names = ["G731GV", "G731GW", "G531GV"]
|
board_names = ["G731GV", "G731GW", "G531GV"]
|
||||||
led_modes = [0, 1, 2, 3, 13, 14]
|
standard = ["Static", "Breathe", "Strobe", "Rainbow"]
|
||||||
|
multizone = true
|
||||||
|
per_key = false
|
||||||
|
|
||||||
[[led_modes]]
|
[[led_data]]
|
||||||
prod_family = "Strix"
|
prod_family = "Strix"
|
||||||
board_names = ["G731GT", "G731GU", "G531GT", "G531GU"]
|
board_names = ["G731GT", "G731GU", "G531GT", "G531GU"]
|
||||||
led_modes = [0, 1, 2, 3]
|
standard = ["Static", "Breathe", "Strobe", "Rainbow"]
|
||||||
|
multizone = false
|
||||||
|
per_key = false
|
||||||
|
|
||||||
[[led_modes]]
|
[[led_data]]
|
||||||
prod_family = "Strix Scar"
|
prod_family = "Strix Scar"
|
||||||
board_names = ["G531", "G731"]
|
board_names = ["G531", "G731"]
|
||||||
led_modes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 255]
|
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Star", "Rain", "Highlight", "Laser", "Ripple", "Pulse", "Comet", "Flash"]
|
||||||
|
multizone = true
|
||||||
|
per_key = true
|
||||||
|
|
||||||
[[led_modes]]
|
[[led_data]]
|
||||||
prod_family = "ROG"
|
prod_family = "ROG"
|
||||||
board_names = ["GL553VE"]
|
board_names = ["GL553VE"]
|
||||||
led_modes = [0, 1, 2, 13, 14]
|
standard = ["Static", "Breathe", "Strobe"]
|
||||||
|
multizone = true
|
||||||
|
per_key = false
|
||||||
@@ -10,6 +10,10 @@
|
|||||||
<allow send_destination="org.asuslinux.Daemon"/>
|
<allow send_destination="org.asuslinux.Daemon"/>
|
||||||
<allow receive_sender="org.asuslinux.Daemon"/>
|
<allow receive_sender="org.asuslinux.Daemon"/>
|
||||||
</policy>
|
</policy>
|
||||||
|
<policy group="users">
|
||||||
|
<allow send_destination="org.asuslinux.Daemon"/>
|
||||||
|
<allow receive_sender="org.asuslinux.Daemon"/>
|
||||||
|
</policy>
|
||||||
<policy group="wheel">
|
<policy group="wheel">
|
||||||
<allow send_destination="org.asuslinux.Daemon"/>
|
<allow send_destination="org.asuslinux.Daemon"/>
|
||||||
<allow receive_sender="org.asuslinux.Daemon"/>
|
<allow receive_sender="org.asuslinux.Daemon"/>
|
||||||
|
|||||||
+2
-2
@@ -1,2 +1,2 @@
|
|||||||
ACTION=="add|change", SUBSYSTEM=="input", ENV{ID_VENDOR_ID}=="0b05", ENV{ID_MODEL_ID}=="18[0-9][0-9]|193b", ENV{ID_TYPE}=="hid", TAG+="systemd", ENV{SYSTEMD_WANTS}="asusd.service"
|
ACTION=="add|change", SUBSYSTEM=="input", ENV{ID_VENDOR_ID}=="0b05", ENV{ID_MODEL_ID}=="1[89][a-zA-Z0-9][a-zA-Z0-9]|193b", ENV{ID_TYPE}=="hid", TAG+="systemd", ENV{SYSTEMD_WANTS}="asusd.service"
|
||||||
ACTION=="add|remove", SUBSYSTEM=="input", ENV{ID_VENDOR_ID}=="0b05", ENV{ID_MODEL_ID}=="18[0-9][0-9]|193b", RUN+="systemctl restart asusd.service"
|
ACTION=="add|remove", SUBSYSTEM=="input", ENV{ID_VENDOR_ID}=="0b05", ENV{ID_MODEL_ID}=="1[89][a-zA-Z0-9][a-zA-Z0-9]|193b", RUN+="systemctl restart asusd.service"
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
Description=ASUS Notebook Control
|
Description=ASUS Notebook Control
|
||||||
StartLimitInterval=200
|
StartLimitInterval=200
|
||||||
StartLimitBurst=2
|
StartLimitBurst=2
|
||||||
|
Before=display-manager.service
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
ExecStart=/usr/bin/asusd
|
ExecStart=/usr/bin/asusd
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
# Author: AlenPaulVarghese <alenpaul2001@gmail.com>
|
||||||
|
|
||||||
|
set -l progname asusctl
|
||||||
|
|
||||||
|
set -l noopt "not __fish_contains_opt -s -s h -s v -s s -s k -s f -s c help version show-supported kbd-bright fan-mode chg-limit; and not __fish_seen_subcommand_from led-mode profile graphics;"
|
||||||
|
|
||||||
|
|
||||||
|
set -l gmod_options '__fish_contains_opt -s m mode;'
|
||||||
|
set -l fan_options '__fish_contains_opt -s f fan-mode;'
|
||||||
|
set -l led_options '__fish_seen_subcommand_from led-mode;'
|
||||||
|
set -l profile_options '__fish_seen_subcommand_from profile;'
|
||||||
|
set -l keyboard_options '__fish_contains_opt -s k kbd-bright;'
|
||||||
|
set -l graphics_options '__fish_seen_subcommand_from graphics;'
|
||||||
|
|
||||||
|
set -l fan_modes 'silent normal boost'
|
||||||
|
set -l brightness_modes 'off low med high'
|
||||||
|
set -l led_modes 'static breathe strobe rainbow comet'
|
||||||
|
set -l graphics_modes 'nvidia hybird compute integrated'
|
||||||
|
|
||||||
|
|
||||||
|
complete -c $progname -e
|
||||||
|
complete -c $progname -f
|
||||||
|
|
||||||
|
# asusctl completion
|
||||||
|
complete -c $progname -s h -f -l help -n "$noopt" -d "print help message"
|
||||||
|
complete -c $progname -s v -f -l version -n "$noopt" -d "show program version number"
|
||||||
|
complete -c $progname -s s -f -l show-supported -n "$noopt" -d "show supported functions of this laptop"
|
||||||
|
complete -c $progname -s k -f -l kbd-bright -n "$noopt" -d "set led brightness"
|
||||||
|
complete -c $progname -s f -f -l fan-mode -n "$noopt" -d "set fan mode independent of profile"
|
||||||
|
complete -c $progname -s c -f -l chg-limit -n "$noopt" -d "set charge limit <20-100>"
|
||||||
|
complete -c $progname -f -a "led-mode" -n "$noopt" -d "Set the keyboard lighting from built-in modes"
|
||||||
|
complete -c $progname -f -a "profile" -n "$noopt" -d "Create and configure profiles"
|
||||||
|
complete -c $progname -f -a "graphics" -n "$noopt" -d "Set the graphics mode"
|
||||||
|
|
||||||
|
# brightness completion
|
||||||
|
complete -c $progname -n "$keyboard_options" -d "available brightness modes" -a "$brightness_modes"
|
||||||
|
|
||||||
|
# fan completion
|
||||||
|
complete -c $progname -n "$fan_options" -d "available fan modes" -a $fan_modes
|
||||||
|
|
||||||
|
# graphics completion
|
||||||
|
set -l gopt 'not __fish_contains_opt -s h -s g -s m -s p help mode get pow;'
|
||||||
|
|
||||||
|
complete -c $progname -n "$graphics_options and $gopt" -a "-h" -d "print help message"
|
||||||
|
complete -c $progname -n "$graphics_options and $gopt" -a "-g" -d "Get the current mode"
|
||||||
|
|
||||||
|
complete -c $progname -s h -f -l help -n "$graphics_options and $gopt" -d "print help message"
|
||||||
|
complete -c $progname -s m -f -l mode -n "$graphics_options and $gopt" -d "Set graphics mode: <nvidia, hybrid, compute, integrated>"
|
||||||
|
complete -c $progname -s g -f -l get -n "$graphics_options and $gopt" -d "Get the current mode"
|
||||||
|
complete -c $progname -s p -f -l pow -n "$graphics_options and $gopt" -d "Get the current power status"
|
||||||
|
|
||||||
|
complete -c $progname -n "$graphics_options and $gmod_options" -d "available graphics modes" -a "$graphics_modes"
|
||||||
|
|
||||||
|
# led-mode completion
|
||||||
|
complete -c $progname -n "$led_options" -a "-h" -d "print help message"
|
||||||
|
complete -c $progname -n "$led_options" -a "-n" -d "switch to next aura mode"
|
||||||
|
|
||||||
|
complete -c $progname -s h -f -l help -n "$led_options" -d "print help message"
|
||||||
|
complete -c $progname -s n -f -l next-mode -n "$led_options" -d "switch to nex aura mode"
|
||||||
|
complete -c $progname -s p -f -l prev-mode -n "$led_options" -d "switch to previous aura mode"
|
||||||
|
complete -c $progname -n "$led_options" -d "available led modes" -a "$led_modes"
|
||||||
|
|
||||||
|
# profile completion
|
||||||
|
set -l popt 'not __fish_contains_opt -s h -s n -s c -s t -s m -s M -s f help next create turbo min-percentage max-percentage fan-preset;'
|
||||||
|
|
||||||
|
complete -c $progname -n "$profile_options and $popt" -a "-h" -d "print help message"
|
||||||
|
complete -c $progname -n "$profile_options and $popt" -a "-n" -d "toggle to next profile in list"
|
||||||
|
|
||||||
|
complete -c $progname -s h -f -l help -n "$profile_options and $popt" -d "print help message"
|
||||||
|
complete -c $progname -s n -f -l next -n "$profile_options and $popt" -d "toggle to next profile in list"
|
||||||
|
complete -c $progname -s c -f -l create -n "$profile_options and $popt" -d "create the profile if it doesn't exist"
|
||||||
|
complete -c $progname -s t -f -l turbo -n "$profile_options and $popt" -d "enable or disable cpu turbo"
|
||||||
|
complete -c $progname -s m -f -l min-percentage -n "$profile_options and $popt" -d "set min cpu scaling (intel)"
|
||||||
|
complete -c $progname -s M -f -l max-percentage -n "$profile_options and $popt" -d "set max cpu scaling (intel)"
|
||||||
|
complete -c $progname -s f -f -l fan-preset -n "$profile_options and $popt" -d "<silent, normal, boost>"
|
||||||
|
complete -c $progname -n "$profile_option and __fish_contains_opt fan-preset" -d "available fan modes" -a $fan_modes
|
||||||
|
|
||||||
+1
-1
@@ -15,4 +15,4 @@ rog_types = { path = "../rog-types" }
|
|||||||
rog_fan_curve = { version = "^0.1", features = ["serde"] }
|
rog_fan_curve = { version = "^0.1", features = ["serde"] }
|
||||||
zbus = "^1.8"
|
zbus = "^1.8"
|
||||||
zbus_macros = "^1.8"
|
zbus_macros = "^1.8"
|
||||||
zvariant = "^2.4"
|
zvariant = "^2.5"
|
||||||
|
|||||||
+9
-6
@@ -11,7 +11,10 @@ pub mod zbus_profile;
|
|||||||
pub mod zbus_rogbios;
|
pub mod zbus_rogbios;
|
||||||
pub mod zbus_supported;
|
pub mod zbus_supported;
|
||||||
|
|
||||||
use rog_types::aura_modes::AuraModes;
|
use rog_types::{
|
||||||
|
aura_modes::AuraEffect,
|
||||||
|
gfx_vendors::{GfxRequiredUserAction, GfxVendors},
|
||||||
|
};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use zbus::{Connection, Result, SignalReceiver};
|
use zbus::{Connection, Result, SignalReceiver};
|
||||||
|
|
||||||
@@ -86,10 +89,10 @@ impl<'a> DbusProxies<'a> {
|
|||||||
|
|
||||||
// Signals separated out
|
// Signals separated out
|
||||||
pub struct Signals {
|
pub struct Signals {
|
||||||
pub gfx_vendor: Arc<Mutex<Option<String>>>,
|
pub gfx_vendor: Arc<Mutex<Option<GfxVendors>>>,
|
||||||
pub gfx_action: Arc<Mutex<Option<String>>>,
|
pub gfx_action: Arc<Mutex<Option<GfxRequiredUserAction>>>,
|
||||||
pub profile: Arc<Mutex<Option<String>>>,
|
pub profile: Arc<Mutex<Option<String>>>,
|
||||||
pub led_mode: Arc<Mutex<Option<AuraModes>>>,
|
pub led_mode: Arc<Mutex<Option<AuraEffect>>>,
|
||||||
pub charge: Arc<Mutex<Option<u8>>>,
|
pub charge: Arc<Mutex<Option<u8>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,13 +154,13 @@ impl<'a> AuraDbusClient<'a> {
|
|||||||
/*
|
/*
|
||||||
* GFX
|
* GFX
|
||||||
*/
|
*/
|
||||||
pub fn gfx_wait_changed(&self) -> Result<String> {
|
pub fn gfx_wait_changed(&self) -> Result<GfxRequiredUserAction> {
|
||||||
loop {
|
loop {
|
||||||
if let Ok(res) = self.proxies.gfx.proxy().next_signal() {
|
if let Ok(res) = self.proxies.gfx.proxy().next_signal() {
|
||||||
if res.is_none() {
|
if res.is_none() {
|
||||||
if let Ok(lock) = self.signals.gfx_action.lock() {
|
if let Ok(lock) = self.signals.gfx_action.lock() {
|
||||||
if let Some(stuff) = lock.as_ref() {
|
if let Some(stuff) = lock.as_ref() {
|
||||||
return Ok(stuff.to_string());
|
return Ok(*stuff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// return Ok("Failed for unknown reason".to_owned());
|
// return Ok("Failed for unknown reason".to_owned());
|
||||||
|
|||||||
+14
-10
@@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
use rog_types::gfx_vendors::{GfxRequiredUserAction, GfxVendors};
|
||||||
use zbus::{dbus_proxy, Connection, Result};
|
use zbus::{dbus_proxy, Connection, Result};
|
||||||
|
|
||||||
#[dbus_proxy(
|
#[dbus_proxy(
|
||||||
@@ -32,18 +33,18 @@ trait Daemon {
|
|||||||
fn power(&self) -> zbus::Result<String>;
|
fn power(&self) -> zbus::Result<String>;
|
||||||
|
|
||||||
/// SetVendor method
|
/// SetVendor method
|
||||||
fn set_vendor(&self, vendor: &str) -> zbus::Result<()>;
|
fn set_vendor(&self, vendor: &GfxVendors) -> zbus::Result<GfxRequiredUserAction>;
|
||||||
|
|
||||||
/// Vendor method
|
/// Vendor method
|
||||||
fn vendor(&self) -> zbus::Result<String>;
|
fn vendor(&self) -> zbus::Result<GfxVendors>;
|
||||||
|
|
||||||
/// NotifyAction signal
|
/// NotifyAction signal
|
||||||
#[dbus_proxy(signal)]
|
#[dbus_proxy(signal)]
|
||||||
fn notify_action(&self, action: &str) -> zbus::Result<()>;
|
fn notify_action(&self, action: GfxRequiredUserAction) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// NotifyGfx signal
|
/// NotifyGfx signal
|
||||||
#[dbus_proxy(signal)]
|
#[dbus_proxy(signal)]
|
||||||
fn notify_gfx(&self, vendor: &str) -> zbus::Result<()>;
|
fn notify_gfx(&self, vendor: GfxVendors) -> zbus::Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct GfxProxy<'a>(DaemonProxy<'a>);
|
pub struct GfxProxy<'a>(DaemonProxy<'a>);
|
||||||
@@ -64,33 +65,36 @@ impl<'a> GfxProxy<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn gfx_get_mode(&self) -> Result<String> {
|
pub fn gfx_get_mode(&self) -> Result<GfxVendors> {
|
||||||
self.0.vendor()
|
self.0.vendor()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn gfx_write_mode(&self, vendor: &str) -> Result<()> {
|
pub fn gfx_write_mode(&self, vendor: &GfxVendors) -> Result<GfxRequiredUserAction> {
|
||||||
self.0.set_vendor(vendor)
|
self.0.set_vendor(vendor)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn connect_notify_action(
|
pub fn connect_notify_action(
|
||||||
&self,
|
&self,
|
||||||
action: Arc<Mutex<Option<String>>>,
|
action: Arc<Mutex<Option<GfxRequiredUserAction>>>,
|
||||||
) -> zbus::fdo::Result<()> {
|
) -> zbus::fdo::Result<()> {
|
||||||
self.0.connect_notify_action(move |data| {
|
self.0.connect_notify_action(move |data| {
|
||||||
if let Ok(mut lock) = action.lock() {
|
if let Ok(mut lock) = action.lock() {
|
||||||
*lock = Some(data.to_owned());
|
*lock = Some(data);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn connect_notify_gfx(&self, vendor: Arc<Mutex<Option<String>>>) -> zbus::fdo::Result<()> {
|
pub fn connect_notify_gfx(
|
||||||
|
&self,
|
||||||
|
vendor: Arc<Mutex<Option<GfxVendors>>>,
|
||||||
|
) -> zbus::fdo::Result<()> {
|
||||||
self.0.connect_notify_gfx(move |data| {
|
self.0.connect_notify_gfx(move |data| {
|
||||||
if let Ok(mut lock) = vendor.lock() {
|
if let Ok(mut lock) = vendor.lock() {
|
||||||
*lock = Some(data.to_owned());
|
*lock = Some(data);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
|
|||||||
+34
-27
@@ -23,7 +23,10 @@ use std::sync::{Arc, Mutex};
|
|||||||
|
|
||||||
use zbus::{dbus_proxy, Connection, Result};
|
use zbus::{dbus_proxy, Connection, Result};
|
||||||
|
|
||||||
use rog_types::{aura_modes::AuraModes, cli_options::LedBrightness, fancy::KeyColourArray};
|
use rog_types::{
|
||||||
|
aura_modes::{AuraEffect, LedBrightness},
|
||||||
|
aura_perkey::KeyColourArray,
|
||||||
|
};
|
||||||
|
|
||||||
const BLOCKING_TIME: u64 = 40; // 100ms = 10 FPS, max 50ms = 20 FPS, 40ms = 25 FPS
|
const BLOCKING_TIME: u64 = 40; // 100ms = 10 FPS, max 50ms = 20 FPS, 40ms = 25 FPS
|
||||||
|
|
||||||
@@ -32,27 +35,34 @@ const BLOCKING_TIME: u64 = 40; // 100ms = 10 FPS, max 50ms = 20 FPS, 40ms = 25 F
|
|||||||
default_path = "/org/asuslinux/Led"
|
default_path = "/org/asuslinux/Led"
|
||||||
)]
|
)]
|
||||||
trait Daemon {
|
trait Daemon {
|
||||||
/// LedBrightness method
|
|
||||||
fn led_brightness(&self) -> zbus::Result<i16>;
|
|
||||||
|
|
||||||
/// LedMode method
|
|
||||||
fn led_mode(&self) -> zbus::Result<String>;
|
|
||||||
|
|
||||||
/// LedModes method
|
|
||||||
fn led_modes(&self) -> zbus::Result<String>;
|
|
||||||
|
|
||||||
/// NextLedMode method
|
/// NextLedMode method
|
||||||
fn next_led_mode(&self) -> zbus::Result<()>;
|
fn next_led_mode(&self) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// PrevLedMode method
|
/// PrevLedMode method
|
||||||
fn prev_led_mode(&self) -> zbus::Result<()>;
|
fn prev_led_mode(&self) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// SetLedMode method
|
/// SetBrightness method
|
||||||
fn set_led_mode(&self, data: &str) -> zbus::Result<()>;
|
fn set_brightness(&self, brightness: LedBrightness) -> zbus::Result<()>;
|
||||||
|
|
||||||
|
/// SetLedMode method
|
||||||
|
fn set_led_mode(&self, effect: &AuraEffect) -> zbus::Result<()>;
|
||||||
|
|
||||||
|
/// NotifyLed signal
|
||||||
/// NotifyLed signal
|
/// NotifyLed signal
|
||||||
#[dbus_proxy(signal)]
|
#[dbus_proxy(signal)]
|
||||||
fn notify_led(&self, data: &str) -> zbus::Result<()>;
|
fn notify_led(&self, data: &str) -> zbus::Result<()>;
|
||||||
|
|
||||||
|
/// LedBrightness property
|
||||||
|
#[dbus_proxy(property)]
|
||||||
|
fn led_brightness(&self) -> zbus::Result<i16>;
|
||||||
|
|
||||||
|
/// LedMode property
|
||||||
|
#[dbus_proxy(property)]
|
||||||
|
fn led_mode(&self) -> zbus::Result<String>;
|
||||||
|
|
||||||
|
/// LedModes property
|
||||||
|
#[dbus_proxy(property)]
|
||||||
|
fn led_modes(&self) -> zbus::Result<String>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct LedProxy<'a>(DaemonProxy<'a>);
|
pub struct LedProxy<'a>(DaemonProxy<'a>);
|
||||||
@@ -68,16 +78,13 @@ impl<'a> LedProxy<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_led_brightness(&self) -> Result<LedBrightness> {
|
pub fn get_led_brightness(&self) -> Result<i16> {
|
||||||
match self.0.led_brightness()? {
|
self.0.led_brightness()
|
||||||
-1 => Ok(LedBrightness::new(None)),
|
|
||||||
level => Ok(LedBrightness::new(Some(level as u8))),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_brightness(&self, level: u8) -> Result<()> {
|
pub fn set_led_brightness(&self, level: LedBrightness) -> Result<()> {
|
||||||
self.set_led_mode(&AuraModes::LedBrightness(level))?;
|
self.0.set_brightness(level)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,8 +99,8 @@ impl<'a> LedProxy<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_led_mode(&self, mode: &AuraModes) -> Result<()> {
|
pub fn set_led_mode(&self, mode: &AuraEffect) -> Result<()> {
|
||||||
self.0.set_led_mode(&serde_json::to_string(mode).unwrap())
|
self.0.set_led_mode(mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write a single colour block.
|
/// Write a single colour block.
|
||||||
@@ -107,9 +114,8 @@ impl<'a> LedProxy<'a> {
|
|||||||
for v in group {
|
for v in group {
|
||||||
vecs.push(v.to_vec());
|
vecs.push(v.to_vec());
|
||||||
}
|
}
|
||||||
let mode = AuraModes::PerKey(vecs);
|
// TODO: let mode = AuraModes::PerKey(vecs);
|
||||||
|
// self.set_led_mode(&mode)?;
|
||||||
self.set_led_mode(&mode)?;
|
|
||||||
|
|
||||||
std::thread::sleep(std::time::Duration::from_millis(BLOCKING_TIME));
|
std::thread::sleep(std::time::Duration::from_millis(BLOCKING_TIME));
|
||||||
|
|
||||||
@@ -124,12 +130,13 @@ impl<'a> LedProxy<'a> {
|
|||||||
/// the keyboard LED EC in the correct mode
|
/// the keyboard LED EC in the correct mode
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn init_effect(&self) -> Result<()> {
|
pub fn init_effect(&self) -> Result<()> {
|
||||||
let mode = AuraModes::PerKey(vec![vec![]]);
|
// TODO: let mode = AuraModes::PerKey(vec![vec![]]);
|
||||||
self.0.set_led_mode(&serde_json::to_string(&mode).unwrap())
|
// self.0.set_led_mode(&serde_json::to_string(&mode).unwrap())
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn connect_notify_led(&self, led: Arc<Mutex<Option<AuraModes>>>) -> zbus::fdo::Result<()> {
|
pub fn connect_notify_led(&self, led: Arc<Mutex<Option<AuraEffect>>>) -> zbus::fdo::Result<()> {
|
||||||
self.0.connect_notify_led(move |data| {
|
self.0.connect_notify_led(move |data| {
|
||||||
if let Ok(mut lock) = led.lock() {
|
if let Ok(mut lock) = led.lock() {
|
||||||
if let Ok(dat) = serde_json::from_str(&data) {
|
if let Ok(dat) = serde_json::from_str(&data) {
|
||||||
|
|||||||
@@ -41,6 +41,12 @@ trait Daemon {
|
|||||||
/// Profiles method
|
/// Profiles method
|
||||||
fn profiles(&self) -> zbus::Result<String>;
|
fn profiles(&self) -> zbus::Result<String>;
|
||||||
|
|
||||||
|
/// ProfileNames method
|
||||||
|
fn profile_names(&self) -> zbus::Result<String>;
|
||||||
|
|
||||||
|
/// Remove method
|
||||||
|
fn remove(&self, profile: &str) -> zbus::Result<()>;
|
||||||
|
|
||||||
/// SetProfile method
|
/// SetProfile method
|
||||||
fn set_profile(&self, profile: &str) -> zbus::Result<()>;
|
fn set_profile(&self, profile: &str) -> zbus::Result<()>;
|
||||||
|
|
||||||
@@ -82,6 +88,16 @@ impl<'a> ProfileProxy<'a> {
|
|||||||
self.0.set_profile(&serde_json::to_string(cmd).unwrap())
|
self.0.set_profile(&serde_json::to_string(cmd).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn profile_names(&self) -> Result<String> {
|
||||||
|
self.0.profile_names()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn remove(&self, profile: &str) -> Result<()> {
|
||||||
|
self.0.remove(profile)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn connect_notify_profile(
|
pub fn connect_notify_profile(
|
||||||
&self,
|
&self,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "rog_types"
|
name = "rog_types"
|
||||||
version = "3.0.0"
|
version = "3.1.1"
|
||||||
license = "MPL-2.0"
|
license = "MPL-2.0"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
authors = ["Luke <luke@ljones.dev>"]
|
authors = ["Luke <luke@ljones.dev>"]
|
||||||
|
|||||||
+286
-218
@@ -1,31 +1,47 @@
|
|||||||
use crate::cli_options::SetAuraBuiltin;
|
// static LED_INIT1: [u8; 2] = [0x5d, 0xb9];
|
||||||
|
// static LED_INIT2: &str = "]ASUS Tech.Inc."; // ] == 0x5d
|
||||||
|
// static LED_INIT3: [u8; 6] = [0x5d, 0x05, 0x20, 0x31, 0, 0x08];
|
||||||
|
// static LED_INIT4: &str = "^ASUS Tech.Inc."; // ^ == 0x5e
|
||||||
|
// static LED_INIT5: [u8; 6] = [0x5e, 0x05, 0x20, 0x31, 0, 0x08];
|
||||||
|
|
||||||
use crate::error::AuraError;
|
use crate::error::AuraError;
|
||||||
use gumdrop::Options;
|
use crate::LED_MSG_LEN;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
use zvariant_derive::Type;
|
||||||
|
|
||||||
pub const STATIC: u8 = 0x00;
|
#[derive(Debug, Copy, Clone, PartialEq, Deserialize, Serialize, Type)]
|
||||||
pub const BREATHING: u8 = 0x01;
|
pub enum LedBrightness {
|
||||||
pub const STROBE: u8 = 0x02;
|
Off,
|
||||||
pub const RAINBOW: u8 = 0x03;
|
Low,
|
||||||
pub const STAR: u8 = 0x04;
|
Med,
|
||||||
pub const RAIN: u8 = 0x05;
|
High,
|
||||||
pub const HIGHLIGHT: u8 = 0x06;
|
}
|
||||||
pub const LASER: u8 = 0x07;
|
|
||||||
pub const RIPPLE: u8 = 0x08;
|
|
||||||
pub const PULSE: u8 = 0x0a;
|
|
||||||
pub const COMET: u8 = 0x0b;
|
|
||||||
pub const FLASH: u8 = 0x0c;
|
|
||||||
pub const MULTISTATIC: u8 = 0x0d;
|
|
||||||
pub const MULTIBREATHE: u8 = 0x0e;
|
|
||||||
pub const PER_KEY: u8 = 0xff;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
impl LedBrightness {
|
||||||
|
pub fn as_char_code(&self) -> u8 {
|
||||||
|
std::char::from_digit(*self as u32, 10).unwrap() as u8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u32> for LedBrightness {
|
||||||
|
fn from(bright: u32) -> Self {
|
||||||
|
match bright {
|
||||||
|
0 => LedBrightness::Off,
|
||||||
|
1 => LedBrightness::Low,
|
||||||
|
2 => LedBrightness::Med,
|
||||||
|
3 => LedBrightness::High,
|
||||||
|
_ => LedBrightness::Med,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Copy, Deserialize, Serialize, Type)]
|
||||||
pub struct Colour(pub u8, pub u8, pub u8);
|
pub struct Colour(pub u8, pub u8, pub u8);
|
||||||
|
|
||||||
impl Default for Colour {
|
impl Default for Colour {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Colour(128, 0, 0)
|
Colour(166, 0, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,7 +59,7 @@ impl FromStr for Colour {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Deserialize, Serialize)]
|
#[derive(Debug, Copy, Clone, PartialEq, Deserialize, Serialize, Type)]
|
||||||
pub enum Speed {
|
pub enum Speed {
|
||||||
Low = 0xe1,
|
Low = 0xe1,
|
||||||
Med = 0xeb,
|
Med = 0xeb,
|
||||||
@@ -71,7 +87,7 @@ impl FromStr for Speed {
|
|||||||
/// Used for Rainbow mode.
|
/// Used for Rainbow mode.
|
||||||
///
|
///
|
||||||
/// Enum corresponds to the required integer value
|
/// Enum corresponds to the required integer value
|
||||||
#[derive(Debug, Copy, Clone, Deserialize, Serialize)]
|
#[derive(Debug, Copy, Clone, PartialEq, Deserialize, Serialize, Type)]
|
||||||
pub enum Direction {
|
pub enum Direction {
|
||||||
Right,
|
Right,
|
||||||
Left,
|
Left,
|
||||||
@@ -98,213 +114,265 @@ impl FromStr for Direction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Options, Default, Deserialize, Serialize)]
|
/// Writes out the correct byte string for brightness
|
||||||
pub struct SingleSpeed {
|
pub const fn aura_brightness_bytes(brightness: u8) -> [u8; 17] {
|
||||||
#[serde(skip)]
|
[
|
||||||
#[options(help = "print help message")]
|
0x5A, 0xBA, 0xC5, 0xC4, brightness, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
help: bool,
|
]
|
||||||
#[options(no_long, meta = "WORD", help = "set the speed: low, med, high")]
|
|
||||||
pub speed: Speed,
|
|
||||||
}
|
}
|
||||||
#[derive(Debug, Clone, Options, Default, Deserialize, Serialize)]
|
|
||||||
pub struct SingleSpeedDirection {
|
#[derive(
|
||||||
#[serde(skip)]
|
Debug, Type, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Copy, Deserialize, Serialize,
|
||||||
#[options(help = "print help message")]
|
)]
|
||||||
help: bool,
|
pub enum AuraModeNum {
|
||||||
#[options(no_long, meta = "", help = "set the direction: up, down, left, right")]
|
Static = 0,
|
||||||
|
Breathe = 1,
|
||||||
|
Strobe = 2,
|
||||||
|
Rainbow = 3,
|
||||||
|
Star = 4,
|
||||||
|
Rain = 5,
|
||||||
|
Highlight = 6,
|
||||||
|
Laser = 7,
|
||||||
|
Ripple = 8,
|
||||||
|
Pulse = 10,
|
||||||
|
Comet = 11,
|
||||||
|
Flash = 12,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&AuraModeNum> for &str {
|
||||||
|
fn from(mode: &AuraModeNum) -> Self {
|
||||||
|
match mode {
|
||||||
|
AuraModeNum::Static => "Static",
|
||||||
|
AuraModeNum::Breathe => "Breathing",
|
||||||
|
AuraModeNum::Strobe => "Strobing",
|
||||||
|
AuraModeNum::Rainbow => "Rainbow",
|
||||||
|
AuraModeNum::Star => "Stars",
|
||||||
|
AuraModeNum::Rain => "Rain",
|
||||||
|
AuraModeNum::Highlight => "Keypress Highlight",
|
||||||
|
AuraModeNum::Laser => "Keypress Laser",
|
||||||
|
AuraModeNum::Ripple => "Keypress Ripple",
|
||||||
|
AuraModeNum::Pulse => "Pulse",
|
||||||
|
AuraModeNum::Comet => "Comet",
|
||||||
|
AuraModeNum::Flash => "Flash",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<&str> for AuraModeNum {
|
||||||
|
fn from(mode: &str) -> Self {
|
||||||
|
match mode {
|
||||||
|
"Static" => AuraModeNum::Static,
|
||||||
|
"Breathing" => AuraModeNum::Breathe,
|
||||||
|
"Strobing" => AuraModeNum::Strobe,
|
||||||
|
"Rainbow" => AuraModeNum::Rainbow,
|
||||||
|
"Stars" => AuraModeNum::Star,
|
||||||
|
"Rain" => AuraModeNum::Rain,
|
||||||
|
"Keypress Highlight" => AuraModeNum::Highlight,
|
||||||
|
"Keypress Laser" => AuraModeNum::Laser,
|
||||||
|
"Keypress Ripple" => AuraModeNum::Ripple,
|
||||||
|
"Pulse" => AuraModeNum::Pulse,
|
||||||
|
"Comet" => AuraModeNum::Comet,
|
||||||
|
"Flash" => AuraModeNum::Flash,
|
||||||
|
_ => AuraModeNum::Static,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u8> for AuraModeNum {
|
||||||
|
fn from(mode: u8) -> Self {
|
||||||
|
match mode {
|
||||||
|
0 => AuraModeNum::Static,
|
||||||
|
1 => AuraModeNum::Breathe,
|
||||||
|
2 => AuraModeNum::Strobe,
|
||||||
|
3 => AuraModeNum::Rainbow,
|
||||||
|
4 => AuraModeNum::Star,
|
||||||
|
5 => AuraModeNum::Rain,
|
||||||
|
6 => AuraModeNum::Highlight,
|
||||||
|
7 => AuraModeNum::Laser,
|
||||||
|
8 => AuraModeNum::Ripple,
|
||||||
|
10 => AuraModeNum::Pulse,
|
||||||
|
11 => AuraModeNum::Comet,
|
||||||
|
12 => AuraModeNum::Flash,
|
||||||
|
_ => AuraModeNum::Static,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
|
pub struct AuraMultiZone {
|
||||||
|
static_: [AuraEffect; 4],
|
||||||
|
breathe: [AuraEffect; 4],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AuraMultiZone {
|
||||||
|
pub fn set(&mut self, effect: AuraEffect) {
|
||||||
|
if effect.mode == AuraModeNum::Static {
|
||||||
|
match effect.zone {
|
||||||
|
AuraZone::None => {}
|
||||||
|
AuraZone::One => self.static_[0] = effect,
|
||||||
|
AuraZone::Two => self.static_[1] = effect,
|
||||||
|
AuraZone::Three => self.static_[2] = effect,
|
||||||
|
AuraZone::Four => self.static_[3] = effect,
|
||||||
|
}
|
||||||
|
} else if effect.mode == AuraModeNum::Breathe {
|
||||||
|
match effect.zone {
|
||||||
|
AuraZone::None => {}
|
||||||
|
AuraZone::One => self.breathe[0] = effect,
|
||||||
|
AuraZone::Two => self.breathe[1] = effect,
|
||||||
|
AuraZone::Three => self.breathe[2] = effect,
|
||||||
|
AuraZone::Four => self.breathe[3] = effect,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn static_(&self) -> &[AuraEffect; 4] {
|
||||||
|
&self.static_
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn breathe(&self) -> &[AuraEffect; 4] {
|
||||||
|
&self.breathe
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for AuraMultiZone {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
static_: [
|
||||||
|
AuraEffect {
|
||||||
|
mode: AuraModeNum::Static,
|
||||||
|
zone: AuraZone::One,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
AuraEffect {
|
||||||
|
mode: AuraModeNum::Static,
|
||||||
|
zone: AuraZone::Two,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
AuraEffect {
|
||||||
|
mode: AuraModeNum::Static,
|
||||||
|
zone: AuraZone::Three,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
AuraEffect {
|
||||||
|
mode: AuraModeNum::Static,
|
||||||
|
zone: AuraZone::Four,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
],
|
||||||
|
breathe: [
|
||||||
|
AuraEffect {
|
||||||
|
mode: AuraModeNum::Breathe,
|
||||||
|
zone: AuraZone::One,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
AuraEffect {
|
||||||
|
mode: AuraModeNum::Breathe,
|
||||||
|
zone: AuraZone::Two,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
AuraEffect {
|
||||||
|
mode: AuraModeNum::Breathe,
|
||||||
|
zone: AuraZone::Three,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
AuraEffect {
|
||||||
|
mode: AuraModeNum::Breathe,
|
||||||
|
zone: AuraZone::Four,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Base effects have no zoning, while multizone is 1-4
|
||||||
|
#[derive(Debug, Type, Copy, Clone, PartialEq, Deserialize, Serialize)]
|
||||||
|
pub enum AuraZone {
|
||||||
|
None,
|
||||||
|
One,
|
||||||
|
Two,
|
||||||
|
Three,
|
||||||
|
Four,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Default factory modes structure
|
||||||
|
#[derive(Debug, Type, Clone, Deserialize, Serialize)]
|
||||||
|
pub struct AuraEffect {
|
||||||
|
/// The effect type
|
||||||
|
pub mode: AuraModeNum,
|
||||||
|
/// `AuraZone::None` for no zone or zoneless keyboards
|
||||||
|
pub zone: AuraZone,
|
||||||
|
/// Primary colour for all modes
|
||||||
|
pub colour1: Colour,
|
||||||
|
/// Secondary colour in some modes like Breathing or Stars
|
||||||
|
pub colour2: Colour,
|
||||||
|
/// One of three speeds for modes that support speed (most that animate)
|
||||||
|
pub speed: Speed,
|
||||||
|
/// Up, down, left, right. Only Rainbow mode seems to use this
|
||||||
pub direction: Direction,
|
pub direction: Direction,
|
||||||
#[options(no_long, meta = "", help = "set the speed: low, med, high")]
|
|
||||||
pub speed: Speed,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Options, Deserialize, Serialize)]
|
impl AuraEffect {
|
||||||
pub struct SingleColour {
|
pub fn mode(&self) -> &AuraModeNum {
|
||||||
#[serde(skip)]
|
&self.mode
|
||||||
#[options(help = "print help message")]
|
}
|
||||||
help: bool,
|
|
||||||
#[options(no_long, meta = "", help = "set the RGB value e.g, ff00ff")]
|
pub fn mode_name(&self) -> String {
|
||||||
pub colour: Colour,
|
(<&str>::from(&self.mode)).to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mode_num(&self) -> u8 {
|
||||||
|
self.mode as u8
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn default_with_mode(mode: AuraModeNum) -> Self {
|
||||||
|
Self {
|
||||||
|
mode,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn zone(&self) -> AuraZone {
|
||||||
|
self.zone
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Options, Deserialize, Serialize)]
|
impl Default for AuraEffect {
|
||||||
pub struct SingleColourSpeed {
|
fn default() -> Self {
|
||||||
#[serde(skip)]
|
Self {
|
||||||
#[options(help = "print help message")]
|
mode: AuraModeNum::Static,
|
||||||
help: bool,
|
zone: AuraZone::None,
|
||||||
#[options(no_long, meta = "", help = "set the RGB value e.g, ff00ff")]
|
colour1: Colour(166, 0, 0),
|
||||||
pub colour: Colour,
|
colour2: Colour(0, 0, 0),
|
||||||
#[options(no_long, meta = "", help = "set the speed: low, med, high")]
|
speed: Speed::Med,
|
||||||
pub speed: Speed,
|
direction: Direction::Right,
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Options, Default, Deserialize, Serialize)]
|
|
||||||
pub struct TwoColourSpeed {
|
|
||||||
#[serde(skip)]
|
|
||||||
#[options(help = "print help message")]
|
|
||||||
help: bool,
|
|
||||||
#[options(no_long, meta = "", help = "set the first RGB value e.g, ff00ff")]
|
|
||||||
pub colour: Colour,
|
|
||||||
#[options(no_long, meta = "", help = "set the second RGB value e.g, ff00ff")]
|
|
||||||
pub colour2: Colour,
|
|
||||||
#[options(no_long, meta = "", help = "set the speed: low, med, high")]
|
|
||||||
pub speed: Speed,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Options, Deserialize, Serialize)]
|
|
||||||
pub struct MultiColour {
|
|
||||||
#[serde(skip)]
|
|
||||||
#[options(help = "print help message")]
|
|
||||||
help: bool,
|
|
||||||
#[options(short = "a", meta = "", help = "set the RGB value e.g, ff00ff")]
|
|
||||||
pub colour1: Colour,
|
|
||||||
#[options(short = "b", meta = "", help = "set the RGB value e.g, ff00ff")]
|
|
||||||
pub colour2: Colour,
|
|
||||||
#[options(short = "c", meta = "", help = "set the RGB value e.g, ff00ff")]
|
|
||||||
pub colour3: Colour,
|
|
||||||
#[options(short = "d", meta = "", help = "set the RGB value e.g, ff00ff")]
|
|
||||||
pub colour4: Colour,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Options, Deserialize, Serialize)]
|
|
||||||
pub struct MultiColourSpeed {
|
|
||||||
#[options(help = "print help message")]
|
|
||||||
help: bool,
|
|
||||||
#[options(short = "a", meta = "", help = "set the RGB value e.g, ff00ff")]
|
|
||||||
pub colour1: Colour,
|
|
||||||
#[options(short = "b", meta = "", help = "set the RGB value e.g, ff00ff")]
|
|
||||||
pub colour2: Colour,
|
|
||||||
#[options(short = "c", meta = "", help = "set the RGB value e.g, ff00ff")]
|
|
||||||
pub colour3: Colour,
|
|
||||||
#[options(short = "d", meta = "", help = "set the RGB value e.g, ff00ff")]
|
|
||||||
pub colour4: Colour,
|
|
||||||
#[options(no_long, meta = "", help = "set the speed: low, med, high")]
|
|
||||||
pub speed: Speed,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
|
||||||
pub enum AuraModes {
|
|
||||||
Static(SingleColour),
|
|
||||||
Breathe(TwoColourSpeed),
|
|
||||||
Strobe(SingleSpeed),
|
|
||||||
Rainbow(SingleSpeedDirection),
|
|
||||||
Star(TwoColourSpeed),
|
|
||||||
Rain(SingleSpeed),
|
|
||||||
Highlight(SingleColourSpeed),
|
|
||||||
Laser(SingleColourSpeed),
|
|
||||||
Ripple(SingleColourSpeed),
|
|
||||||
Pulse(SingleColour),
|
|
||||||
Comet(SingleColour),
|
|
||||||
Flash(SingleColour),
|
|
||||||
MultiStatic(MultiColour),
|
|
||||||
MultiBreathe(MultiColourSpeed),
|
|
||||||
LedBrightness(u8),
|
|
||||||
// TODO: use a serializable structure for this (KeyColourArray)
|
|
||||||
PerKey(Vec<Vec<u8>>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<SetAuraBuiltin> for AuraModes {
|
|
||||||
fn from(mode: SetAuraBuiltin) -> Self {
|
|
||||||
match mode {
|
|
||||||
SetAuraBuiltin::Static(x) => AuraModes::Static(x),
|
|
||||||
SetAuraBuiltin::Breathe(x) => AuraModes::Breathe(x),
|
|
||||||
SetAuraBuiltin::Strobe(x) => AuraModes::Strobe(x),
|
|
||||||
SetAuraBuiltin::Rainbow(x) => AuraModes::Rainbow(x),
|
|
||||||
SetAuraBuiltin::Star(x) => AuraModes::Star(x),
|
|
||||||
SetAuraBuiltin::Rain(x) => AuraModes::Rain(x),
|
|
||||||
SetAuraBuiltin::Highlight(x) => AuraModes::Highlight(x),
|
|
||||||
SetAuraBuiltin::Laser(x) => AuraModes::Laser(x),
|
|
||||||
SetAuraBuiltin::Ripple(x) => AuraModes::Ripple(x),
|
|
||||||
SetAuraBuiltin::Pulse(x) => AuraModes::Pulse(x),
|
|
||||||
SetAuraBuiltin::Comet(x) => AuraModes::Comet(x),
|
|
||||||
SetAuraBuiltin::Flash(x) => AuraModes::Flash(x),
|
|
||||||
SetAuraBuiltin::MultiStatic(x) => AuraModes::MultiStatic(x),
|
|
||||||
SetAuraBuiltin::MultiBreathe(x) => AuraModes::MultiBreathe(x),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Very specific mode conversion required because numbering isn't linear
|
/// Parses `AuraEffect` in to packet data for writing to the USB interface
|
||||||
impl From<AuraModes> for u8 {
|
///
|
||||||
fn from(mode: AuraModes) -> Self {
|
/// Byte structure:
|
||||||
u8::from(&mode)
|
/// ```ignore
|
||||||
}
|
/// | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10| 11| 12|
|
||||||
}
|
/// |---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||||
|
/// |5d |b3 |00 |03 |ff |00 |00 |00 |00 |00 |00 |ff |00 |
|
||||||
|
/// ```
|
||||||
|
impl From<&AuraEffect> for [u8; LED_MSG_LEN] {
|
||||||
|
fn from(aura: &AuraEffect) -> Self {
|
||||||
|
let mut msg = [0u8; LED_MSG_LEN];
|
||||||
|
msg[0] = 0x5d;
|
||||||
|
msg[1] = 0xb3;
|
||||||
|
msg[2] = aura.zone as u8;
|
||||||
|
msg[3] = aura.mode as u8;
|
||||||
|
msg[4] = aura.colour1.0;
|
||||||
|
msg[5] = aura.colour1.1;
|
||||||
|
msg[6] = aura.colour1.2;
|
||||||
|
msg[7] = aura.speed as u8;
|
||||||
|
msg[8] = aura.direction as u8;
|
||||||
|
msg[10] = aura.colour2.0;
|
||||||
|
msg[11] = aura.colour2.1;
|
||||||
|
msg[12] = aura.colour2.2;
|
||||||
|
|
||||||
/// Very specific mode conversion required because numbering isn't linear
|
msg
|
||||||
impl From<&mut AuraModes> for u8 {
|
|
||||||
fn from(mode: &mut AuraModes) -> Self {
|
|
||||||
u8::from(&*mode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Very specific mode conversion required because numbering isn't linear
|
|
||||||
impl From<&AuraModes> for u8 {
|
|
||||||
fn from(mode: &AuraModes) -> Self {
|
|
||||||
match mode {
|
|
||||||
AuraModes::Static(_) => STATIC,
|
|
||||||
AuraModes::Breathe(_) => BREATHING,
|
|
||||||
AuraModes::Strobe(_) => STROBE,
|
|
||||||
AuraModes::Rainbow(_) => RAINBOW,
|
|
||||||
AuraModes::Star(_) => STAR,
|
|
||||||
AuraModes::Rain(_) => RAIN,
|
|
||||||
AuraModes::Highlight(_) => HIGHLIGHT,
|
|
||||||
AuraModes::Laser(_) => LASER,
|
|
||||||
AuraModes::Ripple(_) => RIPPLE,
|
|
||||||
AuraModes::Pulse(_) => PULSE,
|
|
||||||
AuraModes::Comet(_) => COMET,
|
|
||||||
AuraModes::Flash(_) => FLASH,
|
|
||||||
AuraModes::MultiStatic(_) => MULTISTATIC,
|
|
||||||
AuraModes::MultiBreathe(_) => MULTIBREATHE,
|
|
||||||
AuraModes::PerKey(_) => PER_KEY,
|
|
||||||
_ => panic!("Invalid mode"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&AuraModes> for &str {
|
|
||||||
fn from(mode: &AuraModes) -> Self {
|
|
||||||
match mode {
|
|
||||||
AuraModes::Static(_) => "Static",
|
|
||||||
AuraModes::Breathe(_) => "Breathing",
|
|
||||||
AuraModes::Strobe(_) => "Strobing",
|
|
||||||
AuraModes::Rainbow(_) => "Rainbow",
|
|
||||||
AuraModes::Star(_) => "Stars",
|
|
||||||
AuraModes::Rain(_) => "Rain",
|
|
||||||
AuraModes::Highlight(_) => "Keypress Highlight",
|
|
||||||
AuraModes::Laser(_) => "Keypress Laser",
|
|
||||||
AuraModes::Ripple(_) => "Keypress Ripple",
|
|
||||||
AuraModes::Pulse(_) => "Pulse",
|
|
||||||
AuraModes::Comet(_) => "Comet",
|
|
||||||
AuraModes::Flash(_) => "Flash",
|
|
||||||
AuraModes::MultiStatic(_) => "4-Zone Static Colours",
|
|
||||||
AuraModes::MultiBreathe(_) => "4-Zone Breathing Colours",
|
|
||||||
AuraModes::PerKey(_) => "RGB per-key",
|
|
||||||
_ => panic!("Invalid mode"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Exists to convert back from correct bytes. PER_KEY byte intentionally left off as it
|
|
||||||
/// does not correspond to an actual pre-set mode, nor does brightness.
|
|
||||||
impl From<u8> for AuraModes {
|
|
||||||
fn from(byte: u8) -> Self {
|
|
||||||
match byte {
|
|
||||||
STATIC => AuraModes::Static(SingleColour::default()),
|
|
||||||
BREATHING => AuraModes::Breathe(TwoColourSpeed::default()),
|
|
||||||
STROBE => AuraModes::Strobe(SingleSpeed::default()),
|
|
||||||
RAINBOW => AuraModes::Rainbow(SingleSpeedDirection::default()),
|
|
||||||
STAR => AuraModes::Star(TwoColourSpeed::default()),
|
|
||||||
RAIN => AuraModes::Rain(SingleSpeed::default()),
|
|
||||||
HIGHLIGHT => AuraModes::Highlight(SingleColourSpeed::default()),
|
|
||||||
LASER => AuraModes::Laser(SingleColourSpeed::default()),
|
|
||||||
RIPPLE => AuraModes::Ripple(SingleColourSpeed::default()),
|
|
||||||
PULSE => AuraModes::Pulse(SingleColour::default()),
|
|
||||||
COMET => AuraModes::Comet(SingleColour::default()),
|
|
||||||
FLASH => AuraModes::Flash(SingleColour::default()),
|
|
||||||
MULTISTATIC => AuraModes::MultiStatic(MultiColour::default()),
|
|
||||||
MULTIBREATHE => AuraModes::MultiBreathe(MultiColourSpeed::default()),
|
|
||||||
PER_KEY => AuraModes::PerKey(vec![]),
|
|
||||||
_ => panic!("Invalid mode byte"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ impl KeyColourArray {
|
|||||||
|
|
||||||
/// Initialise and clear the keyboard for custom effects
|
/// Initialise and clear the keyboard for custom effects
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_init_msg() -> Vec<u8> {
|
pub const fn get_init_msg() -> [u8; 64] {
|
||||||
let mut init = vec![0u8; 64];
|
let mut init = [0u8; 64];
|
||||||
init[0] = 0x5d; // Report ID
|
init[0] = 0x5d; // Report ID
|
||||||
init[1] = 0xbc; // Mode = custom??, 0xb3 is builtin
|
init[1] = 0xbc; // Mode = custom??, 0xb3 is builtin
|
||||||
init
|
init
|
||||||
@@ -1,97 +1,7 @@
|
|||||||
use crate::{
|
use crate::error::AuraError;
|
||||||
aura_modes::{
|
|
||||||
MultiColour, MultiColourSpeed, SingleColour, SingleColourSpeed, SingleSpeed,
|
|
||||||
SingleSpeedDirection, TwoColourSpeed,
|
|
||||||
},
|
|
||||||
error::AuraError,
|
|
||||||
};
|
|
||||||
use gumdrop::Options;
|
use gumdrop::Options;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
#[derive(Options)]
|
|
||||||
pub struct LedBrightness {
|
|
||||||
level: Option<u8>,
|
|
||||||
}
|
|
||||||
impl LedBrightness {
|
|
||||||
pub fn new(level: Option<u8>) -> Self {
|
|
||||||
LedBrightness { level }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn level(&self) -> Option<u8> {
|
|
||||||
self.level
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl FromStr for LedBrightness {
|
|
||||||
type Err = AuraError;
|
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
let s = s.to_lowercase();
|
|
||||||
match s.as_str() {
|
|
||||||
"off" => Ok(LedBrightness { level: Some(0x00) }),
|
|
||||||
"low" => Ok(LedBrightness { level: Some(0x01) }),
|
|
||||||
"med" => Ok(LedBrightness { level: Some(0x02) }),
|
|
||||||
"high" => Ok(LedBrightness { level: Some(0x03) }),
|
|
||||||
_ => {
|
|
||||||
print!("Invalid argument, must be one of: off, low, med, high");
|
|
||||||
Err(AuraError::ParseBrightness)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl ToString for LedBrightness {
|
|
||||||
fn to_string(&self) -> String {
|
|
||||||
let s = match self.level {
|
|
||||||
Some(0x00) => "low",
|
|
||||||
Some(0x01) => "med",
|
|
||||||
Some(0x02) => "high",
|
|
||||||
_ => "unknown",
|
|
||||||
};
|
|
||||||
s.to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Byte value for setting the built-in mode.
|
|
||||||
///
|
|
||||||
/// Enum corresponds to the required integer value
|
|
||||||
#[derive(Options, Deserialize, Serialize)]
|
|
||||||
pub enum SetAuraBuiltin {
|
|
||||||
#[options(help = "set a single static colour")]
|
|
||||||
Static(SingleColour),
|
|
||||||
#[options(help = "pulse between one or two colours")]
|
|
||||||
Breathe(TwoColourSpeed),
|
|
||||||
#[options(help = "strobe through all colours")]
|
|
||||||
Strobe(SingleSpeed),
|
|
||||||
#[options(help = "rainbow cycling in one of four directions")]
|
|
||||||
Rainbow(SingleSpeedDirection),
|
|
||||||
#[options(help = "rain pattern mimicking raindrops")]
|
|
||||||
Star(TwoColourSpeed),
|
|
||||||
#[options(help = "rain pattern of three preset colours")]
|
|
||||||
Rain(SingleSpeed),
|
|
||||||
#[options(help = "pressed keys are highlighted to fade")]
|
|
||||||
Highlight(SingleColourSpeed),
|
|
||||||
#[options(help = "pressed keys generate horizontal laser")]
|
|
||||||
Laser(SingleColourSpeed),
|
|
||||||
#[options(help = "pressed keys ripple outwards like a splash")]
|
|
||||||
Ripple(SingleColourSpeed),
|
|
||||||
#[options(help = "set a rapid pulse")]
|
|
||||||
Pulse(SingleColour),
|
|
||||||
#[options(help = "set a vertical line zooming from left")]
|
|
||||||
Comet(SingleColour),
|
|
||||||
#[options(help = "set a wide vertical line zooming from left")]
|
|
||||||
Flash(SingleColour),
|
|
||||||
#[options(help = "4-zone multi-colour")]
|
|
||||||
MultiStatic(MultiColour),
|
|
||||||
#[options(help = "4-zone multi-colour breathing")]
|
|
||||||
MultiBreathe(MultiColourSpeed),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for SetAuraBuiltin {
|
|
||||||
fn default() -> Self {
|
|
||||||
SetAuraBuiltin::Static(SingleColour::default())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub enum AniMeStatusValue {
|
pub enum AniMeStatusValue {
|
||||||
On,
|
On,
|
||||||
|
|||||||
@@ -1,15 +1,17 @@
|
|||||||
#[derive(Debug, PartialEq, Clone)]
|
use crate::error::GraphicsError;
|
||||||
|
use serde_derive::{Deserialize, Serialize};
|
||||||
|
use std::str::FromStr;
|
||||||
|
use zvariant_derive::Type;
|
||||||
|
|
||||||
|
#[derive(Debug, Type, PartialEq, Copy, Clone, Deserialize, Serialize)]
|
||||||
pub enum GfxVendors {
|
pub enum GfxVendors {
|
||||||
Nvidia,
|
Nvidia,
|
||||||
Integrated,
|
Integrated,
|
||||||
Compute,
|
Compute,
|
||||||
|
Vfio,
|
||||||
Hybrid,
|
Hybrid,
|
||||||
}
|
}
|
||||||
|
|
||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
use crate::error::GraphicsError;
|
|
||||||
|
|
||||||
impl FromStr for GfxVendors {
|
impl FromStr for GfxVendors {
|
||||||
type Err = GraphicsError;
|
type Err = GraphicsError;
|
||||||
|
|
||||||
@@ -18,10 +20,12 @@ impl FromStr for GfxVendors {
|
|||||||
"nvidia" => Ok(GfxVendors::Nvidia),
|
"nvidia" => Ok(GfxVendors::Nvidia),
|
||||||
"hybrid" => Ok(GfxVendors::Hybrid),
|
"hybrid" => Ok(GfxVendors::Hybrid),
|
||||||
"compute" => Ok(GfxVendors::Compute),
|
"compute" => Ok(GfxVendors::Compute),
|
||||||
|
"vfio" => Ok(GfxVendors::Vfio),
|
||||||
"integrated" => Ok(GfxVendors::Integrated),
|
"integrated" => Ok(GfxVendors::Integrated),
|
||||||
"nvidia\n" => Ok(GfxVendors::Nvidia),
|
"nvidia\n" => Ok(GfxVendors::Nvidia),
|
||||||
"hybrid\n" => Ok(GfxVendors::Hybrid),
|
"hybrid\n" => Ok(GfxVendors::Hybrid),
|
||||||
"compute\n" => Ok(GfxVendors::Compute),
|
"compute\n" => Ok(GfxVendors::Compute),
|
||||||
|
"vfio\n" => Ok(GfxVendors::Vfio),
|
||||||
"integrated\n" => Ok(GfxVendors::Integrated),
|
"integrated\n" => Ok(GfxVendors::Integrated),
|
||||||
_ => Err(GraphicsError::ParseVendor),
|
_ => Err(GraphicsError::ParseVendor),
|
||||||
}
|
}
|
||||||
@@ -29,58 +33,36 @@ impl FromStr for GfxVendors {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl From<&GfxVendors> for &str {
|
impl From<&GfxVendors> for &str {
|
||||||
fn from(mode: &GfxVendors) -> Self {
|
fn from(gfx: &GfxVendors) -> &'static str {
|
||||||
match mode {
|
match gfx {
|
||||||
GfxVendors::Nvidia => "nvidia",
|
GfxVendors::Nvidia => "nvidia",
|
||||||
GfxVendors::Hybrid => "hybrid",
|
GfxVendors::Hybrid => "hybrid",
|
||||||
GfxVendors::Compute => "compute",
|
GfxVendors::Compute => "compute",
|
||||||
|
GfxVendors::Vfio => "vfio",
|
||||||
GfxVendors::Integrated => "integrated",
|
GfxVendors::Integrated => "integrated",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
impl From<GfxVendors> for &str {
|
||||||
pub enum GfxCtrlAction {
|
fn from(gfx: GfxVendors) -> &'static str {
|
||||||
|
(&gfx).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Type, PartialEq, Copy, Clone, Deserialize, Serialize)]
|
||||||
|
pub enum GfxRequiredUserAction {
|
||||||
|
Logout,
|
||||||
Reboot,
|
Reboot,
|
||||||
RestartX,
|
|
||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for GfxCtrlAction {
|
impl From<&GfxRequiredUserAction> for &str {
|
||||||
type Err = GraphicsError;
|
fn from(gfx: &GfxRequiredUserAction) -> &'static str {
|
||||||
|
match gfx {
|
||||||
fn from_str(s: &str) -> Result<Self, GraphicsError> {
|
GfxRequiredUserAction::Logout => "logout",
|
||||||
match s.to_lowercase().as_str() {
|
GfxRequiredUserAction::Reboot => "reboot",
|
||||||
"reboot" => Ok(GfxCtrlAction::Reboot),
|
GfxRequiredUserAction::None => "no action",
|
||||||
"restartx" => Ok(GfxCtrlAction::RestartX),
|
|
||||||
"none" => Ok(GfxCtrlAction::None),
|
|
||||||
_ => Err(GraphicsError::ParseVendor),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&GfxCtrlAction> for &str {
|
|
||||||
fn from(mode: &GfxCtrlAction) -> Self {
|
|
||||||
match mode {
|
|
||||||
GfxCtrlAction::Reboot => "reboot",
|
|
||||||
GfxCtrlAction::RestartX => "restartx",
|
|
||||||
GfxCtrlAction::None => "none",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&GfxCtrlAction> for String {
|
|
||||||
fn from(mode: &GfxCtrlAction) -> Self {
|
|
||||||
match mode {
|
|
||||||
GfxCtrlAction::Reboot => "reboot".into(),
|
|
||||||
GfxCtrlAction::RestartX => "restartx".into(),
|
|
||||||
GfxCtrlAction::None => "none".into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<GfxCtrlAction> for String {
|
|
||||||
fn from(mode: GfxCtrlAction) -> Self {
|
|
||||||
(&mode).into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+5
-261
@@ -1,10 +1,13 @@
|
|||||||
|
//! This crate is intended for shared types (eg, between daemon and CLI), or
|
||||||
|
//! for types that might be useful in third-party crates perhaps for
|
||||||
|
//! sending messages over dbus wire
|
||||||
|
|
||||||
pub static DBUS_NAME: &str = "org.asuslinux.Daemon";
|
pub static DBUS_NAME: &str = "org.asuslinux.Daemon";
|
||||||
pub static DBUS_PATH: &str = "/org/asuslinux/Daemon";
|
pub static DBUS_PATH: &str = "/org/asuslinux/Daemon";
|
||||||
pub static DBUS_IFACE: &str = "org.asuslinux.Daemon";
|
pub static DBUS_IFACE: &str = "org.asuslinux.Daemon";
|
||||||
pub const LED_MSG_LEN: usize = 17;
|
pub const LED_MSG_LEN: usize = 17;
|
||||||
|
|
||||||
pub mod aura_modes;
|
pub mod aura_modes;
|
||||||
use aura_modes::AuraModes;
|
|
||||||
|
|
||||||
pub mod profile;
|
pub mod profile;
|
||||||
|
|
||||||
@@ -12,7 +15,7 @@ pub mod profile;
|
|||||||
pub mod cli_options;
|
pub mod cli_options;
|
||||||
|
|
||||||
/// Enables you to create fancy RGB effects
|
/// Enables you to create fancy RGB effects
|
||||||
pub mod fancy;
|
pub mod aura_perkey;
|
||||||
|
|
||||||
/// Helper functions for the AniMe display
|
/// Helper functions for the AniMe display
|
||||||
pub mod anime_matrix;
|
pub mod anime_matrix;
|
||||||
@@ -22,262 +25,3 @@ pub mod gfx_vendors;
|
|||||||
pub mod error;
|
pub mod error;
|
||||||
|
|
||||||
pub static VERSION: &str = env!("CARGO_PKG_VERSION");
|
pub static VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
|
|
||||||
// static LED_INIT1: [u8; 2] = [0x5d, 0xb9];
|
|
||||||
// static LED_INIT2: &str = "]ASUS Tech.Inc."; // ] == 0x5d
|
|
||||||
// static LED_INIT3: [u8; 6] = [0x5d, 0x05, 0x20, 0x31, 0, 0x08];
|
|
||||||
// static LED_INIT4: &str = "^ASUS Tech.Inc."; // ^ == 0x5e
|
|
||||||
// static LED_INIT5: [u8; 6] = [0x5e, 0x05, 0x20, 0x31, 0, 0x08];
|
|
||||||
|
|
||||||
/// Writes aout the correct byte string for brightness
|
|
||||||
///
|
|
||||||
/// The HID descriptor looks like:
|
|
||||||
///
|
|
||||||
/// ```ignore
|
|
||||||
/// 0x06, 0x31, 0xFF, // Usage Page (Vendor Defined 0xFF31)
|
|
||||||
/// 0x09, 0x76, // Usage (0x76)
|
|
||||||
/// 0xA1, 0x01, // Collection (Application)
|
|
||||||
/// 0x85, 0x5A, // Report ID (90)
|
|
||||||
/// 0x19, 0x00, // Usage Minimum (0x00)
|
|
||||||
/// 0x2A, 0xFF, 0x00, // Usage Maximum (0xFF)
|
|
||||||
/// 0x15, 0x00, // Logical Minimum (0)
|
|
||||||
/// 0x26, 0xFF, 0x00, // Logical Maximum (255)
|
|
||||||
/// 0x75, 0x08, // Report Size (8)
|
|
||||||
/// 0x95, 0x05, // Report Count (5)
|
|
||||||
/// 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
|
||||||
/// 0x19, 0x00, // Usage Minimum (0x00)
|
|
||||||
/// 0x2A, 0xFF, 0x00, // Usage Maximum (0xFF)
|
|
||||||
/// 0x15, 0x00, // Logical Minimum (0)
|
|
||||||
/// 0x26, 0xFF, 0x00, // Logical Maximum (255)
|
|
||||||
/// 0x75, 0x08, // Report Size (8)
|
|
||||||
/// 0x95, 0x3F, // Report Count (63)
|
|
||||||
/// 0xB1, 0x00, // Feature (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
|
||||||
/// 0xC0, // End Collection
|
|
||||||
/// ```
|
|
||||||
pub fn aura_brightness_bytes(brightness: u8) -> [u8; 17] {
|
|
||||||
// TODO: check brightness range
|
|
||||||
[
|
|
||||||
0x5A, 0xBA, 0xC5, 0xC4, brightness, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parses `AuraCommands` in to packet data
|
|
||||||
///
|
|
||||||
/// Byte structure:
|
|
||||||
///
|
|
||||||
/// ```ignore
|
|
||||||
/// | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10| 11| 12|
|
|
||||||
/// |---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
||||||
/// |5d |b3 |00 |03 |ff |00 |00 |00 |00 |00 |00 |ff |00 |
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// Bytes 0 and 1 should always be 5d, b3
|
|
||||||
///
|
|
||||||
/// On multizone laptops byte 2 is the zone number, RGB in usual
|
|
||||||
/// place, byte 3 set to zero
|
|
||||||
///
|
|
||||||
/// Byte 3 sets the mode type:
|
|
||||||
/// - 00 = static
|
|
||||||
/// - 01 = breathe (can set two colours)
|
|
||||||
/// - 02 = strobe (through all colours)
|
|
||||||
/// - 03 = rainbow
|
|
||||||
/// - 04 = star (byte 9 sets rain colour)
|
|
||||||
/// - 05 = rain keys, red, white, turquoise
|
|
||||||
/// - 06 = pressed keys light up and fade
|
|
||||||
/// - 07 = pressed key emits laser
|
|
||||||
/// - 08 = pressed key emits water ripple
|
|
||||||
/// - 09 = no effect/not used
|
|
||||||
/// - 0a fast pulse (no speed setting)
|
|
||||||
/// - 0b vertical line racing to right (no speed setting)
|
|
||||||
/// - 0c wider vertical line racing to right (no speed setting)
|
|
||||||
///
|
|
||||||
/// Bytes 4, 5, 6 are Red, Green, Blue
|
|
||||||
///
|
|
||||||
/// Byte 7 sets speed from
|
|
||||||
/// - 0x00 = Off
|
|
||||||
/// - 0xe1 = Slow
|
|
||||||
/// - 0xeb = Medium
|
|
||||||
/// - 0xf5 = Fast
|
|
||||||
///
|
|
||||||
/// Byte 8 sets rainbow direction:
|
|
||||||
/// - 0x00 = rightwards
|
|
||||||
/// - 0x01 = leftwards
|
|
||||||
/// - 0x02 = upwards
|
|
||||||
/// - 0x03 = downwards
|
|
||||||
///
|
|
||||||
/// Bytes 10, 11, 12 are Red, Green, Blue for second colour if mode supports it
|
|
||||||
///
|
|
||||||
/// The HID descriptor looks like:
|
|
||||||
/// ```ignore
|
|
||||||
/// 0x06, 0x31, 0xFF, // Usage Page (Vendor Defined 0xFF31)
|
|
||||||
/// 0x09, 0x79, // Usage (0x79)
|
|
||||||
/// 0xA1, 0x01, // Collection (Application)
|
|
||||||
/// 0x85, 0x5D, // Report ID (93)
|
|
||||||
/// 0x19, 0x00, // Usage Minimum (0x00)
|
|
||||||
/// 0x2A, 0xFF, 0x00, // Usage Maximum (0xFF)
|
|
||||||
/// 0x15, 0x00, // Logical Minimum (0)
|
|
||||||
/// 0x26, 0xFF, 0x00, // Logical Maximum (255)
|
|
||||||
/// 0x75, 0x08, // Report Size (8)
|
|
||||||
/// 0x95, 0x1F, // Report Count (31)
|
|
||||||
/// 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
|
||||||
/// 0x19, 0x00, // Usage Minimum (0x00)
|
|
||||||
/// 0x2A, 0xFF, 0x00, // Usage Maximum (0xFF)
|
|
||||||
/// 0x15, 0x00, // Logical Minimum (0)
|
|
||||||
/// 0x26, 0xFF, 0x00, // Logical Maximum (255)
|
|
||||||
/// 0x75, 0x08, // Report Size (8)
|
|
||||||
/// 0x95, 0x3F, // Report Count (63)
|
|
||||||
/// 0x91, 0x00, // Output (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
|
||||||
/// 0x19, 0x00, // Usage Minimum (0x00)
|
|
||||||
/// 0x2A, 0xFF, 0x00, // Usage Maximum (0xFF)
|
|
||||||
/// 0x15, 0x00, // Logical Minimum (0)
|
|
||||||
/// 0x26, 0xFF, 0x00, // Logical Maximum (255)
|
|
||||||
/// 0x75, 0x08, // Report Size (8)
|
|
||||||
/// 0x95, 0x3F, // Report Count (63)
|
|
||||||
/// 0xB1, 0x00, // Feature (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
|
||||||
/// 0xC0, // End Collection
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// This descriptor is also used for the per-key LED settings
|
|
||||||
impl From<&AuraModes> for [u8; LED_MSG_LEN] {
|
|
||||||
fn from(mode: &AuraModes) -> Self {
|
|
||||||
let mut msg = [0u8; LED_MSG_LEN];
|
|
||||||
msg[0] = 0x5d;
|
|
||||||
msg[1] = 0xb3;
|
|
||||||
msg[7] = 0xeb;
|
|
||||||
match mode {
|
|
||||||
AuraModes::LedBrightness(n) => return aura_brightness_bytes(*n),
|
|
||||||
AuraModes::Static(_) => msg[3] = 0x00,
|
|
||||||
AuraModes::Breathe(_) => msg[3] = 0x01,
|
|
||||||
AuraModes::Strobe(_) => msg[3] = 0x02,
|
|
||||||
AuraModes::Rainbow(_) => msg[3] = 0x03,
|
|
||||||
AuraModes::Star(_) => msg[3] = 0x04,
|
|
||||||
AuraModes::Rain(_) => msg[3] = 0x05,
|
|
||||||
AuraModes::Highlight(_) => msg[3] = 0x06,
|
|
||||||
AuraModes::Laser(_) => msg[3] = 0x07,
|
|
||||||
AuraModes::Ripple(_) => msg[3] = 0x08,
|
|
||||||
AuraModes::Pulse(_) => msg[3] = 0x0a,
|
|
||||||
AuraModes::Comet(_) => msg[3] = 0x0b,
|
|
||||||
AuraModes::Flash(_) => msg[3] = 0x0c,
|
|
||||||
_ => panic!("Mode not convertable to 1D array: {}", <&str>::from(mode)),
|
|
||||||
}
|
|
||||||
|
|
||||||
match mode {
|
|
||||||
AuraModes::Rainbow(settings) => {
|
|
||||||
msg[7] = settings.speed as u8;
|
|
||||||
msg[8] = settings.direction as u8;
|
|
||||||
}
|
|
||||||
AuraModes::Star(settings) => {
|
|
||||||
msg[4] = settings.colour.0;
|
|
||||||
msg[5] = settings.colour.1;
|
|
||||||
msg[6] = settings.colour.2;
|
|
||||||
msg[7] = settings.speed as u8;
|
|
||||||
msg[9] = settings.colour2.2;
|
|
||||||
}
|
|
||||||
AuraModes::Breathe(settings) => {
|
|
||||||
msg[4] = settings.colour.0;
|
|
||||||
msg[5] = settings.colour.1;
|
|
||||||
msg[6] = settings.colour.2;
|
|
||||||
msg[7] = settings.speed as u8;
|
|
||||||
msg[10] = settings.colour2.0;
|
|
||||||
msg[11] = settings.colour2.1;
|
|
||||||
msg[12] = settings.colour2.2;
|
|
||||||
}
|
|
||||||
AuraModes::Strobe(settings) | AuraModes::Rain(settings) => {
|
|
||||||
msg[7] = settings.speed as u8;
|
|
||||||
}
|
|
||||||
AuraModes::Highlight(settings)
|
|
||||||
| AuraModes::Laser(settings)
|
|
||||||
| AuraModes::Ripple(settings) => {
|
|
||||||
msg[4] = settings.colour.0;
|
|
||||||
msg[5] = settings.colour.1;
|
|
||||||
msg[6] = settings.colour.2;
|
|
||||||
msg[7] = settings.speed as u8;
|
|
||||||
}
|
|
||||||
AuraModes::Static(settings)
|
|
||||||
| AuraModes::Pulse(settings)
|
|
||||||
| AuraModes::Comet(settings)
|
|
||||||
| AuraModes::Flash(settings) => {
|
|
||||||
msg[4] = settings.colour.0;
|
|
||||||
msg[5] = settings.colour.1;
|
|
||||||
msg[6] = settings.colour.2;
|
|
||||||
}
|
|
||||||
_ => panic!("Mode not convertable to 1D array: {}", <&str>::from(mode)),
|
|
||||||
}
|
|
||||||
msg
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<AuraModes> for [u8; LED_MSG_LEN] {
|
|
||||||
#[inline]
|
|
||||||
fn from(mode: AuraModes) -> Self {
|
|
||||||
<[u8; LED_MSG_LEN]>::from(&mode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<AuraModes> for [[u8; LED_MSG_LEN]; 4] {
|
|
||||||
#[inline]
|
|
||||||
fn from(mode: AuraModes) -> Self {
|
|
||||||
<[[u8; LED_MSG_LEN]; 4]>::from(&mode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&AuraModes> for [[u8; LED_MSG_LEN]; 4] {
|
|
||||||
#[inline]
|
|
||||||
fn from(mode: &AuraModes) -> Self {
|
|
||||||
let mut msg = [[0u8; LED_MSG_LEN]; 4];
|
|
||||||
match mode {
|
|
||||||
AuraModes::MultiStatic(settings) => {
|
|
||||||
for (i, row) in msg.iter_mut().enumerate() {
|
|
||||||
row[0] = 0x5d;
|
|
||||||
row[1] = 0xb3;
|
|
||||||
row[2] = i as u8 + 1; // zone
|
|
||||||
row[3] = 0x00; // mode
|
|
||||||
row[7] = 0xeb; // static needs speed?
|
|
||||||
}
|
|
||||||
msg[0][4] = settings.colour1.0;
|
|
||||||
msg[0][5] = settings.colour1.1;
|
|
||||||
msg[0][6] = settings.colour1.2;
|
|
||||||
msg[1][4] = settings.colour2.0;
|
|
||||||
msg[1][5] = settings.colour2.1;
|
|
||||||
msg[1][6] = settings.colour2.2;
|
|
||||||
msg[2][4] = settings.colour3.0;
|
|
||||||
msg[2][5] = settings.colour3.1;
|
|
||||||
msg[2][6] = settings.colour3.2;
|
|
||||||
msg[3][4] = settings.colour4.0;
|
|
||||||
msg[3][5] = settings.colour4.1;
|
|
||||||
msg[3][6] = settings.colour4.2;
|
|
||||||
}
|
|
||||||
AuraModes::MultiBreathe(settings) => {
|
|
||||||
for (i, row) in msg.iter_mut().enumerate() {
|
|
||||||
row[0] = 0x5d;
|
|
||||||
row[1] = 0xb3;
|
|
||||||
row[2] = i as u8 + 1; // zone
|
|
||||||
row[3] = 0x01; // mode
|
|
||||||
}
|
|
||||||
let speed = match settings.speed {
|
|
||||||
aura_modes::Speed::Low => 0xfd,
|
|
||||||
aura_modes::Speed::Med => 0xfe,
|
|
||||||
aura_modes::Speed::High => 0xff,
|
|
||||||
};
|
|
||||||
msg[0][4] = settings.colour1.0;
|
|
||||||
msg[0][5] = settings.colour1.1;
|
|
||||||
msg[0][6] = settings.colour1.2;
|
|
||||||
msg[0][7] = speed; // fd, fe, ff
|
|
||||||
msg[1][4] = settings.colour2.0;
|
|
||||||
msg[1][5] = settings.colour2.1;
|
|
||||||
msg[1][6] = settings.colour2.2;
|
|
||||||
msg[1][7] = speed;
|
|
||||||
msg[2][4] = settings.colour3.0;
|
|
||||||
msg[2][5] = settings.colour3.1;
|
|
||||||
msg[2][6] = settings.colour3.2;
|
|
||||||
msg[2][7] = speed;
|
|
||||||
msg[3][4] = settings.colour4.0;
|
|
||||||
msg[3][5] = settings.colour4.1;
|
|
||||||
msg[3][6] = settings.colour4.2;
|
|
||||||
msg[3][7] = speed;
|
|
||||||
}
|
|
||||||
_ => panic!("Mode not convertable to 2D array: {}", <&str>::from(mode)),
|
|
||||||
}
|
|
||||||
msg
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -80,18 +80,26 @@ pub struct ProfileCommand {
|
|||||||
pub next: bool,
|
pub next: bool,
|
||||||
#[options(help = "create the profile if it doesn't exist")]
|
#[options(help = "create the profile if it doesn't exist")]
|
||||||
pub create: bool,
|
pub create: bool,
|
||||||
|
#[options(help = "list available profiles")]
|
||||||
|
pub list: bool,
|
||||||
|
|
||||||
#[options(help = "enable or disable cpu turbo")]
|
#[options(meta = "", help = "enable or disable cpu turbo")]
|
||||||
pub turbo: Option<bool>,
|
pub turbo: Option<bool>,
|
||||||
#[options(help = "set min cpu scaling (intel)")]
|
#[options(meta = "", help = "set min cpu scaling (intel)")]
|
||||||
pub min_percentage: Option<u8>,
|
pub min_percentage: Option<u8>,
|
||||||
#[options(help = "set max cpu scaling (intel)")]
|
#[options(meta = "", help = "set max cpu scaling (intel)")]
|
||||||
pub max_percentage: Option<u8>,
|
pub max_percentage: Option<u8>,
|
||||||
|
|
||||||
#[options(meta = "PWR", help = "<silent, normal, boost>")]
|
#[options(meta = "", help = "<silent, normal, boost>")]
|
||||||
pub preset: Option<FanLevel>,
|
pub fan_preset: Option<FanLevel>,
|
||||||
#[options(parse(try_from_str = "parse_fan_curve"), help = "set fan curve")]
|
#[options(
|
||||||
|
meta = "",
|
||||||
|
parse(try_from_str = "parse_fan_curve"),
|
||||||
|
help = "set fan curve"
|
||||||
|
)]
|
||||||
pub curve: Option<Curve>,
|
pub curve: Option<Curve>,
|
||||||
#[options(free)]
|
#[options(free)]
|
||||||
pub profile: Option<String>,
|
pub profile: Option<String>,
|
||||||
|
#[options(help = "remove a profile by name")]
|
||||||
|
pub remove: Option<String>,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user