Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2e4ce27f6b | ||
|
|
b8384c55c3 | ||
|
|
dfe1f02101 | ||
|
|
7c2fb0be81 | ||
|
|
b05f680650 | ||
|
|
2a9a436f9c | ||
|
|
0d6faf3fda | ||
|
|
aede000218 | ||
|
|
176ab0a639 | ||
|
|
4efb2caa56 | ||
|
|
6f81f86483 | ||
|
|
b64b8a38e4 | ||
|
|
ff56170ac5 | ||
|
|
733f1f827e | ||
|
|
ac903a05da | ||
|
|
838e6f789b | ||
|
|
d462393e8b | ||
|
|
e98cf8d50b | ||
|
|
eb173fc9dc | ||
|
|
50756046cf | ||
|
|
629bdc2213 | ||
|
|
39bbe33831 | ||
|
|
00bd556d7a | ||
|
|
12061ea9df | ||
|
|
580ed72e73 | ||
|
|
c01f0892a5 | ||
|
|
0fed34b12e | ||
|
|
0af68baf7b | ||
|
|
161e3c4d3b | ||
|
|
4720af2cb8 | ||
|
|
06d37aa009 | ||
|
|
c6fa860b2e | ||
|
|
4fe9ab70e5 | ||
|
|
920e4e86f5 | ||
|
|
720dc0c177 | ||
|
|
b3a555cab9 | ||
|
|
cf13b4f71b |
@@ -13,7 +13,7 @@ test:
|
||||
|
||||
build:
|
||||
only:
|
||||
- next
|
||||
- main
|
||||
script:
|
||||
- make && make vendor
|
||||
artifacts:
|
||||
|
||||
61
CHANGELOG.md
@@ -6,6 +6,66 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
# [3.1.3] - 2021-03-10
|
||||
### Changed
|
||||
- Hotfix: gracefully handle removing modules in use caused by display-manager not
|
||||
fully shutdown at the time of trying to remove modules. It will now retry every
|
||||
250ms per module
|
||||
|
||||
# [3.1.2] - 2021-03-10
|
||||
### Changed
|
||||
- Test and create /etc/X11/xorg.conf.d/ if it doesn't exist
|
||||
- Hotfix to better report module issues
|
||||
|
||||
# [3.1.1] - 2021-03-10
|
||||
### Changed
|
||||
- Add missing nvidia module nvidia_uvm to gfx ctrl list
|
||||
|
||||
# [3.1.0] - 2021-03-09
|
||||
### Added
|
||||
- GU502LU led-modes
|
||||
### Changed
|
||||
- Graphics switching is now rebootless, the daemon will now restart the
|
||||
display-manager to switch modes instead. Caveats are:
|
||||
+ There is no confirmation from the daemon, the program issuing the command
|
||||
must confirm the request.
|
||||
+ systemd only
|
||||
- Laptops with dedicated Nvidia mode:
|
||||
+ You still must reboot for the bios to switch modes
|
||||
+ On boot if dedicated mode is active then asusd will update the required configs
|
||||
to put display-manager in nvidia mode
|
||||
|
||||
# [3.0.0] - 2021-02-22
|
||||
### Added
|
||||
- G531GD led modes
|
||||
|
||||
# [3.0.0] - 2021-02-14
|
||||
### Changed
|
||||
- Write set+apply after each array in multizone
|
||||
- Remove misc bad logic
|
||||
- Use same code path as 0x1866 device to configure led support for 0x1854 device
|
||||
- Remove duplicate code
|
||||
- Set correct speeds for multizone
|
||||
- Remove dbus crate in favour of zbus. This removes the external dbus lib requirement.
|
||||
- Huge internal refactor
|
||||
- BREAKING CHANGE: Anime code refactor. DBUS method names have changed
|
||||
- Cleanup fan and cpu control + configs
|
||||
|
||||
# [2.2.2] - 2021-01-31
|
||||
### Changed
|
||||
- Fix for dedicated gfx capable laptops in integrated mode
|
||||
- Fix for 0x1854 device
|
||||
|
||||
# [2.2.1] - 2021-01-27
|
||||
### Added
|
||||
- Add ROG Zephyrus M15 LED config
|
||||
### Changed
|
||||
- Bugfixes
|
||||
- Fix reboot/restartx status for GFX switching
|
||||
- Update readme
|
||||
- Change CLI arg tag for fan modes
|
||||
- Make dracut include the nvidia modules in initramfs
|
||||
|
||||
# [2.2.0] - 2021-01-26
|
||||
### Added
|
||||
- Dbus command to fetch all supported functions of the laptop. That is, all the
|
||||
@@ -13,7 +73,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Bios setting toggles for:
|
||||
+ Dedicated gfx toggle (support depends on the laptop)
|
||||
+ Bios boot POST sound toggle
|
||||
|
||||
### Changed
|
||||
- added config option for dedicated gfx mode on laptops with it to enable
|
||||
switching directly to dedicated using `asusctl graphics -m nvidia`
|
||||
|
||||
338
Cargo.lock
generated
@@ -1,11 +1,5 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "adler32"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.15"
|
||||
@@ -28,54 +22,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
|
||||
|
||||
[[package]]
|
||||
name = "asus-nb"
|
||||
version = "2.2.0"
|
||||
name = "asus-notify"
|
||||
version = "3.0.0"
|
||||
dependencies = [
|
||||
"daemon",
|
||||
"notify-rust",
|
||||
"rog_dbus",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "asusctl"
|
||||
version = "3.1.0"
|
||||
dependencies = [
|
||||
"dbus",
|
||||
"gumdrop",
|
||||
"rog_fan_curve",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"rog_dbus",
|
||||
"rog_types",
|
||||
"serde_json",
|
||||
"tinybmp",
|
||||
"yansi-term",
|
||||
"zbus",
|
||||
"zvariant",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "asus-nb-ctrl"
|
||||
version = "2.2.0"
|
||||
dependencies = [
|
||||
"asus-nb",
|
||||
"env_logger",
|
||||
"gumdrop",
|
||||
"intel-pstate",
|
||||
"log",
|
||||
"rog_fan_curve",
|
||||
"rusb",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"sysfs-class",
|
||||
"toml 0.4.10",
|
||||
"udev",
|
||||
"yansi-term",
|
||||
"zbus",
|
||||
"zvariant",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "asus-notify"
|
||||
version = "2.0.4"
|
||||
dependencies = [
|
||||
"asus-nb",
|
||||
"asus-nb-ctrl",
|
||||
"dbus",
|
||||
"notify-rust",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -164,9 +129,9 @@ checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.66"
|
||||
version = "1.0.67"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48"
|
||||
checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
@@ -208,34 +173,37 @@ version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.1"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d"
|
||||
checksum = "bae8f328835f8f5a6ceb6a7842a7f2d0c03692adb5c889347235d59194731fe3"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if 1.0.0",
|
||||
"lazy_static",
|
||||
"loom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dbus"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5cd9e78c210146a1860f897db03412fd5091fd73100778e43ee255cca252cf32"
|
||||
name = "daemon"
|
||||
version = "3.1.3"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"libdbus-sys",
|
||||
"env_logger",
|
||||
"intel-pstate",
|
||||
"log",
|
||||
"rog_dbus",
|
||||
"rog_fan_curve",
|
||||
"rog_types",
|
||||
"rusb",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"sysfs-class",
|
||||
"toml",
|
||||
"udev",
|
||||
"zbus",
|
||||
"zvariant",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -245,7 +213,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.8",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.60",
|
||||
]
|
||||
|
||||
@@ -277,15 +245,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "946ee94e3dbf58fdd324f9ce245c7b238d46a66f00e86a020b71996349e46cce"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.8",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.7.1"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
|
||||
checksum = "17392a012ea30ef05a610aa97dfb49496e71c9f676b27879922ea5bdf60d9d3f"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"humantime",
|
||||
@@ -302,7 +270,7 @@ checksum = "22deed3a8124cff5fa835713fa105621e43bbdc46690c3a6b68328a012d350d4"
|
||||
dependencies = [
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote 1.0.8",
|
||||
"quote 1.0.9",
|
||||
"rustversion",
|
||||
"syn 1.0.60",
|
||||
"synstructure",
|
||||
@@ -317,18 +285,6 @@ dependencies = [
|
||||
"instant",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "filetime"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d34cfa13a63ae058bfa601fe9e313bbdb3746427c1459185464ce0fcf62e1e8"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"redox_syscall 0.2.4",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.12"
|
||||
@@ -400,7 +356,7 @@ checksum = "c287d25add322d9f9abdcdc5927ca398917996600182178774032e9f8258fedd"
|
||||
dependencies = [
|
||||
"proc-macro-hack",
|
||||
"proc-macro2",
|
||||
"quote 1.0.8",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.60",
|
||||
]
|
||||
|
||||
@@ -439,6 +395,19 @@ dependencies = [
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generator"
|
||||
version = "0.6.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9fed24fd1e18827652b4d55652899a1e9da8e54d91624dc3437a5bc3a9f9a9c"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"log",
|
||||
"rustversion",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.1.16"
|
||||
@@ -466,7 +435,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "915ef07c710d84733522461de2a734d4d62a3fd39a4d4f404c2f385ef8618d05"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.8",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.60",
|
||||
]
|
||||
|
||||
@@ -481,12 +450,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "humantime"
|
||||
version = "1.3.0"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
|
||||
dependencies = [
|
||||
"quick-error",
|
||||
]
|
||||
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
@@ -521,36 +487,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.82"
|
||||
version = "0.2.86"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929"
|
||||
|
||||
[[package]]
|
||||
name = "libdbus-sys"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc12a3bc971424edbbf7edaf6e5740483444db63aa8e23d3751ff12a30f306f0"
|
||||
dependencies = [
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libflate"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "389de7875e06476365974da3e7ff85d55f1972188ccd9f6020dd7c8156e17914"
|
||||
dependencies = [
|
||||
"adler32",
|
||||
"crc32fast",
|
||||
"libflate_lz77",
|
||||
"rle-decode-fast",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libflate_lz77"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3286f09f7d4926fc486334f28d8d2e6ebe4f7f9994494b6dab27ddfad2c9b11b"
|
||||
checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c"
|
||||
|
||||
[[package]]
|
||||
name = "libudev-sys"
|
||||
@@ -564,25 +503,34 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libusb1-sys"
|
||||
version = "0.4.4"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be241693102a24766d0b8526c8988771edac2842630d7e730f8e9fbc014f3703"
|
||||
checksum = "e22e89d08bbe6816c6c5d446203b859eba35b8fa94bf1b7edb2f6d25d43f023f"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"libflate",
|
||||
"pkg-config",
|
||||
"tar",
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.13"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcf3805d4480bb5b86070dcfeb9e2cb2ebc148adb753c5cca5f884d1d65a42b2"
|
||||
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10",
|
||||
"cfg-if 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "loom"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d44c73b4636e497b4917eb21c33539efa3816741a2d3ff26c6316f1b529481a4"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"generator",
|
||||
"scoped-tls",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -614,12 +562,12 @@ checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
|
||||
|
||||
[[package]]
|
||||
name = "nb-connect"
|
||||
version = "1.0.2"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8123a81538e457d44b933a02faf885d3fe8408806b23fa700e8f01c6c3a98998"
|
||||
checksum = "670361df1bc2399ee1ff50406a0d422587dd3bb0da596e1978fe8e05dabddf4f"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
"socket2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -762,7 +710,7 @@ version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785"
|
||||
dependencies = [
|
||||
"toml 0.5.8",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -773,7 +721,7 @@ checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2",
|
||||
"quote 1.0.8",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.60",
|
||||
"version_check",
|
||||
]
|
||||
@@ -785,7 +733,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.8",
|
||||
"quote 1.0.9",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
@@ -810,12 +758,6 @@ dependencies = [
|
||||
"unicode-xid 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-error"
|
||||
version = "1.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.3.15"
|
||||
@@ -824,9 +766,9 @@ checksum = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.8"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df"
|
||||
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
@@ -837,15 +779,6 @@ version = "0.1.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05ec8ca9416c5ea37062b502703cd7fcb207736bc294f6e0cf367ac6fc234570"
|
||||
dependencies = [
|
||||
"bitflags 1.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.3.5"
|
||||
@@ -853,7 +786,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"redox_syscall 0.1.57",
|
||||
"redox_syscall",
|
||||
"rust-argon2",
|
||||
]
|
||||
|
||||
@@ -876,10 +809,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581"
|
||||
|
||||
[[package]]
|
||||
name = "rle-decode-fast"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cabe4fa914dec5870285fa7f71f602645da47c486e68486d2b4ceb4a343e90ac"
|
||||
name = "rog_dbus"
|
||||
version = "3.0.0"
|
||||
dependencies = [
|
||||
"rog_fan_curve",
|
||||
"rog_types",
|
||||
"serde_json",
|
||||
"zbus",
|
||||
"zbus_macros",
|
||||
"zvariant",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rog_fan_curve"
|
||||
@@ -890,11 +829,23 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rog_types"
|
||||
version = "3.0.0"
|
||||
dependencies = [
|
||||
"gumdrop",
|
||||
"rog_fan_curve",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"zvariant",
|
||||
"zvariant_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rusb"
|
||||
version = "0.6.5"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6f32cd45962594f9f8cd4547b5757132715600e2c8840aa9ccd3d1a9ed6fdc6"
|
||||
checksum = "c470dc7dc6e4710b6f85e9c4aa4650bc742260b39a36328180578db76fa258c1"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"libusb1-sys",
|
||||
@@ -946,15 +897,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9391c295d64fc0abb2c556bad848f33cb8296276b1ad2677d1ae1ace4f258f31"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.8",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.61"
|
||||
version = "1.0.62"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fceb2595057b6891a4ee808f70054bd2d12f0e97f1cbb78689b59f676df325a"
|
||||
checksum = "ea1c6153794552ea7cf7cf63b1231a25de00ec90db326ba6264440fa08e31486"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
@@ -968,7 +919,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dc6b7951b17b051f3210b063f12cc17320e2fe30ae05b0fe2a3abb068551c76"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.8",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.60",
|
||||
]
|
||||
|
||||
@@ -985,10 +936,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "133659a15339456eeeb07572eb02a91c91e9815e9cbc89566944d2c8d3efdbf6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.8",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.3.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strum"
|
||||
version = "0.8.0"
|
||||
@@ -1023,7 +985,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.8",
|
||||
"quote 1.0.9",
|
||||
"unicode-xid 0.2.1",
|
||||
]
|
||||
|
||||
@@ -1043,7 +1005,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.8",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.60",
|
||||
"unicode-xid 0.2.1",
|
||||
]
|
||||
@@ -1057,17 +1019,6 @@ dependencies = [
|
||||
"numtoa",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tar"
|
||||
version = "0.4.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0313546c01d59e29be4f09687bcb4fb6690cec931cc3607b6aec7a0e417f4cc6"
|
||||
dependencies = [
|
||||
"filetime",
|
||||
"libc",
|
||||
"xattr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.1.2"
|
||||
@@ -1079,9 +1030,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.1.2"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8208a331e1cb318dd5bd76951d2b8fc48ca38a69f5f4e4af1b6a9f8c6236915"
|
||||
checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
]
|
||||
@@ -1106,15 +1057,6 @@ dependencies = [
|
||||
"nom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.4.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.8"
|
||||
@@ -1126,12 +1068,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "udev"
|
||||
version = "0.4.0"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24953d50a3bce0f5f5a9a2766567072dc9af8096f8c40ea81815da651066bc9f"
|
||||
checksum = "307c2b8c8a320a38365def5bb3ee92d146d405655196230f7a445fe4da6749f6"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"libudev-sys",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1239,9 +1182,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "winrt-notification"
|
||||
version = "0.2.2"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c31a65da50d792c6f9bd2e3216249566c4fb1d2d34f9b7d2d66d2e93f62a242"
|
||||
checksum = "57790eb281688a4682dab44df2a1ba8b78373233bd71cb291c3e75fecb1a01c4"
|
||||
dependencies = [
|
||||
"strum",
|
||||
"strum_macros",
|
||||
@@ -1250,15 +1193,6 @@ dependencies = [
|
||||
"xml-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xattr"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xml-rs"
|
||||
version = "0.6.1"
|
||||
@@ -1308,7 +1242,7 @@ checksum = "87cc141cda72384bef359badf1808e391d3968f9299e8f3c3cbb78dafa1e0930"
|
||||
dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote 1.0.8",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.60",
|
||||
]
|
||||
|
||||
@@ -1332,6 +1266,6 @@ checksum = "eaee686340b5bff077d52423d8cc4f0f7cb323fe3f31ef676b8a3a2810bc53c5"
|
||||
dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote 1.0.8",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.60",
|
||||
]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[workspace]
|
||||
members = ["asus-notify", "asus-nb-ctrl", "asus-nb"]
|
||||
members = ["asusctl", "asus-notify", "daemon", "rog-types", "rog-dbus"]
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
|
||||
2
Makefile
@@ -1,4 +1,4 @@
|
||||
VERSION := $(shell grep -Pm1 'version = "(\d.\d.\d)"' asus-nb-ctrl/Cargo.toml | cut -d'"' -f2)
|
||||
VERSION := $(shell grep -Pm1 'version = "(\d.\d.\d)"' daemon/Cargo.toml | cut -d'"' -f2)
|
||||
|
||||
INSTALL = install
|
||||
INSTALL_PROGRAM = ${INSTALL} -D -m 0755
|
||||
|
||||
19
README.md
@@ -1,5 +1,7 @@
|
||||
# ASUS NB Ctrl
|
||||
|
||||
[](https://www.paypal.com/donate/?hosted_button_id=4V2DEPS7K6APC) - [Asus Linux Website](https://asus-linux.org/)
|
||||
|
||||
`asusd` is a utility for Linux to control many aspects of various ASUS laptops
|
||||
but can also be used with non-asus laptops with reduced features.
|
||||
|
||||
@@ -7,6 +9,10 @@ but can also be used with non-asus laptops with reduced features.
|
||||
|
||||
This app is developed and tested on fedora only. Support is not provided for Arch or Arch based distros.
|
||||
|
||||
**NOTICE:**
|
||||
The following is *not* required for 5.11 kernel versions, as this version includes
|
||||
all the required patches.
|
||||
---
|
||||
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/).
|
||||
@@ -53,13 +59,17 @@ will probably suffer another rename once it becomes generic enough to do so.
|
||||
- [X] Set battery charge limit (with kernel supporting this)
|
||||
- [X] Fancy fan control on G14 + G15 thanks to @Yarn1
|
||||
- [X] Graphics mode switching between iGPU, dGPU, and On-Demand
|
||||
- [X] Toggle bios setting for boot/POST sound
|
||||
- [X] Toggle bios setting for "dedicated gfx" mode on supported laptops (g-sync)
|
||||
|
||||
# FUNCTIONS
|
||||
|
||||
## Graphics switching
|
||||
|
||||
A new feature has been added to enable switching graphics modes. This can be disabled
|
||||
in the config with `"manage_gfx": false,`. Please be aware it is a work in progress.
|
||||
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.
|
||||
|
||||
The CLI option for this does not require root until it asks for it, and provides
|
||||
instructions.
|
||||
@@ -79,7 +89,8 @@ If you have installed the Nvidia driver manually you will require the
|
||||
### fedora and openSUSE
|
||||
|
||||
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.
|
||||
to stop dracut including the nvidia modules in the ramdisk. This is espeically
|
||||
true if you manually installed the nvidia drivers.
|
||||
|
||||
```
|
||||
# filename /etc/dracut.conf.d/90-nvidia-dracut-G05.conf
|
||||
@@ -135,9 +146,9 @@ To switch Fan/Thermal profiles you need to bind the Fn+F5 key to `asusctl profil
|
||||
|
||||
Requirements are rust >= 1.40 installed from rustup.io if the distro provided version is too old, and `make`.
|
||||
|
||||
**Ubuntu*:** `apt install libdbus-1-dev libclang-dev libudev-dev`
|
||||
**Ubuntu*:** `apt install libclang-dev libudev-dev`
|
||||
|
||||
**fedora:** `dnf install clang-devel dbus-devel systemd-devel`
|
||||
**fedora:** `dnf install clang-devel systemd-devel`
|
||||
|
||||
## Installing
|
||||
|
||||
|
||||
1016
asus-nb-ctrl/Cargo.lock
generated
@@ -1,30 +0,0 @@
|
||||
use std::error;
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum GfxError {
|
||||
ParseVendor,
|
||||
Path(String, std::io::Error),
|
||||
Read(String, std::io::Error),
|
||||
Write(String, std::io::Error),
|
||||
Module(String, std::io::Error),
|
||||
Bus(String, std::io::Error),
|
||||
Command(String, std::io::Error),
|
||||
}
|
||||
|
||||
impl fmt::Display for GfxError {
|
||||
// This trait requires `fmt` with this exact signature.
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
GfxError::ParseVendor => write!(f, "Could not parse vendor name"),
|
||||
GfxError::Path(path, error) => write!(f, "Path {}: {}", path, error),
|
||||
GfxError::Read(path, error) => write!(f, "Read {}: {}", path, error),
|
||||
GfxError::Write(path, error) => write!(f, "Write {}: {}", path, error),
|
||||
GfxError::Module(func, error) => write!(f, "Module error: {}: {}", func, error),
|
||||
GfxError::Bus(func, error) => write!(f, "Bus error: {}: {}", func, error),
|
||||
GfxError::Command(func, error) => write!(f, "Command exec error: {}: {}", func, error),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for GfxError {}
|
||||
@@ -1,384 +0,0 @@
|
||||
use ctrl_gfx::error::GfxError;
|
||||
use ctrl_gfx::*;
|
||||
use ctrl_rog_bios::CtrlRogBios;
|
||||
use log::{error, info, warn};
|
||||
use std::io::Write;
|
||||
use std::iter::FromIterator;
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
use std::str::FromStr;
|
||||
use std::{error::Error, sync::Arc, sync::Mutex};
|
||||
use sysfs_class::{PciDevice, SysClass};
|
||||
use system::{GraphicsDevice, Module, PciBus};
|
||||
use vendors::{GfxCtrlAction, GfxVendors};
|
||||
use zbus::dbus_interface;
|
||||
|
||||
use crate::*;
|
||||
|
||||
pub struct CtrlGraphics {
|
||||
bus: PciBus,
|
||||
_amd: Vec<GraphicsDevice>,
|
||||
_intel: Vec<GraphicsDevice>,
|
||||
nvidia: Vec<GraphicsDevice>,
|
||||
#[allow(dead_code)]
|
||||
other: Vec<GraphicsDevice>,
|
||||
initfs_cmd: Option<Command>,
|
||||
config: Arc<Mutex<Config>>,
|
||||
}
|
||||
|
||||
trait Dbus {
|
||||
fn vendor(&self) -> String;
|
||||
fn power(&self) -> String;
|
||||
fn set_vendor(&mut self, vendor: String);
|
||||
fn notify_gfx(&self, vendor: &str) -> zbus::Result<()>;
|
||||
fn notify_action(&self, action: &str) -> zbus::Result<()>;
|
||||
}
|
||||
|
||||
use std::convert::TryInto;
|
||||
|
||||
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
||||
impl Dbus for CtrlGraphics {
|
||||
fn vendor(&self) -> String {
|
||||
Self::get_vendor().unwrap_or_else(|err| format!("Get vendor failed: {}", err))
|
||||
}
|
||||
|
||||
fn power(&self) -> String {
|
||||
Self::get_runtime_status().unwrap_or_else(|err| format!("Get power status failed: {}", err))
|
||||
}
|
||||
|
||||
fn set_vendor(&mut self, vendor: String) {
|
||||
if let Ok(tmp) = GfxVendors::from_str(&vendor) {
|
||||
let action = self.set(tmp).unwrap_or_else(|err| {
|
||||
warn!("{}", err);
|
||||
format!("Failed: {}", err.to_string())
|
||||
});
|
||||
self.notify_gfx(&vendor)
|
||||
.unwrap_or_else(|err| warn!("{}", err));
|
||||
self.notify_action(&action)
|
||||
.unwrap_or_else(|err| warn!("{}", err));
|
||||
}
|
||||
}
|
||||
|
||||
#[dbus_interface(signal)]
|
||||
fn notify_gfx(&self, vendor: &str) -> zbus::Result<()> {}
|
||||
|
||||
#[dbus_interface(signal)]
|
||||
fn notify_action(&self, action: &str) -> zbus::Result<()> {}
|
||||
}
|
||||
|
||||
impl CtrlGraphics {
|
||||
pub fn new(config: Arc<Mutex<Config>>) -> std::io::Result<CtrlGraphics> {
|
||||
let bus = PciBus::new()?;
|
||||
|
||||
info!("Rescanning PCI bus");
|
||||
bus.rescan()?;
|
||||
|
||||
let devs = PciDevice::all()?;
|
||||
|
||||
let functions = |parent: &PciDevice| -> Vec<PciDevice> {
|
||||
let mut functions = Vec::new();
|
||||
if let Some(parent_slot) = parent.id().split('.').next() {
|
||||
for func in devs.iter() {
|
||||
if let Some(func_slot) = func.id().split('.').next() {
|
||||
if func_slot == parent_slot {
|
||||
info!("{}: Function for {}", func.id(), parent.id());
|
||||
functions.push(func.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
functions
|
||||
};
|
||||
|
||||
let mut amd = Vec::new();
|
||||
let mut intel = Vec::new();
|
||||
let mut nvidia = Vec::new();
|
||||
let mut other = Vec::new();
|
||||
for dev in devs.iter() {
|
||||
let c = dev.class()?;
|
||||
if 0x03 == (c >> 16) & 0xFF {
|
||||
match dev.vendor()? {
|
||||
0x1002 => {
|
||||
info!("{}: AMD graphics", dev.id());
|
||||
amd.push(GraphicsDevice::new(dev.id().to_owned(), functions(&dev)));
|
||||
}
|
||||
0x10DE => {
|
||||
info!("{}: NVIDIA graphics", dev.id());
|
||||
nvidia.push(GraphicsDevice::new(dev.id().to_owned(), functions(&dev)));
|
||||
}
|
||||
0x8086 => {
|
||||
info!("{}: Intel graphics", dev.id());
|
||||
intel.push(GraphicsDevice::new(dev.id().to_owned(), functions(&dev)));
|
||||
}
|
||||
vendor => {
|
||||
info!("{}: Other({:X}) graphics", dev.id(), vendor);
|
||||
other.push(GraphicsDevice::new(dev.id().to_owned(), functions(&dev)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut initfs_cmd = None;
|
||||
|
||||
if Path::new(INITRAMFS_PATH).exists() {
|
||||
let mut cmd = Command::new("update-initramfs");
|
||||
cmd.arg("-u");
|
||||
initfs_cmd = Some(cmd);
|
||||
info!("Using initramfs update command 'update-initramfs'");
|
||||
}
|
||||
// } else if Path::new(DRACUT_PATH).exists() {
|
||||
// let mut cmd = Command::new("dracut");
|
||||
// cmd.arg("-f");
|
||||
// initfs_cmd = Some(cmd);
|
||||
// info!("Using initramfs update command 'dracut'");
|
||||
// }
|
||||
|
||||
Ok(CtrlGraphics {
|
||||
bus,
|
||||
_amd: amd,
|
||||
_intel: intel,
|
||||
nvidia,
|
||||
other,
|
||||
initfs_cmd,
|
||||
config,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn add_to_server(self, server: &mut zbus::ObjectServer) {
|
||||
server
|
||||
.at(
|
||||
&"/org/asuslinux/Gfx".try_into().expect("Some fail here"),
|
||||
self,
|
||||
)
|
||||
.map_err(|err| {
|
||||
warn!("CtrlGraphics: add_to_server {}", err);
|
||||
err
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
|
||||
pub fn reload(&mut self) -> Result<(), Box<dyn Error>> {
|
||||
self.auto_power()?;
|
||||
info!("Reloaded gfx mode: {:?}", CtrlGraphics::get_vendor()?);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_prime_discrete() -> Result<String, GfxError> {
|
||||
let s = std::fs::read_to_string(PRIME_DISCRETE_PATH)
|
||||
.map_err(|err| GfxError::Read(PRIME_DISCRETE_PATH.into(), err))?
|
||||
.trim()
|
||||
.to_owned();
|
||||
Ok(s)
|
||||
}
|
||||
|
||||
fn set_prime_discrete(mode: &str) -> Result<(), GfxError> {
|
||||
std::fs::write(PRIME_DISCRETE_PATH, mode)
|
||||
.map_err(|err| GfxError::Read(PRIME_DISCRETE_PATH.into(), err))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Associated method to get which vendor mode is set
|
||||
pub fn get_vendor() -> Result<String, GfxError> {
|
||||
let mode = match Self::get_prime_discrete() {
|
||||
Ok(m) => m,
|
||||
Err(_) => "nvidia".to_string(),
|
||||
};
|
||||
let modules = Module::all().map_err(|err| GfxError::Read("get_vendor".into(), err))?;
|
||||
|
||||
let driver_loaded = if modules
|
||||
.iter()
|
||||
.any(|module| module.name == "nouveau" || module.name == "nvidia")
|
||||
{
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
let vendor = if mode == "off" {
|
||||
if driver_loaded {
|
||||
info!("dGPU driver loaded for compute mode");
|
||||
"compute".to_string()
|
||||
} else {
|
||||
info!("No dGPU driver loaded");
|
||||
"integrated".to_string()
|
||||
}
|
||||
} else {
|
||||
info!("Assuming dGPU driver loaded");
|
||||
if mode == "on-demand" {
|
||||
"hybrid".to_string()
|
||||
} else {
|
||||
"nvidia".to_string()
|
||||
}
|
||||
};
|
||||
|
||||
Ok(vendor)
|
||||
}
|
||||
|
||||
pub fn is_switching_prime_modes(vendor: &GfxVendors) -> Result<bool, GfxError> {
|
||||
let prev_mode = GfxVendors::from_str(&Self::get_vendor()?)?;
|
||||
let x = (prev_mode == GfxVendors::Hybrid || prev_mode == GfxVendors::Nvidia)
|
||||
&& (*vendor == GfxVendors::Hybrid || *vendor == GfxVendors::Nvidia);
|
||||
Ok(x)
|
||||
}
|
||||
|
||||
pub fn set_gfx_config(vendor: GfxVendors) -> Result<(), GfxError> {
|
||||
let mode = if vendor == GfxVendors::Hybrid {
|
||||
"on-demand\n"
|
||||
} else if vendor == GfxVendors::Nvidia {
|
||||
"on\n"
|
||||
} else {
|
||||
// Integrated or Compute
|
||||
"off\n"
|
||||
};
|
||||
|
||||
info!("Setting {} to {}", PRIME_DISCRETE_PATH, mode);
|
||||
Self::set_prime_discrete(mode)?;
|
||||
|
||||
{
|
||||
info!("Writing {}", MODPROBE_PATH);
|
||||
|
||||
let mut file = std::fs::OpenOptions::new()
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.write(true)
|
||||
.open(MODPROBE_PATH)
|
||||
.map_err(|err| GfxError::Path(MODPROBE_PATH.into(), err))?;
|
||||
|
||||
let text = if vendor == GfxVendors::Hybrid {
|
||||
MODPROBE_HYBRID
|
||||
} else if vendor == GfxVendors::Compute {
|
||||
MODPROBE_COMPUTE
|
||||
} else if vendor == GfxVendors::Nvidia {
|
||||
MODPROBE_NVIDIA
|
||||
} else {
|
||||
MODPROBE_INTEGRATED
|
||||
};
|
||||
|
||||
file.write_all(text)
|
||||
.and_then(|_| file.sync_all())
|
||||
.map_err(|err| GfxError::Write(MODPROBE_PATH.into(), err))?;
|
||||
}
|
||||
|
||||
info!("Writing {}", PRIMARY_GPU_XORG_PATH);
|
||||
|
||||
// begin section for non-separated Nvidia xorg modules
|
||||
// eg, not put in their own directory
|
||||
let mut file = std::fs::OpenOptions::new()
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.write(true)
|
||||
.open(PRIMARY_GPU_XORG_PATH)
|
||||
.map_err(|err| GfxError::Write(PRIMARY_GPU_XORG_PATH.into(), err))?;
|
||||
|
||||
let text = if vendor == GfxVendors::Nvidia {
|
||||
[PRIMARY_GPU_BEGIN, PRIMARY_GPU_NVIDIA, PRIMARY_GPU_END].concat()
|
||||
} else {
|
||||
[PRIMARY_GPU_BEGIN, PRIMARY_GPU_END].concat()
|
||||
};
|
||||
|
||||
file.write_all(&text)
|
||||
.and_then(|_| file.sync_all())
|
||||
.map_err(|err| GfxError::Write(MODPROBE_PATH.into(), err))?;
|
||||
|
||||
let action = if vendor == GfxVendors::Nvidia {
|
||||
info!("Enabling nvidia-fallback.service");
|
||||
"enable"
|
||||
} else {
|
||||
info!("Disabling nvidia-fallback.service");
|
||||
"disable"
|
||||
};
|
||||
|
||||
let status = Command::new("systemctl")
|
||||
.arg(action)
|
||||
.arg("nvidia-fallback.service")
|
||||
.status()
|
||||
.map_err(|err| GfxError::Command("systemctl".into(), err))?;
|
||||
|
||||
if !status.success() {
|
||||
// Error is ignored in case this service is removed
|
||||
warn!(
|
||||
"systemctl: {} (ignore warning if service does not exist!)",
|
||||
status
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Write out config files if required, enable/disable relevant services, and update the ramdisk
|
||||
pub fn set(&mut self, vendor: GfxVendors) -> Result<String, GfxError> {
|
||||
if CtrlRogBios::has_dedicated_gfx_toggle() {
|
||||
if let Ok(config) = self.config.clone().try_lock() {
|
||||
// Switch to dedicated if config says to do so
|
||||
if config.gfx_nv_mode_is_dedicated && vendor == GfxVendors::Nvidia {
|
||||
CtrlRogBios::set_gfx_mode(true)
|
||||
.unwrap_or_else(|err| warn!("Gfx controller: {}", err));
|
||||
} else if let Ok(ded) = CtrlRogBios::get_gfx_mode() {
|
||||
// otherwise if switching to non-Nvidia mode turn off dedicated mode
|
||||
if ded == 1 && vendor != GfxVendors::Nvidia {
|
||||
CtrlRogBios::set_gfx_mode(false)
|
||||
.unwrap_or_else(|err| warn!("Gfx controller: {}", err));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Switching from hybrid to/from nvidia shouldn't require a ramdisk update
|
||||
// or a reboot.
|
||||
let no_reboot = Self::is_switching_prime_modes(&vendor)?;
|
||||
|
||||
Self::set_gfx_config(vendor)?;
|
||||
|
||||
let mut required_action = GfxCtrlAction::None;
|
||||
if !no_reboot {
|
||||
info!("Updating initramfs");
|
||||
if let Some(cmd) = self.initfs_cmd.as_mut() {
|
||||
let status = cmd
|
||||
.status()
|
||||
.map_err(|err| GfxError::Write(format!("{:?}", cmd), err))?;
|
||||
if !status.success() {
|
||||
error!("Ram disk update failed");
|
||||
} else {
|
||||
info!("Successfully updated iniramfs");
|
||||
}
|
||||
}
|
||||
required_action = GfxCtrlAction::Reboot;
|
||||
} else if no_reboot {
|
||||
required_action = GfxCtrlAction::RestartX;
|
||||
}
|
||||
|
||||
Ok(required_action.into())
|
||||
}
|
||||
|
||||
pub fn get_runtime_status() -> Result<String, GfxError> {
|
||||
const PATH: &str = "/sys/bus/pci/devices/0000:01:00.0/power/runtime_status";
|
||||
let buf = std::fs::read_to_string(PATH).map_err(|err| GfxError::Read(PATH.into(), err))?;
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
fn set_power(&self, power: bool) -> Result<(), GfxError> {
|
||||
if power {
|
||||
info!("Enabling graphics power");
|
||||
self.bus
|
||||
.rescan()
|
||||
.map_err(|err| GfxError::Bus("bus rescan error".into(), err))?;
|
||||
} else {
|
||||
info!("Disabling graphics power");
|
||||
|
||||
// Unbind NVIDIA graphics devices and their functions
|
||||
let unbinds = self.nvidia.iter().map(|dev| dev.unbind());
|
||||
|
||||
// Remove NVIDIA graphics devices and their functions
|
||||
let removes = self.nvidia.iter().map(|dev| dev.remove());
|
||||
|
||||
Result::from_iter(unbinds.chain(removes))
|
||||
.map_err(|err| GfxError::Command("device unbind error".into(), err))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn auto_power(&self) -> Result<(), GfxError> {
|
||||
let vendor = CtrlGraphics::get_vendor()?;
|
||||
self.set_power(vendor != "integrated")
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
pub mod vendors;
|
||||
|
||||
pub mod error;
|
||||
|
||||
pub mod gfx;
|
||||
|
||||
pub mod system;
|
||||
|
||||
const PRIME_DISCRETE_PATH: &str = "/etc/prime-discrete";
|
||||
const MODPROBE_PATH: &str = "/etc/modprobe.d/asusd.conf";
|
||||
const INITRAMFS_PATH: &str = "/usr/sbin/update-initramfs";
|
||||
// const DRACUT_PATH: &str = "/usr/bin/dracut";
|
||||
|
||||
static MODPROBE_NVIDIA: &[u8] = MODPROBE_HYBRID;
|
||||
|
||||
static MODPROBE_HYBRID: &[u8] = br#"# Automatically generated by asusd
|
||||
blacklist i2c_nvidia_gpu
|
||||
alias i2c_nvidia_gpu off
|
||||
options nvidia NVreg_DynamicPowerManagement=0x02
|
||||
options nvidia-drm modeset=1
|
||||
"#;
|
||||
|
||||
static MODPROBE_COMPUTE: &[u8] = br#"# Automatically generated by asusd
|
||||
blacklist i2c_nvidia_gpu
|
||||
alias i2c_nvidia_gpu off
|
||||
options nvidia NVreg_DynamicPowerManagement=0x02
|
||||
options nvidia-drm modeset=0
|
||||
"#;
|
||||
|
||||
static MODPROBE_INTEGRATED: &[u8] = br#"# Automatically generated by asusd
|
||||
blacklist i2c_nvidia_gpu
|
||||
blacklist nouveau
|
||||
blacklist nvidia
|
||||
blacklist nvidia-drm
|
||||
blacklist nvidia-modeset
|
||||
alias i2c_nvidia_gpu off
|
||||
alias nouveau off
|
||||
alias nvidia off
|
||||
alias nvidia-drm off
|
||||
alias nvidia-modeset off
|
||||
"#;
|
||||
|
||||
const PRIMARY_GPU_XORG_PATH: &str = "/etc/X11/xorg.conf.d/90-nvidia-primary.conf";
|
||||
|
||||
static PRIMARY_GPU_BEGIN: &[u8] = br#"# Automatically generated by asusd
|
||||
Section "OutputClass"
|
||||
Identifier "nvidia"
|
||||
MatchDriver "nvidia-drm"
|
||||
Driver "nvidia"
|
||||
Option "AllowEmptyInitialConfiguration"
|
||||
Option "AllowExternalGpus""#;
|
||||
|
||||
static PRIMARY_GPU_NVIDIA: &[u8] = br#"
|
||||
Option "PrimaryGPU" "true""#;
|
||||
|
||||
static PRIMARY_GPU_END: &[u8] = br#"
|
||||
EndSection"#;
|
||||
@@ -1,107 +0,0 @@
|
||||
const DBUS_ANIME_PATH: &str = "/org/asuslinux/Anime";
|
||||
pub const ANIME_PANE1_PREFIX: [u8; 7] = [0x5e, 0xc0, 0x02, 0x01, 0x00, 0x73, 0x02];
|
||||
pub const ANIME_PANE2_PREFIX: [u8; 7] = [0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02];
|
||||
|
||||
use crate::anime_matrix::{AniMeMatrix, AniMePacketType};
|
||||
use crate::DBUS_NAME;
|
||||
use dbus::blocking::{Connection, Proxy};
|
||||
use std::error::Error;
|
||||
use std::{thread, time::Duration};
|
||||
|
||||
use crate::dbus_anime::OrgAsuslinuxDaemon as OrgAsuslinuxDaemonAniMe;
|
||||
|
||||
/// Interface for the AniMe dot-matrix display
|
||||
///
|
||||
/// The resolution is 34x56 (1904) but only 1,215 LEDs in the top-left are used.
|
||||
/// The display is available only on select GA401 models.
|
||||
///
|
||||
/// Actual image ratio when displayed is stretched width.
|
||||
///
|
||||
/// Data structure should be nested array of [[u8; 33]; 56]
|
||||
pub struct AniMeDbusWriter {
|
||||
connection: Box<Connection>,
|
||||
block_time: u64,
|
||||
}
|
||||
|
||||
impl AniMeDbusWriter {
|
||||
#[inline]
|
||||
pub fn new() -> Result<Self, Box<dyn Error>> {
|
||||
let connection = Connection::new_system()?;
|
||||
Ok(AniMeDbusWriter {
|
||||
connection: Box::new(connection),
|
||||
block_time: 25,
|
||||
})
|
||||
}
|
||||
|
||||
// Create D-Bus proxy
|
||||
fn new_proxy(&self) -> Proxy<&Connection> {
|
||||
self.connection
|
||||
.with_proxy(DBUS_NAME, DBUS_ANIME_PATH, Duration::from_millis(200))
|
||||
}
|
||||
|
||||
fn thread_sleep(&self) {
|
||||
thread::sleep(Duration::from_millis(self.block_time));
|
||||
}
|
||||
|
||||
pub fn write_image_to_buf(_buf: &mut AniMePacketType, _image_data: &[u8]) {
|
||||
unimplemented!("Image format is in progress of being worked out")
|
||||
}
|
||||
|
||||
/// Write an Animatrix image
|
||||
///
|
||||
/// The expected input here is *two* Vectors, 640 bytes in length.
|
||||
/// The two vectors are each one half of the full image write.
|
||||
///
|
||||
/// 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 packet 1: 0x5e 0xc0 0x02 0x01 0x00 0x73 0x02 .. <led brightness>
|
||||
/// - Write packet 2: 0x5e 0xc0 0x02 0x74 0x02 0x73 0x02 .. <led brightness>
|
||||
///
|
||||
/// Where led brightness is 0..255, low to high
|
||||
#[inline]
|
||||
pub fn write_image(&self, image: &mut AniMePacketType) -> Result<(), Box<dyn Error>> {
|
||||
let proxy = self.new_proxy();
|
||||
|
||||
image[0][..7].copy_from_slice(&ANIME_PANE1_PREFIX);
|
||||
image[1][..7].copy_from_slice(&ANIME_PANE2_PREFIX);
|
||||
|
||||
proxy.set_anime(vec![image[0].to_vec(), image[1].to_vec()])?;
|
||||
self.thread_sleep();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_leds_brightness(&self, led_brightness: u8) -> Result<(), Box<dyn Error>> {
|
||||
let mut anime_matrix = AniMeMatrix::new();
|
||||
|
||||
anime_matrix.fill_with(led_brightness);
|
||||
self.write_image(&mut AniMePacketType::from(anime_matrix))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn turn_on_off(&self, status: bool) -> Result<(), Box<dyn Error>> {
|
||||
let proxy = self.new_proxy();
|
||||
|
||||
proxy.set_on_off(status)?;
|
||||
self.thread_sleep();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn turn_boot_on_off(&self, status: bool) -> Result<(), Box<dyn Error>> {
|
||||
let proxy = self.new_proxy();
|
||||
|
||||
proxy.set_boot_on_off(status)?;
|
||||
self.thread_sleep();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,287 +0,0 @@
|
||||
use crate::error::AuraError;
|
||||
use gumdrop::Options;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(Options)]
|
||||
pub struct LedBrightness {
|
||||
level: Option<u8>,
|
||||
}
|
||||
impl LedBrightness {
|
||||
pub fn new(level: Option<u8>) -> Self {
|
||||
LedBrightness { level }
|
||||
}
|
||||
|
||||
pub fn level(&self) -> Option<u8> {
|
||||
self.level
|
||||
}
|
||||
}
|
||||
impl FromStr for LedBrightness {
|
||||
type Err = AuraError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let s = s.to_lowercase();
|
||||
match s.as_str() {
|
||||
"off" => Ok(LedBrightness { level: Some(0x00) }),
|
||||
"low" => Ok(LedBrightness { level: Some(0x01) }),
|
||||
"med" => Ok(LedBrightness { level: Some(0x02) }),
|
||||
"high" => Ok(LedBrightness { level: Some(0x03) }),
|
||||
_ => {
|
||||
print!(
|
||||
"{}\n{}\n",
|
||||
"Invalid argument, must be one of:", "off, low, med, high"
|
||||
);
|
||||
Err(AuraError::ParseBrightness)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
impl ToString for LedBrightness {
|
||||
fn to_string(&self) -> String {
|
||||
let s = match self.level {
|
||||
Some(0x00) => "low",
|
||||
Some(0x01) => "med",
|
||||
Some(0x02) => "high",
|
||||
_ => "unknown",
|
||||
};
|
||||
s.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct Colour(pub u8, pub u8, pub u8);
|
||||
impl Default for Colour {
|
||||
fn default() -> Self {
|
||||
Colour(255, 0, 0)
|
||||
}
|
||||
}
|
||||
impl FromStr for Colour {
|
||||
type Err = AuraError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
if s.len() < 6 {
|
||||
return Err(AuraError::ParseColour);
|
||||
}
|
||||
let r = u8::from_str_radix(&s[0..2], 16).or(Err(AuraError::ParseColour))?;
|
||||
let g = u8::from_str_radix(&s[2..4], 16).or(Err(AuraError::ParseColour))?;
|
||||
let b = u8::from_str_radix(&s[4..6], 16).or(Err(AuraError::ParseColour))?;
|
||||
Ok(Colour(r, g, b))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub enum Speed {
|
||||
Low = 0xe1,
|
||||
Med = 0xeb,
|
||||
High = 0xf5,
|
||||
}
|
||||
impl Default for Speed {
|
||||
fn default() -> Self {
|
||||
Speed::Med
|
||||
}
|
||||
}
|
||||
impl FromStr for Speed {
|
||||
type Err = AuraError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let s = s.to_lowercase();
|
||||
match s.as_str() {
|
||||
"low" => Ok(Speed::Low),
|
||||
"med" => Ok(Speed::Med),
|
||||
"high" => Ok(Speed::High),
|
||||
_ => Err(AuraError::ParseSpeed),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Used for Rainbow mode.
|
||||
///
|
||||
/// Enum corresponds to the required integer value
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub enum Direction {
|
||||
Right,
|
||||
Left,
|
||||
Up,
|
||||
Down,
|
||||
}
|
||||
impl Default for Direction {
|
||||
fn default() -> Self {
|
||||
Direction::Right
|
||||
}
|
||||
}
|
||||
impl FromStr for Direction {
|
||||
type Err = AuraError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let s = s.to_lowercase();
|
||||
match s.as_str() {
|
||||
"right" => Ok(Direction::Right),
|
||||
"up" => Ok(Direction::Up),
|
||||
"down" => Ok(Direction::Down),
|
||||
"left" => Ok(Direction::Left),
|
||||
_ => Err(AuraError::ParseDirection),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Options, Deserialize, Serialize)]
|
||||
pub struct TwoColourSpeed {
|
||||
#[options(help = "print help message")]
|
||||
help: bool,
|
||||
#[options(no_long, meta = "HEX", help = "set the first RGB value e.g, ff00ff")]
|
||||
pub colour: Colour,
|
||||
#[options(no_long, meta = "HEX", help = "set the second RGB value e.g, ff00ff")]
|
||||
pub colour2: Colour,
|
||||
#[options(no_long, help = "set the speed: low, med, high")]
|
||||
pub speed: Speed,
|
||||
}
|
||||
|
||||
#[derive(Default, Options, Deserialize, Serialize)]
|
||||
pub struct SingleSpeed {
|
||||
#[options(help = "print help message")]
|
||||
help: bool,
|
||||
#[options(no_long, meta = "WORD", help = "set the speed: low, med, high")]
|
||||
pub speed: Speed,
|
||||
}
|
||||
|
||||
#[derive(Default, Options, Deserialize, Serialize)]
|
||||
pub struct SingleColour {
|
||||
#[options(help = "print help message")]
|
||||
help: bool,
|
||||
#[options(no_long, meta = "HEX", help = "set the RGB value e.g, ff00ff")]
|
||||
pub colour: Colour,
|
||||
}
|
||||
|
||||
#[derive(Default, Options, Deserialize, Serialize)]
|
||||
pub struct MultiColour {
|
||||
#[options(help = "print help message")]
|
||||
help: bool,
|
||||
#[options(meta = "HEX", help = "set the RGB value e.g, ff00ff")]
|
||||
pub colour1: Colour,
|
||||
#[options(meta = "HEX", help = "set the RGB value e.g, ff00ff")]
|
||||
pub colour2: Colour,
|
||||
#[options(meta = "HEX", help = "set the RGB value e.g, ff00ff")]
|
||||
pub colour3: Colour,
|
||||
#[options(meta = "HEX", help = "set the RGB value e.g, ff00ff")]
|
||||
pub colour4: Colour,
|
||||
}
|
||||
|
||||
#[derive(Default, Options, Deserialize, Serialize)]
|
||||
pub struct SingleSpeedDirection {
|
||||
#[options(help = "print help message")]
|
||||
help: bool,
|
||||
#[options(
|
||||
no_long,
|
||||
meta = "DIR",
|
||||
help = "set the direction: up, down, left, right"
|
||||
)]
|
||||
pub direction: Direction,
|
||||
#[options(no_long, help = "set the speed: low, med, high")]
|
||||
pub speed: Speed,
|
||||
}
|
||||
|
||||
#[derive(Default, Options, Deserialize, Serialize)]
|
||||
pub struct SingleColourSpeed {
|
||||
#[options(help = "print help message")]
|
||||
help: bool,
|
||||
#[options(no_long, meta = "HEX", help = "set the RGB value e.g, ff00ff")]
|
||||
pub colour: Colour,
|
||||
#[options(no_long, help = "set the speed: low, med, high")]
|
||||
pub speed: Speed,
|
||||
}
|
||||
|
||||
/// Byte value for setting the built-in mode.
|
||||
///
|
||||
/// Enum corresponds to the required integer value
|
||||
#[derive(Options, Deserialize, Serialize)]
|
||||
pub enum SetAuraBuiltin {
|
||||
#[options(help = "set a single static colour")]
|
||||
Static(SingleColour),
|
||||
#[options(help = "pulse between one or two colours")]
|
||||
Breathe(TwoColourSpeed),
|
||||
#[options(help = "strobe through all colours")]
|
||||
Strobe(SingleSpeed),
|
||||
#[options(help = "rainbow cycling in one of four directions")]
|
||||
Rainbow(SingleSpeedDirection),
|
||||
#[options(help = "rain pattern mimicking raindrops")]
|
||||
Star(TwoColourSpeed),
|
||||
#[options(help = "rain pattern of three preset colours")]
|
||||
Rain(SingleSpeed),
|
||||
#[options(help = "pressed keys are highlighted to fade")]
|
||||
Highlight(SingleColourSpeed),
|
||||
#[options(help = "pressed keys generate horizontal laser")]
|
||||
Laser(SingleColourSpeed),
|
||||
#[options(help = "pressed keys ripple outwards like a splash")]
|
||||
Ripple(SingleColourSpeed),
|
||||
#[options(help = "set a rapid pulse")]
|
||||
Pulse(SingleColour),
|
||||
#[options(help = "set a vertical line zooming from left")]
|
||||
Comet(SingleColour),
|
||||
#[options(help = "set a wide vertical line zooming from left")]
|
||||
Flash(SingleColour),
|
||||
#[options(help = "4-zone multi-colour")]
|
||||
MultiStatic(MultiColour),
|
||||
}
|
||||
|
||||
impl Default for SetAuraBuiltin {
|
||||
fn default() -> Self {
|
||||
SetAuraBuiltin::Static(SingleColour {
|
||||
help: false,
|
||||
colour: Colour(255, 0, 0),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum AniMeStatusValue {
|
||||
On,
|
||||
Off,
|
||||
}
|
||||
impl FromStr for AniMeStatusValue {
|
||||
type Err = AuraError;
|
||||
|
||||
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!("{}\n{}\n", "Invalid argument, must be one of:", "on, off");
|
||||
Err(AuraError::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 = "BYTE",
|
||||
help = "set all leds brightness value"
|
||||
)]
|
||||
led_brightness: u8,
|
||||
}
|
||||
impl AniMeLeds {
|
||||
pub fn led_brightness(&self) -> u8 {
|
||||
self.led_brightness
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Options)]
|
||||
pub enum AniMeActions {
|
||||
#[options(help = "change all leds brightness")]
|
||||
Leds(AniMeLeds),
|
||||
}
|
||||
@@ -1,418 +0,0 @@
|
||||
use super::*;
|
||||
use crate::cli_options::LedBrightness;
|
||||
use crate::fancy::KeyColourArray;
|
||||
use crate::profile::ProfileEvent;
|
||||
use dbus::{blocking::Connection, Message};
|
||||
use std::error::Error;
|
||||
use std::sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
Arc, Mutex,
|
||||
};
|
||||
use std::{thread, time::Duration};
|
||||
|
||||
use crate::dbus_charge::{
|
||||
OrgAsuslinuxDaemon as OrgAsuslinuxDaemonCharge, OrgAsuslinuxDaemonNotifyCharge,
|
||||
};
|
||||
use crate::dbus_gfx::{
|
||||
OrgAsuslinuxDaemon as OrgAsuslinuxDaemonGfx, OrgAsuslinuxDaemonNotifyAction,
|
||||
OrgAsuslinuxDaemonNotifyGfx,
|
||||
};
|
||||
use crate::dbus_ledmode::{
|
||||
OrgAsuslinuxDaemon as OrgAsuslinuxDaemonLed, OrgAsuslinuxDaemonNotifyLed,
|
||||
};
|
||||
use crate::dbus_profile::{
|
||||
OrgAsuslinuxDaemon as OrgAsuslinuxDaemonProfile, OrgAsuslinuxDaemonNotifyProfile,
|
||||
};
|
||||
use crate::dbus_rogbios::OrgAsuslinuxDaemon as OrgAsuslinuxDaemonRogBios;
|
||||
use crate::dbus_supported::OrgAsuslinuxDaemon as OrgAsuslinuxDaemonSupported;
|
||||
|
||||
// Signals separated out
|
||||
pub struct CtrlSignals {
|
||||
pub gfx_vendor_signal: Arc<Mutex<Option<String>>>,
|
||||
pub gfx_action_signal: Arc<Mutex<Option<String>>>,
|
||||
pub profile_signal: Arc<Mutex<Option<String>>>,
|
||||
pub ledmode_signal: Arc<Mutex<Option<AuraModes>>>,
|
||||
pub charge_signal: Arc<Mutex<Option<u8>>>,
|
||||
}
|
||||
|
||||
impl CtrlSignals {
|
||||
#[inline]
|
||||
pub fn new(connection: &Connection) -> Result<Self, Box<dyn Error>> {
|
||||
let proxy = connection.with_proxy(
|
||||
"org.asuslinux.Daemon",
|
||||
"/org/asuslinux/Gfx",
|
||||
Duration::from_secs(2),
|
||||
);
|
||||
|
||||
let gfx_vendor_signal = Arc::new(Mutex::new(None));
|
||||
let gfx_res1 = gfx_vendor_signal.clone();
|
||||
|
||||
let _x = proxy.match_signal(
|
||||
move |sig: OrgAsuslinuxDaemonNotifyGfx, _: &Connection, _: &Message| {
|
||||
if let Ok(mut lock) = gfx_res1.lock() {
|
||||
*lock = Some(sig.vendor);
|
||||
}
|
||||
true
|
||||
},
|
||||
)?;
|
||||
|
||||
let gfx_action_signal = Arc::new(Mutex::new(None));
|
||||
let gfx_res1 = gfx_action_signal.clone();
|
||||
|
||||
let _x = proxy.match_signal(
|
||||
move |sig: OrgAsuslinuxDaemonNotifyAction, _: &Connection, _: &Message| {
|
||||
if let Ok(mut lock) = gfx_res1.lock() {
|
||||
*lock = Some(sig.action);
|
||||
}
|
||||
true
|
||||
},
|
||||
)?;
|
||||
|
||||
//
|
||||
let proxy = connection.with_proxy(
|
||||
"org.asuslinux.Daemon",
|
||||
"/org/asuslinux/Profile",
|
||||
Duration::from_secs(2),
|
||||
);
|
||||
|
||||
let profile_signal = Arc::new(Mutex::new(None));
|
||||
let prof_res1 = profile_signal.clone();
|
||||
|
||||
let _x = proxy.match_signal(
|
||||
move |sig: OrgAsuslinuxDaemonNotifyProfile, _: &Connection, _: &Message| {
|
||||
if let Ok(mut lock) = prof_res1.lock() {
|
||||
*lock = Some(sig.profile);
|
||||
}
|
||||
true
|
||||
},
|
||||
)?;
|
||||
|
||||
//
|
||||
let proxy = connection.with_proxy(
|
||||
"org.asuslinux.Daemon",
|
||||
"/org/asuslinux/Led",
|
||||
Duration::from_secs(2),
|
||||
);
|
||||
|
||||
let ledmode_signal = Arc::new(Mutex::new(None));
|
||||
let led_res1 = ledmode_signal.clone();
|
||||
|
||||
let _x = proxy.match_signal(
|
||||
move |sig: OrgAsuslinuxDaemonNotifyLed, _: &Connection, _: &Message| {
|
||||
if let Ok(mut lock) = led_res1.lock() {
|
||||
if let Ok(dat) = serde_json::from_str(&sig.data) {
|
||||
*lock = Some(dat);
|
||||
}
|
||||
}
|
||||
true
|
||||
},
|
||||
)?;
|
||||
|
||||
//
|
||||
let proxy = connection.with_proxy(
|
||||
"org.asuslinux.Daemon",
|
||||
"/org/asuslinux/Charge",
|
||||
Duration::from_secs(2),
|
||||
);
|
||||
|
||||
let charge_signal = Arc::new(Mutex::new(None));
|
||||
let charge_res1 = charge_signal.clone();
|
||||
|
||||
let _x = proxy.match_signal(
|
||||
move |sig: OrgAsuslinuxDaemonNotifyCharge, _: &Connection, _: &Message| {
|
||||
if let Ok(mut lock) = charge_res1.lock() {
|
||||
*lock = Some(sig.limit);
|
||||
}
|
||||
true
|
||||
},
|
||||
)?;
|
||||
|
||||
Ok(CtrlSignals {
|
||||
gfx_vendor_signal,
|
||||
gfx_action_signal,
|
||||
profile_signal,
|
||||
ledmode_signal,
|
||||
charge_signal,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Simplified way to write a effect block
|
||||
pub struct AuraDbusClient {
|
||||
connection: Box<Connection>,
|
||||
block_time: u64,
|
||||
stop: Arc<AtomicBool>,
|
||||
signals: CtrlSignals,
|
||||
}
|
||||
|
||||
impl AuraDbusClient {
|
||||
#[inline]
|
||||
pub fn new() -> Result<Self, Box<dyn Error>> {
|
||||
let connection = Connection::new_system()?;
|
||||
|
||||
let stop = Arc::new(AtomicBool::new(false));
|
||||
let match_rule = dbus::message::MatchRule::new_signal(DBUS_IFACE, "NotifyLed");
|
||||
let stop1 = stop.clone();
|
||||
connection.add_match(match_rule, move |_: (), _, msg| {
|
||||
if msg.read1::<&str>().is_ok() {
|
||||
stop1.clone().store(true, Ordering::Relaxed);
|
||||
}
|
||||
true
|
||||
})?;
|
||||
|
||||
let signals = CtrlSignals::new(&connection)?;
|
||||
|
||||
Ok(AuraDbusClient {
|
||||
connection: Box::new(connection),
|
||||
block_time: 33333,
|
||||
stop,
|
||||
signals,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn wait_gfx_changed(&self) -> Result<String, Box<dyn Error>> {
|
||||
loop {
|
||||
self.connection.process(Duration::from_millis(1))?;
|
||||
if let Ok(lock) = self.signals.gfx_action_signal.lock() {
|
||||
if let Some(stuff) = lock.as_ref() {
|
||||
return Ok(stuff.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This method must always be called before the very first write to initialise
|
||||
/// the keyboard LED EC in the correct mode
|
||||
#[inline]
|
||||
pub fn init_effect(&self) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mode = AuraModes::PerKey(vec![vec![]]);
|
||||
let proxy = self.connection.with_proxy(
|
||||
"org.asuslinux.Daemon",
|
||||
"/org/asuslinux/Led",
|
||||
Duration::from_secs(2),
|
||||
);
|
||||
proxy.set_led_mode(&serde_json::to_string(&mode)?)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Write a single colour block.
|
||||
///
|
||||
/// Intentionally blocks for 10ms after sending to allow the block to
|
||||
/// be written to the keyboard EC. This should not be async.
|
||||
#[inline]
|
||||
pub fn write_colour_block(
|
||||
&mut self,
|
||||
key_colour_array: &KeyColourArray,
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
let group = key_colour_array.get();
|
||||
let mut vecs = Vec::with_capacity(group.len());
|
||||
for v in group {
|
||||
vecs.push(v.to_vec());
|
||||
}
|
||||
let mode = AuraModes::PerKey(vecs);
|
||||
|
||||
self.write_keyboard_leds(&mode)?;
|
||||
|
||||
thread::sleep(Duration::from_micros(self.block_time));
|
||||
self.connection.process(Duration::from_micros(500))?;
|
||||
|
||||
if self.stop.load(Ordering::Relaxed) {
|
||||
println!("Keyboard backlight was changed, exiting");
|
||||
std::process::exit(1)
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn write_keyboard_leds(&self, mode: &AuraModes) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let proxy = self.connection.with_proxy(
|
||||
"org.asuslinux.Daemon",
|
||||
"/org/asuslinux/Led",
|
||||
Duration::from_secs(2),
|
||||
);
|
||||
proxy.set_led_mode(&serde_json::to_string(mode)?)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn next_keyboard_led_mode(&self) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let proxy = self.connection.with_proxy(
|
||||
"org.asuslinux.Daemon",
|
||||
"/org/asuslinux/Led",
|
||||
Duration::from_secs(2),
|
||||
);
|
||||
proxy.next_led_mode()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn prev_keyboard_led_mode(&self) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let proxy = self.connection.with_proxy(
|
||||
"org.asuslinux.Daemon",
|
||||
"/org/asuslinux/Led",
|
||||
Duration::from_secs(2),
|
||||
);
|
||||
proxy.prev_led_mode()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_gfx_pwr(&self) -> Result<String, Box<dyn std::error::Error>> {
|
||||
let proxy = self.connection.with_proxy(
|
||||
"org.asuslinux.Daemon",
|
||||
"/org/asuslinux/Gfx",
|
||||
Duration::from_secs(2),
|
||||
);
|
||||
let x = proxy.power()?;
|
||||
Ok(x)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_gfx_mode(&self) -> Result<String, Box<dyn std::error::Error>> {
|
||||
let proxy = self.connection.with_proxy(
|
||||
"org.asuslinux.Daemon",
|
||||
"/org/asuslinux/Gfx",
|
||||
Duration::from_secs(2),
|
||||
);
|
||||
let x = proxy.vendor()?;
|
||||
Ok(x)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn write_gfx_mode(&self, vendor: String) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let proxy = self.connection.with_proxy(
|
||||
"org.asuslinux.Daemon",
|
||||
"/org/asuslinux/Gfx",
|
||||
Duration::from_secs(30),
|
||||
);
|
||||
proxy.set_vendor(&vendor)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn next_fan_profile(&self) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let proxy = self.connection.with_proxy(
|
||||
"org.asuslinux.Daemon",
|
||||
"/org/asuslinux/Profile",
|
||||
Duration::from_secs(2),
|
||||
);
|
||||
proxy.next_profile()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn write_fan_mode(&self, level: u8) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let proxy = self.connection.with_proxy(
|
||||
"org.asuslinux.Daemon",
|
||||
"/org/asuslinux/Profile",
|
||||
Duration::from_secs(2),
|
||||
);
|
||||
proxy.set_profile(&serde_json::to_string(&ProfileEvent::ChangeMode(level))?)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn write_profile_command(
|
||||
&self,
|
||||
cmd: &ProfileEvent,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let proxy = self.connection.with_proxy(
|
||||
"org.asuslinux.Daemon",
|
||||
"/org/asuslinux/Profile",
|
||||
Duration::from_secs(2),
|
||||
);
|
||||
proxy.set_profile(&serde_json::to_string(cmd)?)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn write_charge_limit(&self, level: u8) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let proxy = self.connection.with_proxy(
|
||||
"org.asuslinux.Daemon",
|
||||
"/org/asuslinux/Charge",
|
||||
Duration::from_secs(2),
|
||||
);
|
||||
proxy.set_limit(level)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn write_builtin_mode(&self, mode: &AuraModes) -> Result<(), Box<dyn std::error::Error>> {
|
||||
self.write_keyboard_leds(mode)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_led_brightness(&self) -> Result<LedBrightness, Box<dyn Error>> {
|
||||
let proxy = self.connection.with_proxy(
|
||||
"org.asuslinux.Daemon",
|
||||
"/org/asuslinux/Led",
|
||||
Duration::from_secs(2),
|
||||
);
|
||||
match proxy.led_brightness()? {
|
||||
-1 => Ok(LedBrightness::new(None)),
|
||||
level => Ok(LedBrightness::new(Some(level as u8))),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn write_brightness(&self, level: u8) -> Result<(), Box<dyn std::error::Error>> {
|
||||
self.write_keyboard_leds(&AuraModes::LedBrightness(level))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
//
|
||||
#[inline]
|
||||
pub fn get_bios_dedicated_gfx(&self) -> Result<i16, Box<dyn std::error::Error>> {
|
||||
let proxy = self.connection.with_proxy(
|
||||
"org.asuslinux.Daemon",
|
||||
"/org/asuslinux/RogBios",
|
||||
Duration::from_secs(2),
|
||||
);
|
||||
let x = proxy.dedicated_graphic_mode()?;
|
||||
Ok(x)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_bios_dedicated_gfx(&self, on: bool) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let proxy = self.connection.with_proxy(
|
||||
"org.asuslinux.Daemon",
|
||||
"/org/asuslinux/RogBios",
|
||||
Duration::from_secs(2),
|
||||
);
|
||||
proxy.set_dedicated_graphic_mode(<bool>::from(on))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_bios_post_sound(&self) -> Result<i16, Box<dyn std::error::Error>> {
|
||||
let proxy = self.connection.with_proxy(
|
||||
"org.asuslinux.Daemon",
|
||||
"/org/asuslinux/RogBios",
|
||||
Duration::from_secs(2),
|
||||
);
|
||||
let x = proxy.post_boot_sound()?;
|
||||
Ok(x)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_bios_post_sound(&self, on: bool) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let proxy = self.connection.with_proxy(
|
||||
"org.asuslinux.Daemon",
|
||||
"/org/asuslinux/RogBios",
|
||||
Duration::from_secs(2),
|
||||
);
|
||||
proxy.set_post_boot_sound(<bool>::from(on))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_supported_functions(&self) -> Result<String, Box<dyn std::error::Error>> {
|
||||
let proxy = self.connection.with_proxy(
|
||||
"org.asuslinux.Daemon",
|
||||
"/org/asuslinux/Supported",
|
||||
Duration::from_secs(2),
|
||||
);
|
||||
let x = proxy.supported_functions()?;
|
||||
Ok(x)
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
// This code was autogenerated with `dbus-codegen-rust -s -d org.asuslinux.Daemon -p /org/asuslinux/Anime -m None -f org.asuslinux.Daemon -c blocking`, see https://github.com/diwic/dbus-rs
|
||||
use dbus;
|
||||
#[allow(unused_imports)]
|
||||
use dbus::arg;
|
||||
use dbus::blocking;
|
||||
|
||||
pub trait OrgAsuslinuxDaemon {
|
||||
fn set_anime(&self, input: Vec<Vec<u8>>) -> Result<(), dbus::Error>;
|
||||
fn set_on_off(&self, status: bool) -> Result<(), dbus::Error>;
|
||||
fn set_boot_on_off(&self, status: bool) -> Result<(), dbus::Error>;
|
||||
}
|
||||
|
||||
impl<'a, T: blocking::BlockingSender, C: ::std::ops::Deref<Target = T>> OrgAsuslinuxDaemon
|
||||
for blocking::Proxy<'a, C>
|
||||
{
|
||||
fn set_anime(&self, input: Vec<Vec<u8>>) -> Result<(), dbus::Error> {
|
||||
self.method_call("org.asuslinux.Daemon", "SetAnime", (input,))
|
||||
}
|
||||
|
||||
fn set_on_off(&self, status: bool) -> Result<(), dbus::Error> {
|
||||
self.method_call("org.asuslinux.Daemon", "SetOnOff", (status,))
|
||||
}
|
||||
|
||||
fn set_boot_on_off(&self, status: bool) -> Result<(), dbus::Error> {
|
||||
self.method_call("org.asuslinux.Daemon", "SetBootOnOff", (status,))
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
// This code was autogenerated with `dbus-codegen-rust -s -d org.asuslinux.Daemon -f org.asuslinux.Daemon -c blocking -p /org/asuslinux/Charge -m None`, see https://github.com/diwic/dbus-rs
|
||||
use dbus;
|
||||
#[allow(unused_imports)]
|
||||
use dbus::arg;
|
||||
use dbus::blocking;
|
||||
|
||||
pub trait OrgAsuslinuxDaemon {
|
||||
fn set_limit(&self, limit: u8) -> Result<(), dbus::Error>;
|
||||
fn limit(&self) -> Result<i16, dbus::Error>;
|
||||
}
|
||||
|
||||
impl<'a, T: blocking::BlockingSender, C: ::std::ops::Deref<Target = T>> OrgAsuslinuxDaemon
|
||||
for blocking::Proxy<'a, C>
|
||||
{
|
||||
fn set_limit(&self, limit: u8) -> Result<(), dbus::Error> {
|
||||
self.method_call("org.asuslinux.Daemon", "SetLimit", (limit,))
|
||||
}
|
||||
|
||||
fn limit(&self) -> Result<i16, dbus::Error> {
|
||||
self.method_call("org.asuslinux.Daemon", "Limit", ())
|
||||
.and_then(|r: (i16,)| Ok(r.0))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct OrgAsuslinuxDaemonNotifyCharge {
|
||||
pub limit: u8,
|
||||
}
|
||||
|
||||
impl arg::AppendAll for OrgAsuslinuxDaemonNotifyCharge {
|
||||
fn append(&self, i: &mut arg::IterAppend) {
|
||||
arg::RefArg::append(&self.limit, i);
|
||||
}
|
||||
}
|
||||
|
||||
impl arg::ReadAll for OrgAsuslinuxDaemonNotifyCharge {
|
||||
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
|
||||
Ok(OrgAsuslinuxDaemonNotifyCharge { limit: i.read()? })
|
||||
}
|
||||
}
|
||||
|
||||
impl dbus::message::SignalArgs for OrgAsuslinuxDaemonNotifyCharge {
|
||||
const NAME: &'static str = "NotifyCharge";
|
||||
const INTERFACE: &'static str = "org.asuslinux.Daemon";
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
// This code was autogenerated with `dbus-codegen-rust -s -d org.asuslinux.Daemon -p /org/asuslinux/Gfx -m None -f org.asuslinux.Daemon -c blocking`, see https://github.com/diwic/dbus-rs
|
||||
use dbus;
|
||||
#[allow(unused_imports)]
|
||||
use dbus::arg;
|
||||
use dbus::blocking;
|
||||
|
||||
pub trait OrgAsuslinuxDaemon {
|
||||
fn vendor(&self) -> Result<String, dbus::Error>;
|
||||
fn power(&self) -> Result<String, dbus::Error>;
|
||||
fn set_vendor(&self, vendor: &str) -> Result<(), dbus::Error>;
|
||||
}
|
||||
|
||||
impl<'a, T: blocking::BlockingSender, C: ::std::ops::Deref<Target = T>> OrgAsuslinuxDaemon
|
||||
for blocking::Proxy<'a, C>
|
||||
{
|
||||
fn vendor(&self) -> Result<String, dbus::Error> {
|
||||
self.method_call("org.asuslinux.Daemon", "Vendor", ())
|
||||
.and_then(|r: (String,)| Ok(r.0))
|
||||
}
|
||||
|
||||
fn power(&self) -> Result<String, dbus::Error> {
|
||||
self.method_call("org.asuslinux.Daemon", "Power", ())
|
||||
.and_then(|r: (String,)| Ok(r.0))
|
||||
}
|
||||
|
||||
fn set_vendor(&self, vendor: &str) -> Result<(), dbus::Error> {
|
||||
self.method_call("org.asuslinux.Daemon", "SetVendor", (vendor,))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct OrgAsuslinuxDaemonNotifyGfx {
|
||||
pub vendor: String,
|
||||
}
|
||||
|
||||
impl arg::AppendAll for OrgAsuslinuxDaemonNotifyGfx {
|
||||
fn append(&self, i: &mut arg::IterAppend) {
|
||||
arg::RefArg::append(&self.vendor, i);
|
||||
}
|
||||
}
|
||||
|
||||
impl arg::ReadAll for OrgAsuslinuxDaemonNotifyGfx {
|
||||
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
|
||||
Ok(OrgAsuslinuxDaemonNotifyGfx { vendor: i.read()? })
|
||||
}
|
||||
}
|
||||
|
||||
impl dbus::message::SignalArgs for OrgAsuslinuxDaemonNotifyGfx {
|
||||
const NAME: &'static str = "NotifyGfx";
|
||||
const INTERFACE: &'static str = "org.asuslinux.Daemon";
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct OrgAsuslinuxDaemonNotifyAction {
|
||||
pub action: String,
|
||||
}
|
||||
|
||||
impl arg::AppendAll for OrgAsuslinuxDaemonNotifyAction {
|
||||
fn append(&self, i: &mut arg::IterAppend) {
|
||||
arg::RefArg::append(&self.action, i);
|
||||
}
|
||||
}
|
||||
|
||||
impl arg::ReadAll for OrgAsuslinuxDaemonNotifyAction {
|
||||
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
|
||||
Ok(OrgAsuslinuxDaemonNotifyAction { action: i.read()? })
|
||||
}
|
||||
}
|
||||
|
||||
impl dbus::message::SignalArgs for OrgAsuslinuxDaemonNotifyAction {
|
||||
const NAME: &'static str = "NotifyAction";
|
||||
const INTERFACE: &'static str = "org.asuslinux.Daemon";
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
// This code was autogenerated with `dbus-codegen-rust -s -d org.asuslinux.Daemon -f org.asuslinux.Daemon -c blocking -p /org/asuslinux/Led -m None`, see https://github.com/diwic/dbus-rs
|
||||
use dbus;
|
||||
#[allow(unused_imports)]
|
||||
use dbus::arg;
|
||||
use dbus::blocking;
|
||||
|
||||
pub trait OrgAsuslinuxDaemon {
|
||||
fn set_led_mode(&self, data: &str) -> Result<(), dbus::Error>;
|
||||
fn next_led_mode(&self) -> Result<(), dbus::Error>;
|
||||
fn prev_led_mode(&self) -> Result<(), dbus::Error>;
|
||||
fn led_mode(&self) -> Result<String, dbus::Error>;
|
||||
fn led_modes(&self) -> Result<String, dbus::Error>;
|
||||
fn led_brightness(&self) -> Result<i16, dbus::Error>;
|
||||
}
|
||||
|
||||
impl<'a, T: blocking::BlockingSender, C: ::std::ops::Deref<Target = T>> OrgAsuslinuxDaemon
|
||||
for blocking::Proxy<'a, C>
|
||||
{
|
||||
fn set_led_mode(&self, data: &str) -> Result<(), dbus::Error> {
|
||||
self.method_call("org.asuslinux.Daemon", "SetLedMode", (data,))
|
||||
}
|
||||
|
||||
fn next_led_mode(&self) -> Result<(), dbus::Error> {
|
||||
self.method_call("org.asuslinux.Daemon", "NextLedMode", ())
|
||||
}
|
||||
|
||||
fn prev_led_mode(&self) -> Result<(), dbus::Error> {
|
||||
self.method_call("org.asuslinux.Daemon", "PrevLedMode", ())
|
||||
}
|
||||
|
||||
fn led_mode(&self) -> Result<String, dbus::Error> {
|
||||
self.method_call("org.asuslinux.Daemon", "LedMode", ())
|
||||
.and_then(|r: (String,)| Ok(r.0))
|
||||
}
|
||||
|
||||
fn led_modes(&self) -> Result<String, dbus::Error> {
|
||||
self.method_call("org.asuslinux.Daemon", "LedModes", ())
|
||||
.and_then(|r: (String,)| Ok(r.0))
|
||||
}
|
||||
|
||||
fn led_brightness(&self) -> Result<i16, dbus::Error> {
|
||||
self.method_call("org.asuslinux.Daemon", "LedBrightness", ())
|
||||
.and_then(|r: (i16,)| Ok(r.0))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct OrgAsuslinuxDaemonNotifyLed {
|
||||
pub data: String,
|
||||
}
|
||||
|
||||
impl arg::AppendAll for OrgAsuslinuxDaemonNotifyLed {
|
||||
fn append(&self, i: &mut arg::IterAppend) {
|
||||
arg::RefArg::append(&self.data, i);
|
||||
}
|
||||
}
|
||||
|
||||
impl arg::ReadAll for OrgAsuslinuxDaemonNotifyLed {
|
||||
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
|
||||
Ok(OrgAsuslinuxDaemonNotifyLed { data: i.read()? })
|
||||
}
|
||||
}
|
||||
|
||||
impl dbus::message::SignalArgs for OrgAsuslinuxDaemonNotifyLed {
|
||||
const NAME: &'static str = "NotifyLed";
|
||||
const INTERFACE: &'static str = "org.asuslinux.Daemon";
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
// This code was autogenerated with `dbus-codegen-rust -s -d org.asuslinux.Daemon -p /org/asuslinux/Profile -m None -f org.asuslinux.Daemon -c blocking`, see https://github.com/diwic/dbus-rs
|
||||
use dbus;
|
||||
#[allow(unused_imports)]
|
||||
use dbus::arg;
|
||||
use dbus::blocking;
|
||||
|
||||
pub trait OrgAsuslinuxDaemon {
|
||||
fn set_profile(&self, profile: &str) -> Result<(), dbus::Error>;
|
||||
fn next_profile(&self) -> Result<(), dbus::Error>;
|
||||
fn active_profile_name(&self) -> Result<String, dbus::Error>;
|
||||
fn profile(&self) -> Result<String, dbus::Error>;
|
||||
fn profiles(&self) -> Result<String, dbus::Error>;
|
||||
}
|
||||
|
||||
impl<'a, T: blocking::BlockingSender, C: ::std::ops::Deref<Target = T>> OrgAsuslinuxDaemon
|
||||
for blocking::Proxy<'a, C>
|
||||
{
|
||||
fn set_profile(&self, profile: &str) -> Result<(), dbus::Error> {
|
||||
self.method_call("org.asuslinux.Daemon", "SetProfile", (profile,))
|
||||
}
|
||||
|
||||
fn next_profile(&self) -> Result<(), dbus::Error> {
|
||||
self.method_call("org.asuslinux.Daemon", "NextProfile", ())
|
||||
}
|
||||
|
||||
fn active_profile_name(&self) -> Result<String, dbus::Error> {
|
||||
self.method_call("org.asuslinux.Daemon", "ActiveProfileName", ())
|
||||
.and_then(|r: (String,)| Ok(r.0))
|
||||
}
|
||||
|
||||
fn profile(&self) -> Result<String, dbus::Error> {
|
||||
self.method_call("org.asuslinux.Daemon", "Profile", ())
|
||||
.and_then(|r: (String,)| Ok(r.0))
|
||||
}
|
||||
|
||||
fn profiles(&self) -> Result<String, dbus::Error> {
|
||||
self.method_call("org.asuslinux.Daemon", "Profiles", ())
|
||||
.and_then(|r: (String,)| Ok(r.0))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct OrgAsuslinuxDaemonNotifyProfile {
|
||||
pub profile: String,
|
||||
}
|
||||
|
||||
impl arg::AppendAll for OrgAsuslinuxDaemonNotifyProfile {
|
||||
fn append(&self, i: &mut arg::IterAppend) {
|
||||
arg::RefArg::append(&self.profile, i);
|
||||
}
|
||||
}
|
||||
|
||||
impl arg::ReadAll for OrgAsuslinuxDaemonNotifyProfile {
|
||||
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
|
||||
Ok(OrgAsuslinuxDaemonNotifyProfile { profile: i.read()? })
|
||||
}
|
||||
}
|
||||
|
||||
impl dbus::message::SignalArgs for OrgAsuslinuxDaemonNotifyProfile {
|
||||
const NAME: &'static str = "NotifyProfile";
|
||||
const INTERFACE: &'static str = "org.asuslinux.Daemon";
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
// This code was autogenerated with `dbus-codegen-rust -s -d org.asuslinux.Daemon -f org.asuslinux.Daemon -c blocking -p /org/asuslinux/RogBios -m None -o asus-nb/src/dbus_rogbios.rs`, see https://github.com/diwic/dbus-rs
|
||||
use dbus;
|
||||
#[allow(unused_imports)]
|
||||
use dbus::arg;
|
||||
use dbus::blocking;
|
||||
|
||||
pub trait OrgAsuslinuxDaemon {
|
||||
fn set_dedicated_graphic_mode(&self, dedicated: bool) -> Result<(), dbus::Error>;
|
||||
fn dedicated_graphic_mode(&self) -> Result<i16, dbus::Error>;
|
||||
fn set_post_boot_sound(&self, on: bool) -> Result<(), dbus::Error>;
|
||||
fn post_boot_sound(&self) -> Result<i16, dbus::Error>;
|
||||
}
|
||||
|
||||
impl<'a, T: blocking::BlockingSender, C: ::std::ops::Deref<Target = T>> OrgAsuslinuxDaemon
|
||||
for blocking::Proxy<'a, C>
|
||||
{
|
||||
fn set_dedicated_graphic_mode(&self, dedicated: bool) -> Result<(), dbus::Error> {
|
||||
self.method_call(
|
||||
"org.asuslinux.Daemon",
|
||||
"SetDedicatedGraphicMode",
|
||||
(dedicated,),
|
||||
)
|
||||
}
|
||||
|
||||
fn dedicated_graphic_mode(&self) -> Result<i16, dbus::Error> {
|
||||
self.method_call("org.asuslinux.Daemon", "DedicatedGraphicMode", ())
|
||||
.and_then(|r: (i16,)| Ok(r.0))
|
||||
}
|
||||
|
||||
fn set_post_boot_sound(&self, on: bool) -> Result<(), dbus::Error> {
|
||||
self.method_call("org.asuslinux.Daemon", "SetPostBootSound", (on,))
|
||||
}
|
||||
|
||||
fn post_boot_sound(&self) -> Result<i16, dbus::Error> {
|
||||
self.method_call("org.asuslinux.Daemon", "PostBootSound", ())
|
||||
.and_then(|r: (i16,)| Ok(r.0))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct OrgAsuslinuxDaemonNotifyDedicatedGraphicMode {
|
||||
pub dedicated: bool,
|
||||
}
|
||||
|
||||
impl arg::AppendAll for OrgAsuslinuxDaemonNotifyDedicatedGraphicMode {
|
||||
fn append(&self, i: &mut arg::IterAppend) {
|
||||
arg::RefArg::append(&self.dedicated, i);
|
||||
}
|
||||
}
|
||||
|
||||
impl arg::ReadAll for OrgAsuslinuxDaemonNotifyDedicatedGraphicMode {
|
||||
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
|
||||
Ok(OrgAsuslinuxDaemonNotifyDedicatedGraphicMode {
|
||||
dedicated: i.read()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl dbus::message::SignalArgs for OrgAsuslinuxDaemonNotifyDedicatedGraphicMode {
|
||||
const NAME: &'static str = "NotifyDedicatedGraphicMode";
|
||||
const INTERFACE: &'static str = "org.asuslinux.Daemon";
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct OrgAsuslinuxDaemonNotifyPostBootSound {
|
||||
pub dedicated: bool,
|
||||
}
|
||||
|
||||
impl arg::AppendAll for OrgAsuslinuxDaemonNotifyPostBootSound {
|
||||
fn append(&self, i: &mut arg::IterAppend) {
|
||||
arg::RefArg::append(&self.dedicated, i);
|
||||
}
|
||||
}
|
||||
|
||||
impl arg::ReadAll for OrgAsuslinuxDaemonNotifyPostBootSound {
|
||||
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
|
||||
Ok(OrgAsuslinuxDaemonNotifyPostBootSound {
|
||||
dedicated: i.read()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl dbus::message::SignalArgs for OrgAsuslinuxDaemonNotifyPostBootSound {
|
||||
const NAME: &'static str = "NotifyPostBootSound";
|
||||
const INTERFACE: &'static str = "org.asuslinux.Daemon";
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
// This code was autogenerated with `dbus-codegen-rust -s -d org.asuslinux.Daemon -f org.asuslinux.Daemon -c blocking -p /org/asuslinux/Supported -m None -o asus-nb/src/dbus_supported.rs`, see https://github.com/diwic/dbus-rs
|
||||
use dbus;
|
||||
#[allow(unused_imports)]
|
||||
use dbus::arg;
|
||||
use dbus::blocking;
|
||||
|
||||
pub trait OrgAsuslinuxDaemon {
|
||||
fn supported_functions(&self) -> Result<String, dbus::Error>;
|
||||
}
|
||||
|
||||
impl<'a, T: blocking::BlockingSender, C: ::std::ops::Deref<Target = T>> OrgAsuslinuxDaemon
|
||||
for blocking::Proxy<'a, C>
|
||||
{
|
||||
fn supported_functions(&self) -> Result<String, dbus::Error> {
|
||||
self.method_call("org.asuslinux.Daemon", "SupportedFunctions", ())
|
||||
.and_then(|r: (String,)| Ok(r.0))
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "asus-notify"
|
||||
version = "2.0.4"
|
||||
version = "3.0.0"
|
||||
authors = ["Luke D Jones <luke@ljones.dev>"]
|
||||
edition = "2018"
|
||||
|
||||
@@ -8,14 +8,11 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
# serialisation
|
||||
serde = "^1.0"
|
||||
serde_derive = "^1.0"
|
||||
serde_json = "^1.0"
|
||||
dbus = { version = "^0.8" }
|
||||
asus-nb = { path = "../asus-nb" }
|
||||
asus-nb-ctrl = { path = "../asus-nb-ctrl" }
|
||||
rog_dbus = { path = "../rog-dbus" }
|
||||
daemon = { path = "../daemon" }
|
||||
|
||||
[dependencies.notify-rust]
|
||||
version = "^4.0.0"
|
||||
version = "^4.0"
|
||||
default-features = false
|
||||
features = ["z"]
|
||||
@@ -1,29 +1,31 @@
|
||||
use asus_nb::core_dbus::CtrlSignals;
|
||||
use daemon::config::{Config, Profile};
|
||||
use dbus::blocking::Connection;
|
||||
use daemon::config::Profile;
|
||||
use notify_rust::{Hint, Notification, NotificationHandle};
|
||||
use rog_dbus::{DbusProxies, Signals};
|
||||
use std::error::Error;
|
||||
use std::time::Duration;
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("Version {}", env!("CARGO_PKG_VERSION"));
|
||||
println!("asus-notify version {}", env!("CARGO_PKG_VERSION"));
|
||||
println!(" daemon version {}", daemon::VERSION);
|
||||
println!(" rog-dbus version {}", rog_dbus::VERSION);
|
||||
|
||||
let mut cfg = Config::read_new()?;
|
||||
let mut last_profile = String::new();
|
||||
// let mut cfg = Config::read_new()?;
|
||||
// let mut last_profile = String::new();
|
||||
|
||||
let connection = Connection::new_system()?;
|
||||
let signals = CtrlSignals::new(&connection)?;
|
||||
let (proxies, conn) = DbusProxies::new()?;
|
||||
let signals = Signals::new(&proxies)?;
|
||||
|
||||
let mut last_profile_notif: Option<NotificationHandle> = None;
|
||||
let mut last_led_notif: Option<NotificationHandle> = None;
|
||||
let mut last_gfx_notif: Option<NotificationHandle> = None;
|
||||
let mut last_chrg_notif: Option<NotificationHandle> = None;
|
||||
|
||||
let recv = proxies.setup_recv(conn);
|
||||
loop {
|
||||
std::thread::sleep(Duration::from_millis(100));
|
||||
connection.process(std::time::Duration::from_millis(200))?;
|
||||
recv.next_signal().unwrap();
|
||||
|
||||
if let Ok(mut lock) = signals.gfx_vendor_signal.lock() {
|
||||
if let Ok(mut lock) = signals.gfx_vendor.lock() {
|
||||
if let Some(vendor) = lock.take() {
|
||||
if let Some(notif) = last_gfx_notif.take() {
|
||||
notif.close();
|
||||
@@ -33,17 +35,32 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(mut lock) = signals.charge_signal.lock() {
|
||||
if let Ok(mut lock) = signals.charge.lock() {
|
||||
if let Some(limit) = lock.take() {
|
||||
if let Some(notif) = last_chrg_notif.take() {
|
||||
notif.close();
|
||||
}
|
||||
let x = do_notif(&format!("Battery charge limit changed to {}", limit))?;
|
||||
last_led_notif = Some(x);
|
||||
last_chrg_notif = Some(x);
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(mut lock) = signals.ledmode_signal.lock() {
|
||||
if let Ok(mut lock) = signals.profile.lock() {
|
||||
if let Some(profile) = lock.take() {
|
||||
if let Some(notif) = last_profile_notif.take() {
|
||||
notif.close();
|
||||
}
|
||||
if let Ok(profile) = serde_json::from_str(&profile) {
|
||||
let profile: Profile = profile;
|
||||
if let Ok(name) = proxies.profile().active_profile_name() {
|
||||
let x = do_thermal_notif(&profile, &name)?;
|
||||
last_profile_notif = Some(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(mut lock) = signals.led_mode.lock() {
|
||||
if let Some(ledmode) = lock.take() {
|
||||
if let Some(notif) = last_led_notif.take() {
|
||||
notif.close();
|
||||
@@ -55,20 +72,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
last_led_notif = Some(x);
|
||||
}
|
||||
}
|
||||
|
||||
// We need to do the config read because of a limitation preventing
|
||||
// easy dbus notification from the profile controller
|
||||
cfg.read();
|
||||
if last_profile != cfg.active_profile {
|
||||
if let Some(notif) = last_profile_notif.take() {
|
||||
notif.close();
|
||||
}
|
||||
if let Some(profile) = cfg.power_profiles.get(&cfg.active_profile) {
|
||||
let x = do_thermal_notif(&profile, &cfg.active_profile)?;
|
||||
last_profile_notif = Some(x);
|
||||
last_profile = cfg.active_profile.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
20
asusctl/Cargo.toml
Normal file
@@ -0,0 +1,20 @@
|
||||
[package]
|
||||
name = "asusctl"
|
||||
version = "3.1.0"
|
||||
authors = ["Luke D Jones <luke@ljones.dev>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
# serialisation
|
||||
serde_json = "^1.0"
|
||||
rog_dbus = { path = "../rog-dbus" }
|
||||
rog_types = { path = "../rog-types" }
|
||||
gumdrop = "^0.8"
|
||||
yansi-term = "^0.1"
|
||||
|
||||
|
||||
[dev-dependencies]
|
||||
tinybmp = "^0.2.3"
|
||||
rog_dbus = { path = "../rog-dbus" }
|
||||
@@ -1,9 +1,9 @@
|
||||
use asus_nb::anime_dbus::AniMeDbusWriter;
|
||||
use asus_nb::anime_matrix::{AniMeMatrix, AniMePacketType, HEIGHT, WIDTH};
|
||||
use rog_dbus::AuraDbusClient;
|
||||
use rog_types::anime_matrix::{AniMeImageBuffer, AniMePacketType, HEIGHT, WIDTH};
|
||||
use tinybmp::{Bmp, Pixel};
|
||||
|
||||
fn main() {
|
||||
let mut writer = AniMeDbusWriter::new().unwrap();
|
||||
let (client, _) = AuraDbusClient::new().unwrap();
|
||||
|
||||
let bmp =
|
||||
Bmp::from_slice(include_bytes!("non-skewed_r.bmp")).expect("Failed to parse BMP image");
|
||||
@@ -11,7 +11,7 @@ fn main() {
|
||||
//assert_eq!(pixels.len(), 56 * 56);
|
||||
|
||||
// Try an outline, top and right
|
||||
let mut matrix = AniMeMatrix::new();
|
||||
let mut matrix = AniMeImageBuffer::new();
|
||||
|
||||
// Aligned left
|
||||
for (i, px) in pixels.iter().enumerate() {
|
||||
@@ -38,5 +38,5 @@ fn main() {
|
||||
// println!("{:?}", matrix[0].to_vec());
|
||||
// println!("{:?}", matrix[1].to_vec());
|
||||
|
||||
writer.write_image(&mut matrix).unwrap();
|
||||
//client.proxies().anime().set_brightness(&mut matrix).unwrap();
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
use asus_nb::{
|
||||
core_dbus::AuraDbusClient,
|
||||
fancy::{GX502Layout, Key, KeyColourArray, KeyLayout},
|
||||
};
|
||||
use rog_dbus::AuraDbusClient;
|
||||
use rog_types::fancy::{GX502Layout, Key, KeyColourArray, KeyLayout};
|
||||
use std::collections::LinkedList;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -54,7 +52,7 @@ impl Ball {
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut writer = AuraDbusClient::new()?;
|
||||
let (dbus, _) = AuraDbusClient::new()?;
|
||||
|
||||
let mut colours = KeyColourArray::new();
|
||||
|
||||
@@ -62,7 +60,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
let mut balls = [Ball::new(2, 1, 12), Ball::new(4, 6, 12)];
|
||||
|
||||
writer.init_effect()?;
|
||||
dbus.proxies().led().init_effect()?;
|
||||
|
||||
let rows = layout.get_rows();
|
||||
loop {
|
||||
@@ -89,10 +87,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
*c.2 = 255;
|
||||
};
|
||||
}
|
||||
dbus.proxies().led().set_per_key(&colours)?;
|
||||
|
||||
writer.write_colour_block(&colours)?;
|
||||
|
||||
// can change 100 times per second, so need to slow it down
|
||||
std::thread::sleep(std::time::Duration::from_millis(30));
|
||||
std::thread::sleep(std::time::Duration::from_millis(10));
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,12 @@
|
||||
use asus_nb::{
|
||||
core_dbus::AuraDbusClient,
|
||||
fancy::{GX502Layout, KeyColourArray, KeyLayout},
|
||||
};
|
||||
use rog_dbus::AuraDbusClient;
|
||||
use rog_types::fancy::{GX502Layout, KeyColourArray, KeyLayout};
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut writer = AuraDbusClient::new()?;
|
||||
let (dbus, _) = AuraDbusClient::new()?;
|
||||
|
||||
let layout = GX502Layout::default();
|
||||
|
||||
writer.init_effect()?;
|
||||
dbus.proxies().led().init_effect()?;
|
||||
let rows = layout.get_rows();
|
||||
|
||||
let mut column = 0;
|
||||
@@ -25,7 +23,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
column += 1;
|
||||
}
|
||||
|
||||
writer.write_colour_block(&key_colours)?;
|
||||
std::thread::sleep(std::time::Duration::from_millis(30));
|
||||
dbus.proxies().led().set_per_key(&key_colours)?;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,13 @@
|
||||
use asus_nb::{
|
||||
core_dbus::AuraDbusClient,
|
||||
fancy::{GX502Layout, Key, KeyColourArray, KeyLayout},
|
||||
};
|
||||
use rog_dbus::AuraDbusClient;
|
||||
use rog_types::fancy::{GX502Layout, Key, KeyColourArray, KeyLayout};
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut writer = AuraDbusClient::new()?;
|
||||
let (dbus, _) = AuraDbusClient::new()?;
|
||||
|
||||
let mut key_colours = KeyColourArray::new();
|
||||
let layout = GX502Layout::default();
|
||||
|
||||
writer.init_effect()?;
|
||||
dbus.proxies().led().init_effect()?;
|
||||
let rows = layout.get_rows();
|
||||
loop {
|
||||
for (r, row) in rows.iter().enumerate() {
|
||||
@@ -48,7 +46,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
*key_colours.key(Key::S).unwrap().0 = 255;
|
||||
*key_colours.key(Key::D).unwrap().0 = 255;
|
||||
|
||||
writer.write_colour_block(&key_colours)?;
|
||||
dbus.proxies().led().set_per_key(&key_colours)?;
|
||||
std::thread::sleep(std::time::Duration::from_millis(100));
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
@@ -1,14 +1,12 @@
|
||||
use asus_nb::{
|
||||
core_dbus::AuraDbusClient,
|
||||
fancy::{Key, KeyColourArray},
|
||||
};
|
||||
use rog_dbus::AuraDbusClient;
|
||||
use rog_types::fancy::{Key, KeyColourArray};
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut writer = AuraDbusClient::new()?;
|
||||
let (dbus, _) = AuraDbusClient::new()?;
|
||||
|
||||
let mut key_colours = KeyColourArray::new();
|
||||
|
||||
writer.init_effect()?;
|
||||
dbus.proxies().led().init_effect()?;
|
||||
loop {
|
||||
let count = 49;
|
||||
for _ in 0..count {
|
||||
@@ -18,7 +16,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
*key_colours.key(Key::N).unwrap().0 += 5;
|
||||
*key_colours.key(Key::U).unwrap().0 += 5;
|
||||
*key_colours.key(Key::X).unwrap().0 += 5;
|
||||
writer.write_colour_block(&key_colours)?;
|
||||
dbus.proxies().led().set_per_key(&key_colours)?;
|
||||
}
|
||||
for _ in 0..count {
|
||||
*key_colours.key(Key::ROG).unwrap().0 -= 5;
|
||||
@@ -27,7 +25,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
*key_colours.key(Key::N).unwrap().0 -= 5;
|
||||
*key_colours.key(Key::U).unwrap().0 -= 5;
|
||||
*key_colours.key(Key::X).unwrap().0 -= 5;
|
||||
writer.write_colour_block(&key_colours)?;
|
||||
dbus.proxies().led().set_per_key(&key_colours)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,13 @@
|
||||
use asus_nb::{
|
||||
core_dbus::AuraDbusClient,
|
||||
fancy::{GX502Layout, KeyColourArray, KeyLayout},
|
||||
};
|
||||
use rog_dbus::AuraDbusClient;
|
||||
use rog_types::fancy::{GX502Layout, KeyColourArray, KeyLayout};
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut writer = AuraDbusClient::new()?;
|
||||
let (dbus, _) = AuraDbusClient::new()?;
|
||||
|
||||
let mut key_colours = KeyColourArray::new();
|
||||
let layout = GX502Layout::default();
|
||||
|
||||
writer.init_effect()?;
|
||||
dbus.proxies().led().init_effect()?;
|
||||
let rows = layout.get_rows();
|
||||
|
||||
let mut fade = 50;
|
||||
@@ -23,7 +21,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
}
|
||||
}
|
||||
|
||||
writer.write_colour_block(&key_colours)?;
|
||||
dbus.proxies().led().set_per_key(&key_colours)?;
|
||||
|
||||
if flip {
|
||||
if fade > 1 {
|
||||
|
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 7.6 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 7.6 KiB |
@@ -1,13 +1,12 @@
|
||||
use asus_nb::{
|
||||
anime_dbus::AniMeDbusWriter,
|
||||
cli_options::{AniMeActions, AniMeStatusValue, LedBrightness, SetAuraBuiltin},
|
||||
core_dbus::AuraDbusClient,
|
||||
profile::{ProfileCommand, ProfileEvent},
|
||||
};
|
||||
use daemon::{ctrl_fan_cpu::FanLevel, ctrl_gfx::vendors::GfxVendors};
|
||||
use gumdrop::{Opt, Options};
|
||||
use log::LevelFilter;
|
||||
use std::{env::args, io::Write, process::Command};
|
||||
use rog_dbus::AuraDbusClient;
|
||||
use rog_types::{
|
||||
anime_matrix::{AniMeDataBuffer, FULL_PANE_LEN},
|
||||
cli_options::{AniMeActions, AniMeStatusValue, LedBrightness, SetAuraBuiltin},
|
||||
gfx_vendors::GfxVendors,
|
||||
profile::{FanLevel, ProfileCommand, ProfileEvent},
|
||||
};
|
||||
use std::env::args;
|
||||
use yansi_term::Colour::Green;
|
||||
use yansi_term::Colour::Red;
|
||||
|
||||
@@ -21,8 +20,11 @@ struct CLIStart {
|
||||
show_supported: bool,
|
||||
#[options(meta = "", help = "<off, low, med, high>")]
|
||||
kbd_bright: Option<LedBrightness>,
|
||||
#[options(meta = "", help = "<silent, normal, boost>")]
|
||||
pwr_profile: Option<FanLevel>,
|
||||
#[options(
|
||||
meta = "",
|
||||
help = "<silent, normal, boost>, set fan mode independent of profile"
|
||||
)]
|
||||
fan_mode: Option<FanLevel>,
|
||||
#[options(meta = "", help = "<20-100>")]
|
||||
chg_limit: Option<u8>,
|
||||
#[options(command)]
|
||||
@@ -102,13 +104,6 @@ struct BiosCommand {
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut logger = env_logger::Builder::new();
|
||||
logger
|
||||
.target(env_logger::Target::Stdout)
|
||||
.format(|buf, record| writeln!(buf, "{}: {}", record.level(), record.args()))
|
||||
.filter(None, LevelFilter::Info)
|
||||
.init();
|
||||
|
||||
let mut args: Vec<String> = args().collect();
|
||||
args.remove(0);
|
||||
|
||||
@@ -137,11 +132,12 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
}
|
||||
|
||||
if parsed.version {
|
||||
println!("Version: {}", daemon::VERSION);
|
||||
println!(" asusctl version {}", env!("CARGO_PKG_VERSION"));
|
||||
println!(" rog-dbus version {}", rog_dbus::VERSION);
|
||||
println!("rog-types version {}", rog_types::VERSION);
|
||||
}
|
||||
|
||||
let dbus_client = AuraDbusClient::new()?;
|
||||
let anime_dbus_client = AniMeDbusWriter::new()?;
|
||||
let (dbus, _) = AuraDbusClient::new()?;
|
||||
|
||||
match parsed.command {
|
||||
Some(CliCommand::LedMode(mode)) => {
|
||||
@@ -150,16 +146,17 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
if let Some(lst) = mode.self_command_list() {
|
||||
println!("\n{}", lst);
|
||||
}
|
||||
println!("\nHelp can also be requested on modes, e.g: static --help");
|
||||
}
|
||||
if mode.next_mode && mode.prev_mode {
|
||||
println!("Please specify either next or previous")
|
||||
}
|
||||
if mode.next_mode {
|
||||
dbus_client.next_keyboard_led_mode()?;
|
||||
dbus.proxies().led().next_led_mode()?;
|
||||
} else if mode.prev_mode {
|
||||
dbus_client.prev_keyboard_led_mode()?;
|
||||
dbus.proxies().led().prev_led_mode()?;
|
||||
} else if let Some(command) = mode.command {
|
||||
dbus_client.write_builtin_mode(&command.into())?
|
||||
dbus.proxies().led().set_led_mode(&command.into())?
|
||||
}
|
||||
}
|
||||
Some(CliCommand::Profile(cmd)) => {
|
||||
@@ -179,12 +176,14 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
}
|
||||
}
|
||||
if cmd.next {
|
||||
dbus_client.next_fan_profile()?;
|
||||
dbus.proxies().profile().next_fan()?;
|
||||
} else {
|
||||
dbus_client.write_profile_command(&ProfileEvent::Cli(cmd))?
|
||||
dbus.proxies()
|
||||
.profile()
|
||||
.write_command(&ProfileEvent::Cli(cmd))?
|
||||
}
|
||||
}
|
||||
Some(CliCommand::Graphics(cmd)) => do_gfx(cmd, &dbus_client)?,
|
||||
Some(CliCommand::Graphics(cmd)) => do_gfx(cmd, &dbus)?,
|
||||
Some(CliCommand::AniMe(cmd)) => {
|
||||
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());
|
||||
@@ -193,16 +192,17 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
}
|
||||
}
|
||||
if let Some(anime_turn) = cmd.turn {
|
||||
anime_dbus_client.turn_on_off(anime_turn.into())?
|
||||
dbus.proxies().anime().toggle_on(anime_turn.into())?
|
||||
}
|
||||
if let Some(anime_boot) = cmd.boot {
|
||||
anime_dbus_client.turn_boot_on_off(anime_boot.into())?
|
||||
dbus.proxies().anime().toggle_boot_on(anime_boot.into())?
|
||||
}
|
||||
if let Some(action) = cmd.command {
|
||||
match action {
|
||||
AniMeActions::Leds(anime_leds) => {
|
||||
let led_brightness = anime_leds.led_brightness();
|
||||
anime_dbus_client.set_leds_brightness(led_brightness)?;
|
||||
let mut data = AniMeDataBuffer::new();
|
||||
data.set([anime_leds.led_brightness(); FULL_PANE_LEN]);
|
||||
dbus.proxies().anime().write_direct(data)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -221,10 +221,10 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
}
|
||||
|
||||
if let Some(opt) = cmd.post_sound_set {
|
||||
dbus_client.set_bios_post_sound(opt)?;
|
||||
dbus.proxies().rog_bios().set_post_sound(opt)?;
|
||||
}
|
||||
if cmd.post_sound_get {
|
||||
let res = if dbus_client.get_bios_post_sound()? == 1 {
|
||||
let res = if dbus.proxies().rog_bios().get_post_sound()? == 1 {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
@@ -232,21 +232,22 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("Bios POST sound on: {}", res);
|
||||
}
|
||||
if let Some(opt) = cmd.dedicated_gfx_set {
|
||||
dbus_client.set_bios_dedicated_gfx(opt)?;
|
||||
dbus.proxies().rog_bios().set_dedicated_gfx(opt)?;
|
||||
}
|
||||
if cmd.dedicated_gfx_get {
|
||||
let res = if dbus_client.get_bios_dedicated_gfx()? == 1 {
|
||||
let res = if dbus.proxies().rog_bios().get_dedicated_gfx()? == 1 {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
println!("Bios dedicated GPU on: {}", res);
|
||||
println!("You must reboot your system to activate dedicated Nvidia mode");
|
||||
}
|
||||
}
|
||||
None => {
|
||||
if (!parsed.show_supported
|
||||
&& parsed.kbd_bright.is_none()
|
||||
&& parsed.pwr_profile.is_none()
|
||||
&& parsed.fan_mode.is_none()
|
||||
&& parsed.chg_limit.is_none())
|
||||
|| parsed.help
|
||||
{
|
||||
@@ -260,23 +261,23 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
if let Some(brightness) = parsed.kbd_bright {
|
||||
match brightness.level() {
|
||||
None => {
|
||||
let level = dbus_client.get_led_brightness()?;
|
||||
let level = dbus.proxies().led().get_led_brightness()?;
|
||||
println!("Current keyboard led brightness: {}", level.to_string());
|
||||
}
|
||||
Some(level) => dbus_client.write_brightness(level)?,
|
||||
Some(level) => dbus.proxies().led().set_brightness(level)?,
|
||||
}
|
||||
}
|
||||
|
||||
if parsed.show_supported {
|
||||
let dat = dbus_client.get_supported_functions()?;
|
||||
let dat = dbus.proxies().supported().get_supported_functions()?;
|
||||
println!("Supported laptop functions:\n{}", dat.to_string());
|
||||
}
|
||||
|
||||
if let Some(fan_level) = parsed.pwr_profile {
|
||||
dbus_client.write_fan_mode(fan_level.into())?;
|
||||
if let Some(fan_level) = parsed.fan_mode {
|
||||
dbus.proxies().profile().write_fan_mode(fan_level.into())?;
|
||||
}
|
||||
if let Some(chg_limit) = parsed.chg_limit {
|
||||
dbus_client.write_charge_limit(chg_limit)?;
|
||||
dbus.proxies().charge().write_limit(chg_limit)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -286,49 +287,27 @@ fn do_gfx(
|
||||
dbus_client: &AuraDbusClient,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
if let Some(mode) = command.mode {
|
||||
println!("Updating settings, please wait...");
|
||||
println!("Changing graphics modes...");
|
||||
println!("If this takes longer than 30s, ctrl+c then check `journalctl -b -u asusd`");
|
||||
|
||||
dbus_client.write_gfx_mode(<&str>::from(&mode).into())?;
|
||||
let res = dbus_client.wait_gfx_changed()?;
|
||||
match res.as_str() {
|
||||
"reboot" => {
|
||||
println!(
|
||||
"{}",
|
||||
Green.paint("\nGraphics vendor mode changed successfully\n"),
|
||||
);
|
||||
do_gfx_action(
|
||||
command.force,
|
||||
Command::new("systemctl").arg("reboot").arg("-i"),
|
||||
"Reboot Linux PC",
|
||||
"Please reboot when ready",
|
||||
)?;
|
||||
}
|
||||
"restartx" => {
|
||||
println!(
|
||||
"{}",
|
||||
Green.paint("\nGraphics vendor mode changed successfully\n")
|
||||
);
|
||||
do_gfx_action(
|
||||
command.force,
|
||||
Command::new("systemctl")
|
||||
.arg("restart")
|
||||
.arg("display-manager.service"),
|
||||
"Restart display-manager server",
|
||||
"Please restart display-manager when ready",
|
||||
)?;
|
||||
std::process::exit(1)
|
||||
}
|
||||
_ => std::process::exit(-1),
|
||||
if do_gfx_action(
|
||||
command.force,
|
||||
"This will restart your display-manager. Please save all work!",
|
||||
"Setting graphics mode...",
|
||||
) {
|
||||
dbus_client.proxies().gfx().gfx_write_mode(mode.into())?;
|
||||
let res = dbus_client.gfx_wait_changed()?;
|
||||
println!("{}", res);
|
||||
std::process::exit(1)
|
||||
}
|
||||
std::process::exit(-1)
|
||||
}
|
||||
if command.get {
|
||||
let res = dbus_client.get_gfx_mode()?;
|
||||
let res = dbus_client.proxies().gfx().gfx_get_mode()?;
|
||||
println!("Current graphics mode: {}", res);
|
||||
}
|
||||
if command.pow {
|
||||
let res = dbus_client.get_gfx_pwr()?;
|
||||
let res = dbus_client.proxies().gfx().gfx_get_pwr()?;
|
||||
if res.contains("active") {
|
||||
println!("Current power status: {}", Red.paint(&format!("{}", res)));
|
||||
} else {
|
||||
@@ -338,34 +317,17 @@ fn do_gfx(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn do_gfx_action(
|
||||
no_confirm: bool,
|
||||
command: &mut Command,
|
||||
ask_msg: &str,
|
||||
cancel_msg: &str,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("{}? y/n", ask_msg);
|
||||
fn do_gfx_action(no_confirm: bool, ask_msg: &str, ok_msg: &str) -> bool {
|
||||
println!("{}", Red.paint(&format!("{} Continue?", ask_msg)));
|
||||
|
||||
let mut buf = String::new();
|
||||
if no_confirm {
|
||||
let status = command.status()?;
|
||||
|
||||
if !status.success() {
|
||||
println!("systemctl: returned with {}", status);
|
||||
}
|
||||
}
|
||||
|
||||
std::io::stdin().read_line(&mut buf).expect("Input failed");
|
||||
let input = buf.chars().next().unwrap() as char;
|
||||
|
||||
if input == 'Y' || input == 'y' || no_confirm {
|
||||
let status = command.status()?;
|
||||
|
||||
if !status.success() {
|
||||
println!("systemctl: returned with {}", status);
|
||||
}
|
||||
} else {
|
||||
println!("{}", Red.paint(&format!("{}", cancel_msg)));
|
||||
println!("{}", Green.paint(&format!("{}", ok_msg)));
|
||||
return true;
|
||||
}
|
||||
Ok(())
|
||||
false
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "asus-nb-ctrl"
|
||||
version = "2.2.0"
|
||||
name = "daemon"
|
||||
version = "3.1.3"
|
||||
license = "MPL-2.0"
|
||||
readme = "README.md"
|
||||
authors = ["Luke <luke@ljones.dev>"]
|
||||
@@ -13,37 +13,31 @@ edition = "2018"
|
||||
name = "daemon"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "asusctl"
|
||||
path = "src/main.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "asusd"
|
||||
path = "src/daemon.rs"
|
||||
|
||||
[dependencies]
|
||||
asus-nb = { path = "../asus-nb" }
|
||||
rusb = "^0.6.0"
|
||||
udev = "^0.4.0"
|
||||
rog_types = { path = "../rog-types" }
|
||||
rog_dbus = { path = "../rog-dbus" }
|
||||
rusb = "^0.7"
|
||||
udev = "^0.6"
|
||||
|
||||
# cli and logging
|
||||
gumdrop = "^0.8.0"
|
||||
log = "^0.4.8"
|
||||
env_logger = "^0.7.1"
|
||||
log = "^0.4"
|
||||
env_logger = "^0.8"
|
||||
|
||||
zbus = "^1.8.0"
|
||||
zvariant = "^2.4.0"
|
||||
zbus = "^1.8"
|
||||
zvariant = "^2.4"
|
||||
|
||||
# serialisation
|
||||
serde = "^1.0"
|
||||
serde_derive = "^1.0"
|
||||
serde_json = "^1.0"
|
||||
toml = "0.4.6"
|
||||
toml = "^0.5"
|
||||
|
||||
# Device control
|
||||
sysfs-class = "^0.1.2" # used for backlight control and baord ID
|
||||
rog_fan_curve = { version = "0.1.5", features = ["serde"] }
|
||||
rog_fan_curve = { version = "0.1", features = ["serde"] }
|
||||
# cpu power management
|
||||
intel-pstate = "^0.2.1"
|
||||
|
||||
yansi-term = "^0.1"
|
||||
intel-pstate = "^0.2"
|
||||
@@ -1,55 +1,24 @@
|
||||
use asus_nb::aura_modes::AuraModes;
|
||||
use log::{error, info, warn};
|
||||
use rog_fan_curve::Curve;
|
||||
use rog_types::{aura_modes::AuraModes, gfx_vendors::GfxVendors};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::collections::BTreeMap;
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::io::{Read, Write};
|
||||
|
||||
use crate::config_old::*;
|
||||
use crate::VERSION;
|
||||
|
||||
pub static CONFIG_PATH: &str = "/etc/asusd/asusd.conf";
|
||||
|
||||
/// for parsing old v2.1.2 config
|
||||
#[derive(Deserialize)]
|
||||
struct ConfigV212 {
|
||||
gfx_managed: bool,
|
||||
active_profile: String,
|
||||
toggle_profiles: Vec<String>,
|
||||
// TODO: remove power_profile
|
||||
power_profile: u8,
|
||||
bat_charge_limit: u8,
|
||||
kbd_led_brightness: u8,
|
||||
kbd_backlight_mode: u8,
|
||||
kbd_backlight_modes: Vec<AuraModes>,
|
||||
power_profiles: BTreeMap<String, Profile>,
|
||||
}
|
||||
|
||||
impl ConfigV212 {
|
||||
fn into_current(self) -> Config {
|
||||
Config {
|
||||
gfx_managed: self.gfx_managed,
|
||||
gfx_nv_mode_is_dedicated: true,
|
||||
active_profile: self.active_profile,
|
||||
toggle_profiles: self.toggle_profiles,
|
||||
power_profile: self.power_profile,
|
||||
bat_charge_limit: self.bat_charge_limit,
|
||||
kbd_led_brightness: self.kbd_led_brightness,
|
||||
kbd_backlight_mode: self.kbd_backlight_mode,
|
||||
kbd_backlight_modes: self.kbd_backlight_modes,
|
||||
power_profiles: self.power_profiles,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Deserialize, Serialize)]
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct Config {
|
||||
pub gfx_mode: GfxVendors,
|
||||
pub gfx_managed: bool,
|
||||
pub gfx_nv_mode_is_dedicated: bool,
|
||||
pub active_profile: String,
|
||||
pub toggle_profiles: Vec<String>,
|
||||
// TODO: remove power_profile
|
||||
pub power_profile: u8,
|
||||
#[serde(skip)]
|
||||
pub curr_fan_mode: u8,
|
||||
pub bat_charge_limit: u8,
|
||||
pub kbd_led_brightness: u8,
|
||||
pub kbd_backlight_mode: u8,
|
||||
@@ -57,6 +26,28 @@ pub struct Config {
|
||||
pub power_profiles: BTreeMap<String, Profile>,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
let mut pwr = BTreeMap::new();
|
||||
pwr.insert("normal".into(), Profile::new(0, 100, true, 0, None));
|
||||
pwr.insert("boost".into(), Profile::new(0, 100, true, 1, None));
|
||||
pwr.insert("silent".into(), Profile::new(0, 100, true, 2, None));
|
||||
|
||||
Config {
|
||||
gfx_mode: GfxVendors::Hybrid,
|
||||
gfx_managed: true,
|
||||
active_profile: "normal".into(),
|
||||
toggle_profiles: vec!["normal".into(), "boost".into(), "silent".into()],
|
||||
curr_fan_mode: 0,
|
||||
bat_charge_limit: 100,
|
||||
kbd_led_brightness: 1,
|
||||
kbd_backlight_mode: 0,
|
||||
kbd_backlight_modes: Vec::new(),
|
||||
power_profiles: pwr,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Config {
|
||||
/// `load` will attempt to read the config, and panic if the dir is missing
|
||||
pub fn load(supported_led_modes: &[u8]) -> Self {
|
||||
@@ -76,6 +67,16 @@ impl Config {
|
||||
} else {
|
||||
if let Ok(data) = serde_json::from_str(&buf) {
|
||||
return data;
|
||||
} 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();
|
||||
@@ -92,36 +93,11 @@ impl Config {
|
||||
fn create_default(file: &mut File, supported_led_modes: &[u8]) -> Self {
|
||||
// create a default config here
|
||||
let mut config = Config::default();
|
||||
config.gfx_managed = true;
|
||||
config.gfx_nv_mode_is_dedicated = true;
|
||||
|
||||
config.bat_charge_limit = 100;
|
||||
config.kbd_backlight_mode = 0;
|
||||
config.kbd_led_brightness = 1;
|
||||
|
||||
for n in supported_led_modes {
|
||||
config.kbd_backlight_modes.push(AuraModes::from(*n))
|
||||
}
|
||||
|
||||
let mut profile = Profile::default();
|
||||
profile.fan_preset = 0;
|
||||
profile.turbo = true;
|
||||
config.power_profiles.insert("normal".into(), profile);
|
||||
|
||||
let mut profile = Profile::default();
|
||||
profile.fan_preset = 1;
|
||||
profile.turbo = true;
|
||||
config.power_profiles.insert("boost".into(), profile);
|
||||
|
||||
let mut profile = Profile::default();
|
||||
profile.fan_preset = 2;
|
||||
config.power_profiles.insert("silent".into(), profile);
|
||||
|
||||
config.toggle_profiles.push("normal".into());
|
||||
config.toggle_profiles.push("boost".into());
|
||||
config.toggle_profiles.push("silent".into());
|
||||
config.active_profile = "normal".into();
|
||||
|
||||
// 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())
|
||||
@@ -208,3 +184,21 @@ impl Default for Profile {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
100
daemon/src/config_old.rs
Normal file
@@ -0,0 +1,100 @@
|
||||
use rog_types::{aura_modes::AuraModes, gfx_vendors::GfxVendors};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use crate::config::{Config, Profile};
|
||||
|
||||
/// for parsing old v2.1.2 config
|
||||
#[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<AuraModes>,
|
||||
}
|
||||
|
||||
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,
|
||||
kbd_led_brightness: self.kbd_led_brightness,
|
||||
kbd_backlight_mode: self.kbd_backlight_mode,
|
||||
kbd_backlight_modes: self.kbd_backlight_modes,
|
||||
power_profiles: self.power_profiles,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// for parsing old v2.2.2 config
|
||||
#[derive(Deserialize)]
|
||||
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<AuraModes>,
|
||||
}
|
||||
|
||||
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,
|
||||
kbd_led_brightness: self.kbd_led_brightness,
|
||||
kbd_backlight_mode: self.kbd_backlight_mode,
|
||||
kbd_backlight_modes: self.kbd_backlight_modes,
|
||||
power_profiles: self.power_profiles,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
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<AuraModes>,
|
||||
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,
|
||||
kbd_led_brightness: self.kbd_led_brightness,
|
||||
kbd_backlight_mode: self.kbd_backlight_mode,
|
||||
kbd_backlight_modes: self.kbd_backlight_modes,
|
||||
power_profiles: self.power_profiles,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,8 +13,13 @@ const APPLY: u8 = 0xc4;
|
||||
// The next byte can be 0x03 for "on" and 0x00 for "off"
|
||||
const ON_OFF: u8 = 0x04;
|
||||
|
||||
use asus_nb::error::AuraError;
|
||||
use log::{error, info, warn};
|
||||
use rog_types::{
|
||||
anime_matrix::{
|
||||
AniMeDataBuffer, AniMeImageBuffer, AniMePacketType, ANIME_PANE1_PREFIX, ANIME_PANE2_PREFIX,
|
||||
},
|
||||
error::AuraError,
|
||||
};
|
||||
use rusb::{Device, DeviceHandle};
|
||||
use std::convert::TryInto;
|
||||
use std::error::Error;
|
||||
@@ -35,28 +40,21 @@ impl GetSupported for CtrlAnimeDisplay {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
pub enum AnimatrixCommand {
|
||||
Apply,
|
||||
SetBoot(bool),
|
||||
Write(Vec<u8>),
|
||||
WriteImage(Vec<Vec<u8>>),
|
||||
//ReloadLast,
|
||||
}
|
||||
|
||||
pub struct CtrlAnimeDisplay {
|
||||
handle: DeviceHandle<rusb::GlobalContext>,
|
||||
initialised: bool,
|
||||
}
|
||||
|
||||
//AnimatrixWrite
|
||||
pub trait Dbus {
|
||||
fn set_anime(&mut self, input: Vec<Vec<u8>>);
|
||||
/// Write an image 34x56 pixels. Each pixel is 0-255 greyscale.
|
||||
fn write_image(&self, input: AniMeImageBuffer);
|
||||
|
||||
fn set_on_off(&mut self, status: bool);
|
||||
/// Write a direct stream of data
|
||||
fn write_direct(&self, input: AniMeDataBuffer);
|
||||
|
||||
fn set_boot_on_off(&mut self, status: bool);
|
||||
fn set_on_off(&self, status: bool);
|
||||
|
||||
fn set_boot_on_off(&self, status: bool);
|
||||
}
|
||||
|
||||
impl crate::ZbusAdd for CtrlAnimeDisplay {
|
||||
@@ -73,41 +71,44 @@ impl crate::ZbusAdd for CtrlAnimeDisplay {
|
||||
|
||||
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
||||
impl Dbus for CtrlAnimeDisplay {
|
||||
fn set_anime(&mut self, input: Vec<Vec<u8>>) {
|
||||
self.do_command(AnimatrixCommand::WriteImage(input))
|
||||
/// 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"));
|
||||
}
|
||||
|
||||
fn set_on_off(&mut self, status: bool) {
|
||||
let mut flush: Vec<u8> = vec![0; PACKET_SIZE];
|
||||
flush[0] = DEV_PAGE;
|
||||
flush[1] = WRITE;
|
||||
flush[2] = ON_OFF;
|
||||
|
||||
let status_str;
|
||||
if status {
|
||||
flush[3] = 0x03;
|
||||
status_str = "on";
|
||||
} else {
|
||||
flush[3] = 0x00;
|
||||
status_str = "off";
|
||||
}
|
||||
|
||||
self.do_command(AnimatrixCommand::Write(flush)).map_or_else(
|
||||
|err| warn!("{}", err),
|
||||
|()| info!("Turning {} the AniMe", status_str),
|
||||
);
|
||||
/// 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_boot_on_off(&mut self, status: bool) {
|
||||
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_command(AnimatrixCommand::SetBoot(status))
|
||||
.and_then(|()| self.do_command(AnimatrixCommand::Apply))
|
||||
.map_or_else(
|
||||
|err| warn!("{}", err),
|
||||
|()| info!("Turning {} the AniMe at boot/shutdown", status_str),
|
||||
);
|
||||
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),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,10 +132,10 @@ impl CtrlAnimeDisplay {
|
||||
})?;
|
||||
|
||||
info!("Device has an AniMe Matrix display");
|
||||
Ok(CtrlAnimeDisplay {
|
||||
handle: device,
|
||||
initialised: false,
|
||||
})
|
||||
let ctrl = CtrlAnimeDisplay { handle: device };
|
||||
ctrl.do_initialization()?;
|
||||
|
||||
Ok(ctrl)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -148,25 +149,9 @@ impl CtrlAnimeDisplay {
|
||||
Err(rusb::Error::NoDevice)
|
||||
}
|
||||
|
||||
pub fn do_command(&mut self, command: AnimatrixCommand) -> Result<(), AuraError> {
|
||||
if !self.initialised {
|
||||
self.do_initialization()?
|
||||
}
|
||||
|
||||
match command {
|
||||
AnimatrixCommand::Apply => self.do_apply()?,
|
||||
//AnimatrixCommand::Set => self.do_set_boot()?,
|
||||
AnimatrixCommand::SetBoot(status) => self.do_set_boot(status)?,
|
||||
AnimatrixCommand::Write(bytes) => self.write_bytes(&bytes)?,
|
||||
AnimatrixCommand::WriteImage(effect) => self.write_image(effect)?,
|
||||
//AnimatrixCommand::ReloadLast => self.reload_last_builtin(&config).await?,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Should only be used if the bytes you are writing are verified correct
|
||||
#[inline]
|
||||
fn write_bytes(&self, message: &[u8]) -> Result<(), AuraError> {
|
||||
fn write_bytes(&self, message: &[u8]) {
|
||||
match self.handle.write_control(
|
||||
0x21, // request_type
|
||||
0x09, // request
|
||||
@@ -181,12 +166,23 @@ impl CtrlAnimeDisplay {
|
||||
_ => error!("Failed to write to led interrupt: {}", err),
|
||||
},
|
||||
}
|
||||
}
|
||||
#[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() {
|
||||
self.write_bytes(row);
|
||||
}
|
||||
self.do_flush()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Write an Animatrix image
|
||||
///
|
||||
/// The expected input here is *two* Vectors, 640 bytes in length. The two vectors
|
||||
/// The expected USB input here is *two* Vectors, 640 bytes in length. The two vectors
|
||||
/// are each one half of the full image write.
|
||||
///
|
||||
/// After each write a flush is written, it is assumed that this tells the device to
|
||||
@@ -200,22 +196,26 @@ impl CtrlAnimeDisplay {
|
||||
///
|
||||
/// Where led brightness is 0..255, low to high
|
||||
#[inline]
|
||||
fn write_image(&mut self, image: Vec<Vec<u8>>) -> Result<(), AuraError> {
|
||||
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() {
|
||||
self.write_bytes(row)?;
|
||||
self.write_bytes(row);
|
||||
}
|
||||
self.do_flush()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn do_initialization(&mut self) -> Result<(), AuraError> {
|
||||
fn do_initialization(&self) -> Result<(), AuraError> {
|
||||
let mut init = [0; PACKET_SIZE];
|
||||
init[0] = DEV_PAGE; // This is the USB page we're using throughout
|
||||
for (idx, byte) in INIT_STR.as_bytes().iter().enumerate() {
|
||||
init[idx + 1] = *byte
|
||||
}
|
||||
self.write_bytes(&init)?;
|
||||
self.write_bytes(&init);
|
||||
|
||||
// clear the init array and write other init message
|
||||
for ch in init.iter_mut() {
|
||||
@@ -224,43 +224,42 @@ impl CtrlAnimeDisplay {
|
||||
init[0] = DEV_PAGE; // write it to be sure?
|
||||
init[1] = INIT;
|
||||
|
||||
self.write_bytes(&init)?;
|
||||
self.initialised = true;
|
||||
self.write_bytes(&init);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn do_flush(&mut self) -> Result<(), AuraError> {
|
||||
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)?;
|
||||
self.write_bytes(&flush);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn do_set_boot(&mut self, status: bool) -> Result<(), AuraError> {
|
||||
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)?;
|
||||
self.write_bytes(&flush);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn do_apply(&mut self) -> Result<(), AuraError> {
|
||||
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)?;
|
||||
self.write_bytes(&flush);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -101,7 +101,7 @@ impl CtrlCharge {
|
||||
}
|
||||
|
||||
pub(super) fn set(&self, limit: u8, config: &mut Config) -> Result<(), RogError> {
|
||||
if limit < 20 || limit > 100 {
|
||||
if !(20..=100).contains(&limit) {
|
||||
warn!(
|
||||
"Unable to set battery charge limit, must be between 20-100: requested {}",
|
||||
limit
|
||||
@@ -1,15 +1,15 @@
|
||||
use crate::error::RogError;
|
||||
use crate::{
|
||||
config::{Config, Profile},
|
||||
GetSupported,
|
||||
};
|
||||
use asus_nb::profile::ProfileEvent;
|
||||
use log::{info, warn};
|
||||
use rog_types::profile::{FanLevel, ProfileEvent};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::convert::TryInto;
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::{Read, Write};
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
use zbus::dbus_interface;
|
||||
@@ -62,8 +62,7 @@ impl DbusFanAndCpu {
|
||||
cfg.read();
|
||||
ctrl.handle_profile_event(&event, &mut cfg)
|
||||
.unwrap_or_else(|err| warn!("{}", err));
|
||||
self.notify_profile(&cfg.active_profile)
|
||||
.unwrap_or_else(|_| ());
|
||||
self.notify_profile(&cfg.active_profile).unwrap_or(());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -132,7 +131,7 @@ impl crate::ZbusAdd for DbusFanAndCpu {
|
||||
server
|
||||
.at(&"/org/asuslinux/Profile".try_into().unwrap(), self)
|
||||
.map_err(|err| {
|
||||
warn!("DbusFanAndCpu: {}", err);
|
||||
warn!("DbusFanAndCpu: add_to_server {}", err);
|
||||
err
|
||||
})
|
||||
.ok();
|
||||
@@ -142,65 +141,17 @@ impl crate::ZbusAdd for DbusFanAndCpu {
|
||||
impl crate::Reloadable for CtrlFanAndCPU {
|
||||
fn reload(&mut self) -> Result<(), RogError> {
|
||||
if let Ok(mut config) = self.config.clone().try_lock() {
|
||||
let mut file = OpenOptions::new()
|
||||
.write(true)
|
||||
.open(self.path)
|
||||
.map_err(|err| RogError::Path(self.path.into(), err))?;
|
||||
file.write_all(format!("{}\n", config.power_profile).as_bytes())
|
||||
.map_err(|err| RogError::Write(self.path.into(), err))?;
|
||||
let profile = config.active_profile.clone();
|
||||
self.set(&profile, &mut config)?;
|
||||
info!(
|
||||
"Reloaded fan mode: {:?}",
|
||||
FanLevel::from(config.power_profile)
|
||||
);
|
||||
// info!(
|
||||
// "Reloaded fan mode: {:?}",
|
||||
// FanLevel::from(config.power_profile)
|
||||
// );
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::CtrlTask for CtrlFanAndCPU {
|
||||
fn do_task(&mut self) -> Result<(), RogError> {
|
||||
let mut file = OpenOptions::new()
|
||||
.read(true)
|
||||
.open(self.path)
|
||||
.map_err(|err| RogError::Path(self.path.into(), err))?;
|
||||
let mut buf = [0u8; 1];
|
||||
file.read_exact(&mut buf)
|
||||
.map_err(|err| RogError::Read(self.path.into(), err))?;
|
||||
if let Some(num) = char::from(buf[0]).to_digit(10) {
|
||||
if let Ok(mut config) = self.config.clone().try_lock() {
|
||||
if config.power_profile != num as u8 {
|
||||
config.read();
|
||||
|
||||
let mut i = config
|
||||
.toggle_profiles
|
||||
.iter()
|
||||
.position(|x| x == &config.active_profile)
|
||||
.map(|i| i + 1)
|
||||
.unwrap_or(0);
|
||||
if i >= config.toggle_profiles.len() {
|
||||
i = 0;
|
||||
}
|
||||
|
||||
let new_profile = config
|
||||
.toggle_profiles
|
||||
.get(i)
|
||||
.unwrap_or(&config.active_profile)
|
||||
.clone();
|
||||
|
||||
self.set(&new_profile, &mut config)?;
|
||||
|
||||
info!("Profile was changed: {}", &new_profile);
|
||||
}
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
Err(RogError::DoTask("Fan-level could not be parsed".into()))
|
||||
}
|
||||
}
|
||||
|
||||
impl CtrlFanAndCPU {
|
||||
pub fn new(config: Arc<Mutex<Config>>) -> Result<Self, RogError> {
|
||||
let path = CtrlFanAndCPU::get_fan_path()?;
|
||||
@@ -246,7 +197,7 @@ impl CtrlFanAndCPU {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(super) fn set_fan_mode(&mut self, preset: u8, config: &mut Config) -> Result<(), RogError> {
|
||||
fn set_fan_mode(&mut self, preset: u8, config: &mut Config) -> Result<(), RogError> {
|
||||
let mode = config.active_profile.clone();
|
||||
let mut fan_ctrl = OpenOptions::new()
|
||||
.write(true)
|
||||
@@ -257,15 +208,13 @@ impl CtrlFanAndCPU {
|
||||
.power_profiles
|
||||
.get_mut(&mode)
|
||||
.ok_or_else(|| RogError::MissingProfile(mode.clone()))?;
|
||||
config.power_profile = preset;
|
||||
config.curr_fan_mode = preset;
|
||||
mode_config.fan_preset = preset;
|
||||
config.write();
|
||||
fan_ctrl
|
||||
.write_all(format!("{}\n", preset).as_bytes())
|
||||
.map_err(|err| RogError::Write(self.path.into(), err))?;
|
||||
info!("Fan mode set to: {:?}", FanLevel::from(preset));
|
||||
self.set_pstate_for_fan_mode(&mode, config)?;
|
||||
self.set_fan_curve_for_fan_mode(&mode, config)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -278,6 +227,9 @@ impl CtrlFanAndCPU {
|
||||
ProfileEvent::Toggle => self.do_next_profile(config)?,
|
||||
ProfileEvent::ChangeMode(mode) => {
|
||||
self.set_fan_mode(*mode, config)?;
|
||||
let mode = config.active_profile.clone();
|
||||
self.set_pstate_for_fan_mode(&mode, config)?;
|
||||
self.set_fan_curve_for_fan_mode(&mode, config)?;
|
||||
}
|
||||
ProfileEvent::Cli(command) => {
|
||||
let profile_key = match command.profile.as_ref() {
|
||||
@@ -328,10 +280,10 @@ impl CtrlFanAndCPU {
|
||||
.write(true)
|
||||
.open(self.path)
|
||||
.map_err(|err| RogError::Path(self.path.into(), err))?;
|
||||
config.curr_fan_mode = mode_config.fan_preset;
|
||||
fan_ctrl
|
||||
.write_all(format!("{}\n", mode_config.fan_preset).as_bytes())
|
||||
.map_err(|err| RogError::Write(self.path.into(), err))?;
|
||||
config.power_profile = mode_config.fan_preset;
|
||||
|
||||
self.set_pstate_for_fan_mode(profile, config)?;
|
||||
self.set_fan_curve_for_fan_mode(profile, config)?;
|
||||
@@ -393,46 +345,3 @@ impl CtrlFanAndCPU {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
use crate::error::RogError;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum FanLevel {
|
||||
Normal,
|
||||
Boost,
|
||||
Silent,
|
||||
}
|
||||
|
||||
impl FromStr for FanLevel {
|
||||
type Err = RogError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, RogError> {
|
||||
match s.to_lowercase().as_str() {
|
||||
"normal" => Ok(FanLevel::Normal),
|
||||
"boost" => Ok(FanLevel::Boost),
|
||||
"silent" => Ok(FanLevel::Silent),
|
||||
_ => Err(RogError::ParseFanLevel),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u8> for FanLevel {
|
||||
fn from(n: u8) -> Self {
|
||||
match n {
|
||||
0 => FanLevel::Normal,
|
||||
1 => FanLevel::Boost,
|
||||
2 => FanLevel::Silent,
|
||||
_ => FanLevel::Normal,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FanLevel> for u8 {
|
||||
fn from(n: FanLevel) -> Self {
|
||||
match n {
|
||||
FanLevel::Normal => 0,
|
||||
FanLevel::Boost => 1,
|
||||
FanLevel::Silent => 2,
|
||||
}
|
||||
}
|
||||
}
|
||||
30
daemon/src/ctrl_gfx/error.rs
Normal file
@@ -0,0 +1,30 @@
|
||||
use std::error;
|
||||
use std::fmt;
|
||||
|
||||
use crate::error::RogError;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum GfxError {
|
||||
ParseVendor,
|
||||
Bus(String, std::io::Error),
|
||||
DisplayManager(String),
|
||||
}
|
||||
|
||||
impl fmt::Display for GfxError {
|
||||
// This trait requires `fmt` with this exact signature.
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
GfxError::ParseVendor => write!(f, "Could not parse vendor name"),
|
||||
GfxError::Bus(func, error) => write!(f, "Bus error: {}: {}", func, error),
|
||||
GfxError::DisplayManager(detail) => write!(f, "Display manager: {}", detail),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for GfxError {}
|
||||
|
||||
impl From<GfxError> for RogError {
|
||||
fn from(err: GfxError) -> Self {
|
||||
RogError::GfxSwitching(err)
|
||||
}
|
||||
}
|
||||
422
daemon/src/ctrl_gfx/gfx.rs
Normal file
@@ -0,0 +1,422 @@
|
||||
use ctrl_gfx::error::GfxError;
|
||||
use ctrl_gfx::*;
|
||||
use log::{error, info, warn};
|
||||
use rog_types::gfx_vendors::GfxVendors;
|
||||
use std::iter::FromIterator;
|
||||
use std::process::Command;
|
||||
use std::str::FromStr;
|
||||
use std::{io::Write, ops::Add, path::Path};
|
||||
use std::{sync::Arc, sync::Mutex};
|
||||
use sysfs_class::{PciDevice, SysClass};
|
||||
use system::{GraphicsDevice, PciBus};
|
||||
use zbus::dbus_interface;
|
||||
|
||||
use crate::*;
|
||||
|
||||
pub struct CtrlGraphics {
|
||||
bus: PciBus,
|
||||
_amd: Vec<GraphicsDevice>,
|
||||
_intel: Vec<GraphicsDevice>,
|
||||
nvidia: Vec<GraphicsDevice>,
|
||||
#[allow(dead_code)]
|
||||
other: Vec<GraphicsDevice>,
|
||||
config: Arc<Mutex<Config>>,
|
||||
}
|
||||
|
||||
trait Dbus {
|
||||
fn vendor(&self) -> String;
|
||||
fn power(&self) -> String;
|
||||
fn set_vendor(&mut self, vendor: String);
|
||||
fn notify_gfx(&self, vendor: &str) -> zbus::Result<()>;
|
||||
fn notify_action(&self, action: &str) -> zbus::Result<()>;
|
||||
}
|
||||
|
||||
use std::convert::TryInto;
|
||||
|
||||
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
||||
impl Dbus for CtrlGraphics {
|
||||
fn vendor(&self) -> String {
|
||||
self.get_gfx_mode()
|
||||
.map(|gfx| gfx.into())
|
||||
.unwrap_or_else(|err| format!("Get vendor failed: {}", err))
|
||||
}
|
||||
|
||||
fn power(&self) -> String {
|
||||
Self::get_runtime_status().unwrap_or_else(|err| format!("Get power status failed: {}", err))
|
||||
}
|
||||
|
||||
fn set_vendor(&mut self, vendor: String) {
|
||||
if let Ok(tmp) = GfxVendors::from_str(&vendor) {
|
||||
info!("Switching gfx mode to {}", vendor);
|
||||
let msg = self.set_gfx_config(tmp).unwrap_or_else(|err| {
|
||||
error!("{}", err);
|
||||
format!("Failed: {}", err.to_string())
|
||||
});
|
||||
self.notify_gfx(&vendor)
|
||||
.unwrap_or_else(|err| warn!("{}", err));
|
||||
self.notify_action(&msg)
|
||||
.unwrap_or_else(|err| warn!("{}", err));
|
||||
}
|
||||
}
|
||||
|
||||
#[dbus_interface(signal)]
|
||||
fn notify_gfx(&self, vendor: &str) -> zbus::Result<()> {}
|
||||
|
||||
#[dbus_interface(signal)]
|
||||
fn notify_action(&self, action: &str) -> zbus::Result<()> {}
|
||||
}
|
||||
|
||||
impl ZbusAdd for CtrlGraphics {
|
||||
fn add_to_server(self, server: &mut zbus::ObjectServer) {
|
||||
server
|
||||
.at(
|
||||
&"/org/asuslinux/Gfx"
|
||||
.try_into()
|
||||
.expect("Couldn't add to zbus"),
|
||||
self,
|
||||
)
|
||||
.map_err(|err| {
|
||||
warn!("CtrlGraphics: add_to_server {}", err);
|
||||
err
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
|
||||
impl Reloadable for CtrlGraphics {
|
||||
fn reload(&mut self) -> Result<(), RogError> {
|
||||
self.auto_power()?;
|
||||
info!("Reloaded gfx mode: {:?}", self.get_gfx_mode()?);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl CtrlGraphics {
|
||||
pub fn new(config: Arc<Mutex<Config>>) -> std::io::Result<CtrlGraphics> {
|
||||
let bus = PciBus::new()?;
|
||||
|
||||
info!("Rescanning PCI bus");
|
||||
bus.rescan()?;
|
||||
|
||||
let devs = PciDevice::all()?;
|
||||
|
||||
let functions = |parent: &PciDevice| -> Vec<PciDevice> {
|
||||
let mut functions = Vec::new();
|
||||
if let Some(parent_slot) = parent.id().split('.').next() {
|
||||
for func in devs.iter() {
|
||||
if let Some(func_slot) = func.id().split('.').next() {
|
||||
if func_slot == parent_slot {
|
||||
info!("{}: Function for {}", func.id(), parent.id());
|
||||
functions.push(func.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
functions
|
||||
};
|
||||
|
||||
let mut amd = Vec::new();
|
||||
let mut intel = Vec::new();
|
||||
let mut nvidia = Vec::new();
|
||||
let mut other = Vec::new();
|
||||
for dev in devs.iter() {
|
||||
let c = dev.class()?;
|
||||
if 0x03 == (c >> 16) & 0xFF {
|
||||
match dev.vendor()? {
|
||||
0x1002 => {
|
||||
info!("{}: AMD graphics", dev.id());
|
||||
amd.push(GraphicsDevice::new(dev.id().to_owned(), functions(&dev)));
|
||||
}
|
||||
0x10DE => {
|
||||
info!("{}: NVIDIA graphics", dev.id());
|
||||
nvidia.push(GraphicsDevice::new(dev.id().to_owned(), functions(&dev)));
|
||||
}
|
||||
0x8086 => {
|
||||
info!("{}: Intel graphics", dev.id());
|
||||
intel.push(GraphicsDevice::new(dev.id().to_owned(), functions(&dev)));
|
||||
}
|
||||
vendor => {
|
||||
info!("{}: Other({:X}) graphics", dev.id(), vendor);
|
||||
other.push(GraphicsDevice::new(dev.id().to_owned(), functions(&dev)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(CtrlGraphics {
|
||||
bus,
|
||||
_amd: amd,
|
||||
_intel: intel,
|
||||
nvidia,
|
||||
other,
|
||||
config,
|
||||
})
|
||||
}
|
||||
|
||||
fn save_gfx_mode(&self, vendor: GfxVendors) -> Result<(), RogError> {
|
||||
if let Ok(mut config) = self.config.lock() {
|
||||
config.gfx_mode = vendor.clone();
|
||||
config.write();
|
||||
return Ok(());
|
||||
}
|
||||
// TODO: Error here
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Associated method to get which vendor mode is set
|
||||
pub fn get_gfx_mode(&self) -> Result<GfxVendors, RogError> {
|
||||
if let Ok(config) = self.config.lock() {
|
||||
return Ok(config.gfx_mode.clone());
|
||||
}
|
||||
// TODO: Error here
|
||||
Ok(GfxVendors::Hybrid)
|
||||
}
|
||||
|
||||
fn get_runtime_status() -> Result<String, RogError> {
|
||||
const PATH: &str = "/sys/bus/pci/devices/0000:01:00.0/power/runtime_status";
|
||||
let buf = std::fs::read_to_string(PATH).map_err(|err| RogError::Read(PATH.into(), err))?;
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
fn toggle_fallback_service(vendor: GfxVendors) -> Result<(), RogError> {
|
||||
let action = if vendor == GfxVendors::Nvidia {
|
||||
info!("Enabling nvidia-fallback.service");
|
||||
"enable"
|
||||
} else {
|
||||
info!("Disabling nvidia-fallback.service");
|
||||
"disable"
|
||||
};
|
||||
|
||||
let status = Command::new("systemctl")
|
||||
.arg(action)
|
||||
.arg("nvidia-fallback.service")
|
||||
.status()
|
||||
.map_err(|err| RogError::Command("systemctl".into(), err))?;
|
||||
|
||||
if !status.success() {
|
||||
// Error is ignored in case this service is removed
|
||||
warn!(
|
||||
"systemctl: {} (ignore warning if service does not exist!)",
|
||||
status
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_xorg_conf(vendor: GfxVendors) -> Result<(), RogError> {
|
||||
let text = if vendor == GfxVendors::Nvidia {
|
||||
[PRIMARY_GPU_BEGIN, PRIMARY_GPU_NVIDIA, PRIMARY_GPU_END].concat()
|
||||
} else {
|
||||
[PRIMARY_GPU_BEGIN, PRIMARY_GPU_END].concat()
|
||||
};
|
||||
|
||||
if !Path::new(XORG_PATH).exists() {
|
||||
std::fs::create_dir(XORG_PATH).map_err(|err| RogError::Write(XORG_PATH.into(), err))?;
|
||||
}
|
||||
|
||||
let file = XORG_PATH.to_string().add(XORG_FILE);
|
||||
info!("Writing {}", file);
|
||||
let mut file = std::fs::OpenOptions::new()
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.write(true)
|
||||
.open(&file)
|
||||
.map_err(|err| RogError::Write(file, err))?;
|
||||
|
||||
file.write_all(&text)
|
||||
.and_then(|_| file.sync_all())
|
||||
.map_err(|err| RogError::Write(MODPROBE_PATH.into(), err))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_modprobe_conf() -> Result<(), RogError> {
|
||||
info!("Writing {}", MODPROBE_PATH);
|
||||
|
||||
let mut file = std::fs::OpenOptions::new()
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.write(true)
|
||||
.open(MODPROBE_PATH)
|
||||
.map_err(|err| RogError::Path(MODPROBE_PATH.into(), err))?;
|
||||
|
||||
file.write_all(MODPROBE_BASE)
|
||||
.and_then(|_| file.sync_all())
|
||||
.map_err(|err| RogError::Write(MODPROBE_PATH.into(), err))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn unbind_remove_nvidia(&self) -> Result<(), RogError> {
|
||||
// Unbind NVIDIA graphics devices and their functions
|
||||
let unbinds = self.nvidia.iter().map(|dev| dev.unbind());
|
||||
|
||||
// Remove NVIDIA graphics devices and their functions
|
||||
let removes = self.nvidia.iter().map(|dev| dev.remove());
|
||||
|
||||
Result::from_iter(unbinds.chain(removes))
|
||||
.map_err(|err| RogError::Command("device unbind error".into(), err))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn do_driver_action(driver: &str, action: &str) -> Result<(), RogError> {
|
||||
let mut cmd;
|
||||
if Self::kmod_exists() {
|
||||
info!("using kmod");
|
||||
cmd = Command::new("kmod");
|
||||
cmd.arg(action);
|
||||
} else {
|
||||
cmd = Command::new(action);
|
||||
}
|
||||
cmd.arg(driver);
|
||||
|
||||
let mut count = 0;
|
||||
const MAX_TRIES: i32 = 6;
|
||||
loop {
|
||||
if count > MAX_TRIES {
|
||||
let msg = format!("{} {} failed for unknown reason", action, driver);
|
||||
error!("{}", msg);
|
||||
return Ok(()) //Err(RogError::Modprobe(msg));
|
||||
}
|
||||
|
||||
let output = cmd
|
||||
.output()
|
||||
.map_err(|err| RogError::Command(format!("{:?}", cmd), err))?;
|
||||
if !output.status.success() {
|
||||
if output.stderr.ends_with("is not currently loaded\n".as_bytes()) {
|
||||
return Ok(())
|
||||
}
|
||||
if output.stderr.ends_with("Permission denied\n".as_bytes()) {
|
||||
let msg = format!("{} {} failed: {:?}", action, driver, String::from_utf8_lossy(&output.stderr));
|
||||
warn!("{}", msg);
|
||||
warn!("It may be safe to ignore the above error, run `lsmod |grep nvidia` to confirm modules loaded");
|
||||
return Ok(())
|
||||
}
|
||||
if count == MAX_TRIES {
|
||||
let msg = format!("{} {} failed: {:?}", action, driver, String::from_utf8_lossy(&output.stderr));
|
||||
return Err(RogError::Modprobe(msg));
|
||||
}
|
||||
}
|
||||
|
||||
count += 1;
|
||||
std::thread::sleep(std::time::Duration::from_millis(250));
|
||||
}
|
||||
}
|
||||
|
||||
fn do_display_manager_action(action: &str) -> Result<(), RogError> {
|
||||
let mut cmd = Command::new("systemctl");
|
||||
cmd.arg(action);
|
||||
cmd.arg(DISPLAY_MANAGER);
|
||||
|
||||
let status = cmd
|
||||
.status()
|
||||
.map_err(|err| RogError::Command(format!("{:?}", cmd), err))?;
|
||||
if !status.success() {
|
||||
let msg = format!(
|
||||
"systemctl {} {} failed: {:?}",
|
||||
action, DISPLAY_MANAGER, status
|
||||
);
|
||||
return Err(GfxError::DisplayManager(msg).into());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn wait_display_manager_inactive() -> Result<(), RogError> {
|
||||
let mut cmd = Command::new("systemctl");
|
||||
cmd.arg("is-active");
|
||||
cmd.arg(DISPLAY_MANAGER);
|
||||
|
||||
let mut count = 0;
|
||||
|
||||
while count <= 4 {
|
||||
let output = cmd
|
||||
.output()
|
||||
.map_err(|err| RogError::Command(format!("{:?}", cmd), err))?;
|
||||
if output.stdout.starts_with("inactive".as_bytes()) {
|
||||
return Ok(());
|
||||
}
|
||||
std::thread::sleep(std::time::Duration::from_millis(500));
|
||||
count += 1;
|
||||
}
|
||||
return Err(
|
||||
GfxError::DisplayManager("display-manager did not completely stop".into()).into(),
|
||||
);
|
||||
}
|
||||
|
||||
fn kmod_exists() -> bool {
|
||||
let mut cmd = Command::new("which");
|
||||
cmd.arg("kmod");
|
||||
if let Ok(output) = cmd
|
||||
.output() {
|
||||
return output.status.success() && output.stdout.ends_with("kmod".as_bytes())
|
||||
}
|
||||
//Path::new("/usr/bin/kmod").exists()
|
||||
false
|
||||
}
|
||||
|
||||
pub fn do_vendor_tasks(&mut self, vendor: GfxVendors) -> Result<(), RogError> {
|
||||
Self::write_xorg_conf(vendor)?;
|
||||
Self::write_modprobe_conf()?; // TODO: Not required here, should put in startup?
|
||||
|
||||
// Rescan before doing remove or add drivers
|
||||
self.bus
|
||||
.rescan()
|
||||
.map_err(|err| GfxError::Bus("bus rescan error".into(), err))?;
|
||||
|
||||
match vendor {
|
||||
GfxVendors::Nvidia | GfxVendors::Hybrid | GfxVendors::Compute => {
|
||||
for driver in NVIDIA_DRIVERS.iter() {
|
||||
Self::do_driver_action(driver, "modprobe")?;
|
||||
}
|
||||
}
|
||||
// TODO: compute mode, needs different setup
|
||||
// GfxVendors::Compute => {}
|
||||
GfxVendors::Integrated => {
|
||||
for driver in NVIDIA_DRIVERS.iter() {
|
||||
Self::do_driver_action(driver, "rmmod")?;
|
||||
}
|
||||
self.unbind_remove_nvidia()?;
|
||||
}
|
||||
}
|
||||
|
||||
self.save_gfx_mode(vendor)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// For manually calling (not on boot/startup)
|
||||
///
|
||||
/// Will stop and start display manager without warning
|
||||
pub fn set_gfx_config(&mut self, vendor: GfxVendors) -> Result<String, RogError> {
|
||||
Self::do_display_manager_action("stop")?;
|
||||
Self::wait_display_manager_inactive()?;
|
||||
self.do_vendor_tasks(vendor)?;
|
||||
Self::do_display_manager_action("start")?;
|
||||
// TODO: undo if failed? Save last mode, catch errors...
|
||||
let v: &str = vendor.into();
|
||||
Ok(format!("Graphics mode changed to {} successfully", v))
|
||||
}
|
||||
|
||||
// if CtrlRogBios::has_dedicated_gfx_toggle() {
|
||||
// if let Ok(config) = self.config.clone().try_lock() {
|
||||
// // Switch to dedicated if config says to do so
|
||||
// if config.gfx_nv_mode_is_dedicated && vendor == GfxVendors::Nvidia {
|
||||
// CtrlRogBios::set_gfx_mode(true)
|
||||
// .unwrap_or_else(|err| warn!("Gfx controller: {}", err));
|
||||
// } else if let Ok(ded) = CtrlRogBios::get_gfx_mode() {
|
||||
// // otherwise if switching to non-Nvidia mode turn off dedicated mode
|
||||
// if ded == 1 && vendor != GfxVendors::Nvidia {
|
||||
// CtrlRogBios::set_gfx_mode(false)
|
||||
// .unwrap_or_else(|err| warn!("Gfx controller: {}", err));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
fn auto_power(&mut self) -> Result<(), RogError> {
|
||||
let vendor = self.get_gfx_mode()?;
|
||||
self.do_vendor_tasks(vendor)?;
|
||||
Self::toggle_fallback_service(vendor)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
37
daemon/src/ctrl_gfx/mod.rs
Normal file
@@ -0,0 +1,37 @@
|
||||
pub mod error;
|
||||
|
||||
pub mod gfx;
|
||||
|
||||
pub mod system;
|
||||
|
||||
const NVIDIA_DRIVERS: [&str; 4] = ["nvidia_drm", "nvidia_modeset", "nvidia_uvm", "nvidia"];
|
||||
|
||||
const DISPLAY_MANAGER: &str = "display-manager.service";
|
||||
|
||||
const MODPROBE_PATH: &str = "/etc/modprobe.d/asusd.conf";
|
||||
|
||||
static MODPROBE_BASE: &[u8] = br#"# Automatically generated by asusd
|
||||
#blacklist i2c_nvidia_gpu
|
||||
#alias i2c_nvidia_gpu off
|
||||
blacklist nouveau
|
||||
alias nouveau off
|
||||
options nvidia NVreg_DynamicPowerManagement=0x02
|
||||
options nvidia-drm modeset=1
|
||||
"#;
|
||||
|
||||
const XORG_FILE: &str = "90-nvidia-primary.conf";
|
||||
const XORG_PATH: &str = "/etc/X11/xorg.conf.d/";
|
||||
|
||||
static PRIMARY_GPU_BEGIN: &[u8] = br#"# Automatically generated by asusd
|
||||
Section "OutputClass"
|
||||
Identifier "nvidia"
|
||||
MatchDriver "nvidia-drm"
|
||||
Driver "nvidia"
|
||||
Option "AllowEmptyInitialConfiguration"
|
||||
Option "AllowExternalGpus""#;
|
||||
|
||||
static PRIMARY_GPU_NVIDIA: &[u8] = br#"
|
||||
Option "PrimaryGPU" "true""#;
|
||||
|
||||
static PRIMARY_GPU_END: &[u8] = br#"
|
||||
EndSection"#;
|
||||
@@ -50,19 +50,20 @@ impl PciBus {
|
||||
}
|
||||
}
|
||||
|
||||
/// Will rescan the device tree, which adds all removed devices back
|
||||
pub fn rescan(&self) -> io::Result<()> {
|
||||
write(self.path.join("rescan"), "1")
|
||||
}
|
||||
}
|
||||
|
||||
pub struct GraphicsDevice {
|
||||
id: String,
|
||||
_id: String,
|
||||
functions: Vec<PciDevice>,
|
||||
}
|
||||
|
||||
impl GraphicsDevice {
|
||||
pub fn new(id: String, functions: Vec<PciDevice>) -> GraphicsDevice {
|
||||
GraphicsDevice { id, functions }
|
||||
GraphicsDevice { _id: id, functions }
|
||||
}
|
||||
|
||||
pub fn exists(&self) -> bool {
|
||||
@@ -95,6 +96,32 @@ impl GraphicsDevice {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn rebind(&self) -> Result<(), std::io::Error> {
|
||||
for func in self.functions.iter() {
|
||||
if func.path().exists() {
|
||||
match func.driver() {
|
||||
Ok(driver) => {
|
||||
info!("{}: Binding {}", driver.id(), func.id());
|
||||
unsafe {
|
||||
driver.bind(&func).map_err(|err| {
|
||||
error!("gfx bind: {}", err);
|
||||
err
|
||||
})?;
|
||||
}
|
||||
}
|
||||
Err(err) => match err.kind() {
|
||||
io::ErrorKind::NotFound => (),
|
||||
_ => {
|
||||
error!("gfx driver: {:?}, {}", func.path(), err);
|
||||
return Err(err);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn remove(&self) -> Result<(), std::io::Error> {
|
||||
for func in self.functions.iter() {
|
||||
if func.path().exists() {
|
||||
@@ -9,13 +9,13 @@ use crate::{
|
||||
error::RogError,
|
||||
laptops::{match_laptop, HELP_ADDRESS},
|
||||
};
|
||||
use asus_nb::{
|
||||
use log::{error, info, warn};
|
||||
use rog_types::{
|
||||
aura_brightness_bytes,
|
||||
aura_modes::{AuraModes, PER_KEY},
|
||||
fancy::KeyColourArray,
|
||||
LED_MSG_LEN,
|
||||
};
|
||||
use log::{info, warn};
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::{Read, Write};
|
||||
use std::sync::Arc;
|
||||
@@ -44,11 +44,9 @@ impl GetSupported for CtrlKbdBacklight {
|
||||
let modes = laptop.supported_modes().to_vec();
|
||||
if modes.contains(&PER_KEY) {
|
||||
per_key_led_mode = true;
|
||||
let modes = modes
|
||||
.iter()
|
||||
.filter(|x| **x != PER_KEY)
|
||||
.map(|x| *x)
|
||||
.collect();
|
||||
let modes = modes.iter().filter(|x| **x != PER_KEY).copied().collect();
|
||||
stock_led_modes = Some(modes);
|
||||
} else {
|
||||
stock_led_modes = Some(modes);
|
||||
}
|
||||
}
|
||||
@@ -91,6 +89,9 @@ impl crate::ZbusAdd for DbusKbdBacklight {
|
||||
fn add_to_server(self, server: &mut zbus::ObjectServer) {
|
||||
server
|
||||
.at(&"/org/asuslinux/Led".try_into().unwrap(), self)
|
||||
.map_err(|err| {
|
||||
error!("DbusKbdBacklight: add_to_server {}", err);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
@@ -108,9 +109,14 @@ impl DbusKbdBacklight {
|
||||
}
|
||||
_ => {
|
||||
if let Ok(json) = serde_json::to_string(&data) {
|
||||
ctrl.do_command(data, &mut cfg)
|
||||
.unwrap_or_else(|err| warn!("{}", err));
|
||||
self.notify_led(&json).ok();
|
||||
match ctrl.do_command(data, &mut cfg) {
|
||||
Ok(_) => {
|
||||
self.notify_led(&json).ok();
|
||||
}
|
||||
Err(err) => {
|
||||
warn!("{}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -278,13 +284,39 @@ impl CtrlKbdBacklight {
|
||||
config: Arc<Mutex<Config>>,
|
||||
) -> Result<Self, RogError> {
|
||||
// TODO: return error if *all* nodes are None
|
||||
let led_node = Self::get_node_failover(id_product, None, Self::scan_led_node).map_or_else(
|
||||
|err| {
|
||||
warn!("led_node: {}", err);
|
||||
None
|
||||
},
|
||||
Some,
|
||||
);
|
||||
|
||||
let kbd_node = Self::get_node_failover(id_product, condev_iface, Self::scan_kbd_node)
|
||||
.map_or_else(
|
||||
|err| {
|
||||
warn!("kbd_node: {}", err);
|
||||
None
|
||||
},
|
||||
Some,
|
||||
);
|
||||
|
||||
let bright_node = Self::get_kbd_bright_path();
|
||||
|
||||
if led_node.is_none() && kbd_node.is_none() && Self::get_kbd_bright_path().is_err() {
|
||||
return Err(RogError::MissingFunction(
|
||||
"All keyboard features missing, you may require a v5.11 series kernel or newer"
|
||||
.into(),
|
||||
));
|
||||
}
|
||||
|
||||
let ctrl = CtrlKbdBacklight {
|
||||
// Using `ok` here so we can continue without keyboard features but
|
||||
// still get brightness control at least... maybe...
|
||||
led_node: Self::get_node_failover(id_product, None, Self::scan_led_node).ok(),
|
||||
kbd_node: Self::get_node_failover(id_product, condev_iface, Self::scan_kbd_node).ok(),
|
||||
led_node,
|
||||
kbd_node,
|
||||
// TODO: Check for existance
|
||||
bright_node: Self::get_kbd_bright_path()?.to_owned(),
|
||||
bright_node: bright_node?.to_owned(),
|
||||
supported_modes,
|
||||
flip_effect_write: false,
|
||||
config,
|
||||
@@ -307,23 +339,12 @@ impl CtrlKbdBacklight {
|
||||
iface: Option<&String>,
|
||||
fun: fn(&str, Option<&String>) -> Result<String, RogError>,
|
||||
) -> Result<String, RogError> {
|
||||
// We do three tries here just to be certain that we avoid systemd unit
|
||||
// load order issues
|
||||
for n in 0..=2 {
|
||||
// 0,1,2 inclusive
|
||||
match fun(id_product, iface) {
|
||||
Ok(o) => return Ok(o),
|
||||
Err(e) => {
|
||||
if n == 2 {
|
||||
warn!("Looking for node: {}", e.to_string());
|
||||
std::thread::sleep(std::time::Duration::from_secs(1));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
match fun(id_product, iface) {
|
||||
Ok(o) => return Ok(o),
|
||||
Err(e) => {
|
||||
warn!("Looking for node: {}", e.to_string());
|
||||
}
|
||||
}
|
||||
// Shouldn't be possible to reach this...
|
||||
Err(RogError::NotFound(format!("{}, {:?}", id_product, iface)))
|
||||
}
|
||||
|
||||
@@ -350,7 +371,7 @@ impl CtrlKbdBacklight {
|
||||
{
|
||||
if parent
|
||||
.attribute_value("idProduct")
|
||||
.ok_or(RogError::NotFound("LED idProduct".into()))?
|
||||
.ok_or_else(|| RogError::NotFound("LED idProduct".into()))?
|
||||
== id_product
|
||||
{
|
||||
if let Some(dev_node) = device.devnode() {
|
||||
@@ -420,6 +441,7 @@ impl CtrlKbdBacklight {
|
||||
fn write_bytes(&self, message: &[u8]) -> Result<(), RogError> {
|
||||
if let Some(led_node) = &self.led_node {
|
||||
if let Ok(mut file) = OpenOptions::new().write(true).open(led_node) {
|
||||
// println!("write: {:02x?}", &message);
|
||||
return file
|
||||
.write_all(message)
|
||||
.map_err(|err| RogError::Write("write_bytes".into(), err));
|
||||
@@ -511,6 +533,10 @@ impl CtrlKbdBacklight {
|
||||
|
||||
#[inline]
|
||||
fn write_mode(&mut self, mode: &AuraModes) -> Result<(), RogError> {
|
||||
let mode_num: u8 = u8::from(mode);
|
||||
if !self.supported_modes.contains(&mode_num) {
|
||||
return Err(RogError::NotSupported);
|
||||
}
|
||||
match mode {
|
||||
AuraModes::PerKey(v) => {
|
||||
if v.is_empty() || v[0].is_empty() {
|
||||
@@ -520,27 +546,22 @@ impl CtrlKbdBacklight {
|
||||
self.write_effect(v)?;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
let mode_num: u8 = u8::from(mode);
|
||||
match mode {
|
||||
AuraModes::MultiStatic(_) => {
|
||||
if self.supported_modes.contains(&mode_num) {
|
||||
let bytes: [[u8; LED_MSG_LEN]; 4] = mode.into();
|
||||
for array in bytes.iter() {
|
||||
self.write_bytes(array)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
if self.supported_modes.contains(&mode_num) {
|
||||
let bytes: [u8; LED_MSG_LEN] = mode.into();
|
||||
self.write_bytes(&bytes)?;
|
||||
}
|
||||
}
|
||||
AuraModes::MultiStatic(_) | AuraModes::MultiBreathe(_) => {
|
||||
let bytes: [[u8; LED_MSG_LEN]; 4] = mode.into();
|
||||
for array in bytes.iter() {
|
||||
self.write_bytes(array)?;
|
||||
}
|
||||
self.write_bytes(&LED_SET)?;
|
||||
// Changes won't persist unless apply is set
|
||||
self.write_bytes(&LED_APPLY)?;
|
||||
return Ok(());
|
||||
}
|
||||
_ => {
|
||||
let bytes: [u8; LED_MSG_LEN] = mode.into();
|
||||
self.write_bytes(&bytes)?;
|
||||
self.write_bytes(&LED_SET)?;
|
||||
// Changes won't persist unless apply is set
|
||||
self.write_bytes(&LED_APPLY)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
@@ -1,27 +1,25 @@
|
||||
use crate::{
|
||||
config::Config,
|
||||
ctrl_gfx::{gfx::CtrlGraphics, vendors::GfxVendors},
|
||||
error::RogError,
|
||||
GetSupported,
|
||||
};
|
||||
//use crate::dbus::DbusEvents;
|
||||
use log::{info, warn};
|
||||
use crate::{config::Config, error::RogError, GetSupported};
|
||||
use log::{error, info, warn};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::convert::TryInto;
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::{Read, Write};
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
use std::{convert::TryInto, io::BufRead};
|
||||
use zbus::dbus_interface;
|
||||
|
||||
const INITRAMFS_PATH: &str = "/usr/sbin/update-initramfs";
|
||||
const DRACUT_PATH: &str = "/usr/bin/dracut";
|
||||
|
||||
static ASUS_SWITCH_GRAPHIC_MODE: &str =
|
||||
"/sys/firmware/efi/efivars/AsusSwitchGraphicMode-607005d5-3f75-4b2e-98f0-85ba66797a3e";
|
||||
static ASUS_POST_LOGO_SOUND: &str =
|
||||
"/sys/firmware/efi/efivars/AsusPostLogoSound-607005d5-3f75-4b2e-98f0-85ba66797a3e";
|
||||
|
||||
pub struct CtrlRogBios {
|
||||
config: Arc<Mutex<Config>>,
|
||||
_config: Arc<Mutex<Config>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
@@ -44,7 +42,7 @@ impl GetSupported for CtrlRogBios {
|
||||
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
||||
impl CtrlRogBios {
|
||||
pub fn set_dedicated_graphic_mode(&mut self, dedicated: bool) {
|
||||
Self::set_gfx_mode(dedicated)
|
||||
self.set_gfx_mode(dedicated)
|
||||
.map_err(|err| {
|
||||
warn!("CtrlRogBios: set_asus_switch_graphic_mode {}", err);
|
||||
err
|
||||
@@ -138,12 +136,12 @@ impl CtrlRogBios {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(CtrlRogBios { config })
|
||||
Ok(CtrlRogBios {
|
||||
_config: config,
|
||||
})
|
||||
}
|
||||
|
||||
fn set_path_mutable(path: &str) -> Result<(), RogError> {
|
||||
use std::process::Command;
|
||||
|
||||
let output = Command::new("/usr/bin/chattr")
|
||||
.arg("-i")
|
||||
.arg(path)
|
||||
@@ -183,7 +181,7 @@ impl CtrlRogBios {
|
||||
Ok(data[idx] as i8)
|
||||
}
|
||||
|
||||
pub(super) fn set_gfx_mode(dedicated: bool) -> Result<(), RogError> {
|
||||
pub(super) fn set_gfx_mode(&self, dedicated: bool) -> Result<(), RogError> {
|
||||
let path = ASUS_SWITCH_GRAPHIC_MODE;
|
||||
let mut file = OpenOptions::new()
|
||||
.read(true)
|
||||
@@ -205,15 +203,17 @@ impl CtrlRogBios {
|
||||
file.write_all(&data)
|
||||
.map_err(|err| RogError::Path(path.into(), err))?;
|
||||
|
||||
if let Ok(ded) = CtrlRogBios::get_gfx_mode() {
|
||||
if let Ok(vendor) = CtrlGraphics::get_vendor() {
|
||||
if ded == 1 && vendor != "nvidia" {
|
||||
warn!("Dedicated GFX toggle is on but driver mode is not nvidia \nSetting to nvidia driver mode");
|
||||
CtrlGraphics::set_gfx_config(GfxVendors::Nvidia)
|
||||
.unwrap_or_else(|err| warn!("Gfx controller: {}", err));
|
||||
}
|
||||
}
|
||||
}
|
||||
self.update_initramfs(dedicated)?;
|
||||
|
||||
// if let Ok(ded) = CtrlRogBios::get_gfx_mode() {
|
||||
// if let Ok(vendor) = CtrlGraphics::get_vendor() {
|
||||
// if ded == 1 && vendor != "nvidia" {
|
||||
// warn!("Dedicated GFX toggle is on but driver mode is not nvidia \nSetting to nvidia driver mode");
|
||||
// CtrlGraphics::set_gfx_config(&GfxVendors::Nvidia)
|
||||
// .unwrap_or_else(|err| warn!("Gfx controller: {}", err));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -258,4 +258,88 @@ impl CtrlRogBios {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// required for g-sync mode
|
||||
fn update_initramfs(&self, dedicated: bool) -> Result<(), RogError> {
|
||||
let mut initfs_cmd = None;
|
||||
|
||||
if Path::new(INITRAMFS_PATH).exists() {
|
||||
let mut cmd = Command::new("update-initramfs");
|
||||
cmd.arg("-u");
|
||||
initfs_cmd = Some(cmd);
|
||||
info!("Using initramfs update command 'update-initramfs'");
|
||||
} else if Path::new(DRACUT_PATH).exists() {
|
||||
let mut cmd = Command::new("dracut");
|
||||
cmd.arg("-f");
|
||||
initfs_cmd = Some(cmd);
|
||||
info!("Using initramfs update command 'dracut'");
|
||||
}
|
||||
|
||||
if let Some(mut cmd) = initfs_cmd {
|
||||
info!("Updating initramfs");
|
||||
|
||||
// If switching to Nvidia dedicated we need these modules included
|
||||
if Path::new(DRACUT_PATH).exists() && dedicated {
|
||||
cmd.arg("--add-drivers");
|
||||
cmd.arg("nvidia nvidia-drm nvidia-modeset nvidia-uvm");
|
||||
info!("System uses dracut, forcing nvidia modules to be included in init");
|
||||
} else if Path::new(INITRAMFS_PATH).exists() {
|
||||
let modules = vec![
|
||||
"nvidia\n",
|
||||
"nvidia-drm\n",
|
||||
"nvidia-modeset\n",
|
||||
"nvidia-uvm\n",
|
||||
];
|
||||
|
||||
let module_include = Path::new("/etc/initramfs-tools/modules");
|
||||
|
||||
if dedicated {
|
||||
let mut file = std::fs::OpenOptions::new()
|
||||
.append(true)
|
||||
.open(module_include)
|
||||
.map_err(|err| {
|
||||
RogError::Write(module_include.to_string_lossy().to_string(), err)
|
||||
})?;
|
||||
// add nvidia modules to module_include
|
||||
file.write_all(modules.concat().as_bytes()).unwrap();
|
||||
} else {
|
||||
let file = std::fs::OpenOptions::new()
|
||||
.read(true)
|
||||
.open(module_include)
|
||||
.map_err(|err| {
|
||||
RogError::Write(module_include.to_string_lossy().to_string(), err)
|
||||
})?;
|
||||
|
||||
let mut buf = Vec::new();
|
||||
// remove modules
|
||||
for line in std::io::BufReader::new(file).lines() {
|
||||
if let Ok(l) = line {
|
||||
if !modules.contains(&l.as_ref()) {
|
||||
buf.append(&mut l.as_bytes().to_vec());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let file = std::fs::OpenOptions::new()
|
||||
.write(true)
|
||||
.open(module_include)
|
||||
.map_err(|err| {
|
||||
RogError::Write(module_include.to_string_lossy().to_string(), err)
|
||||
})?;
|
||||
std::io::BufWriter::new(file).write_all(&buf).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
let status = cmd
|
||||
.status()
|
||||
.map_err(|err| RogError::Write(format!("{:?}", cmd), err))?;
|
||||
if !status.success() {
|
||||
error!("Ram disk update failed");
|
||||
return Err(RogError::Initramfs("Ram disk update failed".into()).into());
|
||||
} else {
|
||||
info!("Successfully updated initramfs");
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -3,17 +3,15 @@ use daemon::ctrl_fan_cpu::{CtrlFanAndCPU, DbusFanAndCpu};
|
||||
use daemon::ctrl_leds::{CtrlKbdBacklight, DbusKbdBacklight};
|
||||
use daemon::laptops::match_laptop;
|
||||
use daemon::{
|
||||
config::Config, laptops::print_board_info, supported::SupportedFunctions, GetSupported,
|
||||
};
|
||||
use daemon::{
|
||||
ctrl_anime::CtrlAnimeDisplay,
|
||||
ctrl_gfx::{gfx::CtrlGraphics, vendors::GfxVendors},
|
||||
config::Config, ctrl_supported::SupportedFunctions, laptops::print_board_info, GetSupported,
|
||||
};
|
||||
use daemon::{ctrl_anime::CtrlAnimeDisplay, ctrl_gfx::gfx::CtrlGraphics};
|
||||
|
||||
use asus_nb::DBUS_NAME;
|
||||
use daemon::{CtrlTask, Reloadable, ZbusAdd};
|
||||
use log::LevelFilter;
|
||||
use log::{error, info, warn};
|
||||
use rog_dbus::DBUS_NAME;
|
||||
use rog_types::gfx_vendors::GfxVendors;
|
||||
use std::error::Error;
|
||||
use std::io::Write;
|
||||
use std::sync::Arc;
|
||||
@@ -33,7 +31,10 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
.filter(None, LevelFilter::Info)
|
||||
.init();
|
||||
|
||||
info!("Version: {}", daemon::VERSION);
|
||||
info!(" daemon v{}", daemon::VERSION);
|
||||
info!(" rog-dbus v{}", rog_dbus::VERSION);
|
||||
info!("rog-types v{}", rog_types::VERSION);
|
||||
|
||||
start_daemon()?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -108,20 +109,19 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
|
||||
// Need to check if a laptop has the dedicated gfx switch
|
||||
if CtrlRogBios::has_dedicated_gfx_toggle() {
|
||||
if let Ok(ded) = CtrlRogBios::get_gfx_mode() {
|
||||
if let Ok(vendor) = CtrlGraphics::get_vendor() {
|
||||
if ded == 1 && vendor != "nvidia" {
|
||||
if let Ok(vendor) = ctrl.get_gfx_mode() {
|
||||
if ded == 1 && vendor != GfxVendors::Nvidia {
|
||||
error!("Dedicated GFX toggle is on but driver mode is not nvidia \nSetting to nvidia driver mode");
|
||||
error!("You must reboot to enable Nvidia driver");
|
||||
ctrl.set(GfxVendors::Nvidia)?;
|
||||
ctrl.do_vendor_tasks(GfxVendors::Nvidia)?;
|
||||
} else if ded == 0 {
|
||||
info!("Dedicated GFX toggle is off");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ctrl.reload()
|
||||
.unwrap_or_else(|err| warn!("Gfx controller: {}", err));
|
||||
}
|
||||
ctrl.reload()
|
||||
.unwrap_or_else(|err| error!("Gfx controller: {}", err));
|
||||
ctrl.add_to_server(&mut object_server);
|
||||
}
|
||||
Err(err) => {
|
||||
@@ -139,8 +139,7 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
|
||||
ctrl.reload()
|
||||
.unwrap_or_else(|err| warn!("Profile control: {}", err));
|
||||
let tmp = Arc::new(Mutex::new(ctrl));
|
||||
DbusFanAndCpu::new(tmp.clone()).add_to_server(&mut object_server);
|
||||
tasks.push(tmp);
|
||||
DbusFanAndCpu::new(tmp).add_to_server(&mut object_server);
|
||||
};
|
||||
|
||||
if let Some(laptop) = laptop {
|
||||
@@ -152,6 +151,7 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
|
||||
)
|
||||
.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);
|
||||
@@ -178,10 +178,15 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
|
||||
}
|
||||
});
|
||||
|
||||
object_server.with(&"/org/asuslinux/Charge".try_into()?, |obj: &CtrlCharge| {
|
||||
let x = obj.limit();
|
||||
obj.notify_charge(x as u8)
|
||||
})?;
|
||||
object_server
|
||||
.with(&"/org/asuslinux/Charge".try_into()?, |obj: &CtrlCharge| {
|
||||
let x = obj.limit();
|
||||
obj.notify_charge(x as u8)
|
||||
})
|
||||
.map_err(|err| {
|
||||
warn!("object_server notify_charge error: {}", err);
|
||||
})
|
||||
.ok();
|
||||
|
||||
loop {
|
||||
if let Err(err) = object_server.try_handle_next() {
|
||||
@@ -1,8 +1,11 @@
|
||||
use intel_pstate::PStateError;
|
||||
use rog_fan_curve::CurveError;
|
||||
use rog_types::error::GraphicsError;
|
||||
use std::convert::From;
|
||||
use std::fmt;
|
||||
|
||||
use crate::ctrl_gfx::error::GfxError;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum RogError {
|
||||
ParseFanLevel,
|
||||
@@ -21,6 +24,10 @@ pub enum RogError {
|
||||
MissingFunction(String),
|
||||
MissingLedBrightNode(String, std::io::Error),
|
||||
ReloadFail(String),
|
||||
GfxSwitching(GfxError),
|
||||
Initramfs(String),
|
||||
Modprobe(String),
|
||||
Command(String, std::io::Error),
|
||||
}
|
||||
|
||||
impl fmt::Display for RogError {
|
||||
@@ -43,6 +50,10 @@ impl fmt::Display for RogError {
|
||||
RogError::MissingFunction(deets) => write!(f, "Missing functionality: {}", deets),
|
||||
RogError::MissingLedBrightNode(path, error) => write!(f, "Led node at {} is missing, please check you have the required patch or dkms module installed: {}", path, error),
|
||||
RogError::ReloadFail(deets) => write!(f, "Task error: {}", deets),
|
||||
RogError::GfxSwitching(deets) => write!(f, "Graphics switching error: {}", deets),
|
||||
RogError::Initramfs(detail) => write!(f, "Initiramfs error: {}", detail),
|
||||
RogError::Modprobe(detail) => write!(f, "Modprobe error: {}", detail),
|
||||
RogError::Command(func, error) => write!(f, "Command exec error: {}: {}", func, error),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -60,3 +71,11 @@ impl From<CurveError> for RogError {
|
||||
RogError::FanCurve(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<GraphicsError> for RogError {
|
||||
fn from(err: GraphicsError) -> Self {
|
||||
match err {
|
||||
GraphicsError::ParseVendor => RogError::GfxSwitching(GfxError::ParseVendor),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
use asus_nb::aura_modes::{AuraModes, BREATHING, STATIC, STROBE};
|
||||
use log::{info, warn};
|
||||
use rog_types::aura_modes::{AuraModes, BREATHING, STATIC};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::Read;
|
||||
@@ -8,6 +8,9 @@ pub static LEDMODE_CONFIG_PATH: &str = "/etc/asusd/asusd-ledmodes.toml";
|
||||
|
||||
pub static HELP_ADDRESS: &str = "https://gitlab.com/asus-linux/asus-nb-ctrl";
|
||||
|
||||
static LAPTOP_DEVICES: [u16; 4] = [0x1866, 0x1869, 0x1854, 0x19b6];
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct LaptopBase {
|
||||
usb_product: String,
|
||||
condev_iface: Option<String>, // required for finding the Consumer Device interface
|
||||
@@ -27,24 +30,24 @@ impl LaptopBase {
|
||||
}
|
||||
|
||||
pub fn match_laptop() -> Option<LaptopBase> {
|
||||
for device in rusb::devices().expect("Failed here").iter() {
|
||||
let device_desc = device.device_descriptor().expect("Failed there");
|
||||
for device in rusb::devices().expect("Couldn't get device").iter() {
|
||||
let device_desc = device
|
||||
.device_descriptor()
|
||||
.expect("Couldn't get device descriptor");
|
||||
if device_desc.vendor_id() == 0x0b05 {
|
||||
match device_desc.product_id() {
|
||||
0x1866 => {
|
||||
let laptop = select_1866_device("1866".to_owned());
|
||||
if LAPTOP_DEVICES.contains(&device_desc.product_id()) {
|
||||
let prod_str = format!("{:x?}", device_desc.product_id());
|
||||
|
||||
if device_desc.product_id() == 0x1854 {
|
||||
let mut laptop = laptop(prod_str, None);
|
||||
if laptop.supported_modes.is_empty() {
|
||||
laptop.supported_modes = vec![STATIC, BREATHING];
|
||||
}
|
||||
return Some(laptop);
|
||||
}
|
||||
0x1869 => return Some(select_1866_device("1869".to_owned())),
|
||||
0x1854 => {
|
||||
info!("Found GL753 or similar");
|
||||
return Some(LaptopBase {
|
||||
usb_product: "1854".to_string(),
|
||||
condev_iface: None,
|
||||
supported_modes: vec![STATIC, BREATHING, STROBE],
|
||||
});
|
||||
}
|
||||
_ => {}
|
||||
|
||||
let laptop = laptop(prod_str, Some("02".to_owned()));
|
||||
return Some(laptop);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -56,14 +59,14 @@ pub fn match_laptop() -> Option<LaptopBase> {
|
||||
None
|
||||
}
|
||||
|
||||
fn select_1866_device(prod: String) -> LaptopBase {
|
||||
fn laptop(prod: String, condev_iface: Option<String>) -> LaptopBase {
|
||||
let dmi = sysfs_class::DmiId::default();
|
||||
let board_name = dmi.board_name().expect("Could not get board_name");
|
||||
let prod_family = dmi.product_family().expect("Could not get product_family");
|
||||
|
||||
let mut laptop = LaptopBase {
|
||||
usb_product: prod,
|
||||
condev_iface: Some("02".to_owned()),
|
||||
condev_iface,
|
||||
supported_modes: vec![],
|
||||
};
|
||||
|
||||
@@ -1,15 +1,26 @@
|
||||
#![deny(unused_must_use)]
|
||||
/// Configuration loading, saving
|
||||
pub mod config;
|
||||
///
|
||||
pub(crate) mod config_old;
|
||||
/// Control of AniMe matrix display
|
||||
pub mod ctrl_anime;
|
||||
///
|
||||
/// Control of battery charge level
|
||||
pub mod ctrl_charge;
|
||||
/// Control CPU min/max freq and turbo, fan mode, fan curves
|
||||
///
|
||||
/// Intel machines can control:
|
||||
/// - CPU min/max frequency
|
||||
/// - CPU turbo enable/disable
|
||||
/// - Fan mode (normal, boost, silent)
|
||||
///
|
||||
/// AMD machines can control:
|
||||
/// - CPU turbo enable/disable
|
||||
/// - Fan mode (normal, boost, silent)
|
||||
/// - Fan min/max RPM curve
|
||||
pub mod ctrl_fan_cpu;
|
||||
///
|
||||
/// 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
|
||||
pub mod ctrl_rog_bios;
|
||||
@@ -17,7 +28,7 @@ pub mod ctrl_rog_bios;
|
||||
pub mod laptops;
|
||||
|
||||
/// Fetch all supported functions for the laptop
|
||||
pub mod supported;
|
||||
pub mod ctrl_supported;
|
||||
|
||||
mod error;
|
||||
|
||||
@@ -8,6 +8,16 @@ prod_family = "Zephyrus M"
|
||||
board_names = ["GU502GV"]
|
||||
led_modes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 255]
|
||||
|
||||
[[led_modes]]
|
||||
prod_family = "ROG Zephyrus M15"
|
||||
board_names = ["GU502LW"]
|
||||
led_modes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 255]
|
||||
|
||||
[[led_modes]]
|
||||
prod_family = "ROG Zephyrus M15"
|
||||
board_names = ["GU502LU"]
|
||||
led_modes = [0, 1, 2, 10]
|
||||
|
||||
[[led_modes]]
|
||||
prod_family = "Zephyrus"
|
||||
board_names = ["GM501GM", "GX531"]
|
||||
@@ -21,17 +31,17 @@ led_modes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 255]
|
||||
[[led_modes]]
|
||||
prod_family = "ROG Strix"
|
||||
board_names = ["GX531", "G512LV", "G712LV"]
|
||||
led_modes = [0, 1, 2, 3, 10, 13]
|
||||
led_modes = [0, 1, 2, 3, 10, 13, 14]
|
||||
|
||||
[[led_modes]]
|
||||
prod_family = "ROG Strix"
|
||||
board_names = ["G512LI", "G712LI"]
|
||||
board_names = ["G512LI", "G712LI", "G531GD"]
|
||||
led_modes = [0, 1, 2, 3, 10]
|
||||
|
||||
[[led_modes]]
|
||||
prod_family = "Strix"
|
||||
board_names = ["G731GV", "G731GW", "G531GV"]
|
||||
led_modes = [0, 1, 2, 3, 13]
|
||||
led_modes = [0, 1, 2, 3, 13, 14]
|
||||
|
||||
[[led_modes]]
|
||||
prod_family = "Strix"
|
||||
@@ -41,4 +51,9 @@ led_modes = [0, 1, 2, 3]
|
||||
[[led_modes]]
|
||||
prod_family = "Strix Scar"
|
||||
board_names = ["G531", "G731"]
|
||||
led_modes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 255]
|
||||
led_modes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 255]
|
||||
|
||||
[[led_modes]]
|
||||
prod_family = "ROG"
|
||||
board_names = ["GL553VE"]
|
||||
led_modes = [0, 1, 2, 13, 14]
|
||||
@@ -10,6 +10,10 @@
|
||||
<allow send_destination="org.asuslinux.Daemon"/>
|
||||
<allow receive_sender="org.asuslinux.Daemon"/>
|
||||
</policy>
|
||||
<policy group="users">
|
||||
<allow send_destination="org.asuslinux.Daemon"/>
|
||||
<allow receive_sender="org.asuslinux.Daemon"/>
|
||||
</policy>
|
||||
<policy group="wheel">
|
||||
<allow send_destination="org.asuslinux.Daemon"/>
|
||||
<allow receive_sender="org.asuslinux.Daemon"/>
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
ACTION=="add|change", SUBSYSTEM=="input", ENV{ID_VENDOR_ID}=="0b05", ENV{ID_MODEL_ID}=="18[0-9][0-9]", ENV{ID_TYPE}=="hid", TAG+="systemd", ENV{SYSTEMD_WANTS}="asusd.service"
|
||||
ACTION=="add|change", SUBSYSTEM=="input", ENV{ID_VENDOR_ID}=="0b05", ENV{ID_MODEL_ID}=="1[89][a-zA-Z0-9][a-zA-Z0-9]|193b", ENV{ID_TYPE}=="hid", TAG+="systemd", ENV{SYSTEMD_WANTS}="asusd.service"
|
||||
ACTION=="add|remove", SUBSYSTEM=="input", ENV{ID_VENDOR_ID}=="0b05", ENV{ID_MODEL_ID}=="1[89][a-zA-Z0-9][a-zA-Z0-9]|193b", RUN+="systemctl restart asusd.service"
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
Description=ASUS Notebook Control
|
||||
StartLimitInterval=200
|
||||
StartLimitBurst=2
|
||||
Before=display-manager.service
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/bin/asusd
|
||||
|
||||
18
rog-dbus/Cargo.toml
Normal file
@@ -0,0 +1,18 @@
|
||||
[package]
|
||||
name = "rog_dbus"
|
||||
version = "3.0.0"
|
||||
license = "MPL-2.0"
|
||||
readme = "README.md"
|
||||
authors = ["Luke <luke@ljones.dev>"]
|
||||
repository = "https://gitlab.com/asus-linux/asus-nb-ctrl"
|
||||
homepage = "https://gitlab.com/asus-linux/asus-nb-ctrl"
|
||||
description = "dbus interface methods for asusctl"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
serde_json = "^1.0"
|
||||
rog_types = { path = "../rog-types" }
|
||||
rog_fan_curve = { version = "^0.1", features = ["serde"] }
|
||||
zbus = "^1.8"
|
||||
zbus_macros = "^1.8"
|
||||
zvariant = "^2.4"
|
||||
168
rog-dbus/src/lib.rs
Normal file
@@ -0,0 +1,168 @@
|
||||
pub static DBUS_NAME: &str = "org.asuslinux.Daemon";
|
||||
pub static DBUS_PATH: &str = "/org/asuslinux/Daemon";
|
||||
pub static DBUS_IFACE: &str = "org.asuslinux.Daemon";
|
||||
pub const LED_MSG_LEN: usize = 17;
|
||||
|
||||
pub mod zbus_anime;
|
||||
pub mod zbus_charge;
|
||||
pub mod zbus_gfx;
|
||||
pub mod zbus_led;
|
||||
pub mod zbus_profile;
|
||||
pub mod zbus_rogbios;
|
||||
pub mod zbus_supported;
|
||||
|
||||
use rog_types::aura_modes::AuraModes;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use zbus::{Connection, Result, SignalReceiver};
|
||||
|
||||
pub static VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
pub struct DbusProxies<'a> {
|
||||
anime: zbus_anime::AnimeProxy<'a>,
|
||||
charge: zbus_charge::ChargeProxy<'a>,
|
||||
gfx: zbus_gfx::GfxProxy<'a>,
|
||||
led: zbus_led::LedProxy<'a>,
|
||||
profile: zbus_profile::ProfileProxy<'a>,
|
||||
rog_bios: zbus_rogbios::RogBiosProxy<'a>,
|
||||
supported: zbus_supported::SupportProxy<'a>,
|
||||
}
|
||||
|
||||
impl<'a> DbusProxies<'a> {
|
||||
#[inline]
|
||||
pub fn new() -> Result<(Self, Connection)> {
|
||||
let conn = Connection::new_system()?;
|
||||
|
||||
Ok((
|
||||
DbusProxies {
|
||||
anime: zbus_anime::AnimeProxy::new(&conn)?,
|
||||
led: zbus_led::LedProxy::new(&conn)?,
|
||||
charge: zbus_charge::ChargeProxy::new(&conn)?,
|
||||
gfx: zbus_gfx::GfxProxy::new(&conn)?,
|
||||
profile: zbus_profile::ProfileProxy::new(&conn)?,
|
||||
rog_bios: zbus_rogbios::RogBiosProxy::new(&conn)?,
|
||||
supported: zbus_supported::SupportProxy::new(&conn)?,
|
||||
},
|
||||
conn,
|
||||
))
|
||||
}
|
||||
|
||||
pub fn setup_recv(&'a self, conn: Connection) -> SignalReceiver {
|
||||
let mut recv = SignalReceiver::new(conn);
|
||||
//recv.receive_for(&self.proxy_anime);
|
||||
recv.receive_for(self.led.proxy());
|
||||
recv.receive_for(self.charge.proxy());
|
||||
recv.receive_for(self.gfx.proxy());
|
||||
recv.receive_for(self.profile.proxy());
|
||||
recv
|
||||
}
|
||||
|
||||
pub fn anime(&self) -> &zbus_anime::AnimeProxy<'a> {
|
||||
&self.anime
|
||||
}
|
||||
|
||||
pub fn charge(&self) -> &zbus_charge::ChargeProxy<'a> {
|
||||
&self.charge
|
||||
}
|
||||
|
||||
pub fn gfx(&self) -> &zbus_gfx::GfxProxy<'a> {
|
||||
&self.gfx
|
||||
}
|
||||
|
||||
pub fn led(&self) -> &zbus_led::LedProxy<'a> {
|
||||
&self.led
|
||||
}
|
||||
|
||||
pub fn profile(&self) -> &zbus_profile::ProfileProxy<'a> {
|
||||
&self.profile
|
||||
}
|
||||
|
||||
pub fn rog_bios(&self) -> &zbus_rogbios::RogBiosProxy<'a> {
|
||||
&self.rog_bios
|
||||
}
|
||||
|
||||
pub fn supported(&self) -> &zbus_supported::SupportProxy<'a> {
|
||||
&self.supported
|
||||
}
|
||||
}
|
||||
|
||||
// Signals separated out
|
||||
pub struct Signals {
|
||||
pub gfx_vendor: Arc<Mutex<Option<String>>>,
|
||||
pub gfx_action: Arc<Mutex<Option<String>>>,
|
||||
pub profile: Arc<Mutex<Option<String>>>,
|
||||
pub led_mode: Arc<Mutex<Option<AuraModes>>>,
|
||||
pub charge: Arc<Mutex<Option<u8>>>,
|
||||
}
|
||||
|
||||
impl Signals {
|
||||
#[inline]
|
||||
pub fn new(proxies: &DbusProxies) -> Result<Self> {
|
||||
//
|
||||
let charge_signal = Arc::new(Mutex::new(None));
|
||||
proxies
|
||||
.charge
|
||||
.connect_notify_charge(charge_signal.clone())?;
|
||||
|
||||
//
|
||||
let ledmode_signal = Arc::new(Mutex::new(None));
|
||||
proxies.led.connect_notify_led(ledmode_signal.clone())?;
|
||||
|
||||
let gfx_action_signal = Arc::new(Mutex::new(None));
|
||||
proxies
|
||||
.gfx
|
||||
.connect_notify_action(gfx_action_signal.clone())?;
|
||||
|
||||
let gfx_vendor_signal = Arc::new(Mutex::new(None));
|
||||
proxies.gfx.connect_notify_gfx(gfx_vendor_signal.clone())?;
|
||||
|
||||
let profile_signal = Arc::new(Mutex::new(None));
|
||||
proxies
|
||||
.profile
|
||||
.connect_notify_profile(profile_signal.clone())?;
|
||||
|
||||
Ok(Signals {
|
||||
gfx_vendor: gfx_vendor_signal,
|
||||
gfx_action: gfx_action_signal,
|
||||
profile: profile_signal,
|
||||
led_mode: ledmode_signal,
|
||||
charge: charge_signal,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// This is the main way to communicate with the DBUS interface
|
||||
pub struct AuraDbusClient<'a> {
|
||||
proxies: DbusProxies<'a>,
|
||||
signals: Signals,
|
||||
}
|
||||
|
||||
impl<'a> AuraDbusClient<'a> {
|
||||
#[inline]
|
||||
pub fn new() -> Result<(Self, Connection)> {
|
||||
let (proxies, conn) = DbusProxies::new()?;
|
||||
let signals = Signals::new(&proxies)?;
|
||||
|
||||
Ok((AuraDbusClient { proxies, signals }, conn))
|
||||
}
|
||||
|
||||
pub fn proxies(&self) -> &DbusProxies {
|
||||
&self.proxies
|
||||
}
|
||||
|
||||
/*
|
||||
* GFX
|
||||
*/
|
||||
pub fn gfx_wait_changed(&self) -> Result<String> {
|
||||
loop {
|
||||
if let Ok(res) = self.proxies.gfx.proxy().next_signal() {
|
||||
if res.is_none() {
|
||||
if let Ok(lock) = self.signals.gfx_action.lock() {
|
||||
if let Some(stuff) = lock.as_ref() {
|
||||
return Ok(stuff.to_string());
|
||||
}
|
||||
}
|
||||
// return Ok("Failed for unknown reason".to_owned());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
74
rog-dbus/src/zbus_anime.rs
Normal file
@@ -0,0 +1,74 @@
|
||||
//! # 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 system bus`.
|
||||
//!
|
||||
//! You may prefer to adapt it, instead of using it verbatim.
|
||||
//!
|
||||
//! More information can be found in the
|
||||
//! [Writing a client proxy](https://zeenix.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::IntrospectableProxy`]
|
||||
//! * [`zbus::fdo::PeerProxy`]
|
||||
//! * [`zbus::fdo::PropertiesProxy`]
|
||||
//!
|
||||
//! …consequently `zbus-xmlgen` did not generate code for the above interfaces.
|
||||
|
||||
use rog_types::anime_matrix::{AniMeDataBuffer, AniMeImageBuffer};
|
||||
use zbus::{dbus_proxy, Connection, Result};
|
||||
|
||||
#[dbus_proxy(
|
||||
interface = "org.asuslinux.Daemon",
|
||||
default_path = "/org/asuslinux/Anime"
|
||||
)]
|
||||
trait Daemon {
|
||||
/// SetBootOnOff method
|
||||
fn set_boot_on_off(&self, status: bool) -> zbus::Result<()>;
|
||||
|
||||
/// SetOnOff method
|
||||
fn set_on_off(&self, status: bool) -> zbus::Result<()>;
|
||||
|
||||
/// WriteDirect method
|
||||
fn write_direct(&self, input: &[u8]) -> zbus::Result<()>;
|
||||
|
||||
/// WriteImage method
|
||||
fn write_image(&self, input: &[Vec<u8>]) -> zbus::Result<()>;
|
||||
}
|
||||
|
||||
pub struct AnimeProxy<'a>(DaemonProxy<'a>);
|
||||
|
||||
impl<'a> AnimeProxy<'a> {
|
||||
#[inline]
|
||||
pub fn new(conn: &Connection) -> Result<Self> {
|
||||
Ok(AnimeProxy(DaemonProxy::new(&conn)?))
|
||||
}
|
||||
|
||||
pub fn proxy(&self) -> &DaemonProxy<'a> {
|
||||
&self.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn toggle_boot_on(&self, on: bool) -> Result<()> {
|
||||
self.0.set_boot_on_off(on)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn toggle_on(&self, on: bool) -> Result<()> {
|
||||
self.0.set_on_off(on)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn write_direct(&self, input: AniMeDataBuffer) -> Result<()> {
|
||||
self.0.write_direct(input.get())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn write_image(&self, input: AniMeImageBuffer) -> Result<()> {
|
||||
self.0.write_image(input.get())
|
||||
}
|
||||
}
|
||||
73
rog-dbus/src/zbus_charge.rs
Normal file
@@ -0,0 +1,73 @@
|
||||
//! # 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/Charge' from service 'org.asuslinux.Daemon' on system bus`.
|
||||
//!
|
||||
//! You may prefer to adapt it, instead of using it verbatim.
|
||||
//!
|
||||
//! More information can be found in the
|
||||
//! [Writing a client proxy](https://zeenix.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::PropertiesProxy`]
|
||||
//! * [`zbus::fdo::PeerProxy`]
|
||||
//! * [`zbus::fdo::IntrospectableProxy`]
|
||||
//!
|
||||
//! …consequently `zbus-xmlgen` did not generate code for the above interfaces.
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use zbus::{dbus_proxy, Connection, Result};
|
||||
|
||||
#[dbus_proxy(
|
||||
interface = "org.asuslinux.Daemon",
|
||||
default_path = "/org/asuslinux/Charge"
|
||||
)]
|
||||
trait Daemon {
|
||||
/// Limit method
|
||||
fn limit(&self) -> zbus::Result<i16>;
|
||||
|
||||
/// SetLimit method
|
||||
fn set_limit(&self, limit: u8) -> zbus::Result<()>;
|
||||
|
||||
/// NotifyCharge signal
|
||||
#[dbus_proxy(signal)]
|
||||
fn notify_charge(&self, limit: u8) -> zbus::Result<()>;
|
||||
}
|
||||
|
||||
pub struct ChargeProxy<'a>(DaemonProxy<'a>);
|
||||
|
||||
impl<'a> ChargeProxy<'a> {
|
||||
#[inline]
|
||||
pub fn new(conn: &Connection) -> Result<Self> {
|
||||
Ok(ChargeProxy(DaemonProxy::new(&conn)?))
|
||||
}
|
||||
|
||||
pub fn proxy(&self) -> &DaemonProxy<'a> {
|
||||
&self.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn write_limit(&self, level: u8) -> Result<()> {
|
||||
self.0.set_limit(level)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_limit(&self) -> Result<i16> {
|
||||
self.0.limit()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn connect_notify_charge(&self, charge: Arc<Mutex<Option<u8>>>) -> zbus::fdo::Result<()> {
|
||||
self.0.connect_notify_charge(move |data| {
|
||||
if let Ok(mut lock) = charge.lock() {
|
||||
*lock = Some(data);
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
98
rog-dbus/src/zbus_gfx.rs
Normal file
@@ -0,0 +1,98 @@
|
||||
//! # DBus interface proxy for: `org.asuslinux.Gfx`
|
||||
//!
|
||||
//! This code was generated by `zbus-xmlgen` `1.0.0` from DBus introspection data.
|
||||
//! Source: `Interface '/org/asuslinux/Gfx' from service 'org.asuslinux.Daemon' on system bus`.
|
||||
//!
|
||||
//! You may prefer to adapt it, instead of using it verbatim.
|
||||
//!
|
||||
//! More information can be found in the
|
||||
//! [Writing a client proxy](https://zeenix.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::PropertiesProxy`]
|
||||
//! * [`zbus::fdo::IntrospectableProxy`]
|
||||
//! * [`zbus::fdo::PeerProxy`]
|
||||
//!
|
||||
//! …consequently `zbus-xmlgen` did not generate code for the above interfaces.
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use zbus::{dbus_proxy, Connection, Result};
|
||||
|
||||
#[dbus_proxy(
|
||||
interface = "org.asuslinux.Daemon",
|
||||
default_path = "/org/asuslinux/Gfx"
|
||||
)]
|
||||
trait Daemon {
|
||||
/// Power method
|
||||
fn power(&self) -> zbus::Result<String>;
|
||||
|
||||
/// SetVendor method
|
||||
fn set_vendor(&self, vendor: &str) -> zbus::Result<()>;
|
||||
|
||||
/// Vendor method
|
||||
fn vendor(&self) -> zbus::Result<String>;
|
||||
|
||||
/// NotifyAction signal
|
||||
#[dbus_proxy(signal)]
|
||||
fn notify_action(&self, action: &str) -> zbus::Result<()>;
|
||||
|
||||
/// NotifyGfx signal
|
||||
#[dbus_proxy(signal)]
|
||||
fn notify_gfx(&self, vendor: &str) -> zbus::Result<()>;
|
||||
}
|
||||
|
||||
pub struct GfxProxy<'a>(DaemonProxy<'a>);
|
||||
|
||||
impl<'a> GfxProxy<'a> {
|
||||
#[inline]
|
||||
pub fn new(conn: &Connection) -> Result<Self> {
|
||||
Ok(GfxProxy(DaemonProxy::new(&conn)?))
|
||||
}
|
||||
|
||||
pub fn proxy(&self) -> &DaemonProxy<'a> {
|
||||
&self.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn gfx_get_pwr(&self) -> Result<String> {
|
||||
self.0.power()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn gfx_get_mode(&self) -> Result<String> {
|
||||
self.0.vendor()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn gfx_write_mode(&self, vendor: &str) -> Result<()> {
|
||||
self.0.set_vendor(vendor)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn connect_notify_action(
|
||||
&self,
|
||||
action: Arc<Mutex<Option<String>>>,
|
||||
) -> zbus::fdo::Result<()> {
|
||||
self.0.connect_notify_action(move |data| {
|
||||
if let Ok(mut lock) = action.lock() {
|
||||
*lock = Some(data.to_owned());
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn connect_notify_gfx(&self, vendor: Arc<Mutex<Option<String>>>) -> zbus::fdo::Result<()> {
|
||||
self.0.connect_notify_gfx(move |data| {
|
||||
if let Ok(mut lock) = vendor.lock() {
|
||||
*lock = Some(data.to_owned());
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
142
rog-dbus/src/zbus_led.rs
Normal file
@@ -0,0 +1,142 @@
|
||||
//! # 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/Led' from service 'org.asuslinux.Daemon' on system bus`.
|
||||
//!
|
||||
//! You may prefer to adapt it, instead of using it verbatim.
|
||||
//!
|
||||
//! More information can be found in the
|
||||
//! [Writing a client proxy](https://zeenix.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 std::sync::{Arc, Mutex};
|
||||
|
||||
use zbus::{dbus_proxy, Connection, Result};
|
||||
|
||||
use rog_types::{aura_modes::AuraModes, cli_options::LedBrightness, fancy::KeyColourArray};
|
||||
|
||||
const BLOCKING_TIME: u64 = 40; // 100ms = 10 FPS, max 50ms = 20 FPS, 40ms = 25 FPS
|
||||
|
||||
#[dbus_proxy(
|
||||
interface = "org.asuslinux.Daemon",
|
||||
default_path = "/org/asuslinux/Led"
|
||||
)]
|
||||
trait Daemon {
|
||||
/// LedBrightness method
|
||||
fn led_brightness(&self) -> zbus::Result<i16>;
|
||||
|
||||
/// LedMode method
|
||||
fn led_mode(&self) -> zbus::Result<String>;
|
||||
|
||||
/// LedModes method
|
||||
fn led_modes(&self) -> zbus::Result<String>;
|
||||
|
||||
/// NextLedMode method
|
||||
fn next_led_mode(&self) -> zbus::Result<()>;
|
||||
|
||||
/// PrevLedMode method
|
||||
fn prev_led_mode(&self) -> zbus::Result<()>;
|
||||
|
||||
/// SetLedMode method
|
||||
fn set_led_mode(&self, data: &str) -> zbus::Result<()>;
|
||||
|
||||
/// NotifyLed signal
|
||||
#[dbus_proxy(signal)]
|
||||
fn notify_led(&self, data: &str) -> zbus::Result<()>;
|
||||
}
|
||||
|
||||
pub struct LedProxy<'a>(DaemonProxy<'a>);
|
||||
|
||||
impl<'a> LedProxy<'a> {
|
||||
#[inline]
|
||||
pub fn new(conn: &Connection) -> Result<Self> {
|
||||
Ok(LedProxy(DaemonProxy::new(&conn)?))
|
||||
}
|
||||
|
||||
pub fn proxy(&self) -> &DaemonProxy<'a> {
|
||||
&self.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_led_brightness(&self) -> Result<LedBrightness> {
|
||||
match self.0.led_brightness()? {
|
||||
-1 => Ok(LedBrightness::new(None)),
|
||||
level => Ok(LedBrightness::new(Some(level as u8))),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_brightness(&self, level: u8) -> Result<()> {
|
||||
self.set_led_mode(&AuraModes::LedBrightness(level))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn next_led_mode(&self) -> Result<()> {
|
||||
self.0.next_led_mode()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn prev_led_mode(&self) -> Result<()> {
|
||||
self.0.prev_led_mode()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_led_mode(&self, mode: &AuraModes) -> Result<()> {
|
||||
self.0.set_led_mode(&serde_json::to_string(mode).unwrap())
|
||||
}
|
||||
|
||||
/// Write a single colour block.
|
||||
///
|
||||
/// Intentionally blocks for 10ms after sending to allow the block to
|
||||
/// be written to the keyboard EC. This should not be async.
|
||||
#[inline]
|
||||
pub fn set_per_key(&self, key_colour_array: &KeyColourArray) -> Result<()> {
|
||||
let group = key_colour_array.get();
|
||||
let mut vecs = Vec::with_capacity(group.len());
|
||||
for v in group {
|
||||
vecs.push(v.to_vec());
|
||||
}
|
||||
let mode = AuraModes::PerKey(vecs);
|
||||
|
||||
self.set_led_mode(&mode)?;
|
||||
|
||||
std::thread::sleep(std::time::Duration::from_millis(BLOCKING_TIME));
|
||||
|
||||
// if self.stop.load(Ordering::Relaxed) {
|
||||
// println!("Keyboard backlight was changed, exiting");
|
||||
// std::process::exit(1)
|
||||
// }
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// This method must always be called before the very first write to initialise
|
||||
/// the keyboard LED EC in the correct mode
|
||||
#[inline]
|
||||
pub fn init_effect(&self) -> Result<()> {
|
||||
let mode = AuraModes::PerKey(vec![vec![]]);
|
||||
self.0.set_led_mode(&serde_json::to_string(&mode).unwrap())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn connect_notify_led(&self, led: Arc<Mutex<Option<AuraModes>>>) -> zbus::fdo::Result<()> {
|
||||
self.0.connect_notify_led(move |data| {
|
||||
if let Ok(mut lock) = led.lock() {
|
||||
if let Ok(dat) = serde_json::from_str(&data) {
|
||||
*lock = Some(dat);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
97
rog-dbus/src/zbus_profile.rs
Normal file
@@ -0,0 +1,97 @@
|
||||
//! # 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/Profile' from service 'org.asuslinux.Daemon' on system bus`.
|
||||
//!
|
||||
//! You may prefer to adapt it, instead of using it verbatim.
|
||||
//!
|
||||
//! More information can be found in the
|
||||
//! [Writing a client proxy](https://zeenix.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::IntrospectableProxy`]
|
||||
//! * [`zbus::fdo::PeerProxy`]
|
||||
//! * [`zbus::fdo::PropertiesProxy`]
|
||||
//!
|
||||
//! …consequently `zbus-xmlgen` did not generate code for the above interfaces.
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use rog_types::profile::ProfileEvent;
|
||||
use zbus::{dbus_proxy, Connection, Result};
|
||||
|
||||
#[dbus_proxy(
|
||||
interface = "org.asuslinux.Daemon",
|
||||
default_path = "/org/asuslinux/Profile"
|
||||
)]
|
||||
trait Daemon {
|
||||
/// ActiveProfileName method
|
||||
fn active_profile_name(&self) -> zbus::Result<String>;
|
||||
|
||||
/// NextProfile method
|
||||
fn next_profile(&self) -> zbus::Result<()>;
|
||||
|
||||
/// Profile method
|
||||
fn profile(&self) -> zbus::Result<String>;
|
||||
|
||||
/// Profiles method
|
||||
fn profiles(&self) -> zbus::Result<String>;
|
||||
|
||||
/// SetProfile method
|
||||
fn set_profile(&self, profile: &str) -> zbus::Result<()>;
|
||||
|
||||
/// NotifyProfile signal
|
||||
#[dbus_proxy(signal)]
|
||||
fn notify_profile(&self, profile: &str) -> zbus::Result<()>;
|
||||
}
|
||||
|
||||
pub struct ProfileProxy<'a>(DaemonProxy<'a>);
|
||||
|
||||
impl<'a> ProfileProxy<'a> {
|
||||
#[inline]
|
||||
pub fn new(conn: &Connection) -> Result<Self> {
|
||||
Ok(ProfileProxy(DaemonProxy::new(&conn)?))
|
||||
}
|
||||
|
||||
pub fn proxy(&self) -> &DaemonProxy<'a> {
|
||||
&self.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn active_profile_name(&self) -> Result<String> {
|
||||
self.0.active_profile_name()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn next_fan(&self) -> Result<()> {
|
||||
self.0.next_profile()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn write_fan_mode(&self, level: u8) -> Result<()> {
|
||||
self.0
|
||||
.set_profile(&serde_json::to_string(&ProfileEvent::ChangeMode(level)).unwrap())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn write_command(&self, cmd: &ProfileEvent) -> Result<()> {
|
||||
self.0.set_profile(&serde_json::to_string(cmd).unwrap())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn connect_notify_profile(
|
||||
&self,
|
||||
charge: Arc<Mutex<Option<String>>>,
|
||||
) -> zbus::fdo::Result<()> {
|
||||
self.0.connect_notify_profile(move |data| {
|
||||
if let Ok(mut lock) = charge.lock() {
|
||||
*lock = Some(data.to_owned());
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
109
rog-dbus/src/zbus_rogbios.rs
Normal file
@@ -0,0 +1,109 @@
|
||||
//! # 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/RogBios' from service 'org.asuslinux.Daemon' on system bus`.
|
||||
//!
|
||||
//! You may prefer to adapt it, instead of using it verbatim.
|
||||
//!
|
||||
//! More information can be found in the
|
||||
//! [Writing a client proxy](https://zeenix.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::PropertiesProxy`]
|
||||
//! * [`zbus::fdo::PeerProxy`]
|
||||
//! * [`zbus::fdo::IntrospectableProxy`]
|
||||
//!
|
||||
//! …consequently `zbus-xmlgen` did not generate code for the above interfaces.
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use zbus::{dbus_proxy, Connection, Result};
|
||||
|
||||
#[dbus_proxy(
|
||||
interface = "org.asuslinux.Daemon",
|
||||
default_path = "/org/asuslinux/RogBios"
|
||||
)]
|
||||
trait Daemon {
|
||||
/// DedicatedGraphicMode method
|
||||
fn dedicated_graphic_mode(&self) -> zbus::Result<i16>;
|
||||
|
||||
/// PostBootSound method
|
||||
fn post_boot_sound(&self) -> zbus::Result<i16>;
|
||||
|
||||
/// SetDedicatedGraphicMode method
|
||||
fn set_dedicated_graphic_mode(&self, dedicated: bool) -> zbus::Result<()>;
|
||||
|
||||
/// SetPostBootSound method
|
||||
fn set_post_boot_sound(&self, on: bool) -> zbus::Result<()>;
|
||||
|
||||
/// NotifyDedicatedGraphicMode signal
|
||||
#[dbus_proxy(signal)]
|
||||
fn notify_dedicated_graphic_mode(&self, dedicated: bool) -> zbus::Result<()>;
|
||||
|
||||
/// NotifyPostBootSound signal
|
||||
#[dbus_proxy(signal)]
|
||||
fn notify_post_boot_sound(&self, dedicated: bool) -> zbus::Result<()>;
|
||||
}
|
||||
|
||||
pub struct RogBiosProxy<'a>(DaemonProxy<'a>);
|
||||
|
||||
impl<'a> RogBiosProxy<'a> {
|
||||
#[inline]
|
||||
pub fn new(conn: &Connection) -> Result<Self> {
|
||||
Ok(RogBiosProxy(DaemonProxy::new(&conn)?))
|
||||
}
|
||||
|
||||
pub fn proxy(&self) -> &DaemonProxy<'a> {
|
||||
&self.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_dedicated_gfx(&self) -> Result<i16> {
|
||||
self.0.dedicated_graphic_mode()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_dedicated_gfx(&self, on: bool) -> Result<()> {
|
||||
self.0.set_dedicated_graphic_mode(on)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_post_sound(&self) -> Result<i16> {
|
||||
self.0.post_boot_sound()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_post_sound(&self, on: bool) -> Result<()> {
|
||||
self.0.set_post_boot_sound(on)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn connect_notify_dedicated_graphic_mode(
|
||||
&self,
|
||||
dedicated: Arc<Mutex<Option<bool>>>,
|
||||
) -> zbus::fdo::Result<()> {
|
||||
self.0.connect_notify_dedicated_graphic_mode(move |data| {
|
||||
if let Ok(mut lock) = dedicated.lock() {
|
||||
*lock = Some(data);
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn connect_notify_post_boot_sound(
|
||||
&self,
|
||||
sound: Arc<Mutex<Option<bool>>>,
|
||||
) -> zbus::fdo::Result<()> {
|
||||
self.0.connect_notify_post_boot_sound(move |data| {
|
||||
if let Ok(mut lock) = sound.lock() {
|
||||
*lock = Some(data);
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
49
rog-dbus/src/zbus_supported.rs
Normal file
@@ -0,0 +1,49 @@
|
||||
//! # 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/Supported' from service 'org.asuslinux.Daemon' on system bus`.
|
||||
//!
|
||||
//! You may prefer to adapt it, instead of using it verbatim.
|
||||
//!
|
||||
//! More information can be found in the
|
||||
//! [Writing a client proxy](https://zeenix.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::PropertiesProxy`]
|
||||
//! * [`zbus::fdo::IntrospectableProxy`]
|
||||
//!
|
||||
//! …consequently `zbus-xmlgen` did not generate code for the above interfaces.
|
||||
|
||||
use zbus::{dbus_proxy, Connection, Result};
|
||||
|
||||
#[dbus_proxy(
|
||||
interface = "org.asuslinux.Daemon",
|
||||
default_path = "/org/asuslinux/Supported"
|
||||
)]
|
||||
trait Daemon {
|
||||
/// SupportedFunctions method
|
||||
fn supported_functions(&self) -> zbus::Result<String>;
|
||||
}
|
||||
|
||||
pub struct SupportProxy<'a>(DaemonProxy<'a>);
|
||||
|
||||
impl<'a> SupportProxy<'a> {
|
||||
#[inline]
|
||||
pub fn new(conn: &Connection) -> Result<Self> {
|
||||
Ok(SupportProxy(DaemonProxy::new(&conn)?))
|
||||
}
|
||||
|
||||
pub fn proxy(&self) -> &DaemonProxy<'a> {
|
||||
&self.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_supported_functions(&self) -> Result<String> {
|
||||
self.0.supported_functions()
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "asus-nb"
|
||||
version = "2.2.0"
|
||||
name = "rog_types"
|
||||
version = "3.0.0"
|
||||
license = "MPL-2.0"
|
||||
readme = "README.md"
|
||||
authors = ["Luke <luke@ljones.dev>"]
|
||||
@@ -11,14 +11,8 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
gumdrop = "^0.8"
|
||||
dbus = { version = "^0.8" }
|
||||
serde = "^1.0"
|
||||
serde_derive = "^1.0"
|
||||
serde_json = "^1.0"
|
||||
yansi-term = "^0.1"
|
||||
rog_fan_curve = { version = "0.1", features = ["serde"] }
|
||||
zbus = "^1.8.0"
|
||||
zvariant = "^2.4.0"
|
||||
|
||||
[dev-dependencies]
|
||||
tinybmp = "^0.2.3"
|
||||
rog_fan_curve = { version = "^0.1", features = ["serde"] }
|
||||
zvariant = "^2.5"
|
||||
zvariant_derive = "^2.5"
|
||||
@@ -1,32 +1,76 @@
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use zvariant_derive::Type;
|
||||
|
||||
pub const WIDTH: usize = 34; // Width is definitely 34 items
|
||||
pub const HEIGHT: usize = 56;
|
||||
pub type AniMeBufferType = [[u8; WIDTH]; HEIGHT];
|
||||
pub type AniMePacketType = [[u8; 640]; 2];
|
||||
const BLOCK_START: usize = 7;
|
||||
/// *Not* inclusive, the byte before this is the final for each "pane"
|
||||
const BLOCK_END: usize = 634;
|
||||
use yansi_term::Colour::RGB;
|
||||
pub const PANE_LEN: usize = BLOCK_END - BLOCK_START;
|
||||
/// The length of usable data
|
||||
pub const FULL_PANE_LEN: usize = PANE_LEN * 2;
|
||||
|
||||
/// Helper structure for writing images.
|
||||
///
|
||||
/// See the examples for ways to write an image to `AniMeMatrix` format.
|
||||
pub struct AniMeMatrix(AniMeBufferType);
|
||||
pub const ANIME_PANE1_PREFIX: [u8; 7] = [0x5e, 0xc0, 0x02, 0x01, 0x00, 0x73, 0x02];
|
||||
pub const ANIME_PANE2_PREFIX: [u8; 7] = [0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02];
|
||||
|
||||
impl Default for AniMeMatrix {
|
||||
#[derive(Debug, Deserialize, Serialize, Type)]
|
||||
pub struct AniMeDataBuffer(Vec<u8>);
|
||||
|
||||
impl Default for AniMeDataBuffer {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl AniMeMatrix {
|
||||
impl AniMeDataBuffer {
|
||||
pub fn new() -> Self {
|
||||
AniMeMatrix([[0u8; WIDTH]; HEIGHT])
|
||||
AniMeDataBuffer(vec![0u8; FULL_PANE_LEN])
|
||||
}
|
||||
|
||||
pub fn get(&self) -> &AniMeBufferType {
|
||||
pub fn get(&self) -> &[u8] {
|
||||
&self.0
|
||||
}
|
||||
|
||||
pub fn get_mut(&mut self) -> &mut AniMeBufferType {
|
||||
pub fn set(&mut self, input: [u8; FULL_PANE_LEN]) {
|
||||
self.0 = input.to_vec();
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AniMeDataBuffer> for AniMePacketType {
|
||||
#[inline]
|
||||
fn from(anime: AniMeDataBuffer) -> Self {
|
||||
assert!(anime.0.len() == FULL_PANE_LEN);
|
||||
let mut buffers = [[0; 640]; 2];
|
||||
for (idx, chunk) in anime.0.as_slice().chunks(PANE_LEN).enumerate() {
|
||||
buffers[idx][BLOCK_START..BLOCK_END].copy_from_slice(chunk);
|
||||
}
|
||||
buffers
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper structure for writing images.
|
||||
///
|
||||
/// See the examples for ways to write an image to `AniMeMatrix` format.
|
||||
#[derive(Debug, Deserialize, Serialize, Type)]
|
||||
pub struct AniMeImageBuffer(Vec<Vec<u8>>);
|
||||
|
||||
impl Default for AniMeImageBuffer {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl AniMeImageBuffer {
|
||||
pub fn new() -> Self {
|
||||
AniMeImageBuffer(vec![vec![0u8; WIDTH]; HEIGHT])
|
||||
}
|
||||
|
||||
pub fn get(&self) -> &Vec<Vec<u8>> {
|
||||
&self.0
|
||||
}
|
||||
|
||||
pub fn get_mut(&mut self) -> &mut Vec<Vec<u8>> {
|
||||
&mut self.0
|
||||
}
|
||||
|
||||
@@ -55,8 +99,8 @@ impl AniMeMatrix {
|
||||
} else {
|
||||
row.iter()
|
||||
};
|
||||
for x in tmp {
|
||||
print!(" {}", RGB(*x, *x, *x).paint("XY"));
|
||||
for _ in tmp {
|
||||
print!(" XY");
|
||||
}
|
||||
|
||||
println!();
|
||||
@@ -78,9 +122,9 @@ impl AniMeMatrix {
|
||||
if count % 2 == 0 {
|
||||
print!(" ");
|
||||
}
|
||||
for (i, x) in row.iter().enumerate() {
|
||||
for (i, _) in row.iter().enumerate() {
|
||||
if i >= index {
|
||||
print!(" {}", RGB(*x, *x, *x).paint("XY"));
|
||||
print!(" XY");
|
||||
} else {
|
||||
print!(" ");
|
||||
}
|
||||
@@ -91,11 +135,11 @@ impl AniMeMatrix {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AniMeMatrix> for AniMePacketType {
|
||||
impl From<AniMeImageBuffer> for AniMePacketType {
|
||||
/// Do conversion from the nested Vec in AniMeMatrix to the two required
|
||||
/// packets suitable for sending over USB
|
||||
#[inline]
|
||||
fn from(anime: AniMeMatrix) -> Self {
|
||||
fn from(anime: AniMeImageBuffer) -> Self {
|
||||
let mut buffers = [[0; 640]; 2];
|
||||
|
||||
let mut write_index = BLOCK_START;
|
||||
@@ -153,15 +197,26 @@ impl From<AniMeMatrix> for AniMePacketType {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::anime_matrix::{AniMeMatrix, AniMePacketType};
|
||||
use crate::anime_matrix::*;
|
||||
|
||||
use super::AniMeDataBuffer;
|
||||
|
||||
#[test]
|
||||
fn check_from_data_buffer() {
|
||||
let mut data = AniMeDataBuffer::new();
|
||||
data.set([42u8; FULL_PANE_LEN]);
|
||||
|
||||
let out: AniMePacketType = data.into();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_data_alignment() {
|
||||
let mut matrix = AniMeMatrix::new();
|
||||
let mut matrix = AniMeImageBuffer::new();
|
||||
{
|
||||
let tmp = matrix.get_mut();
|
||||
for row in tmp.iter_mut() {
|
||||
row[row.len() - 1] = 0xff;
|
||||
let idx = row.len() - 1;
|
||||
row[idx] = 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
use crate::cli_options;
|
||||
use crate::cli_options::SetAuraBuiltin;
|
||||
use crate::error::AuraError;
|
||||
use gumdrop::Options;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::str::FromStr;
|
||||
|
||||
pub const STATIC: u8 = 0x00;
|
||||
pub const BREATHING: u8 = 0x01;
|
||||
@@ -15,41 +17,56 @@ pub const PULSE: u8 = 0x0a;
|
||||
pub const COMET: u8 = 0x0b;
|
||||
pub const FLASH: u8 = 0x0c;
|
||||
pub const MULTISTATIC: u8 = 0x0d;
|
||||
pub const MULTIBREATHE: u8 = 0x0e;
|
||||
pub const PER_KEY: u8 = 0xff;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct Colour(pub u8, pub u8, pub u8);
|
||||
impl From<cli_options::Colour> for Colour {
|
||||
fn from(c: cli_options::Colour) -> Self {
|
||||
Colour(c.0, c.1, c.2)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Colour {
|
||||
fn default() -> Self {
|
||||
Colour(128, 0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Colour {
|
||||
type Err = AuraError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
if s.len() < 6 {
|
||||
return Err(AuraError::ParseColour);
|
||||
}
|
||||
let r = u8::from_str_radix(&s[0..2], 16).or(Err(AuraError::ParseColour))?;
|
||||
let g = u8::from_str_radix(&s[2..4], 16).or(Err(AuraError::ParseColour))?;
|
||||
let b = u8::from_str_radix(&s[4..6], 16).or(Err(AuraError::ParseColour))?;
|
||||
Ok(Colour(r, g, b))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Deserialize, Serialize)]
|
||||
pub enum Speed {
|
||||
Low = 0xe1,
|
||||
Med = 0xeb,
|
||||
High = 0xf5,
|
||||
}
|
||||
impl From<cli_options::Speed> for Speed {
|
||||
fn from(s: cli_options::Speed) -> Self {
|
||||
match s {
|
||||
cli_options::Speed::Low => Speed::Low,
|
||||
cli_options::Speed::Med => Speed::Med,
|
||||
cli_options::Speed::High => Speed::High,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Default for Speed {
|
||||
fn default() -> Self {
|
||||
Speed::Med
|
||||
}
|
||||
}
|
||||
impl FromStr for Speed {
|
||||
type Err = AuraError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let s = s.to_lowercase();
|
||||
match s.as_str() {
|
||||
"low" => Ok(Speed::Low),
|
||||
"med" => Ok(Speed::Med),
|
||||
"high" => Ok(Speed::High),
|
||||
_ => Err(AuraError::ParseSpeed),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Used for Rainbow mode.
|
||||
///
|
||||
@@ -61,107 +78,108 @@ pub enum Direction {
|
||||
Up,
|
||||
Down,
|
||||
}
|
||||
impl From<cli_options::Direction> for Direction {
|
||||
fn from(s: cli_options::Direction) -> Self {
|
||||
match s {
|
||||
cli_options::Direction::Right => Direction::Right,
|
||||
cli_options::Direction::Left => Direction::Left,
|
||||
cli_options::Direction::Up => Direction::Up,
|
||||
cli_options::Direction::Down => Direction::Down,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Default for Direction {
|
||||
fn default() -> Self {
|
||||
Direction::Right
|
||||
}
|
||||
}
|
||||
impl FromStr for Direction {
|
||||
type Err = AuraError;
|
||||
|
||||
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
|
||||
pub struct TwoColourSpeed {
|
||||
pub colour: Colour,
|
||||
pub colour2: Colour,
|
||||
pub speed: Speed,
|
||||
}
|
||||
impl From<cli_options::TwoColourSpeed> for TwoColourSpeed {
|
||||
fn from(mode: cli_options::TwoColourSpeed) -> Self {
|
||||
TwoColourSpeed {
|
||||
colour: mode.colour.into(),
|
||||
colour2: mode.colour2.into(),
|
||||
speed: mode.speed.into(),
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let s = s.to_lowercase();
|
||||
match s.as_str() {
|
||||
"right" => Ok(Direction::Right),
|
||||
"up" => Ok(Direction::Up),
|
||||
"down" => Ok(Direction::Down),
|
||||
"left" => Ok(Direction::Left),
|
||||
_ => Err(AuraError::ParseDirection),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
|
||||
#[derive(Debug, Clone, Options, Default, Deserialize, Serialize)]
|
||||
pub struct SingleSpeed {
|
||||
#[serde(skip)]
|
||||
#[options(help = "print help message")]
|
||||
help: bool,
|
||||
#[options(no_long, meta = "WORD", help = "set the speed: low, med, high")]
|
||||
pub speed: Speed,
|
||||
}
|
||||
impl From<cli_options::SingleSpeed> for SingleSpeed {
|
||||
fn from(mode: cli_options::SingleSpeed) -> Self {
|
||||
SingleSpeed {
|
||||
speed: mode.speed.into(),
|
||||
}
|
||||
}
|
||||
#[derive(Debug, Clone, Options, Default, Deserialize, Serialize)]
|
||||
pub struct SingleSpeedDirection {
|
||||
#[serde(skip)]
|
||||
#[options(help = "print help message")]
|
||||
help: bool,
|
||||
#[options(no_long, meta = "", help = "set the direction: up, down, left, right")]
|
||||
pub direction: Direction,
|
||||
#[options(no_long, meta = "", help = "set the speed: low, med, high")]
|
||||
pub speed: Speed,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
|
||||
#[derive(Debug, Clone, Default, Options, Deserialize, Serialize)]
|
||||
pub struct SingleColour {
|
||||
#[serde(skip)]
|
||||
#[options(help = "print help message")]
|
||||
help: bool,
|
||||
#[options(no_long, meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||
pub colour: Colour,
|
||||
}
|
||||
impl From<cli_options::SingleColour> for SingleColour {
|
||||
fn from(mode: cli_options::SingleColour) -> Self {
|
||||
SingleColour {
|
||||
colour: mode.colour.into(),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Options, Deserialize, Serialize)]
|
||||
pub struct SingleColourSpeed {
|
||||
#[serde(skip)]
|
||||
#[options(help = "print help message")]
|
||||
help: bool,
|
||||
#[options(no_long, meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||
pub colour: Colour,
|
||||
#[options(no_long, meta = "", help = "set the speed: low, med, high")]
|
||||
pub speed: Speed,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
|
||||
pub struct MultiColour {
|
||||
pub colour1: Colour,
|
||||
#[derive(Debug, Clone, Options, Default, Deserialize, Serialize)]
|
||||
pub struct TwoColourSpeed {
|
||||
#[serde(skip)]
|
||||
#[options(help = "print help message")]
|
||||
help: bool,
|
||||
#[options(no_long, meta = "", help = "set the first RGB value e.g, ff00ff")]
|
||||
pub colour: Colour,
|
||||
#[options(no_long, meta = "", help = "set the second RGB value e.g, ff00ff")]
|
||||
pub colour2: Colour,
|
||||
#[options(no_long, meta = "", help = "set the speed: low, med, high")]
|
||||
pub speed: Speed,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Options, Deserialize, Serialize)]
|
||||
pub struct MultiColour {
|
||||
#[serde(skip)]
|
||||
#[options(help = "print help message")]
|
||||
help: bool,
|
||||
#[options(short = "a", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||
pub colour1: Colour,
|
||||
#[options(short = "b", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||
pub colour2: Colour,
|
||||
#[options(short = "c", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||
pub colour3: Colour,
|
||||
#[options(short = "d", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||
pub colour4: Colour,
|
||||
}
|
||||
impl From<cli_options::MultiColour> for MultiColour {
|
||||
fn from(mode: cli_options::MultiColour) -> Self {
|
||||
MultiColour {
|
||||
colour1: mode.colour1.into(),
|
||||
colour2: mode.colour2.into(),
|
||||
colour3: mode.colour3.into(),
|
||||
colour4: mode.colour4.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
|
||||
pub struct SingleSpeedDirection {
|
||||
pub direction: Direction,
|
||||
#[derive(Debug, Clone, Default, Options, Deserialize, Serialize)]
|
||||
pub struct MultiColourSpeed {
|
||||
#[options(help = "print help message")]
|
||||
help: bool,
|
||||
#[options(short = "a", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||
pub colour1: Colour,
|
||||
#[options(short = "b", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||
pub colour2: Colour,
|
||||
#[options(short = "c", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||
pub colour3: Colour,
|
||||
#[options(short = "d", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||
pub colour4: Colour,
|
||||
#[options(no_long, meta = "", help = "set the speed: low, med, high")]
|
||||
pub speed: Speed,
|
||||
}
|
||||
impl From<cli_options::SingleSpeedDirection> for SingleSpeedDirection {
|
||||
fn from(mode: cli_options::SingleSpeedDirection) -> Self {
|
||||
SingleSpeedDirection {
|
||||
direction: mode.direction.into(),
|
||||
speed: mode.speed.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
|
||||
pub struct SingleColourSpeed {
|
||||
pub colour: Colour,
|
||||
pub speed: Speed,
|
||||
}
|
||||
impl From<cli_options::SingleColourSpeed> for SingleColourSpeed {
|
||||
fn from(mode: cli_options::SingleColourSpeed) -> Self {
|
||||
SingleColourSpeed {
|
||||
colour: mode.colour.into(),
|
||||
speed: mode.speed.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub enum AuraModes {
|
||||
@@ -178,6 +196,7 @@ pub enum AuraModes {
|
||||
Comet(SingleColour),
|
||||
Flash(SingleColour),
|
||||
MultiStatic(MultiColour),
|
||||
MultiBreathe(MultiColourSpeed),
|
||||
LedBrightness(u8),
|
||||
// TODO: use a serializable structure for this (KeyColourArray)
|
||||
PerKey(Vec<Vec<u8>>),
|
||||
@@ -186,19 +205,20 @@ pub enum AuraModes {
|
||||
impl From<SetAuraBuiltin> for AuraModes {
|
||||
fn from(mode: SetAuraBuiltin) -> Self {
|
||||
match mode {
|
||||
SetAuraBuiltin::Static(x) => AuraModes::Static(x.into()),
|
||||
SetAuraBuiltin::Breathe(x) => AuraModes::Breathe(x.into()),
|
||||
SetAuraBuiltin::Strobe(x) => AuraModes::Strobe(x.into()),
|
||||
SetAuraBuiltin::Rainbow(x) => AuraModes::Rainbow(x.into()),
|
||||
SetAuraBuiltin::Star(x) => AuraModes::Star(x.into()),
|
||||
SetAuraBuiltin::Rain(x) => AuraModes::Rain(x.into()),
|
||||
SetAuraBuiltin::Highlight(x) => AuraModes::Highlight(x.into()),
|
||||
SetAuraBuiltin::Laser(x) => AuraModes::Laser(x.into()),
|
||||
SetAuraBuiltin::Ripple(x) => AuraModes::Ripple(x.into()),
|
||||
SetAuraBuiltin::Pulse(x) => AuraModes::Pulse(x.into()),
|
||||
SetAuraBuiltin::Comet(x) => AuraModes::Comet(x.into()),
|
||||
SetAuraBuiltin::Flash(x) => AuraModes::Flash(x.into()),
|
||||
SetAuraBuiltin::MultiStatic(x) => AuraModes::MultiStatic(x.into()),
|
||||
SetAuraBuiltin::Static(x) => AuraModes::Static(x),
|
||||
SetAuraBuiltin::Breathe(x) => AuraModes::Breathe(x),
|
||||
SetAuraBuiltin::Strobe(x) => AuraModes::Strobe(x),
|
||||
SetAuraBuiltin::Rainbow(x) => AuraModes::Rainbow(x),
|
||||
SetAuraBuiltin::Star(x) => AuraModes::Star(x),
|
||||
SetAuraBuiltin::Rain(x) => AuraModes::Rain(x),
|
||||
SetAuraBuiltin::Highlight(x) => AuraModes::Highlight(x),
|
||||
SetAuraBuiltin::Laser(x) => AuraModes::Laser(x),
|
||||
SetAuraBuiltin::Ripple(x) => AuraModes::Ripple(x),
|
||||
SetAuraBuiltin::Pulse(x) => AuraModes::Pulse(x),
|
||||
SetAuraBuiltin::Comet(x) => AuraModes::Comet(x),
|
||||
SetAuraBuiltin::Flash(x) => AuraModes::Flash(x),
|
||||
SetAuraBuiltin::MultiStatic(x) => AuraModes::MultiStatic(x),
|
||||
SetAuraBuiltin::MultiBreathe(x) => AuraModes::MultiBreathe(x),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -234,6 +254,7 @@ impl From<&AuraModes> for u8 {
|
||||
AuraModes::Comet(_) => COMET,
|
||||
AuraModes::Flash(_) => FLASH,
|
||||
AuraModes::MultiStatic(_) => MULTISTATIC,
|
||||
AuraModes::MultiBreathe(_) => MULTIBREATHE,
|
||||
AuraModes::PerKey(_) => PER_KEY,
|
||||
_ => panic!("Invalid mode"),
|
||||
}
|
||||
@@ -256,6 +277,7 @@ impl From<&AuraModes> for &str {
|
||||
AuraModes::Comet(_) => "Comet",
|
||||
AuraModes::Flash(_) => "Flash",
|
||||
AuraModes::MultiStatic(_) => "4-Zone Static Colours",
|
||||
AuraModes::MultiBreathe(_) => "4-Zone Breathing Colours",
|
||||
AuraModes::PerKey(_) => "RGB per-key",
|
||||
_ => panic!("Invalid mode"),
|
||||
}
|
||||
@@ -280,6 +302,7 @@ impl From<u8> for AuraModes {
|
||||
COMET => AuraModes::Comet(SingleColour::default()),
|
||||
FLASH => AuraModes::Flash(SingleColour::default()),
|
||||
MULTISTATIC => AuraModes::MultiStatic(MultiColour::default()),
|
||||
MULTIBREATHE => AuraModes::MultiBreathe(MultiColourSpeed::default()),
|
||||
PER_KEY => AuraModes::PerKey(vec![]),
|
||||
_ => panic!("Invalid mode byte"),
|
||||
}
|
||||
147
rog-types/src/cli_options.rs
Normal file
@@ -0,0 +1,147 @@
|
||||
use crate::{
|
||||
aura_modes::{
|
||||
MultiColour, MultiColourSpeed, SingleColour, SingleColourSpeed, SingleSpeed,
|
||||
SingleSpeedDirection, TwoColourSpeed,
|
||||
},
|
||||
error::AuraError,
|
||||
};
|
||||
use gumdrop::Options;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(Options)]
|
||||
pub struct LedBrightness {
|
||||
level: Option<u8>,
|
||||
}
|
||||
impl LedBrightness {
|
||||
pub fn new(level: Option<u8>) -> Self {
|
||||
LedBrightness { level }
|
||||
}
|
||||
|
||||
pub fn level(&self) -> Option<u8> {
|
||||
self.level
|
||||
}
|
||||
}
|
||||
impl FromStr for LedBrightness {
|
||||
type Err = AuraError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let s = s.to_lowercase();
|
||||
match s.as_str() {
|
||||
"off" => Ok(LedBrightness { level: Some(0x00) }),
|
||||
"low" => Ok(LedBrightness { level: Some(0x01) }),
|
||||
"med" => Ok(LedBrightness { level: Some(0x02) }),
|
||||
"high" => Ok(LedBrightness { level: Some(0x03) }),
|
||||
_ => {
|
||||
print!("Invalid argument, must be one of: off, low, med, high");
|
||||
Err(AuraError::ParseBrightness)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
impl ToString for LedBrightness {
|
||||
fn to_string(&self) -> String {
|
||||
let s = match self.level {
|
||||
Some(0x00) => "low",
|
||||
Some(0x01) => "med",
|
||||
Some(0x02) => "high",
|
||||
_ => "unknown",
|
||||
};
|
||||
s.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
/// Byte value for setting the built-in mode.
|
||||
///
|
||||
/// Enum corresponds to the required integer value
|
||||
#[derive(Options, Deserialize, Serialize)]
|
||||
pub enum SetAuraBuiltin {
|
||||
#[options(help = "set a single static colour")]
|
||||
Static(SingleColour),
|
||||
#[options(help = "pulse between one or two colours")]
|
||||
Breathe(TwoColourSpeed),
|
||||
#[options(help = "strobe through all colours")]
|
||||
Strobe(SingleSpeed),
|
||||
#[options(help = "rainbow cycling in one of four directions")]
|
||||
Rainbow(SingleSpeedDirection),
|
||||
#[options(help = "rain pattern mimicking raindrops")]
|
||||
Star(TwoColourSpeed),
|
||||
#[options(help = "rain pattern of three preset colours")]
|
||||
Rain(SingleSpeed),
|
||||
#[options(help = "pressed keys are highlighted to fade")]
|
||||
Highlight(SingleColourSpeed),
|
||||
#[options(help = "pressed keys generate horizontal laser")]
|
||||
Laser(SingleColourSpeed),
|
||||
#[options(help = "pressed keys ripple outwards like a splash")]
|
||||
Ripple(SingleColourSpeed),
|
||||
#[options(help = "set a rapid pulse")]
|
||||
Pulse(SingleColour),
|
||||
#[options(help = "set a vertical line zooming from left")]
|
||||
Comet(SingleColour),
|
||||
#[options(help = "set a wide vertical line zooming from left")]
|
||||
Flash(SingleColour),
|
||||
#[options(help = "4-zone multi-colour")]
|
||||
MultiStatic(MultiColour),
|
||||
#[options(help = "4-zone multi-colour breathing")]
|
||||
MultiBreathe(MultiColourSpeed),
|
||||
}
|
||||
|
||||
impl Default for SetAuraBuiltin {
|
||||
fn default() -> Self {
|
||||
SetAuraBuiltin::Static(SingleColour::default())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum AniMeStatusValue {
|
||||
On,
|
||||
Off,
|
||||
}
|
||||
impl FromStr for AniMeStatusValue {
|
||||
type Err = AuraError;
|
||||
|
||||
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(AuraError::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 enum AniMeActions {
|
||||
#[options(help = "change all leds brightness")]
|
||||
Leds(AniMeLeds),
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, PartialEq, Copy, Clone, Deserialize, Serialize)]
|
||||
pub enum GfxVendors {
|
||||
Nvidia,
|
||||
Integrated,
|
||||
@@ -8,12 +10,12 @@ pub enum GfxVendors {
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
use super::error::GfxError;
|
||||
use crate::error::GraphicsError;
|
||||
|
||||
impl FromStr for GfxVendors {
|
||||
type Err = GfxError;
|
||||
type Err = GraphicsError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, GfxError> {
|
||||
fn from_str(s: &str) -> Result<Self, GraphicsError> {
|
||||
match s.to_lowercase().as_str() {
|
||||
"nvidia" => Ok(GfxVendors::Nvidia),
|
||||
"hybrid" => Ok(GfxVendors::Hybrid),
|
||||
@@ -23,14 +25,14 @@ impl FromStr for GfxVendors {
|
||||
"hybrid\n" => Ok(GfxVendors::Hybrid),
|
||||
"compute\n" => Ok(GfxVendors::Compute),
|
||||
"integrated\n" => Ok(GfxVendors::Integrated),
|
||||
_ => Err(GfxError::ParseVendor),
|
||||
_ => Err(GraphicsError::ParseVendor),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&GfxVendors> for &str {
|
||||
fn from(mode: &GfxVendors) -> Self {
|
||||
match mode {
|
||||
impl Into<&str> for GfxVendors {
|
||||
fn into(self) -> &'static str {
|
||||
match self {
|
||||
GfxVendors::Nvidia => "nvidia",
|
||||
GfxVendors::Hybrid => "hybrid",
|
||||
GfxVendors::Compute => "compute",
|
||||
@@ -39,6 +41,17 @@ impl From<&GfxVendors> for &str {
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<String> for GfxVendors {
|
||||
fn into(self) -> String {
|
||||
match self {
|
||||
GfxVendors::Nvidia => "nvidia".to_string(),
|
||||
GfxVendors::Hybrid => "hybrid".to_string(),
|
||||
GfxVendors::Compute => "compute".to_string(),
|
||||
GfxVendors::Integrated => "integrated".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum GfxCtrlAction {
|
||||
Reboot,
|
||||
@@ -47,14 +60,14 @@ pub enum GfxCtrlAction {
|
||||
}
|
||||
|
||||
impl FromStr for GfxCtrlAction {
|
||||
type Err = GfxError;
|
||||
type Err = GraphicsError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, GfxError> {
|
||||
fn from_str(s: &str) -> Result<Self, GraphicsError> {
|
||||
match s.to_lowercase().as_str() {
|
||||
"reboot" => Ok(GfxCtrlAction::Reboot),
|
||||
"restartx" => Ok(GfxCtrlAction::RestartX),
|
||||
"none" => Ok(GfxCtrlAction::None),
|
||||
_ => Err(GfxError::ParseVendor),
|
||||
_ => Err(GraphicsError::ParseVendor),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,24 +14,14 @@ pub mod cli_options;
|
||||
/// Enables you to create fancy RGB effects
|
||||
pub mod fancy;
|
||||
|
||||
/// The main dbus group for system controls, e.g, fan control, keyboard LED's
|
||||
pub mod core_dbus;
|
||||
|
||||
/// Specific dbus for writing to the AniMe Matrix display (if supported)
|
||||
pub mod anime_dbus;
|
||||
|
||||
/// Helper functions for the AniMe display
|
||||
pub mod anime_matrix;
|
||||
|
||||
pub mod gfx_vendors;
|
||||
|
||||
pub mod error;
|
||||
|
||||
pub mod dbus_anime;
|
||||
pub mod dbus_charge;
|
||||
pub mod dbus_gfx;
|
||||
pub mod dbus_ledmode;
|
||||
pub mod dbus_profile;
|
||||
pub mod dbus_rogbios;
|
||||
pub mod dbus_supported;
|
||||
pub static VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
// static LED_INIT1: [u8; 2] = [0x5d, 0xb9];
|
||||
// static LED_INIT2: &str = "]ASUS Tech.Inc."; // ] == 0x5d
|
||||
@@ -153,6 +143,7 @@ impl From<&AuraModes> for [u8; LED_MSG_LEN] {
|
||||
let mut msg = [0u8; LED_MSG_LEN];
|
||||
msg[0] = 0x5d;
|
||||
msg[1] = 0xb3;
|
||||
msg[7] = 0xeb;
|
||||
match mode {
|
||||
AuraModes::LedBrightness(n) => return aura_brightness_bytes(*n),
|
||||
AuraModes::Static(_) => msg[3] = 0x00,
|
||||
@@ -234,14 +225,15 @@ impl From<&AuraModes> for [[u8; LED_MSG_LEN]; 4] {
|
||||
#[inline]
|
||||
fn from(mode: &AuraModes) -> Self {
|
||||
let mut msg = [[0u8; LED_MSG_LEN]; 4];
|
||||
for (i, row) in msg.iter_mut().enumerate() {
|
||||
row[0] = 0x5d;
|
||||
row[1] = 0xb3;
|
||||
row[2] = i as u8 + 1;
|
||||
}
|
||||
|
||||
match mode {
|
||||
AuraModes::MultiStatic(settings) => {
|
||||
for (i, row) in msg.iter_mut().enumerate() {
|
||||
row[0] = 0x5d;
|
||||
row[1] = 0xb3;
|
||||
row[2] = i as u8 + 1; // zone
|
||||
row[3] = 0x00; // mode
|
||||
row[7] = 0xeb; // static needs speed?
|
||||
}
|
||||
msg[0][4] = settings.colour1.0;
|
||||
msg[0][5] = settings.colour1.1;
|
||||
msg[0][6] = settings.colour1.2;
|
||||
@@ -255,6 +247,35 @@ impl From<&AuraModes> for [[u8; LED_MSG_LEN]; 4] {
|
||||
msg[3][5] = settings.colour4.1;
|
||||
msg[3][6] = settings.colour4.2;
|
||||
}
|
||||
AuraModes::MultiBreathe(settings) => {
|
||||
for (i, row) in msg.iter_mut().enumerate() {
|
||||
row[0] = 0x5d;
|
||||
row[1] = 0xb3;
|
||||
row[2] = i as u8 + 1; // zone
|
||||
row[3] = 0x01; // mode
|
||||
}
|
||||
let speed = match settings.speed {
|
||||
aura_modes::Speed::Low => 0xfd,
|
||||
aura_modes::Speed::Med => 0xfe,
|
||||
aura_modes::Speed::High => 0xff,
|
||||
};
|
||||
msg[0][4] = settings.colour1.0;
|
||||
msg[0][5] = settings.colour1.1;
|
||||
msg[0][6] = settings.colour1.2;
|
||||
msg[0][7] = speed; // fd, fe, ff
|
||||
msg[1][4] = settings.colour2.0;
|
||||
msg[1][5] = settings.colour2.1;
|
||||
msg[1][6] = settings.colour2.2;
|
||||
msg[1][7] = speed;
|
||||
msg[2][4] = settings.colour3.0;
|
||||
msg[2][5] = settings.colour3.1;
|
||||
msg[2][6] = settings.colour3.2;
|
||||
msg[2][7] = speed;
|
||||
msg[3][4] = settings.colour4.0;
|
||||
msg[3][5] = settings.colour4.1;
|
||||
msg[3][6] = settings.colour4.2;
|
||||
msg[3][7] = speed;
|
||||
}
|
||||
_ => panic!("Mode not convertable to 2D array: {}", <&str>::from(mode)),
|
||||
}
|
||||
msg
|
||||