Compare commits
49 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7a4c14f7b8 | |||
| f52a4d464a | |||
| aa71592a31 | |||
| dc6e8f8dcb | |||
| 1a4836246f | |||
| ab80b0742f | |||
| 6926aeed20 | |||
| f95e42e4b9 | |||
| 82bee6b86e | |||
| bd9bc8bcff | |||
| 8a6d364304 | |||
| 64d99a3e05 | |||
| 59f54b76f6 | |||
| 6f36d91281 | |||
| e9f1fa01fc | |||
| 0d3a5d266b | |||
| cc28cee8bd | |||
| 6ebf0c2bb2 | |||
| 77c658c94e | |||
| df64a51372 | |||
| 0657c6cc74 | |||
| f116905e85 | |||
| e515741efa | |||
| d516abdc92 | |||
| ece565de1c | |||
| eb83d1a835 | |||
| 7d0f15d738 | |||
| 8010da0891 | |||
| aa500c35c4 | |||
| 2af33a0416 | |||
| 9b4ed6eb62 | |||
| 47c1ca9fe4 | |||
| 3cd624daf0 | |||
| fa16864a3e | |||
| bfc31b06d5 | |||
| d854f7da1b | |||
| 6d746b21a5 | |||
| 226c083a51 | |||
| de59d00949 | |||
| 7ff01f12e9 | |||
| fbc248177a | |||
| fc3d7653f5 | |||
| 2dc70ea6af | |||
| 01345b28a5 | |||
| 4eeacea832 | |||
| 6bf0fdd117 | |||
| 7fcde7df17 | |||
| 543b0b817f | |||
| 5a7d31fdf6 |
@@ -6,6 +6,59 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
# [3.5.0] - 2021-04-25
|
||||||
|
### Changed
|
||||||
|
+ Keyboard:
|
||||||
|
- Split out all aura functionality that isn't dependent on the daemon in to a
|
||||||
|
new crate `rog-aura` (incomplete)
|
||||||
|
- Keyboard LED control now includes:
|
||||||
|
+ Enable/disable LED's while laptop is awake
|
||||||
|
+ Enable/disable LED animation while laptop is suspended and AC plugged in
|
||||||
|
- Properly reload the last used keyboard mode on boot
|
||||||
|
+ Graphics:
|
||||||
|
- Correctly enable compute mode for nvidia plus no-reboot or logout if switching
|
||||||
|
from vfio/integrated/compute.
|
||||||
|
- Add asusd config option to not save compute/vfio mode switch.
|
||||||
|
+ Anime:
|
||||||
|
- Enable basic multiple user anime configs (asusd-user must still be restarted)
|
||||||
|
+ Profiles:
|
||||||
|
- Enable dbus methods for freq min/max, fan curve, fan preset, CPU turbo enable.
|
||||||
|
These options will apply to the active profile if no profile name is specified.
|
||||||
|
|
||||||
|
# [3.4.1] - 2021-04-11
|
||||||
|
### Changed
|
||||||
|
- Fix anime init sequence
|
||||||
|
|
||||||
|
# [3.4.0] - 2021-04-11
|
||||||
|
### Changed
|
||||||
|
- Revert zbus to 1.9.1
|
||||||
|
- Use enum to show power states, and catch missing pci path for nvidia.
|
||||||
|
- Partial user-daemon for anime/per-key done, `asusd-user`. Includes asusd-user systemd unit.
|
||||||
|
- user-daemon provides dbus emthods to insert anime actions, remove from index, set leds on/off
|
||||||
|
+ Config file is stored in `~/.config/rog/rog-user.cfg`
|
||||||
|
- AniMe display parts split out to individual crate in preparation for publishing
|
||||||
|
on crates.io
|
||||||
|
|
||||||
|
# [3.3.0] - 2021-04-3
|
||||||
|
### Changed
|
||||||
|
- Add ledmodes for G733QS
|
||||||
|
- Add ledmodes for GA401Q
|
||||||
|
- Default to vfio disabled in configuration. Will now hard-error if enabled and
|
||||||
|
the kernel modules are builtin. To enable vfio switching `"gfx_vfio_enable": false,`
|
||||||
|
must be changed to `true` in `/etc/asusd/asusd.conf`
|
||||||
|
|
||||||
|
# [3.2.4] - 2021-03-24
|
||||||
|
### Changed
|
||||||
|
- Ignore vfio-builtin error if switching to integrated
|
||||||
|
|
||||||
|
# [3.2.3] - 2021-03-24
|
||||||
|
### Changed
|
||||||
|
- Better handling of session tracking
|
||||||
|
### Added
|
||||||
|
- List all profile data
|
||||||
|
- Get active profile name
|
||||||
|
- Get active profile data
|
||||||
|
|
||||||
# [3.2.2] - 2021-03-23
|
# [3.2.2] - 2021-03-23
|
||||||
### Changed
|
### Changed
|
||||||
- Fix brightness control, again, for non-RGB keyboards
|
- Fix brightness control, again, for non-RGB keyboards
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "adler"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aho-corasick"
|
name = "aho-corasick"
|
||||||
version = "0.7.15"
|
version = "0.7.15"
|
||||||
@@ -28,15 +36,20 @@ dependencies = [
|
|||||||
"daemon",
|
"daemon",
|
||||||
"notify-rust",
|
"notify-rust",
|
||||||
"rog_dbus",
|
"rog_dbus",
|
||||||
|
"rog_types",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "asusctl"
|
name = "asusctl"
|
||||||
version = "3.1.4"
|
version = "3.5.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"daemon",
|
"daemon",
|
||||||
|
"gif",
|
||||||
|
"glam",
|
||||||
"gumdrop",
|
"gumdrop",
|
||||||
|
"rog_anime",
|
||||||
|
"rog_aura",
|
||||||
"rog_dbus",
|
"rog_dbus",
|
||||||
"rog_types",
|
"rog_types",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
@@ -64,15 +77,6 @@ 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"
|
||||||
@@ -168,6 +172,12 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "color_quant"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "concurrent-queue"
|
name = "concurrent-queue"
|
||||||
version = "1.2.2"
|
version = "1.2.2"
|
||||||
@@ -196,12 +206,14 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "daemon"
|
name = "daemon"
|
||||||
version = "3.2.2"
|
version = "3.5.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"intel-pstate",
|
"intel-pstate",
|
||||||
"log",
|
"log",
|
||||||
"logind-zbus",
|
"logind-zbus",
|
||||||
|
"rog_anime",
|
||||||
|
"rog_aura",
|
||||||
"rog_dbus",
|
"rog_dbus",
|
||||||
"rog_fan_curve",
|
"rog_fan_curve",
|
||||||
"rog_types",
|
"rog_types",
|
||||||
@@ -212,10 +224,26 @@ dependencies = [
|
|||||||
"sysfs-class",
|
"sysfs-class",
|
||||||
"toml",
|
"toml",
|
||||||
"udev",
|
"udev",
|
||||||
"zbus 2.0.0-beta.3",
|
"zbus",
|
||||||
"zvariant",
|
"zvariant",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "daemon-user"
|
||||||
|
version = "1.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"dirs 3.0.1",
|
||||||
|
"rog_anime",
|
||||||
|
"rog_dbus",
|
||||||
|
"rog_types",
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
|
"serde_json",
|
||||||
|
"zbus",
|
||||||
|
"zvariant",
|
||||||
|
"zvariant_derive",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "derivative"
|
name = "derivative"
|
||||||
version = "2.2.0"
|
version = "2.2.0"
|
||||||
@@ -224,7 +252,7 @@ checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote 1.0.9",
|
"quote 1.0.9",
|
||||||
"syn 1.0.64",
|
"syn 1.0.69",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -238,6 +266,26 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dirs"
|
||||||
|
version = "3.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "142995ed02755914747cc6ca76fc7e4583cd18578746716d0508ea6ed558b9ff"
|
||||||
|
dependencies = [
|
||||||
|
"dirs-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dirs-sys"
|
||||||
|
version = "0.3.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e93d7f5705de3e49895a2b5e0b8855a1c27f080192ae9c32a6432d50741a57a"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"redox_users",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "enumflags2"
|
name = "enumflags2"
|
||||||
version = "0.6.4"
|
version = "0.6.4"
|
||||||
@@ -256,7 +304,7 @@ checksum = "946ee94e3dbf58fdd324f9ce245c7b238d46a66f00e86a020b71996349e46cce"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote 1.0.9",
|
"quote 1.0.9",
|
||||||
"syn 1.0.64",
|
"syn 1.0.69",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -282,16 +330,10 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote 1.0.9",
|
"quote 1.0.9",
|
||||||
"rustversion",
|
"rustversion",
|
||||||
"syn 1.0.64",
|
"syn 1.0.69",
|
||||||
"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"
|
||||||
@@ -303,9 +345,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures"
|
name = "futures"
|
||||||
version = "0.3.13"
|
version = "0.3.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7f55667319111d593ba876406af7c409c0ebb44dc4be6132a783ccf163ea14c1"
|
checksum = "a9d5813545e459ad3ca1bff9915e9ad7f1a47dc6a91b627ce321d5863b7dd253"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
@@ -318,9 +360,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-channel"
|
name = "futures-channel"
|
||||||
version = "0.3.13"
|
version = "0.3.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8c2dd2df839b57db9ab69c2c9d8f3e8c81984781937fe2807dc6dcf3b2ad2939"
|
checksum = "ce79c6a52a299137a6013061e0cf0e688fce5d7f1bc60125f520912fdb29ec25"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-sink",
|
"futures-sink",
|
||||||
@@ -328,15 +370,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-core"
|
name = "futures-core"
|
||||||
version = "0.3.13"
|
version = "0.3.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "15496a72fabf0e62bdc3df11a59a3787429221dd0710ba8ef163d6f7a9112c94"
|
checksum = "098cd1c6dda6ca01650f1a37a794245eb73181d0d4d4e955e2f3c37db7af1815"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-executor"
|
name = "futures-executor"
|
||||||
version = "0.3.13"
|
version = "0.3.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "891a4b7b96d84d5940084b2a37632dd65deeae662c114ceaa2c879629c9c0ad1"
|
checksum = "10f6cb7042eda00f0049b1d2080aa4b93442997ee507eb3828e8bd7577f94c9d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-task",
|
"futures-task",
|
||||||
@@ -345,9 +387,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-io"
|
name = "futures-io"
|
||||||
version = "0.3.13"
|
version = "0.3.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d71c2c65c57704c32f5241c1223167c2c3294fd34ac020c807ddbe6db287ba59"
|
checksum = "365a1a1fb30ea1c03a830fdb2158f5236833ac81fa0ad12fe35b29cddc35cb04"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-lite"
|
name = "futures-lite"
|
||||||
@@ -366,33 +408,33 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-macro"
|
name = "futures-macro"
|
||||||
version = "0.3.13"
|
version = "0.3.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ea405816a5139fb39af82c2beb921d52143f556038378d6db21183a5c37fbfb7"
|
checksum = "668c6733a182cd7deb4f1de7ba3bf2120823835b3bcfbeacf7d2c4a773c1bb8b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-hack",
|
"proc-macro-hack",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote 1.0.9",
|
"quote 1.0.9",
|
||||||
"syn 1.0.64",
|
"syn 1.0.69",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-sink"
|
name = "futures-sink"
|
||||||
version = "0.3.13"
|
version = "0.3.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "85754d98985841b7d4f5e8e6fbfa4a4ac847916893ec511a2917ccd8525b8bb3"
|
checksum = "5c5629433c555de3d82861a7a4e3794a4c40040390907cfbfd7143a92a426c23"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-task"
|
name = "futures-task"
|
||||||
version = "0.3.13"
|
version = "0.3.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fa189ef211c15ee602667a6fcfe1c1fd9e07d42250d2156382820fba33c9df80"
|
checksum = "ba7aa51095076f3ba6d9a1f702f74bd05ec65f555d70d2033d55ba8d69f581bc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-util"
|
name = "futures-util"
|
||||||
version = "0.3.13"
|
version = "0.3.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1812c7ab8aedf8d6f2701a43e1243acdbcc2b36ab26e2ad421eb99ac963d96d1"
|
checksum = "3c144ad54d60f23927f0a6b6d816e4271278b64f005ad65e4e35291d2de9c025"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
@@ -420,14 +462,22 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "gif"
|
||||||
version = "0.2.2"
|
version = "0.11.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
|
checksum = "5a668f699973d0f573d15749b7002a9ac9e1f9c6b220e7b165601334c173d8de"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"color_quant",
|
||||||
"libc",
|
"weezl",
|
||||||
"wasi 0.10.2+wasi-snapshot-preview1",
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "glam"
|
||||||
|
version = "0.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "333928d5eb103c5d4050533cec0384302db6be8ef7d3cebd30ec6a35350353da"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -447,7 +497,7 @@ checksum = "915ef07c710d84733522461de2a734d4d62a3fd39a4d4f404c2f385ef8618d05"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote 1.0.9",
|
"quote 1.0.9",
|
||||||
"syn 1.0.64",
|
"syn 1.0.69",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -459,12 +509,6 @@ 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"
|
||||||
@@ -504,9 +548,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.90"
|
version = "0.2.93"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ba4aede83fc3617411dc6993bc8c70919750c1c257c6ca6a502aed6e0e2394ae"
|
checksum = "9385f66bf6105b241aa65a61cb923ef20efc665cb9f9bb50ac2f0c4b7f378d41"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libudev-sys"
|
name = "libudev-sys"
|
||||||
@@ -541,14 +585,14 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "logind-zbus"
|
name = "logind-zbus"
|
||||||
version = "0.6.1"
|
version = "0.7.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6671f6cf88b63e9d63009f4f6f8826fcc265c51a9977e4c7dc1263d743e0dfbb"
|
checksum = "dca64bea11e365933e0c4a1a9342f0122d1d2822a09c87dab0e1d314adb353a2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"zbus 2.0.0-beta.3",
|
"zbus",
|
||||||
"zbus_macros 2.0.0-beta.3",
|
"zbus_macros",
|
||||||
"zvariant",
|
"zvariant",
|
||||||
"zvariant_derive",
|
"zvariant_derive",
|
||||||
]
|
]
|
||||||
@@ -561,7 +605,7 @@ checksum = "3dfb6b71a9a89cd38b395d994214297447e8e63b1ba5708a9a2b0b1048ceda76"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"chrono",
|
"chrono",
|
||||||
"dirs",
|
"dirs 1.0.5",
|
||||||
"objc-foundation",
|
"objc-foundation",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -581,10 +625,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
|
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nb-connect"
|
name = "miniz_oxide"
|
||||||
version = "1.0.3"
|
version = "0.4.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "670361df1bc2399ee1ff50406a0d422587dd3bb0da596e1978fe8e05dabddf4f"
|
checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
|
||||||
|
dependencies = [
|
||||||
|
"adler",
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nb-connect"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a19900e7eee95eb2b3c2e26d12a874cc80aaf750e31be6fcbe743ead369fa45d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"socket2",
|
"socket2",
|
||||||
@@ -603,18 +657,6 @@ 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"
|
||||||
@@ -634,7 +676,7 @@ dependencies = [
|
|||||||
"mac-notification-sys",
|
"mac-notification-sys",
|
||||||
"serde",
|
"serde",
|
||||||
"winrt-notification",
|
"winrt-notification",
|
||||||
"zbus 1.8.0",
|
"zbus",
|
||||||
"zvariant",
|
"zvariant",
|
||||||
"zvariant_derive",
|
"zvariant_derive",
|
||||||
]
|
]
|
||||||
@@ -717,6 +759,12 @@ version = "0.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pix"
|
||||||
|
version = "0.13.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bea9d5c668f13b4a1b97d848780e00cfabf76eb83538129c264c0c6d6a968047"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pkg-config"
|
name = "pkg-config"
|
||||||
version = "0.3.19"
|
version = "0.3.19"
|
||||||
@@ -724,24 +772,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
|
checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "polling"
|
name = "png_pong"
|
||||||
version = "2.0.2"
|
version = "0.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a2a7bc6b2a29e632e45451c941832803a18cce6781db04de8a04696cdca8bde4"
|
checksum = "75851150081bd473079e03e2fa00e25557bcb19706e502b095ca71ce392b70ff"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 0.1.10",
|
"miniz_oxide",
|
||||||
|
"pix",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "polling"
|
||||||
|
version = "2.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4fc12d774e799ee9ebae13f4076ca003b40d18a11ac0f3641e6f899618580b7b"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 1.0.0",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"wepoll-sys",
|
"wepoll-sys",
|
||||||
"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"
|
||||||
@@ -760,7 +812,7 @@ dependencies = [
|
|||||||
"proc-macro-error-attr",
|
"proc-macro-error-attr",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote 1.0.9",
|
"quote 1.0.9",
|
||||||
"syn 1.0.64",
|
"syn 1.0.69",
|
||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -789,9 +841,9 @@ checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.24"
|
version = "1.0.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
|
checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-xid 0.2.1",
|
"unicode-xid 0.2.1",
|
||||||
]
|
]
|
||||||
@@ -811,46 +863,6 @@ 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"
|
||||||
@@ -863,7 +875,7 @@ 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 0.1.16",
|
"getrandom",
|
||||||
"redox_syscall",
|
"redox_syscall",
|
||||||
"rust-argon2",
|
"rust-argon2",
|
||||||
]
|
]
|
||||||
@@ -886,14 +898,42 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548"
|
checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rog_dbus"
|
name = "rog_anime"
|
||||||
version = "3.0.0"
|
version = "1.0.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"gif",
|
||||||
|
"glam",
|
||||||
|
"pix",
|
||||||
|
"png_pong",
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
|
"zbus",
|
||||||
|
"zvariant",
|
||||||
|
"zvariant_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rog_aura"
|
||||||
|
version = "1.0.1"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
|
"zbus",
|
||||||
|
"zvariant",
|
||||||
|
"zvariant_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rog_dbus"
|
||||||
|
version = "3.2.0"
|
||||||
|
dependencies = [
|
||||||
|
"rog_anime",
|
||||||
|
"rog_aura",
|
||||||
"rog_fan_curve",
|
"rog_fan_curve",
|
||||||
"rog_types",
|
"rog_types",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"zbus 1.8.0",
|
"zbus",
|
||||||
"zbus_macros 1.8.0",
|
"zbus_macros",
|
||||||
"zvariant",
|
"zvariant",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -908,9 +948,10 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rog_types"
|
name = "rog_types"
|
||||||
version = "3.1.1"
|
version = "3.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gumdrop",
|
"gumdrop",
|
||||||
|
"rog_aura",
|
||||||
"rog_fan_curve",
|
"rog_fan_curve",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
@@ -920,9 +961,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rusb"
|
name = "rusb"
|
||||||
version = "0.7.0"
|
version = "0.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c470dc7dc6e4710b6f85e9c4aa4650bc742260b39a36328180578db76fa258c1"
|
checksum = "12f3264859095257507e4c011ab420ff9b2d9cc3349c6c08a1d3a019260bb437"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"libusb1-sys",
|
"libusb1-sys",
|
||||||
@@ -960,22 +1001,22 @@ checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.124"
|
version = "1.0.125"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bd761ff957cb2a45fbb9ab3da6512de9de55872866160b23c25f1a841e99d29f"
|
checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.124"
|
version = "1.0.125"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1800f7693e94e186f5e25a28291ae1570da908aff7d97a095dec1e56ff99069b"
|
checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote 1.0.9",
|
"quote 1.0.9",
|
||||||
"syn 1.0.64",
|
"syn 1.0.69",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -997,30 +1038,15 @@ checksum = "2dc6b7951b17b051f3210b063f12cc17320e2fe30ae05b0fe2a3abb068551c76"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote 1.0.9",
|
"quote 1.0.9",
|
||||||
"syn 1.0.64",
|
"syn 1.0.69",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[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"
|
||||||
@@ -1029,16 +1055,15 @@ checksum = "133659a15339456eeeb07572eb02a91c91e9815e9cbc89566944d2c8d3efdbf6"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote 1.0.9",
|
"quote 1.0.9",
|
||||||
"syn 1.0.64",
|
"syn 1.0.69",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
version = "0.3.19"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e"
|
checksum = "9e3dfc207c526015c632472a77be09cf1b6e46866581aecae5cc38fb4235dea2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
|
||||||
"libc",
|
"libc",
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
@@ -1072,9 +1097,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.64"
|
version = "1.0.69"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3fd9d1e9976102a03c542daa2eff1b43f9d72306342f3f8b3ed5fb8908195d6f"
|
checksum = "48fe99c6bd8b1cc636890bcc071842de909d902c81ac7dab53ba33c421ab8ffb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote 1.0.9",
|
"quote 1.0.9",
|
||||||
@@ -1098,7 +1123,7 @@ checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote 1.0.9",
|
"quote 1.0.9",
|
||||||
"syn 1.0.64",
|
"syn 1.0.69",
|
||||||
"unicode-xid 0.2.1",
|
"unicode-xid 0.2.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1122,11 +1147,12 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time"
|
name = "time"
|
||||||
version = "0.1.43"
|
version = "0.1.44"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
|
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
|
"wasi 0.10.0+wasi-snapshot-preview1",
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1150,9 +1176,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "udev"
|
name = "udev"
|
||||||
version = "0.6.0"
|
version = "0.6.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "307c2b8c8a320a38365def5bb3ee92d146d405655196230f7a445fe4da6749f6"
|
checksum = "3193363f52bb34c6708ac2ffedcb5f7e5874f0329ef68e1315f27d8d768eb568"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"libudev-sys",
|
"libudev-sys",
|
||||||
@@ -1179,9 +1205,9 @@ checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vec-arena"
|
name = "vec-arena"
|
||||||
version = "1.0.0"
|
version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "eafc1b9b2dfc6f5529177b62cf806484db55b32dc7c9658a118e11bbeb33061d"
|
checksum = "34b2f665b594b07095e3ac3f718e13c2197143416fae4c5706cffb7b1af8d7f1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
@@ -1209,9 +1235,15 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.10.2+wasi-snapshot-preview1"
|
version = "0.10.0+wasi-snapshot-preview1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "weezl"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4a32b378380f4e9869b22f0b5177c68a5519f03b3454fde0b291455ddbae266c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wepoll-sys"
|
name = "wepoll-sys"
|
||||||
@@ -1295,9 +1327,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zbus"
|
name = "zbus"
|
||||||
version = "1.8.0"
|
version = "1.9.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "40b4d4aa39daed4e32aed75f0c37b969184949a0fdfd5f2e1277abfda61f02a8"
|
checksum = "2326acc379a3ac4e34b794089f5bdb17086bf29a5fdf619b7b4cc772dc2e9dad"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-io",
|
"async-io",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
@@ -1306,66 +1338,26 @@ dependencies = [
|
|||||||
"fastrand",
|
"fastrand",
|
||||||
"futures",
|
"futures",
|
||||||
"nb-connect",
|
"nb-connect",
|
||||||
"nix 0.17.0",
|
"nix",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"polling",
|
"polling",
|
||||||
"scoped-tls",
|
"scoped-tls",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_repr",
|
"serde_repr",
|
||||||
"zbus_macros 1.8.0",
|
"zbus_macros",
|
||||||
"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",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zbus_macros"
|
name = "zbus_macros"
|
||||||
version = "1.8.0"
|
version = "1.9.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "87cc141cda72384bef359badf1808e391d3968f9299e8f3c3cbb78dafa1e0930"
|
checksum = "a482c56029e48681b89b92b5db3c446db0915e8dd1052c0328a574eda38d5f93"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-crate",
|
"proc-macro-crate",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote 1.0.9",
|
"quote 1.0.9",
|
||||||
"syn 1.0.64",
|
"syn 1.0.69",
|
||||||
]
|
|
||||||
|
|
||||||
[[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]]
|
||||||
@@ -1389,5 +1381,5 @@ dependencies = [
|
|||||||
"proc-macro-crate",
|
"proc-macro-crate",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote 1.0.9",
|
"quote 1.0.9",
|
||||||
"syn 1.0.64",
|
"syn 1.0.69",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
members = ["asusctl", "asus-notify", "daemon", "rog-types", "rog-dbus"]
|
members = ["asusctl", "asus-notify", "daemon", "daemon-user", "rog-types", "rog-dbus", "rog-anime"]
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = true
|
lto = true
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ zshcpl = $(datarootdir)/zsh/site-functions
|
|||||||
|
|
||||||
BIN_C := asusctl
|
BIN_C := asusctl
|
||||||
BIN_D := asusd
|
BIN_D := asusd
|
||||||
|
BIN_U := asusd-user
|
||||||
BIN_N := asus-notify
|
BIN_N := asus-notify
|
||||||
LEDCFG := asusd-ledmodes.toml
|
LEDCFG := asusd-ledmodes.toml
|
||||||
X11CFG := 90-nvidia-screen-G05.conf
|
X11CFG := 90-nvidia-screen-G05.conf
|
||||||
@@ -42,6 +43,7 @@ distclean:
|
|||||||
install:
|
install:
|
||||||
$(INSTALL_PROGRAM) "./target/release/$(BIN_C)" "$(DESTDIR)$(bindir)/$(BIN_C)"
|
$(INSTALL_PROGRAM) "./target/release/$(BIN_C)" "$(DESTDIR)$(bindir)/$(BIN_C)"
|
||||||
$(INSTALL_PROGRAM) "./target/release/$(BIN_D)" "$(DESTDIR)$(bindir)/$(BIN_D)"
|
$(INSTALL_PROGRAM) "./target/release/$(BIN_D)" "$(DESTDIR)$(bindir)/$(BIN_D)"
|
||||||
|
$(INSTALL_PROGRAM) "./target/release/$(BIN_U)" "$(DESTDIR)$(bindir)/$(BIN_U)"
|
||||||
$(INSTALL_PROGRAM) "./target/release/$(BIN_N)" "$(DESTDIR)$(bindir)/$(BIN_N)"
|
$(INSTALL_PROGRAM) "./target/release/$(BIN_N)" "$(DESTDIR)$(bindir)/$(BIN_N)"
|
||||||
$(INSTALL_DATA) "./data/$(PMRULES)" "$(DESTDIR)$(libdir)/udev/rules.d/$(PMRULES)"
|
$(INSTALL_DATA) "./data/$(PMRULES)" "$(DESTDIR)$(libdir)/udev/rules.d/$(PMRULES)"
|
||||||
$(INSTALL_DATA) "./data/$(BIN_D).rules" "$(DESTDIR)$(libdir)/udev/rules.d/99-$(BIN_D).rules"
|
$(INSTALL_DATA) "./data/$(BIN_D).rules" "$(DESTDIR)$(libdir)/udev/rules.d/99-$(BIN_D).rules"
|
||||||
@@ -50,11 +52,13 @@ install:
|
|||||||
$(INSTALL_DATA) "./data/$(X11CFG)" "$(DESTDIR)$(datarootdir)/X11/xorg.conf.d/$(X11CFG)"
|
$(INSTALL_DATA) "./data/$(X11CFG)" "$(DESTDIR)$(datarootdir)/X11/xorg.conf.d/$(X11CFG)"
|
||||||
$(INSTALL_DATA) "./data/$(BIN_D).service" "$(DESTDIR)$(libdir)/systemd/system/$(BIN_D).service"
|
$(INSTALL_DATA) "./data/$(BIN_D).service" "$(DESTDIR)$(libdir)/systemd/system/$(BIN_D).service"
|
||||||
$(INSTALL_DATA) "./data/$(BIN_N).service" "$(DESTDIR)$(libdir)/systemd/user/$(BIN_N).service"
|
$(INSTALL_DATA) "./data/$(BIN_N).service" "$(DESTDIR)$(libdir)/systemd/user/$(BIN_N).service"
|
||||||
|
$(INSTALL_DATA) "./data/$(BIN_U).service" "$(DESTDIR)$(libdir)/systemd/user/$(BIN_U).service"
|
||||||
$(INSTALL_DATA) "./data/icons/asus_notif_yellow.png" "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_yellow.png"
|
$(INSTALL_DATA) "./data/icons/asus_notif_yellow.png" "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_yellow.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_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"
|
$(INSTALL_DATA) "./data/completions/asusctl.fish" "$(DESTDIR)$(datarootdir)/fish/vendor_completions.d/asusctl.fish"
|
||||||
|
cd data && find "./anime" -type f -exec install -Dm 755 "{}" "$(DESTDIR)$(datarootdir)/asusd/{}" \;
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
rm -f "$(DESTDIR)$(bindir)/$(BIN_C)"
|
rm -f "$(DESTDIR)$(bindir)/$(BIN_C)"
|
||||||
@@ -72,6 +76,7 @@ uninstall:
|
|||||||
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"
|
rm -f "$(DESTDIR)$(datarootdir)/fish/vendor_completions.d/asusctl.fish"
|
||||||
|
rm -rf "$(DESTDIR)$(datarootdir)/asusd"
|
||||||
|
|
||||||
update:
|
update:
|
||||||
cargo update
|
cargo update
|
||||||
@@ -82,13 +87,13 @@ vendor:
|
|||||||
echo 'directory = "vendor"' >> .cargo/config
|
echo 'directory = "vendor"' >> .cargo/config
|
||||||
mv .cargo/config ./cargo-config
|
mv .cargo/config ./cargo-config
|
||||||
rm -rf .cargo
|
rm -rf .cargo
|
||||||
tar pcfJ vendor_asus-nb-ctrl_$(VERSION).tar.xz vendor
|
tar pcfJ vendor_asusctl_$(VERSION).tar.xz vendor
|
||||||
rm -rf vendor
|
rm -rf vendor
|
||||||
|
|
||||||
build:
|
build:
|
||||||
ifeq ($(VENDORED),1)
|
ifeq ($(VENDORED),1)
|
||||||
@echo "version = $(VERSION)"
|
@echo "version = $(VERSION)"
|
||||||
tar pxf vendor_asus-nb-ctrl_$(VERSION).tar.xz
|
tar pxf vendor_asusctl_$(VERSION).tar.xz
|
||||||
endif
|
endif
|
||||||
cargo build $(ARGS)
|
cargo build $(ARGS)
|
||||||
|
|
||||||
|
|||||||
@@ -5,29 +5,26 @@
|
|||||||
`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.
|
||||||
|
|
||||||
**NOTICE:**
|
## Goals
|
||||||
|
|
||||||
This app is developed and tested on fedora only. Support is not provided for Arch or Arch based distros.
|
1. To provide an interface for rootless control of some system functions most users wish to control such as fan speeds, keyboard LEDs, graphics modes.
|
||||||
|
2. Enable third-party apps to use the above with dbus methods
|
||||||
|
3. To make the above as easy as possible for new users
|
||||||
|
|
||||||
|
Point 3 means that the list of supported distros is very narrow - fedora is explicitly
|
||||||
|
supported, while Ubuntu and openSUSE are level-2 support. All other distros are *not*
|
||||||
|
supported (while asusd might still run fine on them). For best support use fedora 32+ Workstation.
|
||||||
|
|
||||||
**NOTICE:**
|
**NOTICE:**
|
||||||
The following is *not* required for 5.11 kernel versions, as this version includes
|
1. The following is *not* required for 5.11 kernel versions, as this version includes all the required patches.
|
||||||
all the required patches.
|
2. 2021 hardware has a new keyboard prod_id and the patch is included in 5.12+
|
||||||
---
|
|
||||||
This program requires the kernel patch [here](https://www.spinics.net/lists/linux-input/msg68977.html) to be applied.
|
|
||||||
Alternatively you may use the dkms module for 'hid-asus-rog` from one of the
|
|
||||||
repositories [here](https://download.opensuse.org/repositories/home:/luke_nukem:/asus/).
|
|
||||||
|
|
||||||
The patch enables the following in kernel:
|
'hid-asus-rog` DKMS module from [here](https://download.opensuse.org/repositories/home:/luke_nukem:/asus/).
|
||||||
|
|
||||||
|
The module enables the following in kernel:
|
||||||
|
|
||||||
|
- Initialising the keyboard
|
||||||
- All hotkeys (FN+Key combos)
|
- All hotkeys (FN+Key combos)
|
||||||
- Control of keyboard brightness using FN+Key combos (not RGB)
|
|
||||||
- FN+F5 (fan) to toggle fan modes
|
|
||||||
|
|
||||||
You will not get RGB control in kernel (yet), and `asusd` + `asusctl` is required
|
|
||||||
to change modes and RGB settings.
|
|
||||||
|
|
||||||
Many other patches for these laptops, AMD and Intel based, are working their way
|
|
||||||
in to the kernel.
|
|
||||||
|
|
||||||
## Discord
|
## Discord
|
||||||
|
|
||||||
@@ -52,13 +49,14 @@ will probably suffer another rename once it becomes generic enough to do so.
|
|||||||
- [X] User notifications daemon
|
- [X] User notifications daemon
|
||||||
- [X] Setting/modifying built-in LED modes
|
- [X] Setting/modifying built-in LED modes
|
||||||
- [X] Per-key LED setting
|
- [X] Per-key LED setting
|
||||||
- [X] Fancy LED modes (See examples)
|
- [X] Fancy LED modes (See examples) (currently being reworked)
|
||||||
- [X] Saving settings for reload
|
- [X] Saving settings for reload
|
||||||
- [X] Logging - required for journalctl
|
- [X] Logging - required for journalctl
|
||||||
- [X] AniMatrix display on G14 models that include it
|
- [X] AniMatrix display on G14 models that include it (currently being reworked)
|
||||||
- [X] Set battery charge limit (with kernel supporting this)
|
- [X] Set battery charge limit (with kernel supporting this)
|
||||||
- [X] Fancy fan control on G14 + G15 thanks to @Yarn1
|
- [X] Fan curve control on G14 + G15 thanks to @Yarn1
|
||||||
- [X] Graphics mode switching between iGPU, dGPU, and On-Demand
|
- [X] Graphics mode switching between iGPU, dGPU, on-demand, and vfio (for VM pass-through)
|
||||||
|
+ [X] Requires only a logout/login
|
||||||
- [X] Toggle bios setting for boot/POST sound
|
- [X] Toggle bios setting for boot/POST sound
|
||||||
- [X] Toggle bios setting for "dedicated gfx" mode on supported laptops (g-sync)
|
- [X] Toggle bios setting for "dedicated gfx" mode on supported laptops (g-sync)
|
||||||
|
|
||||||
@@ -66,13 +64,20 @@ will probably suffer another rename once it becomes generic enough to do so.
|
|||||||
|
|
||||||
## Graphics switching
|
## Graphics switching
|
||||||
|
|
||||||
A new feature has been added to enable switching graphics modes. This can be disabled
|
`asusd` can switch graphics modes between:
|
||||||
in the config with `"manage_gfx": false,`. Additionally there is an extra setting
|
- `integrated`, uses the iGPU only and force-disables the dGPU
|
||||||
for laptops capable of g-sync dedicated gfx mode to enable the graphics switching
|
- `hybrid`, enables Nvidia prime-offload mode
|
||||||
to switch on dedicated gfx for "nvidia" mode.
|
- `nvidia`, uses the Nvidia gpu only
|
||||||
|
- `vfio`, binds the Nvidia gpu to vfio for VM pass-through
|
||||||
|
|
||||||
The CLI option for this does not require root until it asks for it, and provides
|
**Rebootless note:** You must edit `/etc/default/grub` to remove `nvidia-drm.modeset=1`
|
||||||
instructions.
|
from the line `GRUB_CMDLINE_LINUX=` and then recreate your grub config. In fedora
|
||||||
|
you can do this with `sudo grub2-mkconfig -o /etc/grub2.cfg` - other distro may be
|
||||||
|
similar but with a different config location.
|
||||||
|
|
||||||
|
This can be disabled in the config with `"manage_gfx": false,`. Additionally there
|
||||||
|
is an extra setting for laptops capable of g-sync dedicated gfx mode to enable the
|
||||||
|
graphics switching to switch on dedicated gfx for "nvidia" mode.
|
||||||
|
|
||||||
This switcher conflicts with other gpu switchers like optimus-manager, suse-prime
|
This switcher conflicts with other gpu switchers like optimus-manager, suse-prime
|
||||||
or ubuntu-prime, system76-power, and bbswitch. If you have issues with `asusd`
|
or ubuntu-prime, system76-power, and bbswitch. If you have issues with `asusd`
|
||||||
@@ -81,6 +86,12 @@ stray configs blocking nvidia modules from loading in:
|
|||||||
- `/etc/modprobe.d/`
|
- `/etc/modprobe.d/`
|
||||||
- `/usr/lib/modprope.d/`
|
- `/usr/lib/modprope.d/`
|
||||||
|
|
||||||
|
**VFIO NOTE:** The vfio modules *must not* be compiled into the kernel, they need
|
||||||
|
to be separate modules. If you don't plan to use vfio mode then you can ignore this
|
||||||
|
otherwise you may need a custom built kernel.
|
||||||
|
|
||||||
|
To enable vfio switching you need to edit `/etc/asusd/asusd.conf` and change `"gfx_vfio_enable": false,` to true.
|
||||||
|
|
||||||
### Power management udev rule
|
### Power management udev rule
|
||||||
|
|
||||||
If you have installed the Nvidia driver manually you will require the
|
If you have installed the Nvidia driver manually you will require the
|
||||||
@@ -89,8 +100,8 @@ If you have installed the Nvidia driver manually you will require the
|
|||||||
### fedora and openSUSE
|
### fedora and openSUSE
|
||||||
|
|
||||||
You *may* need a file `/etc/dracut.conf.d/90-nvidia-dracut-G05.conf` installed
|
You *may* need a file `/etc/dracut.conf.d/90-nvidia-dracut-G05.conf` installed
|
||||||
to stop dracut including the nvidia modules in the ramdisk. This is espeically
|
to stop dracut including the nvidia modules in the ramdisk if you manually
|
||||||
true if you manually installed the nvidia drivers.
|
installed the nvidia drivers.
|
||||||
|
|
||||||
```
|
```
|
||||||
# filename /etc/dracut.conf.d/90-nvidia-dracut-G05.conf
|
# filename /etc/dracut.conf.d/90-nvidia-dracut-G05.conf
|
||||||
@@ -109,24 +120,21 @@ Models GA401, GA502, GU502 support LED brightness change only (no RGB).
|
|||||||
If you model isn't getting the correct led modes, you can edit the file
|
If you model isn't getting the correct led modes, you can edit the file
|
||||||
`/etc/asusd/asusd-ledmodes.toml`, the LED Mode numbers are as follows:
|
`/etc/asusd/asusd-ledmodes.toml`, the LED Mode numbers are as follows:
|
||||||
|
|
||||||
```
|
- Static
|
||||||
0 STATIC
|
- Breathe
|
||||||
1 BREATHING
|
- Strobe
|
||||||
2 STROBE
|
- Rainbow
|
||||||
3 RAINBOW
|
- Star
|
||||||
4 STAR
|
- Rain
|
||||||
5 RAIN
|
- Highlight
|
||||||
6 HIGHLIGHT
|
- Laser
|
||||||
7 LASER
|
- Ripple
|
||||||
8 RIPPLE
|
- Pulse
|
||||||
10 PULSE
|
- Comet
|
||||||
11 COMET
|
- Flash
|
||||||
12 FLASH
|
|
||||||
13 MULTISTATIC
|
|
||||||
255 PER_KEY
|
|
||||||
```
|
|
||||||
|
|
||||||
use `cat /sys/class/dmi/id/product_name` to get details about your laptop.
|
use `cat /sys/class/dmi/id/product_name` to get details about your laptop. You
|
||||||
|
must restart the `asusd.service` after editing.
|
||||||
|
|
||||||
# Keybinds
|
# Keybinds
|
||||||
|
|
||||||
@@ -156,8 +164,6 @@ Packaging and auto-builds are available [here](https://build.opensuse.org/packag
|
|||||||
|
|
||||||
Download repositories are available [here](https://download.opensuse.org/repositories/home:/luke_nukem:/asus/)
|
Download repositories are available [here](https://download.opensuse.org/repositories/home:/luke_nukem:/asus/)
|
||||||
|
|
||||||
Alternatively check the releases page for f33 RPM.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Run `make` then `sudo make install` then reboot.
|
Run `make` then `sudo make install` then reboot.
|
||||||
@@ -182,26 +188,8 @@ can be added on request). You will need to install the alternative service from
|
|||||||
|
|
||||||
Run `sudo make uninstall` in the source repo, and remove `/etc/asusd/`.
|
Run `sudo make uninstall` in the source repo, and remove `/etc/asusd/`.
|
||||||
|
|
||||||
## Updating
|
|
||||||
|
|
||||||
If there has been a config file format change your config will be overwritten. This will
|
|
||||||
become less of an issue once the feature set is nailed down. Work is happening to enable
|
|
||||||
parsing of older configs and transferring settings to new.
|
|
||||||
|
|
||||||
# USAGE
|
# USAGE
|
||||||
|
|
||||||
**NOTE! Fan mode toggling requires a newer kernel**. I'm unsure when the patches
|
|
||||||
required for it got merged - I've tested with the 5.6.6 kernel and above only.
|
|
||||||
To see if the fan-mode changed cat either:
|
|
||||||
|
|
||||||
- `cat /sys/devices/platform/asus-nb-wmi/throttle_thermal_policy` or
|
|
||||||
- `cat /sys/devices/platform/asus-nb-wmi/fan_boost_mode`
|
|
||||||
|
|
||||||
The numbers are 0 = Normal/Balanced, 1 = Boost, 2 = Silent.
|
|
||||||
|
|
||||||
Running the program as a daemon manually will require root. Standard (non-daemon)
|
|
||||||
mode expects to be communicating with the daemon mode over dbus.
|
|
||||||
|
|
||||||
Commands are given by:
|
Commands are given by:
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -221,23 +209,6 @@ Some commands may have subcommands:
|
|||||||
asusctl <command> <subcommand> --help
|
asusctl <command> <subcommand> --help
|
||||||
```
|
```
|
||||||
|
|
||||||
## Daemon mode
|
|
||||||
|
|
||||||
If the daemon service is enabled then on boot the following will be reloaded from save:
|
|
||||||
|
|
||||||
- LED brightness
|
|
||||||
- Last used built-in mode
|
|
||||||
- fan-boost/thermal mode
|
|
||||||
- battery charging limit
|
|
||||||
|
|
||||||
The daemon also saves the settings per mode as the keyboard does not do this
|
|
||||||
itself - this means cycling through modes with the Aura keys will use the
|
|
||||||
settings that were used via CLI.
|
|
||||||
|
|
||||||
Daemon mode creates a config file at `/etc/asusd/asusd.conf` which you can edit a
|
|
||||||
little of. Most parts will be byte arrays, but you can adjust things like
|
|
||||||
`mode_performance`.
|
|
||||||
|
|
||||||
## User NOTIFICATIONS via dbus
|
## User NOTIFICATIONS via dbus
|
||||||
|
|
||||||
If you have a notifications handler set up, or are using KDE or Gnome then you
|
If you have a notifications handler set up, or are using KDE or Gnome then you
|
||||||
@@ -247,12 +218,9 @@ can enable the user service to get basic notifications when something changes.
|
|||||||
systemctl --user enable asus-notify.service
|
systemctl --user enable asus-notify.service
|
||||||
systemctl --user start asus-notify.service
|
systemctl --user start asus-notify.service
|
||||||
```
|
```
|
||||||
|
|
||||||
# OTHER
|
# OTHER
|
||||||
|
|
||||||
## DBUS Input
|
|
||||||
|
|
||||||
See [README_DBUS.md](./README_DBUS.md).
|
|
||||||
|
|
||||||
## AniMe input
|
## AniMe input
|
||||||
|
|
||||||
You will want to look at what MeuMeu has done with [https://github.com/Meumeu/ZephyrusBling/](https://github.com/Meumeu/ZephyrusBling/)
|
You will want to look at what MeuMeu has done with [https://github.com/Meumeu/ZephyrusBling/](https://github.com/Meumeu/ZephyrusBling/)
|
||||||
@@ -278,11 +246,3 @@ omit_drivers+=" nvidia nvidia-drm nvidia-modeset nvidia-uvm "
|
|||||||
# License
|
# License
|
||||||
|
|
||||||
Mozilla Public License 2 (MPL-2.0)
|
Mozilla Public License 2 (MPL-2.0)
|
||||||
|
|
||||||
# Credits
|
|
||||||
|
|
||||||
- [flukejones](https://github.com/flukejones/), project maintainer.
|
|
||||||
- [tuxuser](https://github.com/tuxuser/)
|
|
||||||
- [aspann](https://github.com/aspann)
|
|
||||||
- [meumeu](https://github.com/Meumeu)
|
|
||||||
- Anyone missed? Please contact me
|
|
||||||
|
|||||||
@@ -1,115 +0,0 @@
|
|||||||
# DBUS Guide
|
|
||||||
|
|
||||||
**WARNING: In progress updates**
|
|
||||||
|
|
||||||
Interface name = org.asuslinux.Daemon
|
|
||||||
|
|
||||||
Paths:
|
|
||||||
- `/org/asuslinux/Gfx`
|
|
||||||
+ `SetVendor` (string)
|
|
||||||
+ `NotifyVendor` (recv vendor label string)
|
|
||||||
- `/org/asuslinux/Led`
|
|
||||||
+ `LedMode` (AuraMode as json)
|
|
||||||
+ `LedModes` (array[AuraMode] as json)
|
|
||||||
+ `SetLedMode` (AuraMode -> json)
|
|
||||||
+ `NotifyLed` (recv json data)
|
|
||||||
- `/org/asuslinux/Anime`
|
|
||||||
+ `SetAnime` (byte array data)
|
|
||||||
- `/org/asuslinux/Charge`
|
|
||||||
+ `Limit` (u8)
|
|
||||||
+ `SetLimit` (u8)
|
|
||||||
+ `NotifyCharge` (recv i8)
|
|
||||||
- `/org/asuslinux/Profile`
|
|
||||||
+ `Profile` (recv current profile data as json string)
|
|
||||||
+ `Profiles` (recv profiles data as json string (map))
|
|
||||||
+ `SetProfile` (event -> json)
|
|
||||||
+ `NotifyProfile` (recv current profile name)
|
|
||||||
|
|
||||||
All `Notify*` methods are signals.
|
|
||||||
|
|
||||||
### SetLed
|
|
||||||
|
|
||||||
This method expects a string of JSON as input. The JSON is of format such:
|
|
||||||
|
|
||||||
```
|
|
||||||
{
|
|
||||||
"Static": {
|
|
||||||
"colour": [ 255, 0, 0]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The possible contents of a mode are:
|
|
||||||
|
|
||||||
- `"colour": [u8, u8, u8],`
|
|
||||||
- `"speed": <String>,` <Low, Med, High>
|
|
||||||
- `"direction": <String>,` <Up, Down, Left, Right>
|
|
||||||
|
|
||||||
Modes may or may not be available for a specific laptop (TODO: dbus getter for
|
|
||||||
supported modes). Modes are:
|
|
||||||
|
|
||||||
- `"Static": { "colour": <colour> },`
|
|
||||||
- `"Pulse": { "colour": <colour> },`
|
|
||||||
- `"Comet": { "colour": <colour> },`
|
|
||||||
- `"Flash": { "colour": <colour> },`
|
|
||||||
- `"Strobe": { "speed": <speed> },`
|
|
||||||
- `"Rain": { "speed": <speed> },`
|
|
||||||
- `"Laser": { "colour": <colour>, "speed": <speed> },`
|
|
||||||
- `"Ripple": { "colour": <colour>, "speed": <speed> },`
|
|
||||||
- `"Highlight": { "colour": <colour>, "speed": <speed> },`
|
|
||||||
- `"Rainbow": { "direction": <direction>, "speed": <speed> },`
|
|
||||||
- `"Breathe": { "colour": <colour>, "colour2": <colour>, "speed": <speed> },`
|
|
||||||
- `"Star": { "colour": <colour>, "colour2": <colour>, "speed": <speed> },`
|
|
||||||
- `"MultiStatic": { "colour1": <colour>, "colour2": <colour>, , "colour3": <colour>, "colour4": <colour> },`
|
|
||||||
|
|
||||||
Additionally to the above there is `"RGB": [[u8; 64]; 11]` which is for per-key
|
|
||||||
setting of LED's but this requires some refactoring to make it easily useable over
|
|
||||||
dbus.
|
|
||||||
|
|
||||||
Lastly, there is `"LedBrightness": <u8>` which accepts 0-3 for off, low, med, high.
|
|
||||||
|
|
||||||
### SetFanMode
|
|
||||||
|
|
||||||
Accepts an integer from the following:
|
|
||||||
|
|
||||||
- `0`: Normal
|
|
||||||
- `1`: Boost mode
|
|
||||||
- `2`: Silent mode
|
|
||||||
|
|
||||||
## dbus-send examples:
|
|
||||||
|
|
||||||
```
|
|
||||||
dbus-send --system --type=method_call --dest=org.asuslinux.Daemon /org/asuslinux/Profile org.asuslinux.Daemon.NextProfile
|
|
||||||
```
|
|
||||||
|
|
||||||
## dbus-send examples OUTDATED
|
|
||||||
|
|
||||||
```
|
|
||||||
dbus-send --system --type=method_call --dest=org.asuslinux.Daemon /org/asuslinux/Daemon org.asuslinux.Daemon.SetKeyBacklight string:'{"Static": {"colour": [ 80, 0, 40]}}'
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
dbus-send --system --type=method_call --dest=org.asuslinux.Daemon /org/asuslinux/Daemon org.asuslinux.Daemon.SetKeyBacklight string:'{"Star":{"colour":[0,255,255],"colour2":[0,0,0],"speed":"Med"}}'
|
|
||||||
```
|
|
||||||
|
|
||||||
**Note:** setting colour2 to `[0,0,255]` activates random star colour. Colour2 has no effect on the
|
|
||||||
mode otherwise.
|
|
||||||
```
|
|
||||||
dbus-send --system --type=method_call --dest=org.asuslinux.Daemon /org/asuslinux/Daemon org.asuslinux.Daemon.SetKeyBacklight string:'{"Star":{"colour":[0,255,255],"colour2":[0,0,255],"speed":"Med"}}'
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
dbus-send --system --type=method_call --dest=org.asuslinux.Daemon /org/asuslinux/Daemon org.asuslinux.Daemon.SetKeyBacklight string:'{"LedBrightness":3}'
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
dbus-send --system --type=method_call --dest=org.asuslinux.Daemon /org/asuslinux/Daemon org.asuslinux.Daemon.SetFanMode byte:'2'
|
|
||||||
```
|
|
||||||
|
|
||||||
Monitoring dbus while sending commands via `rog-core` will give you the json structure if you are otherwise unsure, e.g: `dbus-monitor --system |grep -A2 asuslinux`.
|
|
||||||
|
|
||||||
## Getting an introspection .xml
|
|
||||||
|
|
||||||
```
|
|
||||||
dbus-send --system --print-reply --dest=org.asuslinux.Daemon /org/asuslinux/Charge org.freedesktop.DBus.Introspectable.Introspect > xml/asusd-charge.xml
|
|
||||||
```
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
# TODO
|
|
||||||
|
|
||||||
- There is lots of code duplication. This should be turned in to macros (dbus stuff etc)
|
|
||||||
- Add a little more information to profile notifications such as freq min/max, fan curves
|
|
||||||
- Finish splitting out controllers to own crates
|
|
||||||
- Finish move to zbus in client when zbus has client signal watch
|
|
||||||
- Consider a rename again because the project is getting a lot less ASUS centric
|
|
||||||
@@ -10,9 +10,10 @@ edition = "2018"
|
|||||||
# serialisation
|
# serialisation
|
||||||
serde_json = "^1.0"
|
serde_json = "^1.0"
|
||||||
rog_dbus = { path = "../rog-dbus" }
|
rog_dbus = { path = "../rog-dbus" }
|
||||||
|
rog_types = { path = "../rog-types" }
|
||||||
daemon = { path = "../daemon" }
|
daemon = { path = "../daemon" }
|
||||||
|
|
||||||
[dependencies.notify-rust]
|
[dependencies.notify-rust]
|
||||||
version = "^4.0"
|
version = "^4.3"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["z"]
|
features = ["z"]
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
use daemon::config::Profile;
|
|
||||||
use notify_rust::{Hint, Notification, NotificationHandle};
|
use notify_rust::{Hint, Notification, NotificationHandle};
|
||||||
use rog_dbus::{DbusProxies, Signals};
|
use rog_dbus::{DbusProxies, Signals};
|
||||||
|
use rog_types::profile::Profile;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
use std::thread::sleep;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
@@ -9,9 +10,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
println!(" daemon version {}", daemon::VERSION);
|
println!(" daemon version {}", daemon::VERSION);
|
||||||
println!(" rog-dbus version {}", rog_dbus::VERSION);
|
println!(" rog-dbus version {}", rog_dbus::VERSION);
|
||||||
|
|
||||||
// let mut cfg = Config::read_new()?;
|
|
||||||
// let mut last_profile = String::new();
|
|
||||||
|
|
||||||
let (proxies, conn) = DbusProxies::new()?;
|
let (proxies, conn) = DbusProxies::new()?;
|
||||||
let signals = Signals::new(&proxies)?;
|
let signals = Signals::new(&proxies)?;
|
||||||
|
|
||||||
@@ -21,9 +19,22 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
let mut last_chrg_notif: Option<NotificationHandle> = None;
|
let mut last_chrg_notif: Option<NotificationHandle> = None;
|
||||||
|
|
||||||
let recv = proxies.setup_recv(conn);
|
let recv = proxies.setup_recv(conn);
|
||||||
|
let mut err_count = 0;
|
||||||
loop {
|
loop {
|
||||||
std::thread::sleep(Duration::from_millis(100));
|
sleep(Duration::from_millis(100));
|
||||||
recv.next_signal().unwrap();
|
if let Err(err) = recv.next_signal() {
|
||||||
|
if err_count < 3 {
|
||||||
|
err_count += 1;
|
||||||
|
println!("{}", err);
|
||||||
|
}
|
||||||
|
if err_count == 3 {
|
||||||
|
err_count += 1;
|
||||||
|
println!("Max error count reached. Spooling silently.");
|
||||||
|
}
|
||||||
|
sleep(Duration::from_millis(2000));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
err_count = 0;
|
||||||
|
|
||||||
if let Ok(mut lock) = signals.gfx_vendor.lock() {
|
if let Ok(mut lock) = signals.gfx_vendor.lock() {
|
||||||
if let Some(vendor) = lock.take() {
|
if let Some(vendor) = lock.take() {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "asusctl"
|
name = "asusctl"
|
||||||
version = "3.1.4"
|
version = "3.5.0"
|
||||||
authors = ["Luke D Jones <luke@ljones.dev>"]
|
authors = ["Luke D Jones <luke@ljones.dev>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
@@ -9,13 +9,16 @@ edition = "2018"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
# serialisation
|
# serialisation
|
||||||
serde_json = "^1.0"
|
serde_json = "^1.0"
|
||||||
|
rog_anime = { path = "../rog-anime" }
|
||||||
|
rog_aura = { path = "../rog-aura" }
|
||||||
rog_dbus = { path = "../rog-dbus" }
|
rog_dbus = { path = "../rog-dbus" }
|
||||||
rog_types = { path = "../rog-types" }
|
rog_types = { path = "../rog-types" }
|
||||||
daemon = { path = "../daemon" }
|
daemon = { path = "../daemon" }
|
||||||
gumdrop = "^0.8"
|
gumdrop = "^0.8"
|
||||||
yansi-term = "^0.1"
|
yansi-term = "^0.1"
|
||||||
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tinybmp = "^0.2.3"
|
tinybmp = "^0.2.3"
|
||||||
rog_dbus = { path = "../rog-dbus" }
|
glam = "0.14.0"
|
||||||
|
rog_dbus = { path = "../rog-dbus" }
|
||||||
|
gif = "^0.11.2"
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
use rog_dbus::AuraDbusClient;
|
|
||||||
use rog_types::anime_matrix::{AniMeImageBuffer, AniMePacketType, HEIGHT, WIDTH};
|
|
||||||
use tinybmp::{Bmp, Pixel};
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let (client, _) = AuraDbusClient::new().unwrap();
|
|
||||||
|
|
||||||
let bmp =
|
|
||||||
Bmp::from_slice(include_bytes!("non-skewed_r.bmp")).expect("Failed to parse BMP image");
|
|
||||||
let pixels: Vec<Pixel> = bmp.into_iter().collect();
|
|
||||||
//assert_eq!(pixels.len(), 56 * 56);
|
|
||||||
|
|
||||||
// Try an outline, top and right
|
|
||||||
let mut matrix = AniMeImageBuffer::new();
|
|
||||||
|
|
||||||
// Aligned left
|
|
||||||
for (i, px) in pixels.iter().enumerate() {
|
|
||||||
if (px.x as usize / 2) < WIDTH && (px.y as usize) < HEIGHT && px.x % 2 == 0 {
|
|
||||||
let mut c = px.color as u32;
|
|
||||||
matrix.get_mut()[px.y as usize][px.x as usize / 2] = c as u8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Throw an alignment border up
|
|
||||||
// {
|
|
||||||
// let tmp = matrix.get_mut();
|
|
||||||
// for x in tmp[0].iter_mut() {
|
|
||||||
// *x = 0xff;
|
|
||||||
// }
|
|
||||||
// for row in tmp.iter_mut() {
|
|
||||||
// row[row.len() - 1] = 0xff;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
matrix.debug_print();
|
|
||||||
|
|
||||||
let mut matrix: AniMePacketType = AniMePacketType::from(matrix);
|
|
||||||
// println!("{:?}", matrix[0].to_vec());
|
|
||||||
// println!("{:?}", matrix[1].to_vec());
|
|
||||||
|
|
||||||
//client.proxies().anime().set_brightness(&mut matrix).unwrap();
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
use std::{env, error::Error, path::Path, process::exit};
|
||||||
|
|
||||||
|
use rog_anime::{AnimeDataBuffer, AnimeDiagonal};
|
||||||
|
use rog_dbus::AuraDbusClient;
|
||||||
|
|
||||||
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
let (client, _) = AuraDbusClient::new().unwrap();
|
||||||
|
|
||||||
|
let args: Vec<String> = env::args().into_iter().collect();
|
||||||
|
if args.len() != 3 {
|
||||||
|
println!("Usage: <filepath> <brightness>");
|
||||||
|
println!("e.g, asusctl/examples/doom_large.png 0.8");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
let matrix =
|
||||||
|
AnimeDiagonal::from_png(Path::new(&args[1]), None, args[2].parse::<f32>().unwrap())?;
|
||||||
|
|
||||||
|
client
|
||||||
|
.proxies()
|
||||||
|
.anime()
|
||||||
|
.write(<AnimeDataBuffer>::from(&matrix))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
use std::{thread::sleep, time::Duration};
|
||||||
|
|
||||||
|
use rog_anime::{AnimeDataBuffer, AnimeDiagonal};
|
||||||
|
use rog_dbus::AuraDbusClient;
|
||||||
|
|
||||||
|
// In usable data:
|
||||||
|
// Top row start at 1, ends at 32
|
||||||
|
|
||||||
|
// 74w x 36h diagonal used by the windows app
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let (client, _) = AuraDbusClient::new().unwrap();
|
||||||
|
|
||||||
|
for step in (2..50).rev() {
|
||||||
|
let mut matrix = AnimeDiagonal::new(None);
|
||||||
|
for c in (0..60).into_iter().step_by(step) {
|
||||||
|
for i in matrix.get_mut().iter_mut() {
|
||||||
|
i[c] = 50;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for c in (0..35).into_iter().step_by(step) {
|
||||||
|
for i in matrix.get_mut()[c].iter_mut() {
|
||||||
|
*i = 50;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let m = <AnimeDataBuffer>::from(&matrix);
|
||||||
|
client.proxies().anime().write(m).unwrap();
|
||||||
|
sleep(Duration::from_millis(300));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
use std::{env, path::Path, thread::sleep};
|
||||||
|
|
||||||
|
use rog_anime::{ActionData, AnimeAction, Sequences};
|
||||||
|
use rog_dbus::AuraDbusClient;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let (client, _) = AuraDbusClient::new().unwrap();
|
||||||
|
|
||||||
|
let args: Vec<String> = env::args().into_iter().collect();
|
||||||
|
if args.len() != 3 {
|
||||||
|
println!("Please supply filepath and brightness");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let path = Path::new(&args[1]);
|
||||||
|
let brightness = args[2].parse::<f32>().unwrap();
|
||||||
|
let mut seq = Sequences::new();
|
||||||
|
seq.insert(
|
||||||
|
0,
|
||||||
|
&AnimeAction::AsusAnimation {
|
||||||
|
file: path.into(),
|
||||||
|
time: rog_anime::AnimTime::Infinite,
|
||||||
|
brightness,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
for action in seq.iter() {
|
||||||
|
if let ActionData::Animation(frames) = action {
|
||||||
|
for frame in frames.frames() {
|
||||||
|
client
|
||||||
|
.proxies()
|
||||||
|
.anime()
|
||||||
|
.write(frame.frame().clone())
|
||||||
|
.unwrap();
|
||||||
|
sleep(frame.delay());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
use rog_anime::{AnimeDataBuffer, AnimeGrid};
|
||||||
|
use rog_dbus::AuraDbusClient;
|
||||||
|
|
||||||
|
// In usable data:
|
||||||
|
// Top row start at 1, ends at 32
|
||||||
|
|
||||||
|
// 74w x 36h diagonal used by the windows app
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let (client, _) = AuraDbusClient::new().unwrap();
|
||||||
|
let mut matrix = AnimeGrid::new(None);
|
||||||
|
let tmp = matrix.get_mut();
|
||||||
|
|
||||||
|
let mut i = 0;
|
||||||
|
for (y, row) in tmp.iter_mut().enumerate() {
|
||||||
|
if y % 2 == 0 && i + 1 != row.len() - 1 {
|
||||||
|
i += 1;
|
||||||
|
dbg!(i);
|
||||||
|
}
|
||||||
|
row[row.len() - i] = 0x22;
|
||||||
|
if i > 5 {
|
||||||
|
row[row.len() - i + 5] = 0x22;
|
||||||
|
}
|
||||||
|
if i > 10 {
|
||||||
|
row[row.len() - i + 10] = 0x22;
|
||||||
|
}
|
||||||
|
|
||||||
|
if i > 15 {
|
||||||
|
row[row.len() - i + 15] = 0x22;
|
||||||
|
}
|
||||||
|
|
||||||
|
if i > 20 {
|
||||||
|
row[row.len() - i + 20] = 0x22;
|
||||||
|
}
|
||||||
|
|
||||||
|
if i > 25 {
|
||||||
|
row[row.len() - i + 25] = 0x22;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let matrix = <AnimeDataBuffer>::from(matrix);
|
||||||
|
|
||||||
|
client.proxies().anime().write(matrix).unwrap();
|
||||||
|
}
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
use rog_anime::AnimeDataBuffer;
|
||||||
|
use rog_dbus::AuraDbusClient;
|
||||||
|
|
||||||
|
// In usable data:
|
||||||
|
// Top row start at 1, ends at 32
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let (client, _) = AuraDbusClient::new().unwrap();
|
||||||
|
let mut matrix = AnimeDataBuffer::new();
|
||||||
|
matrix.get_mut()[1] = 100; // start = 1
|
||||||
|
for n in matrix.get_mut()[2..32].iter_mut() {
|
||||||
|
*n = 250;
|
||||||
|
}
|
||||||
|
matrix.get_mut()[32] = 100; // end
|
||||||
|
matrix.get_mut()[34] = 100; // start x = 0
|
||||||
|
matrix.get_mut()[66] = 100; // end
|
||||||
|
matrix.get_mut()[69] = 100; // start x = 1
|
||||||
|
matrix.get_mut()[101] = 100; // end
|
||||||
|
matrix.get_mut()[102] = 100; // start
|
||||||
|
matrix.get_mut()[134] = 100; // end
|
||||||
|
matrix.get_mut()[137] = 100; // start
|
||||||
|
matrix.get_mut()[169] = 100; // end
|
||||||
|
matrix.get_mut()[170] = 100; // start
|
||||||
|
matrix.get_mut()[202] = 100; // end
|
||||||
|
matrix.get_mut()[204] = 100; // start
|
||||||
|
matrix.get_mut()[236] = 100; // end
|
||||||
|
matrix.get_mut()[237] = 100; // start
|
||||||
|
matrix.get_mut()[268] = 100; // end
|
||||||
|
matrix.get_mut()[270] = 100; // start
|
||||||
|
matrix.get_mut()[301] = 100; // end
|
||||||
|
matrix.get_mut()[302] = 100; // start
|
||||||
|
matrix.get_mut()[332] = 100; // end
|
||||||
|
matrix.get_mut()[334] = 100; // start
|
||||||
|
matrix.get_mut()[364] = 100; // end
|
||||||
|
matrix.get_mut()[365] = 100; // start
|
||||||
|
matrix.get_mut()[394] = 100; // end
|
||||||
|
matrix.get_mut()[396] = 100; // start
|
||||||
|
matrix.get_mut()[425] = 100; // end
|
||||||
|
matrix.get_mut()[426] = 100; // start
|
||||||
|
matrix.get_mut()[454] = 100; // end
|
||||||
|
matrix.get_mut()[456] = 100; // start
|
||||||
|
matrix.get_mut()[484] = 100; // end
|
||||||
|
matrix.get_mut()[485] = 100; // start
|
||||||
|
matrix.get_mut()[512] = 100; // end
|
||||||
|
matrix.get_mut()[514] = 100; // start
|
||||||
|
matrix.get_mut()[541] = 100; // end
|
||||||
|
matrix.get_mut()[542] = 100; // start
|
||||||
|
matrix.get_mut()[568] = 100; // end
|
||||||
|
matrix.get_mut()[570] = 100; // start
|
||||||
|
matrix.get_mut()[596] = 100; // end
|
||||||
|
matrix.get_mut()[597] = 100; // start
|
||||||
|
matrix.get_mut()[622] = 100; // end
|
||||||
|
matrix.get_mut()[624] = 100; // start
|
||||||
|
matrix.get_mut()[649] = 100; // end
|
||||||
|
matrix.get_mut()[650] = 100; // start
|
||||||
|
matrix.get_mut()[674] = 100; // end
|
||||||
|
matrix.get_mut()[676] = 100; // start
|
||||||
|
matrix.get_mut()[700] = 100; // end
|
||||||
|
matrix.get_mut()[701] = 100; // start
|
||||||
|
matrix.get_mut()[724] = 100; // end
|
||||||
|
matrix.get_mut()[726] = 100; // start
|
||||||
|
matrix.get_mut()[749] = 100; // end
|
||||||
|
matrix.get_mut()[750] = 100; // start
|
||||||
|
matrix.get_mut()[772] = 100; // end
|
||||||
|
matrix.get_mut()[774] = 100; // start
|
||||||
|
matrix.get_mut()[796] = 100; // end
|
||||||
|
matrix.get_mut()[797] = 100; // start
|
||||||
|
matrix.get_mut()[818] = 100; // end
|
||||||
|
matrix.get_mut()[820] = 100; // start
|
||||||
|
matrix.get_mut()[841] = 100; // end
|
||||||
|
matrix.get_mut()[842] = 100; // start
|
||||||
|
matrix.get_mut()[862] = 100; // end
|
||||||
|
matrix.get_mut()[864] = 100; // start
|
||||||
|
matrix.get_mut()[884] = 100; // end
|
||||||
|
matrix.get_mut()[885] = 100; // start
|
||||||
|
matrix.get_mut()[904] = 100; // end
|
||||||
|
matrix.get_mut()[906] = 100; // start
|
||||||
|
matrix.get_mut()[925] = 100; // end
|
||||||
|
matrix.get_mut()[926] = 100; // start
|
||||||
|
matrix.get_mut()[944] = 100; // end
|
||||||
|
matrix.get_mut()[946] = 100; // start
|
||||||
|
matrix.get_mut()[964] = 100; // end
|
||||||
|
matrix.get_mut()[965] = 100; // start
|
||||||
|
matrix.get_mut()[982] = 100; // end
|
||||||
|
matrix.get_mut()[984] = 100; // start
|
||||||
|
matrix.get_mut()[1001] = 100; // end
|
||||||
|
matrix.get_mut()[1002] = 100; // start
|
||||||
|
matrix.get_mut()[1018] = 100; // end
|
||||||
|
matrix.get_mut()[1020] = 100; // start
|
||||||
|
matrix.get_mut()[1036] = 100; // end
|
||||||
|
matrix.get_mut()[1037] = 100; // start
|
||||||
|
matrix.get_mut()[1052] = 100; // end
|
||||||
|
matrix.get_mut()[1054] = 100; // start
|
||||||
|
matrix.get_mut()[1069] = 100; // end
|
||||||
|
matrix.get_mut()[1070] = 100; // start
|
||||||
|
matrix.get_mut()[1084] = 100; // end
|
||||||
|
matrix.get_mut()[1086] = 100; // start
|
||||||
|
matrix.get_mut()[1100] = 100; // end
|
||||||
|
matrix.get_mut()[1101] = 100; // start
|
||||||
|
matrix.get_mut()[1114] = 100; // end
|
||||||
|
matrix.get_mut()[1116] = 100; // start
|
||||||
|
matrix.get_mut()[1129] = 100; // end
|
||||||
|
matrix.get_mut()[1130] = 100; // start
|
||||||
|
matrix.get_mut()[1142] = 100; // end
|
||||||
|
matrix.get_mut()[1144] = 100; // start
|
||||||
|
matrix.get_mut()[1156] = 100; // end
|
||||||
|
matrix.get_mut()[1157] = 100; // start
|
||||||
|
matrix.get_mut()[1168] = 100; // end
|
||||||
|
matrix.get_mut()[1170] = 100; // start
|
||||||
|
matrix.get_mut()[1181] = 100; // end
|
||||||
|
matrix.get_mut()[1182] = 100; // start
|
||||||
|
matrix.get_mut()[1192] = 100; // end
|
||||||
|
matrix.get_mut()[1194] = 100; // start
|
||||||
|
matrix.get_mut()[1204] = 100; // end
|
||||||
|
matrix.get_mut()[1205] = 100; // start
|
||||||
|
matrix.get_mut()[1214] = 100; // end
|
||||||
|
matrix.get_mut()[1216] = 100; // start
|
||||||
|
matrix.get_mut()[1225] = 100; // end
|
||||||
|
matrix.get_mut()[1226] = 100; // start
|
||||||
|
matrix.get_mut()[1234] = 100; // end
|
||||||
|
matrix.get_mut()[1236] = 100; // start
|
||||||
|
for n in matrix.get_mut()[1237..1244].iter_mut() {
|
||||||
|
*n = 250;
|
||||||
|
}
|
||||||
|
matrix.get_mut()[1244] = 100; // end
|
||||||
|
println!("{:?}", &matrix);
|
||||||
|
|
||||||
|
client.proxies().anime().write(matrix).unwrap();
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
use std::{env, error::Error, path::Path, process::exit};
|
||||||
|
|
||||||
|
use rog_anime::{
|
||||||
|
AnimeDataBuffer, {AnimeImage, Vec2},
|
||||||
|
};
|
||||||
|
use rog_dbus::AuraDbusClient;
|
||||||
|
|
||||||
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
let (client, _) = AuraDbusClient::new().unwrap();
|
||||||
|
|
||||||
|
let args: Vec<String> = env::args().into_iter().collect();
|
||||||
|
if args.len() != 7 {
|
||||||
|
println!("Usage: <filepath> <scale> <angle> <x pos> <y pos> <brightness>");
|
||||||
|
println!("e.g, asusctl/examples/doom_large.png 0.9 0.4 0.0 0.0 0.8");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
let matrix = AnimeImage::from_png(
|
||||||
|
Path::new(&args[1]),
|
||||||
|
args[2].parse::<f32>().unwrap(),
|
||||||
|
args[3].parse::<f32>().unwrap(),
|
||||||
|
Vec2::new(
|
||||||
|
args[4].parse::<f32>().unwrap(),
|
||||||
|
args[5].parse::<f32>().unwrap(),
|
||||||
|
),
|
||||||
|
args[6].parse::<f32>().unwrap(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
client
|
||||||
|
.proxies()
|
||||||
|
.anime()
|
||||||
|
.write(<AnimeDataBuffer>::from(&matrix))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
use std::{
|
||||||
|
env, error::Error, f32::consts::PI, path::Path, process::exit, thread::sleep, time::Duration,
|
||||||
|
};
|
||||||
|
|
||||||
|
use rog_anime::{
|
||||||
|
AnimeDataBuffer, {AnimeImage, Vec2},
|
||||||
|
};
|
||||||
|
use rog_dbus::AuraDbusClient;
|
||||||
|
|
||||||
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
let (client, _) = AuraDbusClient::new().unwrap();
|
||||||
|
|
||||||
|
let args: Vec<String> = env::args().into_iter().collect();
|
||||||
|
if args.len() != 7 {
|
||||||
|
println!("Usage: <filepath> <scale> <angle> <x pos> <y pos> <brightness>");
|
||||||
|
println!("e.g, asusctl/examples/doom_large.png 0.9 0.4 0.0 0.0 0.8");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut matrix = AnimeImage::from_png(
|
||||||
|
Path::new(&args[1]),
|
||||||
|
args[2].parse::<f32>().unwrap(),
|
||||||
|
args[3].parse::<f32>().unwrap(),
|
||||||
|
Vec2::new(
|
||||||
|
args[4].parse::<f32>().unwrap(),
|
||||||
|
args[5].parse::<f32>().unwrap(),
|
||||||
|
),
|
||||||
|
args[6].parse::<f32>().unwrap(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
matrix.angle += 0.05;
|
||||||
|
if matrix.angle > PI * 2.0 {
|
||||||
|
matrix.angle = 0.0
|
||||||
|
}
|
||||||
|
matrix.update();
|
||||||
|
|
||||||
|
client
|
||||||
|
.proxies()
|
||||||
|
.anime()
|
||||||
|
.write(<AnimeDataBuffer>::from(&matrix))
|
||||||
|
.unwrap();
|
||||||
|
sleep(Duration::from_micros(500));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
|
use rog_aura::{GX502Layout, Key, KeyColourArray, KeyLayout};
|
||||||
use rog_dbus::AuraDbusClient;
|
use rog_dbus::AuraDbusClient;
|
||||||
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_aura::{GX502Layout, KeyColourArray, KeyLayout};
|
||||||
use rog_dbus::AuraDbusClient;
|
use rog_dbus::AuraDbusClient;
|
||||||
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_aura::{GX502Layout, Key, KeyColourArray, KeyLayout};
|
||||||
use rog_dbus::AuraDbusClient;
|
use rog_dbus::AuraDbusClient;
|
||||||
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_aura::{Key, KeyColourArray};
|
||||||
use rog_dbus::AuraDbusClient;
|
use rog_dbus::AuraDbusClient;
|
||||||
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()?;
|
||||||
@@ -10,7 +10,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
loop {
|
loop {
|
||||||
let count = 49;
|
let count = 49;
|
||||||
for _ in 0..count {
|
for _ in 0..count {
|
||||||
*key_colours.key(Key::ROG).unwrap().0 += 5;
|
*key_colours.key(Key::Rog).unwrap().0 += 5;
|
||||||
*key_colours.key(Key::L).unwrap().0 += 5;
|
*key_colours.key(Key::L).unwrap().0 += 5;
|
||||||
*key_colours.key(Key::I).unwrap().0 += 5;
|
*key_colours.key(Key::I).unwrap().0 += 5;
|
||||||
*key_colours.key(Key::N).unwrap().0 += 5;
|
*key_colours.key(Key::N).unwrap().0 += 5;
|
||||||
@@ -19,7 +19,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
dbus.proxies().led().set_per_key(&key_colours)?;
|
dbus.proxies().led().set_per_key(&key_colours)?;
|
||||||
}
|
}
|
||||||
for _ in 0..count {
|
for _ in 0..count {
|
||||||
*key_colours.key(Key::ROG).unwrap().0 -= 5;
|
*key_colours.key(Key::Rog).unwrap().0 -= 5;
|
||||||
*key_colours.key(Key::L).unwrap().0 -= 5;
|
*key_colours.key(Key::L).unwrap().0 -= 5;
|
||||||
*key_colours.key(Key::I).unwrap().0 -= 5;
|
*key_colours.key(Key::I).unwrap().0 -= 5;
|
||||||
*key_colours.key(Key::N).unwrap().0 -= 5;
|
*key_colours.key(Key::N).unwrap().0 -= 5;
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
|
use rog_aura::{GX502Layout, KeyColourArray, KeyLayout};
|
||||||
use rog_dbus::AuraDbusClient;
|
use rog_dbus::AuraDbusClient;
|
||||||
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()?;
|
||||||
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 140 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 7.6 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 7.6 KiB |
@@ -0,0 +1,92 @@
|
|||||||
|
use gumdrop::Options;
|
||||||
|
use rog_aura::error::Error;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub enum AnimeStatusValue {
|
||||||
|
On,
|
||||||
|
Off,
|
||||||
|
}
|
||||||
|
impl FromStr for AnimeStatusValue {
|
||||||
|
type Err = Error;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
let s = s.to_lowercase();
|
||||||
|
match s.as_str() {
|
||||||
|
"on" => Ok(AnimeStatusValue::On),
|
||||||
|
"off" => Ok(AnimeStatusValue::Off),
|
||||||
|
_ => {
|
||||||
|
print!("Invalid argument, must be one of: on, off");
|
||||||
|
Err(Error::ParseAnime)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<AnimeStatusValue> for bool {
|
||||||
|
fn from(value: AnimeStatusValue) -> Self {
|
||||||
|
match value {
|
||||||
|
AnimeStatusValue::On => true,
|
||||||
|
AnimeStatusValue::Off => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Options)]
|
||||||
|
pub struct AnimeLeds {
|
||||||
|
#[options(help = "print help message")]
|
||||||
|
help: bool,
|
||||||
|
#[options(
|
||||||
|
no_long,
|
||||||
|
required,
|
||||||
|
short = "b",
|
||||||
|
meta = "",
|
||||||
|
help = "set all leds brightness value"
|
||||||
|
)]
|
||||||
|
led_brightness: u8,
|
||||||
|
}
|
||||||
|
impl AnimeLeds {
|
||||||
|
pub fn led_brightness(&self) -> u8 {
|
||||||
|
self.led_brightness
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Options)]
|
||||||
|
pub struct AnimeCommand {
|
||||||
|
#[options(help = "print help message")]
|
||||||
|
pub help: bool,
|
||||||
|
#[options(
|
||||||
|
meta = "",
|
||||||
|
help = "turn on/off the panel (accept/reject write requests)"
|
||||||
|
)]
|
||||||
|
pub turn: Option<AnimeStatusValue>,
|
||||||
|
#[options(meta = "", help = "turn on/off the panel at boot (with Asus effect)")]
|
||||||
|
pub boot: Option<AnimeStatusValue>,
|
||||||
|
#[options(command)]
|
||||||
|
pub command: Option<AnimeActions>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Options)]
|
||||||
|
pub enum AnimeActions {
|
||||||
|
#[options(help = "change all leds brightness")]
|
||||||
|
Leds(AnimeLeds),
|
||||||
|
#[options(help = "display an 8bit greyscale png")]
|
||||||
|
Image(AnimeImage),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Options)]
|
||||||
|
pub struct AnimeImage {
|
||||||
|
#[options(help = "print help message")]
|
||||||
|
pub help: bool,
|
||||||
|
#[options(meta = "", help = "full path to the png to display")]
|
||||||
|
pub path: String,
|
||||||
|
#[options(meta = "", default = "1.0", help = "scale 1.0 == normal")]
|
||||||
|
pub scale: f32,
|
||||||
|
#[options(meta = "", default = "0.0", help = "x position (float)")]
|
||||||
|
pub x_pos: f32,
|
||||||
|
#[options(meta = "", default = "0.0", help = "y position (float)")]
|
||||||
|
pub y_pos: f32,
|
||||||
|
#[options(meta = "", default = "0.0", help = "the angle in radians")]
|
||||||
|
pub angle: f32,
|
||||||
|
#[options(meta = "", default = "1.0", help = "brightness 0.0-1.0")]
|
||||||
|
pub bright: f32,
|
||||||
|
}
|
||||||
@@ -1,8 +1,5 @@
|
|||||||
use gumdrop::Options;
|
use gumdrop::Options;
|
||||||
use rog_types::{
|
use rog_aura::{error::Error, AuraEffect, AuraModeNum, AuraZone, Colour, Direction, Speed};
|
||||||
aura_modes::{AuraEffect, AuraModeNum, AuraZone, Colour, Direction, Speed},
|
|
||||||
error::AuraError,
|
|
||||||
};
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
#[derive(Options)]
|
#[derive(Options)]
|
||||||
@@ -19,7 +16,7 @@ impl LedBrightness {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl FromStr for LedBrightness {
|
impl FromStr for LedBrightness {
|
||||||
type Err = AuraError;
|
type Err = Error;
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
let s = s.to_lowercase();
|
let s = s.to_lowercase();
|
||||||
@@ -30,7 +27,7 @@ impl FromStr for LedBrightness {
|
|||||||
"high" => Ok(LedBrightness { level: Some(0x03) }),
|
"high" => Ok(LedBrightness { level: Some(0x03) }),
|
||||||
_ => {
|
_ => {
|
||||||
print!("Invalid argument, must be one of: off, low, med, high");
|
print!("Invalid argument, must be one of: off, low, med, high");
|
||||||
Err(AuraError::ParseBrightness)
|
Err(Error::ParseBrightness)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,26 @@
|
|||||||
|
mod anime_cli;
|
||||||
mod aura_cli;
|
mod aura_cli;
|
||||||
|
|
||||||
use crate::aura_cli::{LedBrightness, SetAuraBuiltin};
|
use crate::aura_cli::{LedBrightness, SetAuraBuiltin};
|
||||||
use daemon::{
|
use anime_cli::{AnimeActions, AnimeCommand};
|
||||||
ctrl_fan_cpu::FanCpuSupportedFunctions, ctrl_leds::LedSupportedFunctions,
|
|
||||||
ctrl_rog_bios::RogBiosSupportedFunctions, ctrl_supported::SupportedFunctions,
|
|
||||||
};
|
|
||||||
use gumdrop::{Opt, Options};
|
use gumdrop::{Opt, Options};
|
||||||
|
use rog_anime::{AnimeDataBuffer, AnimeImage, Vec2, ANIME_DATA_LEN};
|
||||||
|
use rog_aura::{self, AuraEffect};
|
||||||
use rog_dbus::AuraDbusClient;
|
use rog_dbus::AuraDbusClient;
|
||||||
use rog_types::{
|
use rog_types::{
|
||||||
anime_matrix::{AniMeDataBuffer, FULL_PANE_LEN},
|
|
||||||
aura_modes::{self, AuraEffect, AuraModeNum},
|
|
||||||
cli_options::{AniMeActions, AniMeStatusValue},
|
|
||||||
gfx_vendors::GfxVendors,
|
gfx_vendors::GfxVendors,
|
||||||
profile::{FanLevel, ProfileCommand, ProfileEvent},
|
profile::{FanLevel, ProfileCommand, ProfileEvent},
|
||||||
|
supported::{
|
||||||
|
FanCpuSupportedFunctions, LedSupportedFunctions, RogBiosSupportedFunctions,
|
||||||
|
SupportedFunctions,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use std::env::args;
|
use std::{env::args, path::Path};
|
||||||
use yansi_term::Colour::Green;
|
use yansi_term::Colour::Green;
|
||||||
use yansi_term::Colour::Red;
|
use yansi_term::Colour::Red;
|
||||||
|
|
||||||
#[derive(Default, Options)]
|
#[derive(Default, Options)]
|
||||||
struct CLIStart {
|
struct CliStart {
|
||||||
#[options(help_flag, help = "print help message")]
|
#[options(help_flag, help = "print help message")]
|
||||||
help: bool,
|
help: bool,
|
||||||
#[options(help = "show program version number")]
|
#[options(help = "show program version number")]
|
||||||
@@ -48,7 +49,7 @@ enum CliCommand {
|
|||||||
#[options(help = "Set the graphics mode")]
|
#[options(help = "Set the graphics mode")]
|
||||||
Graphics(GraphicsCommand),
|
Graphics(GraphicsCommand),
|
||||||
#[options(name = "anime", help = "Manage AniMe Matrix")]
|
#[options(name = "anime", help = "Manage AniMe Matrix")]
|
||||||
AniMe(AniMeCommand),
|
Anime(AnimeCommand),
|
||||||
#[options(help = "Change bios settings")]
|
#[options(help = "Change bios settings")]
|
||||||
Bios(BiosCommand),
|
Bios(BiosCommand),
|
||||||
}
|
}
|
||||||
@@ -61,6 +62,16 @@ struct LedModeCommand {
|
|||||||
next_mode: bool,
|
next_mode: bool,
|
||||||
#[options(help = "switch to previous aura mode")]
|
#[options(help = "switch to previous aura mode")]
|
||||||
prev_mode: bool,
|
prev_mode: bool,
|
||||||
|
#[options(
|
||||||
|
meta = "",
|
||||||
|
help = "set the keyboard LED to enabled while the device is awake"
|
||||||
|
)]
|
||||||
|
awake_enable: Option<bool>,
|
||||||
|
#[options(
|
||||||
|
meta = "",
|
||||||
|
help = "set the keyboard LED suspend animation to enabled while the device is suspended"
|
||||||
|
)]
|
||||||
|
sleep_enable: Option<bool>,
|
||||||
#[options(command)]
|
#[options(command)]
|
||||||
command: Option<SetAuraBuiltin>,
|
command: Option<SetAuraBuiltin>,
|
||||||
}
|
}
|
||||||
@@ -82,21 +93,6 @@ struct GraphicsCommand {
|
|||||||
force: bool,
|
force: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Options)]
|
|
||||||
struct AniMeCommand {
|
|
||||||
#[options(help = "print help message")]
|
|
||||||
help: bool,
|
|
||||||
#[options(
|
|
||||||
meta = "",
|
|
||||||
help = "turn on/off the panel (accept/reject write requests)"
|
|
||||||
)]
|
|
||||||
turn: Option<AniMeStatusValue>,
|
|
||||||
#[options(meta = "", help = "turn on/off the panel at boot (with Asus effect)")]
|
|
||||||
boot: Option<AniMeStatusValue>,
|
|
||||||
#[options(command)]
|
|
||||||
command: Option<AniMeActions>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Options, Debug)]
|
#[derive(Options, Debug)]
|
||||||
struct BiosCommand {
|
struct BiosCommand {
|
||||||
#[options(help = "print help message")]
|
#[options(help = "print help message")]
|
||||||
@@ -118,14 +114,14 @@ struct BiosCommand {
|
|||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let args: Vec<String> = args().skip(1).collect();
|
let args: Vec<String> = args().skip(1).collect();
|
||||||
|
|
||||||
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'));
|
||||||
match CLIStart::parse_args_default(&args) {
|
match CliStart::parse_args_default(&args) {
|
||||||
Ok(p) => {
|
Ok(p) => {
|
||||||
parsed = p;
|
parsed = p;
|
||||||
}
|
}
|
||||||
Err(err) if err.to_string() == missing_argument_k.to_string() => {
|
Err(err) if err.to_string() == missing_argument_k.to_string() => {
|
||||||
parsed = CLIStart {
|
parsed = CliStart {
|
||||||
kbd_bright: Some(LedBrightness::new(None)),
|
kbd_bright: Some(LedBrightness::new(None)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
@@ -143,6 +139,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
|
|
||||||
if parsed.help {
|
if parsed.help {
|
||||||
print_supported_help(&supported, &parsed);
|
print_supported_help(&supported, &parsed);
|
||||||
|
println!("\nSee https://asus-linux.org/faq/ for additional help");
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,7 +155,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
Some(CliCommand::LedMode(mode)) => handle_led_mode(&dbus, &supported.keyboard_led, &mode)?,
|
Some(CliCommand::LedMode(mode)) => handle_led_mode(&dbus, &supported.keyboard_led, &mode)?,
|
||||||
Some(CliCommand::Profile(cmd)) => handle_profile(&dbus, &supported.fan_cpu_ctrl, &cmd)?,
|
Some(CliCommand::Profile(cmd)) => handle_profile(&dbus, &supported.fan_cpu_ctrl, &cmd)?,
|
||||||
Some(CliCommand::Graphics(cmd)) => do_gfx(&dbus, &supported.rog_bios_ctrl, cmd)?,
|
Some(CliCommand::Graphics(cmd)) => do_gfx(&dbus, &supported.rog_bios_ctrl, cmd)?,
|
||||||
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());
|
||||||
if let Some(lst) = cmd.self_command_list() {
|
if let Some(lst) = cmd.self_command_list() {
|
||||||
@@ -173,10 +170,33 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
}
|
}
|
||||||
if let Some(action) = cmd.command {
|
if let Some(action) = cmd.command {
|
||||||
match action {
|
match action {
|
||||||
AniMeActions::Leds(anime_leds) => {
|
AnimeActions::Leds(anime_leds) => {
|
||||||
let mut data = AniMeDataBuffer::new();
|
let data = AnimeDataBuffer::from_vec(
|
||||||
data.set([anime_leds.led_brightness(); FULL_PANE_LEN]);
|
[anime_leds.led_brightness(); ANIME_DATA_LEN].to_vec(),
|
||||||
dbus.proxies().anime().write_direct(data)?;
|
);
|
||||||
|
dbus.proxies().anime().write(data)?;
|
||||||
|
}
|
||||||
|
AnimeActions::Image(image) => {
|
||||||
|
if image.help_requested() {
|
||||||
|
println!("Missing arg or command\n\n{}", image.self_usage());
|
||||||
|
if let Some(lst) = image.self_command_list() {
|
||||||
|
println!("\n{}", lst);
|
||||||
|
}
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
let matrix = AnimeImage::from_png(
|
||||||
|
Path::new(&image.path),
|
||||||
|
image.scale,
|
||||||
|
image.angle,
|
||||||
|
Vec2::new(image.x_pos, image.y_pos),
|
||||||
|
image.bright,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
dbus.proxies()
|
||||||
|
.anime()
|
||||||
|
.write(<AnimeDataBuffer>::from(&matrix))
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -189,9 +209,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
&& parsed.chg_limit.is_none())
|
&& parsed.chg_limit.is_none())
|
||||||
|| parsed.help
|
|| parsed.help
|
||||||
{
|
{
|
||||||
println!("{}", CLIStart::usage());
|
println!("{}", CliStart::usage());
|
||||||
println!();
|
println!();
|
||||||
println!("{}", CLIStart::command_list().unwrap());
|
println!("{}", CliStart::command_list().unwrap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -205,7 +225,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
Some(level) => dbus
|
Some(level) => dbus
|
||||||
.proxies()
|
.proxies()
|
||||||
.led()
|
.led()
|
||||||
.set_led_brightness(<aura_modes::LedBrightness>::from(level))?,
|
.set_led_brightness(<rog_aura::LedBrightness>::from(level))?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,7 +243,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_supported_help(supported: &SupportedFunctions, parsed: &CLIStart) {
|
fn print_supported_help(supported: &SupportedFunctions, parsed: &CliStart) {
|
||||||
// As help option don't work with `parse_args_default`
|
// As help option don't work with `parse_args_default`
|
||||||
// we will call `parse_args_default_or_exit` instead
|
// we will call `parse_args_default_or_exit` instead
|
||||||
let usage: Vec<String> = parsed.self_usage().lines().map(|s| s.to_string()).collect();
|
let usage: Vec<String> = parsed.self_usage().lines().map(|s| s.to_string()).collect();
|
||||||
@@ -310,10 +330,11 @@ fn do_gfx(
|
|||||||
}
|
}
|
||||||
if command.pow {
|
if command.pow {
|
||||||
let res = dbus.proxies().gfx().gfx_get_pwr()?;
|
let res = dbus.proxies().gfx().gfx_get_pwr()?;
|
||||||
if res.contains("active") {
|
match res {
|
||||||
println!("Current power status: {}", Red.paint(&res));
|
rog_types::gfx_vendors::GfxPower::Active => {
|
||||||
} else {
|
println!("Current power status: {}", Red.paint(<&str>::from(&res)))
|
||||||
println!("Current power status: {}", Green.paint(&res));
|
}
|
||||||
|
_ => println!("Current power status: {}", Green.paint(<&str>::from(&res))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -324,7 +345,12 @@ fn handle_led_mode(
|
|||||||
supported: &LedSupportedFunctions,
|
supported: &LedSupportedFunctions,
|
||||||
mode: &LedModeCommand,
|
mode: &LedModeCommand,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
if mode.command.is_none() && !mode.prev_mode && !mode.next_mode {
|
if mode.command.is_none()
|
||||||
|
&& !mode.prev_mode
|
||||||
|
&& !mode.next_mode
|
||||||
|
&& mode.sleep_enable.is_none()
|
||||||
|
&& mode.awake_enable.is_none()
|
||||||
|
{
|
||||||
if !mode.help {
|
if !mode.help {
|
||||||
println!("Missing arg or command\n");
|
println!("Missing arg or command\n");
|
||||||
}
|
}
|
||||||
@@ -336,9 +362,13 @@ fn handle_led_mode(
|
|||||||
.lines()
|
.lines()
|
||||||
.map(|s| s.to_string())
|
.map(|s| s.to_string())
|
||||||
.collect();
|
.collect();
|
||||||
for command in commands.iter().filter(|mode| {
|
for command in commands.iter().filter(|command| {
|
||||||
if let Some(modes) = supported.stock_led_modes.as_ref() {
|
if let Some(modes) = supported.stock_led_modes.as_ref() {
|
||||||
return modes.contains(&<AuraModeNum>::from(mode.as_str()));
|
for mode in modes {
|
||||||
|
if command.contains(&(<&str>::from(mode)).to_lowercase()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if supported.multizone_led_mode {
|
if supported.multizone_led_mode {
|
||||||
return true;
|
return true;
|
||||||
@@ -378,6 +408,15 @@ fn handle_led_mode(
|
|||||||
.set_led_mode(&<AuraEffect>::from(mode))?,
|
.set_led_mode(&<AuraEffect>::from(mode))?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(enable) = mode.awake_enable {
|
||||||
|
dbus.proxies().led().set_awake_enabled(enable)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(enable) = mode.sleep_enable {
|
||||||
|
dbus.proxies().led().set_sleep_enabled(enable)?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,15 +426,19 @@ fn handle_profile(
|
|||||||
cmd: &ProfileCommand,
|
cmd: &ProfileCommand,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
if !cmd.next
|
if !cmd.next
|
||||||
&& !cmd.create
|
&& !cmd.create // TODO
|
||||||
&& !cmd.list
|
&& !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.profile.is_none()
|
||||||
&& cmd.turbo.is_none()
|
&& !cmd.active_name
|
||||||
|
&& !cmd.active_data
|
||||||
|
&& !cmd.profiles_data
|
||||||
|
&& cmd.remove.is_none()
|
||||||
|
&& cmd.curve.is_none() // TODO
|
||||||
|
&& cmd.fan_preset.is_none() // TODO
|
||||||
|
&& cmd.turbo.is_none() // TODO
|
||||||
|
&& cmd.max_percentage.is_none() // TODO
|
||||||
|
&& cmd.min_percentage.is_none()
|
||||||
|
// TODO
|
||||||
{
|
{
|
||||||
if !cmd.help {
|
if !cmd.help {
|
||||||
println!("Missing arg or command\n");
|
println!("Missing arg or command\n");
|
||||||
@@ -414,20 +457,69 @@ fn handle_profile(
|
|||||||
if let Some(lst) = cmd.self_command_list() {
|
if let Some(lst) = cmd.self_command_list() {
|
||||||
println!("\n{}", lst);
|
println!("\n{}", lst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
println!("Note: turbo, frequency, fan preset and fan curve options will apply to");
|
||||||
|
println!(" to the currently active profile unless a profile name is specified");
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if cmd.next {
|
if cmd.next {
|
||||||
dbus.proxies().profile().next_fan()?;
|
dbus.proxies().profile().next_fan()?;
|
||||||
} else if cmd.list {
|
}
|
||||||
let profile_names = dbus.proxies().profile().profile_names()?;
|
if let Some(profile) = &cmd.remove {
|
||||||
println!("Available profiles are {}", profile_names);
|
|
||||||
} else if let Some(profile) = &cmd.remove {
|
|
||||||
dbus.proxies().profile().remove(profile)?
|
dbus.proxies().profile().remove(profile)?
|
||||||
} else {
|
}
|
||||||
|
if cmd.list {
|
||||||
|
let profile_names = dbus.proxies().profile().profile_names()?;
|
||||||
|
println!("Available profiles are {:?}", profile_names);
|
||||||
|
}
|
||||||
|
if cmd.active_name {
|
||||||
|
println!(
|
||||||
|
"Active profile: {:?}",
|
||||||
|
dbus.proxies().profile().active_profile_name()?
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if cmd.active_data {
|
||||||
|
println!("Active profile:");
|
||||||
|
for s in dbus.proxies().profile().active_profile_data()?.lines() {
|
||||||
|
println!("{}", s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if cmd.profiles_data {
|
||||||
|
println!("Profiles:");
|
||||||
|
for s in dbus.proxies().profile().all_profile_data()?.lines() {
|
||||||
|
println!("{}", s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This must come before the next block of actions so that changing a specific
|
||||||
|
// profile can be done
|
||||||
|
if cmd.profile.is_some() {
|
||||||
dbus.proxies()
|
dbus.proxies()
|
||||||
.profile()
|
.profile()
|
||||||
.write_command(&ProfileEvent::Cli(cmd.clone()))?
|
.write_command(&ProfileEvent::Cli(cmd.clone()))?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(turbo) = cmd.turbo {
|
||||||
|
dbus.proxies().profile().set_turbo(turbo)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(min) = cmd.min_percentage {
|
||||||
|
dbus.proxies().profile().set_min_frequency(min)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(max) = cmd.max_percentage {
|
||||||
|
dbus.proxies().profile().set_max_frequency(max)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(ref preset) = cmd.fan_preset {
|
||||||
|
dbus.proxies().profile().set_fan_preset(preset.into())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(ref curve) = cmd.curve {
|
||||||
|
let s = curve.as_config_string();
|
||||||
|
dbus.proxies().profile().set_fan_curve(&s)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
[package]
|
||||||
|
name = "daemon-user"
|
||||||
|
version = "1.1.0"
|
||||||
|
authors = ["Luke D Jones <luke@ljones.dev>"]
|
||||||
|
edition = "2018"
|
||||||
|
description = "Usermode daemon for user settings, anime, per-key lighting"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "rog_user"
|
||||||
|
path = "src/lib.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "asusd-user"
|
||||||
|
path = "src/daemon.rs"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
# serialisation
|
||||||
|
serde = "^1.0"
|
||||||
|
serde_json = "^1.0"
|
||||||
|
serde_derive = "^1.0"
|
||||||
|
|
||||||
|
rog_anime = { path = "../rog-anime" }
|
||||||
|
rog_dbus = { path = "../rog-dbus" }
|
||||||
|
rog_types = { path = "../rog-types" }
|
||||||
|
|
||||||
|
dirs = "3.0.1"
|
||||||
|
|
||||||
|
zbus = "^1.9.1"
|
||||||
|
zvariant = "^2.6"
|
||||||
|
zvariant_derive = "^2.6"
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
# daemon-user
|
||||||
|
|
||||||
|
This crate is for the binary of `asusd-user` and its helper lib.
|
||||||
|
|
||||||
|
The purpose of `asusd-user` is to run in userland and provide the user + third-party apps an interface for such things as creating AniMe sequences (and more in future, see todo list).
|
||||||
|
|
||||||
|
`asusd-user` should try to be as simple as possible while allowing a decent degree of control.
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
|
||||||
|
- [ ] CLI for basic settings/interaction
|
||||||
|
- [ ] RGB keyboard per-key programs
|
||||||
|
- [ ] User profiles (fan, cpu etc). These would be replacing the system-daemon profiles only when the user is active, otherwise system-daemon defaults to system settings.
|
||||||
|
- [ ] Audio EQ visualiser - for use with anime + keyboard lighting
|
||||||
@@ -0,0 +1,341 @@
|
|||||||
|
use rog_anime::{ActionData, AnimTime, AnimeAction, Sequences, Vec2};
|
||||||
|
use rog_dbus::AuraDbusClient;
|
||||||
|
//use crate::dbus::DbusEvents;
|
||||||
|
use serde_derive::{Deserialize, Serialize};
|
||||||
|
use std::time::Duration;
|
||||||
|
use std::{
|
||||||
|
path::Path,
|
||||||
|
sync::{
|
||||||
|
atomic::{AtomicBool, Ordering},
|
||||||
|
Mutex,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use std::{sync::Arc, thread::sleep, time::Instant};
|
||||||
|
use zbus::dbus_interface;
|
||||||
|
use zvariant::ObjectPath;
|
||||||
|
use zvariant_derive::Type;
|
||||||
|
|
||||||
|
use crate::{error::Error, user_config::UserAnimeConfig};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize, Serialize, Type)]
|
||||||
|
pub enum TimeType {
|
||||||
|
Timer,
|
||||||
|
Count,
|
||||||
|
Infinite,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The inner object exists to allow the zbus proxy to share it with a runner thread
|
||||||
|
/// and a zbus server behind `Arc<Mutex<T>>`
|
||||||
|
pub struct CtrlAnimeInner<'a> {
|
||||||
|
sequences: Sequences,
|
||||||
|
client: AuraDbusClient<'a>,
|
||||||
|
do_early_return: &'a AtomicBool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> CtrlAnimeInner<'static> {
|
||||||
|
pub fn new(
|
||||||
|
sequences: Sequences,
|
||||||
|
client: AuraDbusClient<'static>,
|
||||||
|
do_early_return: &'static AtomicBool,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
Ok(Self {
|
||||||
|
sequences,
|
||||||
|
client,
|
||||||
|
do_early_return,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/// To be called on each main loop iteration to pump out commands to the anime
|
||||||
|
pub fn run(&self) -> Result<(), Error> {
|
||||||
|
if self.do_early_return.load(Ordering::SeqCst) {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
for action in self.sequences.iter() {
|
||||||
|
match action {
|
||||||
|
ActionData::Animation(frames) => {
|
||||||
|
let mut count = 0;
|
||||||
|
let start = Instant::now();
|
||||||
|
'animation: loop {
|
||||||
|
for frame in frames.frames() {
|
||||||
|
if self.do_early_return.load(Ordering::SeqCst) {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
self.client
|
||||||
|
.proxies()
|
||||||
|
.anime()
|
||||||
|
.write(frame.frame().clone())
|
||||||
|
.unwrap();
|
||||||
|
if let AnimTime::Time(time) = frames.duration() {
|
||||||
|
if Instant::now().duration_since(start) > time {
|
||||||
|
break 'animation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sleep(frame.delay());
|
||||||
|
}
|
||||||
|
if let AnimTime::Cycles(times) = frames.duration() {
|
||||||
|
count += 1;
|
||||||
|
if count >= times {
|
||||||
|
break 'animation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ActionData::Image(image) => {
|
||||||
|
self.client
|
||||||
|
.proxies()
|
||||||
|
.anime()
|
||||||
|
.write(image.as_ref().clone())
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
ActionData::Pause(duration) => {
|
||||||
|
let start = Instant::now();
|
||||||
|
'pause: loop {
|
||||||
|
if self.do_early_return.load(Ordering::SeqCst) {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
if Instant::now().duration_since(start) > *duration {
|
||||||
|
break 'pause;
|
||||||
|
}
|
||||||
|
sleep(Duration::from_millis(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ActionData::AudioEq => {}
|
||||||
|
ActionData::SystemInfo => {}
|
||||||
|
ActionData::TimeDate => {}
|
||||||
|
ActionData::Matrix => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct CtrlAnime<'a> {
|
||||||
|
config: Arc<Mutex<UserAnimeConfig>>,
|
||||||
|
client: AuraDbusClient<'a>,
|
||||||
|
inner: Arc<Mutex<CtrlAnimeInner<'a>>>,
|
||||||
|
/// Must be the same Atomic as in CtrlAnimeInner
|
||||||
|
inner_early_return: &'a AtomicBool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> CtrlAnime<'static> {
|
||||||
|
pub fn new(
|
||||||
|
config: Arc<Mutex<UserAnimeConfig>>,
|
||||||
|
inner: Arc<Mutex<CtrlAnimeInner<'static>>>,
|
||||||
|
client: AuraDbusClient<'static>,
|
||||||
|
inner_early_return: &'static AtomicBool,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
Ok(CtrlAnime {
|
||||||
|
config,
|
||||||
|
inner,
|
||||||
|
client,
|
||||||
|
inner_early_return,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_to_server(self, server: &mut zbus::ObjectServer) {
|
||||||
|
server
|
||||||
|
.at(
|
||||||
|
&ObjectPath::from_str_unchecked("/org/asuslinux/Anime"),
|
||||||
|
self,
|
||||||
|
)
|
||||||
|
.map_err(|err| {
|
||||||
|
println!("CtrlAnime: add_to_server {}", err);
|
||||||
|
err
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The pattern for a zbus method is:
|
||||||
|
// - Get config lock if required
|
||||||
|
// - Set inner_early_return to stop the inner run loop temporarily
|
||||||
|
// - Do actions
|
||||||
|
// - Write config if required
|
||||||
|
// - Unset inner_early_return
|
||||||
|
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
||||||
|
impl CtrlAnime<'static> {
|
||||||
|
pub fn insert_asus_gif(
|
||||||
|
&mut self,
|
||||||
|
index: u32,
|
||||||
|
file: String,
|
||||||
|
time: TimeType,
|
||||||
|
count: u32,
|
||||||
|
brightness: f32,
|
||||||
|
) -> zbus::fdo::Result<String> {
|
||||||
|
if let Ok(mut config) = self.config.try_lock() {
|
||||||
|
let time: AnimTime = match time {
|
||||||
|
TimeType::Timer => AnimTime::Time(Duration::from_millis(count as u64)),
|
||||||
|
TimeType::Count => AnimTime::Cycles(count),
|
||||||
|
TimeType::Infinite => AnimTime::Infinite,
|
||||||
|
};
|
||||||
|
let file = Path::new(&file);
|
||||||
|
let action = AnimeAction::AsusAnimation {
|
||||||
|
file: file.into(),
|
||||||
|
brightness,
|
||||||
|
time,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Must make the inner run loop return early
|
||||||
|
self.inner_early_return.store(true, Ordering::SeqCst);
|
||||||
|
|
||||||
|
if let Ok(mut controller) = self.inner.lock() {
|
||||||
|
controller.sequences.insert(index as usize, &action)?;
|
||||||
|
}
|
||||||
|
config.anime.push(action);
|
||||||
|
config.write()?;
|
||||||
|
|
||||||
|
let json = serde_json::to_string_pretty(&*config).expect("Parse config to JSON failed");
|
||||||
|
|
||||||
|
// Release the inner run loop again
|
||||||
|
self.inner_early_return.store(false, Ordering::SeqCst);
|
||||||
|
return Ok(json);
|
||||||
|
}
|
||||||
|
Err(zbus::fdo::Error::Failed("UserConfig lock fail".into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
pub fn insert_image_gif(
|
||||||
|
&mut self,
|
||||||
|
index: u32,
|
||||||
|
file: String,
|
||||||
|
scale: f32,
|
||||||
|
angle: f32,
|
||||||
|
xy: (f32, f32),
|
||||||
|
time: TimeType,
|
||||||
|
count: u32,
|
||||||
|
brightness: f32,
|
||||||
|
) -> zbus::fdo::Result<String> {
|
||||||
|
if let Ok(mut config) = self.config.try_lock() {
|
||||||
|
let time: AnimTime = match time {
|
||||||
|
TimeType::Timer => AnimTime::Time(Duration::from_millis(count as u64)),
|
||||||
|
TimeType::Count => AnimTime::Cycles(count),
|
||||||
|
TimeType::Infinite => AnimTime::Infinite,
|
||||||
|
};
|
||||||
|
let file = Path::new(&file);
|
||||||
|
let translation = Vec2::new(xy.0, xy.1);
|
||||||
|
let action = AnimeAction::ImageAnimation {
|
||||||
|
file: file.into(),
|
||||||
|
scale,
|
||||||
|
angle,
|
||||||
|
translation,
|
||||||
|
brightness,
|
||||||
|
time,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Must make the inner run loop return early
|
||||||
|
self.inner_early_return.store(true, Ordering::SeqCst);
|
||||||
|
|
||||||
|
if let Ok(mut controller) = self.inner.lock() {
|
||||||
|
controller.sequences.insert(index as usize, &action)?;
|
||||||
|
}
|
||||||
|
config.anime.push(action);
|
||||||
|
config.write()?;
|
||||||
|
|
||||||
|
let json =
|
||||||
|
serde_json::to_string_pretty(&*config.anime).expect("Parse config to JSON failed");
|
||||||
|
|
||||||
|
// Release the inner run loop again
|
||||||
|
self.inner_early_return.store(false, Ordering::SeqCst);
|
||||||
|
return Ok(json);
|
||||||
|
}
|
||||||
|
Err(zbus::fdo::Error::Failed("UserConfig lock fail".into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert_image(
|
||||||
|
&mut self,
|
||||||
|
index: u32,
|
||||||
|
file: String,
|
||||||
|
scale: f32,
|
||||||
|
angle: f32,
|
||||||
|
xy: (f32, f32),
|
||||||
|
brightness: f32,
|
||||||
|
) -> zbus::fdo::Result<String> {
|
||||||
|
if let Ok(mut config) = self.config.try_lock() {
|
||||||
|
let file = Path::new(&file);
|
||||||
|
let action = AnimeAction::Image {
|
||||||
|
file: file.into(),
|
||||||
|
scale,
|
||||||
|
angle,
|
||||||
|
translation: Vec2::new(xy.0, xy.1),
|
||||||
|
brightness,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Must make the inner run loop return early
|
||||||
|
self.inner_early_return.store(true, Ordering::SeqCst);
|
||||||
|
|
||||||
|
if let Ok(mut controller) = self.inner.lock() {
|
||||||
|
controller.sequences.insert(index as usize, &action)?;
|
||||||
|
}
|
||||||
|
config.anime.push(action);
|
||||||
|
config.write()?;
|
||||||
|
|
||||||
|
let json =
|
||||||
|
serde_json::to_string_pretty(&*config.anime).expect("Parse config to JSON failed");
|
||||||
|
|
||||||
|
// Release the inner run loop again
|
||||||
|
self.inner_early_return.store(false, Ordering::SeqCst);
|
||||||
|
return Ok(json);
|
||||||
|
}
|
||||||
|
Err(zbus::fdo::Error::Failed("UserConfig lock fail".into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert_pause(&mut self, index: u32, millis: u64) -> zbus::fdo::Result<String> {
|
||||||
|
if let Ok(mut config) = self.config.try_lock() {
|
||||||
|
let action = AnimeAction::Pause(Duration::from_millis(millis));
|
||||||
|
// Must make the inner run loop return early
|
||||||
|
self.inner_early_return.store(true, Ordering::SeqCst);
|
||||||
|
|
||||||
|
if let Ok(mut controller) = self.inner.lock() {
|
||||||
|
controller.sequences.insert(index as usize, &action)?;
|
||||||
|
}
|
||||||
|
config.anime.push(action);
|
||||||
|
config.write()?;
|
||||||
|
|
||||||
|
let json =
|
||||||
|
serde_json::to_string_pretty(&*config.anime).expect("Parse config to JSON failed");
|
||||||
|
|
||||||
|
// Release the inner run loop again
|
||||||
|
self.inner_early_return.store(false, Ordering::SeqCst);
|
||||||
|
return Ok(json);
|
||||||
|
}
|
||||||
|
Err(zbus::fdo::Error::Failed("UserConfig lock fail".into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove_item(&mut self, index: u32) -> zbus::fdo::Result<String> {
|
||||||
|
if let Ok(mut config) = self.config.try_lock() {
|
||||||
|
// Must make the inner run loop return early
|
||||||
|
self.inner_early_return.store(true, Ordering::SeqCst);
|
||||||
|
|
||||||
|
if let Ok(mut controller) = self.inner.lock() {
|
||||||
|
controller.sequences.remove_item(index as usize);
|
||||||
|
}
|
||||||
|
if (index as usize) < config.anime.len() {
|
||||||
|
config.anime.remove(index as usize);
|
||||||
|
}
|
||||||
|
config.write()?;
|
||||||
|
|
||||||
|
let json =
|
||||||
|
serde_json::to_string_pretty(&*config.anime).expect("Parse config to JSON failed");
|
||||||
|
|
||||||
|
// Release the inner run loop again
|
||||||
|
self.inner_early_return.store(false, Ordering::SeqCst);
|
||||||
|
return Ok(json);
|
||||||
|
}
|
||||||
|
Err(zbus::fdo::Error::Failed("UserConfig lock fail".into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_state(&mut self, on: bool) -> zbus::fdo::Result<()> {
|
||||||
|
// Operations here need to be in specific order
|
||||||
|
if on {
|
||||||
|
self.client.proxies().anime().toggle_on(on)?;
|
||||||
|
// Let the inner loop run
|
||||||
|
self.inner_early_return.store(false, Ordering::SeqCst);
|
||||||
|
} else {
|
||||||
|
// Must make the inner run loop return early
|
||||||
|
self.inner_early_return.store(true, Ordering::SeqCst);
|
||||||
|
self.client.proxies().anime().toggle_on(on)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
use rog_dbus::AuraDbusClient;
|
||||||
|
use rog_types::supported::SupportedFunctions;
|
||||||
|
use rog_user::{
|
||||||
|
ctrl_anime::{CtrlAnime, CtrlAnimeInner},
|
||||||
|
user_config::*,
|
||||||
|
DBUS_NAME,
|
||||||
|
};
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
use std::thread;
|
||||||
|
use zbus::{fdo, Connection};
|
||||||
|
|
||||||
|
use std::sync::atomic::AtomicBool;
|
||||||
|
|
||||||
|
/// The anime loop needs an atomic to make it exit early if required
|
||||||
|
static ANIME_INNER_EARLY_RETURN: AtomicBool = AtomicBool::new(false);
|
||||||
|
|
||||||
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
println!(" rog-dbus version {}", rog_dbus::VERSION);
|
||||||
|
|
||||||
|
let (client, _) = AuraDbusClient::new().unwrap();
|
||||||
|
let supported = client.proxies().supported().get_supported_functions()?;
|
||||||
|
let supported = serde_json::from_str::<SupportedFunctions>(&&supported).unwrap();
|
||||||
|
|
||||||
|
let mut config = UserConfig::new();
|
||||||
|
config.load_config()?;
|
||||||
|
|
||||||
|
let anime_config = UserAnimeConfig::load_config(config.active_anime)?;
|
||||||
|
let anime = anime_config.create_anime()?;
|
||||||
|
|
||||||
|
let anime_config = Arc::new(Mutex::new(anime_config));
|
||||||
|
|
||||||
|
// Create server
|
||||||
|
let connection = Connection::new_session()?;
|
||||||
|
fdo::DBusProxy::new(&connection)?
|
||||||
|
.request_name(DBUS_NAME, fdo::RequestNameFlags::ReplaceExisting.into())?;
|
||||||
|
let mut server = zbus::ObjectServer::new(&connection);
|
||||||
|
|
||||||
|
// Set up the anime data and run loop/thread
|
||||||
|
if supported.anime_ctrl.0 {
|
||||||
|
// Inner behind mutex required for thread safety
|
||||||
|
let inner = Arc::new(Mutex::new(CtrlAnimeInner::new(
|
||||||
|
anime,
|
||||||
|
client,
|
||||||
|
&ANIME_INNER_EARLY_RETURN,
|
||||||
|
)?));
|
||||||
|
// Need new client object for dbus control part
|
||||||
|
let (client, _) = AuraDbusClient::new().unwrap();
|
||||||
|
let anime_control = CtrlAnime::new(
|
||||||
|
anime_config,
|
||||||
|
inner.clone(),
|
||||||
|
client,
|
||||||
|
&ANIME_INNER_EARLY_RETURN,
|
||||||
|
)?;
|
||||||
|
anime_control.add_to_server(&mut server);
|
||||||
|
// Thread using inner
|
||||||
|
let _anime_thread = thread::Builder::new()
|
||||||
|
.name("Anime User".into())
|
||||||
|
.spawn(move || loop {
|
||||||
|
if let Ok(inner) = inner.try_lock() {
|
||||||
|
inner.run().unwrap();
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if supported.keyboard_led.per_key_led_mode {}
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if let Err(err) = server.try_handle_next() {
|
||||||
|
println!("{}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
use rog_anime::error::AnimeError;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
Io(std::io::Error),
|
||||||
|
ConfigLoadFail,
|
||||||
|
ConfigLockFail,
|
||||||
|
XdgVars,
|
||||||
|
Anime(AnimeError),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Error {
|
||||||
|
// This trait requires `fmt` with this exact signature.
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Error::Io(err) => write!(f, "Failed to open: {}", err),
|
||||||
|
Error::ConfigLoadFail => write!(f, "Failed to load user config"),
|
||||||
|
Error::ConfigLockFail => write!(f, "Failed to lock user config"),
|
||||||
|
Error::XdgVars => write!(f, "XDG environment vars appear unset"),
|
||||||
|
Error::Anime(err) => write!(f, "Anime error: {}", err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::error::Error for Error {}
|
||||||
|
|
||||||
|
impl From<std::io::Error> for Error {
|
||||||
|
fn from(err: std::io::Error) -> Self {
|
||||||
|
Error::Io(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<AnimeError> for Error {
|
||||||
|
fn from(err: AnimeError) -> Self {
|
||||||
|
Error::Anime(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Error> for zbus::fdo::Error {
|
||||||
|
fn from(err: Error) -> Self {
|
||||||
|
zbus::fdo::Error::Failed(format!("Anime zbus error: {}", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
pub mod user_config;
|
||||||
|
|
||||||
|
pub mod error;
|
||||||
|
|
||||||
|
pub mod ctrl_anime;
|
||||||
|
|
||||||
|
pub mod zbus_anime;
|
||||||
|
|
||||||
|
pub static DBUS_NAME: &str = "org.asuslinux.Daemon";
|
||||||
@@ -0,0 +1,202 @@
|
|||||||
|
use std::{
|
||||||
|
fs::{create_dir, OpenOptions},
|
||||||
|
io::{Read, Write},
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
|
|
||||||
|
use rog_anime::{AnimTime, AnimeAction, Sequences, Vec2};
|
||||||
|
use serde_derive::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::error::Error;
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
pub struct UserAnimeConfig {
|
||||||
|
pub name: String,
|
||||||
|
pub anime: Vec<AnimeAction>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UserAnimeConfig {
|
||||||
|
pub fn create_anime(&self) -> Result<Sequences, Error> {
|
||||||
|
let mut seq = Sequences::new();
|
||||||
|
|
||||||
|
for (idx, action) in self.anime.iter().enumerate() {
|
||||||
|
seq.insert(idx, action)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(seq)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write(&self) -> Result<(), Error> {
|
||||||
|
let mut path = if let Some(dir) = dirs::config_dir() {
|
||||||
|
dir
|
||||||
|
} else {
|
||||||
|
return Err(Error::XdgVars);
|
||||||
|
};
|
||||||
|
|
||||||
|
path.push("rog");
|
||||||
|
if !path.exists() {
|
||||||
|
create_dir(path.clone())?;
|
||||||
|
}
|
||||||
|
let name = self.name.clone();
|
||||||
|
path.push(name + ".cfg");
|
||||||
|
|
||||||
|
let mut file = OpenOptions::new()
|
||||||
|
.write(true)
|
||||||
|
.create(true)
|
||||||
|
.truncate(true)
|
||||||
|
.open(&path)?;
|
||||||
|
|
||||||
|
let json = serde_json::to_string_pretty(&self).unwrap();
|
||||||
|
file.write_all(json.as_bytes())?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load_config(name: String) -> Result<UserAnimeConfig, Error> {
|
||||||
|
let mut path = if let Some(dir) = dirs::config_dir() {
|
||||||
|
dir
|
||||||
|
} else {
|
||||||
|
return Err(Error::XdgVars);
|
||||||
|
};
|
||||||
|
|
||||||
|
path.push("rog");
|
||||||
|
if !path.exists() {
|
||||||
|
create_dir(path.clone())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
path.push(name + ".cfg");
|
||||||
|
|
||||||
|
let mut file = OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.write(true)
|
||||||
|
.create(true)
|
||||||
|
.open(&path)?;
|
||||||
|
|
||||||
|
let mut buf = String::new();
|
||||||
|
|
||||||
|
if let Ok(read_len) = file.read_to_string(&mut buf) {
|
||||||
|
if read_len == 0 {
|
||||||
|
let default = UserAnimeConfig::default();
|
||||||
|
let json = serde_json::to_string_pretty(&default).unwrap();
|
||||||
|
file.write_all(json.as_bytes())?;
|
||||||
|
return Ok(default);
|
||||||
|
} else if let Ok(data) = serde_json::from_str::<UserAnimeConfig>(&buf) {
|
||||||
|
return Ok(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(Error::ConfigLoadFail)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for UserAnimeConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
let x = Self {
|
||||||
|
name: "default".to_string(),
|
||||||
|
anime: vec![
|
||||||
|
AnimeAction::AsusAnimation {
|
||||||
|
file: "/usr/share/asusd/anime/asus/rog/Sunset.gif".into(),
|
||||||
|
brightness: 0.5,
|
||||||
|
time: AnimTime::Cycles(1),
|
||||||
|
},
|
||||||
|
AnimeAction::ImageAnimation {
|
||||||
|
file: "/usr/share/asusd/anime/custom/sonic-run.gif".into(),
|
||||||
|
scale: 0.9,
|
||||||
|
angle: 0.65,
|
||||||
|
translation: Vec2::default(),
|
||||||
|
brightness: 0.5,
|
||||||
|
time: AnimTime::Time(Duration::from_secs(5)),
|
||||||
|
},
|
||||||
|
AnimeAction::Image {
|
||||||
|
file: "/usr/share/asusd/anime/custom/rust.png".into(),
|
||||||
|
scale: 1.0,
|
||||||
|
angle: 0.0,
|
||||||
|
translation: Vec2::default(),
|
||||||
|
brightness: 0.6,
|
||||||
|
},
|
||||||
|
AnimeAction::Pause(Duration::from_secs(6)),
|
||||||
|
AnimeAction::ImageAnimation {
|
||||||
|
file: "/usr/share/asusd/anime/custom/sonic-wait.gif".into(),
|
||||||
|
scale: 0.9,
|
||||||
|
angle: 0.0,
|
||||||
|
translation: Vec2::new(3.0, 2.0),
|
||||||
|
brightness: 0.5,
|
||||||
|
time: AnimTime::Cycles(2),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
println!("{}", serde_json::to_string_pretty(&x).unwrap());
|
||||||
|
x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Deserialize, Serialize)]
|
||||||
|
pub struct UserConfig {
|
||||||
|
/// Name of active anime config file in the user config directory
|
||||||
|
pub active_anime: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UserConfig {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
active_anime: "anime-default".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load_config(&mut self) -> Result<(), Error> {
|
||||||
|
let mut path = if let Some(dir) = dirs::config_dir() {
|
||||||
|
dir
|
||||||
|
} else {
|
||||||
|
return Err(Error::XdgVars);
|
||||||
|
};
|
||||||
|
|
||||||
|
path.push("rog");
|
||||||
|
if !path.exists() {
|
||||||
|
create_dir(path.clone())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
path.push("rog-user.cfg");
|
||||||
|
|
||||||
|
let mut file = OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.write(true)
|
||||||
|
.create(true)
|
||||||
|
.open(&path)?;
|
||||||
|
|
||||||
|
let mut buf = String::new();
|
||||||
|
|
||||||
|
if let Ok(read_len) = file.read_to_string(&mut buf) {
|
||||||
|
if read_len == 0 {
|
||||||
|
let json = serde_json::to_string_pretty(&self).unwrap();
|
||||||
|
file.write_all(json.as_bytes())?;
|
||||||
|
} else if let Ok(data) = serde_json::from_str::<UserConfig>(&buf) {
|
||||||
|
self.active_anime = data.active_anime;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write(&self) -> Result<(), Error> {
|
||||||
|
let mut path = if let Some(dir) = dirs::config_dir() {
|
||||||
|
dir
|
||||||
|
} else {
|
||||||
|
return Err(Error::XdgVars);
|
||||||
|
};
|
||||||
|
|
||||||
|
path.push("rog");
|
||||||
|
if !path.exists() {
|
||||||
|
create_dir(path.clone())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
path.push("rog-user.cfg");
|
||||||
|
|
||||||
|
let mut file = OpenOptions::new()
|
||||||
|
.write(true)
|
||||||
|
.create(true)
|
||||||
|
.truncate(true)
|
||||||
|
.open(&path)?;
|
||||||
|
|
||||||
|
let json = serde_json::to_string_pretty(&self).unwrap();
|
||||||
|
file.write_all(json.as_bytes())?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
//! # DBus interface proxy for: `org.asuslinux.Daemon`
|
||||||
|
//!
|
||||||
|
//! This code was generated by `zbus-xmlgen` `1.0.0` from DBus introspection data.
|
||||||
|
//! Source: `Interface '/org/asuslinux/Anime' from service 'org.asuslinux.Daemon' on session bus`.
|
||||||
|
//!
|
||||||
|
//! You may prefer to adapt it, instead of using it verbatim.
|
||||||
|
//!
|
||||||
|
//! More information can be found in the
|
||||||
|
//! [Writing a client proxy](https://dbus.pages.freedesktop.org/zbus/client.html)
|
||||||
|
//! section of the zbus documentation.
|
||||||
|
//!
|
||||||
|
//! This DBus object implements
|
||||||
|
//! [standard DBus interfaces](https://dbus.freedesktop.org/doc/dbus-specification.html),
|
||||||
|
//! (`org.freedesktop.DBus.*`) for which the following zbus proxies can be used:
|
||||||
|
//!
|
||||||
|
//! * [`zbus::fdo::PeerProxy`]
|
||||||
|
//! * [`zbus::fdo::IntrospectableProxy`]
|
||||||
|
//! * [`zbus::fdo::PropertiesProxy`]
|
||||||
|
//!
|
||||||
|
//! …consequently `zbus-xmlgen` did not generate code for the above interfaces.
|
||||||
|
|
||||||
|
use zbus::dbus_proxy;
|
||||||
|
|
||||||
|
#[dbus_proxy(interface = "org.asuslinux.Daemon")]
|
||||||
|
trait Daemon {
|
||||||
|
/// InsertAsusGif method
|
||||||
|
fn insert_asus_gif(
|
||||||
|
&self,
|
||||||
|
index: u32,
|
||||||
|
file: &str,
|
||||||
|
time: u32,
|
||||||
|
count: u32,
|
||||||
|
brightness: f64,
|
||||||
|
) -> zbus::Result<String>;
|
||||||
|
|
||||||
|
/// InsertImage method
|
||||||
|
fn insert_image(
|
||||||
|
&self,
|
||||||
|
index: u32,
|
||||||
|
file: &str,
|
||||||
|
scale: f64,
|
||||||
|
angle: f64,
|
||||||
|
xy: &(f64, f64),
|
||||||
|
brightness: f64,
|
||||||
|
) -> zbus::Result<String>;
|
||||||
|
|
||||||
|
/// InsertImageGif method
|
||||||
|
fn insert_image_gif(
|
||||||
|
&self,
|
||||||
|
index: u32,
|
||||||
|
file: &str,
|
||||||
|
scale: f64,
|
||||||
|
angle: f64,
|
||||||
|
xy: &(f64, f64),
|
||||||
|
time: u32,
|
||||||
|
count: u32,
|
||||||
|
brightness: f64,
|
||||||
|
) -> zbus::Result<String>;
|
||||||
|
|
||||||
|
/// InsertPause method
|
||||||
|
fn insert_pause(&self, index: u32, millis: u64) -> zbus::Result<String>;
|
||||||
|
|
||||||
|
/// RemoveItem method
|
||||||
|
fn remove_item(&self, index: u32) -> zbus::Result<String>;
|
||||||
|
|
||||||
|
/// SetState method
|
||||||
|
fn set_state(&self, on: bool) -> zbus::Result<()>;
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "daemon"
|
name = "daemon"
|
||||||
version = "3.2.2"
|
version = "3.5.0"
|
||||||
license = "MPL-2.0"
|
license = "MPL-2.0"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
authors = ["Luke <luke@ljones.dev>"]
|
authors = ["Luke <luke@ljones.dev>"]
|
||||||
@@ -18,18 +18,20 @@ name = "asusd"
|
|||||||
path = "src/daemon.rs"
|
path = "src/daemon.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
rog_anime = { path = "../rog-anime" }
|
||||||
|
rog_aura = { path = "../rog-aura" }
|
||||||
rog_types = { path = "../rog-types" }
|
rog_types = { path = "../rog-types" }
|
||||||
rog_dbus = { path = "../rog-dbus" }
|
rog_dbus = { path = "../rog-dbus" }
|
||||||
rusb = "^0.7"
|
rusb = "^0.8"
|
||||||
udev = "^0.6"
|
udev = "^0.6"
|
||||||
|
|
||||||
# cli and logging
|
# cli and logging
|
||||||
log = "^0.4"
|
log = "^0.4"
|
||||||
env_logger = "^0.8"
|
env_logger = "^0.8"
|
||||||
|
|
||||||
zbus = "^2.0.0-beta.3"
|
zbus = "^1.9.1"
|
||||||
zvariant = "^2.5"
|
zvariant = "^2.6"
|
||||||
logind-zbus = "*"
|
logind-zbus = "^0.7.1"
|
||||||
|
|
||||||
# serialisation
|
# serialisation
|
||||||
serde = "^1.0"
|
serde = "^1.0"
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
use rog_fan_curve::Curve;
|
use rog_types::{gfx_vendors::GfxVendors, profile::Profile};
|
||||||
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};
|
||||||
@@ -15,7 +14,10 @@ pub static AURA_CONFIG_PATH: &str = "/etc/asusd/asusd.conf";
|
|||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub gfx_mode: GfxVendors,
|
pub gfx_mode: GfxVendors,
|
||||||
|
pub gfx_last_mode: GfxVendors,
|
||||||
pub gfx_managed: bool,
|
pub gfx_managed: bool,
|
||||||
|
pub gfx_vfio_enable: bool,
|
||||||
|
pub gfx_save_compute_vfio: bool,
|
||||||
pub active_profile: String,
|
pub active_profile: String,
|
||||||
pub toggle_profiles: Vec<String>,
|
pub toggle_profiles: Vec<String>,
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
@@ -33,7 +35,10 @@ impl Default for Config {
|
|||||||
|
|
||||||
Config {
|
Config {
|
||||||
gfx_mode: GfxVendors::Hybrid,
|
gfx_mode: GfxVendors::Hybrid,
|
||||||
|
gfx_last_mode: GfxVendors::Hybrid,
|
||||||
gfx_managed: true,
|
gfx_managed: true,
|
||||||
|
gfx_vfio_enable: false,
|
||||||
|
gfx_save_compute_vfio: 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,
|
||||||
@@ -64,26 +69,21 @@ impl Config {
|
|||||||
} 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::<ConfigV341>(&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::<ConfigV324>(&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::<ConfigV317>(&buf) {
|
} else if let Ok(data) = serde_json::from_str::<ConfigV317>(&buf) {
|
||||||
let config = data.into_current();
|
let config = data.into_current();
|
||||||
config.write();
|
config.write();
|
||||||
info!("Updated config version to: {}", VERSION);
|
info!("Updated config version to: {}", VERSION);
|
||||||
return config;
|
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) {
|
|
||||||
let config = data.into_current();
|
|
||||||
config.write();
|
|
||||||
info!("Updated config version to: {}", VERSION);
|
|
||||||
return config;
|
|
||||||
} else if let Ok(data) = serde_json::from_str::<ConfigV212>(&buf) {
|
|
||||||
let config = data.into_current();
|
|
||||||
config.write();
|
|
||||||
info!("Updated config version to: {}", VERSION);
|
|
||||||
return config;
|
|
||||||
}
|
}
|
||||||
warn!("Could not deserialise {}", CONFIG_PATH);
|
warn!("Could not deserialise {}", CONFIG_PATH);
|
||||||
panic!("Please remove {} then restart asusd", CONFIG_PATH);
|
panic!("Please remove {} then restart asusd", CONFIG_PATH);
|
||||||
@@ -136,45 +136,3 @@ impl Config {
|
|||||||
.unwrap_or_else(|err| error!("Could not write config: {}", err));
|
.unwrap_or_else(|err| error!("Could not write config: {}", err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
|
||||||
pub struct Profile {
|
|
||||||
pub min_percentage: u8,
|
|
||||||
pub max_percentage: u8,
|
|
||||||
pub turbo: bool,
|
|
||||||
pub fan_preset: u8,
|
|
||||||
pub fan_curve: Option<Curve>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[deprecated]
|
|
||||||
pub type CPUSettings = Profile;
|
|
||||||
|
|
||||||
impl Default for Profile {
|
|
||||||
fn default() -> Self {
|
|
||||||
Profile {
|
|
||||||
min_percentage: 0,
|
|
||||||
max_percentage: 100,
|
|
||||||
turbo: false,
|
|
||||||
fan_preset: 0,
|
|
||||||
fan_curve: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Profile {
|
|
||||||
pub fn new(
|
|
||||||
min_percentage: u8,
|
|
||||||
max_percentage: u8,
|
|
||||||
turbo: bool,
|
|
||||||
fan_preset: u8,
|
|
||||||
fan_curve: Option<Curve>,
|
|
||||||
) -> Self {
|
|
||||||
Profile {
|
|
||||||
min_percentage,
|
|
||||||
max_percentage,
|
|
||||||
turbo,
|
|
||||||
fan_preset,
|
|
||||||
fan_curve,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -0,0 +1,201 @@
|
|||||||
|
use crate::VERSION;
|
||||||
|
use log::{error, info, warn};
|
||||||
|
use rog_anime::{error::AnimeError, ActionData, AnimTime, AnimeAction, Vec2};
|
||||||
|
use serde_derive::{Deserialize, Serialize};
|
||||||
|
use std::fs::{File, OpenOptions};
|
||||||
|
use std::io::{Read, Write};
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
pub static ANIME_CONFIG_PATH: &str = "/etc/asusd/anime.conf";
|
||||||
|
pub static ANIME_CACHE_PATH: &str = "/etc/asusd/anime-cache.conf";
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
|
pub struct AnimeConfigV341 {
|
||||||
|
pub system: Option<AnimeAction>,
|
||||||
|
pub boot: Option<AnimeAction>,
|
||||||
|
pub suspend: Option<AnimeAction>,
|
||||||
|
pub shutdown: Option<AnimeAction>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AnimeConfigV341 {
|
||||||
|
pub(crate) fn into_current(self) -> AnimeConfig {
|
||||||
|
AnimeConfig {
|
||||||
|
system: if let Some(ani) = self.system {
|
||||||
|
vec![ani]
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
},
|
||||||
|
boot: if let Some(ani) = self.boot {
|
||||||
|
vec![ani]
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
},
|
||||||
|
wake: if let Some(ani) = self.suspend {
|
||||||
|
vec![ani]
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
},
|
||||||
|
shutdown: if let Some(ani) = self.shutdown {
|
||||||
|
vec![ani]
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
},
|
||||||
|
brightness: 1.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Default)]
|
||||||
|
pub struct AnimeConfigCached {
|
||||||
|
pub system: Vec<ActionData>,
|
||||||
|
pub boot: Vec<ActionData>,
|
||||||
|
pub wake: Vec<ActionData>,
|
||||||
|
pub shutdown: Vec<ActionData>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AnimeConfigCached {
|
||||||
|
pub fn init_from_config(&mut self, config: &AnimeConfig) -> Result<(), AnimeError> {
|
||||||
|
let mut sys = Vec::with_capacity(config.system.len());
|
||||||
|
for ani in config.system.iter() {
|
||||||
|
sys.push(ActionData::from_anime_action(ani)?);
|
||||||
|
}
|
||||||
|
self.system = sys;
|
||||||
|
|
||||||
|
let mut boot = Vec::with_capacity(config.boot.len());
|
||||||
|
for ani in config.boot.iter() {
|
||||||
|
boot.push(ActionData::from_anime_action(ani)?);
|
||||||
|
}
|
||||||
|
self.boot = boot;
|
||||||
|
|
||||||
|
let mut wake = Vec::with_capacity(config.wake.len());
|
||||||
|
for ani in config.wake.iter() {
|
||||||
|
wake.push(ActionData::from_anime_action(ani)?);
|
||||||
|
}
|
||||||
|
self.wake = wake;
|
||||||
|
|
||||||
|
let mut shutdown = Vec::with_capacity(config.shutdown.len());
|
||||||
|
for ani in config.shutdown.iter() {
|
||||||
|
shutdown.push(ActionData::from_anime_action(ani)?);
|
||||||
|
}
|
||||||
|
self.shutdown = shutdown;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Config for base system actions for the anime display
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
|
pub struct AnimeConfig {
|
||||||
|
pub system: Vec<AnimeAction>,
|
||||||
|
pub boot: Vec<AnimeAction>,
|
||||||
|
pub wake: Vec<AnimeAction>,
|
||||||
|
pub shutdown: Vec<AnimeAction>,
|
||||||
|
pub brightness: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for AnimeConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
AnimeConfig {
|
||||||
|
system: Vec::new(),
|
||||||
|
boot: Vec::new(),
|
||||||
|
wake: Vec::new(),
|
||||||
|
shutdown: Vec::new(),
|
||||||
|
brightness: 1.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AnimeConfig {
|
||||||
|
/// `load` will attempt to read the config, and panic if the dir is missing
|
||||||
|
pub fn load() -> Self {
|
||||||
|
let mut file = OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.write(true)
|
||||||
|
.create(true)
|
||||||
|
.open(&ANIME_CONFIG_PATH)
|
||||||
|
.unwrap_or_else(|_| {
|
||||||
|
panic!(
|
||||||
|
"The file {} or directory /etc/asusd/ is missing",
|
||||||
|
ANIME_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 AnimeConfig::create_default(&mut file);
|
||||||
|
} else {
|
||||||
|
if let Ok(data) = serde_json::from_str(&buf) {
|
||||||
|
return data;
|
||||||
|
} else if let Ok(data) = serde_json::from_str::<AnimeConfigV341>(&buf) {
|
||||||
|
let config = data.into_current();
|
||||||
|
config.write();
|
||||||
|
info!("Updated config version to: {}", VERSION);
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
warn!("Could not deserialise {}", ANIME_CONFIG_PATH);
|
||||||
|
panic!("Please remove {} then restart asusd", ANIME_CONFIG_PATH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AnimeConfig::create_default(&mut file)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_default(file: &mut File) -> Self {
|
||||||
|
// create a default config here
|
||||||
|
let config = AnimeConfig {
|
||||||
|
system: vec![],
|
||||||
|
boot: vec![AnimeAction::ImageAnimation {
|
||||||
|
file: "/usr/share/asusd/anime/custom/sonic-run.gif".into(),
|
||||||
|
scale: 0.9,
|
||||||
|
angle: 0.65,
|
||||||
|
translation: Vec2::default(),
|
||||||
|
brightness: 1.0,
|
||||||
|
time: AnimTime::Time(Duration::from_secs(5)),
|
||||||
|
}],
|
||||||
|
wake: vec![AnimeAction::ImageAnimation {
|
||||||
|
file: "/usr/share/asusd/anime/custom/sonic-run.gif".into(),
|
||||||
|
scale: 0.9,
|
||||||
|
angle: 0.65,
|
||||||
|
translation: Vec2::default(),
|
||||||
|
brightness: 1.0,
|
||||||
|
time: AnimTime::Time(Duration::from_secs(5)),
|
||||||
|
}],
|
||||||
|
shutdown: vec![AnimeAction::ImageAnimation {
|
||||||
|
file: "/usr/share/asusd/anime/custom/sonic-wait.gif".into(),
|
||||||
|
scale: 0.9,
|
||||||
|
angle: 0.0,
|
||||||
|
translation: Vec2::new(3.0, 2.0),
|
||||||
|
brightness: 1.0,
|
||||||
|
time: AnimTime::Infinite,
|
||||||
|
}],
|
||||||
|
brightness: 1.0,
|
||||||
|
};
|
||||||
|
// Should be okay to unwrap this as is since it is a Default
|
||||||
|
let json = serde_json::to_string_pretty(&config).unwrap();
|
||||||
|
file.write_all(json.as_bytes())
|
||||||
|
.unwrap_or_else(|_| panic!("Could not write {}", ANIME_CONFIG_PATH));
|
||||||
|
config
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read(&mut self) {
|
||||||
|
let mut file = OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.open(&ANIME_CONFIG_PATH)
|
||||||
|
.unwrap_or_else(|err| panic!("Error reading {}: {}", ANIME_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 {}", ANIME_CONFIG_PATH);
|
||||||
|
} else {
|
||||||
|
let x: AnimeConfig = serde_json::from_str(&buf)
|
||||||
|
.unwrap_or_else(|_| panic!("Could not deserialise {}", ANIME_CONFIG_PATH));
|
||||||
|
*self = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write(&self) {
|
||||||
|
let mut file = File::create(ANIME_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));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::laptops::LaptopLedData;
|
use crate::laptops::LaptopLedData;
|
||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
use rog_types::aura_modes::{AuraEffect, AuraModeNum, AuraMultiZone, AuraZone, LedBrightness};
|
use rog_aura::{AuraEffect, AuraModeNum, AuraZone, LedBrightness};
|
||||||
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};
|
||||||
@@ -146,3 +146,90 @@ impl AuraConfig {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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()
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,97 +1,8 @@
|
|||||||
use rog_types::{aura_modes::AuraEffect, gfx_vendors::GfxVendors};
|
use rog_types::{gfx_vendors::GfxVendors, profile::Profile};
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use crate::config::{Config, Profile};
|
use crate::config::Config;
|
||||||
|
|
||||||
/// 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
|
/// for parsing old v3.1.7 config
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
@@ -114,7 +25,69 @@ impl ConfigV317 {
|
|||||||
pub(crate) fn into_current(self) -> Config {
|
pub(crate) fn into_current(self) -> Config {
|
||||||
Config {
|
Config {
|
||||||
gfx_mode: GfxVendors::Hybrid,
|
gfx_mode: GfxVendors::Hybrid,
|
||||||
|
gfx_last_mode: GfxVendors::Hybrid,
|
||||||
gfx_managed: self.gfx_managed,
|
gfx_managed: self.gfx_managed,
|
||||||
|
gfx_vfio_enable: false,
|
||||||
|
gfx_save_compute_vfio: false,
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
|
pub struct ConfigV324 {
|
||||||
|
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 power_profiles: BTreeMap<String, Profile>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConfigV324 {
|
||||||
|
pub(crate) fn into_current(self) -> Config {
|
||||||
|
Config {
|
||||||
|
gfx_mode: GfxVendors::Hybrid,
|
||||||
|
gfx_last_mode: GfxVendors::Hybrid,
|
||||||
|
gfx_managed: self.gfx_managed,
|
||||||
|
gfx_vfio_enable: false,
|
||||||
|
gfx_save_compute_vfio: false,
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
|
pub struct ConfigV341 {
|
||||||
|
pub gfx_mode: GfxVendors,
|
||||||
|
pub gfx_managed: bool,
|
||||||
|
pub gfx_vfio_enable: bool,
|
||||||
|
pub active_profile: String,
|
||||||
|
pub toggle_profiles: Vec<String>,
|
||||||
|
#[serde(skip)]
|
||||||
|
pub curr_fan_mode: u8,
|
||||||
|
pub bat_charge_limit: u8,
|
||||||
|
pub power_profiles: BTreeMap<String, Profile>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConfigV341 {
|
||||||
|
pub(crate) fn into_current(self) -> Config {
|
||||||
|
Config {
|
||||||
|
gfx_mode: GfxVendors::Hybrid,
|
||||||
|
gfx_last_mode: GfxVendors::Hybrid,
|
||||||
|
gfx_managed: self.gfx_managed,
|
||||||
|
gfx_vfio_enable: false,
|
||||||
|
gfx_save_compute_vfio: false,
|
||||||
active_profile: self.active_profile,
|
active_profile: self.active_profile,
|
||||||
toggle_profiles: self.toggle_profiles,
|
toggle_profiles: self.toggle_profiles,
|
||||||
curr_fan_mode: self.curr_fan_mode,
|
curr_fan_mode: self.curr_fan_mode,
|
||||||
|
|||||||
@@ -1,121 +1,56 @@
|
|||||||
const INIT_STR: &str = "ASUS Tech.Inc.";
|
|
||||||
const PACKET_SIZE: usize = 640;
|
|
||||||
|
|
||||||
// Only these two packets must be 17 bytes
|
|
||||||
const DEV_PAGE: u8 = 0x5e;
|
|
||||||
// These bytes are in [1] position of the array
|
|
||||||
const WRITE: u8 = 0xc0;
|
|
||||||
const INIT: u8 = 0xc2;
|
|
||||||
const SET: u8 = 0xc3;
|
|
||||||
const APPLY: u8 = 0xc4;
|
|
||||||
|
|
||||||
// Used to turn the panel on and off
|
|
||||||
// The next byte can be 0x03 for "on" and 0x00 for "off"
|
|
||||||
const ON_OFF: u8 = 0x04;
|
|
||||||
|
|
||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
use rog_types::{
|
use logind_zbus::ManagerProxy;
|
||||||
anime_matrix::{
|
use rog_anime::{
|
||||||
AniMeDataBuffer, AniMeImageBuffer, AniMePacketType, ANIME_PANE1_PREFIX, ANIME_PANE2_PREFIX,
|
usb::{
|
||||||
|
pkt_for_apply, pkt_for_flush, pkt_for_set_boot, pkt_for_set_on, pkts_for_init, PROD_ID,
|
||||||
|
VENDOR_ID,
|
||||||
},
|
},
|
||||||
error::AuraError,
|
ActionData, AnimTime, AnimeDataBuffer, AnimePacketType, ANIME_DATA_LEN,
|
||||||
};
|
};
|
||||||
|
use rog_types::supported::AnimeSupportedFunctions;
|
||||||
use rusb::{Device, DeviceHandle};
|
use rusb::{Device, DeviceHandle};
|
||||||
use std::error::Error;
|
use std::{
|
||||||
use std::time::Duration;
|
error::Error,
|
||||||
use zbus::dbus_interface;
|
sync::{Arc, Mutex},
|
||||||
|
thread::sleep,
|
||||||
|
time::Instant,
|
||||||
|
};
|
||||||
|
use std::{
|
||||||
|
sync::atomic::{AtomicBool, Ordering},
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
|
use zbus::{dbus_interface, Connection};
|
||||||
|
use zvariant::ObjectPath;
|
||||||
|
|
||||||
use crate::GetSupported;
|
use crate::{
|
||||||
|
config_anime::{AnimeConfig, AnimeConfigCached},
|
||||||
|
error::RogError,
|
||||||
|
GetSupported,
|
||||||
|
};
|
||||||
|
|
||||||
use serde_derive::{Deserialize, Serialize};
|
impl GetSupported for CtrlAnime {
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub struct AnimeSupportedFunctions(pub bool);
|
|
||||||
|
|
||||||
impl GetSupported for CtrlAnimeDisplay {
|
|
||||||
type A = AnimeSupportedFunctions;
|
type A = AnimeSupportedFunctions;
|
||||||
|
|
||||||
fn get_supported() -> Self::A {
|
fn get_supported() -> Self::A {
|
||||||
AnimeSupportedFunctions(CtrlAnimeDisplay::get_device(0x0b05, 0x193b).is_ok())
|
AnimeSupportedFunctions(CtrlAnime::get_device(VENDOR_ID, PROD_ID).is_ok())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CtrlAnimeDisplay {
|
pub struct CtrlAnime {
|
||||||
handle: DeviceHandle<rusb::GlobalContext>,
|
handle: DeviceHandle<rusb::GlobalContext>,
|
||||||
|
cache: AnimeConfigCached,
|
||||||
|
config: AnimeConfig,
|
||||||
|
// set to force thread to exit
|
||||||
|
thread_exit: Arc<AtomicBool>,
|
||||||
|
// Set to false when the thread exits
|
||||||
|
thread_running: Arc<AtomicBool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
//AnimatrixWrite
|
impl CtrlAnime {
|
||||||
pub trait Dbus {
|
|
||||||
/// Write an image 34x56 pixels. Each pixel is 0-255 greyscale.
|
|
||||||
fn write_image(&self, input: AniMeImageBuffer);
|
|
||||||
|
|
||||||
/// Write a direct stream of data
|
|
||||||
fn write_direct(&self, input: AniMeDataBuffer);
|
|
||||||
|
|
||||||
fn set_on_off(&self, status: bool);
|
|
||||||
|
|
||||||
fn set_boot_on_off(&self, status: bool);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl crate::ZbusAdd for CtrlAnimeDisplay {
|
|
||||||
fn add_to_server(self, server: &mut zbus::ObjectServer) {
|
|
||||||
server
|
|
||||||
.at("/org/asuslinux/Anime", self)
|
|
||||||
.map_err(|err| {
|
|
||||||
warn!("CtrlAnimeDisplay: add_to_server {}", err);
|
|
||||||
err
|
|
||||||
})
|
|
||||||
.ok();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
|
||||||
impl Dbus for CtrlAnimeDisplay {
|
|
||||||
/// Writes a 34x56 image
|
|
||||||
fn write_image(&self, input: AniMeImageBuffer) {
|
|
||||||
self.write_image_buffer(input)
|
|
||||||
.map_or_else(|err| warn!("{}", err), |()| info!("Writing image to Anime"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Writes a data stream of length
|
|
||||||
fn write_direct(&self, input: AniMeDataBuffer) {
|
|
||||||
self.write_data_buffer(input)
|
|
||||||
.map_or_else(|err| warn!("{}", err), |()| info!("Writing data to Anime"));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_on_off(&self, status: bool) {
|
|
||||||
let mut buffer = [0u8; PACKET_SIZE];
|
|
||||||
buffer[0] = DEV_PAGE;
|
|
||||||
buffer[1] = WRITE;
|
|
||||||
buffer[2] = ON_OFF;
|
|
||||||
|
|
||||||
if status {
|
|
||||||
buffer[3] = 0x03;
|
|
||||||
} else {
|
|
||||||
buffer[3] = 0x00;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.write_bytes(&buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_boot_on_off(&self, status: bool) {
|
|
||||||
let status_str = if status { "on" } else { "off" };
|
|
||||||
|
|
||||||
self.do_set_boot(status).map_or_else(
|
|
||||||
|err| warn!("{}", err),
|
|
||||||
|()| info!("Turning {} the AniMe at boot/shutdown", status_str),
|
|
||||||
);
|
|
||||||
self.do_apply().map_or_else(
|
|
||||||
|err| warn!("{}", err),
|
|
||||||
|()| info!("Turning {} the AniMe at boot/shutdown", status_str),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CtrlAnimeDisplay {
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new() -> Result<CtrlAnimeDisplay, Box<dyn Error>> {
|
pub fn new(config: AnimeConfig) -> Result<CtrlAnime, Box<dyn Error>> {
|
||||||
// We don't expect this ID to ever change
|
// We don't expect this ID to ever change
|
||||||
let device = CtrlAnimeDisplay::get_device(0x0b05, 0x193b)?;
|
let device = CtrlAnime::get_device(0x0b05, 0x193b)?;
|
||||||
|
|
||||||
let mut device = device.open()?;
|
let mut device = device.open()?;
|
||||||
device.reset()?;
|
device.reset()?;
|
||||||
@@ -131,13 +66,21 @@ impl CtrlAnimeDisplay {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
info!("Device has an AniMe Matrix display");
|
info!("Device has an AniMe Matrix display");
|
||||||
let ctrl = CtrlAnimeDisplay { handle: device };
|
let mut cache = AnimeConfigCached::default();
|
||||||
ctrl.do_initialization()?;
|
cache.init_from_config(&config)?;
|
||||||
|
|
||||||
|
let ctrl = CtrlAnime {
|
||||||
|
handle: device,
|
||||||
|
cache,
|
||||||
|
config,
|
||||||
|
thread_exit: Arc::new(AtomicBool::new(false)),
|
||||||
|
thread_running: Arc::new(AtomicBool::new(false)),
|
||||||
|
};
|
||||||
|
ctrl.do_initialization();
|
||||||
|
|
||||||
Ok(ctrl)
|
Ok(ctrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn get_device(vendor: u16, product: u16) -> Result<Device<rusb::GlobalContext>, rusb::Error> {
|
fn get_device(vendor: u16, product: u16) -> Result<Device<rusb::GlobalContext>, rusb::Error> {
|
||||||
for device in rusb::devices()?.iter() {
|
for device in rusb::devices()?.iter() {
|
||||||
let device_desc = device.device_descriptor()?;
|
let device_desc = device.device_descriptor()?;
|
||||||
@@ -148,8 +91,117 @@ impl CtrlAnimeDisplay {
|
|||||||
Err(rusb::Error::NoDevice)
|
Err(rusb::Error::NoDevice)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Should only be used if the bytes you are writing are verified correct
|
/// Start an action thread. This is classed as a singleton and there should be only
|
||||||
#[inline]
|
/// one running - so the thread uses atomics to signal run/exit.
|
||||||
|
///
|
||||||
|
/// Because this also writes to the usb device, other write tries (display only) *must*
|
||||||
|
/// get the mutex lock and set the thread_exit atomic.
|
||||||
|
fn run_thread(inner: Arc<Mutex<CtrlAnime>>, actions: Vec<ActionData>, mut once: bool) {
|
||||||
|
if actions.is_empty() {
|
||||||
|
warn!("AniMe system actions was empty");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Loop rules:
|
||||||
|
// - Lock the mutex **only when required**. That is, the lock must be held for the shortest duration possible.
|
||||||
|
// - An AtomicBool used for thread exit should be checked in every loop, including nested
|
||||||
|
|
||||||
|
// The only reason for this outer thread is to prevent blocking while waiting for the
|
||||||
|
// next spawned thread to exit
|
||||||
|
std::thread::Builder::new()
|
||||||
|
.name("AniMe system thread start".into())
|
||||||
|
.spawn(move || {
|
||||||
|
info!("AniMe system thread started");
|
||||||
|
// Getting copies of these Atomics is done *in* the thread to ensure
|
||||||
|
// we don't block other threads/main
|
||||||
|
let thread_exit;
|
||||||
|
let thread_running;
|
||||||
|
// First two loops are to ensure we *do* aquire a lock on the mutex
|
||||||
|
// The reason the loop is required is because the USB writes can block
|
||||||
|
// for up to 10ms. We can't fail to get the atomics.
|
||||||
|
loop {
|
||||||
|
if let Ok(lock) = inner.try_lock() {
|
||||||
|
thread_exit = lock.thread_exit.clone();
|
||||||
|
thread_running = lock.thread_running.clone();
|
||||||
|
// Make any running loop exit first
|
||||||
|
thread_exit.store(true, Ordering::SeqCst);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loop {
|
||||||
|
// wait for other threads to set not running so we know they exited
|
||||||
|
if !thread_running.load(Ordering::SeqCst) {
|
||||||
|
thread_exit.store(false, Ordering::SeqCst);
|
||||||
|
info!("AniMe forced a thread to exit");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
'main: loop {
|
||||||
|
if thread_exit.load(Ordering::SeqCst) {
|
||||||
|
break 'main;
|
||||||
|
}
|
||||||
|
for action in actions.iter() {
|
||||||
|
match action {
|
||||||
|
ActionData::Animation(frames) => {
|
||||||
|
let mut count = 0;
|
||||||
|
let start = Instant::now();
|
||||||
|
'animation: loop {
|
||||||
|
for frame in frames.frames() {
|
||||||
|
if let Ok(lock) = inner.try_lock() {
|
||||||
|
lock.write_data_buffer(frame.frame().clone());
|
||||||
|
}
|
||||||
|
if let AnimTime::Time(time) = frames.duration() {
|
||||||
|
if Instant::now().duration_since(start) > time {
|
||||||
|
break 'animation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sleep(frame.delay());
|
||||||
|
// Need to check for early exit condition here or it might run
|
||||||
|
// until end of gif or time
|
||||||
|
if thread_exit.load(Ordering::SeqCst) {
|
||||||
|
break 'main;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let AnimTime::Cycles(times) = frames.duration() {
|
||||||
|
count += 1;
|
||||||
|
if count >= times {
|
||||||
|
break 'animation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ActionData::Image(image) => {
|
||||||
|
once = false;
|
||||||
|
if let Ok(lock) = inner.try_lock() {
|
||||||
|
lock.write_data_buffer(image.as_ref().clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ActionData::Pause(duration) => sleep(*duration),
|
||||||
|
ActionData::AudioEq => {}
|
||||||
|
ActionData::SystemInfo => {}
|
||||||
|
ActionData::TimeDate => {}
|
||||||
|
ActionData::Matrix => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if once || actions.is_empty() {
|
||||||
|
break 'main;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Clear the display on exit
|
||||||
|
if let Ok(lock) = inner.try_lock() {
|
||||||
|
let data = AnimeDataBuffer::from_vec([0u8; ANIME_DATA_LEN].to_vec());
|
||||||
|
lock.write_data_buffer(data);
|
||||||
|
}
|
||||||
|
// Loop ended, set the atmonics
|
||||||
|
thread_exit.store(false, Ordering::SeqCst);
|
||||||
|
thread_running.store(false, Ordering::SeqCst);
|
||||||
|
info!("AniMe system thread exited");
|
||||||
|
})
|
||||||
|
.map(|err| info!("AniMe system thread: {:?}", err))
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
fn write_bytes(&self, message: &[u8]) {
|
fn write_bytes(&self, message: &[u8]) {
|
||||||
match self.handle.write_control(
|
match self.handle.write_control(
|
||||||
0x21, // request_type
|
0x21, // request_type
|
||||||
@@ -166,99 +218,208 @@ impl CtrlAnimeDisplay {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[inline]
|
|
||||||
fn write_data_buffer(&self, buffer: AniMeDataBuffer) -> Result<(), AuraError> {
|
|
||||||
let mut image = AniMePacketType::from(buffer);
|
|
||||||
image[0][..7].copy_from_slice(&ANIME_PANE1_PREFIX);
|
|
||||||
image[1][..7].copy_from_slice(&ANIME_PANE2_PREFIX);
|
|
||||||
|
|
||||||
for row in image.iter() {
|
/// Write only a data packet. This will modify the leds brightness using the
|
||||||
|
/// global brightness set in config.
|
||||||
|
fn write_data_buffer(&self, mut buffer: AnimeDataBuffer) {
|
||||||
|
for led in buffer.get_mut()[7..].iter_mut() {
|
||||||
|
let mut bright = *led as f32 * self.config.brightness;
|
||||||
|
if bright > 254.0 {
|
||||||
|
bright = 254.0;
|
||||||
|
}
|
||||||
|
*led = bright as u8;
|
||||||
|
}
|
||||||
|
let data = AnimePacketType::from(buffer);
|
||||||
|
for row in data.iter() {
|
||||||
self.write_bytes(row);
|
self.write_bytes(row);
|
||||||
}
|
}
|
||||||
self.do_flush()?;
|
self.write_bytes(&pkt_for_flush());
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write an Animatrix image
|
fn do_initialization(&self) {
|
||||||
///
|
let pkts = pkts_for_init();
|
||||||
/// The expected USB input here is *two* Vectors, 640 bytes in length. The two vectors
|
self.write_bytes(&pkts[0]);
|
||||||
/// are each one half of the full image write.
|
self.write_bytes(&pkts[1]);
|
||||||
///
|
}
|
||||||
/// After each write a flush is written, it is assumed that this tells the device to
|
}
|
||||||
/// go ahead and display the written bytes
|
|
||||||
///
|
|
||||||
/// # Note:
|
|
||||||
/// The vectors are expected to contain the full sequence of bytes as follows
|
|
||||||
///
|
|
||||||
/// - Write pane 1: 0x5e 0xc0 0x02 0x01 0x00 0x73 0x02 .. <led brightness>
|
|
||||||
/// - Write pane 2: 0x5e 0xc0 0x02 0x74 0x02 0x73 0x02 .. <led brightness>
|
|
||||||
///
|
|
||||||
/// Where led brightness is 0..255, low to high
|
|
||||||
#[inline]
|
|
||||||
fn write_image_buffer(&self, buffer: AniMeImageBuffer) -> Result<(), AuraError> {
|
|
||||||
let mut image = AniMePacketType::from(buffer);
|
|
||||||
image[0][..7].copy_from_slice(&ANIME_PANE1_PREFIX);
|
|
||||||
image[1][..7].copy_from_slice(&ANIME_PANE2_PREFIX);
|
|
||||||
|
|
||||||
for row in image.iter() {
|
pub struct CtrlAnimeTask<'a> {
|
||||||
self.write_bytes(row);
|
inner: Arc<Mutex<CtrlAnime>>,
|
||||||
|
_c: Connection,
|
||||||
|
manager: ManagerProxy<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> CtrlAnimeTask<'a> {
|
||||||
|
pub fn new(inner: Arc<Mutex<CtrlAnime>>) -> Self {
|
||||||
|
let connection = Connection::new_system().unwrap();
|
||||||
|
|
||||||
|
let manager = ManagerProxy::new(&connection).unwrap();
|
||||||
|
|
||||||
|
let c1 = inner.clone();
|
||||||
|
// Run this action when the system starts shutting down
|
||||||
|
manager
|
||||||
|
.connect_prepare_for_shutdown(move |shutdown| {
|
||||||
|
if shutdown {
|
||||||
|
'outer: loop {
|
||||||
|
if let Ok(lock) = c1.try_lock() {
|
||||||
|
lock.thread_exit.store(true, Ordering::SeqCst);
|
||||||
|
CtrlAnime::run_thread(c1.clone(), lock.cache.shutdown.clone(), false);
|
||||||
|
break 'outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.map_err(|err| {
|
||||||
|
warn!("CtrlAnimeTask: new() {}", err);
|
||||||
|
err
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
|
||||||
|
let c1 = inner.clone();
|
||||||
|
// Run this action when the system wakes up from sleep
|
||||||
|
manager
|
||||||
|
.connect_prepare_for_sleep(move |sleep| {
|
||||||
|
if !sleep {
|
||||||
|
// wait a fraction for things to wake up properly
|
||||||
|
std::thread::sleep(Duration::from_millis(100));
|
||||||
|
'outer: loop {
|
||||||
|
if let Ok(lock) = c1.try_lock() {
|
||||||
|
lock.thread_exit.store(true, Ordering::SeqCst);
|
||||||
|
CtrlAnime::run_thread(c1.clone(), lock.cache.wake.clone(), true);
|
||||||
|
break 'outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.map_err(|err| {
|
||||||
|
warn!("CtrlAnimeTask: new() {}", err);
|
||||||
|
err
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
inner,
|
||||||
|
_c: connection,
|
||||||
|
manager,
|
||||||
}
|
}
|
||||||
self.do_flush()?;
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
impl<'a> crate::CtrlTask for CtrlAnimeTask<'a> {
|
||||||
fn do_initialization(&self) -> Result<(), AuraError> {
|
fn do_task(&self) -> Result<(), RogError> {
|
||||||
let mut init = [0; PACKET_SIZE];
|
if let Ok(mut lock) = self.inner.try_lock() {
|
||||||
init[0] = DEV_PAGE; // This is the USB page we're using throughout
|
// Refresh the config and cache incase the user has edited it
|
||||||
for (idx, byte) in INIT_STR.as_bytes().iter().enumerate() {
|
let config = AnimeConfig::load();
|
||||||
init[idx + 1] = *byte
|
lock.cache
|
||||||
|
.init_from_config(&config)
|
||||||
|
.map_err(|err| {
|
||||||
|
warn!("CtrlAnimeTask: do_task {}", err);
|
||||||
|
err
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
}
|
}
|
||||||
self.write_bytes(&init);
|
|
||||||
|
|
||||||
// clear the init array and write other init message
|
// Check for signals on each task iteration, this will run the callbacks
|
||||||
for ch in init.iter_mut() {
|
// if any signal is recieved
|
||||||
*ch = 0;
|
self.manager.next_signal()?;
|
||||||
}
|
|
||||||
init[0] = DEV_PAGE; // write it to be sure?
|
|
||||||
init[1] = INIT;
|
|
||||||
|
|
||||||
self.write_bytes(&init);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn do_flush(&self) -> Result<(), AuraError> {
|
|
||||||
let mut flush = [0; PACKET_SIZE];
|
|
||||||
flush[0] = DEV_PAGE;
|
|
||||||
flush[1] = WRITE;
|
|
||||||
flush[2] = 0x03;
|
|
||||||
|
|
||||||
self.write_bytes(&flush);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn do_set_boot(&self, status: bool) -> Result<(), AuraError> {
|
|
||||||
let mut flush = [0; PACKET_SIZE];
|
|
||||||
flush[0] = DEV_PAGE;
|
|
||||||
flush[1] = SET;
|
|
||||||
flush[2] = 0x01;
|
|
||||||
flush[3] = if status { 0x00 } else { 0x80 };
|
|
||||||
|
|
||||||
self.write_bytes(&flush);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn do_apply(&self) -> Result<(), AuraError> {
|
|
||||||
let mut flush = [0; PACKET_SIZE];
|
|
||||||
flush[0] = DEV_PAGE;
|
|
||||||
flush[1] = APPLY;
|
|
||||||
flush[2] = 0x01;
|
|
||||||
flush[3] = 0x80;
|
|
||||||
|
|
||||||
self.write_bytes(&flush);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct CtrlAnimeReloader(pub Arc<Mutex<CtrlAnime>>);
|
||||||
|
|
||||||
|
impl crate::Reloadable for CtrlAnimeReloader {
|
||||||
|
fn reload(&mut self) -> Result<(), RogError> {
|
||||||
|
if let Ok(lock) = self.0.try_lock() {
|
||||||
|
let action = lock.cache.boot.clone();
|
||||||
|
CtrlAnime::run_thread(self.0.clone(), action, true);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct CtrlAnimeZbus(pub Arc<Mutex<CtrlAnime>>);
|
||||||
|
|
||||||
|
/// The struct with the main dbus methods requires this trait
|
||||||
|
impl crate::ZbusAdd for CtrlAnimeZbus {
|
||||||
|
fn add_to_server(self, server: &mut zbus::ObjectServer) {
|
||||||
|
server
|
||||||
|
.at(
|
||||||
|
&ObjectPath::from_str_unchecked("/org/asuslinux/Anime"),
|
||||||
|
self,
|
||||||
|
)
|
||||||
|
.map_err(|err| {
|
||||||
|
warn!("CtrlAnimeDisplay: add_to_server {}", err);
|
||||||
|
err
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// None of these calls can be guarnateed to succeed unless we loop until okay
|
||||||
|
// If the try_lock *does* succeed then any other thread trying to lock will not grab it
|
||||||
|
// until we finish.
|
||||||
|
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
||||||
|
impl CtrlAnimeZbus {
|
||||||
|
/// Writes a data stream of length. Will force system thread to exit until it is restarted
|
||||||
|
fn write(&self, input: AnimeDataBuffer) {
|
||||||
|
'outer: loop {
|
||||||
|
if let Ok(lock) = self.0.try_lock() {
|
||||||
|
lock.thread_exit.store(true, Ordering::SeqCst);
|
||||||
|
lock.write_data_buffer(input);
|
||||||
|
break 'outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_brightness(&self, bright: f32) {
|
||||||
|
'outer: loop {
|
||||||
|
if let Ok(mut lock) = self.0.try_lock() {
|
||||||
|
let mut bright = bright;
|
||||||
|
if bright < 0.0 {
|
||||||
|
bright = 0.0
|
||||||
|
} else if bright > 254.0 {
|
||||||
|
bright = 254.0;
|
||||||
|
}
|
||||||
|
lock.config.brightness = bright;
|
||||||
|
lock.config.write();
|
||||||
|
break 'outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_on_off(&self, status: bool) {
|
||||||
|
'outer: loop {
|
||||||
|
if let Ok(lock) = self.0.try_lock() {
|
||||||
|
lock.write_bytes(&pkt_for_set_on(status));
|
||||||
|
break 'outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_boot_on_off(&self, on: bool) {
|
||||||
|
'outer: loop {
|
||||||
|
if let Ok(lock) = self.0.try_lock() {
|
||||||
|
lock.write_bytes(&pkt_for_set_boot(on));
|
||||||
|
lock.write_bytes(&pkt_for_apply());
|
||||||
|
break 'outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The main loop is the base system set action if the user isn't running
|
||||||
|
/// the user daemon
|
||||||
|
fn run_main_loop(&self, start: bool) {
|
||||||
|
if start {
|
||||||
|
'outer: loop {
|
||||||
|
if let Ok(lock) = self.0.try_lock() {
|
||||||
|
lock.thread_exit.store(true, Ordering::SeqCst);
|
||||||
|
CtrlAnime::run_thread(self.0.clone(), lock.cache.system.clone(), false);
|
||||||
|
break 'outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,21 +1,17 @@
|
|||||||
use crate::{config::Config, error::RogError, GetSupported};
|
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 rog_types::supported::ChargeSupportedFunctions;
|
||||||
use std::fs::OpenOptions;
|
use std::fs::OpenOptions;
|
||||||
use std::io::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;
|
||||||
|
use zvariant::ObjectPath;
|
||||||
|
|
||||||
static BAT_CHARGE_PATH: &str = "/sys/class/power_supply/BAT0/charge_control_end_threshold";
|
static BAT_CHARGE_PATH: &str = "/sys/class/power_supply/BAT0/charge_control_end_threshold";
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub struct ChargeSupportedFunctions {
|
|
||||||
pub charge_level_set: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GetSupported for CtrlCharge {
|
impl GetSupported for CtrlCharge {
|
||||||
type A = ChargeSupportedFunctions;
|
type A = ChargeSupportedFunctions;
|
||||||
|
|
||||||
@@ -63,7 +59,10 @@ 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", self)
|
.at(
|
||||||
|
&ObjectPath::from_str_unchecked("/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,10 +6,16 @@ use crate::error::RogError;
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum GfxError {
|
pub enum GfxError {
|
||||||
ParseVendor,
|
ParseVendor,
|
||||||
|
ParsePower,
|
||||||
Bus(String, std::io::Error),
|
Bus(String, std::io::Error),
|
||||||
DisplayManagerAction(String, ExitStatus),
|
DisplayManagerAction(String, ExitStatus),
|
||||||
DisplayManagerTimeout(String),
|
DisplayManagerTimeout(String),
|
||||||
GsyncModeActive,
|
GsyncModeActive,
|
||||||
|
VfioBuiltin,
|
||||||
|
VfioDisabled,
|
||||||
|
MissingModule(String),
|
||||||
|
Modprobe(String),
|
||||||
|
Command(String, std::io::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for GfxError {
|
impl fmt::Display for GfxError {
|
||||||
@@ -17,6 +23,7 @@ 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::ParsePower => write!(f, "Could not parse dGPU power status"),
|
||||||
GfxError::Bus(func, error) => write!(f, "Bus error: {}: {}", func, error),
|
GfxError::Bus(func, error) => write!(f, "Bus error: {}: {}", func, error),
|
||||||
GfxError::DisplayManagerAction(action, status) => {
|
GfxError::DisplayManagerAction(action, status) => {
|
||||||
write!(f, "Display-manager action {} failed: {}", action, status)
|
write!(f, "Display-manager action {} failed: {}", action, status)
|
||||||
@@ -28,6 +35,16 @@ impl fmt::Display for GfxError {
|
|||||||
f,
|
f,
|
||||||
"Can not switch gfx modes when dedicated/G-Sync mode is active"
|
"Can not switch gfx modes when dedicated/G-Sync mode is active"
|
||||||
),
|
),
|
||||||
|
GfxError::VfioBuiltin => write!(
|
||||||
|
f,
|
||||||
|
"Can not switch to vfio mode if the modules are built in to kernel"
|
||||||
|
),
|
||||||
|
GfxError::VfioDisabled => {
|
||||||
|
write!(f, "Can not switch to vfio mode if disabled in config file")
|
||||||
|
}
|
||||||
|
GfxError::MissingModule(m) => write!(f, "The module {} is missing", m),
|
||||||
|
GfxError::Modprobe(detail) => write!(f, "Modprobe error: {}", detail),
|
||||||
|
GfxError::Command(func, error) => write!(f, "Command exec error: {}: {}", func, error),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,18 +3,19 @@ use ctrl_gfx::*;
|
|||||||
use ctrl_rog_bios::CtrlRogBios;
|
use ctrl_rog_bios::CtrlRogBios;
|
||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
use logind_zbus::{
|
use logind_zbus::{
|
||||||
types::{SessionClass, SessionInfo, SessionType},
|
types::{SessionClass, SessionInfo, SessionState, SessionType},
|
||||||
ManagerProxy, SessionProxy,
|
ManagerProxy, SessionProxy,
|
||||||
};
|
};
|
||||||
use rog_types::gfx_vendors::{GfxRequiredUserAction, GfxVendors};
|
use rog_types::gfx_vendors::{GfxPower, GfxRequiredUserAction, GfxVendors};
|
||||||
use std::sync::mpsc;
|
|
||||||
use std::{io::Write, ops::Add, path::Path, time::Instant};
|
use std::{io::Write, ops::Add, path::Path, time::Instant};
|
||||||
use std::{iter::FromIterator, thread::JoinHandle};
|
use std::{iter::FromIterator, thread::JoinHandle};
|
||||||
use std::{process::Command, thread::sleep, time::Duration};
|
use std::{process::Command, thread::sleep, time::Duration};
|
||||||
|
use std::{str::FromStr, sync::mpsc};
|
||||||
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, PciBus};
|
use system::{GraphicsDevice, PciBus};
|
||||||
use zbus::{dbus_interface, Connection};
|
use zbus::{dbus_interface, Connection};
|
||||||
|
use zvariant::ObjectPath;
|
||||||
|
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
@@ -33,7 +34,7 @@ pub struct CtrlGraphics {
|
|||||||
|
|
||||||
trait Dbus {
|
trait Dbus {
|
||||||
fn vendor(&self) -> zbus::fdo::Result<GfxVendors>;
|
fn vendor(&self) -> zbus::fdo::Result<GfxVendors>;
|
||||||
fn power(&self) -> String;
|
fn power(&self) -> zbus::fdo::Result<GfxPower>;
|
||||||
fn set_vendor(&mut self, vendor: GfxVendors) -> zbus::fdo::Result<GfxRequiredUserAction>;
|
fn set_vendor(&mut self, vendor: GfxVendors) -> zbus::fdo::Result<GfxRequiredUserAction>;
|
||||||
fn notify_gfx(&self, vendor: &GfxVendors) -> zbus::Result<()>;
|
fn notify_gfx(&self, vendor: &GfxVendors) -> zbus::Result<()>;
|
||||||
fn notify_action(&self, action: &GfxRequiredUserAction) -> zbus::Result<()>;
|
fn notify_action(&self, action: &GfxRequiredUserAction) -> zbus::Result<()>;
|
||||||
@@ -48,8 +49,11 @@ impl Dbus for CtrlGraphics {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn power(&self) -> String {
|
fn power(&self) -> zbus::fdo::Result<GfxPower> {
|
||||||
Self::get_runtime_status().unwrap_or_else(|err| format!("Get power status failed: {}", err))
|
Self::get_runtime_status().map_err(|err| {
|
||||||
|
error!("GFX: {}", err);
|
||||||
|
zbus::fdo::Error::Failed(format!("GFX fail: {}", err))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_vendor(&mut self, vendor: GfxVendors) -> zbus::fdo::Result<GfxRequiredUserAction> {
|
fn set_vendor(&mut self, vendor: GfxVendors) -> zbus::fdo::Result<GfxRequiredUserAction> {
|
||||||
@@ -75,7 +79,7 @@ impl Dbus for CtrlGraphics {
|
|||||||
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("/org/asuslinux/Gfx", self)
|
.at(&ObjectPath::from_str_unchecked("/org/asuslinux/Gfx"), self)
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
warn!("GFX: CtrlGraphics: add_to_server {}", err);
|
warn!("GFX: CtrlGraphics: add_to_server {}", err);
|
||||||
err
|
err
|
||||||
@@ -95,10 +99,8 @@ impl Reloadable for CtrlGraphics {
|
|||||||
impl CtrlGraphics {
|
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!("GFX: Rescanning PCI bus");
|
info!("GFX: Rescanning PCI bus");
|
||||||
bus.rescan()?;
|
bus.rescan()?;
|
||||||
|
|
||||||
let devs = PciDevice::all()?;
|
let devs = PciDevice::all()?;
|
||||||
|
|
||||||
let functions = |parent: &PciDevice| -> Vec<PciDevice> {
|
let functions = |parent: &PciDevice| -> Vec<PciDevice> {
|
||||||
@@ -166,10 +168,10 @@ impl CtrlGraphics {
|
|||||||
/// Save the selected `Vendor` mode to config
|
/// Save the selected `Vendor` mode to config
|
||||||
fn save_gfx_mode(vendor: GfxVendors, config: Arc<Mutex<Config>>) {
|
fn save_gfx_mode(vendor: GfxVendors, config: Arc<Mutex<Config>>) {
|
||||||
if let Ok(mut config) = config.lock() {
|
if let Ok(mut config) = config.lock() {
|
||||||
|
config.gfx_last_mode = config.gfx_mode;
|
||||||
config.gfx_mode = vendor;
|
config.gfx_mode = vendor;
|
||||||
config.write();
|
config.write();
|
||||||
}
|
}
|
||||||
// TODO: Error here
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Associated method to get which vendor mode is set
|
/// Associated method to get which vendor mode is set
|
||||||
@@ -181,12 +183,22 @@ impl CtrlGraphics {
|
|||||||
Ok(GfxVendors::Hybrid)
|
Ok(GfxVendors::Hybrid)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_runtime_status() -> Result<String, RogError> {
|
fn get_runtime_status() -> Result<GfxPower, RogError> {
|
||||||
const PATH: &str = "/sys/bus/pci/devices/0000:01:00.0/power/runtime_status";
|
let path = Path::new("/sys/bus/pci/devices/0000:01:00.0/power/runtime_status");
|
||||||
let buf = std::fs::read_to_string(PATH).map_err(|err| RogError::Read(PATH.into(), err))?;
|
if path.exists() {
|
||||||
Ok(buf)
|
let buf = std::fs::read_to_string(path).map_err(|err| {
|
||||||
|
RogError::Read(
|
||||||
|
"/sys/bus/pci/devices/0000:01:00.0/power/runtime_status".to_string(),
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
Ok(GfxPower::from_str(&buf)?)
|
||||||
|
} else {
|
||||||
|
Ok(GfxPower::Off)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Some systems have a fallback service to load nouveau if nvidia fails
|
||||||
fn toggle_fallback_service(vendor: GfxVendors) -> Result<(), RogError> {
|
fn toggle_fallback_service(vendor: GfxVendors) -> Result<(), RogError> {
|
||||||
let action = if vendor == GfxVendors::Nvidia {
|
let action = if vendor == GfxVendors::Nvidia {
|
||||||
info!("GFX: Enabling nvidia-fallback.service");
|
info!("GFX: Enabling nvidia-fallback.service");
|
||||||
@@ -213,6 +225,7 @@ impl CtrlGraphics {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Write the appropriate xorg config for the chosen mode
|
||||||
fn write_xorg_conf(vendor: GfxVendors) -> Result<(), RogError> {
|
fn write_xorg_conf(vendor: GfxVendors) -> Result<(), RogError> {
|
||||||
let text = if vendor == GfxVendors::Nvidia {
|
let text = if vendor == GfxVendors::Nvidia {
|
||||||
[PRIMARY_GPU_BEGIN, PRIMARY_GPU_NVIDIA, PRIMARY_GPU_END].concat()
|
[PRIMARY_GPU_BEGIN, PRIMARY_GPU_NVIDIA, PRIMARY_GPU_END].concat()
|
||||||
@@ -239,6 +252,7 @@ impl CtrlGraphics {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates the full modprobe.conf required for vfio pass-through
|
||||||
fn get_vfio_conf(devices: &[GraphicsDevice]) -> Vec<u8> {
|
fn get_vfio_conf(devices: &[GraphicsDevice]) -> Vec<u8> {
|
||||||
let mut vifo = MODPROBE_VFIO.to_vec();
|
let mut vifo = MODPROBE_VFIO.to_vec();
|
||||||
for (d_count, dev) in devices.iter().enumerate() {
|
for (d_count, dev) in devices.iter().enumerate() {
|
||||||
@@ -268,10 +282,14 @@ impl CtrlGraphics {
|
|||||||
fn write_modprobe_conf(vendor: GfxVendors, devices: &[GraphicsDevice]) -> Result<(), RogError> {
|
fn write_modprobe_conf(vendor: GfxVendors, devices: &[GraphicsDevice]) -> Result<(), RogError> {
|
||||||
info!("GFX: Writing {}", MODPROBE_PATH);
|
info!("GFX: Writing {}", MODPROBE_PATH);
|
||||||
let content = match vendor {
|
let content = match vendor {
|
||||||
GfxVendors::Nvidia | GfxVendors::Hybrid | GfxVendors::Compute => MODPROBE_BASE.to_vec(),
|
GfxVendors::Nvidia | GfxVendors::Hybrid => {
|
||||||
|
let mut base = MODPROBE_BASE.to_vec();
|
||||||
|
base.append(&mut MODPROBE_DRM_MODESET.to_vec());
|
||||||
|
base
|
||||||
|
}
|
||||||
GfxVendors::Vfio => Self::get_vfio_conf(devices),
|
GfxVendors::Vfio => Self::get_vfio_conf(devices),
|
||||||
// GfxVendors::Compute => {}
|
|
||||||
GfxVendors::Integrated => MODPROBE_INTEGRATED.to_vec(),
|
GfxVendors::Integrated => MODPROBE_INTEGRATED.to_vec(),
|
||||||
|
GfxVendors::Compute => MODPROBE_BASE.to_vec(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut file = std::fs::OpenOptions::new()
|
let mut file = std::fs::OpenOptions::new()
|
||||||
@@ -303,7 +321,7 @@ impl CtrlGraphics {
|
|||||||
.map_err(|err| RogError::Command("device unbind error".into(), err))
|
.map_err(|err| RogError::Command("device unbind error".into(), err))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_driver_action(driver: &str, action: &str) -> Result<(), RogError> {
|
fn do_driver_action(driver: &str, action: &str) -> Result<(), GfxError> {
|
||||||
let mut cmd = Command::new(action);
|
let mut cmd = Command::new(action);
|
||||||
cmd.arg(driver);
|
cmd.arg(driver);
|
||||||
|
|
||||||
@@ -318,7 +336,7 @@ impl CtrlGraphics {
|
|||||||
|
|
||||||
let output = cmd
|
let output = cmd
|
||||||
.output()
|
.output()
|
||||||
.map_err(|err| RogError::Command(format!("{:?}", cmd), err))?;
|
.map_err(|err| GfxError::Command(format!("{:?}", cmd), err))?;
|
||||||
if !output.status.success() {
|
if !output.status.success() {
|
||||||
if output
|
if output
|
||||||
.stderr
|
.stderr
|
||||||
@@ -326,6 +344,9 @@ impl CtrlGraphics {
|
|||||||
{
|
{
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
if output.stderr.ends_with("is builtin.\n".as_bytes()) {
|
||||||
|
return Err(GfxError::VfioBuiltin);
|
||||||
|
}
|
||||||
if output.stderr.ends_with("Permission denied\n".as_bytes()) {
|
if output.stderr.ends_with("Permission denied\n".as_bytes()) {
|
||||||
warn!(
|
warn!(
|
||||||
"{} {} failed: {:?}",
|
"{} {} failed: {:?}",
|
||||||
@@ -336,6 +357,11 @@ impl CtrlGraphics {
|
|||||||
warn!("GFX: It may be safe to ignore the above error, run `lsmod |grep {}` to confirm modules loaded", driver);
|
warn!("GFX: It may be safe to ignore the above error, run `lsmod |grep {}` to confirm modules loaded", driver);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
if String::from_utf8_lossy(&output.stderr)
|
||||||
|
.contains(&format!("Module {} not found", driver))
|
||||||
|
{
|
||||||
|
return Err(GfxError::MissingModule(driver.into()));
|
||||||
|
}
|
||||||
if count >= MAX_TRIES {
|
if count >= MAX_TRIES {
|
||||||
let msg = format!(
|
let msg = format!(
|
||||||
"{} {} failed: {:?}",
|
"{} {} failed: {:?}",
|
||||||
@@ -343,14 +369,14 @@ impl CtrlGraphics {
|
|||||||
driver,
|
driver,
|
||||||
String::from_utf8_lossy(&output.stderr)
|
String::from_utf8_lossy(&output.stderr)
|
||||||
);
|
);
|
||||||
return Err(RogError::Modprobe(msg));
|
return Err(GfxError::Modprobe(msg));
|
||||||
}
|
}
|
||||||
} else if output.status.success() {
|
} else if output.status.success() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
count += 1;
|
count += 1;
|
||||||
std::thread::sleep(std::time::Duration::from_millis(250));
|
std::thread::sleep(std::time::Duration::from_millis(50));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -397,9 +423,13 @@ impl CtrlGraphics {
|
|||||||
fn logout_required(&self, vendor: GfxVendors) -> GfxRequiredUserAction {
|
fn logout_required(&self, vendor: GfxVendors) -> GfxRequiredUserAction {
|
||||||
if let Ok(config) = self.config.lock() {
|
if let Ok(config) = self.config.lock() {
|
||||||
let current = config.gfx_mode;
|
let current = config.gfx_mode;
|
||||||
if matches!(current, GfxVendors::Integrated | GfxVendors::Vfio)
|
if matches!(
|
||||||
&& matches!(vendor, GfxVendors::Integrated | GfxVendors::Vfio)
|
current,
|
||||||
{
|
GfxVendors::Integrated | GfxVendors::Vfio | GfxVendors::Compute
|
||||||
|
) && matches!(
|
||||||
|
vendor,
|
||||||
|
GfxVendors::Integrated | GfxVendors::Vfio | GfxVendors::Compute
|
||||||
|
) {
|
||||||
return GfxRequiredUserAction::None;
|
return GfxRequiredUserAction::None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -419,6 +449,7 @@ impl CtrlGraphics {
|
|||||||
/// The daemon needs direct access to this function when it detects that the
|
/// The daemon needs direct access to this function when it detects that the
|
||||||
pub fn do_vendor_tasks(
|
pub fn do_vendor_tasks(
|
||||||
vendor: GfxVendors,
|
vendor: GfxVendors,
|
||||||
|
vfio_enable: bool,
|
||||||
devices: &[GraphicsDevice],
|
devices: &[GraphicsDevice],
|
||||||
bus: &PciBus,
|
bus: &PciBus,
|
||||||
) -> Result<(), RogError> {
|
) -> Result<(), RogError> {
|
||||||
@@ -431,23 +462,33 @@ impl CtrlGraphics {
|
|||||||
|
|
||||||
match vendor {
|
match vendor {
|
||||||
GfxVendors::Nvidia | GfxVendors::Hybrid | GfxVendors::Compute => {
|
GfxVendors::Nvidia | GfxVendors::Hybrid | GfxVendors::Compute => {
|
||||||
for driver in VFIO_DRIVERS.iter() {
|
if vfio_enable {
|
||||||
Self::do_driver_action(driver, "rmmod")?;
|
for driver in VFIO_DRIVERS.iter() {
|
||||||
|
Self::do_driver_action(driver, "rmmod")?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for driver in NVIDIA_DRIVERS.iter() {
|
for driver in NVIDIA_DRIVERS.iter() {
|
||||||
Self::do_driver_action(driver, "modprobe")?;
|
Self::do_driver_action(driver, "modprobe")?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GfxVendors::Vfio => {
|
GfxVendors::Vfio => {
|
||||||
for driver in NVIDIA_DRIVERS.iter() {
|
if vfio_enable {
|
||||||
Self::do_driver_action(driver, "rmmod")?;
|
Self::do_driver_action("nouveau", "rmmod")?;
|
||||||
|
for driver in NVIDIA_DRIVERS.iter() {
|
||||||
|
Self::do_driver_action(driver, "rmmod")?;
|
||||||
|
}
|
||||||
|
Self::unbind_only(&devices)?;
|
||||||
|
Self::do_driver_action("vfio-pci", "modprobe")?;
|
||||||
|
} else {
|
||||||
|
return Err(GfxError::VfioDisabled.into());
|
||||||
}
|
}
|
||||||
Self::unbind_only(&devices)?;
|
|
||||||
Self::do_driver_action("vfio-pci", "modprobe")?;
|
|
||||||
}
|
}
|
||||||
GfxVendors::Integrated => {
|
GfxVendors::Integrated => {
|
||||||
for driver in VFIO_DRIVERS.iter() {
|
Self::do_driver_action("nouveau", "rmmod")?;
|
||||||
Self::do_driver_action(driver, "rmmod")?;
|
if vfio_enable {
|
||||||
|
for driver in VFIO_DRIVERS.iter() {
|
||||||
|
Self::do_driver_action(driver, "rmmod")?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for driver in NVIDIA_DRIVERS.iter() {
|
for driver in NVIDIA_DRIVERS.iter() {
|
||||||
Self::do_driver_action(driver, "rmmod")?;
|
Self::do_driver_action(driver, "rmmod")?;
|
||||||
@@ -455,22 +496,23 @@ impl CtrlGraphics {
|
|||||||
Self::unbind_remove_nvidia(&devices)?;
|
Self::unbind_remove_nvidia(&devices)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn graphical_session_alive(
|
/// Check if the user has any graphical uiser sessions that are active or online
|
||||||
|
fn graphical_user_sessions_exist(
|
||||||
connection: &Connection,
|
connection: &Connection,
|
||||||
sessions: &[SessionInfo],
|
sessions: &[SessionInfo],
|
||||||
) -> Result<bool, RogError> {
|
) -> Result<bool, RogError> {
|
||||||
for session in sessions {
|
for session in sessions {
|
||||||
let session_proxy = SessionProxy::new(&connection, session)?;
|
let session_proxy = SessionProxy::new(connection, session)?;
|
||||||
if session_proxy.get_class()? == SessionClass::User {
|
if session_proxy.get_class()? == SessionClass::User {
|
||||||
match session_proxy.get_type()? {
|
match session_proxy.get_type()? {
|
||||||
SessionType::X11 | SessionType::Wayland | SessionType::MIR => {
|
SessionType::X11 | SessionType::Wayland | SessionType::MIR => {
|
||||||
//if session_proxy.get_active()? {
|
match session_proxy.get_state()? {
|
||||||
return Ok(true);
|
SessionState::Online | SessionState::Active => return Ok(true),
|
||||||
//}
|
SessionState::Closing | SessionState::Invalid => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@@ -499,12 +541,11 @@ impl CtrlGraphics {
|
|||||||
loop {
|
loop {
|
||||||
let tmp = manager.list_sessions()?;
|
let tmp = manager.list_sessions()?;
|
||||||
if !tmp.iter().eq(&sessions) {
|
if !tmp.iter().eq(&sessions) {
|
||||||
warn!("GFX: Sessions list changed");
|
info!("GFX thread: Sessions list changed");
|
||||||
warn!("GFX: Old list:\n{:?}\nNew list:\n{:?}", &sessions, &tmp);
|
|
||||||
sessions = tmp;
|
sessions = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !Self::graphical_session_alive(&connection, &sessions)? {
|
if !Self::graphical_user_sessions_exist(&connection, &sessions)? {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -523,36 +564,28 @@ impl CtrlGraphics {
|
|||||||
sleep(SLEEP_PERIOD);
|
sleep(SLEEP_PERIOD);
|
||||||
}
|
}
|
||||||
|
|
||||||
info!("GFX: all graphical user sessions ended, continuing");
|
info!("GFX thread: all graphical user sessions ended, continuing");
|
||||||
Self::do_display_manager_action("stop")?;
|
Self::do_display_manager_action("stop")?;
|
||||||
|
Self::wait_display_manager_state("inactive")?;
|
||||||
|
|
||||||
match Self::wait_display_manager_state("inactive") {
|
let vfio_enable = if let Ok(config) = config.lock() {
|
||||||
Ok(_) => info!("GFX: display-manager stopped"),
|
config.gfx_vfio_enable
|
||||||
Err(err) => {
|
} else {
|
||||||
warn!("GFX: {}", err);
|
false
|
||||||
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_vendor_tasks(vendor, vfio_enable, &devices, &bus)?;
|
||||||
Self::do_display_manager_action("start")?;
|
Self::do_display_manager_action("restart")?;
|
||||||
|
|
||||||
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
|
// Save selected mode in case of reboot
|
||||||
Self::save_gfx_mode(vendor, config);
|
Self::save_gfx_mode(vendor, config);
|
||||||
info!("GFX: display-manager started");
|
info!("GFX thread: display-manager started");
|
||||||
|
|
||||||
let v: &str = vendor.into();
|
let v: &str = vendor.into();
|
||||||
info!("GFX: Graphics mode changed to {} successfully", v);
|
info!("GFX thread: Graphics mode changed to {} successfully", v);
|
||||||
Ok(format!("Graphics mode changed to {} successfully", v))
|
Ok(format!("Graphics mode changed to {} successfully", v))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Before starting a new thread the old one *must* be cancelled
|
||||||
fn cancel_thread(&self) {
|
fn cancel_thread(&self) {
|
||||||
if let Ok(lock) = self.thread_kill.lock() {
|
if let Ok(lock) = self.thread_kill.lock() {
|
||||||
if let Some(tx) = lock.as_ref() {
|
if let Some(tx) = lock.as_ref() {
|
||||||
@@ -560,7 +593,7 @@ impl CtrlGraphics {
|
|||||||
info!("GFX: Cancelling previous thread");
|
info!("GFX: Cancelling previous thread");
|
||||||
tx.send(true)
|
tx.send(true)
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
warn!("GFX: {}", err);
|
warn!("GFX thread: {}", err);
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
@@ -605,6 +638,17 @@ impl CtrlGraphics {
|
|||||||
return Err(GfxError::GsyncModeActive.into());
|
return Err(GfxError::GsyncModeActive.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let vfio_enable = if let Ok(config) = self.config.lock() {
|
||||||
|
config.gfx_vfio_enable
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
if !vfio_enable && matches!(vendor, GfxVendors::Vfio) {
|
||||||
|
return Err(GfxError::VfioDisabled.into());
|
||||||
|
}
|
||||||
|
|
||||||
// Must always cancel any thread running
|
// Must always cancel any thread running
|
||||||
self.cancel_thread();
|
self.cancel_thread();
|
||||||
// determine which method we need here
|
// determine which method we need here
|
||||||
@@ -618,7 +662,15 @@ impl CtrlGraphics {
|
|||||||
info!("GFX: mode change does not require logout");
|
info!("GFX: mode change does not require logout");
|
||||||
let devices = self.nvidia.clone();
|
let devices = self.nvidia.clone();
|
||||||
let bus = self.bus.clone();
|
let bus = self.bus.clone();
|
||||||
Self::do_vendor_tasks(vendor, &devices, &bus)?;
|
Self::do_vendor_tasks(vendor, vfio_enable, &devices, &bus)?;
|
||||||
|
info!("GFX: Graphics mode changed to {}", <&str>::from(vendor));
|
||||||
|
if let Ok(config) = self.config.lock() {
|
||||||
|
if matches!(vendor, GfxVendors::Compute | GfxVendors::Vfio)
|
||||||
|
&& config.gfx_save_compute_vfio
|
||||||
|
{
|
||||||
|
Self::save_gfx_mode(vendor, self.config.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// TODO: undo if failed? Save last mode, catch errors...
|
// TODO: undo if failed? Save last mode, catch errors...
|
||||||
Ok(action_required)
|
Ok(action_required)
|
||||||
@@ -629,7 +681,14 @@ impl CtrlGraphics {
|
|||||||
let vendor = self.get_gfx_mode()?;
|
let vendor = self.get_gfx_mode()?;
|
||||||
let devices = self.nvidia.clone();
|
let devices = self.nvidia.clone();
|
||||||
let bus = self.bus.clone();
|
let bus = self.bus.clone();
|
||||||
Self::do_vendor_tasks(vendor, &devices, &bus)?;
|
|
||||||
|
let vfio_enable = if let Ok(config) = self.config.lock() {
|
||||||
|
config.gfx_vfio_enable
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
Self::do_vendor_tasks(vendor, vfio_enable, &devices, &bus)?;
|
||||||
Self::toggle_fallback_service(vendor)?;
|
Self::toggle_fallback_service(vendor)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ static MODPROBE_BASE: &[u8] = br#"# Automatically generated by asusd
|
|||||||
blacklist nouveau
|
blacklist nouveau
|
||||||
alias nouveau off
|
alias nouveau off
|
||||||
options nvidia NVreg_DynamicPowerManagement=0x02
|
options nvidia NVreg_DynamicPowerManagement=0x02
|
||||||
|
"#;
|
||||||
|
|
||||||
|
static MODPROBE_DRM_MODESET: &[u8] = br#"
|
||||||
options nvidia-drm modeset=1
|
options nvidia-drm modeset=1
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
// Only these two packets must be 17 bytes
|
// Only these two packets must be 17 bytes
|
||||||
static LED_APPLY: [u8; 17] = [0x5d, 0xb4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
|
||||||
static LED_SET: [u8; 17] = [0x5d, 0xb5, 0, 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::{
|
||||||
@@ -10,29 +7,22 @@ use crate::{
|
|||||||
laptops::{LaptopLedData, ASUS_KEYBOARD_DEVICES},
|
laptops::{LaptopLedData, ASUS_KEYBOARD_DEVICES},
|
||||||
};
|
};
|
||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
use rog_types::{
|
use rog_aura::{
|
||||||
aura_modes::{AuraEffect, AuraModeNum, LedBrightness},
|
usb::{LED_APPLY, LED_AWAKE_OFF, LED_AWAKE_ON, LED_SET, LED_SLEEP_OFF, LED_SLEEP_ON},
|
||||||
LED_MSG_LEN,
|
AuraEffect, LedBrightness, LED_MSG_LEN,
|
||||||
};
|
};
|
||||||
|
use rog_types::supported::LedSupportedFunctions;
|
||||||
use std::fs::OpenOptions;
|
use std::fs::OpenOptions;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, 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;
|
||||||
|
use zvariant::ObjectPath;
|
||||||
|
|
||||||
use crate::GetSupported;
|
use crate::GetSupported;
|
||||||
|
|
||||||
use serde_derive::{Deserialize, Serialize};
|
impl GetSupported for CtrlKbdLed {
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub struct LedSupportedFunctions {
|
|
||||||
pub brightness_set: bool,
|
|
||||||
pub stock_led_modes: Option<Vec<AuraModeNum>>,
|
|
||||||
pub multizone_led_mode: bool,
|
|
||||||
pub per_key_led_mode: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GetSupported for CtrlKbdBacklight {
|
|
||||||
type A = LedSupportedFunctions;
|
type A = LedSupportedFunctions;
|
||||||
|
|
||||||
fn get_supported() -> Self::A {
|
fn get_supported() -> Self::A {
|
||||||
@@ -47,7 +37,7 @@ impl GetSupported for CtrlKbdBacklight {
|
|||||||
};
|
};
|
||||||
|
|
||||||
LedSupportedFunctions {
|
LedSupportedFunctions {
|
||||||
brightness_set: CtrlKbdBacklight::get_kbd_bright_path().is_some(),
|
brightness_set: CtrlKbdLed::get_kbd_bright_path().is_some(),
|
||||||
stock_led_modes,
|
stock_led_modes,
|
||||||
multizone_led_mode,
|
multizone_led_mode,
|
||||||
per_key_led_mode,
|
per_key_led_mode,
|
||||||
@@ -55,7 +45,7 @@ impl GetSupported for CtrlKbdBacklight {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CtrlKbdBacklight {
|
pub struct CtrlKbdLed {
|
||||||
led_node: Option<String>,
|
led_node: Option<String>,
|
||||||
pub bright_node: String,
|
pub bright_node: String,
|
||||||
supported_modes: LaptopLedData,
|
supported_modes: LaptopLedData,
|
||||||
@@ -63,28 +53,67 @@ pub struct CtrlKbdBacklight {
|
|||||||
config: AuraConfig,
|
config: AuraConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DbusKbdBacklight {
|
pub struct CtrlKbdLedTask(pub Arc<Mutex<CtrlKbdLed>>);
|
||||||
inner: Arc<Mutex<CtrlKbdBacklight>>,
|
|
||||||
|
impl crate::CtrlTask for CtrlKbdLedTask {
|
||||||
|
fn do_task(&self) -> Result<(), RogError> {
|
||||||
|
if let Ok(mut lock) = self.0.try_lock() {
|
||||||
|
let mut file = OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.open(&lock.bright_node)
|
||||||
|
.map_err(|err| match err.kind() {
|
||||||
|
std::io::ErrorKind::NotFound => {
|
||||||
|
RogError::MissingLedBrightNode((&lock.bright_node).into(), err)
|
||||||
|
}
|
||||||
|
_ => RogError::Path((&lock.bright_node).into(), err),
|
||||||
|
})?;
|
||||||
|
let mut buf = [0u8; 1];
|
||||||
|
file.read_exact(&mut buf)
|
||||||
|
.map_err(|err| RogError::Read("buffer".into(), err))?;
|
||||||
|
if let Some(num) = char::from(buf[0]).to_digit(10) {
|
||||||
|
if lock.config.brightness != num.into() {
|
||||||
|
lock.config.read();
|
||||||
|
lock.config.brightness = num.into();
|
||||||
|
lock.config.write();
|
||||||
|
}
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
return Err(RogError::ParseLed);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DbusKbdBacklight {
|
pub struct CtrlKbdLedReloader(pub Arc<Mutex<CtrlKbdLed>>);
|
||||||
pub fn new(inner: Arc<Mutex<CtrlKbdBacklight>>) -> Self {
|
|
||||||
|
impl crate::Reloadable for CtrlKbdLedReloader {
|
||||||
|
fn reload(&mut self) -> Result<(), RogError> {
|
||||||
|
if let Ok(mut lock) = self.0.try_lock() {
|
||||||
|
let current = lock.config.current_mode;
|
||||||
|
if let Some(mode) = lock.config.builtins.get(¤t).cloned() {
|
||||||
|
lock.do_command(mode).ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct CtrlKbdLedZbus {
|
||||||
|
inner: Arc<Mutex<CtrlKbdLed>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CtrlKbdLedZbus {
|
||||||
|
pub fn new(inner: Arc<Mutex<CtrlKbdLed>>) -> Self {
|
||||||
Self { inner }
|
Self { inner }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Dbus {
|
impl crate::ZbusAdd for CtrlKbdLedZbus {
|
||||||
fn set_led(&mut self, data: String);
|
|
||||||
fn ledmode(&self) -> String;
|
|
||||||
fn notify_led(&self, data: &str) -> zbus::Result<()>;
|
|
||||||
}
|
|
||||||
|
|
||||||
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", self)
|
.at(&ObjectPath::from_str_unchecked("/org/asuslinux/Led"), self)
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
error!("DbusKbdBacklight: add_to_server {}", err);
|
error!("DbusKbdLed: add_to_server {}", err);
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
@@ -94,7 +123,8 @@ impl crate::ZbusAdd for DbusKbdBacklight {
|
|||||||
///
|
///
|
||||||
/// LED commands are split between Brightness, Modes, Per-Key
|
/// LED commands are split between Brightness, Modes, Per-Key
|
||||||
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
||||||
impl DbusKbdBacklight {
|
impl CtrlKbdLedZbus {
|
||||||
|
/// Set the keyboard brightness level (0-3)
|
||||||
fn set_brightness(&mut self, brightness: LedBrightness) {
|
fn set_brightness(&mut self, brightness: LedBrightness) {
|
||||||
if let Ok(ctrl) = self.inner.try_lock() {
|
if let Ok(ctrl) = self.inner.try_lock() {
|
||||||
ctrl.set_brightness(brightness)
|
ctrl.set_brightness(brightness)
|
||||||
@@ -103,6 +133,24 @@ impl DbusKbdBacklight {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the keyboard LED to enabled while the device is awake
|
||||||
|
fn set_awake_enabled(&mut self, enabled: bool) {
|
||||||
|
if let Ok(ctrl) = self.inner.try_lock() {
|
||||||
|
ctrl.set_awake_enable(enabled)
|
||||||
|
.map_err(|err| warn!("{}", err))
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the keyboard LED suspend animation to enabled while the device is suspended
|
||||||
|
fn set_sleep_enabled(&mut self, enabled: bool) {
|
||||||
|
if let Ok(ctrl) = self.inner.try_lock() {
|
||||||
|
ctrl.set_sleep_anim_enable(enabled)
|
||||||
|
.map_err(|err| warn!("{}", err))
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn set_led_mode(&mut self, effect: AuraEffect) {
|
fn set_led_mode(&mut self, effect: AuraEffect) {
|
||||||
if let Ok(mut ctrl) = self.inner.try_lock() {
|
if let Ok(mut ctrl) = self.inner.try_lock() {
|
||||||
let mode_name = effect.mode_name();
|
let mode_name = effect.mode_name();
|
||||||
@@ -185,74 +233,7 @@ impl DbusKbdBacklight {
|
|||||||
fn notify_led(&self, data: &str) -> zbus::Result<()>;
|
fn notify_led(&self, data: &str) -> zbus::Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl crate::Reloadable for CtrlKbdBacklight {
|
impl CtrlKbdLed {
|
||||||
fn reload(&mut self) -> Result<(), RogError> {
|
|
||||||
// set current mode (if any)
|
|
||||||
if self.supported_modes.standard.len() > 1 {
|
|
||||||
let current_mode = self.config.current_mode;
|
|
||||||
if self.supported_modes.standard.contains(&(current_mode)) {
|
|
||||||
let mode = self
|
|
||||||
.config
|
|
||||||
.builtins
|
|
||||||
.get(¤t_mode)
|
|
||||||
.ok_or(RogError::NotSupported)?
|
|
||||||
.to_owned();
|
|
||||||
self.write_mode(&mode)?;
|
|
||||||
info!("Reloaded last used mode");
|
|
||||||
} else {
|
|
||||||
warn!(
|
|
||||||
"An unsupported mode was set: {}, reset to first mode available",
|
|
||||||
<&str>::from(&self.config.current_mode)
|
|
||||||
);
|
|
||||||
self.config.builtins.remove(¤t_mode);
|
|
||||||
self.config.current_mode = AuraModeNum::Static;
|
|
||||||
// TODO: do a recursive call with a boxed dyn future later
|
|
||||||
let mode = self
|
|
||||||
.config
|
|
||||||
.builtins
|
|
||||||
.get(¤t_mode)
|
|
||||||
.ok_or(RogError::NotSupported)?
|
|
||||||
.to_owned();
|
|
||||||
self.write_mode(&mode)?;
|
|
||||||
info!("Reloaded last used mode");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reload brightness
|
|
||||||
let bright = self.config.brightness;
|
|
||||||
self.set_brightness(bright)?;
|
|
||||||
info!("Reloaded last used brightness");
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl crate::CtrlTask for CtrlKbdBacklight {
|
|
||||||
fn do_task(&mut self) -> Result<(), RogError> {
|
|
||||||
let mut file = OpenOptions::new()
|
|
||||||
.read(true)
|
|
||||||
.open(&self.bright_node)
|
|
||||||
.map_err(|err| match err.kind() {
|
|
||||||
std::io::ErrorKind::NotFound => {
|
|
||||||
RogError::MissingLedBrightNode((&self.bright_node).into(), err)
|
|
||||||
}
|
|
||||||
_ => RogError::Path((&self.bright_node).into(), err),
|
|
||||||
})?;
|
|
||||||
let mut buf = [0u8; 1];
|
|
||||||
file.read_exact(&mut buf)
|
|
||||||
.map_err(|err| RogError::Read("buffer".into(), err))?;
|
|
||||||
if let Some(num) = char::from(buf[0]).to_digit(10) {
|
|
||||||
if self.config.brightness != num.into() {
|
|
||||||
self.config.read();
|
|
||||||
self.config.brightness = num.into();
|
|
||||||
self.config.write();
|
|
||||||
}
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
Err(RogError::ParseLED)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CtrlKbdBacklight {
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(supported_modes: LaptopLedData, config: AuraConfig) -> Result<Self, RogError> {
|
pub fn new(supported_modes: LaptopLedData, config: AuraConfig) -> Result<Self, RogError> {
|
||||||
// TODO: return error if *all* nodes are None
|
// TODO: return error if *all* nodes are None
|
||||||
@@ -282,7 +263,7 @@ impl CtrlKbdBacklight {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let ctrl = CtrlKbdBacklight {
|
let ctrl = CtrlKbdLed {
|
||||||
led_node,
|
led_node,
|
||||||
bright_node: bright_node.unwrap(), // If was none then we already returned above
|
bright_node: bright_node.unwrap(), // If was none then we already returned above
|
||||||
supported_modes,
|
supported_modes,
|
||||||
@@ -299,7 +280,7 @@ impl CtrlKbdBacklight {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_brightness(&self) -> Result<u8, RogError> {
|
fn get_brightness(&self) -> Result<u8, RogError> {
|
||||||
let mut file = OpenOptions::new()
|
let mut file = OpenOptions::new()
|
||||||
.read(true)
|
.read(true)
|
||||||
.open(&self.bright_node)
|
.open(&self.bright_node)
|
||||||
@@ -315,7 +296,7 @@ impl CtrlKbdBacklight {
|
|||||||
Ok(buf[0])
|
Ok(buf[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_brightness(&self, brightness: LedBrightness) -> Result<(), RogError> {
|
fn set_brightness(&self, brightness: LedBrightness) -> Result<(), RogError> {
|
||||||
let path = Path::new(&self.bright_node);
|
let path = Path::new(&self.bright_node);
|
||||||
let mut file =
|
let mut file =
|
||||||
OpenOptions::new()
|
OpenOptions::new()
|
||||||
@@ -332,6 +313,26 @@ impl CtrlKbdBacklight {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the keyboard LED to active if laptop is awake
|
||||||
|
fn set_awake_enable(&self, enabled: bool) -> Result<(), RogError> {
|
||||||
|
let bytes = if enabled { LED_AWAKE_ON } else { LED_AWAKE_OFF };
|
||||||
|
self.write_bytes(&bytes)?;
|
||||||
|
self.write_bytes(&LED_SET)?;
|
||||||
|
// Changes won't persist unless apply is set
|
||||||
|
self.write_bytes(&LED_APPLY)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the keyboard suspend animation to on if plugged in
|
||||||
|
fn set_sleep_anim_enable(&self, enabled: bool) -> Result<(), RogError> {
|
||||||
|
let bytes = if enabled { LED_SLEEP_ON } else { LED_SLEEP_OFF };
|
||||||
|
self.write_bytes(&bytes)?;
|
||||||
|
self.write_bytes(&LED_SET)?;
|
||||||
|
// Changes won't persist unless apply is set
|
||||||
|
self.write_bytes(&LED_APPLY)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn find_led_node(id_product: &str) -> Result<String, RogError> {
|
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);
|
||||||
|
|||||||
@@ -1,197 +1,40 @@
|
|||||||
|
pub mod zbus;
|
||||||
|
|
||||||
use crate::error::RogError;
|
use crate::error::RogError;
|
||||||
use crate::{
|
use crate::{config::Config, GetSupported};
|
||||||
config::{Config, Profile},
|
|
||||||
GetSupported,
|
|
||||||
};
|
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
use rog_types::profile::{FanLevel, ProfileEvent};
|
use rog_types::{
|
||||||
use serde_derive::{Deserialize, Serialize};
|
profile::{FanLevel, Profile, ProfileEvent},
|
||||||
|
supported::FanCpuSupportedFunctions,
|
||||||
|
};
|
||||||
use std::fs::OpenOptions;
|
use std::fs::OpenOptions;
|
||||||
use std::io::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, 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";
|
||||||
static AMD_BOOST_PATH: &str = "/sys/devices/system/cpu/cpufreq/boost";
|
static AMD_BOOST_PATH: &str = "/sys/devices/system/cpu/cpufreq/boost";
|
||||||
|
|
||||||
pub struct CtrlFanAndCPU {
|
pub struct CtrlFanAndCpu {
|
||||||
pub path: &'static str,
|
pub path: &'static str,
|
||||||
config: Arc<Mutex<Config>>,
|
config: Arc<Mutex<Config>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
impl GetSupported for CtrlFanAndCpu {
|
||||||
pub struct FanCpuSupportedFunctions {
|
|
||||||
pub stock_fan_modes: bool,
|
|
||||||
pub min_max_freq: bool,
|
|
||||||
pub fan_curve_set: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GetSupported for CtrlFanAndCPU {
|
|
||||||
type A = FanCpuSupportedFunctions;
|
type A = FanCpuSupportedFunctions;
|
||||||
|
|
||||||
fn get_supported() -> Self::A {
|
fn get_supported() -> Self::A {
|
||||||
FanCpuSupportedFunctions {
|
FanCpuSupportedFunctions {
|
||||||
stock_fan_modes: CtrlFanAndCPU::get_fan_path().is_ok(),
|
stock_fan_modes: CtrlFanAndCpu::get_fan_path().is_ok(),
|
||||||
min_max_freq: intel_pstate::PState::new().is_ok(),
|
min_max_freq: intel_pstate::PState::new().is_ok(),
|
||||||
fan_curve_set: rog_fan_curve::Board::from_board_name().is_some(),
|
fan_curve_set: rog_fan_curve::Board::from_board_name().is_some(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DbusFanAndCpu {
|
impl crate::Reloadable for CtrlFanAndCpu {
|
||||||
inner: Arc<Mutex<CtrlFanAndCPU>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DbusFanAndCpu {
|
|
||||||
pub fn new(inner: Arc<Mutex<CtrlFanAndCPU>>) -> Self {
|
|
||||||
Self { inner }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
|
||||||
impl DbusFanAndCpu {
|
|
||||||
/// Set profile details
|
|
||||||
fn set_profile(&self, profile: String) {
|
|
||||||
if let Ok(event) = serde_json::from_str(&profile) {
|
|
||||||
if let Ok(mut ctrl) = self.inner.try_lock() {
|
|
||||||
if let Ok(mut cfg) = ctrl.config.clone().try_lock() {
|
|
||||||
cfg.read();
|
|
||||||
ctrl.handle_profile_event(&event, &mut cfg)
|
|
||||||
.unwrap_or_else(|err| warn!("{}", err));
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Fetch the active profile name
|
|
||||||
fn next_profile(&mut self) {
|
|
||||||
if let Ok(mut ctrl) = self.inner.try_lock() {
|
|
||||||
if let Ok(mut cfg) = ctrl.config.clone().try_lock() {
|
|
||||||
cfg.read();
|
|
||||||
ctrl.do_next_profile(&mut cfg)
|
|
||||||
.unwrap_or_else(|err| warn!("{}", err));
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Fetch the active profile name
|
|
||||||
fn active_profile_name(&mut self) -> String {
|
|
||||||
if let Ok(ctrl) = self.inner.try_lock() {
|
|
||||||
if let Ok(mut cfg) = ctrl.config.try_lock() {
|
|
||||||
cfg.read();
|
|
||||||
return cfg.active_profile.clone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"Failed".to_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Fetch the active profile details
|
|
||||||
fn profile(&mut self) -> String {
|
|
||||||
if let Ok(ctrl) = self.inner.try_lock() {
|
|
||||||
if let Ok(mut cfg) = ctrl.config.try_lock() {
|
|
||||||
cfg.read();
|
|
||||||
if let Some(profile) = cfg.power_profiles.get(&cfg.active_profile) {
|
|
||||||
if let Ok(json) = serde_json::to_string(profile) {
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"Failed".to_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn profiles(&mut self) -> String {
|
|
||||||
if let Ok(ctrl) = self.inner.try_lock() {
|
|
||||||
if let Ok(mut cfg) = ctrl.config.try_lock() {
|
|
||||||
cfg.read();
|
|
||||||
if let Ok(json) = serde_json::to_string(&cfg.power_profiles) {
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"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)]
|
|
||||||
fn notify_profile(&self, profile: &str) -> zbus::Result<()> {}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl crate::ZbusAdd for DbusFanAndCpu {
|
|
||||||
fn add_to_server(self, server: &mut zbus::ObjectServer) {
|
|
||||||
server
|
|
||||||
.at("/org/asuslinux/Profile", self)
|
|
||||||
.map_err(|err| {
|
|
||||||
warn!("DbusFanAndCpu: add_to_server {}", err);
|
|
||||||
err
|
|
||||||
})
|
|
||||||
.ok();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl crate::Reloadable for CtrlFanAndCPU {
|
|
||||||
fn reload(&mut self) -> Result<(), RogError> {
|
fn reload(&mut self) -> Result<(), RogError> {
|
||||||
if let Ok(mut config) = self.config.clone().try_lock() {
|
if let Ok(mut config) = self.config.clone().try_lock() {
|
||||||
let profile = config.active_profile.clone();
|
let profile = config.active_profile.clone();
|
||||||
@@ -205,11 +48,11 @@ impl crate::Reloadable for CtrlFanAndCPU {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CtrlFanAndCPU {
|
impl CtrlFanAndCpu {
|
||||||
pub fn new(config: Arc<Mutex<Config>>) -> Result<Self, RogError> {
|
pub fn new(config: Arc<Mutex<Config>>) -> Result<Self, RogError> {
|
||||||
let path = CtrlFanAndCPU::get_fan_path()?;
|
let path = CtrlFanAndCpu::get_fan_path()?;
|
||||||
info!("Device has thermal throttle control");
|
info!("Device has thermal throttle control");
|
||||||
Ok(CtrlFanAndCPU { path, config })
|
Ok(CtrlFanAndCpu { path, config })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_fan_path() -> Result<&'static str, RogError> {
|
fn get_fan_path() -> Result<&'static str, RogError> {
|
||||||
@@ -0,0 +1,255 @@
|
|||||||
|
use log::warn;
|
||||||
|
use rog_fan_curve::Curve;
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
use zbus::{dbus_interface, fdo::Error};
|
||||||
|
use zvariant::ObjectPath;
|
||||||
|
|
||||||
|
use super::CtrlFanAndCpu;
|
||||||
|
|
||||||
|
pub struct FanAndCpuZbus {
|
||||||
|
inner: Arc<Mutex<CtrlFanAndCpu>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FanAndCpuZbus {
|
||||||
|
pub fn new(inner: Arc<Mutex<CtrlFanAndCpu>>) -> Self {
|
||||||
|
Self { inner }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
||||||
|
impl FanAndCpuZbus {
|
||||||
|
/// Set profile details
|
||||||
|
fn set_profile(&self, profile: String) {
|
||||||
|
if let Ok(event) = serde_json::from_str(&profile) {
|
||||||
|
if let Ok(mut ctrl) = self.inner.try_lock() {
|
||||||
|
if let Ok(mut cfg) = ctrl.config.clone().try_lock() {
|
||||||
|
cfg.read();
|
||||||
|
ctrl.handle_profile_event(&event, &mut cfg)
|
||||||
|
.unwrap_or_else(|err| warn!("{}", err));
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Modify the active profile
|
||||||
|
fn set_turbo(&self, enable: bool) -> zbus::fdo::Result<()> {
|
||||||
|
if let Ok(mut ctrl) = self.inner.try_lock() {
|
||||||
|
if let Ok(mut cfg) = ctrl.config.clone().try_lock() {
|
||||||
|
// Update the profile then set it
|
||||||
|
cfg.read();
|
||||||
|
let profile = cfg.active_profile.clone();
|
||||||
|
if let Some(profile) = cfg.power_profiles.get_mut(&profile) {
|
||||||
|
profile.turbo = enable;
|
||||||
|
}
|
||||||
|
ctrl.set(&profile, &mut cfg)?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Modify the active profile
|
||||||
|
fn set_min_frequency(&self, percentage: u8) -> zbus::fdo::Result<()> {
|
||||||
|
if let Ok(mut ctrl) = self.inner.try_lock() {
|
||||||
|
if let Ok(mut cfg) = ctrl.config.clone().try_lock() {
|
||||||
|
// Update the profile then set it
|
||||||
|
cfg.read();
|
||||||
|
let profile = cfg.active_profile.clone();
|
||||||
|
if let Some(profile) = cfg.power_profiles.get_mut(&profile) {
|
||||||
|
profile.min_percentage = percentage;
|
||||||
|
}
|
||||||
|
ctrl.set(&profile, &mut cfg)?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Modify the active profile
|
||||||
|
fn set_max_frequency(&self, percentage: u8) -> zbus::fdo::Result<()> {
|
||||||
|
if let Ok(mut ctrl) = self.inner.try_lock() {
|
||||||
|
if let Ok(mut cfg) = ctrl.config.clone().try_lock() {
|
||||||
|
// Update the profile then set it
|
||||||
|
cfg.read();
|
||||||
|
let profile = cfg.active_profile.clone();
|
||||||
|
if let Some(profile) = cfg.power_profiles.get_mut(&profile) {
|
||||||
|
profile.max_percentage = percentage;
|
||||||
|
}
|
||||||
|
ctrl.set(&profile, &mut cfg)?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Modify the active profile
|
||||||
|
fn set_fan_preset(&self, preset: u8) -> zbus::fdo::Result<()> {
|
||||||
|
if preset > 2 {
|
||||||
|
return Err(zbus::fdo::Error::InvalidArgs(
|
||||||
|
"Fan preset must be 0, 1, or 2".to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if let Ok(mut ctrl) = self.inner.try_lock() {
|
||||||
|
if let Ok(mut cfg) = ctrl.config.clone().try_lock() {
|
||||||
|
// Update the profile then set it
|
||||||
|
cfg.read();
|
||||||
|
let profile = cfg.active_profile.clone();
|
||||||
|
if let Some(profile) = cfg.power_profiles.get_mut(&profile) {
|
||||||
|
profile.fan_preset = preset;
|
||||||
|
}
|
||||||
|
ctrl.set(&profile, &mut cfg)?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Modify the active profile
|
||||||
|
fn set_fan_curve(&self, curve: String) -> zbus::fdo::Result<()> {
|
||||||
|
let curve = Curve::from_config_str(&curve)
|
||||||
|
.map_err(|err| zbus::fdo::Error::InvalidArgs(format!("Fan curve error: {}", err)))?;
|
||||||
|
if let Ok(mut ctrl) = self.inner.try_lock() {
|
||||||
|
if let Ok(mut cfg) = ctrl.config.clone().try_lock() {
|
||||||
|
// Update the profile then set it
|
||||||
|
cfg.read();
|
||||||
|
let profile = cfg.active_profile.clone();
|
||||||
|
if let Some(profile) = cfg.power_profiles.get_mut(&profile) {
|
||||||
|
profile.fan_curve = Some(curve);
|
||||||
|
}
|
||||||
|
ctrl.set(&profile, &mut cfg)?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetch the active profile name
|
||||||
|
fn next_profile(&mut self) {
|
||||||
|
if let Ok(mut ctrl) = self.inner.try_lock() {
|
||||||
|
if let Ok(mut cfg) = ctrl.config.clone().try_lock() {
|
||||||
|
cfg.read();
|
||||||
|
ctrl.do_next_profile(&mut cfg)
|
||||||
|
.unwrap_or_else(|err| warn!("{}", err));
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetch the active profile name
|
||||||
|
fn active_profile_name(&mut self) -> zbus::fdo::Result<String> {
|
||||||
|
if let Ok(ctrl) = self.inner.try_lock() {
|
||||||
|
if let Ok(mut cfg) = ctrl.config.try_lock() {
|
||||||
|
cfg.read();
|
||||||
|
return Ok(cfg.active_profile.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(Error::Failed(
|
||||||
|
"Failed to get active profile name".to_string(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Profile can't implement Type because of Curve
|
||||||
|
/// Fetch the active profile details
|
||||||
|
fn profile(&mut self) -> zbus::fdo::Result<String> {
|
||||||
|
if let Ok(ctrl) = self.inner.try_lock() {
|
||||||
|
if let Ok(mut cfg) = ctrl.config.try_lock() {
|
||||||
|
cfg.read();
|
||||||
|
if let Some(profile) = cfg.power_profiles.get(&cfg.active_profile) {
|
||||||
|
if let Ok(json) = serde_json::to_string_pretty(profile) {
|
||||||
|
return Ok(json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(Error::Failed(
|
||||||
|
"Failed to get active profile details".to_string(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetch all profile data
|
||||||
|
fn profiles(&mut self) -> zbus::fdo::Result<String> {
|
||||||
|
if let Ok(ctrl) = self.inner.try_lock() {
|
||||||
|
if let Ok(mut cfg) = ctrl.config.try_lock() {
|
||||||
|
cfg.read();
|
||||||
|
if let Ok(json) = serde_json::to_string_pretty(&cfg.power_profiles) {
|
||||||
|
return Ok(json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(Error::Failed(
|
||||||
|
"Failed to get all profile details".to_string(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn profile_names(&self) -> zbus::fdo::Result<Vec<String>> {
|
||||||
|
if let Ok(ctrl) = self.inner.try_lock() {
|
||||||
|
if let Ok(mut cfg) = ctrl.config.try_lock() {
|
||||||
|
cfg.read();
|
||||||
|
let profile_names = cfg.power_profiles.keys().cloned().collect::<Vec<String>>();
|
||||||
|
return Ok(profile_names);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(Error::Failed("Failed to get all profile names".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(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(Error::Failed("Failed to lock configuration".to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[dbus_interface(signal)]
|
||||||
|
fn notify_profile(&self, profile: &str) -> zbus::Result<()> {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl crate::ZbusAdd for FanAndCpuZbus {
|
||||||
|
fn add_to_server(self, server: &mut zbus::ObjectServer) {
|
||||||
|
server
|
||||||
|
.at(
|
||||||
|
&ObjectPath::from_str_unchecked("/org/asuslinux/Profile"),
|
||||||
|
self,
|
||||||
|
)
|
||||||
|
.map_err(|err| {
|
||||||
|
warn!("DbusFanAndCpu: add_to_server {}", err);
|
||||||
|
err
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::{config::Config, error::RogError, GetSupported};
|
use crate::{config::Config, error::RogError, GetSupported};
|
||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use rog_types::supported::RogBiosSupportedFunctions;
|
||||||
use std::fs::OpenOptions;
|
use std::fs::OpenOptions;
|
||||||
use std::io::BufRead;
|
use std::io::BufRead;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
@@ -9,6 +9,7 @@ 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;
|
||||||
|
use zvariant::ObjectPath;
|
||||||
|
|
||||||
const INITRAMFS_PATH: &str = "/usr/sbin/update-initramfs";
|
const INITRAMFS_PATH: &str = "/usr/sbin/update-initramfs";
|
||||||
const DRACUT_PATH: &str = "/usr/bin/dracut";
|
const DRACUT_PATH: &str = "/usr/bin/dracut";
|
||||||
@@ -22,12 +23,6 @@ pub struct CtrlRogBios {
|
|||||||
_config: Arc<Mutex<Config>>,
|
_config: Arc<Mutex<Config>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub struct RogBiosSupportedFunctions {
|
|
||||||
pub post_sound_toggle: bool,
|
|
||||||
pub dedicated_gfx_toggle: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GetSupported for CtrlRogBios {
|
impl GetSupported for CtrlRogBios {
|
||||||
type A = RogBiosSupportedFunctions;
|
type A = RogBiosSupportedFunctions;
|
||||||
|
|
||||||
@@ -101,7 +96,10 @@ 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", self)
|
.at(
|
||||||
|
&ObjectPath::from_str_unchecked("/org/asuslinux/RogBios"),
|
||||||
|
self,
|
||||||
|
)
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
warn!("CtrlRogBios: add_to_server {}", err);
|
warn!("CtrlRogBios: add_to_server {}", err);
|
||||||
err
|
err
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
use log::warn;
|
use log::warn;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use zbus::dbus_interface;
|
use zbus::dbus_interface;
|
||||||
|
use zvariant::ObjectPath;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ctrl_anime::{AnimeSupportedFunctions, CtrlAnimeDisplay},
|
ctrl_anime::CtrlAnime, ctrl_charge::CtrlCharge, ctrl_leds::CtrlKbdLed,
|
||||||
ctrl_charge::{ChargeSupportedFunctions, CtrlCharge},
|
ctrl_profiles::CtrlFanAndCpu, ctrl_rog_bios::CtrlRogBios, GetSupported,
|
||||||
ctrl_fan_cpu::{CtrlFanAndCPU, FanCpuSupportedFunctions},
|
};
|
||||||
ctrl_leds::{CtrlKbdBacklight, LedSupportedFunctions},
|
|
||||||
ctrl_rog_bios::{CtrlRogBios, RogBiosSupportedFunctions},
|
use rog_types::supported::{
|
||||||
GetSupported,
|
AnimeSupportedFunctions, ChargeSupportedFunctions, FanCpuSupportedFunctions,
|
||||||
|
LedSupportedFunctions, RogBiosSupportedFunctions,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
@@ -30,7 +32,10 @@ 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", self)
|
.at(
|
||||||
|
&ObjectPath::from_str_unchecked("/org/asuslinux/Supported"),
|
||||||
|
self,
|
||||||
|
)
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
warn!("SupportedFunctions: add_to_server {}", err);
|
warn!("SupportedFunctions: add_to_server {}", err);
|
||||||
err
|
err
|
||||||
@@ -44,10 +49,10 @@ impl GetSupported for SupportedFunctions {
|
|||||||
|
|
||||||
fn get_supported() -> Self::A {
|
fn get_supported() -> Self::A {
|
||||||
SupportedFunctions {
|
SupportedFunctions {
|
||||||
keyboard_led: CtrlKbdBacklight::get_supported(),
|
keyboard_led: CtrlKbdLed::get_supported(),
|
||||||
anime_ctrl: CtrlAnimeDisplay::get_supported(),
|
anime_ctrl: CtrlAnime::get_supported(),
|
||||||
charge_ctrl: CtrlCharge::get_supported(),
|
charge_ctrl: CtrlCharge::get_supported(),
|
||||||
fan_cpu_ctrl: CtrlFanAndCPU::get_supported(),
|
fan_cpu_ctrl: CtrlFanAndCpu::get_supported(),
|
||||||
rog_bios_ctrl: CtrlRogBios::get_supported(),
|
rog_bios_ctrl: CtrlRogBios::get_supported(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
use daemon::ctrl_leds::{CtrlKbdBacklight, DbusKbdBacklight};
|
use daemon::ctrl_leds::{CtrlKbdLed, CtrlKbdLedReloader, CtrlKbdLedTask, CtrlKbdLedZbus};
|
||||||
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::{config_anime::AnimeConfig, config_aura::AuraConfig, ctrl_charge::CtrlCharge};
|
||||||
use daemon::{ctrl_anime::CtrlAnimeDisplay, ctrl_gfx::gfx::CtrlGraphics};
|
use daemon::{ctrl_anime::*, ctrl_gfx::gfx::CtrlGraphics};
|
||||||
use daemon::{
|
use daemon::{
|
||||||
ctrl_fan_cpu::{CtrlFanAndCPU, DbusFanAndCpu},
|
ctrl_profiles::{zbus::FanAndCpuZbus, CtrlFanAndCpu},
|
||||||
laptops::LaptopLedData,
|
laptops::LaptopLedData,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -23,6 +23,7 @@ use daemon::ctrl_rog_bios::CtrlRogBios;
|
|||||||
use std::convert::Into;
|
use std::convert::Into;
|
||||||
use zbus::fdo;
|
use zbus::fdo;
|
||||||
use zbus::Connection;
|
use zbus::Connection;
|
||||||
|
use zvariant::ObjectPath;
|
||||||
|
|
||||||
pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut logger = env_logger::Builder::new();
|
let mut logger = env_logger::Builder::new();
|
||||||
@@ -40,27 +41,24 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Timing is such that:
|
/// The actual main loop for the daemon
|
||||||
// - interrupt write is minimum 1ms (sometimes lower)
|
|
||||||
// - read interrupt must timeout, minimum of 1ms
|
|
||||||
// - for a single usb packet, 2ms total.
|
|
||||||
// - to maintain constant times of 1ms, per-key colours should use
|
|
||||||
// the effect endpoint so that the complete colour block is written
|
|
||||||
// as fast as 1ms per row of the matrix inside it. (10ms total time)
|
|
||||||
fn start_daemon() -> Result<(), Box<dyn Error>> {
|
fn start_daemon() -> Result<(), Box<dyn Error>> {
|
||||||
let supported = SupportedFunctions::get_supported();
|
let supported = SupportedFunctions::get_supported();
|
||||||
print_board_info();
|
print_board_info();
|
||||||
println!("{}", serde_json::to_string_pretty(&supported).unwrap());
|
println!("{}", serde_json::to_string_pretty(&supported).unwrap());
|
||||||
|
|
||||||
let config = Config::load();
|
// Collect tasks for task thread
|
||||||
let enable_gfx_switching = config.gfx_managed;
|
let mut tasks: Vec<Box<dyn CtrlTask + Send>> = Vec::new();
|
||||||
let config = Arc::new(Mutex::new(config));
|
// Start zbus server
|
||||||
|
|
||||||
let connection = Connection::new_system()?;
|
let connection = Connection::new_system()?;
|
||||||
fdo::DBusProxy::new(&connection)?
|
fdo::DBusProxy::new(&connection)?
|
||||||
.request_name(DBUS_NAME, fdo::RequestNameFlags::ReplaceExisting.into())?;
|
.request_name(DBUS_NAME, fdo::RequestNameFlags::ReplaceExisting.into())?;
|
||||||
let mut object_server = zbus::ObjectServer::new(&connection);
|
let mut object_server = zbus::ObjectServer::new(&connection);
|
||||||
|
|
||||||
|
let config = Config::load();
|
||||||
|
let enable_gfx_switching = config.gfx_managed;
|
||||||
|
let config = Arc::new(Mutex::new(config));
|
||||||
|
|
||||||
supported.add_to_server(&mut object_server);
|
supported.add_to_server(&mut object_server);
|
||||||
|
|
||||||
match CtrlRogBios::new(config.clone()) {
|
match CtrlRogBios::new(config.clone()) {
|
||||||
@@ -89,29 +87,86 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match CtrlAnimeDisplay::new() {
|
match CtrlFanAndCpu::new(config.clone()) {
|
||||||
|
Ok(mut ctrl) => {
|
||||||
|
ctrl.reload()
|
||||||
|
.unwrap_or_else(|err| warn!("Profile control: {}", err));
|
||||||
|
let tmp = Arc::new(Mutex::new(ctrl));
|
||||||
|
FanAndCpuZbus::new(tmp).add_to_server(&mut object_server);
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
error!("Profile control: {}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match CtrlAnime::new(AnimeConfig::load()) {
|
||||||
Ok(ctrl) => {
|
Ok(ctrl) => {
|
||||||
ctrl.add_to_server(&mut object_server);
|
let inner = Arc::new(Mutex::new(ctrl));
|
||||||
|
|
||||||
|
let mut reload = CtrlAnimeReloader(inner.clone());
|
||||||
|
reload
|
||||||
|
.reload()
|
||||||
|
.unwrap_or_else(|err| warn!("AniMe: {}", err));
|
||||||
|
|
||||||
|
let zbus = CtrlAnimeZbus(inner.clone());
|
||||||
|
zbus.add_to_server(&mut object_server);
|
||||||
|
|
||||||
|
tasks.push(Box::new(CtrlAnimeTask::new(inner)));
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("AniMe control: {}", err);
|
error!("AniMe control: {}", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let laptop = LaptopLedData::get_data();
|
||||||
|
let aura_config = AuraConfig::load(&laptop);
|
||||||
|
match CtrlKbdLed::new(laptop, aura_config) {
|
||||||
|
Ok(ctrl) => {
|
||||||
|
let inner = Arc::new(Mutex::new(ctrl));
|
||||||
|
|
||||||
|
let mut reload = CtrlKbdLedReloader(inner.clone());
|
||||||
|
reload
|
||||||
|
.reload()
|
||||||
|
.unwrap_or_else(|err| warn!("Keyboard LED control: {}", err));
|
||||||
|
|
||||||
|
CtrlKbdLedZbus::new(inner.clone()).add_to_server(&mut object_server);
|
||||||
|
let task = CtrlKbdLedTask(inner);
|
||||||
|
tasks.push(Box::new(task));
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
error!("Keyboard control: {}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Graphics switching requires some checks on boot specifically for g-sync capable laptops
|
||||||
if enable_gfx_switching {
|
if enable_gfx_switching {
|
||||||
match CtrlGraphics::new(config.clone()) {
|
match CtrlGraphics::new(config.clone()) {
|
||||||
Ok(mut ctrl) => {
|
Ok(mut ctrl) => {
|
||||||
// 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) = ctrl.get_gfx_mode() {
|
if let Ok(mut config) = config.lock() {
|
||||||
if ded == 1 && vendor != GfxVendors::Nvidia {
|
if ded == 1 {
|
||||||
warn!("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");
|
||||||
|
config.gfx_last_mode = config.gfx_mode;
|
||||||
let devices = ctrl.devices();
|
let devices = ctrl.devices();
|
||||||
let bus = ctrl.bus();
|
let bus = ctrl.bus();
|
||||||
CtrlGraphics::do_vendor_tasks(GfxVendors::Nvidia, &devices, &bus)?;
|
CtrlGraphics::do_vendor_tasks(
|
||||||
|
GfxVendors::Nvidia,
|
||||||
|
false,
|
||||||
|
&devices,
|
||||||
|
&bus,
|
||||||
|
)?;
|
||||||
} else if ded == 0 {
|
} else if ded == 0 {
|
||||||
info!("Dedicated GFX toggle is off");
|
info!("Dedicated GFX toggle is off");
|
||||||
|
let devices = ctrl.devices();
|
||||||
|
let bus = ctrl.bus();
|
||||||
|
CtrlGraphics::do_vendor_tasks(
|
||||||
|
config.gfx_last_mode,
|
||||||
|
false,
|
||||||
|
&devices,
|
||||||
|
&bus,
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -126,61 +181,44 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect tasks for task thread
|
|
||||||
let mut tasks: Vec<Arc<Mutex<dyn CtrlTask + Send>>> = Vec::new();
|
|
||||||
|
|
||||||
if let Ok(mut ctrl) = CtrlFanAndCPU::new(config).map_err(|err| {
|
|
||||||
error!("Profile control: {}", err);
|
|
||||||
}) {
|
|
||||||
ctrl.reload()
|
|
||||||
.unwrap_or_else(|err| warn!("Profile control: {}", err));
|
|
||||||
let tmp = Arc::new(Mutex::new(ctrl));
|
|
||||||
DbusFanAndCpu::new(tmp).add_to_server(&mut object_server);
|
|
||||||
};
|
|
||||||
|
|
||||||
let laptop = LaptopLedData::get_data();
|
|
||||||
let aura_config = AuraConfig::load(&laptop);
|
|
||||||
if let Ok(ctrl) = CtrlKbdBacklight::new(laptop, aura_config).map_err(|err| {
|
|
||||||
error!("Keyboard control: {}", err);
|
|
||||||
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
|
||||||
// These tasks generally read a sys path or file to check for a
|
|
||||||
// change
|
// Run tasks
|
||||||
let _handle = std::thread::Builder::new()
|
let handle = std::thread::Builder::new()
|
||||||
.name("asusd watch".to_string())
|
.name("asusd watch".to_string())
|
||||||
.spawn(move || loop {
|
.spawn(move || loop {
|
||||||
std::thread::sleep(std::time::Duration::from_millis(100));
|
std::thread::sleep(std::time::Duration::from_millis(100));
|
||||||
|
|
||||||
for ctrl in tasks.iter() {
|
for ctrl in tasks.iter() {
|
||||||
if let Ok(mut lock) = ctrl.try_lock() {
|
ctrl.do_task()
|
||||||
lock.do_task()
|
.map_err(|err| {
|
||||||
.map_err(|err| {
|
warn!("do_task error: {}", err);
|
||||||
warn!("do_task error: {}", err);
|
})
|
||||||
})
|
.ok();
|
||||||
.ok();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Run zbus server
|
||||||
object_server
|
object_server
|
||||||
.with("/org/asuslinux/Charge", |obj: &CtrlCharge| {
|
.with(
|
||||||
let x = obj.limit();
|
&ObjectPath::from_str_unchecked("/org/asuslinux/Charge"),
|
||||||
obj.notify_charge(x as u8)
|
|obj: &CtrlCharge| {
|
||||||
})
|
let x = obj.limit();
|
||||||
|
obj.notify_charge(x as u8)
|
||||||
|
},
|
||||||
|
)
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
warn!("object_server notify_charge error: {}", err);
|
warn!("object_server notify_charge error: {}", err);
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
|
// Loop to check errors and iterate zbus server
|
||||||
loop {
|
loop {
|
||||||
|
if let Err(err) = &handle {
|
||||||
|
error!("{}", err);
|
||||||
|
}
|
||||||
if let Err(err) = object_server.try_handle_next() {
|
if let Err(err) = object_server.try_handle_next() {
|
||||||
eprintln!("{}", err);
|
error!("{}", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use crate::ctrl_gfx::error::GfxError;
|
|||||||
pub enum RogError {
|
pub enum RogError {
|
||||||
ParseFanLevel,
|
ParseFanLevel,
|
||||||
ParseVendor,
|
ParseVendor,
|
||||||
ParseLED,
|
ParseLed,
|
||||||
MissingProfile(String),
|
MissingProfile(String),
|
||||||
Udev(String, std::io::Error),
|
Udev(String, std::io::Error),
|
||||||
Path(String, std::io::Error),
|
Path(String, std::io::Error),
|
||||||
@@ -38,7 +38,7 @@ impl fmt::Display for RogError {
|
|||||||
match self {
|
match self {
|
||||||
RogError::ParseFanLevel => write!(f, "Parse profile error"),
|
RogError::ParseFanLevel => write!(f, "Parse profile error"),
|
||||||
RogError::ParseVendor => write!(f, "Parse gfx vendor error"),
|
RogError::ParseVendor => write!(f, "Parse gfx vendor error"),
|
||||||
RogError::ParseLED => write!(f, "Parse LED error"),
|
RogError::ParseLed => write!(f, "Parse LED error"),
|
||||||
RogError::MissingProfile(profile) => write!(f, "Profile does not exist {}", profile),
|
RogError::MissingProfile(profile) => write!(f, "Profile does not exist {}", profile),
|
||||||
RogError::Udev(deets, error) => write!(f, "udev {}: {}", deets, error),
|
RogError::Udev(deets, error) => write!(f, "udev {}: {}", deets, error),
|
||||||
RogError::Path(path, error) => write!(f, "Path {}: {}", path, error),
|
RogError::Path(path, error) => write!(f, "Path {}: {}", path, error),
|
||||||
@@ -80,6 +80,7 @@ impl From<GraphicsError> for RogError {
|
|||||||
fn from(err: GraphicsError) -> Self {
|
fn from(err: GraphicsError) -> Self {
|
||||||
match err {
|
match err {
|
||||||
GraphicsError::ParseVendor => RogError::GfxSwitching(GfxError::ParseVendor),
|
GraphicsError::ParseVendor => RogError::GfxSwitching(GfxError::ParseVendor),
|
||||||
|
GraphicsError::ParsePower => RogError::GfxSwitching(GfxError::ParsePower),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,3 +96,10 @@ impl From<std::io::Error> for RogError {
|
|||||||
RogError::Io(err)
|
RogError::Io(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<RogError> for zbus::fdo::Error {
|
||||||
|
#[inline]
|
||||||
|
fn from(err: RogError) -> Self {
|
||||||
|
zbus::fdo::Error::Failed(format!("{}", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
use rog_types::aura_modes::AuraModeNum;
|
use rog_aura::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;
|
||||||
|
|||||||
@@ -1,12 +1,17 @@
|
|||||||
#![deny(unused_must_use)]
|
#![deny(unused_must_use)]
|
||||||
/// Configuration loading, saving
|
/// Configuration loading, saving
|
||||||
pub mod config;
|
pub mod config;
|
||||||
|
pub mod config_anime;
|
||||||
pub mod config_aura;
|
pub mod config_aura;
|
||||||
pub(crate) mod config_old;
|
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
|
||||||
pub mod ctrl_charge;
|
pub mod ctrl_charge;
|
||||||
|
/// GPU switching and power
|
||||||
|
pub mod ctrl_gfx;
|
||||||
|
/// Keyboard LED brightness control, RGB, and LED display modes
|
||||||
|
pub mod ctrl_leds;
|
||||||
/// Control CPU min/max freq and turbo, fan mode, fan curves
|
/// Control CPU min/max freq and turbo, fan mode, fan curves
|
||||||
///
|
///
|
||||||
/// Intel machines can control:
|
/// Intel machines can control:
|
||||||
@@ -18,11 +23,7 @@ pub mod ctrl_charge;
|
|||||||
/// - CPU turbo enable/disable
|
/// - CPU turbo enable/disable
|
||||||
/// - Fan mode (normal, boost, silent)
|
/// - Fan mode (normal, boost, silent)
|
||||||
/// - Fan min/max RPM curve
|
/// - Fan min/max RPM curve
|
||||||
pub mod ctrl_fan_cpu;
|
pub mod ctrl_profiles;
|
||||||
/// GPU switching and power
|
|
||||||
pub mod ctrl_gfx;
|
|
||||||
/// Keyboard LED brightness control, RGB, and LED display modes
|
|
||||||
pub mod ctrl_leds;
|
|
||||||
/// Control ASUS bios function such as boot sound, Optimus/Dedicated gfx mode
|
/// Control ASUS bios function such as boot sound, Optimus/Dedicated gfx mode
|
||||||
pub mod ctrl_rog_bios;
|
pub mod ctrl_rog_bios;
|
||||||
/// Laptop matching to determine capabilities
|
/// Laptop matching to determine capabilities
|
||||||
@@ -48,7 +49,7 @@ pub trait ZbusAdd {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait CtrlTask {
|
pub trait CtrlTask {
|
||||||
fn do_task(&mut self) -> Result<(), RogError>;
|
fn do_task(&self) -> Result<(), RogError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait CtrlTaskComplex {
|
pub trait CtrlTaskComplex {
|
||||||
|
|||||||
|
After Width: | Height: | Size: 72 KiB |
|
After Width: | Height: | Size: 61 KiB |
|
After Width: | Height: | Size: 137 KiB |
|
After Width: | Height: | Size: 109 KiB |
|
After Width: | Height: | Size: 99 KiB |
|
After Width: | Height: | Size: 85 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 96 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 234 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 49 KiB |
|
After Width: | Height: | Size: 63 KiB |
|
After Width: | Height: | Size: 119 KiB |
|
After Width: | Height: | Size: 132 KiB |
|
After Width: | Height: | Size: 90 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 7.7 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 120 KiB |
|
After Width: | Height: | Size: 112 KiB |
|
After Width: | Height: | Size: 73 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 152 KiB |
|
After Width: | Height: | Size: 28 KiB |
@@ -35,14 +35,14 @@ per_key = false
|
|||||||
|
|
||||||
[[led_data]]
|
[[led_data]]
|
||||||
prod_family = "ROG Strix"
|
prod_family = "ROG Strix"
|
||||||
board_names = ["G531GW"]
|
board_names = ["G531GW", "G733QS", "G733QR"]
|
||||||
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Star", "Rain", "Highlight", "Laser", "Ripple", "Pulse", "Comet", "Flash"]
|
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Star", "Rain", "Highlight", "Laser", "Ripple", "Pulse", "Comet", "Flash"]
|
||||||
multizone = false
|
multizone = false
|
||||||
per_key = true
|
per_key = true
|
||||||
|
|
||||||
[[led_data]]
|
[[led_data]]
|
||||||
prod_family = "ROG Strix"
|
prod_family = "ROG Strix"
|
||||||
board_names = ["GX531", "G512LV", "G712LV"]
|
board_names = ["GX531", "G512LV", "G712LV", "G712LW"]
|
||||||
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Pulse"]
|
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Pulse"]
|
||||||
multizone = true
|
multizone = true
|
||||||
per_key = false
|
per_key = false
|
||||||
@@ -80,4 +80,11 @@ prod_family = "ROG"
|
|||||||
board_names = ["GL553VE"]
|
board_names = ["GL553VE"]
|
||||||
standard = ["Static", "Breathe", "Strobe"]
|
standard = ["Static", "Breathe", "Strobe"]
|
||||||
multizone = true
|
multizone = true
|
||||||
|
per_key = false
|
||||||
|
|
||||||
|
[[led_data]]
|
||||||
|
prod_family = "ROG Zephyrus G14"
|
||||||
|
board_names = ["GA401Q"]
|
||||||
|
standard = ["Static", "Breathe", "Pulse"]
|
||||||
|
multizone = false
|
||||||
per_key = false
|
per_key = false
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=ASUS User Daemon
|
||||||
|
StartLimitInterval=200
|
||||||
|
StartLimitBurst=2
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStartPre=/usr/bin/sleep 2
|
||||||
|
ExecStart=/usr/bin/asusd-user
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=1
|
||||||
|
Type=simple
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=default.target
|
||||||
@@ -10,4 +10,6 @@ Restart=on-failure
|
|||||||
Restart=always
|
Restart=always
|
||||||
RestartSec=1
|
RestartSec=1
|
||||||
Type=dbus
|
Type=dbus
|
||||||
BusName=org.asuslinux.Daemon
|
BusName=org.asuslinux.Daemon
|
||||||
|
SELinuxContext=system_u:system_r:unconfined_t:s0
|
||||||
|
#SELinuxContext=system_u:object_r:modules_object_t:s0
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
{
|
||||||
|
"anime": [
|
||||||
|
{
|
||||||
|
"AsusAnimation": {
|
||||||
|
"file": "/usr/share/asusd/anime/asus/rog/Sunset.gif",
|
||||||
|
"time": {
|
||||||
|
"Cycles": 1
|
||||||
|
},
|
||||||
|
"brightness": 0.5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImageAnimation": {
|
||||||
|
"file": "/usr/share/asusd/anime/custom/sonic-run.gif",
|
||||||
|
"scale": 0.9,
|
||||||
|
"angle": 0.65,
|
||||||
|
"translation": [
|
||||||
|
0.0,
|
||||||
|
0.0
|
||||||
|
],
|
||||||
|
"time": {
|
||||||
|
"Time": {
|
||||||
|
"secs": 5,
|
||||||
|
"nanos": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"brightness": 0.5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Image": {
|
||||||
|
"file": "/usr/share/asusd/anime/custom/rust.png",
|
||||||
|
"scale": 1.0,
|
||||||
|
"angle": 0.0,
|
||||||
|
"translation": [
|
||||||
|
0.0,
|
||||||
|
0.0
|
||||||
|
],
|
||||||
|
"brightness": 0.6
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Pause": {
|
||||||
|
"secs": 6,
|
||||||
|
"nanos": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImageAnimation": {
|
||||||
|
"file": "/usr/share/asusd/anime/custom/sonic-wait.gif",
|
||||||
|
"scale": 0.9,
|
||||||
|
"angle": 0.0,
|
||||||
|
"translation": [
|
||||||
|
3.0,
|
||||||
|
2.0
|
||||||
|
],
|
||||||
|
"time": {
|
||||||
|
"Cycles": 2
|
||||||
|
},
|
||||||
|
"brightness": 0.5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||