mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-01-22 17:33:19 +01:00
Compare commits
156 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9faebe9e38 | ||
|
|
2e2d5cb46b | ||
|
|
4e3a610a0f | ||
|
|
03e10610dd | ||
|
|
a6a10a5bc4 | ||
|
|
0985eca7ce | ||
|
|
bb7b3a81fb | ||
|
|
19607d71c3 | ||
|
|
96f281d789 | ||
|
|
7613eded95 | ||
|
|
50eccd2b1d | ||
|
|
ba54007102 | ||
|
|
a028f5375f | ||
|
|
9ec02cd727 | ||
|
|
4b46ece09a | ||
|
|
086bbd0908 | ||
|
|
c94eaa473e | ||
|
|
b1b809834b | ||
|
|
84183288ec | ||
|
|
86cbef83b6 | ||
|
|
006fb632c4 | ||
|
|
e3636ed8ce | ||
|
|
cfd207f251 | ||
|
|
d4c68546e7 | ||
|
|
6f4a7e16dc | ||
|
|
f64253d633 | ||
|
|
124c17aadc | ||
|
|
ab40f9fcbf | ||
|
|
5cdfa5a8d4 | ||
|
|
ce870cd5ed | ||
|
|
4541d2e1ba | ||
|
|
b525411fd3 | ||
|
|
a867496f13 | ||
|
|
f421b8ee3b | ||
|
|
82780feb4b | ||
|
|
1e5443e206 | ||
|
|
027a591d26 | ||
|
|
e90375828d | ||
|
|
75b4d67072 | ||
|
|
9aa332de3b | ||
|
|
5efd7fc6a7 | ||
|
|
0aafe24a02 | ||
|
|
dda6d343d9 | ||
|
|
6f39307080 | ||
|
|
ef63789faa | ||
|
|
c422e77ba6 | ||
|
|
3c234dd3c4 | ||
|
|
c420dd820a | ||
|
|
a3e6fec163 | ||
|
|
9b4e76be87 | ||
|
|
7b2125cbdf | ||
|
|
694a644cc6 | ||
|
|
922aa0c352 | ||
|
|
c06f78990f | ||
|
|
5c8bb6e6ea | ||
|
|
993131d0a9 | ||
|
|
0a69c23288 | ||
|
|
f6e4cc0626 | ||
|
|
1f696508e7 | ||
|
|
fa043adc99 | ||
|
|
b9c2d929b3 | ||
|
|
eda1e920df | ||
|
|
0de2c9e424 | ||
|
|
e88e7be8ae | ||
|
|
e470d3acc0 | ||
|
|
f5b3f0bc38 | ||
|
|
19497c94e0 | ||
|
|
670eee23e8 | ||
|
|
26309776e9 | ||
|
|
a7d5057976 | ||
|
|
8eb9b1d4eb | ||
|
|
71ee9e43ba | ||
|
|
f1b0e1288a | ||
|
|
35c7fd10b3 | ||
|
|
4c50dc259c | ||
|
|
0fd0aeff88 | ||
|
|
fd37f41ef1 | ||
|
|
1307997122 | ||
|
|
85187d2d8d | ||
|
|
e29a568195 | ||
|
|
6c375a9951 | ||
|
|
4641e19c43 | ||
|
|
91f0c2ea14 | ||
|
|
b4a8cb9de2 | ||
|
|
67bbcdb964 | ||
|
|
8acfe0a9e8 | ||
|
|
5f6e6ec382 | ||
|
|
cf92526d87 | ||
|
|
f290594562 | ||
|
|
423bd54f79 | ||
|
|
ea0eaef8a6 | ||
|
|
ef62a26148 | ||
|
|
2f916fa4e5 | ||
|
|
e42fd10404 | ||
|
|
93edd1b632 | ||
|
|
6957a08d83 | ||
|
|
98569b98e7 | ||
|
|
573568d6e2 | ||
|
|
3ec37a4dac | ||
|
|
11483b28a6 | ||
|
|
2cce83d164 | ||
|
|
42b92f3b87 | ||
|
|
b652fd15a2 | ||
|
|
9154aaa97c | ||
|
|
9e65921c0a | ||
|
|
8d8b5e5f51 | ||
|
|
9418b63454 | ||
|
|
2d396a49da | ||
|
|
a6d89a622b | ||
|
|
51bcb0082b | ||
|
|
eb54250e4d | ||
|
|
eafc831231 | ||
|
|
c625e97b7b | ||
|
|
fea56879d6 | ||
|
|
03052e129b | ||
|
|
3dbc893905 | ||
|
|
50152961c7 | ||
|
|
8be0e7e6bf | ||
|
|
d6d4a00fc3 | ||
|
|
611140716c | ||
|
|
a09f7b5275 | ||
|
|
823958492e | ||
|
|
668135eab3 | ||
|
|
622e07505d | ||
|
|
5c159d2294 | ||
|
|
6cfa09a02b | ||
|
|
95666cc40b | ||
|
|
458d58c87c | ||
|
|
7328ebdda3 | ||
|
|
14d043bbc3 | ||
|
|
98dec6403c | ||
|
|
3546f5bd21 | ||
|
|
db1683de46 | ||
|
|
669c8ac3c7 | ||
|
|
4f3a6ce1c6 | ||
|
|
6d3918ccf0 | ||
|
|
b002187b39 | ||
|
|
13965b2261 | ||
|
|
b182fbd323 | ||
|
|
19b28f202c | ||
|
|
ed51a7fa14 | ||
|
|
c94358a8f3 | ||
|
|
2a8ca0a39a | ||
|
|
83455a5ba3 | ||
|
|
bc776deb70 | ||
|
|
59b1059aee | ||
|
|
dbe80d1914 | ||
|
|
e325ebed18 | ||
|
|
a743bda6e0 | ||
|
|
15e6782e10 | ||
|
|
6b058c9922 | ||
|
|
fc8879ac24 | ||
|
|
4d2d5707a1 | ||
|
|
439c830311 | ||
|
|
91223d4ced | ||
|
|
7b17a13ce7 |
12
.gitignore
vendored
12
.gitignore
vendored
@@ -8,4 +8,14 @@ vendor_*
|
||||
.vscode-ctags
|
||||
.vscode
|
||||
.~lock.*
|
||||
*.ods#
|
||||
*.ods#
|
||||
|
||||
# gnome extension
|
||||
node-modules
|
||||
bindings/ts/*.d.ts
|
||||
bindings/ts/*.js.map
|
||||
desktop-extensions/gnome*/dist
|
||||
desktop-extensions/gnome*/@types/gir-generated
|
||||
desktop-extensions/gnome*/node_modules
|
||||
desktop-extensions/gnome*/schemas/gschemas.compiled
|
||||
desktop-extensions/gnome*/*.zip
|
||||
|
||||
@@ -59,6 +59,7 @@ release:
|
||||
- tags
|
||||
<<: *rust_cache
|
||||
script:
|
||||
- cargo install cargo-vendor-filterer
|
||||
- make && make vendor
|
||||
artifacts:
|
||||
paths:
|
||||
|
||||
24
.gitlab/issue_templates/default.md
Normal file
24
.gitlab/issue_templates/default.md
Normal file
@@ -0,0 +1,24 @@
|
||||
## Issue description
|
||||
|
||||
(Summarize the bug encountered)
|
||||
|
||||
## Steps to reproduce
|
||||
|
||||
(How can the issue be reproduced)
|
||||
|
||||
## What is the current bug behavior?
|
||||
|
||||
(What actually happens)
|
||||
|
||||
## What is the expected correct behavior?
|
||||
|
||||
(What you should see instead)
|
||||
|
||||
## Relevant logs and/or screenshots
|
||||
|
||||
(run `journalctl -b -u supergfxd > ~/supergfxd.log` and attach `~/supergfxd.log`)
|
||||
|
||||
(Paste any relevant logs - use code blocks (```) to format console output, logs, and code, as
|
||||
it's very hard to read otherwise.)
|
||||
|
||||
/label ~bug ~reproducable ~needs-investigation
|
||||
119
CHANGELOG.md
119
CHANGELOG.md
@@ -5,14 +5,120 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
## [v4.7.0-RC1]
|
||||
|
||||
## [v5.0.8]
|
||||
### Changed
|
||||
- Reintroduce persisting dark/light mode in config file
|
||||
- Added ability to change what EPP is linked with each throttle profile
|
||||
- Don't change EPP or thermal profile if the battery/ac state hasn't actually changed on resume
|
||||
- Re-implement the `asusctl -s` command (not fully)
|
||||
- Add more docs to some parts of code, and dbus interfaces
|
||||
- Reload asusd.ron if changed. Does not notify any dbus listeners (yet)
|
||||
- Fix the broken pipe error
|
||||
- Remove the use of bytes in zbus signatures (another cause of broken pipe)
|
||||
|
||||
### Added
|
||||
- Support for G614J LED modes
|
||||
|
||||
## [v5.0.7]
|
||||
### Changed
|
||||
- Fix to suspend process in anime thread to let custom anims run on wake.
|
||||
- Fix to reload the fan curves correctly on boot.
|
||||
- Add new config option `platform_policy_linked_epp` to set if energy_performance_preference should be paired with platform_profile/throttle_thermal_policy
|
||||
- Small fixes to rog-control-center
|
||||
|
||||
## [v5.0.6]
|
||||
- Revert egui update due to a lot of issues arising from window closing.
|
||||
|
||||
## [v5.0.5]
|
||||
- Resync. A release was made that was missing some commits.
|
||||
|
||||
## [v5.0.4]
|
||||
### Changed
|
||||
- Added G834JZ led config
|
||||
- Fix in ROGCC to apply the actual effect changed
|
||||
- Re-enable all fan curves (available) in ROGCC
|
||||
- Update smithay-client-toolkit
|
||||
|
||||
## [v5.0.3]
|
||||
### Changed
|
||||
- Fix and error in platform ppt value gets
|
||||
- Fix to asusctl CLI where an incorrect enum variant was used in throttle check
|
||||
- Turn some error messages in to warning or info to prevent confusion
|
||||
- Re-add the keyboard power settings in rogcc
|
||||
- Add two new aura dbus properties for providing some basic info on aura modes/power
|
||||
|
||||
## [v5.0.2]
|
||||
### Changed
|
||||
- Fan-curves: nuke a few async deadlocks
|
||||
- Anime: force power/wakeup disabled to prevent idiotic random wakes
|
||||
|
||||
## [v5.0.1]
|
||||
### Changed
|
||||
- Fix setting next fan profile
|
||||
- Fix the assud.service
|
||||
- Fix dbus signature of some power setting types for some keyboards
|
||||
|
||||
## [v5.0.0]
|
||||
### Added
|
||||
- Gnome 45 plugin
|
||||
- Support for G513RW LED modes
|
||||
- Support Rog Ally LED modes (basic)
|
||||
- Add on_lid_closed and on_external_power_changed events for running certain tasks
|
||||
- Anime dbus: add:
|
||||
- SetOffWhenUnplugged, also add asusctl CLI option
|
||||
- SetOffWhenSuspended, also add asusctl CLI option
|
||||
- SetOffWhenLidClosed, also add asusctl CLI option
|
||||
- Anime: add brightness_on_battery config option
|
||||
- Platform: add `post_animation_sound`, kernel 6.7+ requires patch
|
||||
- Add changing of CPU energy perfromance preference in relation to throttle_thermal_policy. This means that the CPU correctly behaves according to throttle_thermal_policy (and platform profile use is *removed*)
|
||||
- Add setting of throttle_thermal_policy on power plug/unplug
|
||||
|
||||
### Changed
|
||||
- asusd: remove set_image_brightness for anime
|
||||
- asusd: refactor how certain things like display enable/builtins are toggled
|
||||
- Refactor sleep/shutdown tasks
|
||||
- rog-control-center: ensure brightness slider works correctly
|
||||
- Update `smithay-client-toolkit` for fix to issue #407
|
||||
- Remove the "sleep" animations from Anime to stop preventing the display-off
|
||||
- Anime:
|
||||
- Ensure display is off when lid is closed and option is set
|
||||
- Ensure display is off when on battery and option is set
|
||||
- Ensure builtin animations run instead of custom animations if option is set
|
||||
|
||||
### Breaking
|
||||
- DBUS stuff. Again. All of it.
|
||||
|
||||
## [v4.7.2]
|
||||
### Added
|
||||
- Support for G733PZ LED modes
|
||||
- Support for G713RC LED modes
|
||||
|
||||
### Changed
|
||||
- Fix loading of fan curves from stored settings
|
||||
|
||||
## [v4.7.1]
|
||||
### Changed
|
||||
- Fixes to asusctl CLI tool to show fan curves
|
||||
- Fixes to asusd to ensure fan curve defaults are loaded if the config file fails
|
||||
- Further refine the asusctl CLI for fan-curve control
|
||||
- Fixes to AniMe detection
|
||||
- Fixes to aura config creation/loading
|
||||
|
||||
### Added
|
||||
- Support for GV601V LED modes
|
||||
|
||||
## [v4.7.0]
|
||||
### Added
|
||||
- Support for FX507Z LED modes
|
||||
- Support for GL503V LED modes
|
||||
- Support for G733C LED modes
|
||||
- Support for GV601VI LED modes
|
||||
- Support for FX505G LED modes
|
||||
- Support for GA402X LED modes
|
||||
- Support for G634J LED modes (layout is in progress)
|
||||
- Support the Rear Glow on some laptops
|
||||
- Added field to aura_support to determine which LED power zones are supported. This will need folks to contribute data.
|
||||
- Support M16 matrix display
|
||||
- Custom images
|
||||
- Pixel gifs
|
||||
@@ -22,6 +128,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Add `model_override` option to anime config, this is handy for forcing a model for "Unknown" anime, and for simulators
|
||||
- Add `mini_led_mode` support to asusd and zbus crates (requires kernel patch https://lkml.org/lkml/2023/6/19/1264)
|
||||
- Add `mini_led_mode` toggle to rog-control-center GUI, tray, notifications
|
||||
- Add generation of typescript types from the rust types used via dbus using typeshare
|
||||
- Add generation of introspection XML from asusd dbus
|
||||
- Add a reworked gnome extension to the main repo under `desktop-extensions/gnome/`. This was done to better keep the extension in sync with work done on asusd, especially around breaking dbus
|
||||
- Add support for the mid fan custom curves on some laptops
|
||||
### Changed
|
||||
- Move FX506HC to FX506H in arua DB to catch full series of this range
|
||||
- Move FX506LH to FX506L in arua DB to catch full series of this range
|
||||
@@ -31,8 +141,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Prevent the multiple notifications from a profile change from occuring (too many functions with side effects!)
|
||||
- Apply keyboard brightness when setting a mode
|
||||
- Update GL503 led config
|
||||
- Arua LED power control has been heavily refactored for 0x19b6+ devices
|
||||
- Rog Control Center:
|
||||
- Added option to enable/disable system tray
|
||||
- Added button to fully quit app (exits from background)
|
||||
- Moved application settings to new page
|
||||
- Aura LED power refactor is now taken advantage of in RCC, exposing all settings
|
||||
### BREAKING
|
||||
- All Anime related DBUS methods/notifs are changed
|
||||
- All dbus interfaces that handled an enum have now been forced to use the enum as String type, not uint or similar, this unfortunately breaks a heap of stuff but has the benefit of allowing asusctl to use crates to generate a typescript (or other) binding to the types being used by zbus for the proxies. The implication here is that there will be an eventual tighter integration with the gnome extension and maybe KDE also.
|
||||
|
||||
## [v4.6.2]
|
||||
- Fix rog-control-center not reopening if `startup_in_background` is set
|
||||
|
||||
1609
Cargo.lock
generated
1609
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
18
Cargo.toml
18
Cargo.toml
@@ -1,25 +1,27 @@
|
||||
[workspace]
|
||||
members = ["asusctl", "asusd", "asusd-user", "config-traits", "rog-platform", "rog-dbus", "rog-anime", "rog-aura", "rog-profiles", "rog-control-center", "simulators"]
|
||||
default-members = ["asusctl", "asusd", "asusd-user", "rog-control-center"]
|
||||
members = ["asusctl", "asusd", "asusd-user", "config-traits", "cpuctl", "dmi-id", "rog-platform", "rog-dbus", "rog-anime", "rog-aura", "rog-profiles", "rog-control-center", "simulators"]
|
||||
default-members = ["asusctl", "asusd", "asusd-user", "cpuctl", "rog-control-center"]
|
||||
resolver = "2"
|
||||
|
||||
[workspace.package]
|
||||
version = "4.7.0-RC1"
|
||||
version = "5.0.10"
|
||||
rust-version = "1.75"
|
||||
|
||||
[workspace.dependencies]
|
||||
async-trait = "^0.1"
|
||||
tokio = { version = "^1.23.0", features = ["macros", "rt-multi-thread", "time", "sync"]}
|
||||
tokio = { version = "^1.23.0", default-features = false, features = ["macros", "sync"]}
|
||||
concat-idents = "^1.1"
|
||||
dirs = "^4.0"
|
||||
smol = "^1.3"
|
||||
|
||||
zbus = "~3.13.1"
|
||||
logind-zbus = { version = "^3.1.0" } #, default-features = false, features = ["non_blocking"] }
|
||||
zbus = "~3.14.1"
|
||||
logind-zbus = { version = "~3.1" } #, default-features = false, features = ["non_blocking"] }
|
||||
|
||||
serde = "^1.0"
|
||||
serde_derive = "^1.0"
|
||||
serde_json = "^1.0"
|
||||
toml = "^0.5.10"
|
||||
ron = "*"
|
||||
typeshare = "1.0.0"
|
||||
|
||||
log = "^0.4"
|
||||
env_logger = "^0.10.0"
|
||||
@@ -28,7 +30,6 @@ glam = { version = "^0.22", features = ["serde"] }
|
||||
gumdrop = "^0.8"
|
||||
udev = "^0.7"
|
||||
rusb = "^0.9"
|
||||
sysfs-class = "^0.1.3"
|
||||
inotify = "^0.10.0"
|
||||
|
||||
png_pong = "^0.8"
|
||||
@@ -47,6 +48,7 @@ lto = "fat"
|
||||
debug = false
|
||||
opt-level = 3
|
||||
panic = "abort"
|
||||
#codegen-units = 1
|
||||
|
||||
[profile.dev]
|
||||
debug = true
|
||||
|
||||
20
Makefile
20
Makefile
@@ -112,11 +112,29 @@ vendor:
|
||||
echo 'directory = "vendor"' >> .cargo/config
|
||||
mv .cargo/config ./cargo-config
|
||||
rm -rf .cargo
|
||||
rm -rf vendor
|
||||
cargo vendor-filterer --platform x86_64-unknown-linux-gnu vendor
|
||||
tar pcfJ vendor_asusctl_$(VERSION).tar.xz vendor
|
||||
rm -rf vendor
|
||||
|
||||
bindings:
|
||||
typeshare ./rog-anime/src/ --lang=typescript --output-file=bindings/ts/anime.ts
|
||||
typeshare ./rog-aura/src/ --lang=typescript --output-file=bindings/ts/aura.ts
|
||||
typeshare ./rog-profiles/src/ --lang=typescript --output-file=bindings/ts/profiles.ts
|
||||
typeshare ./rog-platform/src/ --lang=typescript --output-file=bindings/ts/platform.ts
|
||||
|
||||
introspect:
|
||||
gdbus introspect --system -d org.asuslinux.Daemon -o /org/asuslinux/Platform -x > bindings/dbus-xml/org-asuslinux-platform-4.xml
|
||||
gdbus introspect --system -d org.asuslinux.Daemon -o /org/asuslinux/Aura -x > bindings/dbus-xml/org-asuslinux-aura-4.xml
|
||||
gdbus introspect --system -d org.asuslinux.Daemon -o /org/asuslinux/Anime -x > bindings/dbus-xml/org-asuslinux-anime-4.xml
|
||||
gdbus introspect --system -d org.asuslinux.Daemon -o /org/asuslinux/FanCurves -x > bindings/dbus-xml/org-asuslinux-fan-curves-4.xml
|
||||
xmlstarlet ed -L -O -d '//interface[@name="org.freedesktop.DBus.Introspectable"]' bindings/dbus-xml/org-asuslinux-*
|
||||
xmlstarlet ed -L -O -d '//interface[@name="org.freedesktop.DBus.Properties"]' bindings/dbus-xml/org-asuslinux-*
|
||||
xmlstarlet ed -L -O -d '//interface[@name="org.freedesktop.DBus.Peer"]' bindings/dbus-xml/org-asuslinux-*
|
||||
|
||||
build:
|
||||
ifeq ($(VENDORED),1)
|
||||
cargo vendor
|
||||
@echo "version = $(VERSION)"
|
||||
tar pxf vendor_asusctl_$(VERSION).tar.xz
|
||||
endif
|
||||
@@ -129,4 +147,4 @@ ifneq ($(STRIP_BINARIES),0)
|
||||
endif
|
||||
|
||||
|
||||
.PHONY: all clean distclean install uninstall update build
|
||||
.PHONY: all clean distclean install uninstall update build bindings
|
||||
|
||||
46
README.md
46
README.md
@@ -1,8 +1,8 @@
|
||||
# `asusctl` for ASUS ROG
|
||||
|
||||
[](https://www.paypal.com/donate/?hosted_button_id=4V2DEPS7K6APC) - [Asus Linux Website](https://asus-linux.org/)
|
||||
[Become a Patron!](https://www.patreon.com/bePatron?u=7602281) - [Asus Linux Website](https://asus-linux.org/)
|
||||
|
||||
**WARNING:** Many features are developed in tandem with kernel patches. If you see a feature is missing you either need a patched kernel, or v6.1 which has all my work merged upstream.
|
||||
**WARNING:** Many features are developed in tandem with kernel patches. If you see a feature is missing you either need a patched kernel or latest release.
|
||||
|
||||
`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.
|
||||
@@ -11,23 +11,23 @@ Now includes a GUI, `rog-control-center`.
|
||||
|
||||
## Kernel support
|
||||
|
||||
**The minimum supported kernel version is 5.17**
|
||||
|
||||
**For TUF laptops, the minimum supported kernel version is 6.1**
|
||||
**The minimum supported kernel version is 6.6**
|
||||
|
||||
## Goals
|
||||
|
||||
1. To provide an interface for rootless control of some system functions most users wish to control such as fan speeds, keyboard LEDs, graphics modes.
|
||||
2. Enable third-party apps to use the above with dbus methods
|
||||
3. To make the above as easy as possible for new users
|
||||
4. Respect the users resources: be small, light, and fast
|
||||
The main goal of this work is to provide a safe and easy to use abstraction over various laptop features via DBUS, and to provide some helpful defaults and other behaviour such as toggling throttle/profile on AC/battery change.
|
||||
|
||||
Point 3 means that the list of supported distros is very narrow - fedora is explicitly
|
||||
supported. All other distros are *not* supported (while asusd might still run fine on them).
|
||||
For best support use fedora 36+ Workstation.
|
||||
1. Provide safe dbus interface
|
||||
2. Respect the users resources: be small, light, and fast
|
||||
|
||||
Point 4? asusd currently uses a tiny fraction of cpu time, and less than 1Mb of ram, the way
|
||||
a system-level daemon should.
|
||||
a system-level daemon should. Languages such as JS and python should never be used for system level daemons (please stop).
|
||||
|
||||
## Keyboard LEDs
|
||||
|
||||
The level of support for laptops is dependent on folks submitting data to include in [`./rog-aura/data/layouts/aura_support.ron`](./rog-aura/data/layouts/aura_support.ron), typically installed in `/usr/share/asusd/aura_support.ron`. This is because the controller used for keyboards and LEDs is used across many years and many laptop models, all with different firmware configurations - the only way to track this is with the file mentioned above. Why not just enable all by default? Because it confuses people.
|
||||
|
||||
See the [rog-aura readme](./rog-aura/README.md) for more details.
|
||||
|
||||
## Discord
|
||||
|
||||
@@ -41,6 +41,10 @@ to this:
|
||||
```
|
||||
Bus 001 Device 002: ID 0b05:1866 ASUSTek Computer, Inc. N-KEY Device
|
||||
```
|
||||
or
|
||||
```
|
||||
Bus 003 Device 002: ID 0b05:19b6 ASUSTek Computer, Inc. [unknown]
|
||||
```
|
||||
|
||||
then it may work without tweaks. Technically all other functions except the LED
|
||||
and AniMe parts should work regardless of your latop make.
|
||||
@@ -48,13 +52,11 @@ and AniMe parts should work regardless of your latop make.
|
||||
## Implemented
|
||||
|
||||
- [X] System daemon
|
||||
- [X] GUI app
|
||||
- [X] User notifications daemon
|
||||
- [X] GUI app (includes tray and notifications)
|
||||
- [X] Setting/modifying built-in LED modes
|
||||
- [X] Per-key LED setting
|
||||
- [X] Fancy LED modes (See examples) (currently being reworked)
|
||||
- [X] Saving settings for reload
|
||||
- [X] AniMatrix display on G14 models that include it
|
||||
- [X] AniMatrix display on G14 and M16 models that include it
|
||||
- [X] Set battery charge limit (with kernel supporting this)
|
||||
- [X] Fan curve control on supported laptops (G14/G15, some TUF like FA507)
|
||||
- [X] Toggle bios setting for boot/POST sound
|
||||
@@ -70,7 +72,7 @@ A gui is now in the repo - ROG Control Center. At this time it is still a WIP, b
|
||||
|
||||
# BUILDING
|
||||
|
||||
Requirements are rust >= 1.57 installed from rustup.io if the distro provided version is too old, and `make`.
|
||||
Requirements are rust >= 1.75 installed from rustup.io if the distro provided version is too old, and `make`.
|
||||
|
||||
**Ubuntu (unsuported):**
|
||||
|
||||
@@ -130,8 +132,16 @@ Run `sudo make uninstall` in the source repo, and remove `/etc/asusd/`.
|
||||
|
||||
See `CONTRIBUTING.md`. Additionally, also do `cargo clean` and `cargo test` on first checkout to ensure the commit hooks are used (via `cargo-husky`).
|
||||
|
||||
Generation of the bindings with `make bindings` requires `typeshare` to be installed.
|
||||
|
||||
Dbus introsepction XML requires with `make introspection` requires `anime_sim` to be running before starting `asusd`.
|
||||
|
||||
# OTHER
|
||||
|
||||
## AniMe Matrix simulator
|
||||
|
||||
A simulator using SDL2 can be built using `cargo build --package rog_simulators` and run with `./target/debug/anime_sim`. Once started `asusd` will need restarting to pick it up. If running this sim on a laptop *with* the display, the simulated display will be used instead of the physical display.
|
||||
|
||||
## Supporting more laptops
|
||||
|
||||
Please file a support request.
|
||||
|
||||
@@ -12,15 +12,16 @@ rog_dbus = { path = "../rog-dbus" }
|
||||
rog_profiles = { path = "../rog-profiles" }
|
||||
rog_platform = { path = "../rog-platform" }
|
||||
asusd = { path = "../asusd" }
|
||||
dmi_id = { path = "../dmi-id" }
|
||||
|
||||
gumdrop.workspace = true
|
||||
toml.workspace = true
|
||||
sysfs-class.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
gif.workspace = true
|
||||
tinybmp.workspace = true
|
||||
glam.workspace = true
|
||||
rog_dbus = { path = "../rog-dbus" }
|
||||
tokio = { version = "^1.23.0", default-features = false, features = ["macros", "sync", "rt", "time"]}
|
||||
|
||||
cargo-husky.workspace = true
|
||||
@@ -10,7 +10,7 @@ use rog_dbus::RogDbusClientBlocking;
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let (client, _) = RogDbusClientBlocking::new().unwrap();
|
||||
|
||||
let args: Vec<String> = env::args().into_iter().collect();
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if args.len() != 3 {
|
||||
println!("Usage: <filepath> <brightness>");
|
||||
println!("e.g, asusctl/examples/doom_large.png 0.8");
|
||||
|
||||
@@ -15,13 +15,13 @@ fn main() {
|
||||
|
||||
for step in (2..50).rev() {
|
||||
let mut matrix = AnimeDiagonal::new(AnimeType::GA401, None);
|
||||
for c in (0..60).into_iter().step_by(step) {
|
||||
for c in (0..60).step_by(step) {
|
||||
for i in matrix.get_mut().iter_mut() {
|
||||
i[c] = 50;
|
||||
}
|
||||
}
|
||||
|
||||
for c in (0..35).into_iter().step_by(step) {
|
||||
for c in (0..35).step_by(step) {
|
||||
for i in &mut matrix.get_mut()[c] {
|
||||
*i = 50;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ use rog_dbus::RogDbusClientBlocking;
|
||||
fn main() {
|
||||
let (client, _) = RogDbusClientBlocking::new().unwrap();
|
||||
|
||||
let args: Vec<String> = env::args().into_iter().collect();
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if args.len() != 3 {
|
||||
println!("Please supply filepath and brightness");
|
||||
return;
|
||||
|
||||
@@ -11,7 +11,7 @@ use rog_dbus::RogDbusClientBlocking;
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let (client, _) = RogDbusClientBlocking::new().unwrap();
|
||||
|
||||
let args: Vec<String> = env::args().into_iter().collect();
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if args.len() != 7 {
|
||||
println!("Usage: <filepath> <scale> <angle> <x pos> <y pos> <brightness>");
|
||||
println!("e.g, asusctl/examples/doom_large.png 0.9 0.4 0.0 0.0 0.8");
|
||||
|
||||
@@ -14,7 +14,7 @@ use rog_dbus::RogDbusClientBlocking;
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let (client, _) = RogDbusClientBlocking::new().unwrap();
|
||||
|
||||
let args: Vec<String> = env::args().into_iter().collect();
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if args.len() != 7 {
|
||||
println!("Usage: <filepath> <scale> <angle> <x pos> <y pos> <brightness>");
|
||||
println!("e.g, asusctl/examples/doom_large.png 0.9 0.4 0.0 0.0 0.8");
|
||||
|
||||
@@ -32,7 +32,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
let zone = Effect::DoomFlicker(rog_aura::effects::DoomFlicker::new(
|
||||
LedCode::SingleZone,
|
||||
Colour(200, 110, 0),
|
||||
Colour {
|
||||
r: 200,
|
||||
g: 110,
|
||||
b: 0,
|
||||
},
|
||||
100,
|
||||
10,
|
||||
));
|
||||
@@ -58,7 +62,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
seq.next_state(&layout);
|
||||
let packets = seq.create_packets();
|
||||
|
||||
client.proxies().led().direct_addressing_raw(packets)?;
|
||||
client.proxies().aura().direct_addressing_raw(packets)?;
|
||||
std::thread::sleep(std::time::Duration::from_millis(33));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,10 +17,28 @@ pub struct AnimeCommand {
|
||||
help = "set global base brightness value <Off, Low, Med, High>"
|
||||
)]
|
||||
pub brightness: Option<Brightness>,
|
||||
#[options(meta = "", help = "set global (image) brightness value")]
|
||||
pub image_brightness: Option<f32>,
|
||||
#[options(help = "clear the display")]
|
||||
pub clear: bool,
|
||||
#[options(
|
||||
no_short,
|
||||
meta = "",
|
||||
help = "turn the anime off when external power is unplugged"
|
||||
)]
|
||||
pub off_when_unplugged: Option<bool>,
|
||||
#[options(
|
||||
no_short,
|
||||
meta = "",
|
||||
help = "turn the anime off when the laptop suspends"
|
||||
)]
|
||||
pub off_when_suspended: Option<bool>,
|
||||
#[options(
|
||||
no_short,
|
||||
meta = "",
|
||||
help = "turn the anime off when the lid is closed"
|
||||
)]
|
||||
pub off_when_lid_closed: Option<bool>,
|
||||
#[options(no_short, meta = "", help = "Off with his head!!!")]
|
||||
pub off_with_his_head: Option<bool>,
|
||||
#[options(command)]
|
||||
pub command: Option<AnimeActions>,
|
||||
}
|
||||
@@ -43,15 +61,27 @@ pub enum AnimeActions {
|
||||
pub struct Builtins {
|
||||
#[options(help = "print help message")]
|
||||
pub help: bool,
|
||||
#[options(meta = "", help = " <GlitchConstruction, StaticEmergence>")]
|
||||
#[options(
|
||||
meta = "",
|
||||
help = "Default is used if unspecified, <default:GlitchConstruction, StaticEmergence>"
|
||||
)]
|
||||
pub boot: AnimBooting,
|
||||
#[options(meta = "", help = "<BinaryBannerScroll, RogLogoGlitch>")]
|
||||
#[options(
|
||||
meta = "",
|
||||
help = "Default is used if unspecified, <default:BinaryBannerScroll, RogLogoGlitch>"
|
||||
)]
|
||||
pub awake: AnimAwake,
|
||||
#[options(meta = "", help = "<BannerSwipe, Starfield>")]
|
||||
#[options(
|
||||
meta = "",
|
||||
help = "Default is used if unspecified, <default:BannerSwipe, Starfield>"
|
||||
)]
|
||||
pub sleep: AnimSleeping,
|
||||
#[options(meta = "", help = "<GlitchOut, SeeYa>")]
|
||||
#[options(
|
||||
meta = "",
|
||||
help = "Default is used if unspecified, <default:GlitchOut, SeeYa>"
|
||||
)]
|
||||
pub shutdown: AnimShutdown,
|
||||
#[options(meta = "", help = "set/apply the animations")]
|
||||
#[options(meta = "", help = "set/apply the animations <true/false>")]
|
||||
pub set: Option<bool>,
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ use gumdrop::Options;
|
||||
use rog_aura::error::Error;
|
||||
use rog_aura::{AuraEffect, AuraModeNum, AuraZone, Colour, Direction, Speed};
|
||||
|
||||
#[derive(Options)]
|
||||
#[derive(Options, Debug)]
|
||||
pub struct LedPowerCommand1 {
|
||||
#[options(help = "print help message")]
|
||||
pub help: bool,
|
||||
@@ -20,73 +20,53 @@ pub struct LedPowerCommand1 {
|
||||
pub sleep: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Options)]
|
||||
#[derive(Options, Debug)]
|
||||
pub struct LedPowerCommand2 {
|
||||
#[options(help = "print help message")]
|
||||
pub help: bool,
|
||||
#[options(command)]
|
||||
pub command: Option<SetAuraEnabled>,
|
||||
pub command: Option<SetAuraZoneEnabled>,
|
||||
}
|
||||
|
||||
#[derive(Options)]
|
||||
pub enum SetAuraEnabled {
|
||||
#[derive(Options, Debug)]
|
||||
pub enum SetAuraZoneEnabled {
|
||||
/// Applies to both old and new models
|
||||
#[options(help = "set <keyboard, logo, lightbar, rearglow> to enabled while device is awake")]
|
||||
Awake(AuraEnabled),
|
||||
#[options(
|
||||
help = "set <keyboard, logo, lightbar, rearglow> to enabled while the device is booting"
|
||||
)]
|
||||
Boot(AuraEnabled),
|
||||
#[options(
|
||||
help = "set <keyboard, logo, lightbar, rearglow> to animate while the device is suspended"
|
||||
)]
|
||||
Sleep(AuraEnabled),
|
||||
#[options(
|
||||
help = "set <keyboard, logo, lightbar, rearglow> to animate while the device is shutdown"
|
||||
)]
|
||||
Shutdown(AuraEnabled),
|
||||
#[options(help = "")]
|
||||
Keyboard(AuraPowerStates),
|
||||
#[options(help = "")]
|
||||
Logo(AuraPowerStates),
|
||||
#[options(help = "")]
|
||||
Lightbar(AuraPowerStates),
|
||||
#[options(help = "")]
|
||||
Lid(AuraPowerStates),
|
||||
#[options(help = "")]
|
||||
RearGlow(AuraPowerStates),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Options)]
|
||||
pub struct AuraEnabled {
|
||||
#[derive(Debug, Clone, Options)]
|
||||
pub struct AuraPowerStates {
|
||||
#[options(help = "print help message")]
|
||||
pub help: bool,
|
||||
#[options(meta = "", help = "<true/false>")]
|
||||
pub keyboard: Option<bool>,
|
||||
#[options(meta = "", help = "<true/false>")]
|
||||
pub logo: Option<bool>,
|
||||
#[options(meta = "", help = "<true/false>")]
|
||||
pub frontglow: Option<bool>,
|
||||
#[options(meta = "", help = "<true/false>")]
|
||||
pub rearglow: Option<bool>,
|
||||
#[options(meta = "", help = "<true/false>")]
|
||||
pub lid: Option<bool>,
|
||||
#[options(help = "defaults to false if option unused")]
|
||||
pub boot: bool,
|
||||
#[options(help = "defaults to false if option unused")]
|
||||
pub awake: bool,
|
||||
#[options(help = "defaults to false if option unused")]
|
||||
pub sleep: bool,
|
||||
#[options(help = "defaults to false if option unused")]
|
||||
pub shutdown: bool,
|
||||
}
|
||||
|
||||
// impl FromStr for AuraEnabled {
|
||||
// type Err = Error;
|
||||
|
||||
// fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
// let s = s.to_lowercase();
|
||||
// Ok(Self {
|
||||
// help: false,
|
||||
// keyboard: None,
|
||||
// logo: None,
|
||||
// lightbar: None,
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
|
||||
#[derive(Options)]
|
||||
pub struct LedBrightness {
|
||||
level: Option<u32>,
|
||||
level: Option<u8>,
|
||||
}
|
||||
impl LedBrightness {
|
||||
pub fn new(level: Option<u32>) -> Self {
|
||||
pub fn new(level: Option<u8>) -> Self {
|
||||
LedBrightness { level }
|
||||
}
|
||||
|
||||
pub fn level(&self) -> Option<u32> {
|
||||
pub fn level(&self) -> Option<u8> {
|
||||
self.level
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
use gumdrop::Options;
|
||||
use rog_platform::platform::ThrottlePolicy;
|
||||
|
||||
use crate::anime_cli::AnimeCommand;
|
||||
use crate::aura_cli::{LedBrightness, LedPowerCommand1, LedPowerCommand2, SetAuraBuiltin};
|
||||
use crate::profiles_cli::{FanCurveCommand, ProfileCommand};
|
||||
use crate::fan_curve_cli::FanCurveCommand;
|
||||
|
||||
#[derive(Default, Options)]
|
||||
pub struct CliStart {
|
||||
@@ -44,6 +45,24 @@ pub enum CliCommand {
|
||||
Bios(BiosCommand),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Options)]
|
||||
pub struct ProfileCommand {
|
||||
#[options(help = "print help message")]
|
||||
pub help: bool,
|
||||
|
||||
#[options(help = "toggle to next profile in list")]
|
||||
pub next: bool,
|
||||
|
||||
#[options(help = "list available profiles")]
|
||||
pub list: bool,
|
||||
|
||||
#[options(help = "get profile")]
|
||||
pub profile_get: bool,
|
||||
|
||||
#[options(meta = "", help = "set the active profile")]
|
||||
pub profile_set: Option<ThrottlePolicy>,
|
||||
}
|
||||
|
||||
#[derive(Options)]
|
||||
pub struct LedModeCommand {
|
||||
#[options(help = "print help message")]
|
||||
|
||||
49
asusctl/src/fan_curve_cli.rs
Normal file
49
asusctl/src/fan_curve_cli.rs
Normal file
@@ -0,0 +1,49 @@
|
||||
use gumdrop::Options;
|
||||
use rog_platform::platform::ThrottlePolicy;
|
||||
use rog_profiles::fan_curve_set::CurveData;
|
||||
use rog_profiles::FanCurvePU;
|
||||
|
||||
#[derive(Debug, Clone, Options)]
|
||||
pub struct FanCurveCommand {
|
||||
#[options(help = "print help message")]
|
||||
pub help: bool,
|
||||
|
||||
#[options(help = "get enabled fan profiles")]
|
||||
pub get_enabled: bool,
|
||||
|
||||
#[options(help = "set the active profile's fan curve to default")]
|
||||
pub default: bool,
|
||||
|
||||
#[options(
|
||||
meta = "",
|
||||
help = "profile to modify fan-curve for. Shows data if no options provided"
|
||||
)]
|
||||
pub mod_profile: Option<ThrottlePolicy>,
|
||||
|
||||
#[options(
|
||||
meta = "",
|
||||
help = "enable or disable <true/false> fan all curves for a profile. `--mod_profile` \
|
||||
required"
|
||||
)]
|
||||
pub enable_fan_curves: Option<bool>,
|
||||
|
||||
#[options(
|
||||
meta = "",
|
||||
help = "enable or disable <true/false> a single fan curve for a profile. `--mod_profile` \
|
||||
and `--fan` required"
|
||||
)]
|
||||
pub enable_fan_curve: Option<bool>,
|
||||
|
||||
#[options(
|
||||
meta = "",
|
||||
help = "select fan <cpu/gpu/mid> to modify. `--mod_profile` required"
|
||||
)]
|
||||
pub fan: Option<FanCurvePU>,
|
||||
|
||||
#[options(
|
||||
meta = "",
|
||||
help = "data format = 30c:1%,49c:2%,59c:3%,69c:4%,79c:31%,89c:49%,99c:56%,109c:58%. \
|
||||
`--mod-profile` required. If '%' is omitted the fan range is 0-255"
|
||||
)]
|
||||
pub data: Option<CurveData>,
|
||||
}
|
||||
@@ -5,25 +5,29 @@ use std::process::Command;
|
||||
use std::thread::sleep;
|
||||
|
||||
use anime_cli::{AnimeActions, AnimeCommand};
|
||||
use asusd::ctrl_aura::trait_impls::AURA_ZBUS_NAME;
|
||||
use asusd::ctrl_fancurves::FAN_CURVE_ZBUS_NAME;
|
||||
use aura_cli::{LedPowerCommand1, LedPowerCommand2};
|
||||
use dmi_id::DMIID;
|
||||
use fan_curve_cli::FanCurveCommand;
|
||||
use gumdrop::{Opt, Options};
|
||||
use profiles_cli::{FanCurveCommand, ProfileCommand};
|
||||
use rog_anime::usb::get_anime_type;
|
||||
use rog_anime::{AnimTime, AnimeDataBuffer, AnimeDiagonal, AnimeGif, AnimeImage, AnimeType, Vec2};
|
||||
use rog_aura::usb::{AuraDevRog1, AuraDevRog2, AuraDevTuf, AuraDevice, AuraPowerDev};
|
||||
use rog_aura::power::KbAuraPowerState;
|
||||
use rog_aura::usb::{AuraDevRog1, AuraDevTuf, AuraPowerDev};
|
||||
use rog_aura::{self, AuraEffect};
|
||||
use rog_dbus::RogDbusClientBlocking;
|
||||
use rog_platform::platform::GpuMode;
|
||||
use rog_platform::supported::*;
|
||||
use rog_platform::error::PlatformError;
|
||||
use rog_platform::platform::{GpuMode, Properties, ThrottlePolicy};
|
||||
use rog_profiles::error::ProfileError;
|
||||
|
||||
use crate::aura_cli::LedBrightness;
|
||||
use crate::aura_cli::{AuraPowerStates, LedBrightness};
|
||||
use crate::cli_opts::*;
|
||||
|
||||
mod anime_cli;
|
||||
mod aura_cli;
|
||||
mod cli_opts;
|
||||
mod profiles_cli;
|
||||
mod fan_curve_cli;
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = args().skip(1).collect();
|
||||
@@ -42,43 +46,42 @@ fn main() {
|
||||
};
|
||||
|
||||
if let Ok((dbus, _)) = RogDbusClientBlocking::new().map_err(|e| {
|
||||
print_error_help(&e, None);
|
||||
check_service("asusd");
|
||||
println!("\nError: {e}\n");
|
||||
print_info();
|
||||
}) {
|
||||
if let Ok(supported) = dbus
|
||||
.proxies()
|
||||
.supported()
|
||||
.supported_functions()
|
||||
.map_err(|e| {
|
||||
print_error_help(&e, None);
|
||||
})
|
||||
{
|
||||
if parsed.version {
|
||||
println!("asusctl v{}", env!("CARGO_PKG_VERSION"));
|
||||
println!();
|
||||
print_info();
|
||||
}
|
||||
let supported_properties = dbus.proxies().platform().supported_properties().unwrap();
|
||||
let supported_interfaces = dbus.proxies().platform().supported_interfaces().unwrap();
|
||||
|
||||
if let Err(err) = do_parsed(&parsed, &supported, &dbus) {
|
||||
print_error_help(&*err, Some(&supported));
|
||||
}
|
||||
if parsed.version {
|
||||
println!("asusctl v{}", env!("CARGO_PKG_VERSION"));
|
||||
println!();
|
||||
print_info();
|
||||
}
|
||||
|
||||
if let Err(err) = do_parsed(&parsed, &supported_interfaces, &supported_properties, &dbus) {
|
||||
print_error_help(&*err, &supported_interfaces, &supported_properties);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn print_error_help(err: &dyn std::error::Error, supported: Option<&SupportedFunctions>) {
|
||||
fn print_error_help(
|
||||
err: &dyn std::error::Error,
|
||||
supported_interfaces: &[String],
|
||||
supported_properties: &[Properties],
|
||||
) {
|
||||
check_service("asusd");
|
||||
println!("\nError: {}\n", err);
|
||||
print_info();
|
||||
if let Some(supported) = supported {
|
||||
println!();
|
||||
println!("Supported laptop functions:\n\n{}", supported);
|
||||
}
|
||||
println!();
|
||||
println!("Supported interfaces:\n\n{:#?}\n", supported_interfaces);
|
||||
println!("Supported properties:\n\n{:#?}\n", supported_properties);
|
||||
}
|
||||
|
||||
fn print_info() {
|
||||
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 dmi = DMIID::new().unwrap_or_default();
|
||||
let board_name = dmi.board_name;
|
||||
let prod_family = dmi.product_family;
|
||||
println!("asusctl version: {}", env!("CARGO_PKG_VERSION"));
|
||||
println!(" Product family: {}", prod_family.trim());
|
||||
println!(" Board name: {}", board_name.trim());
|
||||
@@ -103,20 +106,21 @@ fn check_service(name: &str) -> bool {
|
||||
|
||||
fn do_parsed(
|
||||
parsed: &CliStart,
|
||||
supported: &SupportedFunctions,
|
||||
supported_interfaces: &[String],
|
||||
supported_properties: &[Properties],
|
||||
dbus: &RogDbusClientBlocking<'_>,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
match &parsed.command {
|
||||
Some(CliCommand::LedMode(mode)) => handle_led_mode(dbus, &supported.keyboard_led, mode)?,
|
||||
Some(CliCommand::LedPow1(pow)) => handle_led_power1(dbus, &supported.keyboard_led, pow)?,
|
||||
Some(CliCommand::LedPow2(pow)) => handle_led_power2(dbus, &supported.keyboard_led, pow)?,
|
||||
Some(CliCommand::Profile(cmd)) => handle_profile(dbus, &supported.platform_profile, cmd)?,
|
||||
Some(CliCommand::LedMode(mode)) => handle_led_mode(dbus, supported_interfaces, mode)?,
|
||||
Some(CliCommand::LedPow1(pow)) => handle_led_power1(dbus, supported_interfaces, pow)?,
|
||||
Some(CliCommand::LedPow2(pow)) => handle_led_power2(dbus, supported_interfaces, pow)?,
|
||||
Some(CliCommand::Profile(cmd)) => handle_throttle_profile(dbus, supported_properties, cmd)?,
|
||||
Some(CliCommand::FanCurve(cmd)) => {
|
||||
handle_fan_curve(dbus, &supported.platform_profile, cmd)?;
|
||||
handle_fan_curve(dbus, supported_interfaces, cmd)?;
|
||||
}
|
||||
Some(CliCommand::Graphics(_)) => do_gfx(),
|
||||
Some(CliCommand::Anime(cmd)) => handle_anime(dbus, &supported.anime_ctrl, cmd)?,
|
||||
Some(CliCommand::Bios(cmd)) => handle_bios_option(dbus, &supported.rog_bios_ctrl, cmd)?,
|
||||
Some(CliCommand::Anime(cmd)) => handle_anime(dbus, cmd)?,
|
||||
Some(CliCommand::Bios(cmd)) => handle_platform_properties(dbus, supported_properties, cmd)?,
|
||||
None => {
|
||||
if (!parsed.show_supported
|
||||
&& parsed.kbd_bright.is_none()
|
||||
@@ -128,21 +132,16 @@ fn do_parsed(
|
||||
println!("{}", CliStart::usage());
|
||||
println!();
|
||||
if let Some(cmdlist) = CliStart::command_list() {
|
||||
let dev_type = dbus.proxies().aura().device_type()?;
|
||||
let commands: Vec<String> = cmdlist.lines().map(|s| s.to_owned()).collect();
|
||||
for command in commands.iter().filter(|command| {
|
||||
if !matches!(
|
||||
supported.keyboard_led.dev_id,
|
||||
AuraDevice::X1854
|
||||
| AuraDevice::X1869
|
||||
| AuraDevice::X1866
|
||||
| AuraDevice::Tuf
|
||||
) && command.trim().starts_with("led-pow-1")
|
||||
if !dev_type.is_old_style()
|
||||
&& !dev_type.is_tuf_style()
|
||||
&& command.trim().starts_with("led-pow-1")
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if supported.keyboard_led.dev_id != AuraDevice::X19b6
|
||||
&& command.trim().starts_with("led-pow-2")
|
||||
{
|
||||
if !dev_type.is_new_style() && command.trim().starts_with("led-pow-2") {
|
||||
return false;
|
||||
}
|
||||
true
|
||||
@@ -161,31 +160,47 @@ fn do_parsed(
|
||||
if let Some(brightness) = &parsed.kbd_bright {
|
||||
match brightness.level() {
|
||||
None => {
|
||||
let level = dbus.proxies().led().led_brightness()?;
|
||||
println!("Current keyboard led brightness: {}", level);
|
||||
let level = dbus.proxies().aura().brightness()?;
|
||||
println!("Current keyboard led brightness: {level:?}");
|
||||
}
|
||||
Some(level) => dbus
|
||||
.proxies()
|
||||
.led()
|
||||
.set_brightness(<rog_aura::LedBrightness>::from(level))?,
|
||||
.aura()
|
||||
.set_brightness(rog_aura::LedBrightness::from(level))?,
|
||||
}
|
||||
}
|
||||
|
||||
if parsed.next_kbd_bright {
|
||||
dbus.proxies().led().next_led_brightness()?;
|
||||
let brightness = dbus.proxies().aura().brightness()?;
|
||||
dbus.proxies().aura().set_brightness(brightness.next())?;
|
||||
}
|
||||
|
||||
if parsed.prev_kbd_bright {
|
||||
dbus.proxies().led().prev_led_brightness()?;
|
||||
let brightness = dbus.proxies().aura().brightness()?;
|
||||
dbus.proxies().aura().set_brightness(brightness.prev())?;
|
||||
}
|
||||
|
||||
if parsed.show_supported {
|
||||
println!("Supported laptop functions:\n\n{}", supported);
|
||||
println!("Supported Core Functions:\n{:#?}", supported_interfaces);
|
||||
println!(
|
||||
"Supported Platform Properties:\n{:#?}",
|
||||
supported_properties
|
||||
);
|
||||
if supported_interfaces.contains(&"Aura".to_owned()) {
|
||||
let bright = dbus.proxies().aura().supported_brightness()?;
|
||||
let modes = dbus.proxies().aura().supported_basic_modes()?;
|
||||
let zones = dbus.proxies().aura().supported_basic_zones()?;
|
||||
let power = dbus.proxies().aura().supported_power_zones()?;
|
||||
println!("Supported Keyboard Brightness:\n{:#?}", bright);
|
||||
println!("Supported Aura Modes:\n{:#?}", modes);
|
||||
println!("Supported Aura Zones:\n{:#?}", zones);
|
||||
println!("Supported Aura Power Zones:\n{:#?}", power);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(chg_limit) = parsed.chg_limit {
|
||||
dbus.proxies()
|
||||
.charge()
|
||||
.platform()
|
||||
.set_charge_control_end_threshold(chg_limit)?;
|
||||
}
|
||||
|
||||
@@ -202,14 +217,16 @@ fn do_gfx() {
|
||||
|
||||
fn handle_anime(
|
||||
dbus: &RogDbusClientBlocking<'_>,
|
||||
_supported: &AnimeSupportedFunctions,
|
||||
cmd: &AnimeCommand,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
if (cmd.command.is_none()
|
||||
&& cmd.enable_display.is_none()
|
||||
&& cmd.enable_powersave_anim.is_none()
|
||||
&& cmd.brightness.is_none()
|
||||
&& cmd.image_brightness.is_none()
|
||||
&& cmd.off_when_lid_closed.is_none()
|
||||
&& cmd.off_when_suspended.is_none()
|
||||
&& cmd.off_when_unplugged.is_none()
|
||||
&& cmd.off_with_his_head.is_none()
|
||||
&& !cmd.clear)
|
||||
|| cmd.help
|
||||
{
|
||||
@@ -227,9 +244,17 @@ fn handle_anime(
|
||||
if let Some(bright) = cmd.brightness {
|
||||
dbus.proxies().anime().set_brightness(bright)?;
|
||||
}
|
||||
if let Some(bright) = cmd.image_brightness {
|
||||
verify_brightness(bright);
|
||||
dbus.proxies().anime().set_image_brightness(bright)?;
|
||||
if let Some(enable) = cmd.off_when_lid_closed {
|
||||
dbus.proxies().anime().set_off_when_lid_closed(enable)?;
|
||||
}
|
||||
if let Some(enable) = cmd.off_when_suspended {
|
||||
dbus.proxies().anime().set_off_when_suspended(enable)?;
|
||||
}
|
||||
if let Some(enable) = cmd.off_when_unplugged {
|
||||
dbus.proxies().anime().set_off_when_unplugged(enable)?;
|
||||
}
|
||||
if cmd.off_with_his_head.is_some() {
|
||||
println!("Did Alice _really_ make it back from Wonderland?");
|
||||
}
|
||||
|
||||
let mut anime_type = get_anime_type()?;
|
||||
@@ -366,12 +391,14 @@ fn handle_anime(
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
dbus.proxies().anime().set_builtin_animations(
|
||||
builtins.boot,
|
||||
builtins.awake,
|
||||
builtins.sleep,
|
||||
builtins.shutdown,
|
||||
)?;
|
||||
dbus.proxies()
|
||||
.anime()
|
||||
.set_builtin_animations(rog_anime::Animations {
|
||||
boot: builtins.boot,
|
||||
awake: builtins.awake,
|
||||
sleep: builtins.sleep,
|
||||
shutdown: builtins.shutdown,
|
||||
})?;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -389,9 +416,14 @@ fn verify_brightness(brightness: f32) {
|
||||
|
||||
fn handle_led_mode(
|
||||
dbus: &RogDbusClientBlocking<'_>,
|
||||
supported: &LedSupportedFunctions,
|
||||
supported: &[String],
|
||||
mode: &LedModeCommand,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
if !supported.contains(&AURA_ZBUS_NAME.to_string()) {
|
||||
println!("This laptop does not support power options");
|
||||
return Err(PlatformError::NotSupported.into());
|
||||
}
|
||||
|
||||
if mode.command.is_none() && !mode.prev_mode && !mode.next_mode {
|
||||
if !mode.help {
|
||||
println!("Missing arg or command\n");
|
||||
@@ -401,8 +433,9 @@ fn handle_led_mode(
|
||||
|
||||
if let Some(cmdlist) = LedModeCommand::command_list() {
|
||||
let commands: Vec<String> = cmdlist.lines().map(|s| s.to_owned()).collect();
|
||||
let modes = dbus.proxies().aura().supported_basic_modes()?;
|
||||
for command in commands.iter().filter(|command| {
|
||||
for mode in &supported.basic_modes {
|
||||
for mode in &modes {
|
||||
if command
|
||||
.trim()
|
||||
.starts_with(&<&str>::from(mode).to_lowercase())
|
||||
@@ -410,9 +443,10 @@ fn handle_led_mode(
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if !supported.basic_zones.is_empty() && command.trim().starts_with("multi") {
|
||||
return true;
|
||||
}
|
||||
// TODO
|
||||
// if !supported.basic_zones.is_empty() && command.trim().starts_with("multi") {
|
||||
// return true;
|
||||
// }
|
||||
false
|
||||
}) {
|
||||
println!("{}", command);
|
||||
@@ -428,17 +462,31 @@ fn handle_led_mode(
|
||||
return Ok(());
|
||||
}
|
||||
if mode.next_mode {
|
||||
dbus.proxies().led().next_led_mode()?;
|
||||
let mode = dbus.proxies().aura().led_mode()?;
|
||||
let modes = dbus.proxies().aura().supported_basic_modes()?;
|
||||
let mut pos = modes.iter().position(|m| *m == mode).unwrap() + 1;
|
||||
if pos >= modes.len() {
|
||||
pos = 0;
|
||||
}
|
||||
dbus.proxies().aura().set_led_mode(modes[pos])?;
|
||||
} else if mode.prev_mode {
|
||||
dbus.proxies().led().prev_led_mode()?;
|
||||
let mode = dbus.proxies().aura().led_mode()?;
|
||||
let modes = dbus.proxies().aura().supported_basic_modes()?;
|
||||
let mut pos = modes.iter().position(|m| *m == mode).unwrap();
|
||||
if pos == 0 {
|
||||
pos = modes.len() - 1;
|
||||
} else {
|
||||
pos -= 1;
|
||||
}
|
||||
dbus.proxies().aura().set_led_mode(modes[pos])?;
|
||||
} else if let Some(mode) = mode.command.as_ref() {
|
||||
if mode.help_requested() {
|
||||
println!("{}", mode.self_usage());
|
||||
return Ok(());
|
||||
}
|
||||
dbus.proxies()
|
||||
.led()
|
||||
.set_led_mode(&<AuraEffect>::from(mode))?;
|
||||
.aura()
|
||||
.set_led_mode_data(<AuraEffect>::from(mode))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -446,9 +494,18 @@ fn handle_led_mode(
|
||||
|
||||
fn handle_led_power1(
|
||||
dbus: &RogDbusClientBlocking<'_>,
|
||||
supported: &LedSupportedFunctions,
|
||||
supported: &[String],
|
||||
power: &LedPowerCommand1,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
if !supported.contains(&AURA_ZBUS_NAME.to_string()) {
|
||||
println!("This laptop does not support power options");
|
||||
return Err(PlatformError::NotSupported.into());
|
||||
}
|
||||
let dev_type = dbus.proxies().aura().device_type()?;
|
||||
if !dev_type.is_old_style() && !dev_type.is_tuf_style() {
|
||||
println!("This option applies only to keyboards 2021+");
|
||||
}
|
||||
|
||||
if power.awake.is_none()
|
||||
&& power.sleep.is_none()
|
||||
&& power.boot.is_none()
|
||||
@@ -462,15 +519,12 @@ fn handle_led_power1(
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if matches!(
|
||||
supported.dev_id,
|
||||
AuraDevice::X1854 | AuraDevice::X1869 | AuraDevice::X1866
|
||||
) {
|
||||
if dev_type.is_old_style() {
|
||||
handle_led_power_1_do_1866(dbus, power)?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if matches!(supported.dev_id, AuraDevice::Tuf) {
|
||||
if dev_type.is_tuf_style() {
|
||||
handle_led_power_1_do_tuf(dbus, power)?;
|
||||
return Ok(());
|
||||
}
|
||||
@@ -503,18 +557,16 @@ fn handle_led_power_1_do_1866(
|
||||
check(power.lightbar, AuraDevRog1::Lightbar);
|
||||
|
||||
let data = AuraPowerDev {
|
||||
x1866: enabled,
|
||||
x19b6: vec![],
|
||||
tuf: vec![],
|
||||
old_rog: enabled,
|
||||
..Default::default()
|
||||
};
|
||||
dbus.proxies().led().set_leds_power(data, true)?;
|
||||
dbus.proxies().aura().set_led_power((data, true))?;
|
||||
|
||||
let data = AuraPowerDev {
|
||||
x1866: disabled,
|
||||
x19b6: vec![],
|
||||
tuf: vec![],
|
||||
old_rog: disabled,
|
||||
..Default::default()
|
||||
};
|
||||
dbus.proxies().led().set_leds_power(data, false)?;
|
||||
dbus.proxies().aura().set_led_power((data, false))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -542,27 +594,34 @@ fn handle_led_power_1_do_tuf(
|
||||
check(power.keyboard, AuraDevTuf::Keyboard);
|
||||
|
||||
let data = AuraPowerDev {
|
||||
x1866: vec![],
|
||||
x19b6: vec![],
|
||||
tuf: enabled,
|
||||
..Default::default()
|
||||
};
|
||||
dbus.proxies().led().set_leds_power(data, true)?;
|
||||
dbus.proxies().aura().set_led_power((data, true))?;
|
||||
|
||||
let data = AuraPowerDev {
|
||||
x1866: vec![],
|
||||
x19b6: vec![],
|
||||
tuf: disabled,
|
||||
..Default::default()
|
||||
};
|
||||
dbus.proxies().led().set_leds_power(data, false)?;
|
||||
dbus.proxies().aura().set_led_power((data, false))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_led_power2(
|
||||
dbus: &RogDbusClientBlocking<'_>,
|
||||
supported: &LedSupportedFunctions,
|
||||
supported: &[String],
|
||||
power: &LedPowerCommand2,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
if !supported.contains(&AURA_ZBUS_NAME.to_string()) {
|
||||
println!("This laptop does not support power options");
|
||||
return Err(PlatformError::NotSupported.into());
|
||||
}
|
||||
let dev_type = dbus.proxies().aura().device_type()?;
|
||||
if !dev_type.is_new_style() {
|
||||
println!("This option applies only to keyboards 2021+");
|
||||
}
|
||||
|
||||
if power.command().is_none() {
|
||||
if !power.help {
|
||||
println!("Missing arg or command\n");
|
||||
@@ -587,81 +646,36 @@ fn handle_led_power2(
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if supported.dev_id != AuraDevice::X19b6 {
|
||||
println!("This option applies only to keyboards with product ID 0x19b6");
|
||||
}
|
||||
|
||||
let mut enabled: Vec<AuraDevRog2> = Vec::new();
|
||||
let mut disabled: Vec<AuraDevRog2> = Vec::new();
|
||||
let mut check = |e: Option<bool>, a: AuraDevRog2| {
|
||||
if let Some(arg) = e {
|
||||
if arg {
|
||||
enabled.push(a);
|
||||
} else {
|
||||
disabled.push(a);
|
||||
}
|
||||
}
|
||||
let set = |power: &mut KbAuraPowerState, set_to: &AuraPowerStates| {
|
||||
power.boot = set_to.boot;
|
||||
power.awake = set_to.awake;
|
||||
power.sleep = set_to.sleep;
|
||||
power.shutdown = set_to.shutdown;
|
||||
};
|
||||
|
||||
match pow {
|
||||
aura_cli::SetAuraEnabled::Boot(arg) => {
|
||||
check(arg.keyboard, AuraDevRog2::BootKeyb);
|
||||
check(arg.logo, AuraDevRog2::BootLogo);
|
||||
check(arg.frontglow, AuraDevRog2::BootBar);
|
||||
check(arg.rearglow, AuraDevRog2::BootRearGlow);
|
||||
check(arg.lid, AuraDevRog2::AwakeLid);
|
||||
}
|
||||
aura_cli::SetAuraEnabled::Sleep(arg) => {
|
||||
check(arg.keyboard, AuraDevRog2::SleepKeyb);
|
||||
check(arg.logo, AuraDevRog2::SleepLogo);
|
||||
check(arg.frontglow, AuraDevRog2::SleepBar);
|
||||
check(arg.rearglow, AuraDevRog2::SleepRearGlow);
|
||||
check(arg.lid, AuraDevRog2::SleepLid);
|
||||
}
|
||||
aura_cli::SetAuraEnabled::Awake(arg) => {
|
||||
check(arg.keyboard, AuraDevRog2::AwakeKeyb);
|
||||
check(arg.logo, AuraDevRog2::AwakeLogo);
|
||||
check(arg.frontglow, AuraDevRog2::AwakeBar);
|
||||
check(arg.rearglow, AuraDevRog2::AwakeRearGlow);
|
||||
check(arg.lid, AuraDevRog2::AwakeLid);
|
||||
}
|
||||
aura_cli::SetAuraEnabled::Shutdown(arg) => {
|
||||
check(arg.keyboard, AuraDevRog2::ShutdownKeyb);
|
||||
check(arg.logo, AuraDevRog2::ShutdownLogo);
|
||||
check(arg.frontglow, AuraDevRog2::ShutdownBar);
|
||||
check(arg.rearglow, AuraDevRog2::ShutdownRearGlow);
|
||||
check(arg.lid, AuraDevRog2::ShutdownLid);
|
||||
let mut enabled = dbus.proxies().aura().led_power()?;
|
||||
if let Some(cmd) = &power.command {
|
||||
match cmd {
|
||||
aura_cli::SetAuraZoneEnabled::Keyboard(k) => set(&mut enabled.rog.keyboard, k),
|
||||
aura_cli::SetAuraZoneEnabled::Logo(l) => set(&mut enabled.rog.logo, l),
|
||||
aura_cli::SetAuraZoneEnabled::Lightbar(l) => set(&mut enabled.rog.lightbar, l),
|
||||
aura_cli::SetAuraZoneEnabled::Lid(l) => set(&mut enabled.rog.lid, l),
|
||||
aura_cli::SetAuraZoneEnabled::RearGlow(r) => set(&mut enabled.rog.rear_glow, r),
|
||||
}
|
||||
}
|
||||
|
||||
if !enabled.is_empty() {
|
||||
let data = AuraPowerDev {
|
||||
tuf: vec![],
|
||||
x1866: vec![],
|
||||
x19b6: enabled,
|
||||
};
|
||||
dbus.proxies().led().set_leds_power(data, true)?;
|
||||
}
|
||||
|
||||
if !disabled.is_empty() {
|
||||
let data = AuraPowerDev {
|
||||
tuf: vec![],
|
||||
x1866: vec![],
|
||||
x19b6: disabled,
|
||||
};
|
||||
dbus.proxies().led().set_leds_power(data, false)?;
|
||||
}
|
||||
dbus.proxies().aura().set_led_power((enabled, true))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_profile(
|
||||
fn handle_throttle_profile(
|
||||
dbus: &RogDbusClientBlocking<'_>,
|
||||
supported: &PlatformProfileFunctions,
|
||||
supported: &[Properties],
|
||||
cmd: &ProfileCommand,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
if !supported.platform_profile {
|
||||
if !supported.contains(&Properties::ThrottlePolicy) {
|
||||
println!("Profiles not supported by either this kernel or by the laptop.");
|
||||
return Err(ProfileError::NotSupported.into());
|
||||
}
|
||||
@@ -677,23 +691,27 @@ fn handle_profile(
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
let current = dbus.proxies().platform().throttle_thermal_policy()?;
|
||||
|
||||
if cmd.next {
|
||||
dbus.proxies().profile().next_profile()?;
|
||||
dbus.proxies()
|
||||
.platform()
|
||||
.set_throttle_thermal_policy(current.next())?;
|
||||
} else if let Some(profile) = cmd.profile_set {
|
||||
dbus.proxies().profile().set_active_profile(profile)?;
|
||||
dbus.proxies()
|
||||
.platform()
|
||||
.set_throttle_thermal_policy(profile)?;
|
||||
}
|
||||
|
||||
if cmd.list {
|
||||
let res = dbus.proxies().profile().profiles()?;
|
||||
let res = ThrottlePolicy::list();
|
||||
for p in &res {
|
||||
println!("{:?}", p);
|
||||
}
|
||||
}
|
||||
|
||||
if cmd.profile_get {
|
||||
let res = dbus.proxies().profile().active_profile()?;
|
||||
println!("Active profile is {:?}", res);
|
||||
println!("Active profile is {current:?}");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -701,12 +719,11 @@ fn handle_profile(
|
||||
|
||||
fn handle_fan_curve(
|
||||
dbus: &RogDbusClientBlocking<'_>,
|
||||
supported: &PlatformProfileFunctions,
|
||||
supported: &[String],
|
||||
cmd: &FanCurveCommand,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
if !supported.fan_curves {
|
||||
if !supported.contains(&FAN_CURVE_ZBUS_NAME.to_string()) {
|
||||
println!("Fan-curves not supported by either this kernel or by the laptop.");
|
||||
println!("This requires kernel 5.17 or the fan curve patch listed in the readme.");
|
||||
return Err(ProfileError::NotSupported.into());
|
||||
}
|
||||
|
||||
@@ -722,48 +739,67 @@ fn handle_fan_curve(
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if (cmd.enabled.is_some() || cmd.fan.is_some() || cmd.data.is_some())
|
||||
if (cmd.enable_fan_curves.is_some() || cmd.fan.is_some() || cmd.data.is_some())
|
||||
&& cmd.mod_profile.is_none()
|
||||
{
|
||||
println!("--enabled, --fan, and --data options require --mod-profile");
|
||||
println!(
|
||||
"--enable-fan-curves, --enable-fan-curve, --fan, and --data options require \
|
||||
--mod-profile"
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if cmd.get_enabled {
|
||||
let res = dbus.proxies().profile().enabled_fan_profiles()?;
|
||||
println!("{:?}", res);
|
||||
let profile = dbus.proxies().platform().throttle_thermal_policy()?;
|
||||
let curves = dbus.proxies().fan_curves().fan_curve_data(profile)?;
|
||||
for curve in curves.iter() {
|
||||
println!("{}", String::from(curve));
|
||||
}
|
||||
}
|
||||
|
||||
if cmd.default {
|
||||
dbus.proxies().profile().set_active_curve_to_defaults()?;
|
||||
dbus.proxies().fan_curves().set_active_curve_to_defaults()?;
|
||||
}
|
||||
|
||||
if let Some(profile) = cmd.mod_profile {
|
||||
if cmd.enabled.is_none() && cmd.data.is_none() {
|
||||
let data = dbus.proxies().profile().fan_curve_data(profile)?;
|
||||
if cmd.enable_fan_curves.is_none() && cmd.data.is_none() {
|
||||
let data = dbus.proxies().fan_curves().fan_curve_data(profile)?;
|
||||
let data = toml::to_string(&data)?;
|
||||
println!("\nFan curves for {:?}\n\n{}", profile, data);
|
||||
}
|
||||
|
||||
if let Some(enabled) = cmd.enabled {
|
||||
if let Some(enabled) = cmd.enable_fan_curves {
|
||||
dbus.proxies()
|
||||
.profile()
|
||||
.set_fan_curve_enabled(profile, enabled)?;
|
||||
.fan_curves()
|
||||
.set_fan_curves_enabled(profile, enabled)?;
|
||||
}
|
||||
|
||||
if let Some(enabled) = cmd.enable_fan_curve {
|
||||
if let Some(fan) = cmd.fan {
|
||||
dbus.proxies()
|
||||
.fan_curves()
|
||||
.set_profile_fan_curve_enabled(profile, fan, enabled)?;
|
||||
} else {
|
||||
println!(
|
||||
"--enable-fan-curves, --enable-fan-curve, --fan, and --data options require \
|
||||
--mod-profile"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(mut curve) = cmd.data.clone() {
|
||||
let fan = cmd.fan.unwrap_or_default();
|
||||
curve.set_fan(fan);
|
||||
dbus.proxies().profile().set_fan_curve(profile, curve)?;
|
||||
dbus.proxies().fan_curves().set_fan_curve(profile, curve)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_bios_option(
|
||||
fn handle_platform_properties(
|
||||
dbus: &RogDbusClientBlocking<'_>,
|
||||
supported: &RogBiosSupportedFunctions,
|
||||
supported: &[Properties],
|
||||
cmd: &BiosCommand,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
{
|
||||
@@ -780,26 +816,26 @@ fn handle_bios_option(
|
||||
let usage: Vec<String> = BiosCommand::usage().lines().map(|s| s.to_owned()).collect();
|
||||
|
||||
for line in usage.iter().filter(|line| {
|
||||
line.contains("sound") && supported.post_sound
|
||||
|| line.contains("GPU") && supported.gpu_mux
|
||||
|| line.contains("panel") && supported.panel_overdrive
|
||||
line.contains("sound") && supported.contains(&Properties::PostAnimationSound)
|
||||
|| line.contains("GPU") && supported.contains(&Properties::GpuMuxMode)
|
||||
|| line.contains("panel") && supported.contains(&Properties::PanelOd)
|
||||
}) {
|
||||
println!("{}", line);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(opt) = cmd.post_sound_set {
|
||||
dbus.proxies().rog_bios().set_post_boot_sound(opt)?;
|
||||
dbus.proxies().platform().set_post_animation_sound(opt)?;
|
||||
}
|
||||
if cmd.post_sound_get {
|
||||
let res = dbus.proxies().rog_bios().post_boot_sound()? == 1;
|
||||
let res = dbus.proxies().platform().post_animation_sound()?;
|
||||
println!("Bios POST sound on: {}", res);
|
||||
}
|
||||
|
||||
if let Some(opt) = cmd.gpu_mux_mode_set {
|
||||
println!("Rebuilding initrd to include drivers");
|
||||
dbus.proxies()
|
||||
.rog_bios()
|
||||
.platform()
|
||||
.set_gpu_mux_mode(GpuMode::from_mux(opt))?;
|
||||
println!(
|
||||
"The mode change is not active until you reboot, on boot the bios will make the \
|
||||
@@ -807,15 +843,15 @@ fn handle_bios_option(
|
||||
);
|
||||
}
|
||||
if cmd.gpu_mux_mode_get {
|
||||
let res = dbus.proxies().rog_bios().gpu_mux_mode()?;
|
||||
let res = dbus.proxies().platform().gpu_mux_mode()?;
|
||||
println!("Bios GPU MUX: {:?}", res);
|
||||
}
|
||||
|
||||
if let Some(opt) = cmd.panel_overdrive_set {
|
||||
dbus.proxies().rog_bios().set_panel_od(opt)?;
|
||||
dbus.proxies().platform().set_panel_od(opt)?;
|
||||
}
|
||||
if cmd.panel_overdrive_get {
|
||||
let res = dbus.proxies().rog_bios().panel_od()?;
|
||||
let res = dbus.proxies().platform().panel_od()?;
|
||||
println!("Panel overdrive on: {}", res);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
use gumdrop::Options;
|
||||
use rog_profiles::fan_curve_set::CurveData;
|
||||
use rog_profiles::{FanCurvePU, Profile};
|
||||
|
||||
#[derive(Debug, Clone, Options)]
|
||||
pub struct ProfileCommand {
|
||||
#[options(help = "print help message")]
|
||||
pub help: bool,
|
||||
#[options(help = "toggle to next profile in list")]
|
||||
pub next: bool,
|
||||
#[options(help = "list available profiles")]
|
||||
pub list: bool,
|
||||
|
||||
#[options(help = "get profile")]
|
||||
pub profile_get: bool,
|
||||
#[options(meta = "", help = "set the active profile")]
|
||||
pub profile_set: Option<Profile>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Options)]
|
||||
pub struct FanCurveCommand {
|
||||
#[options(help = "print help message")]
|
||||
pub help: bool,
|
||||
|
||||
#[options(help = "get enabled fan profiles")]
|
||||
pub get_enabled: bool,
|
||||
#[options(help = "set the active profile's fan curve to default")]
|
||||
pub default: bool,
|
||||
|
||||
#[options(
|
||||
meta = "",
|
||||
help = "profile to modify fan-curve for. Shows data if no options provided"
|
||||
)]
|
||||
pub mod_profile: Option<Profile>,
|
||||
#[options(
|
||||
meta = "",
|
||||
help = "enable or disable <true/false> fan curve. `mod-profile` required"
|
||||
)]
|
||||
pub enabled: Option<bool>,
|
||||
#[options(
|
||||
meta = "",
|
||||
help = "select fan <cpu/gpu> to modify. `mod-profile` required"
|
||||
)]
|
||||
pub fan: Option<FanCurvePU>,
|
||||
|
||||
#[options(
|
||||
meta = "",
|
||||
help = "data format = 30c:1%,49c:2%,59c:3%,69c:4%,79c:31%,89c:49%,99c:56%,109c:58%.
|
||||
`--mod-profile` required. If '%' is omitted the fan range is 0-255"
|
||||
)]
|
||||
pub data: Option<CurveData>,
|
||||
}
|
||||
@@ -136,8 +136,16 @@ impl Default for ConfigAura {
|
||||
let mut seq = AuraSequences::new(false);
|
||||
let mut key = Effect::Breathe(Breathe::new(
|
||||
LedCode::W,
|
||||
Colour(255, 0, 20),
|
||||
Colour(20, 255, 0),
|
||||
Colour {
|
||||
r: 255,
|
||||
g: 0,
|
||||
b: 20,
|
||||
},
|
||||
Colour {
|
||||
r: 20,
|
||||
g: 255,
|
||||
b: 0,
|
||||
},
|
||||
Speed::Low,
|
||||
));
|
||||
|
||||
@@ -151,20 +159,25 @@ impl Default for ConfigAura {
|
||||
|
||||
let key = Effect::Breathe(Breathe::new(
|
||||
LedCode::F,
|
||||
Colour(255, 0, 0),
|
||||
Colour(255, 0, 0),
|
||||
Colour { r: 255, g: 0, b: 0 },
|
||||
Colour { r: 255, g: 0, b: 0 },
|
||||
Speed::High,
|
||||
));
|
||||
seq.push(key);
|
||||
|
||||
let mut key = Effect::Static(Static::new(LedCode::RCtrl, Colour(0, 0, 255)));
|
||||
let mut key = Effect::Static(Static::new(LedCode::RCtrl, Colour { r: 0, g: 0, b: 255 }));
|
||||
seq.push(key.clone());
|
||||
key.set_led(LedCode::LCtrl);
|
||||
seq.push(key.clone());
|
||||
key.set_led(LedCode::Esc);
|
||||
seq.push(key);
|
||||
|
||||
let key = Effect::DoomFlicker(DoomFlicker::new(LedCode::N9, Colour(0, 0, 255), 80, 40));
|
||||
let key = Effect::DoomFlicker(DoomFlicker::new(
|
||||
LedCode::N9,
|
||||
Colour { r: 0, g: 0, b: 255 },
|
||||
80,
|
||||
40,
|
||||
));
|
||||
seq.push(key);
|
||||
|
||||
Self {
|
||||
|
||||
@@ -22,22 +22,18 @@ pub struct Timer {
|
||||
/// animation loop count
|
||||
count: u64,
|
||||
/// Used only for `TimeType::Timer`, milliseonds to fade the image in for
|
||||
fade_in: Option<u64>,
|
||||
fade_in: u64,
|
||||
/// Used only for `TimeType::Timer`, milliseonds to fade the image out for
|
||||
fade_out: Option<u64>,
|
||||
fade_out: u64,
|
||||
}
|
||||
|
||||
impl From<Timer> for AnimTime {
|
||||
fn from(time: Timer) -> Self {
|
||||
match time.type_of {
|
||||
TimeType::Timer => {
|
||||
if time.fade_in.is_some() || time.fade_out.is_some() {
|
||||
let fade_in = time
|
||||
.fade_in
|
||||
.map_or(Duration::from_secs(0), Duration::from_millis);
|
||||
let fade_out = time
|
||||
.fade_out
|
||||
.map_or(Duration::from_secs(0), Duration::from_millis);
|
||||
if time.fade_in != 0 && time.fade_out != 0 {
|
||||
let fade_in = Duration::from_millis(time.fade_in);
|
||||
let fade_out = Duration::from_millis(time.fade_out);
|
||||
let show_for = if time.count != 0 {
|
||||
Some(Duration::from_millis(time.count))
|
||||
} else {
|
||||
|
||||
@@ -5,12 +5,11 @@ use std::sync::{Arc, Mutex};
|
||||
|
||||
use asusd_user::config::*;
|
||||
use asusd_user::ctrl_anime::{CtrlAnime, CtrlAnimeInner};
|
||||
use asusd_user::DBUS_NAME;
|
||||
use config_traits::{StdConfig, StdConfigLoad};
|
||||
use rog_anime::usb::get_anime_type;
|
||||
use rog_aura::aura_detection::LaptopLedData;
|
||||
use rog_aura::layouts::KeyLayout;
|
||||
use rog_dbus::RogDbusClientBlocking;
|
||||
use rog_dbus::{RogDbusClientBlocking, DBUS_NAME};
|
||||
use smol::Executor;
|
||||
use zbus::Connection;
|
||||
|
||||
@@ -34,15 +33,18 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("rog-platform v{}", rog_platform::VERSION);
|
||||
|
||||
let (client, _) = RogDbusClientBlocking::new()?;
|
||||
let supported = client.proxies().supported().supported_functions()?;
|
||||
|
||||
let supported = client
|
||||
.proxies()
|
||||
.platform()
|
||||
.supported_interfaces()
|
||||
.unwrap_or_default()
|
||||
.contains(&"Anime".to_string());
|
||||
let config = ConfigBase::new().load();
|
||||
|
||||
let executor = Executor::new();
|
||||
|
||||
let early_return = Arc::new(AtomicBool::new(false));
|
||||
// Set up the anime data and run loop/thread
|
||||
if supported.anime_ctrl.0 {
|
||||
if supported {
|
||||
if let Some(cfg) = config.active_anime {
|
||||
let anime_type = get_anime_type()?;
|
||||
let anime_config = ConfigAnime::new().set_name(cfg).load();
|
||||
@@ -100,7 +102,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
client
|
||||
.proxies()
|
||||
.led()
|
||||
.aura()
|
||||
.direct_addressing_raw(packets)
|
||||
.unwrap();
|
||||
std::thread::sleep(std::time::Duration::from_millis(33));
|
||||
|
||||
@@ -6,6 +6,4 @@ pub mod ctrl_anime;
|
||||
|
||||
pub mod zbus_anime;
|
||||
|
||||
pub static DBUS_NAME: &str = "org.asuslinux.Daemon";
|
||||
|
||||
pub static VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
@@ -23,7 +23,10 @@
|
||||
|
||||
use zbus::dbus_proxy;
|
||||
|
||||
#[dbus_proxy(interface = "org.asuslinux.Daemon")]
|
||||
#[dbus_proxy(
|
||||
interface = "org.asuslinux.Daemon",
|
||||
default_path = "/org/asuslinux/Anime"
|
||||
)]
|
||||
trait Daemon {
|
||||
/// InsertAsusGif method
|
||||
fn insert_asus_gif(
|
||||
|
||||
@@ -19,9 +19,11 @@ rog_anime = { path = "../rog-anime", features = ["dbus"] }
|
||||
rog_aura = { path = "../rog-aura", features = ["dbus"] }
|
||||
rog_platform = { path = "../rog-platform" }
|
||||
rog_profiles = { path = "../rog-profiles" }
|
||||
rog_dbus = { path = "../rog-dbus" }
|
||||
dmi_id = { path = "../dmi-id" }
|
||||
futures-lite = "*"
|
||||
udev.workspace = true
|
||||
inotify.workspace = true
|
||||
|
||||
async-trait.workspace = true
|
||||
tokio.workspace = true
|
||||
|
||||
# cli and logging
|
||||
@@ -35,9 +37,6 @@ logind-zbus.workspace = true
|
||||
serde.workspace = true
|
||||
serde_derive.workspace = true
|
||||
|
||||
# Device control
|
||||
sysfs-class.workspace = true # used for backlight control and baord ID
|
||||
|
||||
concat-idents.workspace = true
|
||||
|
||||
systemd-zbus = "*"
|
||||
|
||||
@@ -1,28 +1,90 @@
|
||||
use config_traits::{StdConfig, StdConfigLoad2};
|
||||
use config_traits::{StdConfig, StdConfigLoad3};
|
||||
use rog_platform::cpu::CPUEPP;
|
||||
use rog_platform::platform::ThrottlePolicy;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
|
||||
const CONFIG_FILE: &str = "asusd.ron";
|
||||
|
||||
#[derive(Deserialize, Serialize, Default, Debug)]
|
||||
#[derive(Deserialize, Serialize, Debug, PartialEq, PartialOrd)]
|
||||
pub struct Config {
|
||||
/// Save charge limit for restoring on boot
|
||||
pub bat_charge_limit: u8,
|
||||
/// Save charge limit for restoring on boot/resume
|
||||
pub charge_control_end_threshold: u8,
|
||||
pub panel_od: bool,
|
||||
pub mini_led_mode: bool,
|
||||
pub disable_nvidia_powerd_on_battery: bool,
|
||||
/// An optional command/script to run when power is changed to AC
|
||||
pub ac_command: String,
|
||||
/// An optional command/script to run when power is changed to battery
|
||||
pub bat_command: String,
|
||||
/// Set true if energy_performance_preference should be set if the
|
||||
/// throttle/platform profile is changed
|
||||
pub throttle_policy_linked_epp: bool,
|
||||
/// Which throttle/profile to use on battery power
|
||||
pub throttle_policy_on_battery: ThrottlePolicy,
|
||||
/// Which throttle/profile to use on AC power
|
||||
pub throttle_policy_on_ac: ThrottlePolicy,
|
||||
/// The energy_performance_preference for this throttle/platform profile
|
||||
pub throttle_quiet_epp: CPUEPP,
|
||||
/// The energy_performance_preference for this throttle/platform profile
|
||||
pub throttle_balanced_epp: CPUEPP,
|
||||
/// The energy_performance_preference for this throttle/platform profile
|
||||
pub throttle_performance_epp: CPUEPP,
|
||||
/// Defaults to `None` if not supported
|
||||
pub ppt_pl1_spl: Option<u8>,
|
||||
/// Defaults to `None` if not supported
|
||||
pub ppt_pl2_sppt: Option<u8>,
|
||||
/// Defaults to `None` if not supported
|
||||
pub ppt_fppt: Option<u8>,
|
||||
/// Defaults to `None` if not supported
|
||||
pub ppt_apu_sppt: Option<u8>,
|
||||
/// Defaults to `None` if not supported
|
||||
pub ppt_platform_sppt: Option<u8>,
|
||||
/// Defaults to `None` if not supported
|
||||
pub nv_dynamic_boost: Option<u8>,
|
||||
/// Defaults to `None` if not supported
|
||||
pub nv_temp_target: Option<u8>,
|
||||
/// Temporary state for AC/Batt
|
||||
#[serde(skip)]
|
||||
pub last_power_plugged: u8,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
charge_control_end_threshold: 100,
|
||||
panel_od: false,
|
||||
mini_led_mode: false,
|
||||
disable_nvidia_powerd_on_battery: true,
|
||||
ac_command: Default::default(),
|
||||
bat_command: Default::default(),
|
||||
throttle_policy_linked_epp: true,
|
||||
throttle_policy_on_battery: ThrottlePolicy::Quiet,
|
||||
throttle_policy_on_ac: ThrottlePolicy::Performance,
|
||||
throttle_quiet_epp: CPUEPP::Power,
|
||||
throttle_balanced_epp: CPUEPP::BalancePower,
|
||||
throttle_performance_epp: CPUEPP::Performance,
|
||||
ppt_pl1_spl: Default::default(),
|
||||
ppt_pl2_sppt: Default::default(),
|
||||
ppt_fppt: Default::default(),
|
||||
ppt_apu_sppt: Default::default(),
|
||||
ppt_platform_sppt: Default::default(),
|
||||
nv_dynamic_boost: Default::default(),
|
||||
nv_temp_target: Default::default(),
|
||||
last_power_plugged: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl StdConfig for Config {
|
||||
fn new() -> Self {
|
||||
Config {
|
||||
bat_charge_limit: 100,
|
||||
panel_od: false,
|
||||
mini_led_mode: false,
|
||||
charge_control_end_threshold: 100,
|
||||
disable_nvidia_powerd_on_battery: true,
|
||||
throttle_policy_on_battery: ThrottlePolicy::Quiet,
|
||||
throttle_policy_on_ac: ThrottlePolicy::Performance,
|
||||
ac_command: String::new(),
|
||||
bat_command: String::new(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,49 +97,128 @@ impl StdConfig for Config {
|
||||
}
|
||||
}
|
||||
|
||||
impl StdConfigLoad2<Config458, Config462> for Config {}
|
||||
impl StdConfigLoad3<Config472, Config506, Config507> for Config {}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct Config462 {
|
||||
pub struct Config507 {
|
||||
/// Save charge limit for restoring on boot
|
||||
pub charge_control_end_threshold: u8,
|
||||
pub panel_od: bool,
|
||||
pub mini_led_mode: bool,
|
||||
pub disable_nvidia_powerd_on_battery: bool,
|
||||
pub ac_command: String,
|
||||
pub bat_command: String,
|
||||
pub platform_policy_linked_epp: bool,
|
||||
pub platform_policy_on_battery: ThrottlePolicy,
|
||||
pub platform_policy_on_ac: ThrottlePolicy,
|
||||
//
|
||||
pub ppt_pl1_spl: Option<u8>,
|
||||
pub ppt_pl2_sppt: Option<u8>,
|
||||
pub ppt_fppt: Option<u8>,
|
||||
pub ppt_apu_sppt: Option<u8>,
|
||||
pub ppt_platform_sppt: Option<u8>,
|
||||
pub nv_dynamic_boost: Option<u8>,
|
||||
pub nv_temp_target: Option<u8>,
|
||||
}
|
||||
|
||||
impl From<Config507> for Config {
|
||||
fn from(c: Config507) -> Self {
|
||||
Self {
|
||||
charge_control_end_threshold: c.charge_control_end_threshold,
|
||||
panel_od: c.panel_od,
|
||||
disable_nvidia_powerd_on_battery: c.disable_nvidia_powerd_on_battery,
|
||||
ac_command: c.ac_command,
|
||||
bat_command: c.bat_command,
|
||||
mini_led_mode: c.mini_led_mode,
|
||||
throttle_policy_linked_epp: true,
|
||||
throttle_policy_on_battery: c.platform_policy_on_battery,
|
||||
throttle_policy_on_ac: c.platform_policy_on_ac,
|
||||
throttle_quiet_epp: CPUEPP::Power,
|
||||
throttle_balanced_epp: CPUEPP::BalancePower,
|
||||
throttle_performance_epp: CPUEPP::Performance,
|
||||
ppt_pl1_spl: c.ppt_pl1_spl,
|
||||
ppt_pl2_sppt: c.ppt_pl2_sppt,
|
||||
ppt_fppt: c.ppt_fppt,
|
||||
ppt_apu_sppt: c.ppt_apu_sppt,
|
||||
ppt_platform_sppt: c.ppt_platform_sppt,
|
||||
nv_dynamic_boost: c.nv_dynamic_boost,
|
||||
nv_temp_target: c.nv_temp_target,
|
||||
last_power_plugged: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct Config506 {
|
||||
/// Save charge limit for restoring on boot
|
||||
pub charge_control_end_threshold: u8,
|
||||
pub panel_od: bool,
|
||||
pub mini_led_mode: bool,
|
||||
pub disable_nvidia_powerd_on_battery: bool,
|
||||
pub ac_command: String,
|
||||
pub bat_command: String,
|
||||
/// Restored on boot as well as when power is plugged
|
||||
#[serde(skip)]
|
||||
pub platform_policy_to_restore: ThrottlePolicy,
|
||||
pub platform_policy_on_battery: ThrottlePolicy,
|
||||
pub platform_policy_on_ac: ThrottlePolicy,
|
||||
//
|
||||
pub ppt_pl1_spl: Option<u8>,
|
||||
pub ppt_pl2_sppt: Option<u8>,
|
||||
pub ppt_fppt: Option<u8>,
|
||||
pub ppt_apu_sppt: Option<u8>,
|
||||
pub ppt_platform_sppt: Option<u8>,
|
||||
pub nv_dynamic_boost: Option<u8>,
|
||||
pub nv_temp_target: Option<u8>,
|
||||
}
|
||||
|
||||
impl From<Config506> for Config {
|
||||
fn from(c: Config506) -> Self {
|
||||
Self {
|
||||
charge_control_end_threshold: c.charge_control_end_threshold,
|
||||
panel_od: c.panel_od,
|
||||
disable_nvidia_powerd_on_battery: c.disable_nvidia_powerd_on_battery,
|
||||
ac_command: c.ac_command,
|
||||
bat_command: c.bat_command,
|
||||
mini_led_mode: c.mini_led_mode,
|
||||
throttle_policy_linked_epp: true,
|
||||
throttle_policy_on_battery: c.platform_policy_on_battery,
|
||||
throttle_policy_on_ac: c.platform_policy_on_ac,
|
||||
throttle_quiet_epp: CPUEPP::Power,
|
||||
throttle_balanced_epp: CPUEPP::BalancePower,
|
||||
throttle_performance_epp: CPUEPP::Performance,
|
||||
ppt_pl1_spl: c.ppt_pl1_spl,
|
||||
ppt_pl2_sppt: c.ppt_pl2_sppt,
|
||||
ppt_fppt: c.ppt_fppt,
|
||||
ppt_apu_sppt: c.ppt_apu_sppt,
|
||||
ppt_platform_sppt: c.ppt_platform_sppt,
|
||||
nv_dynamic_boost: c.nv_dynamic_boost,
|
||||
nv_temp_target: c.nv_temp_target,
|
||||
last_power_plugged: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct Config472 {
|
||||
/// Save charge limit for restoring on boot
|
||||
pub bat_charge_limit: u8,
|
||||
pub panel_od: bool,
|
||||
pub mini_led_mode: bool,
|
||||
pub disable_nvidia_powerd_on_battery: bool,
|
||||
pub ac_command: String,
|
||||
pub bat_command: String,
|
||||
}
|
||||
|
||||
impl From<Config462> for Config {
|
||||
fn from(c: Config462) -> Self {
|
||||
impl From<Config472> for Config {
|
||||
fn from(c: Config472) -> Self {
|
||||
Self {
|
||||
bat_charge_limit: c.bat_charge_limit,
|
||||
charge_control_end_threshold: c.bat_charge_limit,
|
||||
panel_od: c.panel_od,
|
||||
mini_led_mode: false,
|
||||
disable_nvidia_powerd_on_battery: true,
|
||||
ac_command: String::new(),
|
||||
bat_command: String::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct Config458 {
|
||||
/// Save charge limit for restoring on boot
|
||||
pub bat_charge_limit: u8,
|
||||
pub panel_od: bool,
|
||||
pub ac_command: String,
|
||||
pub bat_command: String,
|
||||
}
|
||||
|
||||
impl From<Config458> for Config {
|
||||
fn from(c: Config458) -> Self {
|
||||
Self {
|
||||
bat_charge_limit: c.bat_charge_limit,
|
||||
panel_od: c.panel_od,
|
||||
mini_led_mode: false,
|
||||
disable_nvidia_powerd_on_battery: true,
|
||||
ac_command: c.ac_command,
|
||||
bat_command: c.bat_command,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,9 @@ use std::time::Duration;
|
||||
use config_traits::{StdConfig, StdConfigLoad2};
|
||||
use rog_anime::error::AnimeError;
|
||||
use rog_anime::usb::Brightness;
|
||||
use rog_anime::{ActionData, ActionLoader, AnimTime, Animations, AnimeType, Fade, Vec2};
|
||||
use rog_anime::{
|
||||
ActionData, ActionLoader, AnimTime, Animations, AnimeType, DeviceState, Fade, Vec2,
|
||||
};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
|
||||
const CONFIG_FILE: &str = "anime.ron";
|
||||
@@ -24,7 +26,6 @@ impl From<AnimeConfigV460> for AnimeConfig {
|
||||
system: c.system,
|
||||
boot: c.boot,
|
||||
wake: c.wake,
|
||||
sleep: c.sleep,
|
||||
shutdown: c.shutdown,
|
||||
..Default::default()
|
||||
}
|
||||
@@ -32,25 +33,32 @@ impl From<AnimeConfigV460> for AnimeConfig {
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
pub struct AnimeConfigV5 {
|
||||
pub struct AnimeConfigV472 {
|
||||
pub model_override: Option<AnimeType>,
|
||||
pub system: Vec<ActionLoader>,
|
||||
pub boot: Vec<ActionLoader>,
|
||||
pub wake: Vec<ActionLoader>,
|
||||
pub sleep: Vec<ActionLoader>,
|
||||
pub shutdown: Vec<ActionLoader>,
|
||||
pub brightness: f32,
|
||||
pub awake_enabled: bool,
|
||||
pub boot_anim_enabled: bool,
|
||||
pub display_enabled: bool,
|
||||
pub display_brightness: Brightness,
|
||||
pub builtin_anims_enabled: bool,
|
||||
pub builtin_anims: Animations,
|
||||
}
|
||||
|
||||
impl From<AnimeConfigV5> for AnimeConfig {
|
||||
fn from(c: AnimeConfigV5) -> AnimeConfig {
|
||||
impl From<AnimeConfigV472> for AnimeConfig {
|
||||
fn from(c: AnimeConfigV472) -> AnimeConfig {
|
||||
AnimeConfig {
|
||||
system: c.system,
|
||||
boot: c.boot,
|
||||
wake: c.wake,
|
||||
sleep: c.sleep,
|
||||
shutdown: c.shutdown,
|
||||
model_override: c.model_override,
|
||||
display_enabled: c.display_enabled,
|
||||
display_brightness: c.display_brightness,
|
||||
builtin_anims_enabled: c.builtin_anims_enabled,
|
||||
builtin_anims: c.builtin_anims,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
@@ -61,7 +69,6 @@ pub struct AnimeConfigCached {
|
||||
pub system: Vec<ActionData>,
|
||||
pub boot: Vec<ActionData>,
|
||||
pub wake: Vec<ActionData>,
|
||||
pub sleep: Vec<ActionData>,
|
||||
pub shutdown: Vec<ActionData>,
|
||||
}
|
||||
|
||||
@@ -89,12 +96,6 @@ impl AnimeConfigCached {
|
||||
}
|
||||
self.wake = wake;
|
||||
|
||||
let mut sleep = Vec::with_capacity(config.sleep.len());
|
||||
for ani in &config.sleep {
|
||||
sleep.push(ActionData::from_anime_action(anime_type, ani)?);
|
||||
}
|
||||
self.sleep = sleep;
|
||||
|
||||
let mut shutdown = Vec::with_capacity(config.shutdown.len());
|
||||
for ani in &config.shutdown {
|
||||
shutdown.push(ActionData::from_anime_action(anime_type, ani)?);
|
||||
@@ -111,12 +112,15 @@ pub struct AnimeConfig {
|
||||
pub system: Vec<ActionLoader>,
|
||||
pub boot: Vec<ActionLoader>,
|
||||
pub wake: Vec<ActionLoader>,
|
||||
pub sleep: Vec<ActionLoader>,
|
||||
pub shutdown: Vec<ActionLoader>,
|
||||
pub brightness: f32,
|
||||
// pub brightness: f32,
|
||||
pub display_enabled: bool,
|
||||
pub display_brightness: Brightness,
|
||||
pub builtin_anims_enabled: bool,
|
||||
pub off_when_unplugged: bool,
|
||||
pub off_when_suspended: bool,
|
||||
pub off_when_lid_closed: bool,
|
||||
pub brightness_on_battery: Brightness,
|
||||
pub builtin_anims: Animations,
|
||||
}
|
||||
|
||||
@@ -127,12 +131,15 @@ impl Default for AnimeConfig {
|
||||
system: Vec::new(),
|
||||
boot: Vec::new(),
|
||||
wake: Vec::new(),
|
||||
sleep: Vec::new(),
|
||||
shutdown: Vec::new(),
|
||||
brightness: 1.0,
|
||||
// brightness: 1.0,
|
||||
display_enabled: true,
|
||||
display_brightness: Brightness::Med,
|
||||
builtin_anims_enabled: true,
|
||||
off_when_unplugged: true,
|
||||
off_when_suspended: true,
|
||||
off_when_lid_closed: true,
|
||||
brightness_on_battery: Brightness::Low,
|
||||
builtin_anims: Animations::default(),
|
||||
}
|
||||
}
|
||||
@@ -152,7 +159,22 @@ impl StdConfig for AnimeConfig {
|
||||
}
|
||||
}
|
||||
|
||||
impl StdConfigLoad2<AnimeConfigV460, AnimeConfigV5> for AnimeConfig {}
|
||||
impl StdConfigLoad2<AnimeConfigV460, AnimeConfigV472> for AnimeConfig {}
|
||||
|
||||
impl From<&AnimeConfig> for DeviceState {
|
||||
fn from(config: &AnimeConfig) -> Self {
|
||||
DeviceState {
|
||||
display_enabled: config.display_enabled,
|
||||
display_brightness: config.display_brightness,
|
||||
builtin_anims_enabled: config.builtin_anims_enabled,
|
||||
builtin_anims: config.builtin_anims,
|
||||
off_when_unplugged: config.off_when_unplugged,
|
||||
off_when_suspended: config.off_when_suspended,
|
||||
off_when_lid_closed: config.off_when_lid_closed,
|
||||
brightness_on_battery: config.brightness_on_battery,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AnimeConfig {
|
||||
// fn clamp_config_brightness(mut config: &mut AnimeConfig) {
|
||||
@@ -193,14 +215,6 @@ impl AnimeConfig {
|
||||
Duration::from_secs(2),
|
||||
)),
|
||||
}],
|
||||
sleep: vec![ActionLoader::ImageAnimation {
|
||||
file: "/usr/share/asusd/anime/custom/sonic-wait.gif".into(),
|
||||
scale: 0.9,
|
||||
angle: 0.0,
|
||||
translation: Vec2::new(3.0, 2.0),
|
||||
brightness: 1.0,
|
||||
time: AnimTime::Infinite,
|
||||
}],
|
||||
shutdown: vec![ActionLoader::ImageAnimation {
|
||||
file: "/usr/share/asusd/anime/custom/sonic-wait.gif".into(),
|
||||
scale: 0.9,
|
||||
@@ -209,7 +223,6 @@ impl AnimeConfig {
|
||||
brightness: 1.0,
|
||||
time: AnimTime::Infinite,
|
||||
}],
|
||||
brightness: 1.0,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,23 +10,16 @@ use std::thread::sleep;
|
||||
use ::zbus::export::futures_util::lock::Mutex;
|
||||
use log::{error, info, warn};
|
||||
use rog_anime::error::AnimeError;
|
||||
use rog_anime::usb::{get_anime_type, pkt_flush, pkt_set_enable_powersave_anim, pkts_for_init};
|
||||
use rog_anime::usb::{
|
||||
get_anime_type, pkt_flush, pkt_set_brightness, pkt_set_enable_display,
|
||||
pkt_set_enable_powersave_anim, pkts_for_init, Brightness,
|
||||
};
|
||||
use rog_anime::{ActionData, AnimeDataBuffer, AnimePacketType, AnimeType};
|
||||
use rog_platform::hid_raw::HidRaw;
|
||||
use rog_platform::supported::AnimeSupportedFunctions;
|
||||
use rog_platform::usb_raw::USBRaw;
|
||||
|
||||
use self::config::{AnimeConfig, AnimeConfigCached};
|
||||
use crate::error::RogError;
|
||||
use crate::GetSupported;
|
||||
|
||||
impl GetSupported for CtrlAnime {
|
||||
type A = AnimeSupportedFunctions;
|
||||
|
||||
fn get_supported() -> Self::A {
|
||||
AnimeSupportedFunctions(HidRaw::new("193b").is_ok())
|
||||
}
|
||||
}
|
||||
|
||||
enum Node {
|
||||
Usb(USBRaw),
|
||||
@@ -46,6 +39,13 @@ impl Node {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_builtins_enabled(&self, enabled: bool, bright: Brightness) -> Result<(), RogError> {
|
||||
self.write_bytes(&pkt_set_enable_powersave_anim(enabled))?;
|
||||
self.write_bytes(&pkt_set_enable_display(enabled))?;
|
||||
self.write_bytes(&pkt_set_brightness(bright))?;
|
||||
self.write_bytes(&pkt_set_enable_powersave_anim(enabled))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CtrlAnime {
|
||||
@@ -63,7 +63,6 @@ pub struct CtrlAnime {
|
||||
impl CtrlAnime {
|
||||
#[inline]
|
||||
pub fn new(config: AnimeConfig) -> Result<CtrlAnime, RogError> {
|
||||
// let node = HidRaw::new("193b")?;
|
||||
let usb = USBRaw::new(0x193b).ok();
|
||||
let hid = HidRaw::new("193b").ok();
|
||||
let node = if usb.is_some() {
|
||||
@@ -74,6 +73,20 @@ impl CtrlAnime {
|
||||
return Err(RogError::Anime(AnimeError::NoDevice));
|
||||
};
|
||||
|
||||
// TODO: something better to set wakeups disabled
|
||||
if matches!(node, Node::Usb(_)) {
|
||||
if let Ok(mut enumerator) = udev::Enumerator::new() {
|
||||
enumerator.match_subsystem("usb").ok();
|
||||
enumerator.match_attribute("idProduct", "193b").ok();
|
||||
|
||||
if let Ok(mut enumer) = enumerator.scan_devices() {
|
||||
if let Some(mut dev) = enumer.next() {
|
||||
dev.set_attribute_value("power/wakeup", "disabled").ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut anime_type = get_anime_type()?;
|
||||
if let AnimeType::Unknown = anime_type {
|
||||
if let Some(model) = config.model_override {
|
||||
@@ -231,6 +244,14 @@ impl CtrlAnime {
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
lock.node
|
||||
.write_bytes(&pkt_set_enable_powersave_anim(
|
||||
lock.config.builtin_anims_enabled,
|
||||
))
|
||||
.map_err(|err| {
|
||||
warn!("rog_anime::run_animation:callback {}", err);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
// Loop ended, set the atmonics
|
||||
thread_running.store(false, Ordering::SeqCst);
|
||||
@@ -244,7 +265,7 @@ impl CtrlAnime {
|
||||
/// global brightness set in config.
|
||||
fn write_data_buffer(&self, mut buffer: AnimeDataBuffer) -> Result<(), RogError> {
|
||||
for led in buffer.data_mut().iter_mut() {
|
||||
let mut bright = *led as f32 * self.config.brightness;
|
||||
let mut bright = *led as f32;
|
||||
if bright > 254.0 {
|
||||
bright = 254.0;
|
||||
}
|
||||
|
||||
@@ -1,30 +1,42 @@
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use config_traits::StdConfig;
|
||||
use log::warn;
|
||||
use logind_zbus::manager::ManagerProxy;
|
||||
use rog_anime::usb::{
|
||||
pkt_set_brightness, pkt_set_builtin_animations, pkt_set_enable_display,
|
||||
pkt_set_enable_powersave_anim, AnimAwake, AnimBooting, AnimShutdown, AnimSleeping, Brightness,
|
||||
pkt_set_enable_powersave_anim, Brightness,
|
||||
};
|
||||
use rog_anime::{AnimeDataBuffer, DeviceState};
|
||||
use rog_anime::{Animations, AnimeDataBuffer, DeviceState};
|
||||
use zbus::export::futures_util::lock::Mutex;
|
||||
use zbus::{dbus_interface, Connection, SignalContext};
|
||||
use zbus::{dbus_interface, CacheProperties, Connection, SignalContext};
|
||||
|
||||
use super::CtrlAnime;
|
||||
use crate::error::RogError;
|
||||
|
||||
pub(super) const ZBUS_PATH: &str = "/org/asuslinux/Anime";
|
||||
pub const ANIME_ZBUS_NAME: &str = "Anime";
|
||||
pub const ANIME_ZBUS_PATH: &str = "/org/asuslinux/Anime";
|
||||
|
||||
async fn get_logind_manager<'a>() -> ManagerProxy<'a> {
|
||||
let connection = Connection::system()
|
||||
.await
|
||||
.expect("Controller could not create dbus connection");
|
||||
|
||||
ManagerProxy::builder(&connection)
|
||||
.cache_properties(CacheProperties::No)
|
||||
.build()
|
||||
.await
|
||||
.expect("Controller could not create ManagerProxy")
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct CtrlAnimeZbus(pub Arc<Mutex<CtrlAnime>>);
|
||||
|
||||
/// The struct with the main dbus methods requires this trait
|
||||
#[async_trait]
|
||||
impl crate::ZbusRun for CtrlAnimeZbus {
|
||||
async fn add_to_server(self, server: &mut Connection) {
|
||||
Self::add_to_server_helper(self, ZBUS_PATH, server).await;
|
||||
Self::add_to_server_helper(self, ANIME_ZBUS_PATH, server).await;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,155 +51,192 @@ impl CtrlAnimeZbus {
|
||||
let lock = self.0.lock().await;
|
||||
lock.thread_exit.store(true, Ordering::SeqCst);
|
||||
lock.write_data_buffer(input).map_err(|err| {
|
||||
warn!("rog_anime::run_animation:callback {}", err);
|
||||
warn!("ctrl_anime::run_animation:callback {}", err);
|
||||
err
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Set the global AniMe brightness
|
||||
async fn set_image_brightness(&self, bright: f32) {
|
||||
let mut lock = self.0.lock().await;
|
||||
let mut bright = bright;
|
||||
if bright < 0.0 {
|
||||
bright = 0.0;
|
||||
} else if bright > 1.0 {
|
||||
bright = 1.0;
|
||||
}
|
||||
lock.config.brightness = bright;
|
||||
lock.config.write();
|
||||
/// Set base brightness level
|
||||
#[dbus_interface(property)]
|
||||
async fn brightness(&self) -> Brightness {
|
||||
let lock = self.0.lock().await;
|
||||
lock.config.display_brightness
|
||||
}
|
||||
|
||||
/// Set base brightness level
|
||||
// TODO: enum for brightness
|
||||
async fn set_brightness(
|
||||
&self,
|
||||
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
||||
brightness: Brightness,
|
||||
) {
|
||||
#[dbus_interface(property)]
|
||||
async fn set_brightness(&self, brightness: Brightness) {
|
||||
let mut lock = self.0.lock().await;
|
||||
lock.node
|
||||
.write_bytes(&pkt_set_brightness(brightness))
|
||||
.map_err(|err| {
|
||||
warn!("rog_anime::run_animation:callback {}", err);
|
||||
warn!("ctrl_anime::set_brightness {}", err);
|
||||
})
|
||||
.ok();
|
||||
lock.node
|
||||
.write_bytes(&pkt_set_enable_display(brightness != Brightness::Off))
|
||||
.map_err(|err| {
|
||||
warn!("ctrl_anime::set_brightness {}", err);
|
||||
})
|
||||
.ok();
|
||||
|
||||
lock.config.display_enabled = brightness != Brightness::Off;
|
||||
lock.config.display_brightness = brightness;
|
||||
lock.config.write();
|
||||
|
||||
Self::notify_device_state(
|
||||
&ctxt,
|
||||
DeviceState {
|
||||
display_enabled: lock.config.display_enabled,
|
||||
display_brightness: lock.config.display_brightness,
|
||||
builtin_anims_enabled: lock.config.builtin_anims_enabled,
|
||||
builtin_anims: lock.config.builtin_anims,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.ok();
|
||||
}
|
||||
|
||||
/// Enable the builtin animations or not
|
||||
async fn set_builtins_enabled(
|
||||
&self,
|
||||
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
||||
enabled: bool,
|
||||
) {
|
||||
#[dbus_interface(property)]
|
||||
async fn builtins_enabled(&self) -> bool {
|
||||
let lock = self.0.lock().await;
|
||||
lock.config.builtin_anims_enabled
|
||||
}
|
||||
|
||||
/// Enable the builtin animations or not. This is quivalent to "Powersave
|
||||
/// animations" in Armory crate
|
||||
#[dbus_interface(property)]
|
||||
async fn set_builtins_enabled(&self, enabled: bool) {
|
||||
let mut lock = self.0.lock().await;
|
||||
lock.node
|
||||
.write_bytes(&pkt_set_enable_powersave_anim(enabled))
|
||||
.set_builtins_enabled(enabled, lock.config.display_brightness)
|
||||
.map_err(|err| {
|
||||
warn!("rog_anime::run_animation:callback {}", err);
|
||||
warn!("ctrl_anime::set_builtins_enabled {}", err);
|
||||
})
|
||||
.ok();
|
||||
|
||||
if !enabled {
|
||||
let data = vec![255u8; lock.anime_type.data_length()];
|
||||
if let Ok(tmp) = AnimeDataBuffer::from_vec(lock.anime_type, data).map_err(|err| {
|
||||
warn!("ctrl_anime::set_builtins_enabled {}", err);
|
||||
}) {
|
||||
lock.node
|
||||
.write_bytes(tmp.data())
|
||||
.map_err(|err| {
|
||||
warn!("ctrl_anime::set_builtins_enabled {}", err);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
|
||||
lock.config.builtin_anims_enabled = enabled;
|
||||
lock.config.write();
|
||||
if enabled {
|
||||
lock.thread_exit.store(true, Ordering::Release);
|
||||
}
|
||||
}
|
||||
|
||||
Self::notify_device_state(
|
||||
&ctxt,
|
||||
DeviceState {
|
||||
display_enabled: lock.config.display_enabled,
|
||||
display_brightness: lock.config.display_brightness,
|
||||
builtin_anims_enabled: lock.config.builtin_anims_enabled,
|
||||
builtin_anims: lock.config.builtin_anims,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.ok();
|
||||
#[dbus_interface(property)]
|
||||
async fn builtin_animations(&self) -> Animations {
|
||||
let lock = self.0.lock().await;
|
||||
lock.config.builtin_anims
|
||||
}
|
||||
|
||||
/// Set which builtin animation is used for each stage
|
||||
async fn set_builtin_animations(
|
||||
&self,
|
||||
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
||||
boot: AnimBooting,
|
||||
awake: AnimAwake,
|
||||
sleep: AnimSleeping,
|
||||
shutdown: AnimShutdown,
|
||||
) {
|
||||
#[dbus_interface(property)]
|
||||
async fn set_builtin_animations(&self, settings: Animations) {
|
||||
let mut lock = self.0.lock().await;
|
||||
lock.node
|
||||
.write_bytes(&pkt_set_builtin_animations(
|
||||
settings.boot,
|
||||
settings.awake,
|
||||
settings.sleep,
|
||||
settings.shutdown,
|
||||
))
|
||||
.map_err(|err| {
|
||||
warn!("ctrl_anime::run_animation:callback {}", err);
|
||||
})
|
||||
.ok();
|
||||
lock.node
|
||||
.write_bytes(&pkt_set_enable_powersave_anim(true))
|
||||
.map_err(|err| {
|
||||
warn!("rog_anime::run_animation:callback {}", err);
|
||||
warn!("ctrl_anime::run_animation:callback {}", err);
|
||||
})
|
||||
.ok();
|
||||
lock.node
|
||||
.write_bytes(&pkt_set_builtin_animations(boot, awake, sleep, shutdown))
|
||||
.map_err(|err| {
|
||||
warn!("rog_anime::run_animation:callback {}", err);
|
||||
})
|
||||
.ok();
|
||||
lock.config.builtin_anims.boot = boot;
|
||||
lock.config.builtin_anims.sleep = sleep;
|
||||
lock.config.builtin_anims.awake = awake;
|
||||
lock.config.builtin_anims.shutdown = shutdown;
|
||||
lock.config.display_enabled = true;
|
||||
lock.config.builtin_anims = settings;
|
||||
lock.config.write();
|
||||
}
|
||||
|
||||
Self::notify_device_state(
|
||||
&ctxt,
|
||||
DeviceState {
|
||||
display_enabled: lock.config.display_enabled,
|
||||
display_brightness: lock.config.display_brightness,
|
||||
builtin_anims_enabled: lock.config.builtin_anims_enabled,
|
||||
builtin_anims: lock.config.builtin_anims,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.ok();
|
||||
#[dbus_interface(property)]
|
||||
async fn enable_display(&self) -> bool {
|
||||
let lock = self.0.lock().await;
|
||||
lock.config.display_enabled
|
||||
}
|
||||
|
||||
/// Set whether the AniMe is enabled at all
|
||||
async fn set_enable_display(
|
||||
&self,
|
||||
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
||||
enabled: bool,
|
||||
) {
|
||||
#[dbus_interface(property)]
|
||||
async fn set_enable_display(&self, enabled: bool) {
|
||||
let mut lock = self.0.lock().await;
|
||||
lock.node
|
||||
.write_bytes(&pkt_set_enable_display(enabled))
|
||||
.map_err(|err| {
|
||||
warn!("rog_anime::run_animation:callback {}", err);
|
||||
warn!("ctrl_anime::run_animation:callback {}", err);
|
||||
})
|
||||
.ok();
|
||||
lock.config.display_enabled = enabled;
|
||||
lock.config.write();
|
||||
}
|
||||
|
||||
Self::notify_device_state(
|
||||
&ctxt,
|
||||
DeviceState {
|
||||
display_enabled: lock.config.display_enabled,
|
||||
display_brightness: lock.config.display_brightness,
|
||||
builtin_anims_enabled: lock.config.builtin_anims_enabled,
|
||||
builtin_anims: lock.config.builtin_anims,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.ok();
|
||||
#[dbus_interface(property)]
|
||||
async fn off_when_unplugged(&self) -> bool {
|
||||
let lock = self.0.lock().await;
|
||||
lock.config.off_when_unplugged
|
||||
}
|
||||
|
||||
/// Set if to turn the AniMe Matrix off when external power is unplugged
|
||||
#[dbus_interface(property)]
|
||||
async fn set_off_when_unplugged(&self, enabled: bool) {
|
||||
let mut lock = self.0.lock().await;
|
||||
let manager = get_logind_manager().await;
|
||||
let pow = manager.on_external_power().await.unwrap_or_default();
|
||||
|
||||
lock.node
|
||||
.write_bytes(&pkt_set_enable_display(!pow && !enabled))
|
||||
.map_err(|err| {
|
||||
warn!("create_sys_event_tasks::off_when_lid_closed {}", err);
|
||||
})
|
||||
.ok();
|
||||
|
||||
lock.config.off_when_unplugged = enabled;
|
||||
lock.config.write();
|
||||
}
|
||||
|
||||
#[dbus_interface(property)]
|
||||
async fn off_when_suspended(&self) -> bool {
|
||||
let lock = self.0.lock().await;
|
||||
lock.config.off_when_suspended
|
||||
}
|
||||
|
||||
/// Set if to turn the AniMe Matrix off when the laptop is suspended
|
||||
#[dbus_interface(property)]
|
||||
async fn set_off_when_suspended(&self, enabled: bool) {
|
||||
let mut lock = self.0.lock().await;
|
||||
lock.config.off_when_suspended = enabled;
|
||||
lock.config.write();
|
||||
}
|
||||
|
||||
#[dbus_interface(property)]
|
||||
async fn off_when_lid_closed(&self) -> bool {
|
||||
let lock = self.0.lock().await;
|
||||
lock.config.off_when_lid_closed
|
||||
}
|
||||
|
||||
/// Set if to turn the AniMe Matrix off when the lid is closed
|
||||
#[dbus_interface(property)]
|
||||
async fn set_off_when_lid_closed(&self, enabled: bool) {
|
||||
let mut lock = self.0.lock().await;
|
||||
let manager = get_logind_manager().await;
|
||||
let lid = manager.lid_closed().await.unwrap_or_default();
|
||||
|
||||
lock.node
|
||||
.write_bytes(&pkt_set_enable_display(lid && !enabled))
|
||||
.map_err(|err| {
|
||||
warn!("create_sys_event_tasks::off_when_lid_closed {}", err);
|
||||
})
|
||||
.ok();
|
||||
|
||||
lock.config.off_when_lid_closed = enabled;
|
||||
lock.config.write();
|
||||
}
|
||||
|
||||
/// The main loop is the base system set action if the user isn't running
|
||||
@@ -204,24 +253,13 @@ impl CtrlAnimeZbus {
|
||||
// #[dbus_interface(property)]
|
||||
async fn device_state(&self) -> DeviceState {
|
||||
let lock = self.0.lock().await;
|
||||
DeviceState {
|
||||
display_enabled: lock.config.display_enabled,
|
||||
display_brightness: lock.config.display_brightness,
|
||||
builtin_anims_enabled: lock.config.builtin_anims_enabled,
|
||||
builtin_anims: lock.config.builtin_anims,
|
||||
}
|
||||
DeviceState::from(&lock.config)
|
||||
}
|
||||
|
||||
/// Notify listeners of the status of AniMe LED power and factory
|
||||
/// system-status animations
|
||||
#[dbus_interface(signal)]
|
||||
async fn notify_device_state(ctxt: &SignalContext<'_>, data: DeviceState) -> zbus::Result<()>;
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl crate::CtrlTask for CtrlAnimeZbus {
|
||||
fn zbus_path() -> &'static str {
|
||||
ZBUS_PATH
|
||||
ANIME_ZBUS_PATH
|
||||
}
|
||||
|
||||
async fn create_tasks(&self, _: SignalContext<'static>) -> Result<(), RogError> {
|
||||
@@ -230,36 +268,111 @@ impl crate::CtrlTask for CtrlAnimeZbus {
|
||||
let inner3 = self.0.clone();
|
||||
let inner4 = self.0.clone();
|
||||
self.create_sys_event_tasks(
|
||||
move || {
|
||||
move |sleeping| {
|
||||
// on_sleep
|
||||
let inner1 = inner1.clone();
|
||||
let inner = inner1.clone();
|
||||
async move {
|
||||
let lock = inner1.lock().await;
|
||||
CtrlAnime::run_thread(inner1.clone(), lock.cache.sleep.clone(), true).await;
|
||||
let lock = inner.lock().await;
|
||||
if lock.config.display_enabled {
|
||||
lock.thread_exit.store(true, Ordering::Release); // ensure clean slate
|
||||
|
||||
lock.node
|
||||
.write_bytes(&pkt_set_enable_display(
|
||||
!(sleeping && lock.config.off_when_suspended),
|
||||
))
|
||||
.map_err(|err| {
|
||||
warn!("create_sys_event_tasks::off_when_suspended {}", err);
|
||||
})
|
||||
.ok();
|
||||
|
||||
if lock.config.builtin_anims_enabled {
|
||||
lock.node
|
||||
.write_bytes(&pkt_set_enable_powersave_anim(
|
||||
!(sleeping && lock.config.off_when_suspended),
|
||||
))
|
||||
.map_err(|err| {
|
||||
warn!("create_sys_event_tasks::off_when_suspended {}", err);
|
||||
})
|
||||
.ok();
|
||||
} else if !sleeping && !lock.config.builtin_anims_enabled {
|
||||
// Run custom wake animation
|
||||
lock.node
|
||||
.write_bytes(&pkt_set_enable_powersave_anim(false))
|
||||
.ok(); // ensure builtins are disabled
|
||||
|
||||
CtrlAnime::run_thread(inner.clone(), lock.cache.wake.clone(), true)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
move || {
|
||||
// on_wake
|
||||
let inner2 = inner2.clone();
|
||||
async move {
|
||||
let lock = inner2.lock().await;
|
||||
CtrlAnime::run_thread(inner2.clone(), lock.cache.wake.clone(), true).await;
|
||||
}
|
||||
},
|
||||
move || {
|
||||
move |shutting_down| {
|
||||
// on_shutdown
|
||||
let inner3 = inner3.clone();
|
||||
let inner = inner2.clone();
|
||||
async move {
|
||||
let lock = inner3.lock().await;
|
||||
CtrlAnime::run_thread(inner3.clone(), lock.cache.shutdown.clone(), true).await;
|
||||
let lock = inner.lock().await;
|
||||
if lock.config.display_enabled && !lock.config.builtin_anims_enabled {
|
||||
if shutting_down {
|
||||
CtrlAnime::run_thread(inner.clone(), lock.cache.shutdown.clone(), true)
|
||||
.await;
|
||||
} else {
|
||||
CtrlAnime::run_thread(inner.clone(), lock.cache.boot.clone(), true)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
move || {
|
||||
// on_boot
|
||||
let inner4 = inner4.clone();
|
||||
move |lid_closed| {
|
||||
let inner = inner3.clone();
|
||||
// on lid change
|
||||
async move {
|
||||
let lock = inner4.lock().await;
|
||||
CtrlAnime::run_thread(inner4.clone(), lock.cache.boot.clone(), true).await;
|
||||
let lock = inner.lock().await;
|
||||
if lock.config.off_when_lid_closed {
|
||||
if lock.config.builtin_anims_enabled {
|
||||
lock.node
|
||||
.write_bytes(&pkt_set_enable_powersave_anim(!lid_closed))
|
||||
.map_err(|err| {
|
||||
warn!("create_sys_event_tasks::off_when_suspended {}", err);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
lock.node
|
||||
.write_bytes(&pkt_set_enable_display(!lid_closed))
|
||||
.map_err(|err| {
|
||||
warn!("create_sys_event_tasks::off_when_lid_closed {}", err);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
},
|
||||
move |power_plugged| {
|
||||
let inner = inner4.clone();
|
||||
// on power change
|
||||
async move {
|
||||
let lock = inner.lock().await;
|
||||
if lock.config.off_when_unplugged {
|
||||
if lock.config.builtin_anims_enabled {
|
||||
lock.node
|
||||
.write_bytes(&pkt_set_enable_powersave_anim(power_plugged))
|
||||
.map_err(|err| {
|
||||
warn!("create_sys_event_tasks::off_when_suspended {}", err);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
lock.node
|
||||
.write_bytes(&pkt_set_enable_display(power_plugged))
|
||||
.map_err(|err| {
|
||||
warn!("create_sys_event_tasks::off_when_unplugged {}", err);
|
||||
})
|
||||
.ok();
|
||||
} else {
|
||||
lock.node
|
||||
.write_bytes(&pkt_set_brightness(lock.config.brightness_on_battery))
|
||||
.map_err(|err| {
|
||||
warn!("create_sys_event_tasks::off_when_unplugged {}", err);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
@@ -269,30 +382,52 @@ impl crate::CtrlTask for CtrlAnimeZbus {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl crate::Reloadable for CtrlAnimeZbus {
|
||||
async fn reload(&mut self) -> Result<(), RogError> {
|
||||
if let Some(lock) = self.0.try_lock() {
|
||||
let anim = &lock.config.builtin_anims;
|
||||
lock.node
|
||||
.write_bytes(&pkt_set_enable_display(lock.config.display_enabled))?;
|
||||
lock.node.write_bytes(&pkt_set_enable_powersave_anim(
|
||||
// Set builtins
|
||||
if lock.config.builtin_anims_enabled {
|
||||
lock.node.write_bytes(&pkt_set_builtin_animations(
|
||||
anim.boot,
|
||||
anim.awake,
|
||||
anim.sleep,
|
||||
anim.shutdown,
|
||||
))?;
|
||||
}
|
||||
// Builtins enabled or na?
|
||||
lock.node.set_builtins_enabled(
|
||||
lock.config.builtin_anims_enabled,
|
||||
))?;
|
||||
lock.node.write_bytes(&pkt_set_builtin_animations(
|
||||
anim.boot,
|
||||
anim.awake,
|
||||
anim.sleep,
|
||||
anim.shutdown,
|
||||
))?;
|
||||
lock.config.display_brightness,
|
||||
)?;
|
||||
|
||||
if lock.config.builtin_anims_enabled && !lock.cache.boot.is_empty() {
|
||||
let manager = get_logind_manager().await;
|
||||
let lid_closed = manager.lid_closed().await.unwrap_or_default();
|
||||
let power_plugged = manager.on_external_power().await.unwrap_or_default();
|
||||
|
||||
let turn_off = (lid_closed && lock.config.off_when_lid_closed)
|
||||
|| (!power_plugged && lock.config.off_when_unplugged);
|
||||
lock.node
|
||||
.write_bytes(&pkt_set_enable_display(!turn_off))
|
||||
.map_err(|err| {
|
||||
warn!("create_sys_event_tasks::reload {}", err);
|
||||
})
|
||||
.ok();
|
||||
|
||||
if turn_off || !lock.config.display_enabled {
|
||||
lock.node.write_bytes(&pkt_set_enable_display(false))?;
|
||||
// early return so we don't run animation thread
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if !lock.config.builtin_anims_enabled && !lock.cache.boot.is_empty() {
|
||||
lock.node
|
||||
.write_bytes(&pkt_set_enable_powersave_anim(false))
|
||||
.ok();
|
||||
|
||||
let action = lock.cache.boot.clone();
|
||||
CtrlAnime::run_thread(self.0.clone(), action, true).await;
|
||||
}
|
||||
let action = lock.cache.boot.clone();
|
||||
CtrlAnime::run_thread(self.0.clone(), action, true).await;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
use std::collections::{BTreeMap, HashSet};
|
||||
|
||||
use config_traits::{StdConfig, StdConfigLoad};
|
||||
use rog_aura::aura_detection::LaptopLedData;
|
||||
use rog_aura::usb::{AuraDevRog1, AuraDevRog2, AuraDevTuf, AuraDevice, AuraPowerDev};
|
||||
use log::{debug, warn};
|
||||
use rog_aura::aura_detection::{LaptopLedData, ASUS_KEYBOARD_DEVICES};
|
||||
use rog_aura::power::AuraPower;
|
||||
use rog_aura::usb::{AuraDevRog1, AuraDevTuf, AuraDevice, AuraPowerDev};
|
||||
use rog_aura::{AuraEffect, AuraModeNum, AuraZone, Direction, LedBrightness, Speed, GRADIENT};
|
||||
use rog_platform::hid_raw::HidRaw;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
|
||||
const CONFIG_FILE: &str = "aura.ron";
|
||||
@@ -15,7 +18,7 @@ const CONFIG_FILE: &str = "aura.ron";
|
||||
pub enum AuraPowerConfig {
|
||||
AuraDevTuf(HashSet<AuraDevTuf>),
|
||||
AuraDevRog1(HashSet<AuraDevRog1>),
|
||||
AuraDevRog2(HashSet<AuraDevRog2>),
|
||||
AuraDevRog2(AuraPower),
|
||||
}
|
||||
|
||||
impl AuraPowerConfig {
|
||||
@@ -27,10 +30,7 @@ impl AuraPowerConfig {
|
||||
let c: Vec<AuraDevRog1> = c.iter().copied().collect();
|
||||
AuraDevRog1::to_bytes(&c)
|
||||
}
|
||||
AuraPowerConfig::AuraDevRog2(c) => {
|
||||
let c: Vec<AuraDevRog2> = c.iter().copied().collect();
|
||||
AuraDevRog2::to_bytes(&c)
|
||||
}
|
||||
AuraPowerConfig::AuraDevRog2(c) => c.to_bytes(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,13 +78,9 @@ impl AuraPowerConfig {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_0x19b6(&mut self, power: AuraDevRog2, on: bool) {
|
||||
pub fn set_0x19b6(&mut self, power: AuraPower) {
|
||||
if let Self::AuraDevRog2(p) = self {
|
||||
if on {
|
||||
p.insert(power);
|
||||
} else {
|
||||
p.remove(&power);
|
||||
}
|
||||
*p = power;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -94,18 +90,15 @@ impl From<&AuraPowerConfig> for AuraPowerDev {
|
||||
match config {
|
||||
AuraPowerConfig::AuraDevTuf(d) => AuraPowerDev {
|
||||
tuf: d.iter().copied().collect(),
|
||||
x1866: vec![],
|
||||
x19b6: vec![],
|
||||
..Default::default()
|
||||
},
|
||||
AuraPowerConfig::AuraDevRog1(d) => AuraPowerDev {
|
||||
tuf: vec![],
|
||||
x1866: d.iter().copied().collect(),
|
||||
x19b6: vec![],
|
||||
old_rog: d.iter().copied().collect(),
|
||||
..Default::default()
|
||||
},
|
||||
AuraPowerConfig::AuraDevRog2(d) => AuraPowerDev {
|
||||
tuf: vec![],
|
||||
x1866: vec![],
|
||||
x19b6: d.iter().copied().collect(),
|
||||
rog: d.clone(),
|
||||
..Default::default()
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -123,9 +116,17 @@ pub struct AuraConfig {
|
||||
}
|
||||
|
||||
impl StdConfig for AuraConfig {
|
||||
/// Detect the keyboard type and load from default DB if data available
|
||||
fn new() -> Self {
|
||||
// Self::create_default(AuraDevice::X19b6, &LaptopLedData::get_data())
|
||||
panic!("AuraConfig::new() should not be used, use AuraConfig::create_default() instead");
|
||||
warn!("AuraConfig: creating new config");
|
||||
let mut prod_id = AuraDevice::Unknown;
|
||||
for prod in ASUS_KEYBOARD_DEVICES {
|
||||
if HidRaw::new(prod.into()).is_ok() {
|
||||
prod_id = prod;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Self::from_default_support(prod_id, &LaptopLedData::get_data())
|
||||
}
|
||||
|
||||
fn config_dir() -> std::path::PathBuf {
|
||||
@@ -140,28 +141,11 @@ impl StdConfig for AuraConfig {
|
||||
impl StdConfigLoad for AuraConfig {}
|
||||
|
||||
impl AuraConfig {
|
||||
pub fn create_default(prod_id: AuraDevice, support_data: &LaptopLedData) -> Self {
|
||||
pub fn from_default_support(prod_id: AuraDevice, support_data: &LaptopLedData) -> Self {
|
||||
// create a default config here
|
||||
let enabled = if prod_id == AuraDevice::X19b6 {
|
||||
AuraPowerConfig::AuraDevRog2(HashSet::from([
|
||||
AuraDevRog2::BootLogo,
|
||||
AuraDevRog2::BootKeyb,
|
||||
AuraDevRog2::SleepLogo,
|
||||
AuraDevRog2::SleepKeyb,
|
||||
AuraDevRog2::AwakeLogo,
|
||||
AuraDevRog2::AwakeKeyb,
|
||||
AuraDevRog2::ShutdownLogo,
|
||||
AuraDevRog2::ShutdownKeyb,
|
||||
AuraDevRog2::BootBar,
|
||||
AuraDevRog2::AwakeBar,
|
||||
AuraDevRog2::SleepBar,
|
||||
AuraDevRog2::ShutdownBar,
|
||||
AuraDevRog2::BootRearGlow,
|
||||
AuraDevRog2::AwakeRearGlow,
|
||||
AuraDevRog2::SleepRearGlow,
|
||||
AuraDevRog2::ShutdownRearGlow,
|
||||
]))
|
||||
} else if prod_id == AuraDevice::Tuf {
|
||||
let enabled = if prod_id.is_new_style() {
|
||||
AuraPowerConfig::AuraDevRog2(AuraPower::new_all_on())
|
||||
} else if prod_id.is_tuf_style() {
|
||||
AuraPowerConfig::AuraDevTuf(HashSet::from([
|
||||
AuraDevTuf::Awake,
|
||||
AuraDevTuf::Boot,
|
||||
@@ -187,6 +171,7 @@ impl AuraConfig {
|
||||
};
|
||||
|
||||
for n in &support_data.basic_modes {
|
||||
debug!("AuraConfig: creating default for {n}");
|
||||
config
|
||||
.builtins
|
||||
.insert(*n, AuraEffect::default_with_mode(*n));
|
||||
@@ -264,10 +249,15 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn set_multizone_4key_config() {
|
||||
let mut config = AuraConfig::create_default(AuraDevice::X19b6, &LaptopLedData::default());
|
||||
let mut config =
|
||||
AuraConfig::from_default_support(AuraDevice::X19b6, &LaptopLedData::default());
|
||||
|
||||
let effect = AuraEffect {
|
||||
colour1: Colour(0xff, 0x00, 0xff),
|
||||
colour1: Colour {
|
||||
r: 0xff,
|
||||
g: 0x00,
|
||||
b: 0xff,
|
||||
},
|
||||
zone: AuraZone::Key1,
|
||||
..Default::default()
|
||||
};
|
||||
@@ -276,21 +266,33 @@ mod tests {
|
||||
assert!(config.multizone.is_some());
|
||||
|
||||
let effect = AuraEffect {
|
||||
colour1: Colour(0x00, 0xff, 0xff),
|
||||
colour1: Colour {
|
||||
r: 0x00,
|
||||
g: 0xff,
|
||||
b: 0xff,
|
||||
},
|
||||
zone: AuraZone::Key2,
|
||||
..Default::default()
|
||||
};
|
||||
config.set_builtin(effect);
|
||||
|
||||
let effect = AuraEffect {
|
||||
colour1: Colour(0xff, 0xff, 0x00),
|
||||
colour1: Colour {
|
||||
r: 0xff,
|
||||
g: 0xff,
|
||||
b: 0x00,
|
||||
},
|
||||
zone: AuraZone::Key3,
|
||||
..Default::default()
|
||||
};
|
||||
config.set_builtin(effect);
|
||||
|
||||
let effect = AuraEffect {
|
||||
colour1: Colour(0x00, 0xff, 0x00),
|
||||
colour1: Colour {
|
||||
r: 0x00,
|
||||
g: 0xff,
|
||||
b: 0x00,
|
||||
},
|
||||
zone: AuraZone::Key4,
|
||||
..Default::default()
|
||||
};
|
||||
@@ -302,15 +304,44 @@ mod tests {
|
||||
let res = config.multizone.unwrap();
|
||||
let sta = res.get(&AuraModeNum::Static).unwrap();
|
||||
assert_eq!(sta.len(), 4);
|
||||
assert_eq!(sta[0].colour1, Colour(0xff, 0x00, 0xff));
|
||||
assert_eq!(sta[1].colour1, Colour(0x00, 0xff, 0xff));
|
||||
assert_eq!(sta[2].colour1, Colour(0xff, 0xff, 0x00));
|
||||
assert_eq!(sta[3].colour1, Colour(0x00, 0xff, 0x00));
|
||||
assert_eq!(
|
||||
sta[0].colour1,
|
||||
Colour {
|
||||
r: 0xff,
|
||||
g: 0x00,
|
||||
b: 0xff
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
sta[1].colour1,
|
||||
Colour {
|
||||
r: 0x00,
|
||||
g: 0xff,
|
||||
b: 0xff
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
sta[2].colour1,
|
||||
Colour {
|
||||
r: 0xff,
|
||||
g: 0xff,
|
||||
b: 0x00
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
sta[3].colour1,
|
||||
Colour {
|
||||
r: 0x00,
|
||||
g: 0xff,
|
||||
b: 0x00
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_multizone_multimode_config() {
|
||||
let mut config = AuraConfig::create_default(AuraDevice::X19b6, &LaptopLedData::default());
|
||||
let mut config =
|
||||
AuraConfig::from_default_support(AuraDevice::X19b6, &LaptopLedData::default());
|
||||
|
||||
let effect = AuraEffect {
|
||||
zone: AuraZone::Key1,
|
||||
|
||||
@@ -1,55 +1,19 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use config_traits::{StdConfig, StdConfigLoad};
|
||||
use dmi_id::DMIID;
|
||||
use log::{info, warn};
|
||||
use rog_aura::advanced::{LedUsbPackets, UsbPackets};
|
||||
use rog_aura::aura_detection::{LaptopLedData, ASUS_KEYBOARD_DEVICES};
|
||||
use rog_aura::usb::{AuraDevice, LED_APPLY, LED_SET};
|
||||
use rog_aura::{AuraEffect, AuraZone, Direction, LedBrightness, Speed, GRADIENT, LED_MSG_LEN};
|
||||
use rog_aura::{AuraEffect, Direction, LedBrightness, Speed, GRADIENT, LED_MSG_LEN};
|
||||
use rog_platform::hid_raw::HidRaw;
|
||||
use rog_platform::keyboard_led::KeyboardLed;
|
||||
use rog_platform::supported::LedSupportedFunctions;
|
||||
|
||||
use super::config::{AuraConfig, AuraPowerConfig};
|
||||
use crate::error::RogError;
|
||||
use crate::GetSupported;
|
||||
|
||||
impl GetSupported for CtrlKbdLed {
|
||||
type A = LedSupportedFunctions;
|
||||
|
||||
fn get_supported() -> Self::A {
|
||||
// let mode = <&str>::from(&<AuraModes>::from(*mode));
|
||||
let laptop = LaptopLedData::get_data();
|
||||
let stock_led_modes = laptop.basic_modes;
|
||||
let multizone_led_mode = laptop.basic_zones;
|
||||
let advanced_type = laptop.advanced_type;
|
||||
|
||||
let mut prod_id = AuraDevice::Unknown;
|
||||
for prod in ASUS_KEYBOARD_DEVICES {
|
||||
if HidRaw::new(prod.into()).is_ok() {
|
||||
prod_id = prod;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let rgb = KeyboardLed::new();
|
||||
if let Ok(p) = rgb.as_ref() {
|
||||
if p.has_kbd_rgb_mode() {
|
||||
prod_id = AuraDevice::Tuf;
|
||||
}
|
||||
}
|
||||
|
||||
LedSupportedFunctions {
|
||||
dev_id: prod_id,
|
||||
brightness: rgb.is_ok(),
|
||||
basic_modes: stock_led_modes,
|
||||
basic_zones: multizone_led_mode,
|
||||
advanced_type: advanced_type.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd)]
|
||||
#[derive(Debug)]
|
||||
pub enum LEDNode {
|
||||
KbdLed(KeyboardLed),
|
||||
Rog(HidRaw),
|
||||
@@ -60,15 +24,14 @@ pub struct CtrlKbdLed {
|
||||
// TODO: config stores the keyboard type as an AuraPower, use or update this
|
||||
pub led_prod: AuraDevice,
|
||||
pub led_node: LEDNode,
|
||||
pub kd_brightness: KeyboardLed,
|
||||
pub supported_modes: LaptopLedData,
|
||||
pub flip_effect_write: bool,
|
||||
pub sysfs_node: KeyboardLed,
|
||||
pub supported_data: LaptopLedData,
|
||||
pub per_key_mode_active: bool,
|
||||
pub config: AuraConfig,
|
||||
}
|
||||
|
||||
impl CtrlKbdLed {
|
||||
pub fn new(supported_modes: LaptopLedData) -> Result<Self, RogError> {
|
||||
pub fn new(supported_basic_modes: LaptopLedData) -> Result<Self, RogError> {
|
||||
let mut led_prod = AuraDevice::Unknown;
|
||||
let mut usb_node = None;
|
||||
for prod in ASUS_KEYBOARD_DEVICES {
|
||||
@@ -92,14 +55,12 @@ impl CtrlKbdLed {
|
||||
let rgb_led = KeyboardLed::new()?;
|
||||
|
||||
if usb_node.is_none() && !rgb_led.has_kbd_rgb_mode() {
|
||||
let dmi = sysfs_class::DmiId::default();
|
||||
if let Ok(prod_family) = dmi.product_family() {
|
||||
if prod_family.contains("TUF") {
|
||||
warn!(
|
||||
"kbd_rgb_mode was not found in the /sys/. You require a minimum 6.1 \
|
||||
kernel and a supported TUF laptop"
|
||||
);
|
||||
}
|
||||
let dmi = DMIID::new().unwrap_or_default();
|
||||
if dmi.dmi_family.contains("TUF") {
|
||||
warn!(
|
||||
"kbd_rgb_mode was not found in the /sys/. You require a minimum 6.1 kernel \
|
||||
and a supported TUF laptop"
|
||||
);
|
||||
}
|
||||
return Err(RogError::NoAuraKeyboard);
|
||||
}
|
||||
@@ -114,15 +75,17 @@ impl CtrlKbdLed {
|
||||
LEDNode::None
|
||||
};
|
||||
|
||||
let mut config_init = AuraConfig::create_default(led_prod, &supported_modes);
|
||||
// New loads data fromt he DB also
|
||||
let mut config_init = AuraConfig::new();
|
||||
let mut config_loaded = config_init.clone().load();
|
||||
|
||||
// update the initialised data with what we loaded from disk
|
||||
for mode in &mut config_init.builtins {
|
||||
// update init values from loaded values if they exist
|
||||
if let Some(loaded) = config_loaded.builtins.get(mode.0) {
|
||||
*mode.1 = loaded.clone();
|
||||
}
|
||||
}
|
||||
// Then replace just incase the initialised data contains new modes added
|
||||
config_loaded.builtins = config_init.builtins;
|
||||
|
||||
if let (Some(mut multizone_init), Some(multizone_loaded)) =
|
||||
@@ -134,7 +97,7 @@ impl CtrlKbdLed {
|
||||
let mut new_set = Vec::new();
|
||||
// only reuse a zone mode if the mode is supported
|
||||
for mode in loaded {
|
||||
if supported_modes.basic_modes.contains(&mode.mode) {
|
||||
if supported_basic_modes.basic_modes.contains(&mode.mode) {
|
||||
new_set.push(mode.clone());
|
||||
}
|
||||
}
|
||||
@@ -146,50 +109,15 @@ impl CtrlKbdLed {
|
||||
|
||||
let ctrl = CtrlKbdLed {
|
||||
led_prod,
|
||||
led_node, // on TUF this is the same as rgb_led / kd_brightness
|
||||
kd_brightness: rgb_led, // If was none then we already returned above
|
||||
supported_modes,
|
||||
flip_effect_write: false,
|
||||
led_node, // on TUF this is the same as rgb_led / kd_brightness
|
||||
sysfs_node: rgb_led, // If was none then we already returned above
|
||||
supported_data: supported_basic_modes,
|
||||
per_key_mode_active: false,
|
||||
config: config_loaded,
|
||||
};
|
||||
Ok(ctrl)
|
||||
}
|
||||
|
||||
pub(super) fn get_brightness(&self) -> Result<u8, RogError> {
|
||||
self.kd_brightness
|
||||
.get_brightness()
|
||||
.map_err(RogError::Platform)
|
||||
}
|
||||
|
||||
pub(super) fn set_brightness(&self, brightness: LedBrightness) -> Result<(), RogError> {
|
||||
self.kd_brightness
|
||||
.set_brightness(brightness as u8)
|
||||
.map_err(RogError::Platform)
|
||||
}
|
||||
|
||||
pub fn next_brightness(&mut self) -> Result<(), RogError> {
|
||||
let mut bright = (self.config.brightness as u32) + 1;
|
||||
if bright > 3 {
|
||||
bright = 0;
|
||||
}
|
||||
self.config.brightness = <LedBrightness>::from(bright);
|
||||
self.config.write();
|
||||
self.set_brightness(self.config.brightness)
|
||||
}
|
||||
|
||||
pub fn prev_brightness(&mut self) -> Result<(), RogError> {
|
||||
let mut bright = self.config.brightness as u32;
|
||||
if bright == 0 {
|
||||
bright = 3;
|
||||
} else {
|
||||
bright -= 1;
|
||||
}
|
||||
self.config.brightness = <LedBrightness>::from(bright);
|
||||
self.config.write();
|
||||
self.set_brightness(self.config.brightness)
|
||||
}
|
||||
|
||||
/// Set combination state for boot animation/sleep animation/all leds/keys
|
||||
/// leds/side leds LED active
|
||||
pub(super) fn set_power_states(&mut self) -> Result<(), RogError> {
|
||||
@@ -210,29 +138,6 @@ impl CtrlKbdLed {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Set an Aura effect if the effect mode or zone is supported.
|
||||
///
|
||||
/// On success the aura config file is read to refresh cached values, then
|
||||
/// the effect is stored and config written to disk.
|
||||
pub(crate) fn set_effect(&mut self, effect: AuraEffect) -> Result<(), RogError> {
|
||||
if !self.supported_modes.basic_modes.contains(&effect.mode)
|
||||
|| effect.zone != AuraZone::None
|
||||
&& !self.supported_modes.basic_zones.contains(&effect.zone)
|
||||
{
|
||||
return Err(RogError::AuraEffectNotSupported);
|
||||
}
|
||||
|
||||
self.write_mode(&effect)?;
|
||||
self.config.read(); // refresh config if successful
|
||||
self.config.set_builtin(effect);
|
||||
if self.config.brightness == LedBrightness::Off {
|
||||
self.config.brightness = LedBrightness::Med;
|
||||
}
|
||||
self.config.write();
|
||||
self.set_brightness(self.config.brightness)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Write an effect block. This is for per-key, but can be repurposed to
|
||||
/// write the raw factory mode packets - when doing this it is expected that
|
||||
/// only the first `Vec` (`effect[0]`) is valid.
|
||||
@@ -272,54 +177,18 @@ impl CtrlKbdLed {
|
||||
tuf.set_kbd_rgb_mode(&[0, 0, r, g, b, 0])?;
|
||||
}
|
||||
}
|
||||
self.flip_effect_write = !self.flip_effect_write;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(super) fn toggle_mode(&mut self, reverse: bool) -> Result<(), RogError> {
|
||||
let current = self.config.current_mode;
|
||||
if let Some(idx) = self
|
||||
.supported_modes
|
||||
.basic_modes
|
||||
.iter()
|
||||
.position(|v| *v == current)
|
||||
{
|
||||
let mut idx = idx;
|
||||
// goes past end of array
|
||||
if reverse {
|
||||
if idx == 0 {
|
||||
idx = self.supported_modes.basic_modes.len() - 1;
|
||||
} else {
|
||||
idx -= 1;
|
||||
}
|
||||
} else {
|
||||
idx += 1;
|
||||
if idx == self.supported_modes.basic_modes.len() {
|
||||
idx = 0;
|
||||
}
|
||||
}
|
||||
let next = self.supported_modes.basic_modes[idx];
|
||||
|
||||
self.config.read();
|
||||
// if self.config.builtins.contains_key(&next) {
|
||||
self.config.current_mode = next;
|
||||
self.write_current_config_mode()?;
|
||||
// }
|
||||
self.config.write();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_mode(&mut self, mode: &AuraEffect) -> Result<(), RogError> {
|
||||
pub fn write_mode(&mut self, mode: &AuraEffect) -> Result<(), RogError> {
|
||||
if let LEDNode::KbdLed(platform) = &self.led_node {
|
||||
let buf = [
|
||||
1,
|
||||
mode.mode as u8,
|
||||
mode.colour1.0,
|
||||
mode.colour1.1,
|
||||
mode.colour1.2,
|
||||
mode.colour1.r,
|
||||
mode.colour1.g,
|
||||
mode.colour1.b,
|
||||
mode.speed as u8,
|
||||
];
|
||||
platform.set_kbd_rgb_mode(&buf)?;
|
||||
@@ -376,7 +245,7 @@ impl CtrlKbdLed {
|
||||
/// exists.
|
||||
fn create_multizone_default(&mut self) -> Result<(), RogError> {
|
||||
let mut default = vec![];
|
||||
for (i, tmp) in self.supported_modes.basic_zones.iter().enumerate() {
|
||||
for (i, tmp) in self.supported_data.basic_zones.iter().enumerate() {
|
||||
default.push(AuraEffect {
|
||||
mode: self.config.current_mode,
|
||||
zone: *tmp,
|
||||
@@ -403,96 +272,32 @@ impl CtrlKbdLed {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use rog_aura::aura_detection::LaptopLedData;
|
||||
use rog_aura::aura_detection::{LaptopLedData, PowerZones};
|
||||
use rog_aura::usb::AuraDevice;
|
||||
use rog_aura::{AuraEffect, AuraModeNum, AuraZone, Colour};
|
||||
use rog_aura::{AuraModeNum, AuraZone};
|
||||
use rog_platform::keyboard_led::KeyboardLed;
|
||||
|
||||
use super::CtrlKbdLed;
|
||||
use crate::ctrl_aura::config::AuraConfig;
|
||||
use crate::ctrl_aura::controller::LEDNode;
|
||||
|
||||
#[test]
|
||||
// #[ignore = "Must be manually run due to detection stage"]
|
||||
fn check_set_mode_errors() {
|
||||
// Checking to ensure set_mode errors when unsupported modes are tried
|
||||
let config = AuraConfig::create_default(AuraDevice::X19b6, &LaptopLedData::default());
|
||||
let supported_modes = LaptopLedData {
|
||||
board_name: String::new(),
|
||||
layout_name: "ga401".to_owned(),
|
||||
basic_modes: vec![AuraModeNum::Static],
|
||||
basic_zones: vec![],
|
||||
advanced_type: rog_aura::AdvancedAuraType::None,
|
||||
};
|
||||
let mut controller = CtrlKbdLed {
|
||||
led_prod: AuraDevice::X19b6,
|
||||
led_node: LEDNode::None,
|
||||
kd_brightness: KeyboardLed::default(),
|
||||
supported_modes,
|
||||
flip_effect_write: false,
|
||||
per_key_mode_active: false,
|
||||
config,
|
||||
};
|
||||
|
||||
let mut effect = AuraEffect {
|
||||
colour1: Colour(0xff, 0x00, 0xff),
|
||||
zone: AuraZone::None,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
// This error comes from write_bytes because we don't have a keyboard node
|
||||
// stored
|
||||
assert_eq!(
|
||||
controller
|
||||
.set_effect(effect.clone())
|
||||
.unwrap_err()
|
||||
.to_string(),
|
||||
"No supported Aura keyboard"
|
||||
);
|
||||
|
||||
effect.mode = AuraModeNum::Laser;
|
||||
assert_eq!(
|
||||
controller
|
||||
.set_effect(effect.clone())
|
||||
.unwrap_err()
|
||||
.to_string(),
|
||||
"Aura effect not supported"
|
||||
);
|
||||
|
||||
effect.mode = AuraModeNum::Static;
|
||||
effect.zone = AuraZone::Key2;
|
||||
assert_eq!(
|
||||
controller
|
||||
.set_effect(effect.clone())
|
||||
.unwrap_err()
|
||||
.to_string(),
|
||||
"Aura effect not supported"
|
||||
);
|
||||
|
||||
controller.supported_modes.basic_zones.push(AuraZone::Key2);
|
||||
assert_eq!(
|
||||
controller.set_effect(effect).unwrap_err().to_string(),
|
||||
"No supported Aura keyboard"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn create_multizone_if_no_config() {
|
||||
// Checking to ensure set_mode errors when unsupported modes are tried
|
||||
let config = AuraConfig::create_default(AuraDevice::X19b6, &LaptopLedData::default());
|
||||
let supported_modes = LaptopLedData {
|
||||
let config = AuraConfig::from_default_support(AuraDevice::X19b6, &LaptopLedData::default());
|
||||
let supported_basic_modes = LaptopLedData {
|
||||
board_name: String::new(),
|
||||
layout_name: "ga401".to_owned(),
|
||||
basic_modes: vec![AuraModeNum::Static],
|
||||
basic_zones: vec![],
|
||||
advanced_type: rog_aura::AdvancedAuraType::None,
|
||||
power_zones: vec![PowerZones::Keyboard, PowerZones::RearGlow],
|
||||
};
|
||||
let mut controller = CtrlKbdLed {
|
||||
led_prod: AuraDevice::X19b6,
|
||||
led_node: LEDNode::None,
|
||||
kd_brightness: KeyboardLed::default(),
|
||||
supported_modes,
|
||||
flip_effect_write: false,
|
||||
sysfs_node: KeyboardLed::default(),
|
||||
supported_data: supported_basic_modes,
|
||||
per_key_mode_active: false,
|
||||
config,
|
||||
};
|
||||
@@ -501,8 +306,8 @@ mod tests {
|
||||
assert!(controller.create_multizone_default().is_err());
|
||||
assert!(controller.config.multizone.is_none());
|
||||
|
||||
controller.supported_modes.basic_zones.push(AuraZone::Key1);
|
||||
controller.supported_modes.basic_zones.push(AuraZone::Key2);
|
||||
controller.supported_data.basic_zones.push(AuraZone::Key1);
|
||||
controller.supported_data.basic_zones.push(AuraZone::Key2);
|
||||
assert!(controller.create_multizone_default().is_ok());
|
||||
assert!(controller.config.multizone.is_some());
|
||||
|
||||
@@ -517,20 +322,20 @@ mod tests {
|
||||
#[test]
|
||||
fn next_mode_create_multizone_if_no_config() {
|
||||
// Checking to ensure set_mode errors when unsupported modes are tried
|
||||
let config = AuraConfig::create_default(AuraDevice::X19b6, &LaptopLedData::default());
|
||||
let supported_modes = LaptopLedData {
|
||||
let config = AuraConfig::from_default_support(AuraDevice::X19b6, &LaptopLedData::default());
|
||||
let supported_basic_modes = LaptopLedData {
|
||||
board_name: String::new(),
|
||||
layout_name: "ga401".to_owned(),
|
||||
basic_modes: vec![AuraModeNum::Static],
|
||||
basic_zones: vec![AuraZone::Key1, AuraZone::Key2],
|
||||
advanced_type: rog_aura::AdvancedAuraType::None,
|
||||
power_zones: vec![PowerZones::Keyboard, PowerZones::RearGlow],
|
||||
};
|
||||
let mut controller = CtrlKbdLed {
|
||||
led_prod: AuraDevice::X19b6,
|
||||
led_node: LEDNode::None,
|
||||
kd_brightness: KeyboardLed::default(),
|
||||
supported_modes,
|
||||
flip_effect_write: false,
|
||||
sysfs_node: KeyboardLed::default(),
|
||||
supported_data: supported_basic_modes,
|
||||
per_key_mode_active: false,
|
||||
config,
|
||||
};
|
||||
|
||||
@@ -1,39 +1,40 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use config_traits::StdConfig;
|
||||
use log::{error, info, warn};
|
||||
use log::{debug, error, info, warn};
|
||||
use rog_aura::advanced::UsbPackets;
|
||||
use rog_aura::usb::AuraPowerDev;
|
||||
use rog_aura::{AuraEffect, AuraModeNum, LedBrightness};
|
||||
use rog_aura::aura_detection::PowerZones;
|
||||
use rog_aura::usb::{AuraDevice, AuraPowerDev};
|
||||
use rog_aura::{AuraEffect, AuraModeNum, AuraZone, LedBrightness};
|
||||
use zbus::export::futures_util::lock::{Mutex, MutexGuard};
|
||||
use zbus::export::futures_util::StreamExt;
|
||||
use zbus::fdo::Error as ZbErr;
|
||||
use zbus::{dbus_interface, Connection, SignalContext};
|
||||
|
||||
use super::controller::CtrlKbdLed;
|
||||
use crate::error::RogError;
|
||||
use crate::CtrlTask;
|
||||
|
||||
pub(super) const ZBUS_PATH: &str = "/org/asuslinux/Aura";
|
||||
pub const AURA_ZBUS_NAME: &str = "Aura";
|
||||
pub const AURA_ZBUS_PATH: &str = "/org/asuslinux/Aura";
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct CtrlKbdLedZbus(pub Arc<Mutex<CtrlKbdLed>>);
|
||||
pub struct CtrlAuraZbus(pub Arc<Mutex<CtrlKbdLed>>);
|
||||
|
||||
impl CtrlKbdLedZbus {
|
||||
impl CtrlAuraZbus {
|
||||
fn update_config(lock: &mut CtrlKbdLed) -> Result<(), RogError> {
|
||||
let bright = lock.kd_brightness.get_brightness()?;
|
||||
let bright = lock.sysfs_node.get_brightness()?;
|
||||
lock.config.read();
|
||||
lock.config.brightness = (bright as u32).into();
|
||||
lock.config.brightness = bright.into();
|
||||
lock.config.write();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl crate::ZbusRun for CtrlKbdLedZbus {
|
||||
impl crate::ZbusRun for CtrlAuraZbus {
|
||||
async fn add_to_server(self, server: &mut Connection) {
|
||||
Self::add_to_server_helper(self, ZBUS_PATH, server).await;
|
||||
Self::add_to_server_helper(self, AURA_ZBUS_PATH, server).await;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,211 +42,170 @@ impl crate::ZbusRun for CtrlKbdLedZbus {
|
||||
///
|
||||
/// LED commands are split between Brightness, Modes, Per-Key
|
||||
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
||||
impl CtrlKbdLedZbus {
|
||||
/// Set the keyboard brightness level (0-3)
|
||||
async fn set_brightness(&mut self, brightness: LedBrightness) {
|
||||
impl CtrlAuraZbus {
|
||||
/// Return the device type for this Aura keyboard
|
||||
#[dbus_interface(property)]
|
||||
async fn device_type(&self) -> AuraDevice {
|
||||
let ctrl = self.0.lock().await;
|
||||
ctrl.set_brightness(brightness)
|
||||
.map_err(|err| warn!("{}", err))
|
||||
.ok();
|
||||
ctrl.led_prod
|
||||
}
|
||||
|
||||
/// Return the current LED brightness
|
||||
#[dbus_interface(property)]
|
||||
async fn brightness(&self) -> Result<LedBrightness, ZbErr> {
|
||||
let ctrl = self.0.lock().await;
|
||||
Ok(ctrl.sysfs_node.get_brightness().map(|n| n.into())?)
|
||||
}
|
||||
|
||||
/// Set the keyboard brightness level (0-3)
|
||||
#[dbus_interface(property)]
|
||||
async fn set_brightness(&mut self, brightness: LedBrightness) -> Result<(), ZbErr> {
|
||||
let ctrl = self.0.lock().await;
|
||||
Ok(ctrl.sysfs_node.set_brightness(brightness.into())?)
|
||||
}
|
||||
|
||||
/// Total levels of brightness available
|
||||
#[dbus_interface(property)]
|
||||
async fn supported_brightness(&self) -> Vec<LedBrightness> {
|
||||
vec![
|
||||
LedBrightness::Off,
|
||||
LedBrightness::Low,
|
||||
LedBrightness::Med,
|
||||
LedBrightness::High,
|
||||
]
|
||||
}
|
||||
|
||||
/// The total available modes
|
||||
#[dbus_interface(property)]
|
||||
async fn supported_basic_modes(&self) -> Result<Vec<AuraModeNum>, ZbErr> {
|
||||
let ctrl = self.0.lock().await;
|
||||
Ok(ctrl.config.builtins.keys().cloned().collect())
|
||||
}
|
||||
|
||||
#[dbus_interface(property)]
|
||||
async fn supported_basic_zones(&self) -> Result<Vec<AuraZone>, ZbErr> {
|
||||
let ctrl = self.0.lock().await;
|
||||
Ok(ctrl.supported_data.basic_zones.clone())
|
||||
}
|
||||
|
||||
#[dbus_interface(property)]
|
||||
async fn supported_power_zones(&self) -> Result<Vec<PowerZones>, ZbErr> {
|
||||
let ctrl = self.0.lock().await;
|
||||
Ok(ctrl.supported_data.power_zones.clone())
|
||||
}
|
||||
|
||||
/// The current mode data
|
||||
#[dbus_interface(property)]
|
||||
async fn led_mode(&self) -> Result<AuraModeNum, ZbErr> {
|
||||
let ctrl = self.0.lock().await;
|
||||
Ok(ctrl.config.current_mode)
|
||||
}
|
||||
|
||||
/// Set an Aura effect if the effect mode or zone is supported.
|
||||
///
|
||||
/// On success the aura config file is read to refresh cached values, then
|
||||
/// the effect is stored and config written to disk.
|
||||
#[dbus_interface(property)]
|
||||
async fn set_led_mode(&mut self, num: AuraModeNum) -> Result<(), ZbErr> {
|
||||
let mut ctrl = self.0.lock().await;
|
||||
ctrl.config.current_mode = num;
|
||||
ctrl.write_current_config_mode()?;
|
||||
if ctrl.config.brightness == LedBrightness::Off {
|
||||
ctrl.config.brightness = LedBrightness::Med;
|
||||
}
|
||||
ctrl.sysfs_node
|
||||
.set_brightness(ctrl.config.brightness.into())?;
|
||||
ctrl.config.write();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// The current mode data
|
||||
#[dbus_interface(property)]
|
||||
async fn led_mode_data(&self) -> Result<AuraEffect, ZbErr> {
|
||||
let ctrl = self.0.lock().await;
|
||||
let mode = ctrl.config.current_mode;
|
||||
match ctrl.config.builtins.get(&mode) {
|
||||
Some(effect) => Ok(effect.clone()),
|
||||
None => Err(ZbErr::Failed("Could not get the current effect".into())),
|
||||
}
|
||||
}
|
||||
|
||||
/// Set an Aura effect if the effect mode or zone is supported.
|
||||
///
|
||||
/// On success the aura config file is read to refresh cached values, then
|
||||
/// the effect is stored and config written to disk.
|
||||
#[dbus_interface(property)]
|
||||
async fn set_led_mode_data(&mut self, effect: AuraEffect) -> Result<(), ZbErr> {
|
||||
let mut ctrl = self.0.lock().await;
|
||||
if !ctrl.supported_data.basic_modes.contains(&effect.mode)
|
||||
|| effect.zone != AuraZone::None
|
||||
&& !ctrl.supported_data.basic_zones.contains(&effect.zone)
|
||||
{
|
||||
return Err(ZbErr::NotSupported(format!(
|
||||
"The Aura effect is not supported: {effect:?}"
|
||||
)));
|
||||
}
|
||||
|
||||
ctrl.write_mode(&effect)?;
|
||||
if ctrl.config.brightness == LedBrightness::Off {
|
||||
ctrl.config.brightness = LedBrightness::Med;
|
||||
}
|
||||
ctrl.sysfs_node
|
||||
.set_brightness(ctrl.config.brightness.into())?;
|
||||
ctrl.config.set_builtin(effect);
|
||||
ctrl.config.write();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get the data set for every mode available
|
||||
async fn all_mode_data(&self) -> BTreeMap<AuraModeNum, AuraEffect> {
|
||||
let ctrl = self.0.lock().await;
|
||||
ctrl.config.builtins.clone()
|
||||
}
|
||||
|
||||
// As property doesn't work for AuraPowerDev (complexity of serialization?)
|
||||
#[dbus_interface(property)]
|
||||
async fn led_power(&self) -> AuraPowerDev {
|
||||
let ctrl = self.0.lock().await;
|
||||
AuraPowerDev::from(&ctrl.config.enabled)
|
||||
}
|
||||
|
||||
/// Set a variety of states, input is array of enum.
|
||||
/// `enabled` sets if the sent array should be disabled or enabled
|
||||
///
|
||||
/// ```text
|
||||
/// pub struct AuraPowerDev {
|
||||
/// pub x1866: Vec<AuraDev1866>,
|
||||
/// pub x19b6: Vec<AuraDev19b6>,
|
||||
/// }
|
||||
/// pub enum AuraDev1866 {
|
||||
/// Awake,
|
||||
/// Keyboard,
|
||||
/// Lightbar,
|
||||
/// Boot,
|
||||
/// Sleep,
|
||||
/// }
|
||||
/// enum AuraDev19b6 {
|
||||
/// BootLogo,
|
||||
/// BootKeyb,
|
||||
/// AwakeLogo,
|
||||
/// AwakeKeyb,
|
||||
/// SleepLogo,
|
||||
/// SleepKeyb,
|
||||
/// ShutdownLogo,
|
||||
/// ShutdownKeyb,
|
||||
/// AwakeBar,
|
||||
/// BootBar,
|
||||
/// SleepBar,
|
||||
/// ShutdownBar,
|
||||
/// BootRearBar,
|
||||
/// AwakeRearBar,
|
||||
/// SleepRearBar,
|
||||
/// ShutdownRearBar,
|
||||
/// }
|
||||
/// ```
|
||||
async fn set_leds_power(
|
||||
&mut self,
|
||||
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
||||
options: AuraPowerDev,
|
||||
enabled: bool,
|
||||
) -> zbus::fdo::Result<()> {
|
||||
/// For Modern ROG devices the "enabled" flag is ignored.
|
||||
#[dbus_interface(property)]
|
||||
async fn set_led_power(&mut self, options: (AuraPowerDev, bool)) -> Result<(), ZbErr> {
|
||||
let enabled = options.1;
|
||||
let options = options.0;
|
||||
let mut ctrl = self.0.lock().await;
|
||||
for p in options.tuf {
|
||||
ctrl.config.enabled.set_tuf(p, enabled);
|
||||
}
|
||||
for p in options.x1866 {
|
||||
for p in options.old_rog {
|
||||
ctrl.config.enabled.set_0x1866(p, enabled);
|
||||
}
|
||||
for p in options.x19b6 {
|
||||
ctrl.config.enabled.set_0x19b6(p, enabled);
|
||||
}
|
||||
|
||||
ctrl.config.enabled.set_0x19b6(options.rog);
|
||||
ctrl.config.write();
|
||||
|
||||
ctrl.set_power_states().map_err(|e| {
|
||||
Ok(ctrl.set_power_states().map_err(|e| {
|
||||
warn!("{}", e);
|
||||
e
|
||||
})?;
|
||||
|
||||
Self::notify_power_states(&ctxt, &AuraPowerDev::from(&ctrl.config.enabled))
|
||||
.await
|
||||
.unwrap_or_else(|err| warn!("{}", err));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn set_led_mode(
|
||||
&mut self,
|
||||
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
||||
effect: AuraEffect,
|
||||
) -> zbus::fdo::Result<()> {
|
||||
let mut ctrl = self.0.lock().await;
|
||||
|
||||
ctrl.set_effect(effect).map_err(|e| {
|
||||
warn!("{}", e);
|
||||
e
|
||||
})?;
|
||||
|
||||
ctrl.set_brightness(ctrl.config.brightness).map_err(|e| {
|
||||
warn!("{}", e);
|
||||
e
|
||||
})?;
|
||||
|
||||
if let Some(mode) = ctrl.config.builtins.get(&ctrl.config.current_mode) {
|
||||
Self::notify_led(&ctxt, mode.clone())
|
||||
.await
|
||||
.unwrap_or_else(|err| warn!("{}", err));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn next_led_mode(
|
||||
&self,
|
||||
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
||||
) -> zbus::fdo::Result<()> {
|
||||
let mut ctrl = self.0.lock().await;
|
||||
|
||||
ctrl.toggle_mode(false).map_err(|e| {
|
||||
warn!("{}", e);
|
||||
e
|
||||
})?;
|
||||
|
||||
if let Some(mode) = ctrl.config.builtins.get(&ctrl.config.current_mode) {
|
||||
Self::notify_led(&ctxt, mode.clone())
|
||||
.await
|
||||
.unwrap_or_else(|err| warn!("{}", err));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn prev_led_mode(
|
||||
&self,
|
||||
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
||||
) -> zbus::fdo::Result<()> {
|
||||
let mut ctrl = self.0.lock().await;
|
||||
|
||||
ctrl.toggle_mode(true).map_err(|e| {
|
||||
warn!("{}", e);
|
||||
e
|
||||
})?;
|
||||
|
||||
if let Some(mode) = ctrl.config.builtins.get(&ctrl.config.current_mode) {
|
||||
Self::notify_led(&ctxt, mode.clone())
|
||||
.await
|
||||
.unwrap_or_else(|err| warn!("{}", err));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn next_led_brightness(&self) -> zbus::fdo::Result<()> {
|
||||
let mut ctrl = self.0.lock().await;
|
||||
ctrl.next_brightness().map_err(|e| {
|
||||
warn!("{}", e);
|
||||
e
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn prev_led_brightness(&self) -> zbus::fdo::Result<()> {
|
||||
let mut ctrl = self.0.lock().await;
|
||||
ctrl.prev_brightness().map_err(|e| {
|
||||
warn!("{}", e);
|
||||
e
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// As property doesn't work for AuraPowerDev (complexity of serialization?)
|
||||
// #[dbus_interface(property)]
|
||||
async fn leds_enabled(&self) -> AuraPowerDev {
|
||||
let ctrl = self.0.lock().await;
|
||||
AuraPowerDev::from(&ctrl.config.enabled)
|
||||
}
|
||||
|
||||
/// Return the current mode data
|
||||
async fn led_mode(&self) -> AuraModeNum {
|
||||
let ctrl = self.0.lock().await;
|
||||
ctrl.config.current_mode
|
||||
}
|
||||
|
||||
/// Return a list of available modes
|
||||
async fn led_modes(&self) -> BTreeMap<AuraModeNum, AuraEffect> {
|
||||
let ctrl = self.0.lock().await;
|
||||
ctrl.config.builtins.clone()
|
||||
})?)
|
||||
}
|
||||
|
||||
/// On machine that have some form of either per-key keyboard or per-zone
|
||||
/// this can be used to write custom effects over dbus. The input is a
|
||||
/// nested `Vec<Vec<8>>` where `Vec<u8>` is a raw USB packet
|
||||
async fn direct_addressing_raw(&self, data: UsbPackets) -> zbus::fdo::Result<()> {
|
||||
async fn direct_addressing_raw(&self, data: UsbPackets) -> Result<(), ZbErr> {
|
||||
let mut ctrl = self.0.lock().await;
|
||||
ctrl.write_effect_block(&data)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Return the current LED brightness
|
||||
#[dbus_interface(property)]
|
||||
async fn led_brightness(&self) -> i8 {
|
||||
let ctrl = self.0.lock().await;
|
||||
ctrl.get_brightness().map(|n| n as i8).unwrap_or(-1)
|
||||
}
|
||||
|
||||
#[dbus_interface(signal)]
|
||||
async fn notify_led(signal_ctxt: &SignalContext<'_>, data: AuraEffect) -> zbus::Result<()>;
|
||||
|
||||
#[dbus_interface(signal)]
|
||||
async fn notify_power_states(
|
||||
signal_ctxt: &SignalContext<'_>,
|
||||
data: &AuraPowerDev,
|
||||
) -> zbus::Result<()>;
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl CtrlTask for CtrlKbdLedZbus {
|
||||
impl CtrlTask for CtrlAuraZbus {
|
||||
fn zbus_path() -> &'static str {
|
||||
ZBUS_PATH
|
||||
AURA_ZBUS_PATH
|
||||
}
|
||||
|
||||
async fn create_tasks(&self, _: SignalContext<'static>) -> Result<(), RogError> {
|
||||
@@ -253,14 +213,14 @@ impl CtrlTask for CtrlKbdLedZbus {
|
||||
// If waking up
|
||||
if !start {
|
||||
info!("CtrlKbdLedTask reloading brightness and modes");
|
||||
lock.set_brightness(lock.config.brightness)
|
||||
lock.sysfs_node
|
||||
.set_brightness(lock.config.brightness.into())
|
||||
.map_err(|e| error!("CtrlKbdLedTask: {e}"))
|
||||
.ok();
|
||||
lock.write_current_config_mode()
|
||||
.map_err(|e| error!("CtrlKbdLedTask: {e}"))
|
||||
.ok();
|
||||
} else if start {
|
||||
info!("CtrlKbdLedTask saving last brightness");
|
||||
Self::update_config(&mut lock)
|
||||
.map_err(|e| error!("CtrlKbdLedTask: {e}"))
|
||||
.ok();
|
||||
@@ -268,46 +228,36 @@ impl CtrlTask for CtrlKbdLedZbus {
|
||||
};
|
||||
|
||||
let inner1 = self.0.clone();
|
||||
let inner2 = self.0.clone();
|
||||
let inner3 = self.0.clone();
|
||||
let inner4 = self.0.clone();
|
||||
self.create_sys_event_tasks(
|
||||
// Loop so that we do aquire the lock but also don't block other
|
||||
// threads (prevents potential deadlocks)
|
||||
move || {
|
||||
move |sleeping| {
|
||||
let inner1 = inner1.clone();
|
||||
async move {
|
||||
let lock = inner1.lock().await;
|
||||
load_save(true, lock);
|
||||
load_save(sleeping, lock);
|
||||
}
|
||||
},
|
||||
move || {
|
||||
let inner2 = inner2.clone();
|
||||
async move {
|
||||
let lock = inner2.lock().await;
|
||||
load_save(false, lock);
|
||||
}
|
||||
},
|
||||
move || {
|
||||
move |_shutting_down| {
|
||||
let inner3 = inner3.clone();
|
||||
async move {
|
||||
let lock = inner3.lock().await;
|
||||
load_save(false, lock);
|
||||
}
|
||||
},
|
||||
move || {
|
||||
let inner4 = inner4.clone();
|
||||
async move {
|
||||
let lock = inner4.lock().await;
|
||||
load_save(false, lock);
|
||||
}
|
||||
move |_lid_closed| {
|
||||
// on lid change
|
||||
async move {}
|
||||
},
|
||||
move |_power_plugged| {
|
||||
// power change
|
||||
async move {}
|
||||
},
|
||||
)
|
||||
.await;
|
||||
|
||||
let ctrl2 = self.0.clone();
|
||||
let ctrl = self.0.lock().await;
|
||||
let watch = ctrl.kd_brightness.monitor_brightness()?;
|
||||
let watch = ctrl.sysfs_node.monitor_brightness()?;
|
||||
tokio::spawn(async move {
|
||||
let mut buffer = [0; 32];
|
||||
watch
|
||||
@@ -325,11 +275,12 @@ impl CtrlTask for CtrlKbdLedZbus {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl crate::Reloadable for CtrlKbdLedZbus {
|
||||
impl crate::Reloadable for CtrlAuraZbus {
|
||||
async fn reload(&mut self) -> Result<(), RogError> {
|
||||
let mut ctrl = self.0.lock().await;
|
||||
debug!("CtrlKbdLedZbus: reloading keyboard mode");
|
||||
ctrl.write_current_config_mode()?;
|
||||
debug!("CtrlKbdLedZbus: reloading power states");
|
||||
ctrl.set_power_states().map_err(|err| warn!("{err}")).ok();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
292
asusd/src/ctrl_fancurves.rs
Normal file
292
asusd/src/ctrl_fancurves.rs
Normal file
@@ -0,0 +1,292 @@
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use std::thread::sleep;
|
||||
use std::time::Duration;
|
||||
|
||||
use config_traits::{StdConfig, StdConfigLoad};
|
||||
use futures_lite::StreamExt;
|
||||
use log::{debug, error, info, warn};
|
||||
use rog_platform::platform::{RogPlatform, ThrottlePolicy};
|
||||
use rog_profiles::error::ProfileError;
|
||||
use rog_profiles::fan_curve_set::CurveData;
|
||||
use rog_profiles::{find_fan_curve_node, FanCurvePU, FanCurveProfiles};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use tokio::sync::Mutex;
|
||||
use zbus::{dbus_interface, Connection, SignalContext};
|
||||
|
||||
use crate::error::RogError;
|
||||
use crate::{CtrlTask, CONFIG_PATH_BASE};
|
||||
|
||||
const MOD_NAME: &str = "FanCurveZbus";
|
||||
pub const FAN_CURVE_ZBUS_NAME: &str = "FanCurves";
|
||||
pub const FAN_CURVE_ZBUS_PATH: &str = "/org/asuslinux/FanCurves";
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug, Default)]
|
||||
pub struct FanCurveConfig {
|
||||
pub profiles: FanCurveProfiles,
|
||||
#[serde(skip)]
|
||||
pub current: u8,
|
||||
}
|
||||
|
||||
impl StdConfig for FanCurveConfig {
|
||||
/// Create a new config. The defaults are zeroed so the device must be read
|
||||
/// to get the actual device defaults.
|
||||
fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
fn file_name(&self) -> String {
|
||||
"fan_curves.ron".to_owned()
|
||||
}
|
||||
|
||||
fn config_dir() -> std::path::PathBuf {
|
||||
PathBuf::from(CONFIG_PATH_BASE)
|
||||
}
|
||||
}
|
||||
|
||||
impl StdConfigLoad for FanCurveConfig {}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CtrlFanCurveZbus {
|
||||
config: Arc<Mutex<FanCurveConfig>>,
|
||||
platform: RogPlatform,
|
||||
}
|
||||
|
||||
// Non-zbus-derive impl
|
||||
impl CtrlFanCurveZbus {
|
||||
pub fn new() -> Result<Self, RogError> {
|
||||
let platform = RogPlatform::new()?;
|
||||
if platform.has_throttle_thermal_policy() {
|
||||
info!("{MOD_NAME}: Device has profile control available");
|
||||
find_fan_curve_node()?;
|
||||
info!("{MOD_NAME}: Device has fan curves available");
|
||||
let mut config = FanCurveConfig::new();
|
||||
let mut fan_curves = FanCurveProfiles::default();
|
||||
|
||||
// Only do defaults if the config doesn't already exist\
|
||||
if config.profiles.balanced.is_empty() || !config.file_path().exists() {
|
||||
info!("{MOD_NAME}: Fetching default fan curves");
|
||||
|
||||
let current = platform.get_throttle_thermal_policy()?;
|
||||
for this in [
|
||||
ThrottlePolicy::Balanced,
|
||||
ThrottlePolicy::Performance,
|
||||
ThrottlePolicy::Quiet,
|
||||
] {
|
||||
// For each profile we need to switch to it before we
|
||||
// can read the existing values from hardware. The ACPI method used
|
||||
// for this is what limits us.
|
||||
platform.set_throttle_thermal_policy(this.into())?;
|
||||
let mut dev = find_fan_curve_node()?;
|
||||
fan_curves.set_active_curve_to_defaults(this, &mut dev)?;
|
||||
|
||||
info!("{MOD_NAME}: {this:?}:");
|
||||
for curve in fan_curves.get_fan_curves_for(this) {
|
||||
info!("{}", String::from(curve));
|
||||
}
|
||||
}
|
||||
platform.set_throttle_thermal_policy(current)?;
|
||||
config.profiles = fan_curves;
|
||||
config.write();
|
||||
} else {
|
||||
info!("{MOD_NAME}: Fan curves previously stored, loading...");
|
||||
config = config.load();
|
||||
}
|
||||
|
||||
return Ok(Self {
|
||||
config: Arc::new(Mutex::new(config)),
|
||||
platform,
|
||||
});
|
||||
}
|
||||
|
||||
Err(ProfileError::NotSupported.into())
|
||||
}
|
||||
}
|
||||
|
||||
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
||||
impl CtrlFanCurveZbus {
|
||||
/// Set all fan curves for a profile to enabled status. Will also activate a
|
||||
/// fan curve if in the same profile mode
|
||||
async fn set_fan_curves_enabled(
|
||||
&mut self,
|
||||
profile: ThrottlePolicy,
|
||||
enabled: bool,
|
||||
) -> zbus::fdo::Result<()> {
|
||||
self.config
|
||||
.lock()
|
||||
.await
|
||||
.profiles
|
||||
.set_profile_curves_enabled(profile, enabled);
|
||||
self.config
|
||||
.lock()
|
||||
.await
|
||||
.profiles
|
||||
.write_profile_curve_to_platform(profile, &mut find_fan_curve_node()?)?;
|
||||
self.config.lock().await.write();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Set a single fan curve for a profile to enabled status. Will also
|
||||
/// activate a fan curve if in the same profile mode
|
||||
async fn set_profile_fan_curve_enabled(
|
||||
&mut self,
|
||||
profile: ThrottlePolicy,
|
||||
fan: FanCurvePU,
|
||||
enabled: bool,
|
||||
) -> zbus::fdo::Result<()> {
|
||||
self.config
|
||||
.lock()
|
||||
.await
|
||||
.profiles
|
||||
.set_profile_fan_curve_enabled(profile, fan, enabled);
|
||||
self.config
|
||||
.lock()
|
||||
.await
|
||||
.profiles
|
||||
.write_profile_curve_to_platform(profile, &mut find_fan_curve_node()?)?;
|
||||
self.config.lock().await.write();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get the fan-curve data for the currently active ThrottlePolicy
|
||||
async fn fan_curve_data(
|
||||
&mut self,
|
||||
profile: ThrottlePolicy,
|
||||
) -> zbus::fdo::Result<Vec<CurveData>> {
|
||||
let curve = self
|
||||
.config
|
||||
.lock()
|
||||
.await
|
||||
.profiles
|
||||
.get_fan_curves_for(profile)
|
||||
.to_vec();
|
||||
Ok(curve)
|
||||
}
|
||||
|
||||
/// Set the fan curve for the specified profile.
|
||||
/// Will also activate the fan curve if the user is in the same mode.
|
||||
async fn set_fan_curve(
|
||||
&mut self,
|
||||
profile: ThrottlePolicy,
|
||||
curve: CurveData,
|
||||
) -> zbus::fdo::Result<()> {
|
||||
self.config
|
||||
.lock()
|
||||
.await
|
||||
.profiles
|
||||
.save_fan_curve(curve, profile)?;
|
||||
self.config
|
||||
.lock()
|
||||
.await
|
||||
.profiles
|
||||
.write_profile_curve_to_platform(profile, &mut find_fan_curve_node()?)?;
|
||||
self.config.lock().await.write();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Reset the stored (self) and device curve to the defaults of the
|
||||
/// platform.
|
||||
///
|
||||
/// Each platform_profile has a different default and the defualt can be
|
||||
/// read only for the currently active profile.
|
||||
async fn set_active_curve_to_defaults(&mut self) -> zbus::fdo::Result<()> {
|
||||
let active = self.platform.get_throttle_thermal_policy()?;
|
||||
self.config
|
||||
.lock()
|
||||
.await
|
||||
.profiles
|
||||
.set_active_curve_to_defaults(active.into(), &mut find_fan_curve_node()?)?;
|
||||
self.config.lock().await.write();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Reset the stored (self) and device curve to the defaults of the
|
||||
/// platform.
|
||||
///
|
||||
/// Each platform_profile has a different default and the defualt can be
|
||||
/// read only for the currently active profile.
|
||||
async fn reset_profile_curves(&self, profile: ThrottlePolicy) -> zbus::fdo::Result<()> {
|
||||
let active = self.platform.get_throttle_thermal_policy()?;
|
||||
|
||||
self.platform.set_throttle_thermal_policy(profile.into())?;
|
||||
self.config
|
||||
.lock()
|
||||
.await
|
||||
.profiles
|
||||
.set_active_curve_to_defaults(active.into(), &mut find_fan_curve_node()?)?;
|
||||
self.platform.set_throttle_thermal_policy(active)?;
|
||||
|
||||
self.config.lock().await.write();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::ZbusRun for CtrlFanCurveZbus {
|
||||
async fn add_to_server(self, server: &mut Connection) {
|
||||
Self::add_to_server_helper(self, FAN_CURVE_ZBUS_PATH, server).await;
|
||||
}
|
||||
}
|
||||
|
||||
impl CtrlTask for CtrlFanCurveZbus {
|
||||
fn zbus_path() -> &'static str {
|
||||
FAN_CURVE_ZBUS_PATH
|
||||
}
|
||||
|
||||
async fn create_tasks(&self, _signal_ctxt: SignalContext<'static>) -> Result<(), RogError> {
|
||||
let watch_throttle_thermal_policy = self.platform.monitor_throttle_thermal_policy()?;
|
||||
let platform = self.platform.clone();
|
||||
let config = self.config.clone();
|
||||
let fan_curves = self.config.clone();
|
||||
|
||||
tokio::spawn(async move {
|
||||
let mut buffer = [0; 32];
|
||||
if let Ok(mut stream) = watch_throttle_thermal_policy.into_event_stream(&mut buffer) {
|
||||
while (stream.next().await).is_some() {
|
||||
debug!("watch_throttle_thermal_policy changed");
|
||||
if let Ok(profile) = platform.get_throttle_thermal_policy().map_err(|e| {
|
||||
error!("{MOD_NAME}: get_throttle_thermal_policy error: {e}");
|
||||
}) {
|
||||
if profile != config.lock().await.current {
|
||||
fan_curves
|
||||
.lock()
|
||||
.await
|
||||
.profiles
|
||||
.write_profile_curve_to_platform(
|
||||
profile.into(),
|
||||
&mut find_fan_curve_node().unwrap(),
|
||||
)
|
||||
.map_err(|e| {
|
||||
warn!("{MOD_NAME}: write_profile_curve_to_platform, {}", e)
|
||||
})
|
||||
.ok();
|
||||
config.lock().await.current = profile;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::Reloadable for CtrlFanCurveZbus {
|
||||
/// Fetch the active profile and use that to set all related components up
|
||||
async fn reload(&mut self) -> Result<(), RogError> {
|
||||
let active = self.platform.get_throttle_thermal_policy()?.into();
|
||||
if let Ok(mut device) = find_fan_curve_node() {
|
||||
// There is a possibility that the curve was default zeroed, so this call
|
||||
// initialises the data from system read and we need to save it
|
||||
// after
|
||||
loop {
|
||||
if let Ok(mut config) = self.config.try_lock() {
|
||||
config
|
||||
.profiles
|
||||
.write_profile_curve_to_platform(active, &mut device)?;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,287 +0,0 @@
|
||||
use std::process::Command;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use config_traits::StdConfig;
|
||||
use log::{error, info, warn};
|
||||
use rog_platform::power::AsusPower;
|
||||
use rog_platform::supported::ChargeSupportedFunctions;
|
||||
use systemd_zbus::{ManagerProxy as SystemdProxy, Mode, UnitFileState};
|
||||
use tokio::time::sleep;
|
||||
use zbus::export::futures_util::lock::Mutex;
|
||||
use zbus::{dbus_interface, Connection, SignalContext};
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::error::RogError;
|
||||
use crate::{CtrlTask, GetSupported};
|
||||
|
||||
const ZBUS_PATH: &str = "/org/asuslinux/Power";
|
||||
const NVIDIA_POWERD: &str = "nvidia-powerd.service";
|
||||
|
||||
impl GetSupported for CtrlPower {
|
||||
type A = ChargeSupportedFunctions;
|
||||
|
||||
fn get_supported() -> Self::A {
|
||||
ChargeSupportedFunctions {
|
||||
charge_level_set: if let Ok(power) = AsusPower::new() {
|
||||
power.has_charge_control_end_threshold()
|
||||
} else {
|
||||
false
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct CtrlPower {
|
||||
power: AsusPower,
|
||||
config: Arc<Mutex<Config>>,
|
||||
}
|
||||
|
||||
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
||||
impl CtrlPower {
|
||||
async fn set_charge_control_end_threshold(
|
||||
&mut self,
|
||||
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
||||
limit: u8,
|
||||
) -> zbus::fdo::Result<()> {
|
||||
if !(20..=100).contains(&limit) {
|
||||
return Err(RogError::ChargeLimit(limit))?;
|
||||
}
|
||||
self.set(limit)
|
||||
.map_err(|err| {
|
||||
warn!("CtrlCharge: set_limit {}", err);
|
||||
err
|
||||
})
|
||||
.ok();
|
||||
Self::notify_charge_control_end_threshold(&ctxt, limit)
|
||||
.await
|
||||
.ok();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn charge_control_end_threshold(&self) -> u8 {
|
||||
loop {
|
||||
if let Some(mut config) = self.config.try_lock() {
|
||||
let limit = self
|
||||
.power
|
||||
.get_charge_control_end_threshold()
|
||||
.map_err(|err| {
|
||||
warn!("CtrlCharge: get_charge_control_end_threshold {}", err);
|
||||
err
|
||||
})
|
||||
.unwrap_or(100);
|
||||
|
||||
config.read();
|
||||
config.bat_charge_limit = limit;
|
||||
config.write();
|
||||
|
||||
return config.bat_charge_limit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn mains_online(&self) -> bool {
|
||||
if self.power.has_online() {
|
||||
if let Ok(v) = self.power.get_online() {
|
||||
return v == 1;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
#[dbus_interface(signal)]
|
||||
async fn notify_charge_control_end_threshold(
|
||||
ctxt: &SignalContext<'_>,
|
||||
limit: u8,
|
||||
) -> zbus::Result<()>;
|
||||
|
||||
#[dbus_interface(signal)]
|
||||
async fn notify_mains_online(ctxt: &SignalContext<'_>, on: bool) -> zbus::Result<()>;
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl crate::ZbusRun for CtrlPower {
|
||||
async fn add_to_server(self, server: &mut Connection) {
|
||||
Self::add_to_server_helper(self, ZBUS_PATH, server).await;
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl crate::Reloadable for CtrlPower {
|
||||
async fn reload(&mut self) -> Result<(), RogError> {
|
||||
if let Some(mut config) = self.config.try_lock() {
|
||||
config.read();
|
||||
self.set(config.bat_charge_limit)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl CtrlPower {
|
||||
// task_watch_item!(charge_control_end_threshold power);
|
||||
|
||||
pub fn new(config: Arc<Mutex<Config>>) -> Result<Self, RogError> {
|
||||
Ok(CtrlPower {
|
||||
power: AsusPower::new()?,
|
||||
config,
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn set(&self, limit: u8) -> Result<(), RogError> {
|
||||
if !(20..=100).contains(&limit) {
|
||||
return Err(RogError::ChargeLimit(limit));
|
||||
}
|
||||
|
||||
self.power.set_charge_control_end_threshold(limit)?;
|
||||
|
||||
info!("Battery charge limit: {}", limit);
|
||||
|
||||
if let Some(mut config) = self.config.try_lock() {
|
||||
config.read();
|
||||
config.bat_charge_limit = limit;
|
||||
config.write();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl CtrlTask for CtrlPower {
|
||||
fn zbus_path() -> &'static str {
|
||||
ZBUS_PATH
|
||||
}
|
||||
|
||||
async fn create_tasks(&self, signal_ctxt: SignalContext<'static>) -> Result<(), RogError> {
|
||||
let conn = zbus::Connection::system().await?;
|
||||
let sysd1 = SystemdProxy::new(&conn).await?;
|
||||
let sysd2 = sysd1.clone();
|
||||
let sysd3 = sysd1.clone();
|
||||
|
||||
let power1 = self.clone();
|
||||
let power2 = self.clone();
|
||||
self.create_sys_event_tasks(
|
||||
move || async {},
|
||||
move || {
|
||||
let power = power1.clone();
|
||||
let sysd = sysd1.clone();
|
||||
async move {
|
||||
info!("CtrlCharge reloading charge limit");
|
||||
let lock = power.config.lock().await;
|
||||
power
|
||||
.set(lock.bat_charge_limit)
|
||||
.map_err(|err| {
|
||||
warn!("CtrlCharge: set_limit {}", err);
|
||||
err
|
||||
})
|
||||
.ok();
|
||||
|
||||
if lock.disable_nvidia_powerd_on_battery {
|
||||
if let Ok(value) = power.power.get_online() {
|
||||
do_nvidia_powerd_action(&sysd, value == 1).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
move || async {},
|
||||
move || {
|
||||
let power = power2.clone();
|
||||
let sysd = sysd2.clone();
|
||||
async move {
|
||||
info!("CtrlCharge reloading charge limit");
|
||||
let lock = power.config.lock().await;
|
||||
power
|
||||
.set(lock.bat_charge_limit)
|
||||
.map_err(|err| {
|
||||
warn!("CtrlCharge: set_limit {}", err);
|
||||
err
|
||||
})
|
||||
.ok();
|
||||
|
||||
if lock.disable_nvidia_powerd_on_battery {
|
||||
if let Ok(value) = power.power.get_online() {
|
||||
do_nvidia_powerd_action(&sysd, value == 1).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
.await;
|
||||
|
||||
let config = self.config.clone();
|
||||
// self.watch_charge_control_end_threshold(signal_ctxt.clone())
|
||||
// .await?;
|
||||
|
||||
let ctrl = self.clone();
|
||||
tokio::spawn(async move {
|
||||
let mut online = 10;
|
||||
loop {
|
||||
if let Ok(value) = ctrl.power.get_online() {
|
||||
if online != value {
|
||||
online = value;
|
||||
let mut config = config.lock().await;
|
||||
config.read();
|
||||
|
||||
if config.disable_nvidia_powerd_on_battery {
|
||||
do_nvidia_powerd_action(&sysd3, value == 1).await;
|
||||
}
|
||||
|
||||
Self::notify_mains_online(&signal_ctxt, value == 1)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let mut prog: Vec<&str> = Vec::new();
|
||||
if value == 1 {
|
||||
// AC ONLINE
|
||||
prog = config.ac_command.split_whitespace().collect();
|
||||
} else if value == 0 {
|
||||
// BATTERY
|
||||
prog = config.bat_command.split_whitespace().collect();
|
||||
}
|
||||
|
||||
if prog.len() > 1 {
|
||||
let mut cmd = Command::new(prog[0]);
|
||||
for arg in prog.iter().skip(1) {
|
||||
cmd.arg(*arg);
|
||||
}
|
||||
if let Err(e) = cmd.spawn() {
|
||||
if value == 1 {
|
||||
error!("AC power command error: {e}");
|
||||
} else {
|
||||
error!("Battery power command error: {e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// The inotify doesn't pick up events when the kernel changes internal value
|
||||
// so we need to watch it with a thread and sleep unfortunately
|
||||
sleep(Duration::from_secs(1)).await;
|
||||
}
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
async fn do_nvidia_powerd_action(proxy: &SystemdProxy<'_>, ac_on: bool) {
|
||||
if let Ok(res) = proxy.get_unit_file_state(NVIDIA_POWERD).await {
|
||||
if res == UnitFileState::Enabled {
|
||||
if ac_on {
|
||||
proxy
|
||||
.start_unit(NVIDIA_POWERD, Mode::Replace)
|
||||
.await
|
||||
.map_err(|e| error!("Error stopping {NVIDIA_POWERD}, {e:?}"))
|
||||
.ok();
|
||||
} else {
|
||||
proxy
|
||||
.stop_unit(NVIDIA_POWERD, Mode::Replace)
|
||||
.await
|
||||
.map_err(|e| error!("Error stopping {NVIDIA_POWERD}, {e:?}"))
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use config_traits::{StdConfig, StdConfigLoad};
|
||||
use rog_profiles::fan_curve_set::FanCurveSet;
|
||||
use rog_profiles::Profile;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
|
||||
use crate::CONFIG_PATH_BASE;
|
||||
|
||||
const CONFIG_FILE: &str = "profile.ron";
|
||||
const CONFIG_FAN_FILE: &str = "fan_curves.ron";
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
pub struct ProfileConfig {
|
||||
/// For restore on boot
|
||||
pub active_profile: Profile,
|
||||
}
|
||||
|
||||
impl StdConfig for ProfileConfig {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
active_profile: Profile::Balanced,
|
||||
}
|
||||
}
|
||||
|
||||
fn config_dir() -> std::path::PathBuf {
|
||||
PathBuf::from(CONFIG_PATH_BASE)
|
||||
}
|
||||
|
||||
fn file_name(&self) -> String {
|
||||
CONFIG_FILE.to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
impl StdConfigLoad for ProfileConfig {}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug, Default)]
|
||||
pub struct FanCurveConfig {
|
||||
pub balanced: FanCurveSet,
|
||||
pub performance: FanCurveSet,
|
||||
pub quiet: FanCurveSet,
|
||||
}
|
||||
|
||||
impl StdConfig for FanCurveConfig {
|
||||
/// Create a new config. The defaults are zeroed so the device must be read
|
||||
/// to get the actual device defaults.
|
||||
fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
fn config_dir() -> std::path::PathBuf {
|
||||
PathBuf::from(CONFIG_PATH_BASE)
|
||||
}
|
||||
|
||||
fn file_name(&self) -> String {
|
||||
CONFIG_FAN_FILE.to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
impl StdConfigLoad for FanCurveConfig {}
|
||||
@@ -1,175 +0,0 @@
|
||||
use config_traits::{StdConfig, StdConfigLoad};
|
||||
use log::{info, warn};
|
||||
use rog_platform::platform::AsusPlatform;
|
||||
use rog_platform::supported::PlatformProfileFunctions;
|
||||
use rog_profiles::error::ProfileError;
|
||||
use rog_profiles::{FanCurveProfiles, Profile};
|
||||
|
||||
use super::config::{FanCurveConfig, ProfileConfig};
|
||||
use crate::error::RogError;
|
||||
use crate::GetSupported;
|
||||
|
||||
// TODO: macro wrapper for warn/info/error log macros to add module name
|
||||
const MOD_NAME: &str = "CtrlPlatformProfile";
|
||||
|
||||
pub struct FanCurves {
|
||||
config_file: FanCurveConfig,
|
||||
profiles: FanCurveProfiles,
|
||||
}
|
||||
|
||||
impl FanCurves {
|
||||
pub fn update_profiles_from_config(&mut self) {
|
||||
self.profiles.balanced = self.config_file.balanced.clone();
|
||||
self.profiles.performance = self.config_file.performance.clone();
|
||||
self.profiles.quiet = self.config_file.quiet.clone();
|
||||
}
|
||||
|
||||
pub fn update_config_from_profiles(&mut self) {
|
||||
self.config_file.balanced = self.profiles.balanced.clone();
|
||||
self.config_file.performance = self.profiles.performance.clone();
|
||||
self.config_file.quiet = self.profiles.quiet.clone();
|
||||
}
|
||||
|
||||
pub fn profiles(&self) -> &FanCurveProfiles {
|
||||
&self.profiles
|
||||
}
|
||||
|
||||
pub fn profiles_mut(&mut self) -> &mut FanCurveProfiles {
|
||||
&mut self.profiles
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CtrlPlatformProfile {
|
||||
pub profile_config: ProfileConfig,
|
||||
pub fan_curves: Option<FanCurves>,
|
||||
pub platform: AsusPlatform,
|
||||
}
|
||||
|
||||
impl GetSupported for CtrlPlatformProfile {
|
||||
type A = PlatformProfileFunctions;
|
||||
|
||||
fn get_supported() -> Self::A {
|
||||
if !Profile::is_platform_profile_supported() {
|
||||
warn!(
|
||||
"platform_profile kernel interface not found, your laptop does not support this, \
|
||||
or the interface is missing."
|
||||
);
|
||||
}
|
||||
|
||||
let res = FanCurveProfiles::is_supported();
|
||||
let mut fan_curve_supported = res.is_err();
|
||||
if let Ok(r) = res {
|
||||
fan_curve_supported = r;
|
||||
};
|
||||
|
||||
if !fan_curve_supported {
|
||||
info!(
|
||||
"fan curves kernel interface not found, your laptop does not support this, or the \
|
||||
interface is missing."
|
||||
);
|
||||
}
|
||||
|
||||
PlatformProfileFunctions {
|
||||
platform_profile: Profile::is_platform_profile_supported(),
|
||||
fan_curves: fan_curve_supported,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CtrlPlatformProfile {
|
||||
pub fn new(config: ProfileConfig) -> Result<Self, RogError> {
|
||||
let platform = AsusPlatform::new()?;
|
||||
if platform.has_platform_profile() || platform.has_throttle_thermal_policy() {
|
||||
info!("{MOD_NAME}: Device has profile control available");
|
||||
|
||||
let mut controller = CtrlPlatformProfile {
|
||||
profile_config: config,
|
||||
fan_curves: None,
|
||||
platform,
|
||||
};
|
||||
if FanCurveProfiles::get_device().is_ok() {
|
||||
info!("{MOD_NAME}: Device has fan curves available");
|
||||
let fan_config = FanCurveConfig::new();
|
||||
// Only do defaults if the config doesn't already exist
|
||||
if !fan_config.file_path().exists() {
|
||||
info!("{MOD_NAME}: Fetching default fan curves");
|
||||
controller.fan_curves = Some(FanCurves {
|
||||
config_file: fan_config,
|
||||
profiles: FanCurveProfiles::default(),
|
||||
});
|
||||
for _ in [Profile::Balanced, Profile::Performance, Profile::Quiet] {
|
||||
// For each profile we need to switch to it before we
|
||||
// can read the existing values from hardware. The ACPI method used
|
||||
// for this is what limits us.
|
||||
let next =
|
||||
Profile::get_next_profile(controller.profile_config.active_profile);
|
||||
Profile::set_profile(next)
|
||||
.map_err(|e| warn!("{MOD_NAME}: set_profile, {}", e))
|
||||
.ok();
|
||||
controller.profile_config.active_profile = next;
|
||||
|
||||
// Make sure to set the baseline to default
|
||||
controller.set_active_curve_to_defaults()?;
|
||||
let active = Profile::get_active_profile().unwrap_or(Profile::Balanced);
|
||||
|
||||
if let Some(curves) = controller.fan_curves.as_ref() {
|
||||
info!(
|
||||
"{MOD_NAME}: {active:?}: {}",
|
||||
String::from(curves.profiles().get_fan_curves_for(active))
|
||||
);
|
||||
}
|
||||
}
|
||||
if let Some(curves) = controller.fan_curves.as_ref() {
|
||||
curves.config_file.write();
|
||||
}
|
||||
} else {
|
||||
info!("{MOD_NAME}: Fan curves previously stored, loading...");
|
||||
let mut fan_curves = FanCurves {
|
||||
config_file: fan_config.load(),
|
||||
profiles: FanCurveProfiles::default(),
|
||||
};
|
||||
fan_curves.update_profiles_from_config();
|
||||
controller.fan_curves = Some(fan_curves);
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(controller);
|
||||
}
|
||||
|
||||
Err(ProfileError::NotSupported.into())
|
||||
}
|
||||
|
||||
pub fn save_config(&mut self) {
|
||||
self.profile_config.write();
|
||||
if let Some(fans) = self.fan_curves.as_mut() {
|
||||
fans.update_config_from_profiles();
|
||||
fans.config_file.write(); // config write
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the curve for the active profile active
|
||||
pub(super) fn write_profile_curve_to_platform(&mut self) -> Result<(), RogError> {
|
||||
if let Some(curves) = &mut self.fan_curves {
|
||||
if let Ok(mut device) = FanCurveProfiles::get_device() {
|
||||
curves.profiles_mut().write_profile_curve_to_platform(
|
||||
self.profile_config.active_profile,
|
||||
&mut device,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(super) fn set_active_curve_to_defaults(&mut self) -> Result<(), RogError> {
|
||||
if let Some(curves) = self.fan_curves.as_mut() {
|
||||
if let Ok(mut device) = FanCurveProfiles::get_device() {
|
||||
curves.profiles_mut().set_active_curve_to_defaults(
|
||||
self.profile_config.active_profile,
|
||||
&mut device,
|
||||
)?;
|
||||
curves.update_config_from_profiles();
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
pub mod config;
|
||||
pub mod controller;
|
||||
/// Implements `CtrlTask`, Reloadable, `ZbusRun`
|
||||
pub mod trait_impls;
|
||||
@@ -1,316 +0,0 @@
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use config_traits::StdConfig;
|
||||
use log::{error, info, warn};
|
||||
use rog_profiles::fan_curve_set::{CurveData, FanCurveSet};
|
||||
use rog_profiles::{FanCurveProfiles, Profile};
|
||||
use zbus::export::futures_util::lock::Mutex;
|
||||
use zbus::export::futures_util::StreamExt;
|
||||
use zbus::fdo::Error;
|
||||
use zbus::{dbus_interface, Connection, SignalContext};
|
||||
|
||||
use super::controller::CtrlPlatformProfile;
|
||||
use crate::error::RogError;
|
||||
use crate::CtrlTask;
|
||||
|
||||
const MOD_NAME: &str = "ProfileZbus";
|
||||
|
||||
const ZBUS_PATH: &str = "/org/asuslinux/Profile";
|
||||
const UNSUPPORTED_MSG: &str =
|
||||
"Fan curves are not supported on this laptop or you require a patched kernel";
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ProfileZbus(pub Arc<Mutex<CtrlPlatformProfile>>);
|
||||
|
||||
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
||||
impl ProfileZbus {
|
||||
/// Fetch profile names
|
||||
fn profiles(&mut self) -> zbus::fdo::Result<Vec<Profile>> {
|
||||
if let Ok(profiles) = Profile::get_profile_names() {
|
||||
return Ok(profiles);
|
||||
}
|
||||
Err(Error::Failed(
|
||||
"Failed to get all profile details".to_owned(),
|
||||
))
|
||||
}
|
||||
|
||||
/// Toggle to next platform_profile. Names provided by `Profiles`.
|
||||
/// If fan-curves are supported will also activate a fan curve for profile.
|
||||
async fn next_profile(&mut self, #[zbus(signal_context)] ctxt: SignalContext<'_>) {
|
||||
let mut ctrl = self.0.lock().await;
|
||||
let next = Profile::get_next_profile(ctrl.profile_config.active_profile);
|
||||
Profile::set_profile(next)
|
||||
.map_err(|e| warn!("{MOD_NAME}: set_profile, {}", e))
|
||||
.ok();
|
||||
ctrl.profile_config.active_profile = next;
|
||||
ctrl.save_config();
|
||||
|
||||
Self::notify_profile(&ctxt, ctrl.profile_config.active_profile)
|
||||
.await
|
||||
.ok();
|
||||
}
|
||||
|
||||
/// Fetch the active profile name
|
||||
async fn active_profile(&mut self) -> zbus::fdo::Result<Profile> {
|
||||
let mut ctrl = self.0.lock().await;
|
||||
ctrl.profile_config.read();
|
||||
Ok(ctrl.profile_config.active_profile)
|
||||
}
|
||||
|
||||
/// Set this platform_profile name as active
|
||||
async fn set_active_profile(
|
||||
&self,
|
||||
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
||||
profile: Profile,
|
||||
) {
|
||||
let mut ctrl = self.0.lock().await;
|
||||
// Read first just incase the user has modified the config before calling this
|
||||
ctrl.profile_config.read();
|
||||
Profile::set_profile(profile)
|
||||
.map_err(|e| warn!("{MOD_NAME}: set_profile, {}", e))
|
||||
.ok();
|
||||
ctrl.profile_config.active_profile = profile;
|
||||
ctrl.write_profile_curve_to_platform()
|
||||
.map_err(|e| warn!("{MOD_NAME}: write_profile_curve_to_platform, {}", e))
|
||||
.ok();
|
||||
|
||||
ctrl.save_config();
|
||||
|
||||
Self::notify_profile(&ctxt, ctrl.profile_config.active_profile)
|
||||
.await
|
||||
.ok();
|
||||
}
|
||||
|
||||
/// Get a list of profiles that have fan-curves enabled.
|
||||
async fn enabled_fan_profiles(&mut self) -> zbus::fdo::Result<Vec<Profile>> {
|
||||
let mut ctrl = self.0.lock().await;
|
||||
ctrl.profile_config.read();
|
||||
if let Some(curves) = &mut ctrl.fan_curves {
|
||||
return Ok(curves.profiles().get_enabled_curve_profiles());
|
||||
}
|
||||
Err(Error::Failed(UNSUPPORTED_MSG.to_owned()))
|
||||
}
|
||||
|
||||
/// Set a profile fan curve enabled status. Will also activate a fan curve
|
||||
/// if in the same profile mode
|
||||
async fn set_fan_curve_enabled(
|
||||
&mut self,
|
||||
profile: Profile,
|
||||
enabled: bool,
|
||||
) -> zbus::fdo::Result<()> {
|
||||
let mut ctrl = self.0.lock().await;
|
||||
ctrl.profile_config.read();
|
||||
if let Some(curves) = &mut ctrl.fan_curves {
|
||||
curves
|
||||
.profiles_mut()
|
||||
.set_profile_curve_enabled(profile, enabled);
|
||||
|
||||
ctrl.write_profile_curve_to_platform()
|
||||
.map_err(|e| warn!("{MOD_NAME}: write_profile_curve_to_platform, {}", e))
|
||||
.ok();
|
||||
|
||||
ctrl.save_config();
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::Failed(UNSUPPORTED_MSG.to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the fan-curve data for the currently active Profile
|
||||
async fn fan_curve_data(&mut self, profile: Profile) -> zbus::fdo::Result<FanCurveSet> {
|
||||
let mut ctrl = self.0.lock().await;
|
||||
ctrl.profile_config.read();
|
||||
if let Some(curves) = &mut ctrl.fan_curves {
|
||||
let curve = curves.profiles().get_fan_curves_for(profile);
|
||||
return Ok(curve.clone());
|
||||
}
|
||||
Err(Error::Failed(UNSUPPORTED_MSG.to_owned()))
|
||||
}
|
||||
|
||||
/// Set the fan curve for the specified profile.
|
||||
/// Will also activate the fan curve if the user is in the same mode.
|
||||
async fn set_fan_curve(&self, profile: Profile, curve: CurveData) -> zbus::fdo::Result<()> {
|
||||
let mut ctrl = self.0.lock().await;
|
||||
ctrl.profile_config.read();
|
||||
if let Some(curves) = &mut ctrl.fan_curves {
|
||||
curves
|
||||
.profiles_mut()
|
||||
.save_fan_curve(curve, profile)
|
||||
.map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?;
|
||||
} else {
|
||||
return Err(Error::Failed(UNSUPPORTED_MSG.to_owned()));
|
||||
}
|
||||
ctrl.write_profile_curve_to_platform()
|
||||
.map_err(|e| warn!("{MOD_NAME}: Profile::set_profile, {}", e))
|
||||
.ok();
|
||||
ctrl.save_config();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Reset the stored (self) and device curve to the defaults of the
|
||||
/// platform.
|
||||
///
|
||||
/// Each platform_profile has a different default and the defualt can be
|
||||
/// read only for the currently active profile.
|
||||
async fn set_active_curve_to_defaults(&self) -> zbus::fdo::Result<()> {
|
||||
let mut ctrl = self.0.lock().await;
|
||||
ctrl.profile_config.read();
|
||||
ctrl.set_active_curve_to_defaults()
|
||||
.map_err(|e| warn!("{MOD_NAME}: Profile::set_active_curve_to_defaults, {}", e))
|
||||
.ok();
|
||||
ctrl.save_config();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Reset the stored (self) and device curve to the defaults of the
|
||||
/// platform.
|
||||
///
|
||||
/// Each platform_profile has a different default and the defualt can be
|
||||
/// read only for the currently active profile.
|
||||
async fn reset_profile_curves(&self, profile: Profile) -> zbus::fdo::Result<()> {
|
||||
let mut ctrl = self.0.lock().await;
|
||||
ctrl.profile_config.read();
|
||||
let active = Profile::get_active_profile().unwrap_or(Profile::Balanced);
|
||||
|
||||
Profile::set_profile(profile)
|
||||
.map_err(|e| warn!("{MOD_NAME}: set_profile, {}", e))
|
||||
.ok();
|
||||
ctrl.set_active_curve_to_defaults()
|
||||
.map_err(|e| warn!("{MOD_NAME}: Profile::set_active_curve_to_defaults, {}", e))
|
||||
.ok();
|
||||
|
||||
Profile::set_profile(active)
|
||||
.map_err(|e| warn!("{MOD_NAME}: set_profile, {}", e))
|
||||
.ok();
|
||||
ctrl.save_config();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[dbus_interface(signal)]
|
||||
async fn notify_profile(signal_ctxt: &SignalContext<'_>, profile: Profile) -> zbus::Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl crate::ZbusRun for ProfileZbus {
|
||||
async fn add_to_server(self, server: &mut Connection) {
|
||||
Self::add_to_server_helper(self, ZBUS_PATH, server).await;
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl CtrlTask for ProfileZbus {
|
||||
fn zbus_path() -> &'static str {
|
||||
ZBUS_PATH
|
||||
}
|
||||
|
||||
async fn create_tasks(&self, signal_ctxt: SignalContext<'static>) -> Result<(), RogError> {
|
||||
let ctrl = self.0.clone();
|
||||
let sig_ctx = signal_ctxt.clone();
|
||||
let watch = self
|
||||
.0
|
||||
.lock()
|
||||
.await
|
||||
.platform
|
||||
.monitor_throttle_thermal_policy()?;
|
||||
|
||||
tokio::spawn(async move {
|
||||
let mut buffer = [0; 32];
|
||||
if let Ok(stream) = watch.into_event_stream(&mut buffer) {
|
||||
stream
|
||||
.for_each(|_| async {
|
||||
let mut lock = ctrl.lock().await;
|
||||
if let Ok(profile) =
|
||||
lock.platform.get_throttle_thermal_policy().map_err(|e| {
|
||||
error!("{MOD_NAME}: get_throttle_thermal_policy error: {e}");
|
||||
})
|
||||
{
|
||||
let new_profile = Profile::from_throttle_thermal_policy(profile);
|
||||
if new_profile != lock.profile_config.active_profile {
|
||||
info!("{MOD_NAME}: platform_profile changed to {new_profile}");
|
||||
lock.profile_config.active_profile = new_profile;
|
||||
lock.write_profile_curve_to_platform().unwrap();
|
||||
lock.save_config();
|
||||
Profile::set_profile(lock.profile_config.active_profile)
|
||||
.map_err(|e| {
|
||||
error!("Profile::set_profile() error: {e}");
|
||||
})
|
||||
.ok();
|
||||
|
||||
Self::notify_profile(&sig_ctx, lock.profile_config.active_profile)
|
||||
.await
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
})
|
||||
.await;
|
||||
}
|
||||
});
|
||||
|
||||
let ctrl = self.0.clone();
|
||||
let watch = self.0.lock().await.platform.monitor_platform_profile()?;
|
||||
|
||||
tokio::spawn(async move {
|
||||
let mut buffer = [0; 32];
|
||||
if let Ok(stream) = watch.into_event_stream(&mut buffer) {
|
||||
stream
|
||||
.for_each(|_| async {
|
||||
let mut lock = ctrl.lock().await;
|
||||
if let Ok(profile) = lock.platform.get_platform_profile().map_err(|e| {
|
||||
error!("get_platform_profile error: {e}");
|
||||
}) {
|
||||
if let Ok(new_profile) = Profile::from_str(&profile).map_err(|e| {
|
||||
error!("Profile::from_str(&profile) error: {e}");
|
||||
}) {
|
||||
if new_profile != lock.profile_config.active_profile {
|
||||
info!("{MOD_NAME}: platform_profile changed to {new_profile}");
|
||||
lock.profile_config.active_profile = new_profile;
|
||||
lock.write_profile_curve_to_platform().unwrap();
|
||||
lock.save_config();
|
||||
Profile::set_profile(lock.profile_config.active_profile)
|
||||
.map_err(|e| {
|
||||
error!("Profile::set_profile() error: {e}");
|
||||
})
|
||||
.ok();
|
||||
|
||||
Self::notify_profile(
|
||||
&signal_ctxt,
|
||||
lock.profile_config.active_profile,
|
||||
)
|
||||
.await
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.await;
|
||||
}
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl crate::Reloadable for ProfileZbus {
|
||||
/// Fetch the active profile and use that to set all related components up
|
||||
async fn reload(&mut self) -> Result<(), RogError> {
|
||||
let mut ctrl = self.0.lock().await;
|
||||
let active = ctrl.profile_config.active_profile;
|
||||
if let Some(curves) = &mut ctrl.fan_curves {
|
||||
if let Ok(mut device) = FanCurveProfiles::get_device() {
|
||||
// There is a possibility that the curve was default zeroed, so this call
|
||||
// initialises the data from system read and we need to save it
|
||||
// after
|
||||
curves
|
||||
.profiles_mut()
|
||||
.write_profile_curve_to_platform(active, &mut device)?;
|
||||
ctrl.profile_config.write();
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
use async_trait::async_trait;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use zbus::zvariant::Type;
|
||||
use zbus::{dbus_interface, Connection};
|
||||
|
||||
use crate::ctrl_anime::CtrlAnime;
|
||||
use crate::ctrl_aura::controller::CtrlKbdLed;
|
||||
use crate::ctrl_platform::CtrlPlatform;
|
||||
use crate::ctrl_power::CtrlPower;
|
||||
use crate::ctrl_profiles::controller::CtrlPlatformProfile;
|
||||
use crate::GetSupported;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Type)]
|
||||
pub struct SupportedFunctions(rog_platform::supported::SupportedFunctions);
|
||||
|
||||
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
||||
impl SupportedFunctions {
|
||||
pub fn supported_functions(&self) -> &rog_platform::supported::SupportedFunctions {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl crate::ZbusRun for SupportedFunctions {
|
||||
async fn add_to_server(self, server: &mut Connection) {
|
||||
Self::add_to_server_helper(self, "/org/asuslinux/Supported", server).await;
|
||||
}
|
||||
}
|
||||
|
||||
impl GetSupported for SupportedFunctions {
|
||||
type A = SupportedFunctions;
|
||||
|
||||
fn get_supported() -> Self::A {
|
||||
Self(rog_platform::supported::SupportedFunctions {
|
||||
anime_ctrl: CtrlAnime::get_supported(),
|
||||
keyboard_led: CtrlKbdLed::get_supported(),
|
||||
charge_ctrl: CtrlPower::get_supported(),
|
||||
platform_profile: CtrlPlatformProfile::get_supported(),
|
||||
rog_bios_ctrl: CtrlPlatform::get_supported(),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -11,19 +11,13 @@ use asusd::ctrl_anime::config::AnimeConfig;
|
||||
use asusd::ctrl_anime::trait_impls::CtrlAnimeZbus;
|
||||
use asusd::ctrl_anime::CtrlAnime;
|
||||
use asusd::ctrl_aura::controller::CtrlKbdLed;
|
||||
use asusd::ctrl_aura::trait_impls::CtrlKbdLedZbus;
|
||||
use asusd::ctrl_aura::trait_impls::CtrlAuraZbus;
|
||||
use asusd::ctrl_fancurves::CtrlFanCurveZbus;
|
||||
use asusd::ctrl_platform::CtrlPlatform;
|
||||
use asusd::ctrl_power::CtrlPower;
|
||||
use asusd::ctrl_profiles::config::ProfileConfig;
|
||||
use asusd::ctrl_profiles::controller::CtrlPlatformProfile;
|
||||
use asusd::ctrl_profiles::trait_impls::ProfileZbus;
|
||||
use asusd::ctrl_supported::SupportedFunctions;
|
||||
use asusd::{print_board_info, CtrlTask, GetSupported, Reloadable, ZbusRun};
|
||||
use config_traits::{StdConfig, StdConfigLoad, StdConfigLoad2};
|
||||
use asusd::{print_board_info, CtrlTask, Reloadable, ZbusRun, DBUS_NAME};
|
||||
use config_traits::{StdConfig, StdConfigLoad2, StdConfigLoad3};
|
||||
use log::{error, info, warn};
|
||||
use rog_aura::aura_detection::LaptopLedData;
|
||||
use rog_dbus::DBUS_NAME;
|
||||
use rog_profiles::Profile;
|
||||
use tokio::time::sleep;
|
||||
use zbus::SignalContext;
|
||||
|
||||
@@ -53,7 +47,6 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
info!(" daemon v{}", asusd::VERSION);
|
||||
info!(" rog-anime v{}", rog_anime::VERSION);
|
||||
info!(" rog-aura v{}", rog_aura::VERSION);
|
||||
info!(" rog-dbus v{}", rog_dbus::VERSION);
|
||||
info!(" rog-profiles v{}", rog_profiles::VERSION);
|
||||
info!("rog-platform v{}", rog_platform::VERSION);
|
||||
|
||||
@@ -63,19 +56,34 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
/// The actual main loop for the daemon
|
||||
async fn start_daemon() -> Result<(), Box<dyn Error>> {
|
||||
let supported = SupportedFunctions::get_supported();
|
||||
// let supported = SupportedFunctions::get_supported();
|
||||
print_board_info();
|
||||
println!("{}", supported.supported_functions());
|
||||
// println!("{:?}", supported.supported_functions());
|
||||
|
||||
// Start zbus server
|
||||
let mut connection = Connection::system().await?;
|
||||
|
||||
let config = Config::new().load();
|
||||
let cfg_path = config.file_path();
|
||||
let config = Arc::new(Mutex::new(config));
|
||||
|
||||
supported.add_to_server(&mut connection).await;
|
||||
// supported.add_to_server(&mut connection).await;
|
||||
|
||||
match CtrlPlatform::new(config.clone()) {
|
||||
match CtrlFanCurveZbus::new() {
|
||||
Ok(ctrl) => {
|
||||
let sig_ctx = CtrlFanCurveZbus::signal_context(&connection)?;
|
||||
start_tasks(ctrl, &mut connection, sig_ctx).await?;
|
||||
}
|
||||
Err(err) => {
|
||||
error!("FanCurves: {}", err);
|
||||
}
|
||||
}
|
||||
|
||||
match CtrlPlatform::new(
|
||||
config.clone(),
|
||||
&cfg_path,
|
||||
CtrlPlatform::signal_context(&connection)?,
|
||||
) {
|
||||
Ok(ctrl) => {
|
||||
let sig_ctx = CtrlPlatform::signal_context(&connection)?;
|
||||
start_tasks(ctrl, &mut connection, sig_ctx).await?;
|
||||
@@ -85,32 +93,6 @@ async fn start_daemon() -> Result<(), Box<dyn Error>> {
|
||||
}
|
||||
}
|
||||
|
||||
match CtrlPower::new(config.clone()) {
|
||||
Ok(ctrl) => {
|
||||
let sig_ctx = CtrlPower::signal_context(&connection)?;
|
||||
start_tasks(ctrl, &mut connection, sig_ctx).await?;
|
||||
}
|
||||
Err(err) => {
|
||||
error!("CtrlPower: {}", err);
|
||||
}
|
||||
}
|
||||
|
||||
if Profile::is_platform_profile_supported() {
|
||||
let profile_config = ProfileConfig::new().load();
|
||||
match CtrlPlatformProfile::new(profile_config) {
|
||||
Ok(ctrl) => {
|
||||
let zbus = ProfileZbus(Arc::new(Mutex::new(ctrl)));
|
||||
let sig_ctx = ProfileZbus::signal_context(&connection)?;
|
||||
start_tasks(zbus, &mut connection, sig_ctx).await?;
|
||||
}
|
||||
Err(err) => {
|
||||
error!("Profile control: {}", err);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
warn!("platform_profile support not found");
|
||||
}
|
||||
|
||||
match CtrlAnime::new(AnimeConfig::new().load()) {
|
||||
Ok(ctrl) => {
|
||||
let zbus = CtrlAnimeZbus(Arc::new(Mutex::new(ctrl)));
|
||||
@@ -127,8 +109,8 @@ async fn start_daemon() -> Result<(), Box<dyn Error>> {
|
||||
// detection first
|
||||
match CtrlKbdLed::new(laptop) {
|
||||
Ok(ctrl) => {
|
||||
let zbus = CtrlKbdLedZbus(Arc::new(Mutex::new(ctrl)));
|
||||
let sig_ctx = CtrlKbdLedZbus::signal_context(&connection)?;
|
||||
let zbus = CtrlAuraZbus(Arc::new(Mutex::new(ctrl)));
|
||||
let sig_ctx = CtrlAuraZbus::signal_context(&connection)?;
|
||||
start_tasks(zbus, &mut connection, sig_ctx).await?;
|
||||
}
|
||||
Err(err) => {
|
||||
|
||||
234
asusd/src/lib.rs
234
asusd/src/lib.rs
@@ -5,30 +5,30 @@ pub mod config;
|
||||
pub mod ctrl_anime;
|
||||
/// Keyboard LED brightness control, RGB, and LED display modes
|
||||
pub mod ctrl_aura;
|
||||
/// Control platform profiles + fan-curves if available
|
||||
pub mod ctrl_fancurves;
|
||||
/// Control ASUS bios function such as boot sound, Optimus/Dedicated gfx mode
|
||||
pub mod ctrl_platform;
|
||||
/// Control of battery charge level
|
||||
pub mod ctrl_power;
|
||||
/// Control platform profiles + fan-curves if available
|
||||
pub mod ctrl_profiles;
|
||||
|
||||
/// Fetch all supported functions for the laptop
|
||||
pub mod ctrl_supported;
|
||||
|
||||
pub mod error;
|
||||
|
||||
use std::future::Future;
|
||||
use std::time::Duration;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use dmi_id::DMIID;
|
||||
use futures_lite::stream::StreamExt;
|
||||
use log::{debug, info, warn};
|
||||
use logind_zbus::manager::ManagerProxy;
|
||||
use zbus::export::futures_util::StreamExt;
|
||||
use tokio::time::sleep;
|
||||
use zbus::zvariant::ObjectPath;
|
||||
use zbus::{Connection, SignalContext};
|
||||
use zbus::{CacheProperties, Connection, SignalContext};
|
||||
|
||||
use crate::error::RogError;
|
||||
|
||||
const CONFIG_PATH_BASE: &str = "/etc/asusd/";
|
||||
pub static DBUS_NAME: &str = "org.asuslinux.Daemon";
|
||||
pub static DBUS_PATH: &str = "/org/asuslinux/Daemon";
|
||||
pub static DBUS_IFACE: &str = "org.asuslinux.Daemon";
|
||||
|
||||
/// This macro adds a function which spawns an `inotify` task on the passed in
|
||||
/// `Executor`.
|
||||
@@ -46,7 +46,7 @@ const CONFIG_PATH_BASE: &str = "/etc/asusd/";
|
||||
/// # Example
|
||||
///
|
||||
/// ```ignore
|
||||
/// impl CtrlRogBios {
|
||||
/// impl RogPlatform {
|
||||
/// task_watch_item!(panel_od platform);
|
||||
/// task_watch_item!(gpu_mux_mode platform);
|
||||
/// }
|
||||
@@ -69,9 +69,45 @@ macro_rules! task_watch_item {
|
||||
tokio::spawn(async move {
|
||||
let mut buffer = [0; 32];
|
||||
watch.into_event_stream(&mut buffer).unwrap().for_each(|_| async {
|
||||
let value = ctrl.$name();
|
||||
concat_idents::concat_idents!(notif_fn = notify_, $name {
|
||||
Self::notif_fn(&signal_ctxt, value).await.ok();
|
||||
if let Ok(value) = ctrl.$name() { // get new value from zbus method
|
||||
concat_idents::concat_idents!(notif_fn = $name, _changed {
|
||||
ctrl.notif_fn(&signal_ctxt).await.ok();
|
||||
});
|
||||
let mut lock = ctrl.config.lock().await;
|
||||
lock.$name = value;
|
||||
lock.write();
|
||||
}
|
||||
}).await;
|
||||
});
|
||||
}
|
||||
Err(e) => info!("inotify watch failed: {}. You can ignore this if your device does not support the feature", e),
|
||||
}
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! task_watch_item_notify {
|
||||
($name:ident $self_inner:ident) => {
|
||||
concat_idents::concat_idents!(fn_name = watch_, $name {
|
||||
async fn fn_name(
|
||||
&self,
|
||||
signal_ctxt: SignalContext<'static>,
|
||||
) -> Result<(), RogError> {
|
||||
use zbus::export::futures_util::StreamExt;
|
||||
|
||||
let ctrl = self.clone();
|
||||
concat_idents::concat_idents!(watch_fn = monitor_, $name {
|
||||
match self.$self_inner.watch_fn() {
|
||||
Ok(watch) => {
|
||||
tokio::spawn(async move {
|
||||
let mut buffer = [0; 32];
|
||||
watch.into_event_stream(&mut buffer).unwrap().for_each(|_| async {
|
||||
concat_idents::concat_idents!(notif_fn = $name, _changed {
|
||||
ctrl.notif_fn(&signal_ctxt).await.ok();
|
||||
});
|
||||
}).await;
|
||||
});
|
||||
@@ -88,42 +124,49 @@ macro_rules! task_watch_item {
|
||||
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
pub fn print_board_info() {
|
||||
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");
|
||||
|
||||
info!("Product family: {}", prod_family.trim());
|
||||
info!("Board name: {}", board_name.trim());
|
||||
let dmi = DMIID::new().unwrap_or_default();
|
||||
info!("Product family: {}", dmi.product_family);
|
||||
info!("Board name: {}", dmi.board_name);
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub trait Reloadable {
|
||||
async fn reload(&mut self) -> Result<(), RogError>;
|
||||
fn reload(&mut self) -> impl std::future::Future<Output = Result<(), RogError>> + Send;
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub trait ZbusRun {
|
||||
async fn add_to_server(self, server: &mut Connection);
|
||||
pub trait ReloadAndNotify {
|
||||
type Data: Send;
|
||||
|
||||
async fn add_to_server_helper(
|
||||
fn reload_and_notify(
|
||||
&mut self,
|
||||
signal_context: &SignalContext<'static>,
|
||||
data: Self::Data,
|
||||
) -> impl std::future::Future<Output = Result<(), RogError>> + Send;
|
||||
}
|
||||
|
||||
pub trait ZbusRun {
|
||||
fn add_to_server(self, server: &mut Connection)
|
||||
-> impl std::future::Future<Output = ()> + Send;
|
||||
|
||||
fn add_to_server_helper(
|
||||
iface: impl zbus::Interface,
|
||||
path: &str,
|
||||
server: &mut Connection,
|
||||
) {
|
||||
server
|
||||
.object_server()
|
||||
.at(&ObjectPath::from_str_unchecked(path), iface)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
warn!("{}: add_to_server {}", path, err);
|
||||
err
|
||||
})
|
||||
.ok();
|
||||
) -> impl std::future::Future<Output = ()> + Send {
|
||||
async move {
|
||||
server
|
||||
.object_server()
|
||||
.at(&ObjectPath::from_str_unchecked(path), iface)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
warn!("{}: add_to_server {}", path, err);
|
||||
err
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Set up a task to run on the async executor
|
||||
#[async_trait]
|
||||
pub trait CtrlTask {
|
||||
fn zbus_path() -> &'static str;
|
||||
|
||||
@@ -134,7 +177,10 @@ pub trait CtrlTask {
|
||||
/// Implement to set up various tasks that may be required, using the
|
||||
/// `Executor`. No blocking loops are allowed, or they must be run on a
|
||||
/// separate thread.
|
||||
async fn create_tasks(&self, signal: SignalContext<'static>) -> Result<(), RogError>;
|
||||
fn create_tasks(
|
||||
&self,
|
||||
signal: SignalContext<'static>,
|
||||
) -> impl std::future::Future<Output = Result<(), RogError>> + Send;
|
||||
|
||||
// /// Create a timed repeating task
|
||||
// async fn repeating_task(&self, millis: u64, mut task: impl FnMut() + Send +
|
||||
@@ -152,7 +198,7 @@ pub trait CtrlTask {
|
||||
///
|
||||
/// The closures can potentially block, so execution time should be the
|
||||
/// minimal possible such as save a variable.
|
||||
async fn create_sys_event_tasks<
|
||||
fn create_sys_event_tasks<
|
||||
Fut1,
|
||||
Fut2,
|
||||
Fut3,
|
||||
@@ -163,63 +209,87 @@ pub trait CtrlTask {
|
||||
F4: Send + 'static,
|
||||
>(
|
||||
&self,
|
||||
mut on_sleep: F1,
|
||||
mut on_wake: F2,
|
||||
mut on_shutdown: F3,
|
||||
mut on_boot: F4,
|
||||
) where
|
||||
F1: FnMut() -> Fut1,
|
||||
F2: FnMut() -> Fut2,
|
||||
F3: FnMut() -> Fut3,
|
||||
F4: FnMut() -> Fut4,
|
||||
mut on_prepare_for_sleep: F1,
|
||||
mut on_prepare_for_shutdown: F2,
|
||||
mut on_lid_change: F3,
|
||||
mut on_external_power_change: F4,
|
||||
) -> impl std::future::Future<Output = ()> + Send
|
||||
where
|
||||
F1: FnMut(bool) -> Fut1,
|
||||
F2: FnMut(bool) -> Fut2,
|
||||
F3: FnMut(bool) -> Fut3,
|
||||
F4: FnMut(bool) -> Fut4,
|
||||
Fut1: Future<Output = ()> + Send,
|
||||
Fut2: Future<Output = ()> + Send,
|
||||
Fut3: Future<Output = ()> + Send,
|
||||
Fut4: Future<Output = ()> + Send,
|
||||
{
|
||||
let connection = Connection::system()
|
||||
.await
|
||||
.expect("Controller could not create dbus connection");
|
||||
async {
|
||||
let connection = Connection::system()
|
||||
.await
|
||||
.expect("Controller could not create dbus connection");
|
||||
|
||||
let manager = ManagerProxy::new(&connection)
|
||||
.await
|
||||
.expect("Controller could not create ManagerProxy");
|
||||
let manager = ManagerProxy::builder(&connection)
|
||||
.cache_properties(CacheProperties::No)
|
||||
.build()
|
||||
.await
|
||||
.expect("Controller could not create ManagerProxy");
|
||||
|
||||
tokio::spawn(async move {
|
||||
if let Ok(mut notif) = manager.receive_prepare_for_sleep().await {
|
||||
while let Some(event) = notif.next().await {
|
||||
if let Ok(args) = event.args() {
|
||||
if args.start {
|
||||
debug!("Doing on_sleep()");
|
||||
on_sleep().await;
|
||||
} else if !args.start() {
|
||||
debug!("Doing on_wake()");
|
||||
on_wake().await;
|
||||
let manager1 = manager.clone();
|
||||
tokio::spawn(async move {
|
||||
if let Ok(mut notif) = manager1.receive_prepare_for_shutdown().await {
|
||||
while let Some(event) = notif.next().await {
|
||||
// blocks thread :|
|
||||
if let Ok(args) = event.args() {
|
||||
debug!("Doing on_prepare_for_shutdown({})", args.start);
|
||||
on_prepare_for_shutdown(args.start).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
let manager = ManagerProxy::new(&connection)
|
||||
.await
|
||||
.expect("Controller could not create ManagerProxy");
|
||||
|
||||
tokio::spawn(async move {
|
||||
if let Ok(mut notif) = manager.receive_prepare_for_shutdown().await {
|
||||
while let Some(event) = notif.next().await {
|
||||
if let Ok(args) = event.args() {
|
||||
if args.start {
|
||||
debug!("Doing on_shutdown()");
|
||||
on_shutdown().await;
|
||||
} else if !args.start() {
|
||||
debug!("Doing on_boot()");
|
||||
on_boot().await;
|
||||
let manager2 = manager.clone();
|
||||
tokio::spawn(async move {
|
||||
if let Ok(mut notif) = manager2.receive_prepare_for_sleep().await {
|
||||
while let Some(event) = notif.next().await {
|
||||
// blocks thread :|
|
||||
if let Ok(args) = event.args() {
|
||||
debug!("Doing on_prepare_for_sleep({})", args.start);
|
||||
on_prepare_for_sleep(args.start).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
let manager3 = manager.clone();
|
||||
tokio::spawn(async move {
|
||||
let mut last_power = manager3.on_external_power().await.unwrap_or_default();
|
||||
|
||||
loop {
|
||||
if let Ok(next) = manager3.on_external_power().await {
|
||||
if next != last_power {
|
||||
last_power = next;
|
||||
on_external_power_change(next).await;
|
||||
}
|
||||
}
|
||||
sleep(Duration::from_secs(2)).await;
|
||||
}
|
||||
});
|
||||
|
||||
tokio::spawn(async move {
|
||||
let mut last_lid = manager.lid_closed().await.unwrap_or_default();
|
||||
// need to loop on these as they don't emit signals
|
||||
loop {
|
||||
if let Ok(next) = manager.lid_closed().await {
|
||||
if next != last_lid {
|
||||
last_lid = next;
|
||||
on_lid_change(next).await;
|
||||
}
|
||||
}
|
||||
sleep(Duration::from_secs(2)).await;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
57
bindings/dbus-xml/org-asuslinux-anime-4.xml
Normal file
57
bindings/dbus-xml/org-asuslinux-anime-4.xml
Normal file
@@ -0,0 +1,57 @@
|
||||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
<node>
|
||||
<interface name="org.asuslinux.Daemon">
|
||||
<!--
|
||||
Writes a data stream of length. Will force system thread to exit until
|
||||
it is restarted
|
||||
-->
|
||||
<method name="Write">
|
||||
<arg name="input" type="(ays)" direction="in"/>
|
||||
</method>
|
||||
<!--
|
||||
The main loop is the base system set action if the user isn't running
|
||||
the user daemon
|
||||
-->
|
||||
<method name="RunMainLoop">
|
||||
<arg name="start" type="b" direction="in"/>
|
||||
</method>
|
||||
<!--
|
||||
Get the device state as stored by asusd
|
||||
-->
|
||||
<method name="DeviceState">
|
||||
<arg type="(bub(ssss)bbbu)" direction="out"/>
|
||||
</method>
|
||||
<!--
|
||||
Set base brightness level
|
||||
-->
|
||||
<!--
|
||||
Set base brightness level
|
||||
-->
|
||||
<property name="Brightness" type="u" access="readwrite"/>
|
||||
<!--
|
||||
Set which builtin animation is used for each stage
|
||||
-->
|
||||
<property name="BuiltinAnimations" type="(ssss)" access="readwrite"/>
|
||||
<!--
|
||||
Enable the builtin animations or not. This is quivalent to "Powersave
|
||||
animations" in Armory crate
|
||||
-->
|
||||
<property name="BuiltinsEnabled" type="b" access="readwrite"/>
|
||||
<!--
|
||||
Set whether the AniMe is enabled at all
|
||||
-->
|
||||
<property name="EnableDisplay" type="b" access="readwrite"/>
|
||||
<!--
|
||||
Set if to turn the AniMe Matrix off when the lid is closed
|
||||
-->
|
||||
<property name="OffWhenLidClosed" type="b" access="readwrite"/>
|
||||
<!--
|
||||
Set if to turn the AniMe Matrix off when the laptop is suspended
|
||||
-->
|
||||
<property name="OffWhenSuspended" type="b" access="readwrite"/>
|
||||
<!--
|
||||
Set if to turn the AniMe Matrix off when external power is unplugged
|
||||
-->
|
||||
<property name="OffWhenUnplugged" type="b" access="readwrite"/>
|
||||
</interface>
|
||||
</node>
|
||||
67
bindings/dbus-xml/org-asuslinux-aura-4.xml
Normal file
67
bindings/dbus-xml/org-asuslinux-aura-4.xml
Normal file
@@ -0,0 +1,67 @@
|
||||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
<node>
|
||||
<interface name="org.asuslinux.Daemon">
|
||||
<!--
|
||||
Get the data set for every mode available
|
||||
-->
|
||||
<method name="AllModeData">
|
||||
<arg type="a{u(uu(yyy)(yyy)ss)}" direction="out"/>
|
||||
</method>
|
||||
<!--
|
||||
On machine that have some form of either per-key keyboard or per-zone
|
||||
this can be used to write custom effects over dbus. The input is a
|
||||
nested `Vec<Vec<8>>` where `Vec<u8>` is a raw USB packet
|
||||
-->
|
||||
<method name="DirectAddressingRaw">
|
||||
<arg name="data" type="aay" direction="in"/>
|
||||
</method>
|
||||
<!--
|
||||
Return the current LED brightness
|
||||
-->
|
||||
<!--
|
||||
Set the keyboard brightness level (0-3)
|
||||
-->
|
||||
<property name="Brightness" type="u" access="readwrite"/>
|
||||
<!--
|
||||
Return the device type for this Aura keyboard
|
||||
-->
|
||||
<property name="DeviceType" type="s" access="read"/>
|
||||
<!--
|
||||
The current mode data
|
||||
-->
|
||||
<!--
|
||||
Set an Aura effect if the effect mode or zone is supported.
|
||||
|
||||
On success the aura config file is read to refresh cached values, then
|
||||
the effect is stored and config written to disk.
|
||||
-->
|
||||
<property name="LedMode" type="u" access="readwrite"/>
|
||||
<!--
|
||||
The current mode data
|
||||
-->
|
||||
<!--
|
||||
Set an Aura effect if the effect mode or zone is supported.
|
||||
|
||||
On success the aura config file is read to refresh cached values, then
|
||||
the effect is stored and config written to disk.
|
||||
-->
|
||||
<property name="LedModeData" type="(uu(yyy)(yyy)ss)" access="readwrite"/>
|
||||
<!--
|
||||
Set a variety of states, input is array of enum.
|
||||
`enabled` sets if the sent array should be disabled or enabled
|
||||
|
||||
For Modern ROG devices the "enabled" flag is ignored.
|
||||
-->
|
||||
<property name="LedPower" type="(ayay((ubbbb)(ubbbb)(ubbbb)(ubbbb)(ubbbb)))" access="readwrite"/>
|
||||
<!--
|
||||
The total available modes
|
||||
-->
|
||||
<property name="SupportedBasicModes" type="au" access="read"/>
|
||||
<property name="SupportedBasicZones" type="au" access="read"/>
|
||||
<!--
|
||||
Total levels of brightness available
|
||||
-->
|
||||
<property name="SupportedBrightness" type="au" access="read"/>
|
||||
<property name="SupportedPowerZones" type="au" access="read"/>
|
||||
</interface>
|
||||
</node>
|
||||
56
bindings/dbus-xml/org-asuslinux-fan-curves-4.xml
Normal file
56
bindings/dbus-xml/org-asuslinux-fan-curves-4.xml
Normal file
@@ -0,0 +1,56 @@
|
||||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
<node>
|
||||
<interface name="org.asuslinux.Daemon">
|
||||
<!--
|
||||
Set all fan curves for a profile to enabled status. Will also activate a
|
||||
fan curve if in the same profile mode
|
||||
-->
|
||||
<method name="SetFanCurvesEnabled">
|
||||
<arg name="profile" type="s" direction="in"/>
|
||||
<arg name="enabled" type="b" direction="in"/>
|
||||
</method>
|
||||
<!--
|
||||
Set a single fan curve for a profile to enabled status. Will also
|
||||
activate a fan curve if in the same profile mode
|
||||
-->
|
||||
<method name="SetProfileFanCurveEnabled">
|
||||
<arg name="profile" type="s" direction="in"/>
|
||||
<arg name="fan" type="s" direction="in"/>
|
||||
<arg name="enabled" type="b" direction="in"/>
|
||||
</method>
|
||||
<!--
|
||||
Get the fan-curve data for the currently active ThrottlePolicy
|
||||
-->
|
||||
<method name="FanCurveData">
|
||||
<arg name="profile" type="s" direction="in"/>
|
||||
<arg type="a(s(yyyyyyyy)(yyyyyyyy)b)" direction="out"/>
|
||||
</method>
|
||||
<!--
|
||||
Set the fan curve for the specified profile.
|
||||
Will also activate the fan curve if the user is in the same mode.
|
||||
-->
|
||||
<method name="SetFanCurve">
|
||||
<arg name="profile" type="s" direction="in"/>
|
||||
<arg name="curve" type="(s(yyyyyyyy)(yyyyyyyy)b)" direction="in"/>
|
||||
</method>
|
||||
<!--
|
||||
Reset the stored (self) and device curve to the defaults of the
|
||||
platform.
|
||||
|
||||
Each platform_profile has a different default and the defualt can be
|
||||
read only for the currently active profile.
|
||||
-->
|
||||
<method name="SetActiveCurveToDefaults">
|
||||
</method>
|
||||
<!--
|
||||
Reset the stored (self) and device curve to the defaults of the
|
||||
platform.
|
||||
|
||||
Each platform_profile has a different default and the defualt can be
|
||||
read only for the currently active profile.
|
||||
-->
|
||||
<method name="ResetProfileCurves">
|
||||
<arg name="profile" type="s" direction="in"/>
|
||||
</method>
|
||||
</interface>
|
||||
</node>
|
||||
46
bindings/dbus-xml/org-asuslinux-platform-4.xml
Normal file
46
bindings/dbus-xml/org-asuslinux-platform-4.xml
Normal file
@@ -0,0 +1,46 @@
|
||||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
<node>
|
||||
<interface name="org.asuslinux.Daemon">
|
||||
<!--
|
||||
Returns a list of property names that this system supports
|
||||
-->
|
||||
<method name="SupportedProperties">
|
||||
<arg type="as" direction="out"/>
|
||||
</method>
|
||||
<method name="SupportedInterfaces">
|
||||
<arg type="as" direction="out"/>
|
||||
</method>
|
||||
<!--
|
||||
Toggle to next platform_profile. Names provided by `Profiles`.
|
||||
If fan-curves are supported will also activate a fan curve for profile.
|
||||
-->
|
||||
<method name="NextThrottleThermalPolicy">
|
||||
</method>
|
||||
<property name="ChargeControlEndThreshold" type="y" access="readwrite"/>
|
||||
<property name="DgpuDisable" type="b" access="read"/>
|
||||
<property name="EgpuEnable" type="b" access="read"/>
|
||||
<property name="GpuMuxMode" type="y" access="readwrite"/>
|
||||
<!--
|
||||
Get the `panel_od` value from platform. Updates the stored value in
|
||||
internal config also.
|
||||
-->
|
||||
<property name="MiniLedMode" type="b" access="readwrite"/>
|
||||
<property name="NvDynamicBoost" type="y" access="readwrite"/>
|
||||
<property name="NvTempTarget" type="y" access="readwrite"/>
|
||||
<!--
|
||||
Get the `panel_od` value from platform. Updates the stored value in
|
||||
internal config also.
|
||||
-->
|
||||
<property name="PanelOd" type="b" access="readwrite"/>
|
||||
<property name="PostAnimationSound" type="b" access="readwrite"/>
|
||||
<property name="PptApuSppt" type="y" access="readwrite"/>
|
||||
<property name="PptFppt" type="y" access="readwrite"/>
|
||||
<!--
|
||||
************************************************************************
|
||||
-->
|
||||
<property name="PptPl1Spl" type="y" access="readwrite"/>
|
||||
<property name="PptPl2Sppt" type="y" access="readwrite"/>
|
||||
<property name="PptPlatformSppt" type="y" access="readwrite"/>
|
||||
<property name="ThrottleThermalPolicy" type="s" access="readwrite"/>
|
||||
</interface>
|
||||
</node>
|
||||
57
bindings/ts/anime.ts
Normal file
57
bindings/ts/anime.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
Generated by typeshare 1.7.0
|
||||
*/
|
||||
|
||||
export enum AnimBooting {
|
||||
GlitchConstruction = "GlitchConstruction",
|
||||
StaticEmergence = "StaticEmergence",
|
||||
}
|
||||
|
||||
export enum AnimAwake {
|
||||
BinaryBannerScroll = "BinaryBannerScroll",
|
||||
RogLogoGlitch = "RogLogoGlitch",
|
||||
}
|
||||
|
||||
export enum AnimSleeping {
|
||||
BannerSwipe = "BannerSwipe",
|
||||
Starfield = "Starfield",
|
||||
}
|
||||
|
||||
export enum AnimShutdown {
|
||||
GlitchOut = "GlitchOut",
|
||||
SeeYa = "SeeYa",
|
||||
}
|
||||
|
||||
export interface Animations {
|
||||
boot: AnimBooting;
|
||||
awake: AnimAwake;
|
||||
sleep: AnimSleeping;
|
||||
shutdown: AnimShutdown;
|
||||
}
|
||||
|
||||
/** Base LED brightness of the display */
|
||||
export enum Brightness {
|
||||
Off = "Off",
|
||||
Low = "Low",
|
||||
Med = "Med",
|
||||
High = "High",
|
||||
}
|
||||
|
||||
export interface DeviceState {
|
||||
display_enabled: boolean;
|
||||
display_brightness: Brightness;
|
||||
builtin_anims_enabled: boolean;
|
||||
builtin_anims: Animations;
|
||||
off_when_unplugged: boolean;
|
||||
off_when_suspended: boolean;
|
||||
off_when_lid_closed: boolean;
|
||||
brightness_on_battery: Brightness;
|
||||
}
|
||||
|
||||
export enum AnimeType {
|
||||
GA401 = "GA401",
|
||||
GA402 = "GA402",
|
||||
GU604 = "GU604",
|
||||
Unknown = "Unknown",
|
||||
}
|
||||
|
||||
233
bindings/ts/aura.ts
Normal file
233
bindings/ts/aura.ts
Normal file
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
Generated by typeshare 1.7.0
|
||||
*/
|
||||
|
||||
/** Represents the per-key raw USB packets */
|
||||
export type UsbPackets = number[][];
|
||||
|
||||
/**
|
||||
* A `UsbPackets` contains all data to change the full set of keyboard
|
||||
* key colours individually.
|
||||
*
|
||||
* Each row of the internal array is a full HID packet that can be sent
|
||||
* to the keyboard EC. One row controls one group of keys, these keys are not
|
||||
* necessarily all on the same row of the keyboard, with some splitting between
|
||||
* two rows.
|
||||
*/
|
||||
export interface LedUsbPackets {
|
||||
/** The packet data used to send data to the USB keyboard */
|
||||
usb_packets: UsbPackets;
|
||||
/**
|
||||
* Wether or not this packet collection is zoned. The determines which
|
||||
* starting bytes are used and what the indexing is for lightbar RGB
|
||||
* colours
|
||||
*/
|
||||
zoned: boolean;
|
||||
}
|
||||
|
||||
export interface Colour {
|
||||
r: number;
|
||||
g: number;
|
||||
b: number;
|
||||
}
|
||||
|
||||
/** Enum of modes that convert to the actual number required by a USB HID packet */
|
||||
export enum AuraModeNum {
|
||||
Static = "Static",
|
||||
Breathe = "Breathe",
|
||||
Strobe = "Strobe",
|
||||
Rainbow = "Rainbow",
|
||||
Star = "Star",
|
||||
Rain = "Rain",
|
||||
Highlight = "Highlight",
|
||||
Laser = "Laser",
|
||||
Ripple = "Ripple",
|
||||
Pulse = "Pulse",
|
||||
Comet = "Comet",
|
||||
Flash = "Flash",
|
||||
}
|
||||
|
||||
/** Base effects have no zoning, while multizone is 1-4 */
|
||||
export enum AuraZone {
|
||||
/** Used if keyboard has no zones, or if setting all */
|
||||
None = "None",
|
||||
/** Leftmost zone */
|
||||
Key1 = "Key1",
|
||||
/** Zone after leftmost */
|
||||
Key2 = "Key2",
|
||||
/** Zone second from right */
|
||||
Key3 = "Key3",
|
||||
/** Rightmost zone */
|
||||
Key4 = "Key4",
|
||||
/** Logo on the lid (or elsewhere?) */
|
||||
Logo = "Logo",
|
||||
/** The left part of a lightbar (typically on the front of laptop) */
|
||||
BarLeft = "BarLeft",
|
||||
/** The right part of a lightbar */
|
||||
BarRight = "BarRight",
|
||||
}
|
||||
|
||||
export enum Speed {
|
||||
Low = "Low",
|
||||
Med = "Med",
|
||||
High = "High",
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for Rainbow mode.
|
||||
*
|
||||
* Enum corresponds to the required integer value
|
||||
*/
|
||||
export enum Direction {
|
||||
Right = "Right",
|
||||
Left = "Left",
|
||||
Up = "Up",
|
||||
Down = "Down",
|
||||
}
|
||||
|
||||
/**
|
||||
* Default factory modes structure. This easily converts to an USB HID packet
|
||||
* with:
|
||||
* ```rust
|
||||
* // let bytes: [u8; LED_MSG_LEN] = mode.into();
|
||||
* ```
|
||||
*/
|
||||
export interface AuraEffect {
|
||||
/** The effect type */
|
||||
mode: AuraModeNum;
|
||||
/** `AuraZone::None` for no zone or zoneless keyboards */
|
||||
zone: AuraZone;
|
||||
/** Primary colour for all modes */
|
||||
colour1: Colour;
|
||||
/** Secondary colour in some modes like Breathing or Stars */
|
||||
colour2: Colour;
|
||||
/** One of three speeds for modes that support speed (most that animate) */
|
||||
speed: Speed;
|
||||
/** Up, down, left, right. Only Rainbow mode seems to use this */
|
||||
direction: Direction;
|
||||
}
|
||||
|
||||
/** The powerr zones this laptop supports */
|
||||
export enum PowerZones {
|
||||
/** The logo on some laptop lids */
|
||||
Logo = "Logo",
|
||||
/** The full keyboard (not zones) */
|
||||
Keyboard = "Keyboard",
|
||||
/** The lightbar, typically on the front of the laptop */
|
||||
Lightbar = "Lightbar",
|
||||
/** The leds that may be placed around the edge of the laptop lid */
|
||||
Lid = "Lid",
|
||||
/** The led strip on the rear of some laptops */
|
||||
RearGlow = "RearGlow",
|
||||
}
|
||||
|
||||
export interface KbAuraPowerState {
|
||||
zone: PowerZones;
|
||||
boot: boolean;
|
||||
awake: boolean;
|
||||
sleep: boolean;
|
||||
shutdown: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Track and control the Aura keyboard power state
|
||||
*
|
||||
* # Bits for newer 0x18c6, 0x19B6, 0x1a30, keyboard models
|
||||
*
|
||||
* | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Label |
|
||||
* |--------|---------|---------|---------|----------|
|
||||
* |00000001| 00000000| 00000000| 00000000|boot_logo_|
|
||||
* |00000010| 00000000| 00000000| 00000000|boot_keyb_|
|
||||
* |00000100| 00000000| 00000000| 00000000|awake_logo|
|
||||
* |00001000| 00000000| 00000000| 00000000|awake_keyb|
|
||||
* |00010000| 00000000| 00000000| 00000000|sleep_logo|
|
||||
* |00100000| 00000000| 00000000| 00000000|sleep_keyb|
|
||||
* |01000000| 00000000| 00000000| 00000000|shut_logo_|
|
||||
* |10000000| 00000000| 00000000| 00000000|shut_keyb_|
|
||||
* |00000000| 00000010| 00000000| 00000000|boot_bar__|
|
||||
* |00000000| 00000100| 00000000| 00000000|awake_bar_|
|
||||
* |00000000| 00001000| 00000000| 00000000|sleep_bar_|
|
||||
* |00000000| 00010000| 00000000| 00000000|shut_bar__|
|
||||
* |00000000| 00000000| 00000001| 00000000|boot_lid__|
|
||||
* |00000000| 00000000| 00000010| 00000000|awkae_lid_|
|
||||
* |00000000| 00000000| 00000100| 00000000|sleep_lid_|
|
||||
* |00000000| 00000000| 00001000| 00000000|shut_lid__|
|
||||
* |00000000| 00000000| 00000000| 00000001|boot_rear_|
|
||||
* |00000000| 00000000| 00000000| 00000010|awake_rear|
|
||||
* |00000000| 00000000| 00000000| 00000100|sleep_rear|
|
||||
* |00000000| 00000000| 00000000| 00001000|shut_rear_|
|
||||
*/
|
||||
export interface AuraPower {
|
||||
keyboard: KbAuraPowerState;
|
||||
logo: KbAuraPowerState;
|
||||
lightbar: KbAuraPowerState;
|
||||
lid: KbAuraPowerState;
|
||||
rear_glow: KbAuraPowerState;
|
||||
}
|
||||
|
||||
export enum AuraDevTuf {
|
||||
Boot = "Boot",
|
||||
Awake = "Awake",
|
||||
Sleep = "Sleep",
|
||||
Keyboard = "Keyboard",
|
||||
}
|
||||
|
||||
/**
|
||||
* # Bits for older 0x1866 keyboard model
|
||||
*
|
||||
* Keybord and Lightbar require Awake, Boot and Sleep apply to both
|
||||
* Keybord and Lightbar regardless of if either are enabled (or Awake is
|
||||
* enabled)
|
||||
*
|
||||
* | Byte 1 | Byte 2 | Byte 3 | function | hex |
|
||||
* |------------|------------|------------|----------|----------|
|
||||
* | 0000, 0000 | 0000, 0000 | 0000, 0010 | Awake | 00,00,02 |
|
||||
* | 0000, 1000 | 0000, 0000 | 0000, 0000 | Keyboard | 08,00,00 |
|
||||
* | 0000, 0100 | 0000, 0101 | 0000, 0000 | Lightbar | 04,05,00 |
|
||||
* | 1100, 0011 | 0001, 0010 | 0000, 1001 | Boot/Sht | c3,12,09 |
|
||||
* | 0011, 0000 | 0000, 1000 | 0000, 0100 | Sleep | 30,08,04 |
|
||||
* | 1111, 1111 | 0001, 1111 | 0000, 1111 | all on | |
|
||||
*/
|
||||
export enum AuraDevRog1 {
|
||||
Awake = "Awake",
|
||||
Keyboard = "Keyboard",
|
||||
Lightbar = "Lightbar",
|
||||
Boot = "Boot",
|
||||
Sleep = "Sleep",
|
||||
}
|
||||
|
||||
/** This struct is intended as a helper to pass args to generic dbus interface */
|
||||
export interface AuraPowerDev {
|
||||
/**
|
||||
* TUF laptops use a similar style of control to the older ROG devices but
|
||||
* through WMI
|
||||
*/
|
||||
tuf: AuraDevTuf[];
|
||||
/**
|
||||
* Pre-0x19b6 devices use a different smaller scheme to the newer ROG
|
||||
* devices
|
||||
*/
|
||||
old_rog: AuraDevRog1[];
|
||||
/** ASUS standardised control scheme from 2020 onwards */
|
||||
rog: AuraPower;
|
||||
}
|
||||
|
||||
export enum LedBrightness {
|
||||
Off = "Off",
|
||||
Low = "Low",
|
||||
Med = "Med",
|
||||
High = "High",
|
||||
}
|
||||
|
||||
export enum AuraDevice {
|
||||
Tuf = "Tuf",
|
||||
X1854 = "X1854",
|
||||
X1869 = "X1869",
|
||||
X1866 = "X1866",
|
||||
X18c6 = "X18c6",
|
||||
X19b6 = "X19b6",
|
||||
X1a30 = "X1a30",
|
||||
X1abe = "X1abe",
|
||||
Unknown = "Unknown",
|
||||
}
|
||||
|
||||
55
bindings/ts/platform.ts
Normal file
55
bindings/ts/platform.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
Generated by typeshare 1.7.0
|
||||
*/
|
||||
|
||||
export enum CPUGovernor {
|
||||
Performance = "Performance",
|
||||
Powersave = "Powersave",
|
||||
BadValue = "BadValue",
|
||||
}
|
||||
|
||||
export enum CPUEPP {
|
||||
Default = "Default",
|
||||
Performance = "Performance",
|
||||
BalancePerformance = "BalancePerformance",
|
||||
BalancePower = "BalancePower",
|
||||
Power = "Power",
|
||||
}
|
||||
|
||||
export enum GpuMode {
|
||||
Discrete = "Discrete",
|
||||
Optimus = "Optimus",
|
||||
Integrated = "Integrated",
|
||||
Egpu = "Egpu",
|
||||
Vfio = "Vfio",
|
||||
Ultimate = "Ultimate",
|
||||
Error = "Error",
|
||||
NotSupported = "NotSupported",
|
||||
}
|
||||
|
||||
/** `throttle_thermal_policy` in asus_wmi */
|
||||
export enum ThrottlePolicy {
|
||||
Balanced = "Balanced",
|
||||
Performance = "Performance",
|
||||
Quiet = "Quiet",
|
||||
}
|
||||
|
||||
/** CamelCase names of the properties. Intended for use with DBUS */
|
||||
export enum Properties {
|
||||
ChargeControlEndThreshold = "ChargeControlEndThreshold",
|
||||
DgpuDisable = "DgpuDisable",
|
||||
GpuMuxMode = "GpuMuxMode",
|
||||
PostAnimationSound = "PostAnimationSound",
|
||||
PanelOd = "PanelOd",
|
||||
MiniLedMode = "MiniLedMode",
|
||||
EgpuEnable = "EgpuEnable",
|
||||
ThrottlePolicy = "ThrottlePolicy",
|
||||
PptPl1Spl = "PptPl1Spl",
|
||||
PptPl2Sppt = "PptPl2Sppt",
|
||||
PptFppt = "PptFppt",
|
||||
PptApuSppt = "PptApuSppt",
|
||||
PptPlatformSppt = "PptPlatformSppt",
|
||||
NvDynamicBoost = "NvDynamicBoost",
|
||||
NvTempTarget = "NvTempTarget",
|
||||
}
|
||||
|
||||
24
bindings/ts/profiles.ts
Normal file
24
bindings/ts/profiles.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
Generated by typeshare 1.7.0
|
||||
*/
|
||||
|
||||
export enum FanCurvePU {
|
||||
CPU = "CPU",
|
||||
GPU = "GPU",
|
||||
MID = "MID",
|
||||
}
|
||||
|
||||
export interface CurveData {
|
||||
fan: FanCurvePU;
|
||||
pwm: [number, number, number, number, number, number, number, number];
|
||||
temp: [number, number, number, number, number, number, number, number];
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
/** Main purpose of `FanCurves` is to enable restoring state on system boot */
|
||||
export interface FanCurveProfiles {
|
||||
balanced: CurveData[];
|
||||
performance: CurveData[];
|
||||
quiet: CurveData[];
|
||||
}
|
||||
|
||||
@@ -109,6 +109,20 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Open and parse the config file to self from ron format
|
||||
fn read_new(&self) -> Option<Self> {
|
||||
if let Ok(data) = fs::read_to_string(self.file_path()) {
|
||||
if data.is_empty() {
|
||||
warn!("File is empty {:?}", self.file_path());
|
||||
} else if let Ok(data) = ron::from_str(&data) {
|
||||
return Some(data);
|
||||
} else {
|
||||
warn!("Could not deserialise {:?}", self.file_path());
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Write the config file data to pretty ron format
|
||||
fn write(&self) {
|
||||
let mut file = match File::create(self.file_path()) {
|
||||
|
||||
7
cpuctl/Cargo.toml
Normal file
7
cpuctl/Cargo.toml
Normal file
@@ -0,0 +1,7 @@
|
||||
[package]
|
||||
name = "cpuctl"
|
||||
license = "MPL-2.0"
|
||||
edition = "2021"
|
||||
version.workspace = true
|
||||
|
||||
[dependencies]
|
||||
14
cpuctl/src/lib.rs
Normal file
14
cpuctl/src/lib.rs
Normal file
@@ -0,0 +1,14 @@
|
||||
pub fn add(left: usize, right: usize) -> usize {
|
||||
left + right
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn it_works() {
|
||||
let result = add(2, 2);
|
||||
assert_eq!(result, 4);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,3 @@
|
||||
#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"
|
||||
|
||||
ENV{DMI_VENDOR}="$attr{[dmi/id]sys_vendor}"
|
||||
ENV{DMI_VENDOR}!="ASUSTeK COMPUTER INC.", GOTO="asusd_end"
|
||||
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
[Unit]
|
||||
Description=ASUS Notebook Control
|
||||
StartLimitInterval=200
|
||||
StartLimitBurst=2
|
||||
Before=multi-user.target
|
||||
After=power-profiles-daemon.service
|
||||
After=nvidia-powerd.service
|
||||
StartLimitInterval=500
|
||||
StartLimitBurst=5
|
||||
After=nvidia-powerd.service systemd-udevd.service
|
||||
|
||||
[Service]
|
||||
Environment=IS_SERVICE=1
|
||||
Environment=RUST_LOG="info"
|
||||
ExecStartPre=/bin/sleep 2
|
||||
# ExecStartPre=/bin/sleep 2 # was required only for slow devices
|
||||
ExecStart=/usr/bin/asusd
|
||||
Restart=on-failure
|
||||
RestartSec=1
|
||||
|
||||
1
data/icons/scalable/anime.svg
Normal file
1
data/icons/scalable/anime.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!-- Generator: Gravit.io --><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="isolation:isolate" viewBox="0 0 512 512" width="512pt" height="512pt"><defs><clipPath id="_clipPath_8C5izdJ0sH9w7nD5UuBTlpktuZWEWJn8"><rect width="512" height="512"/></clipPath></defs><g clip-path="url(#_clipPath_8C5izdJ0sH9w7nD5UuBTlpktuZWEWJn8)"><path d=" M 113.969 270.246 C 113.969 301.718 88.456 327.231 56.985 327.231 C 25.513 327.231 0 301.718 0 270.246 C 0 238.775 25.513 213.262 56.985 213.262 C 88.456 213.262 113.969 238.775 113.969 270.246 Z M 56.985 384.215 C 41.249 384.215 28.492 396.972 28.492 412.708 C 28.492 428.443 41.249 441.2 56.985 441.2 C 72.72 441.2 85.477 428.443 85.477 412.708 C 85.477 396.972 72.72 384.215 56.985 384.215 Z M 56.985 70.8 C 25.513 70.8 0 96.313 0 127.785 C 0 159.256 25.513 184.769 56.985 184.769 C 88.456 184.769 113.969 159.256 113.969 127.785 C 113.969 96.313 88.456 70.8 56.985 70.8 Z M 199.446 241.754 C 183.71 241.754 170.954 254.51 170.954 270.246 C 170.954 285.982 183.71 298.738 199.446 298.738 C 215.182 298.738 227.938 285.982 227.938 270.246 C 227.938 254.51 215.182 241.754 199.446 241.754 Z M 199.446 384.215 C 183.71 384.215 170.954 396.972 170.954 412.708 C 170.954 428.443 183.71 441.2 199.446 441.2 C 215.182 441.2 227.938 428.443 227.938 412.708 C 227.938 396.972 215.182 384.215 199.446 384.215 Z M 199.446 70.8 C 167.975 70.8 142.462 96.313 142.462 127.785 C 142.462 159.256 167.975 184.769 199.446 184.769 C 230.918 184.769 256.431 159.256 256.431 127.785 C 256.431 96.313 230.918 70.8 199.446 70.8 Z M 339.904 241.754 C 324.169 241.754 311.412 254.51 311.412 270.246 C 311.412 285.982 324.169 298.738 339.904 298.738 C 355.64 298.738 368.397 285.982 368.397 270.246 C 368.397 254.51 355.64 241.754 339.904 241.754 Z M 339.904 384.215 C 324.169 384.215 311.412 396.972 311.412 412.708 C 311.412 428.443 324.169 441.2 339.904 441.2 C 355.64 441.2 368.397 428.443 368.397 412.708 C 368.397 396.972 355.64 384.215 339.904 384.215 Z M 339.904 70.8 C 308.433 70.8 282.92 96.313 282.92 127.785 C 282.92 159.256 308.433 184.769 339.904 184.769 C 371.376 184.769 396.889 159.256 396.889 127.785 C 396.889 96.313 371.376 70.8 339.904 70.8 Z M 482.366 241.754 C 466.63 241.754 453.874 254.51 453.874 270.246 C 453.874 285.982 466.63 298.738 482.366 298.738 C 498.102 298.738 510.858 285.982 510.858 270.246 C 510.858 254.51 498.102 241.754 482.366 241.754 Z M 482.366 384.215 C 466.63 384.215 453.874 396.972 453.874 412.708 C 453.874 428.443 466.63 441.2 482.366 441.2 C 498.102 441.2 510.858 428.443 510.858 412.708 C 510.858 396.972 498.102 384.215 482.366 384.215 Z M 482.366 99.292 C 466.63 99.292 453.874 112.049 453.874 127.785 C 453.874 143.52 466.63 156.277 482.366 156.277 C 498.102 156.277 510.858 143.52 510.858 127.785 C 510.858 112.049 498.102 99.292 482.366 99.292 Z " fill="#F2F2F2"/></g></svg>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
1
data/icons/scalable/reboot.svg
Normal file
1
data/icons/scalable/reboot.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!-- Generator: Gravit.io --><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="isolation:isolate" viewBox="141 297.96 507.339 471.04" width="507.339pt" height="471.04pt"><g><g><g><g><path d=" M 537.075 443.463 L 537.075 443.463 L 564.723 427.335 C 504.903 324.571 375.966 285.313 269.027 337.304 L 269.027 297.96 L 237.027 297.96 L 237.027 393.96 L 333.027 393.96 L 333.027 361.96 L 292.147 361.96 C 382.665 323.563 487.612 358.486 537.075 443.463 Z " fill="rgb(221,221,221)"/><path d=" M 245.027 692.775 C 170.84 632.524 151.314 527.353 198.931 444.488 L 171.187 428.488 C 116.876 523.063 137.426 642.887 220.147 713.96 L 181.027 713.96 L 181.027 745.96 L 277.027 745.96 L 277.027 649.96 L 245.027 649.96 L 245.027 692.775 L 245.027 692.775 Z " fill="rgb(221,221,221)"/><path d=" M 580.451 499.048 L 512.579 566.936 L 535.203 589.56 L 562.403 562.36 C 551.734 661.49 468.201 736.724 368.499 737 L 368.499 769 C 487.289 768.688 585.833 677.011 594.707 558.552 L 625.715 589.56 L 648.339 566.936 L 580.451 499.048 Z " fill="rgb(221,221,221)"/></g></g></g></g></svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
1
data/icons/scalable/rog-logo.svg
Normal file
1
data/icons/scalable/rog-logo.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!-- Generator: Gravit.io --><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="isolation:isolate" viewBox="0 0 128 128" width="128pt" height="128pt"><defs><clipPath id="_clipPath_CHRnLOITGqiXLlZjYLaUfMylStiUiIRD"><rect width="128" height="128"/></clipPath></defs><g clip-path="url(#_clipPath_CHRnLOITGqiXLlZjYLaUfMylStiUiIRD)"><path d=" M 69.096 31.645 C 68.865 31.712 68.805 31.816 68.577 32.011 C 68.393 32.168 68.238 32.28 68.059 32.434 C 67.651 32.785 67.411 33.003 67.052 33.305 C 65.269 34.805 62.85 37.142 61.102 38.778 C 58.391 41.317 55.947 43.762 53.346 46.287 C 48.441 51.049 42.882 56.766 37.972 61.357 C 33.914 65.151 30.434 68.558 26.194 72.351 C 24.574 73.801 23.553 75.121 21.346 75.197 C 17.705 75.323 12.902 72.224 10.446 70.814 C 8.299 69.583 2.598 66.23 -0.15 66.137 L 1.864 68.903 C 3.303 71.1 5.724 75.885 6.887 78.214 C 10.881 86.213 16.273 94.589 23.136 100.161 C 24.891 101.586 26.481 102.783 28.71 104.132 C 29.687 104.723 30.685 105.215 31.778 105.834 C 32.157 106.049 34.786 107.277 35.11 107.276 C 34.39 106.554 33.649 105.673 33.064 104.985 C 30.452 101.912 24.64 95.938 22.894 92.889 C 21.428 90.329 21.091 88.761 22.72 86.192 C 24.582 83.254 28.924 79.619 31.648 77.289 C 38.277 71.62 44.256 66.485 51.191 61.102 C 54.478 58.551 57.895 55.949 61.429 53.427 C 64.896 50.954 68.381 48.57 72 46.178 L 77.465 42.7 C 77.972 42.409 82.95 39.446 83.029 39.347 L 87.9 36.66 C 89.536 35.736 91.124 34.964 92.857 34.031 C 97.94 31.294 108.035 26.833 113.82 24.792 C 115.718 24.122 117.528 23.489 119.449 22.833 L 125.205 21.03 C 124.739 20.79 118.379 20.724 117.207 20.724 C 112.491 20.723 109.598 20.855 105.095 21.211 C 101.65 21.483 95.237 22.19 92.104 22.948 C 91.54 23.084 90.872 23.142 90.304 23.292 C 89.218 23.578 87.974 23.775 86.861 24.052 C 84.567 24.623 82.484 25.271 80.328 25.914 C 78.108 26.575 76.101 27.36 74.115 28.177 C 72.942 28.659 69.397 31.029 69.096 31.645 L 69.096 31.645 Z M 115.16 43.036 L 119.345 40.899 C 120.797 40.208 122.299 39.413 123.667 38.745 C 126.441 37.389 128.04 32.995 127.999 30.179 C 127.509 30.199 125.516 31.144 124.975 31.342 C 124.603 31.479 124.259 31.596 123.911 31.744 C 121.439 32.794 118.139 34.036 115.795 35.142 C 115.115 35.463 114.457 35.729 113.769 36.024 C 113.228 36.256 112.036 36.724 111.814 36.999 C 111.07 36.962 95.925 44.467 94.037 45.443 C 91.35 46.833 87.97 48.499 85.386 49.936 C 85.08 50.106 77.204 54.275 76.891 54.676 C 76.372 54.762 70.974 57.968 70.112 58.454 C 59.43 64.482 47.599 72.065 37.367 79.004 C 34.524 80.933 30.892 83.463 28.034 85.617 L 25.739 87.329 C 25.476 87.53 25.165 87.663 25.013 87.965 C 26.033 88.843 32.791 91.628 34.403 92.209 C 43.451 95.47 51.92 97.742 61.441 99.376 L 67.483 100.3 L 72.241 100.72 L 68.366 100.378 C 69.105 100.462 69.839 100.582 70.559 100.651 C 71.624 100.753 72.679 100.84 73.776 100.949 C 75.841 101.157 78.238 101.298 80.361 101.335 C 82.999 101.381 84.453 101.516 86.617 100.603 C 88.294 99.894 89.659 99.013 90.992 97.992 C 95.957 94.187 100.375 88.235 103.899 82.849 C 107.587 77.213 110.909 70.915 113.773 64.675 C 115.231 61.498 116.599 58.182 117.888 54.804 C 118.541 53.092 119.107 51.439 119.697 49.622 C 120.023 48.617 121.212 44.945 121.302 44.125 C 119.948 44.31 96.265 57.088 94.012 58.297 C 90.956 59.938 88.029 61.647 85.064 63.258 C 82.182 64.823 79.134 66.672 76.267 68.266 C 70.441 71.504 64.575 75.11 58.757 78.479 C 57.76 79.056 50.352 83.387 50.086 83.691 C 50.584 83.611 74.07 73.525 74.639 73.29 C 75.746 72.832 98.806 62.937 99.184 62.92 C 99.052 63.454 97.624 66.118 97.264 66.901 C 96.664 68.206 95.94 69.692 95.284 70.989 C 91.565 78.346 87.529 87.178 79.411 90.439 L 78.923 90.732 C 78.488 90.742 77.299 91.225 76.775 91.369 C 75.986 91.586 75.223 91.736 74.428 91.899 C 70.686 92.665 65.028 92.266 61.129 91.656 C 56.682 90.96 53.568 90.179 49.258 89.137 C 48.229 88.889 40.792 86.799 40.362 86.516 C 40.604 86.093 44.858 83.368 45.23 83.109 C 53.46 77.389 67.13 68.983 76.02 63.925 C 76.961 63.389 77.835 62.903 78.696 62.41 C 79.411 62 80.72 61.317 81.298 60.897 L 85.457 58.616 C 86.864 57.835 88.155 57.159 89.637 56.314 C 92.438 54.716 95.275 53.376 98.032 51.823 C 98.437 51.595 114.179 43.323 115.159 43.037 L 115.16 43.036 Z " fill-rule="evenodd" fill="#F2F2F2"/></g></svg>
|
||||
|
After Width: | Height: | Size: 4.2 KiB |
25
desktop-extensions/gnome-45/.eslintrc.cjs
Normal file
25
desktop-extensions/gnome-45/.eslintrc.cjs
Normal file
@@ -0,0 +1,25 @@
|
||||
/* eslint-env node */
|
||||
module.exports = {
|
||||
extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
|
||||
parser: "@typescript-eslint/parser",
|
||||
plugins: ["@typescript-eslint"],
|
||||
root: true,
|
||||
|
||||
rules: {
|
||||
// enable additional rules
|
||||
indent: ["error", 4],
|
||||
"linebreak-style": ["error", "unix"],
|
||||
quotes: ["error", "double"],
|
||||
semi: ["error", "always"],
|
||||
|
||||
// override configuration set by extending "eslint:recommended"
|
||||
"no-empty": "warn",
|
||||
"no-cond-assign": ["error", "always"],
|
||||
|
||||
// disable rules from base configurations
|
||||
"for-direction": "off",
|
||||
|
||||
"@typescript-eslint/no-explicit-any": "warn",
|
||||
"@typescript-eslint/ban-ts-comment": "off",
|
||||
},
|
||||
};
|
||||
13
desktop-extensions/gnome-45/.prettierignore
Normal file
13
desktop-extensions/gnome-45/.prettierignore
Normal file
@@ -0,0 +1,13 @@
|
||||
# Generated files
|
||||
/@types/gir-generated/*
|
||||
|
||||
# Build outputes
|
||||
/dist/
|
||||
/build/
|
||||
|
||||
# Node configuration and modules
|
||||
/package.json
|
||||
/node_modules/
|
||||
|
||||
# Files I prefer not to be formatted
|
||||
*.md
|
||||
9
desktop-extensions/gnome-45/.prettierrc.json
Normal file
9
desktop-extensions/gnome-45/.prettierrc.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"printWidth": 100,
|
||||
"useTabs": false,
|
||||
"semi": true,
|
||||
"singleQuote": false,
|
||||
"trailingComma": "all",
|
||||
"bracketSpacing": true,
|
||||
"arrowParens": "always"
|
||||
}
|
||||
373
desktop-extensions/gnome-45/LICENSE
Normal file
373
desktop-extensions/gnome-45/LICENSE
Normal file
@@ -0,0 +1,373 @@
|
||||
Mozilla Public License Version 2.0
|
||||
==================================
|
||||
|
||||
1. Definitions
|
||||
--------------
|
||||
|
||||
1.1. "Contributor"
|
||||
means each individual or legal entity that creates, contributes to
|
||||
the creation of, or owns Covered Software.
|
||||
|
||||
1.2. "Contributor Version"
|
||||
means the combination of the Contributions of others (if any) used
|
||||
by a Contributor and that particular Contributor's Contribution.
|
||||
|
||||
1.3. "Contribution"
|
||||
means Covered Software of a particular Contributor.
|
||||
|
||||
1.4. "Covered Software"
|
||||
means Source Code Form to which the initial Contributor has attached
|
||||
the notice in Exhibit A, the Executable Form of such Source Code
|
||||
Form, and Modifications of such Source Code Form, in each case
|
||||
including portions thereof.
|
||||
|
||||
1.5. "Incompatible With Secondary Licenses"
|
||||
means
|
||||
|
||||
(a) that the initial Contributor has attached the notice described
|
||||
in Exhibit B to the Covered Software; or
|
||||
|
||||
(b) that the Covered Software was made available under the terms of
|
||||
version 1.1 or earlier of the License, but not also under the
|
||||
terms of a Secondary License.
|
||||
|
||||
1.6. "Executable Form"
|
||||
means any form of the work other than Source Code Form.
|
||||
|
||||
1.7. "Larger Work"
|
||||
means a work that combines Covered Software with other material, in
|
||||
a separate file or files, that is not Covered Software.
|
||||
|
||||
1.8. "License"
|
||||
means this document.
|
||||
|
||||
1.9. "Licensable"
|
||||
means having the right to grant, to the maximum extent possible,
|
||||
whether at the time of the initial grant or subsequently, any and
|
||||
all of the rights conveyed by this License.
|
||||
|
||||
1.10. "Modifications"
|
||||
means any of the following:
|
||||
|
||||
(a) any file in Source Code Form that results from an addition to,
|
||||
deletion from, or modification of the contents of Covered
|
||||
Software; or
|
||||
|
||||
(b) any new file in Source Code Form that contains any Covered
|
||||
Software.
|
||||
|
||||
1.11. "Patent Claims" of a Contributor
|
||||
means any patent claim(s), including without limitation, method,
|
||||
process, and apparatus claims, in any patent Licensable by such
|
||||
Contributor that would be infringed, but for the grant of the
|
||||
License, by the making, using, selling, offering for sale, having
|
||||
made, import, or transfer of either its Contributions or its
|
||||
Contributor Version.
|
||||
|
||||
1.12. "Secondary License"
|
||||
means either the GNU General Public License, Version 2.0, the GNU
|
||||
Lesser General Public License, Version 2.1, the GNU Affero General
|
||||
Public License, Version 3.0, or any later versions of those
|
||||
licenses.
|
||||
|
||||
1.13. "Source Code Form"
|
||||
means the form of the work preferred for making modifications.
|
||||
|
||||
1.14. "You" (or "Your")
|
||||
means an individual or a legal entity exercising rights under this
|
||||
License. For legal entities, "You" includes any entity that
|
||||
controls, is controlled by, or is under common control with You. For
|
||||
purposes of this definition, "control" means (a) the power, direct
|
||||
or indirect, to cause the direction or management of such entity,
|
||||
whether by contract or otherwise, or (b) ownership of more than
|
||||
fifty percent (50%) of the outstanding shares or beneficial
|
||||
ownership of such entity.
|
||||
|
||||
2. License Grants and Conditions
|
||||
--------------------------------
|
||||
|
||||
2.1. Grants
|
||||
|
||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license:
|
||||
|
||||
(a) under intellectual property rights (other than patent or trademark)
|
||||
Licensable by such Contributor to use, reproduce, make available,
|
||||
modify, display, perform, distribute, and otherwise exploit its
|
||||
Contributions, either on an unmodified basis, with Modifications, or
|
||||
as part of a Larger Work; and
|
||||
|
||||
(b) under Patent Claims of such Contributor to make, use, sell, offer
|
||||
for sale, have made, import, and otherwise transfer either its
|
||||
Contributions or its Contributor Version.
|
||||
|
||||
2.2. Effective Date
|
||||
|
||||
The licenses granted in Section 2.1 with respect to any Contribution
|
||||
become effective for each Contribution on the date the Contributor first
|
||||
distributes such Contribution.
|
||||
|
||||
2.3. Limitations on Grant Scope
|
||||
|
||||
The licenses granted in this Section 2 are the only rights granted under
|
||||
this License. No additional rights or licenses will be implied from the
|
||||
distribution or licensing of Covered Software under this License.
|
||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
||||
Contributor:
|
||||
|
||||
(a) for any code that a Contributor has removed from Covered Software;
|
||||
or
|
||||
|
||||
(b) for infringements caused by: (i) Your and any other third party's
|
||||
modifications of Covered Software, or (ii) the combination of its
|
||||
Contributions with other software (except as part of its Contributor
|
||||
Version); or
|
||||
|
||||
(c) under Patent Claims infringed by Covered Software in the absence of
|
||||
its Contributions.
|
||||
|
||||
This License does not grant any rights in the trademarks, service marks,
|
||||
or logos of any Contributor (except as may be necessary to comply with
|
||||
the notice requirements in Section 3.4).
|
||||
|
||||
2.4. Subsequent Licenses
|
||||
|
||||
No Contributor makes additional grants as a result of Your choice to
|
||||
distribute the Covered Software under a subsequent version of this
|
||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
||||
permitted under the terms of Section 3.3).
|
||||
|
||||
2.5. Representation
|
||||
|
||||
Each Contributor represents that the Contributor believes its
|
||||
Contributions are its original creation(s) or it has sufficient rights
|
||||
to grant the rights to its Contributions conveyed by this License.
|
||||
|
||||
2.6. Fair Use
|
||||
|
||||
This License is not intended to limit any rights You have under
|
||||
applicable copyright doctrines of fair use, fair dealing, or other
|
||||
equivalents.
|
||||
|
||||
2.7. Conditions
|
||||
|
||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
|
||||
in Section 2.1.
|
||||
|
||||
3. Responsibilities
|
||||
-------------------
|
||||
|
||||
3.1. Distribution of Source Form
|
||||
|
||||
All distribution of Covered Software in Source Code Form, including any
|
||||
Modifications that You create or to which You contribute, must be under
|
||||
the terms of this License. You must inform recipients that the Source
|
||||
Code Form of the Covered Software is governed by the terms of this
|
||||
License, and how they can obtain a copy of this License. You may not
|
||||
attempt to alter or restrict the recipients' rights in the Source Code
|
||||
Form.
|
||||
|
||||
3.2. Distribution of Executable Form
|
||||
|
||||
If You distribute Covered Software in Executable Form then:
|
||||
|
||||
(a) such Covered Software must also be made available in Source Code
|
||||
Form, as described in Section 3.1, and You must inform recipients of
|
||||
the Executable Form how they can obtain a copy of such Source Code
|
||||
Form by reasonable means in a timely manner, at a charge no more
|
||||
than the cost of distribution to the recipient; and
|
||||
|
||||
(b) You may distribute such Executable Form under the terms of this
|
||||
License, or sublicense it under different terms, provided that the
|
||||
license for the Executable Form does not attempt to limit or alter
|
||||
the recipients' rights in the Source Code Form under this License.
|
||||
|
||||
3.3. Distribution of a Larger Work
|
||||
|
||||
You may create and distribute a Larger Work under terms of Your choice,
|
||||
provided that You also comply with the requirements of this License for
|
||||
the Covered Software. If the Larger Work is a combination of Covered
|
||||
Software with a work governed by one or more Secondary Licenses, and the
|
||||
Covered Software is not Incompatible With Secondary Licenses, this
|
||||
License permits You to additionally distribute such Covered Software
|
||||
under the terms of such Secondary License(s), so that the recipient of
|
||||
the Larger Work may, at their option, further distribute the Covered
|
||||
Software under the terms of either this License or such Secondary
|
||||
License(s).
|
||||
|
||||
3.4. Notices
|
||||
|
||||
You may not remove or alter the substance of any license notices
|
||||
(including copyright notices, patent notices, disclaimers of warranty,
|
||||
or limitations of liability) contained within the Source Code Form of
|
||||
the Covered Software, except that You may alter any license notices to
|
||||
the extent required to remedy known factual inaccuracies.
|
||||
|
||||
3.5. Application of Additional Terms
|
||||
|
||||
You may choose to offer, and to charge a fee for, warranty, support,
|
||||
indemnity or liability obligations to one or more recipients of Covered
|
||||
Software. However, You may do so only on Your own behalf, and not on
|
||||
behalf of any Contributor. You must make it absolutely clear that any
|
||||
such warranty, support, indemnity, or liability obligation is offered by
|
||||
You alone, and You hereby agree to indemnify every Contributor for any
|
||||
liability incurred by such Contributor as a result of warranty, support,
|
||||
indemnity or liability terms You offer. You may include additional
|
||||
disclaimers of warranty and limitations of liability specific to any
|
||||
jurisdiction.
|
||||
|
||||
4. Inability to Comply Due to Statute or Regulation
|
||||
---------------------------------------------------
|
||||
|
||||
If it is impossible for You to comply with any of the terms of this
|
||||
License with respect to some or all of the Covered Software due to
|
||||
statute, judicial order, or regulation then You must: (a) comply with
|
||||
the terms of this License to the maximum extent possible; and (b)
|
||||
describe the limitations and the code they affect. Such description must
|
||||
be placed in a text file included with all distributions of the Covered
|
||||
Software under this License. Except to the extent prohibited by statute
|
||||
or regulation, such description must be sufficiently detailed for a
|
||||
recipient of ordinary skill to be able to understand it.
|
||||
|
||||
5. Termination
|
||||
--------------
|
||||
|
||||
5.1. The rights granted under this License will terminate automatically
|
||||
if You fail to comply with any of its terms. However, if You become
|
||||
compliant, then the rights granted under this License from a particular
|
||||
Contributor are reinstated (a) provisionally, unless and until such
|
||||
Contributor explicitly and finally terminates Your grants, and (b) on an
|
||||
ongoing basis, if such Contributor fails to notify You of the
|
||||
non-compliance by some reasonable means prior to 60 days after You have
|
||||
come back into compliance. Moreover, Your grants from a particular
|
||||
Contributor are reinstated on an ongoing basis if such Contributor
|
||||
notifies You of the non-compliance by some reasonable means, this is the
|
||||
first time You have received notice of non-compliance with this License
|
||||
from such Contributor, and You become compliant prior to 30 days after
|
||||
Your receipt of the notice.
|
||||
|
||||
5.2. If You initiate litigation against any entity by asserting a patent
|
||||
infringement claim (excluding declaratory judgment actions,
|
||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
||||
directly or indirectly infringes any patent, then the rights granted to
|
||||
You by any and all Contributors for the Covered Software under Section
|
||||
2.1 of this License shall terminate.
|
||||
|
||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
|
||||
end user license agreements (excluding distributors and resellers) which
|
||||
have been validly granted by You or Your distributors under this License
|
||||
prior to termination shall survive termination.
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 6. Disclaimer of Warranty *
|
||||
* ------------------------- *
|
||||
* *
|
||||
* Covered Software is provided under this License on an "as is" *
|
||||
* basis, without warranty of any kind, either expressed, implied, or *
|
||||
* statutory, including, without limitation, warranties that the *
|
||||
* Covered Software is free of defects, merchantable, fit for a *
|
||||
* particular purpose or non-infringing. The entire risk as to the *
|
||||
* quality and performance of the Covered Software is with You. *
|
||||
* Should any Covered Software prove defective in any respect, You *
|
||||
* (not any Contributor) assume the cost of any necessary servicing, *
|
||||
* repair, or correction. This disclaimer of warranty constitutes an *
|
||||
* essential part of this License. No use of any Covered Software is *
|
||||
* authorized under this License except under this disclaimer. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 7. Limitation of Liability *
|
||||
* -------------------------- *
|
||||
* *
|
||||
* Under no circumstances and under no legal theory, whether tort *
|
||||
* (including negligence), contract, or otherwise, shall any *
|
||||
* Contributor, or anyone who distributes Covered Software as *
|
||||
* permitted above, be liable to You for any direct, indirect, *
|
||||
* special, incidental, or consequential damages of any character *
|
||||
* including, without limitation, damages for lost profits, loss of *
|
||||
* goodwill, work stoppage, computer failure or malfunction, or any *
|
||||
* and all other commercial damages or losses, even if such party *
|
||||
* shall have been informed of the possibility of such damages. This *
|
||||
* limitation of liability shall not apply to liability for death or *
|
||||
* personal injury resulting from such party's negligence to the *
|
||||
* extent applicable law prohibits such limitation. Some *
|
||||
* jurisdictions do not allow the exclusion or limitation of *
|
||||
* incidental or consequential damages, so this exclusion and *
|
||||
* limitation may not apply to You. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
8. Litigation
|
||||
-------------
|
||||
|
||||
Any litigation relating to this License may be brought only in the
|
||||
courts of a jurisdiction where the defendant maintains its principal
|
||||
place of business and such litigation shall be governed by laws of that
|
||||
jurisdiction, without reference to its conflict-of-law provisions.
|
||||
Nothing in this Section shall prevent a party's ability to bring
|
||||
cross-claims or counter-claims.
|
||||
|
||||
9. Miscellaneous
|
||||
----------------
|
||||
|
||||
This License represents the complete agreement concerning the subject
|
||||
matter hereof. If any provision of this License is held to be
|
||||
unenforceable, such provision shall be reformed only to the extent
|
||||
necessary to make it enforceable. Any law or regulation which provides
|
||||
that the language of a contract shall be construed against the drafter
|
||||
shall not be used to construe this License against a Contributor.
|
||||
|
||||
10. Versions of the License
|
||||
---------------------------
|
||||
|
||||
10.1. New Versions
|
||||
|
||||
Mozilla Foundation is the license steward. Except as provided in Section
|
||||
10.3, no one other than the license steward has the right to modify or
|
||||
publish new versions of this License. Each version will be given a
|
||||
distinguishing version number.
|
||||
|
||||
10.2. Effect of New Versions
|
||||
|
||||
You may distribute the Covered Software under the terms of the version
|
||||
of the License under which You originally received the Covered Software,
|
||||
or under the terms of any subsequent version published by the license
|
||||
steward.
|
||||
|
||||
10.3. Modified Versions
|
||||
|
||||
If you create software not governed by this License, and you want to
|
||||
create a new license for such software, you may create and use a
|
||||
modified version of this License if you rename the license and remove
|
||||
any references to the name of the license steward (except to note that
|
||||
such modified license differs from this License).
|
||||
|
||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
||||
Licenses
|
||||
|
||||
If You choose to distribute Source Code Form that is Incompatible With
|
||||
Secondary Licenses under the terms of this version of the License, the
|
||||
notice described in Exhibit B of this License must be attached.
|
||||
|
||||
Exhibit A - Source Code Form License Notice
|
||||
-------------------------------------------
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular
|
||||
file, then You may include the notice in a location (such as a LICENSE
|
||||
file in a relevant directory) where a recipient would be likely to look
|
||||
for such a notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
|
||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
||||
---------------------------------------------------------
|
||||
|
||||
This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
defined by the Mozilla Public License, v. 2.0.
|
||||
21
desktop-extensions/gnome-45/README.md
Normal file
21
desktop-extensions/gnome-45/README.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# asusctl
|
||||
|
||||
Requires `asusd` to be installed and running.
|
||||
|
||||
## build and install
|
||||
|
||||
```
|
||||
npm install
|
||||
npm run build && gnome-extensions install asusctl-gnome@asus-linux.org.zip --force
|
||||
npm run build && gnome-extensions enable asusctl-gnome@asus-linux.org.zip
|
||||
```
|
||||
|
||||
You will need to restart Gnome after installing or updating
|
||||
|
||||
## development
|
||||
|
||||
```
|
||||
npm run build
|
||||
gnome-extensions install asusctl-gnome@asus-linux.org.zip --force
|
||||
MUTTER_DEBUG_DUMMY_MODE_SPECS=1366x768 dbus-run-session -- gnome-shell --nested --wayland
|
||||
```
|
||||
67
desktop-extensions/gnome-45/esbuild.js
Normal file
67
desktop-extensions/gnome-45/esbuild.js
Normal file
@@ -0,0 +1,67 @@
|
||||
import { build } from "esbuild";
|
||||
import { exec } from "child_process";
|
||||
import { copyFileSync, cpSync } from "fs";
|
||||
import { resolve, dirname } from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import AdmZip from "adm-zip";
|
||||
import metadata from "./src/metadata.json" assert { type: "json" };
|
||||
|
||||
build({
|
||||
entryPoints: ["src/extension.ts"],
|
||||
outdir: "dist",
|
||||
bundle: true,
|
||||
// Do not remove the functions `enable()`, `disable()` and `init()`
|
||||
treeShaking: false,
|
||||
// firefox60 // Since GJS 1.53.90
|
||||
// firefox68 // Since GJS 1.63.90
|
||||
// firefox78 // Since GJS 1.65.90
|
||||
// firefox91 // Since GJS 1.71.1
|
||||
// firefox102 // Since GJS 1.73.2
|
||||
target: "firefox102",
|
||||
//platform: "neutral",
|
||||
platform: "node",
|
||||
// mainFields: ['main'],
|
||||
// conditions: ['require', 'default'],
|
||||
format: "esm",
|
||||
external: ["gi://*", "resource://*", "system", "gettext", "cairo"],
|
||||
}).then(() => {
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
|
||||
const metaSrc = resolve(__dirname, "src/metadata.json");
|
||||
const metaDist = resolve(__dirname, "dist/metadata.json");
|
||||
const schemaSrc = resolve(__dirname, "schemas");
|
||||
const schemaDist = resolve(__dirname, "dist/schemas");
|
||||
const dbusXmlSrc = resolve(__dirname, "../../bindings/dbus-xml");
|
||||
const dbusXmlDist = resolve(__dirname, "dist/resources/dbus");
|
||||
const zipFilename = `${metadata.uuid}.zip`;
|
||||
const zipDist = resolve(__dirname, zipFilename);
|
||||
|
||||
exec("glib-compile-schemas schemas/", (error, stdout, stderr) => {
|
||||
console.log("stdout: " + stdout);
|
||||
console.log("stderr: " + stderr);
|
||||
});
|
||||
|
||||
copyFileSync(metaSrc, metaDist);
|
||||
|
||||
cpSync(schemaSrc, schemaDist, { recursive: true }, (err) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
}
|
||||
});
|
||||
|
||||
cpSync(dbusXmlSrc, dbusXmlDist, { recursive: true }, (err) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
}
|
||||
});
|
||||
|
||||
const zip = new AdmZip();
|
||||
zip.addLocalFolder(resolve(__dirname, "dist"));
|
||||
zip.writeZip(zipDist);
|
||||
|
||||
console.log(`Build complete. Zip file: ${zipFilename}\n`);
|
||||
console.log(`Install with: gnome-extensions install ${zipFilename}`);
|
||||
console.log(`Update with: gnome-extensions install ${zipFilename} --force`);
|
||||
console.log(`Enable with: gnome-extensions enable ${metadata.uuid} --user`);
|
||||
});
|
||||
51
desktop-extensions/gnome-45/generate.sh
Executable file
51
desktop-extensions/gnome-45/generate.sh
Executable file
@@ -0,0 +1,51 @@
|
||||
#!/bin/bash
|
||||
|
||||
## Script to initialise dev-environment (types)
|
||||
gv="44"
|
||||
wd=${PWD}
|
||||
|
||||
# cleanup
|
||||
rm -rf @types
|
||||
|
||||
# generate GJS from gir (this does not include the extensions)
|
||||
echo "Generating GJS types from gir.."
|
||||
npx ts-for-gir generate Shell-12 St-12 Gtk-4.0 \
|
||||
-g /usr/share/gir-1.0 \
|
||||
-g /usr/share/gnome-shell \
|
||||
-g /usr/share/gnome-shell/gir-1.0 \
|
||||
-g /usr/lib64/mutter-12 \
|
||||
-t esm -o @types/Gjs
|
||||
|
||||
# get latest js (44) in this case and create the types for it
|
||||
echo "Generating GJS Extension (Gex) types from extension source.."
|
||||
mkdir -p ./_tmp/
|
||||
cd ./_tmp
|
||||
wget -q -O gnome-shell-js-${gv}.tar.gz https://gitlab.gnome.org/GNOME/gnome-shell/-/archive/gnome-${gv}/gnome-shell-gnome-${gv}.tar.gz?path=js
|
||||
tar xf gnome-shell-js-${gv}.tar.gz
|
||||
cd gnome-shell-gnome-${gv}-js
|
||||
cat >tsconfig.json <<EOL
|
||||
{
|
||||
"include": ["js/ui/*"],
|
||||
"exclude": [
|
||||
"js/ui/shellDBus.js",
|
||||
"node_modules",
|
||||
"**/node_modules/*"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"declaration": true,
|
||||
"emitDeclarationOnly": true,
|
||||
"outDir": "gex-types",
|
||||
"declarationMap": true,
|
||||
"lib": ["es2019"]
|
||||
}
|
||||
}
|
||||
EOL
|
||||
npx tsc
|
||||
cd ${wd}
|
||||
mv ./_tmp/gnome-shell-gnome-${gv}-js/gex-types @types/Gex
|
||||
# rm -rf ./_tmp/
|
||||
|
||||
echo "done."
|
||||
|
||||
exit 0
|
||||
2747
desktop-extensions/gnome-45/package-lock.json
generated
Normal file
2747
desktop-extensions/gnome-45/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
55
desktop-extensions/gnome-45/package.json
Normal file
55
desktop-extensions/gnome-45/package.json
Normal file
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"name": "asusctl-gnome",
|
||||
"version": "5.0.0-RC1",
|
||||
"description": "asusctl-gnome a gnome extension exposing some of the base features of asusd in a helpful and easy to use way",
|
||||
"type": "module",
|
||||
"main": "dist/extension.js",
|
||||
"scripts": {
|
||||
"clear": "rm -rf dist",
|
||||
"compile": "tsc --build tsconfig.json",
|
||||
"build:app": "node esbuild.js",
|
||||
"build": "yarn run clear && yarn run build:app",
|
||||
"validate": "tsc --noEmit",
|
||||
"generate:gir-types": "ts-for-gir generate",
|
||||
"check:types": "tsc --build tsconfig.types.json",
|
||||
"lint": "eslint .",
|
||||
"format": "prettier . -w"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@girs/gnome-shell": "^45.0.0-beta2",
|
||||
"@typescript-eslint/eslint-plugin": "^5.60.1",
|
||||
"@typescript-eslint/parser": "^5.60.1",
|
||||
"adm-zip": "^0.5.10",
|
||||
"esbuild": "^0.19.5",
|
||||
"eslint": "^8.51.0",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"prettier": "^3.0.3",
|
||||
"typescript": "^5.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@girs/gjs": "^3.2.5",
|
||||
"@girs/gobject-2.0": "^2.78.0-3.2.5",
|
||||
"@girs/st-13": "^13.0.0-3.2.5"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+ssh://git@gitlab.com/asus-linux/asusctl.git"
|
||||
},
|
||||
"keywords": [
|
||||
"gnome-shell",
|
||||
"extension",
|
||||
"asusctl",
|
||||
"asus",
|
||||
"rog",
|
||||
"gnome",
|
||||
"gjs",
|
||||
"typescript"
|
||||
],
|
||||
"author": "Armas Spann, Marco Laux, Luke Jones",
|
||||
"license": "MPL-2",
|
||||
"bugs": {
|
||||
"url": "https://gitlab.com/asus-linux/asusctl/issues"
|
||||
},
|
||||
"homepage": "https://gitlab.com/asus-linux/asusctl/desktop-extensions/gnome#readme"
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<schemalist gettext-domain="AsusctlGnomeExtension">
|
||||
<schema id="org.gnome.shell.extensions.asusctl-gnome" path="/org/gnome/shell/extensions/asusctl-gnome/" >
|
||||
<key type="b" name="mini-led-enabled">
|
||||
<default>false</default>
|
||||
</key>
|
||||
<key type="b" name="panel-od-enabled">
|
||||
<default>false</default>
|
||||
</key>
|
||||
<key type="b" name="anime-power">
|
||||
<default>false</default>
|
||||
</key>
|
||||
<key type="b" name="anime-builtins">
|
||||
<default>false</default>
|
||||
</key>
|
||||
<key name="charge-level" type="u">
|
||||
<range min="20" max="100"/>
|
||||
<default>100</default>
|
||||
</key>
|
||||
<key type="s" name="primary-quickmenu-toggle">
|
||||
<default>"mini-led"</default>
|
||||
</key>
|
||||
</schema>
|
||||
</schemalist>
|
||||
1
desktop-extensions/gnome-45/src/bindings
Symbolic link
1
desktop-extensions/gnome-45/src/bindings
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../bindings/ts
|
||||
127
desktop-extensions/gnome-45/src/extension.ts
Normal file
127
desktop-extensions/gnome-45/src/extension.ts
Normal file
@@ -0,0 +1,127 @@
|
||||
import { Extension, gettext as _ } from "@girs/gnome-shell/extensions/extension";
|
||||
import * as platform from "./bindings/platform";
|
||||
import { AsusQuickToggle } from "./modules/rog_quick_toggle";
|
||||
import { AsusMenuToggle } from "./modules/rog_menu_toggle";
|
||||
import { AsusIndicator } from "./modules/rog_indicator";
|
||||
import { AsusSlider } from "./modules/rog_slider_100pc";
|
||||
import { FeatureMenuToggle } from "./modules/quick_menus/laptop_features";
|
||||
import { DbusBase } from "./modules/dbus_proxy";
|
||||
import { main } from "@girs/gnome-shell/ui";
|
||||
|
||||
export const uuid = "asusctl-gnome@asus-linux.org";
|
||||
export default class AsusExtension extends Extension {
|
||||
// public dbus_aura: AuraDbus = new AuraDbus;
|
||||
// public dbus_anime: AnimeDbus = new AnimeDbus;
|
||||
public dbus_platform: DbusBase | undefined;
|
||||
public dbus_anime: DbusBase | undefined;
|
||||
|
||||
private individual = false;
|
||||
public supported_properties!: platform.Properties;
|
||||
public supported_interfaces: string[] = [];
|
||||
private feature_menu = null;
|
||||
private panel_od = null;
|
||||
private mini_led = null;
|
||||
private anime_display = null;
|
||||
private anime_builtins = null;
|
||||
private charge_thres = null;
|
||||
// private _feature: typeof FeatureMenuToggle;
|
||||
|
||||
async enable() {
|
||||
log(this.path);
|
||||
|
||||
if (this.dbus_platform == undefined) {
|
||||
this.dbus_platform = new DbusBase("org-asuslinux-platform-4.xml", "/org/asuslinux/Platform");
|
||||
await this.dbus_platform.start();
|
||||
}
|
||||
|
||||
if (this.dbus_anime == undefined) {
|
||||
this.dbus_anime = new DbusBase("org-asuslinux-anime-4.xml", "/org/asuslinux/Anime");
|
||||
await this.dbus_anime.start();
|
||||
}
|
||||
|
||||
this.supported_interfaces = this.dbus_platform?.proxy.SupportedInterfacesSync()[0];
|
||||
this.supported_properties = this.dbus_platform?.proxy.SupportedPropertiesSync()[0];
|
||||
log(this.supported_interfaces);
|
||||
log(this.supported_properties);
|
||||
|
||||
// new AsusIndicator("selection-mode-symbolic", "mini-led-enabled");
|
||||
// new AsusIndicator("selection-mode-symbolic", "panel-od-enabled");
|
||||
|
||||
if (!this.individual) {
|
||||
if (this.feature_menu == null)
|
||||
this.feature_menu = new FeatureMenuToggle(this.dbus_platform, this.dbus_anime);
|
||||
} else {
|
||||
if (this.supported_properties.includes("PanelOd") && this.dbus_platform.proxy.PanelOd != null)
|
||||
if (this.panel_od == null) {
|
||||
this.panel_od = new AsusQuickToggle(
|
||||
this.dbus_platform,
|
||||
"PanelOd",
|
||||
"panel-od-enabled",
|
||||
"Panel Overdrive",
|
||||
);
|
||||
}
|
||||
|
||||
if (this.supported_properties.includes("MiniLed") && this.dbus_platform.proxy.MiniLed != null)
|
||||
if (this.mini_led == null) {
|
||||
this.mini_led = new AsusQuickToggle(
|
||||
this.dbus_platform,
|
||||
"MiniLed",
|
||||
"mini-led-enabled",
|
||||
"Mini-LED",
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
this.supported_interfaces.includes("Anime") &&
|
||||
this.dbus_anime.proxy.EnableDisplay != null
|
||||
)
|
||||
if (this.anime_display == null) {
|
||||
this.anime_display = new AsusQuickToggle(
|
||||
this.dbus_anime,
|
||||
"EnableDisplay",
|
||||
"anime-power",
|
||||
"AniMe Display",
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
this.supported_interfaces.includes("Anime") &&
|
||||
this.dbus_anime.proxy.BuiltinsEnabled != null
|
||||
)
|
||||
if (this.anime_builtins == null) {
|
||||
this.anime_builtins = new AsusQuickToggle(
|
||||
this.dbus_anime,
|
||||
"BuiltinsEnabled",
|
||||
"anime-builtins",
|
||||
"Use builtins",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
this.supported_properties.includes("ChargeControlEndThreshold") &&
|
||||
this.dbus_platform.proxy.ChargeControlEndThreshold != null
|
||||
)
|
||||
if (this.charge_thres == null) {
|
||||
this.charge_thres = new AsusSlider(
|
||||
this.dbus_platform,
|
||||
"ChargeControlEndThreshold",
|
||||
"charge-level",
|
||||
"Charge Level",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
disable() {
|
||||
this.dbus_platform?.stop();
|
||||
this.dbus_anime?.stop();
|
||||
|
||||
this.feature_menu?.destroy();
|
||||
feature_menu?.destroy();
|
||||
panel_od?.destroy();
|
||||
mini_led?.destroy();
|
||||
anime_display?.destroy();
|
||||
anime_builtins?.destroy();
|
||||
charge_thres?.destroy();
|
||||
}
|
||||
}
|
||||
9
desktop-extensions/gnome-45/src/metadata.json
Normal file
9
desktop-extensions/gnome-45/src/metadata.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "asusctl-gnome",
|
||||
"description": "asusctl-gnome a gnome extension exposing some of the base features of asusd in a helpful and easy to use way",
|
||||
"uuid": "asusctl-gnome@asus-linux.org",
|
||||
"uuid-dev": "asusctl-gnome-dev@asus-linux.org",
|
||||
"settings-schema": "org.gnome.shell.extensions.asusctl-gnome",
|
||||
"version": "4.3.2",
|
||||
"shell-version": ["45"]
|
||||
}
|
||||
98
desktop-extensions/gnome-45/src/modules/dbus/animatrix.ts
Normal file
98
desktop-extensions/gnome-45/src/modules/dbus/animatrix.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
import { DbusBase } from "../dbus_proxy";
|
||||
import {
|
||||
DeviceState,
|
||||
AnimBooting,
|
||||
Brightness,
|
||||
AnimAwake,
|
||||
AnimSleeping,
|
||||
AnimShutdown,
|
||||
} from "../../bindings/anime";
|
||||
|
||||
export class AnimeDbus extends DbusBase {
|
||||
deviceState: DeviceState = {
|
||||
display_enabled: false,
|
||||
display_brightness: Brightness.Med,
|
||||
builtin_anims_enabled: false,
|
||||
builtin_anims: {
|
||||
boot: AnimBooting.GlitchConstruction,
|
||||
awake: AnimAwake.BinaryBannerScroll,
|
||||
sleep: AnimSleeping.BannerSwipe,
|
||||
shutdown: AnimShutdown.GlitchOut,
|
||||
},
|
||||
off_when_unplugged: false,
|
||||
off_when_suspended: false,
|
||||
off_when_lid_closed: false,
|
||||
};
|
||||
|
||||
// TODO: interface or something to enforce requirement of "sync()" method
|
||||
public notifyAnimeStateSubscribers: any[] = [];
|
||||
|
||||
constructor() {
|
||||
super("org-asuslinux-anime-4", "/org/asuslinux/Anime");
|
||||
}
|
||||
|
||||
_parseData(data: any) {
|
||||
if (data.length > 0) {
|
||||
this.deviceState.display_enabled = data[0];
|
||||
this.deviceState.display_brightness = Brightness[data[1] as Brightness];
|
||||
this.deviceState.builtin_anims_enabled = data[2];
|
||||
this.deviceState.builtin_anims.boot = AnimBooting[data[3][0] as AnimBooting];
|
||||
this.deviceState.builtin_anims.awake = AnimAwake[data[3][1] as AnimAwake];
|
||||
this.deviceState.builtin_anims.sleep = AnimSleeping[data[3][2] as AnimSleeping];
|
||||
this.deviceState.builtin_anims.shutdown = AnimShutdown[data[3][3] as AnimShutdown];
|
||||
this.deviceState.off_when_unplugged = data[4];
|
||||
this.deviceState.off_when_suspended = data[5];
|
||||
this.deviceState.off_when_lid_closed = data[6];
|
||||
}
|
||||
}
|
||||
|
||||
public getDeviceState() {
|
||||
if (this.isRunning()) {
|
||||
try {
|
||||
// janky shit going on with DeviceStateSync
|
||||
this._parseData(this.dbus_proxy.DeviceStateSync());
|
||||
//@ts-ignore
|
||||
log("Anime Matrix: display_enabled: " + this.deviceState.display_enabled);
|
||||
//@ts-ignore
|
||||
log("Anime Matrix: display_brightness: " + this.deviceState.display_brightness);
|
||||
//@ts-ignore
|
||||
log("Anime Matrix: builtin_anims_enabled: " + this.deviceState.builtin_anims_enabled);
|
||||
//@ts-ignore
|
||||
log("Anime Matrix: builtin_anims: " + this.deviceState.builtin_anims);
|
||||
//@ts-ignore
|
||||
log("Anime Matrix: off_when_unplugged: " + this.deviceState.off_when_unplugged);
|
||||
//@ts-ignore
|
||||
log("Anime Matrix: off_when_suspended: " + this.deviceState.off_when_suspended);
|
||||
//@ts-ignore
|
||||
log("Anime Matrix: off_when_lid_closed: " + this.deviceState.off_when_lid_closed);
|
||||
} catch (e) {
|
||||
//@ts-ignore
|
||||
log("Failed to fetch DeviceState!", e);
|
||||
}
|
||||
}
|
||||
return this.deviceState;
|
||||
}
|
||||
|
||||
async start() {
|
||||
await super.start();
|
||||
this.getDeviceState();
|
||||
|
||||
this.dbus_proxy.connectSignal(
|
||||
"NotifyDeviceState",
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(proxy: any = null, name: string, data: string) => {
|
||||
if (proxy) {
|
||||
// idiot xml parsing mneans the get is not nested while this is
|
||||
this._parseData(data[0]);
|
||||
this.notifyAnimeStateSubscribers.forEach((sub) => {
|
||||
sub.sync();
|
||||
});
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
async stop() {
|
||||
await super.stop();
|
||||
}
|
||||
}
|
||||
300
desktop-extensions/gnome-45/src/modules/dbus/aura.ts
Normal file
300
desktop-extensions/gnome-45/src/modules/dbus/aura.ts
Normal file
@@ -0,0 +1,300 @@
|
||||
import {
|
||||
AuraDevRog1,
|
||||
AuraDevTuf,
|
||||
AuraDevice,
|
||||
AuraEffect,
|
||||
AuraModeNum,
|
||||
AuraPower,
|
||||
AuraPowerDev,
|
||||
AuraZone,
|
||||
Direction,
|
||||
PowerZones,
|
||||
Speed,
|
||||
} from "../../bindings/aura";
|
||||
import { DbusBase } from "./base";
|
||||
|
||||
export class AuraDbus extends DbusBase {
|
||||
public device: AuraDevice = AuraDevice.Unknown;
|
||||
public current_aura_mode: AuraModeNum = AuraModeNum.Static;
|
||||
public aura_modes: Map<AuraModeNum, AuraEffect> = new Map();
|
||||
public leds_powered: AuraPowerDev = {
|
||||
tuf: [],
|
||||
old_rog: [],
|
||||
rog: {
|
||||
keyboard: {
|
||||
zone: PowerZones.Keyboard,
|
||||
boot: false,
|
||||
awake: false,
|
||||
sleep: false,
|
||||
shutdown: false,
|
||||
},
|
||||
logo: {
|
||||
zone: PowerZones.Logo,
|
||||
boot: false,
|
||||
awake: false,
|
||||
sleep: false,
|
||||
shutdown: false,
|
||||
},
|
||||
lightbar: {
|
||||
zone: PowerZones.Lightbar,
|
||||
boot: false,
|
||||
awake: false,
|
||||
sleep: false,
|
||||
shutdown: false,
|
||||
},
|
||||
lid: {
|
||||
zone: PowerZones.Lid,
|
||||
boot: false,
|
||||
awake: false,
|
||||
sleep: false,
|
||||
shutdown: false,
|
||||
},
|
||||
rear_glow: {
|
||||
zone: PowerZones.RearGlow,
|
||||
boot: false,
|
||||
awake: false,
|
||||
sleep: false,
|
||||
shutdown: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
// TODO: interface or something to enforce requirement of "sync()" method
|
||||
public notifyAuraModeSubscribers: any[] = [];
|
||||
public notifyAuraPowerSubscribers: any[] = [];
|
||||
|
||||
constructor() {
|
||||
super("org-asuslinux-aura-4", "/org/asuslinux/Aura");
|
||||
}
|
||||
|
||||
public getDevice() {
|
||||
if (this.isRunning()) {
|
||||
try {
|
||||
this.device = AuraDevice[this.dbus_proxy.DeviceTypeSync() as AuraDevice];
|
||||
//@ts-ignore
|
||||
log("LED device: " + this.device);
|
||||
} catch (e) {
|
||||
//@ts-ignore
|
||||
log("Failed to fetch supported functionalities", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_parsePowerStates(data: any[]) {
|
||||
const power: AuraPowerDev = this.leds_powered;
|
||||
|
||||
power.tuf = data[0].map((value: string) => {
|
||||
return AuraDevTuf[value as AuraDevTuf];
|
||||
});
|
||||
power.old_rog = data[1].map((value: string) => {
|
||||
return AuraDevRog1[value as AuraDevRog1];
|
||||
});
|
||||
power.rog = {
|
||||
keyboard: {
|
||||
zone: PowerZones[data[2][0][0] as PowerZones],
|
||||
boot: data[2][0][1],
|
||||
awake: data[2][0][2],
|
||||
sleep: data[2][0][3],
|
||||
shutdown: data[2][0][4],
|
||||
},
|
||||
logo: {
|
||||
zone: PowerZones[data[2][1][0] as PowerZones],
|
||||
boot: data[2][1][1],
|
||||
awake: data[2][1][2],
|
||||
sleep: data[2][1][3],
|
||||
shutdown: data[2][1][4],
|
||||
},
|
||||
lightbar: {
|
||||
zone: PowerZones[data[2][2][0] as PowerZones],
|
||||
boot: data[2][2][1],
|
||||
awake: data[2][2][2],
|
||||
sleep: data[2][2][3],
|
||||
shutdown: data[2][2][4],
|
||||
},
|
||||
lid: {
|
||||
zone: PowerZones[data[2][3][0] as PowerZones],
|
||||
boot: data[2][3][1],
|
||||
awake: data[2][3][2],
|
||||
sleep: data[2][3][3],
|
||||
shutdown: data[2][3][4],
|
||||
},
|
||||
rear_glow: {
|
||||
zone: PowerZones[data[2][4][0] as PowerZones],
|
||||
boot: data[2][4][1],
|
||||
awake: data[2][4][2],
|
||||
sleep: data[2][4][3],
|
||||
shutdown: data[2][4][4],
|
||||
},
|
||||
};
|
||||
|
||||
return power;
|
||||
}
|
||||
|
||||
public getLedPower() {
|
||||
if (this.isRunning()) {
|
||||
try {
|
||||
const data = this.dbus_proxy.LedPowerSync();
|
||||
this.leds_powered = this._parsePowerStates(data);
|
||||
//@ts-ignore
|
||||
log("LED power tuf: " + this.leds_powered.tuf);
|
||||
//@ts-ignore
|
||||
log("LED power x1866: " + this.leds_powered.old_rog);
|
||||
//@ts-ignore
|
||||
log("LED power x19b6: " + this.leds_powered.rog);
|
||||
} catch (e) {
|
||||
//@ts-ignore
|
||||
log("Failed to fetch supported functionalities", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public getLedMode() {
|
||||
if (this.isRunning()) {
|
||||
try {
|
||||
this.current_aura_mode = AuraModeNum[this.dbus_proxy.LedModeSync() as AuraModeNum];
|
||||
//@ts-ignore
|
||||
log("Current LED mode:", this.current_aura_mode);
|
||||
} catch (e) {
|
||||
//@ts-ignore
|
||||
log("Failed to fetch supported functionalities", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public setLedMode(mode: AuraEffect) {
|
||||
if (this.isRunning()) {
|
||||
try {
|
||||
this.dbus_proxy.SetLedModeSync([
|
||||
mode.mode,
|
||||
mode.zone,
|
||||
[mode.colour1.r, mode.colour1.g, mode.colour1.b],
|
||||
[mode.colour2.r, mode.colour2.g, mode.colour2.b],
|
||||
mode.speed,
|
||||
mode.direction,
|
||||
]);
|
||||
} catch (e) {
|
||||
//@ts-ignore
|
||||
log("Failed to fetch supported functionalities", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_parseAuraEffect(data: any[]) {
|
||||
const aura: AuraEffect = {
|
||||
mode: AuraModeNum[data[0] as AuraModeNum],
|
||||
zone: AuraZone[data[1] as AuraZone],
|
||||
colour1: {
|
||||
r: parseInt(data[2][0]),
|
||||
g: parseInt(data[2][1]),
|
||||
b: parseInt(data[2][2]),
|
||||
},
|
||||
colour2: {
|
||||
r: parseInt(data[3][0]),
|
||||
g: parseInt(data[3][1]),
|
||||
b: parseInt(data[3][2]),
|
||||
},
|
||||
speed: Speed[data[4] as Speed],
|
||||
direction: Direction[data[5] as Direction],
|
||||
};
|
||||
return aura;
|
||||
}
|
||||
|
||||
// Return a list of the available modes, and the current settings for each
|
||||
public getLedModes() {
|
||||
// {'Breathe': ('Breathe', 'None', (166, 0, 0), (0, 0, 0), 'Med', 'Right'),
|
||||
// 'Comet': ('Comet', 'None', (166, 0, 0), (0, 0, 0), 'Med', 'Right'),
|
||||
// 'Static': ('Static', 'None', (78, 0, 0), (0, 0, 0), 'Med', 'Right'),
|
||||
// 'Strobe': ('Strobe', 'None', (166, 0, 0), (0, 0, 0), 'Med', 'Right')}
|
||||
if (this.isRunning()) {
|
||||
try {
|
||||
const _data = this.dbus_proxy.LedModesSync();
|
||||
for (const key in _data[0]) {
|
||||
const data = _data[0][key];
|
||||
const aura: AuraEffect = this._parseAuraEffect(data);
|
||||
this.aura_modes.set(AuraModeNum[key as AuraModeNum], aura);
|
||||
}
|
||||
|
||||
for (const [key, value] of this.aura_modes) {
|
||||
//@ts-ignore
|
||||
log(key, value.zone, value.colour1.r, value.speed, value.direction);
|
||||
}
|
||||
} catch (e) {
|
||||
//@ts-ignore
|
||||
log("Failed to fetch supported functionalities", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async start() {
|
||||
try {
|
||||
await super.start();
|
||||
this.getDevice();
|
||||
this.getLedPower();
|
||||
this.getLedMode();
|
||||
this.getLedModes();
|
||||
|
||||
//@ts-ignore
|
||||
log("Current LED mode data:", this.aura_modes.get(this.current_aura_mode)?.speed);
|
||||
|
||||
this.dbus_proxy.connectSignal("NotifyLed", (proxy: any = null, name: string, data: any) => {
|
||||
if (proxy) {
|
||||
const aura: AuraEffect = this._parseAuraEffect(data[0]);
|
||||
this.current_aura_mode = aura.mode;
|
||||
this.aura_modes.set(aura.mode, aura);
|
||||
//@ts-ignore
|
||||
log(
|
||||
"LED data has changed to ",
|
||||
aura.mode,
|
||||
aura.zone,
|
||||
aura.colour1.r,
|
||||
aura.speed,
|
||||
aura.direction,
|
||||
);
|
||||
this.notifyAuraModeSubscribers.forEach((sub) => {
|
||||
sub.sync();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.dbus_proxy.connectSignal(
|
||||
"NotifyPowerStates",
|
||||
(proxy: any = null, name: string, data: any) => {
|
||||
if (proxy) {
|
||||
const power: AuraPowerDev = this._parsePowerStates(data[0]);
|
||||
this.leds_powered = power;
|
||||
switch (this.device) {
|
||||
case AuraDevice.Tuf:
|
||||
//@ts-ignore
|
||||
log("LED power has changed to ", this.leds_powered.tuf);
|
||||
break;
|
||||
case AuraDevice.X1854:
|
||||
case AuraDevice.X1869:
|
||||
case AuraDevice.X18c6:
|
||||
//@ts-ignore
|
||||
log("LED power has changed to ", this.leds_powered.old_rog);
|
||||
break;
|
||||
case AuraDevice.X19b6:
|
||||
case AuraDevice.X1a30:
|
||||
//@ts-ignore
|
||||
log("LED power has changed to ", this.leds_powered.rog);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
//@ts-ignore
|
||||
log("LED power has changed to ", this.leds_powered.rog);
|
||||
this.notifyAuraPowerSubscribers.forEach((sub) => {
|
||||
sub.sync();
|
||||
});
|
||||
}
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
//@ts-ignore
|
||||
log("Supported DBus initialization failed!", e);
|
||||
}
|
||||
}
|
||||
|
||||
async stop() {
|
||||
await super.stop();
|
||||
}
|
||||
}
|
||||
64
desktop-extensions/gnome-45/src/modules/dbus_proxy.ts
Normal file
64
desktop-extensions/gnome-45/src/modules/dbus_proxy.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import { Extension, gettext as _ } from "@girs/gnome-shell/extensions/extension";
|
||||
import { Gio } from "@girs/gio-2.0";
|
||||
import { GLib } from "@girs/glib-2.0";
|
||||
import { imports } from "@girs/gjs";
|
||||
|
||||
// Reads the contents of a file contained in the global resources archive. The data
|
||||
// is returned as a string.
|
||||
export function getStringResource(path: string | null) {
|
||||
const data = Gio.resources_lookup_data(path, 0);
|
||||
return new TextDecoder().decode(data.get_data()?.buffer);
|
||||
}
|
||||
|
||||
export class DbusBase {
|
||||
proxy!: Gio.DBusProxy;
|
||||
connected = false;
|
||||
ifaceXml = "";
|
||||
dbus_path = "";
|
||||
|
||||
constructor(file_name: string, dbus_path: string) {
|
||||
let extensionObject = Extension.lookupByUUID("asusctl-gnome@asus-linux.org");
|
||||
const path = extensionObject?.path + "/resources/dbus/" + file_name;
|
||||
const [ok, data] = GLib.file_get_contents(path);
|
||||
if (!ok) {
|
||||
throw new Error("could not read interface file");
|
||||
}
|
||||
this.ifaceXml = imports.byteArray.toString(data);
|
||||
this.dbus_path = dbus_path;
|
||||
}
|
||||
|
||||
async start() {
|
||||
//@ts-ignore
|
||||
log(`Starting ${this.dbus_path} dbus module`);
|
||||
try {
|
||||
log(this.ifaceXml);
|
||||
this.proxy = Gio.DBusProxy.makeProxyWrapper(this.ifaceXml)(
|
||||
Gio.DBus.system,
|
||||
"org.asuslinux.Daemon",
|
||||
this.dbus_path,
|
||||
);
|
||||
|
||||
this.connected = true;
|
||||
//@ts-ignore
|
||||
log(`${this.dbus_path} client started successfully.`);
|
||||
} catch (e) {
|
||||
//@ts-ignore
|
||||
logError(`${this.xml_resource} dbus init failed!`, e);
|
||||
}
|
||||
}
|
||||
|
||||
async stop() {
|
||||
//@ts-ignore
|
||||
log(`Stopping ${this.xml_resource} dbus module`);
|
||||
|
||||
if (this.connected && this.proxy != undefined) {
|
||||
this.proxy.run_dispose();
|
||||
this.proxy = undefined;
|
||||
this.connected = false;
|
||||
}
|
||||
}
|
||||
|
||||
isRunning(): boolean {
|
||||
return this.connected;
|
||||
}
|
||||
}
|
||||
14
desktop-extensions/gnome-45/src/modules/helpers.ts
Normal file
14
desktop-extensions/gnome-45/src/modules/helpers.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import * as Main from "resource:///org/gnome/shell/ui/main.js";
|
||||
import { QuickToggle } from "resource:///org/gnome/shell/ui/quickSettings.js";
|
||||
|
||||
export function addQuickSettingsItems(items: [typeof QuickToggle], width = 1) {
|
||||
const QuickSettingsMenu = Main.panel.statusArea.quickSettings;
|
||||
items.forEach((item) => QuickSettingsMenu.menu.addItem(item, width));
|
||||
// Ensure the tile(s) are above the background apps menu
|
||||
for (const item of items) {
|
||||
QuickSettingsMenu.menu._grid.set_child_below_sibling(
|
||||
item,
|
||||
QuickSettingsMenu._backgroundApps.quickSettingsItems[0],
|
||||
);
|
||||
}
|
||||
}
|
||||
85
desktop-extensions/gnome-45/src/modules/quick_menus/aura.ts
Normal file
85
desktop-extensions/gnome-45/src/modules/quick_menus/aura.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
import { addQuickSettingsItems } from "../helpers";
|
||||
import { AuraDbus } from "../dbus/aura";
|
||||
import { AuraEffect, AuraModeNum } from "../../bindings/aura";
|
||||
import GObject from "gi://GObject";
|
||||
|
||||
import * as PopupMenu from "resource:///org/gnome/shell/ui/popupMenu.js";
|
||||
import * as QuickSettings from "resource:///org/gnome/shell/ui/quickSettings.js";
|
||||
|
||||
export const AuraMenuToggle = GObject.registerClass(
|
||||
class AuraMenuToggle extends QuickSettings.QuickMenuToggle {
|
||||
private _dbus_aura: AuraDbus;
|
||||
private _last_mode: AuraModeNum = AuraModeNum.Static;
|
||||
|
||||
constructor(dbus_aura: AuraDbus) {
|
||||
super({
|
||||
title: "Aura Modes",
|
||||
iconName: "selection-mode-symbolic",
|
||||
toggleMode: true,
|
||||
});
|
||||
this._dbus_aura = dbus_aura;
|
||||
|
||||
this.connectObject(this);
|
||||
|
||||
this.menu.setHeader("selection-mode-symbolic", this._dbus_aura.current_aura_mode);
|
||||
|
||||
this._itemsSection = new PopupMenu.PopupMenuSection();
|
||||
|
||||
this._dbus_aura.aura_modes.forEach((mode, key) => {
|
||||
this._itemsSection.addAction(
|
||||
key,
|
||||
() => {
|
||||
this._dbus_aura.setLedMode(mode);
|
||||
this.sync();
|
||||
},
|
||||
"",
|
||||
);
|
||||
});
|
||||
|
||||
this.menu.addMenuItem(this._itemsSection);
|
||||
|
||||
// Add an entry-point for more settings
|
||||
// this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||
// const settingsItem = this.menu.addAction("More Settings",
|
||||
// () => ExtensionUtils.openPrefs());
|
||||
// // Ensure the settings are unavailable when the screen is locked
|
||||
// settingsItem.visible = Main.sessionMode.allowSettings;
|
||||
// this.menu._settingsActions[Me.uuid] = settingsItem;
|
||||
|
||||
this.connectObject(
|
||||
"clicked",
|
||||
() => {
|
||||
let mode: AuraEffect | undefined;
|
||||
if (this._dbus_aura.current_aura_mode == AuraModeNum.Static) {
|
||||
mode = this._dbus_aura.aura_modes.get(this._last_mode);
|
||||
} else {
|
||||
mode = this._dbus_aura.aura_modes.get(AuraModeNum.Static);
|
||||
}
|
||||
if (mode != undefined) {
|
||||
this._dbus_aura.setLedMode(mode);
|
||||
this.sync();
|
||||
}
|
||||
},
|
||||
this,
|
||||
);
|
||||
|
||||
this._dbus_aura.notifyAuraModeSubscribers.push(this);
|
||||
this.sync();
|
||||
|
||||
addQuickSettingsItems([this]);
|
||||
}
|
||||
|
||||
sync() {
|
||||
const checked = this._dbus_aura.current_aura_mode != AuraModeNum.Static;
|
||||
this.title = this._dbus_aura.current_aura_mode;
|
||||
if (
|
||||
this._last_mode != this._dbus_aura.current_aura_mode &&
|
||||
this._dbus_aura.current_aura_mode != AuraModeNum.Static
|
||||
) {
|
||||
this._last_mode = this._dbus_aura.current_aura_mode;
|
||||
}
|
||||
|
||||
if (this.checked !== checked) this.set({ checked });
|
||||
}
|
||||
},
|
||||
);
|
||||
@@ -0,0 +1,216 @@
|
||||
import { Extension, gettext as _ } from "@girs/gnome-shell/extensions/extension";
|
||||
import { quickSettings, popupMenu } from "@girs/gnome-shell/ui";
|
||||
import { GObject } from "@girs/gobject-2.0";
|
||||
|
||||
import { DbusBase } from "../../modules/dbus_proxy";
|
||||
|
||||
import { addQuickSettingsItems } from "../helpers";
|
||||
|
||||
import * as AsusExtension from "../../extension";
|
||||
import * as platform from "../../bindings/platform";
|
||||
import { uuid } from "../../extension";
|
||||
import { AsusMenuToggle } from "../rog_menu_toggle";
|
||||
|
||||
export const FeatureMenuToggle = GObject.registerClass(
|
||||
class FeatureMenuToggle extends quickSettings.QuickMenuToggle {
|
||||
private dbus_platform: DbusBase;
|
||||
private dbus_anime: DbusBase;
|
||||
private last_selection = "mini-led";
|
||||
private supported_properties!: platform.Properties;
|
||||
private supported_interfaces: string[] = [];
|
||||
|
||||
private miniLed?: typeof AsusMenuToggle;
|
||||
private panelOd?: typeof AsusMenuToggle;
|
||||
private animeDisplayPower?: typeof AsusMenuToggle;
|
||||
private animePowersaveAnim?: typeof AsusMenuToggle;
|
||||
_itemsSection: popupMenu.PopupMenuSection;
|
||||
|
||||
constructor(dbus_platform: DbusBase, dbus_anime: DbusBase) {
|
||||
super({
|
||||
label: "Laptop",
|
||||
toggle_mode: true,
|
||||
icon_name: "selection-mode-symbolic",
|
||||
});
|
||||
this.label = "Laptop";
|
||||
this.title = "Laptop";
|
||||
this.dbus_platform = dbus_platform;
|
||||
this.dbus_anime = dbus_anime;
|
||||
|
||||
this.menu.setHeader("selection-mode-symbolic", "Laptop features");
|
||||
|
||||
this.last_selection = Extension.lookupByUUID(AsusExtension.uuid)
|
||||
?.getSettings()
|
||||
.get_string("primary-quickmenu-toggle")!;
|
||||
|
||||
this.supported_interfaces = this.dbus_platform?.proxy.SupportedInterfacesSync()[0];
|
||||
this.supported_properties = this.dbus_platform?.proxy.SupportedPropertiesSync()[0];
|
||||
|
||||
// TODO: temporary block
|
||||
if (this.last_selection == "mini-led" && !this.supported_properties.includes("MiniLed")) {
|
||||
this.last_selection = "panel-od";
|
||||
} else if (
|
||||
this.last_selection == "panel-od" &&
|
||||
!this.supported_properties.includes("PanelOd")
|
||||
) {
|
||||
this.last_selection = "anime-power";
|
||||
} else if (
|
||||
this.last_selection == "anime-power" &&
|
||||
!this.supported_interfaces.includes("Anime")
|
||||
) {
|
||||
this.last_selection = "mini-led";
|
||||
} else if (this.last_selection.length == 0) {
|
||||
this.last_selection = "panel-od";
|
||||
}
|
||||
|
||||
// AsusExtension.extension._settings.connect('changed::primary-quickmenu-toggle', this.sync);
|
||||
Extension.lookupByUUID(uuid)
|
||||
?.getSettings()
|
||||
.set_string("primary-quickmenu-toggle", this.last_selection);
|
||||
|
||||
this._itemsSection = new popupMenu.PopupMenuSection();
|
||||
if (this.supported_properties.includes("MiniLed")) {
|
||||
if (this.miniLed == null) {
|
||||
this.miniLed = new AsusMenuToggle(
|
||||
this.dbus_platform,
|
||||
"MiniLed",
|
||||
"mini-led-enabled",
|
||||
"Mini-LED Enabled",
|
||||
);
|
||||
this._itemsSection.addMenuItem(this.miniLed, 0);
|
||||
this.miniLed.toggle_callback = () => {
|
||||
this.last_selection = "mini-led";
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (this.supported_properties.includes("PanelOd")) {
|
||||
if (this.panelOd == null) {
|
||||
this.panelOd = new AsusMenuToggle(
|
||||
this.dbus_platform,
|
||||
"PanelOd",
|
||||
"panel-od-enabled",
|
||||
"Panel Overdrive Enabled",
|
||||
);
|
||||
this._itemsSection.addMenuItem(this.panelOd, 1);
|
||||
this.panelOd.toggle_callback = () => {
|
||||
this.last_selection = "panel-od";
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (this.supported_interfaces.includes("Anime")) {
|
||||
if (this.animeDisplayPower == null) {
|
||||
this.animeDisplayPower = new AsusMenuToggle(
|
||||
this.dbus_anime,
|
||||
"EnableDisplay",
|
||||
"anime-power",
|
||||
"AniMe Display Enabled",
|
||||
);
|
||||
this._itemsSection.addMenuItem(this.animeDisplayPower, 2);
|
||||
this.animeDisplayPower.toggle_callback = () => {
|
||||
this.last_selection = "anime-power";
|
||||
};
|
||||
}
|
||||
|
||||
if (this.animePowersaveAnim == null) {
|
||||
this.animePowersaveAnim = new AsusMenuToggle(
|
||||
this.dbus_anime,
|
||||
"BuiltinsEnabled",
|
||||
"anime-builtins",
|
||||
"AniMe Built-in Animations",
|
||||
);
|
||||
this._itemsSection.addMenuItem(this.animePowersaveAnim, 3);
|
||||
this.animePowersaveAnim.toggle_callback = () => {
|
||||
this.last_selection = "anime-builtins";
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
this.connectObject(
|
||||
"clicked",
|
||||
() => {
|
||||
this._toggle();
|
||||
},
|
||||
this,
|
||||
);
|
||||
|
||||
this.menu.addMenuItem(this._itemsSection, 0);
|
||||
|
||||
this.dbus_platform?.proxy.connect("g-properties-changed", (_proxy, changed, invalidated) => {
|
||||
//const properties = changed.deepUnpack();
|
||||
this.sync();
|
||||
});
|
||||
|
||||
this.dbus_anime?.proxy.connect("g-properties-changed", (_proxy, changed, invalidated) => {
|
||||
//const properties = changed.deepUnpack();
|
||||
this.sync();
|
||||
});
|
||||
|
||||
// // Add an entry-point for more extension._settings
|
||||
// this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||
// const settingsItem = this.menu.addAction("More Settings",
|
||||
// () => ExtensionUtils.openPrefs());
|
||||
// // Ensure the extension._settings are unavailable when the screen is locked
|
||||
// settingsItem.visible = Main.sessionMode.allowSettings;
|
||||
// this.menu._settingsActions[Me.uuid] = settingsItem;
|
||||
|
||||
this.sync();
|
||||
addQuickSettingsItems([this]);
|
||||
}
|
||||
|
||||
_toggle() {
|
||||
if (this.last_selection == "mini-led" && this.miniLed != null) {
|
||||
if (this.checked !== this.dbus_platform.proxy.MiniLed)
|
||||
this.dbus_platform.proxy.MiniLed = this.checked;
|
||||
}
|
||||
|
||||
if (this.last_selection == "panel-od" && this.panelOd != null) {
|
||||
if (this.checked !== this.dbus_platform.proxy.PanelOd) {
|
||||
this.dbus_platform.proxy.PanelOd = this.checked;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.last_selection == "anime-power" && this.animeDisplayPower != null) {
|
||||
if (this.checked !== this.dbus_anime.proxy.EnableDisplay)
|
||||
this.dbus_anime.proxy.EnableDisplay = this.checked;
|
||||
}
|
||||
|
||||
if (this.last_selection == "anime-builtins" && this.animePowersaveAnim != null) {
|
||||
if (this.checked !== this.dbus_anime.proxy.BuiltinsEnabled)
|
||||
this.dbus_anime.proxy.BuiltinsEnabled = this.checked;
|
||||
}
|
||||
}
|
||||
|
||||
sync() {
|
||||
let checked = false;
|
||||
if (this.last_selection == "mini-led" && this.miniLed != null) {
|
||||
this.title = this.miniLed.title;
|
||||
checked = this.dbus_platform.proxy.MiniLed;
|
||||
}
|
||||
|
||||
if (this.last_selection == "panel-od" && this.panelOd != null) {
|
||||
this.title = this.panelOd.title;
|
||||
checked = this.dbus_platform.proxy.PanelOd;
|
||||
}
|
||||
|
||||
if (this.last_selection == "anime-power" && this.animeDisplayPower != null) {
|
||||
this.title = this.animeDisplayPower.title;
|
||||
checked = this.dbus_anime.proxy.EnableDisplay;
|
||||
}
|
||||
|
||||
if (this.last_selection == "anime-builtins" && this.animePowersaveAnim != null) {
|
||||
this.title = this.animePowersaveAnim.title;
|
||||
checked = this.dbus_anime.proxy.BuiltinsEnabled;
|
||||
}
|
||||
|
||||
// if (this.animePowersaveAnim != null) {
|
||||
// }
|
||||
|
||||
if (this.checked !== checked) this.set({ checked });
|
||||
}
|
||||
|
||||
destroy() {
|
||||
// this.panelOd?.destroy();
|
||||
}
|
||||
},
|
||||
);
|
||||
26
desktop-extensions/gnome-45/src/modules/rog_indicator.ts
Normal file
26
desktop-extensions/gnome-45/src/modules/rog_indicator.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { Extension, gettext as _ } from "@girs/gnome-shell/extensions/extension";
|
||||
import { quickSettings, main } from "@girs/gnome-shell/ui";
|
||||
import { Gio } from "@girs/gio-2.0";
|
||||
import { GObject } from "@girs/gobject-2.0";
|
||||
import { uuid } from "../extension";
|
||||
//import { DbusBase } from '../dbus_proxy';
|
||||
|
||||
export const AsusIndicator = GObject.registerClass(
|
||||
class AsusIndicator extends quickSettings.SystemIndicator {
|
||||
private _indicator: any;
|
||||
private _settings: Gio.Settings | undefined;
|
||||
|
||||
constructor(icon_name: string, setting_name: string) {
|
||||
super();
|
||||
// Create an icon for the indicator
|
||||
this._indicator = this._addIndicator();
|
||||
this._indicator.icon_name = icon_name;
|
||||
|
||||
// Showing an indicator when the feature is enabled
|
||||
this._settings = Extension.lookupByUUID(uuid)?.getSettings();
|
||||
this._settings?.bind(setting_name, this._indicator, "visible", Gio.SettingsBindFlags.DEFAULT);
|
||||
|
||||
main.panel.statusArea.quickSettings.addExternalIndicator(this);
|
||||
}
|
||||
},
|
||||
);
|
||||
50
desktop-extensions/gnome-45/src/modules/rog_menu_toggle.ts
Normal file
50
desktop-extensions/gnome-45/src/modules/rog_menu_toggle.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { popupMenu } from "@girs/gnome-shell/ui";
|
||||
import { GObject } from "@girs/gobject-2.0";
|
||||
import { DbusBase } from "./dbus_proxy";
|
||||
|
||||
export const AsusMenuToggle = GObject.registerClass(
|
||||
class AsusMenuToggle extends popupMenu.PopupSwitchMenuItem {
|
||||
public title: string = "";
|
||||
dbus!: DbusBase;
|
||||
prop_name: string = "";
|
||||
public toggle_callback = () => {};
|
||||
|
||||
constructor(dbus: DbusBase, prop_name: string, setting: string, title: string) {
|
||||
super(title, true);
|
||||
this.prop_name = prop_name;
|
||||
this.dbus = dbus;
|
||||
this.title = title;
|
||||
|
||||
this.dbus?.proxy.connect("g-properties-changed", (_proxy, changed, invalidated) => {
|
||||
const properties = changed.deepUnpack();
|
||||
// .find() fails on some shit for some reason
|
||||
for (const v of Object.entries(properties)) {
|
||||
if (v[0] == this.prop_name) {
|
||||
this.sync();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.connectObject("toggled", () => this._toggleMode(), this);
|
||||
|
||||
this.connect("destroy", () => {
|
||||
this.destroy();
|
||||
});
|
||||
|
||||
this.sync();
|
||||
}
|
||||
|
||||
_toggleMode() {
|
||||
// hacky shit, index to get base object property and set it
|
||||
const state = this.dbus.proxy[this.prop_name];
|
||||
if (this.state !== state) this.dbus.proxy[this.prop_name] = this.state;
|
||||
this.toggle_callback();
|
||||
}
|
||||
|
||||
sync() {
|
||||
const state = this.dbus.proxy[this.prop_name];
|
||||
if (this.state !== state) this.setToggleState(state);
|
||||
}
|
||||
},
|
||||
);
|
||||
64
desktop-extensions/gnome-45/src/modules/rog_quick_toggle.ts
Normal file
64
desktop-extensions/gnome-45/src/modules/rog_quick_toggle.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import { Extension, gettext as _ } from "@girs/gnome-shell/extensions/extension";
|
||||
import { addQuickSettingsItems } from "./helpers";
|
||||
import { quickSettings } from "@girs/gnome-shell/ui";
|
||||
import { Gio } from "@girs/gio-2.0";
|
||||
import { GObject } from "@girs/gobject-2.0";
|
||||
import { uuid } from "../extension";
|
||||
import { DbusBase } from "./dbus_proxy";
|
||||
|
||||
export const AsusQuickToggle = GObject.registerClass(
|
||||
class AsusQuickToggle extends quickSettings.QuickToggle {
|
||||
dbus!: DbusBase;
|
||||
prop_name: string = "";
|
||||
public toggle_callback = () => {};
|
||||
|
||||
constructor(dbus: DbusBase, prop_name: string, setting: string, title: string) {
|
||||
super({
|
||||
label: title,
|
||||
icon_name: "selection-mode-symbolic",
|
||||
toggle_mode: true,
|
||||
});
|
||||
this.prop_name = prop_name;
|
||||
this.label = title;
|
||||
this.dbus = dbus;
|
||||
|
||||
this.dbus?.proxy.connect("g-properties-changed", (_proxy, changed, invalidated) => {
|
||||
const properties = changed.deepUnpack();
|
||||
// .find() fails on some shit for some reason
|
||||
for (const v of Object.entries(properties)) {
|
||||
if (v[0] == this.prop_name) {
|
||||
const checked = v[1].unpack();
|
||||
if (this.checked !== checked) this.checked = checked;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.connectObject("clicked", () => this._toggleMode(), this);
|
||||
|
||||
this.connect("destroy", () => {
|
||||
this.destroy();
|
||||
});
|
||||
|
||||
Extension.lookupByUUID(uuid)
|
||||
?.getSettings()
|
||||
.bind(setting, this, "checked", Gio.SettingsBindFlags.DEFAULT);
|
||||
|
||||
this.sync();
|
||||
|
||||
addQuickSettingsItems([this]);
|
||||
}
|
||||
|
||||
_toggleMode() {
|
||||
// hacky shit, index to get base object property and set it
|
||||
const checked = this.dbus.proxy[this.prop_name];
|
||||
if (this.checked !== checked) this.dbus.proxy[this.prop_name] = this.checked;
|
||||
this.toggle_callback();
|
||||
}
|
||||
|
||||
sync() {
|
||||
const checked = this.dbus.proxy[this.prop_name];
|
||||
if (this.checked !== checked) this.set({ checked });
|
||||
}
|
||||
},
|
||||
);
|
||||
75
desktop-extensions/gnome-45/src/modules/rog_slider_100pc.ts
Normal file
75
desktop-extensions/gnome-45/src/modules/rog_slider_100pc.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
import { Extension, gettext as _ } from "@girs/gnome-shell/extensions/extension";
|
||||
import { addQuickSettingsItems } from "./helpers";
|
||||
import { quickSettings } from "@girs/gnome-shell/ui";
|
||||
import { Gio } from "@girs/gio-2.0";
|
||||
import { GObject } from "@girs/gobject-2.0";
|
||||
import { uuid } from "../extension";
|
||||
import { DbusBase } from "./dbus_proxy";
|
||||
|
||||
export const AsusSlider = GObject.registerClass(
|
||||
class AsusSlider extends quickSettings.QuickSlider {
|
||||
private dbus: DbusBase;
|
||||
private settings: any = undefined;
|
||||
private setting = "";
|
||||
private prop_name = "";
|
||||
|
||||
constructor(dbus: DbusBase, prop_name: string, setting: string, title: string) {
|
||||
super({
|
||||
label: title,
|
||||
icon_name: "selection-mode-symbolic",
|
||||
});
|
||||
this.label = title;
|
||||
this.dbus = dbus;
|
||||
this.setting = setting;
|
||||
this.prop_name = prop_name;
|
||||
this.settings = Extension.lookupByUUID(uuid)?.getSettings();
|
||||
|
||||
this._sliderChangedId = this.slider.connect("drag-end", this._onSliderChanged.bind(this));
|
||||
|
||||
// Binding the slider to a GSettings key
|
||||
|
||||
this.settings.connect(`changed::${this.setting}`, this._onSettingsChanged.bind(this));
|
||||
|
||||
// Set an accessible name for the slider
|
||||
this.slider.accessible_name = title;
|
||||
|
||||
this.dbus?.proxy.connect("g-properties-changed", (_proxy, changed, invalidated) => {
|
||||
const properties = changed.deepUnpack();
|
||||
// .find() fails on some shit for some reason
|
||||
for (const v of Object.entries(properties)) {
|
||||
if (v[0] == this.prop_name) {
|
||||
const checked = v[1].unpack();
|
||||
this._sync();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this._sync();
|
||||
this._onSettingsChanged();
|
||||
|
||||
addQuickSettingsItems([this], 2);
|
||||
}
|
||||
|
||||
_onSettingsChanged() {
|
||||
// Prevent the slider from emitting a change signal while being updated
|
||||
this.slider.block_signal_handler(this._sliderChangedId);
|
||||
this.slider.value = this.settings.get_uint(this.setting) / 100.0;
|
||||
this.slider.unblock_signal_handler(this._sliderChangedId);
|
||||
}
|
||||
|
||||
_onSliderChanged() {
|
||||
// Assuming our GSettings holds values between 0..100, adjust for the
|
||||
// slider taking values between 0..1
|
||||
const percent = Math.floor(this.slider.value * 100);
|
||||
const stored = Math.floor(this.settings.get_uint(this.setting) / 100.0);
|
||||
if (this.slider.value !== stored) this.dbus.proxy[this.prop_name] = percent;
|
||||
this.settings.set_uint(this.setting, percent);
|
||||
}
|
||||
|
||||
_sync() {
|
||||
const value = this.dbus.proxy[this.prop_name];
|
||||
if (this.slider.value !== value / 100) this.settings.set_uint(this.setting, value);
|
||||
}
|
||||
},
|
||||
);
|
||||
19
desktop-extensions/gnome-45/tsconfig.json
Normal file
19
desktop-extensions/gnome-45/tsconfig.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
// "extends": "@tsconfig/strictest/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"lib": ["ESNext"],
|
||||
"types": [],
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Bundler",
|
||||
"declaration": true,
|
||||
"removeComments": true,
|
||||
"strict": true,
|
||||
"allowJs": true,
|
||||
"paths": {},
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"files": ["./src/extension.ts"],
|
||||
"include": ["src/*.ts"],
|
||||
"exclude": [".ts-for-girrc.js", ".eslintrc.cjs"]
|
||||
}
|
||||
1584
desktop-extensions/gnome-45/yarn.lock
Normal file
1584
desktop-extensions/gnome-45/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
128
distro-packaging/asusctl.spec
Executable file
128
distro-packaging/asusctl.spec
Executable file
@@ -0,0 +1,128 @@
|
||||
#
|
||||
# spec file for package asus-nb-ctrl
|
||||
#
|
||||
# Copyright (c) 2020-2021 Luke Jones <luke@ljones.dev>
|
||||
#
|
||||
# All modifications and additions to the file contributed by third parties
|
||||
# remain the property of their copyright owners, unless otherwise agreed
|
||||
# upon. The license for this file, and modifications and additions to the
|
||||
# file, is the same license as for the pristine package itself (unless the
|
||||
# license for the pristine package is not an Open Source License, in which
|
||||
# case the license is the MIT License). An "Open Source License" is a
|
||||
# license that conforms to the Open Source Definition (Version 1.9)
|
||||
# published by the Open Source Initiative.
|
||||
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
%if %{defined fedora}
|
||||
%global debug_package %{nil}
|
||||
%endif
|
||||
|
||||
%global rpm_dkms_opt 1
|
||||
|
||||
# Use hardening ldflags.
|
||||
%global rustflags -Clink-arg=-Wl,-z,relro,-z,now
|
||||
Name: asusctl
|
||||
Version: 4.7.0
|
||||
Release: 2
|
||||
Summary: Control fan speeds, LEDs, graphics modes, and charge levels for ASUS notebooks
|
||||
License: MPLv2
|
||||
|
||||
Group: System Environment/Kernel
|
||||
|
||||
URL: https://gitlab.com/asus-linux/asusctl
|
||||
Source: %{name}-%{version}.tar.gz
|
||||
Source1: vendor-%{name}-%{version}.tar.gz
|
||||
Source2: cargo_config
|
||||
|
||||
BuildRequires: cargo
|
||||
BuildRequires: rust-packaging
|
||||
BuildRequires: systemd-rpm-macros
|
||||
BuildRequires: clang-devel
|
||||
BuildRequires: cmake
|
||||
BuildRequires: rust
|
||||
BuildRequires: rust-std-static
|
||||
BuildRequires: pkgconfig(dbus-1)
|
||||
BuildRequires: pkgconfig(libudev)
|
||||
BuildRequires: pkgconfig(gtk+-3.0)
|
||||
BuildRequires: pkgconfig(gdk-3.0)
|
||||
BuildRequires: desktop-file-utils
|
||||
Requires: libappindicator-gtk3
|
||||
|
||||
%description
|
||||
asus-nb-ctrl 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.
|
||||
|
||||
It provides an interface for rootless control of some system functions such as
|
||||
fan speeds, keyboard LEDs, battery charge level, and graphics modes.
|
||||
asus-nb-ctrl enables third-party apps to use the above with dbus methods.
|
||||
|
||||
%package rog-gui
|
||||
Summary: An experimental GUI for %{name}
|
||||
|
||||
%description rog-gui
|
||||
A one-stop-shop GUI tool for asusd/asusctl. It aims to provide most controls,
|
||||
a notification service, and ability to run in the background.
|
||||
|
||||
%prep
|
||||
%autosetup
|
||||
%setup -D -T -a 1 -c -n %{name}-%{version}/vendor
|
||||
cd ..
|
||||
|
||||
mv Cargo.lock{,.bak}
|
||||
%cargo_prep
|
||||
mv Cargo.lock{.bak,}
|
||||
sed -i 's|replace-with = "local-registry"|replace-with = "vendored-sources"|' .cargo/config
|
||||
cat %{SOURCE2} >> .cargo/config
|
||||
|
||||
%build
|
||||
export RUSTFLAGS="%{rustflags}"
|
||||
%cargo_build
|
||||
#cargo build --release --frozen --offline --config .cargo/config.toml
|
||||
|
||||
%install
|
||||
export RUSTFLAGS="%{rustflags}"
|
||||
mkdir -p "%{buildroot}/%{_bindir}" "%{buildroot}%{_docdir}"
|
||||
%make_install
|
||||
|
||||
install -D -m 0644 README.md %{buildroot}/%{_docdir}/%{name}/README.md
|
||||
install -D -m 0644 rog-anime/README.md %{buildroot}/%{_docdir}/%{name}/README-anime.md
|
||||
install -D -m 0644 rog-anime/data/diagonal-template.png %{buildroot}/%{_docdir}/%{name}/diagonal-template.png
|
||||
|
||||
desktop-file-validate %{buildroot}/%{_datadir}/applications/rog-control-center.desktop
|
||||
|
||||
%files
|
||||
%license LICENSE
|
||||
%{_bindir}/asusd
|
||||
%{_bindir}/asusd-user
|
||||
%{_bindir}/asusctl
|
||||
%{_unitdir}/asusd.service
|
||||
%{_userunitdir}/asusd-user.service
|
||||
%{_udevrulesdir}/99-asusd.rules
|
||||
#%dir %{_sysconfdir}/asusd/
|
||||
%{_datadir}/asusd/aura_support.ron
|
||||
%{_datadir}/dbus-1/system.d/asusd.conf
|
||||
%{_datadir}/icons/hicolor/512x512/apps/asus_notif_yellow.png
|
||||
%{_datadir}/icons/hicolor/512x512/apps/asus_notif_green.png
|
||||
%{_datadir}/icons/hicolor/512x512/apps/asus_notif_red.png
|
||||
%{_datadir}/icons/hicolor/512x512/apps/asus_notif_blue.png
|
||||
%{_datadir}/icons/hicolor/512x512/apps/asus_notif_orange.png
|
||||
%{_datadir}/icons/hicolor/512x512/apps/asus_notif_white.png
|
||||
%{_datadir}/icons/hicolor/scalable/status/gpu-compute.svg
|
||||
%{_datadir}/icons/hicolor/scalable/status/gpu-hybrid.svg
|
||||
%{_datadir}/icons/hicolor/scalable/status/gpu-integrated.svg
|
||||
%{_datadir}/icons/hicolor/scalable/status/gpu-nvidia.svg
|
||||
%{_datadir}/icons/hicolor/scalable/status/gpu-vfio.svg
|
||||
%{_datadir}/icons/hicolor/scalable/status/notification-reboot.svg
|
||||
%{_docdir}/%{name}/
|
||||
%{_datadir}/asusd/
|
||||
|
||||
%files rog-gui
|
||||
%{_bindir}/rog-control-center
|
||||
%{_datadir}/applications/rog-control-center.desktop
|
||||
%{_datadir}/icons/hicolor/512x512/apps/rog-control-center.png
|
||||
%{_datadir}/rog-gui
|
||||
|
||||
%changelog
|
||||
8
dmi-id/Cargo.toml
Normal file
8
dmi-id/Cargo.toml
Normal file
@@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "dmi_id"
|
||||
edition = "2021"
|
||||
version.workspace = true
|
||||
|
||||
[dependencies]
|
||||
log.workspace = true
|
||||
udev.workspace = true
|
||||
113
dmi-id/src/lib.rs
Normal file
113
dmi-id/src/lib.rs
Normal file
@@ -0,0 +1,113 @@
|
||||
use log::{info, warn};
|
||||
|
||||
#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Clone)]
|
||||
pub struct DMIID {
|
||||
pub id_model: String,
|
||||
pub dmi_family: String,
|
||||
pub dmi_vendor: String,
|
||||
pub board_name: String,
|
||||
pub board_vendor: String,
|
||||
pub bios_date: String,
|
||||
pub bios_release: String,
|
||||
pub bios_vendor: String,
|
||||
pub bios_version: String,
|
||||
pub product_family: String,
|
||||
pub product_name: String,
|
||||
}
|
||||
|
||||
impl DMIID {
|
||||
pub fn new() -> Result<Self, String> {
|
||||
let mut enumerator = udev::Enumerator::new().map_err(|err| {
|
||||
warn!("{}", err);
|
||||
format!("dmi enumerator failed: {err}")
|
||||
})?;
|
||||
|
||||
enumerator.match_subsystem("dmi").map_err(|err| {
|
||||
warn!("{}", err);
|
||||
format!("dmi match_subsystem failed: {err}")
|
||||
})?;
|
||||
|
||||
let mut result = enumerator.scan_devices().map_err(|err| {
|
||||
warn!("{}", err);
|
||||
format!("dmi scan_devices failed: {err}")
|
||||
})?;
|
||||
|
||||
if let Some(device) = (result).next() {
|
||||
info!("Found dmi ID info at {:?}", device.sysname());
|
||||
|
||||
return Ok(Self {
|
||||
id_model: device
|
||||
.property_value("ID_MODEL")
|
||||
.map(|s| s.to_string_lossy().to_string())
|
||||
.unwrap_or("Unknown".to_string()),
|
||||
dmi_family: device
|
||||
.property_value("DMI_FAMILY")
|
||||
.map(|s| s.to_string_lossy().to_string())
|
||||
.unwrap_or("Unknown".to_string()),
|
||||
dmi_vendor: device
|
||||
.property_value("DMI_VENDOR")
|
||||
.map(|s| s.to_string_lossy().to_string())
|
||||
.unwrap_or("Unknown".to_string()),
|
||||
board_name: device
|
||||
.attribute_value("board_name")
|
||||
.map(|s| s.to_string_lossy().to_string())
|
||||
.unwrap_or("Unknown".to_string()),
|
||||
board_vendor: device
|
||||
.attribute_value("board_vendor")
|
||||
.map(|s| s.to_string_lossy().to_string())
|
||||
.unwrap_or("Unknown".to_string()),
|
||||
bios_date: device
|
||||
.attribute_value("bios_date")
|
||||
.map(|s| s.to_string_lossy().to_string())
|
||||
.unwrap_or("Unknown".to_string()),
|
||||
bios_release: device
|
||||
.attribute_value("bios_release")
|
||||
.map(|s| s.to_string_lossy().to_string())
|
||||
.unwrap_or("Unknown".to_string()),
|
||||
bios_vendor: device
|
||||
.attribute_value("bios_vendor")
|
||||
.map(|s| s.to_string_lossy().to_string())
|
||||
.unwrap_or("Unknown".to_string()),
|
||||
bios_version: device
|
||||
.attribute_value("bios_version")
|
||||
.map(|s| s.to_string_lossy().to_string())
|
||||
.unwrap_or("Unknown".to_string()),
|
||||
product_family: device
|
||||
.attribute_value("product_family")
|
||||
.map(|s| s.to_string_lossy().to_string())
|
||||
.unwrap_or("Unknown".to_string()),
|
||||
product_name: device
|
||||
.attribute_value("product_name")
|
||||
.map(|s| s.to_string_lossy().to_string())
|
||||
.unwrap_or("Unknown".to_string()),
|
||||
});
|
||||
}
|
||||
Err("dmi not found".into())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
#[ignore = "Does not run in docker images"]
|
||||
fn dmi_sysfs_properties_not_unknown() {
|
||||
let dmi = DMIID::new().unwrap();
|
||||
|
||||
assert_ne!(dmi.id_model, "Unknown".to_string());
|
||||
dbg!(dmi.id_model);
|
||||
assert_ne!(dmi.dmi_family, "Unknown".to_string());
|
||||
dbg!(dmi.dmi_family);
|
||||
assert_ne!(dmi.dmi_vendor, "Unknown".to_string());
|
||||
dbg!(dmi.dmi_vendor);
|
||||
assert_ne!(dmi.board_name, "Unknown".to_string());
|
||||
dbg!(dmi.board_name);
|
||||
assert_ne!(dmi.board_vendor, "Unknown".to_string());
|
||||
dbg!(dmi.board_vendor);
|
||||
assert_ne!(dmi.product_family, "Unknown".to_string());
|
||||
dbg!(dmi.product_family);
|
||||
assert_ne!(dmi.product_name, "Unknown".to_string());
|
||||
dbg!(dmi.product_name);
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ exclude = ["data"]
|
||||
[features]
|
||||
default = ["dbus", "detect"]
|
||||
dbus = ["zbus"]
|
||||
detect = ["sysfs-class"]
|
||||
detect = ["dmi_id"]
|
||||
|
||||
[lib]
|
||||
name = "rog_anime"
|
||||
@@ -31,10 +31,11 @@ serde.workspace = true
|
||||
serde_derive.workspace = true
|
||||
|
||||
glam.workspace = true
|
||||
typeshare.workspace = true
|
||||
|
||||
zbus = { workspace = true, optional = true }
|
||||
|
||||
sysfs-class = { workspace = true, optional = true }
|
||||
dmi_id = { path = "../dmi-id", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
cargo-husky.workspace = true
|
||||
@@ -5,8 +5,9 @@ use std::time::{Duration, Instant};
|
||||
|
||||
use log::info;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use typeshare::typeshare;
|
||||
#[cfg(feature = "dbus")]
|
||||
use zbus::zvariant::Type;
|
||||
use zbus::zvariant::{OwnedValue, Type, Value};
|
||||
|
||||
use crate::error::{AnimeError, Result};
|
||||
use crate::usb::{AnimAwake, AnimBooting, AnimShutdown, AnimSleeping, Brightness};
|
||||
@@ -27,7 +28,9 @@ pub const USB_PREFIX2: [u8; 7] = [0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02];
|
||||
/// Third packet is for GA402 matrix
|
||||
pub const USB_PREFIX3: [u8; 7] = [0x5e, 0xc0, 0x02, 0xe7, 0x04, 0x73, 0x02];
|
||||
|
||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||
#[typeshare]
|
||||
#[cfg_attr(feature = "dbus", derive(Type, Value, OwnedValue))]
|
||||
#[typeshare]
|
||||
#[derive(Default, Deserialize, PartialEq, Eq, Clone, Copy, Serialize, Debug)]
|
||||
pub struct Animations {
|
||||
pub boot: AnimBooting,
|
||||
@@ -36,17 +39,25 @@ pub struct Animations {
|
||||
pub shutdown: AnimShutdown,
|
||||
}
|
||||
|
||||
// TODO: move this out
|
||||
#[typeshare]
|
||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||
#[typeshare]
|
||||
#[derive(Debug, PartialEq, Eq, Copy, Clone, Deserialize, Serialize)]
|
||||
pub struct DeviceState {
|
||||
pub display_enabled: bool,
|
||||
pub display_brightness: Brightness,
|
||||
pub builtin_anims_enabled: bool,
|
||||
pub builtin_anims: Animations,
|
||||
pub off_when_unplugged: bool,
|
||||
pub off_when_suspended: bool,
|
||||
pub off_when_lid_closed: bool,
|
||||
pub brightness_on_battery: Brightness,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize)]
|
||||
#[typeshare]
|
||||
#[cfg_attr(feature = "dbus", derive(Type), zvariant(signature = "s"))]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Deserialize, Serialize)]
|
||||
pub enum AnimeType {
|
||||
GA401,
|
||||
GA402,
|
||||
|
||||
@@ -33,3 +33,27 @@ pub mod error;
|
||||
pub mod usb;
|
||||
|
||||
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
// #[cfg(feature = "typescript")]
|
||||
// #[cfg(test)]
|
||||
// mod tests {
|
||||
// use crate::usb::{AnimShutdown, Brightness, AnimSleeping, AnimAwake,
|
||||
// AnimBooting}; use crate::{AnimeType, Animations, DeviceState};
|
||||
// use ts_rs::SingleFileExporter;
|
||||
// #[test]
|
||||
// fn test_singlefile() {
|
||||
// let out = SingleFileExporter::new(false)
|
||||
// .and::<AnimeType>()
|
||||
// .and::<Animations>()
|
||||
// .and::<DeviceState>()
|
||||
// .and::<Brightness>()
|
||||
// .and::<AnimShutdown>()
|
||||
// .and::<AnimSleeping>()
|
||||
// .and::<AnimAwake>()
|
||||
// .and::<AnimBooting>()
|
||||
// .finish()
|
||||
// .unwrap();
|
||||
// println!("{out}");
|
||||
// assert_eq!(out, "");
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -10,9 +10,11 @@
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
use dmi_id::DMIID;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use typeshare::typeshare;
|
||||
#[cfg(feature = "dbus")]
|
||||
use zbus::zvariant::Type;
|
||||
use zbus::zvariant::{OwnedValue, Type, Value};
|
||||
|
||||
use crate::error::AnimeError;
|
||||
use crate::AnimeType;
|
||||
@@ -22,15 +24,20 @@ const DEV_PAGE: u8 = 0x5e;
|
||||
pub const VENDOR_ID: u16 = 0x0b05;
|
||||
pub const PROD_ID: u16 = 0x193b;
|
||||
|
||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||
#[cfg_attr(
|
||||
feature = "dbus",
|
||||
derive(Type, Value, OwnedValue),
|
||||
zvariant(signature = "u")
|
||||
)]
|
||||
#[typeshare]
|
||||
#[derive(Debug, Default, PartialEq, Eq, Copy, Clone, Deserialize, Serialize)]
|
||||
/// Base LED brightness of the display
|
||||
pub enum Brightness {
|
||||
Off,
|
||||
Low,
|
||||
Off = 0,
|
||||
Low = 1,
|
||||
#[default]
|
||||
Med,
|
||||
High,
|
||||
Med = 2,
|
||||
High = 3,
|
||||
}
|
||||
|
||||
impl FromStr for Brightness {
|
||||
@@ -58,12 +65,17 @@ impl From<u8> for Brightness {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||
#[cfg_attr(
|
||||
feature = "dbus",
|
||||
derive(Type, Value, OwnedValue),
|
||||
zvariant(signature = "s")
|
||||
)]
|
||||
#[typeshare]
|
||||
#[derive(Debug, Default, PartialEq, Eq, Copy, Clone, Deserialize, Serialize)]
|
||||
pub enum AnimBooting {
|
||||
#[default]
|
||||
GlitchConstruction,
|
||||
StaticEmergence,
|
||||
GlitchConstruction = 0,
|
||||
StaticEmergence = 1,
|
||||
}
|
||||
|
||||
impl FromStr for AnimBooting {
|
||||
@@ -78,12 +90,17 @@ impl FromStr for AnimBooting {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||
#[cfg_attr(
|
||||
feature = "dbus",
|
||||
derive(Type, Value, OwnedValue),
|
||||
zvariant(signature = "s")
|
||||
)]
|
||||
#[typeshare]
|
||||
#[derive(Debug, Default, PartialEq, Eq, Copy, Clone, Deserialize, Serialize)]
|
||||
pub enum AnimAwake {
|
||||
#[default]
|
||||
BinaryBannerScroll,
|
||||
RogLogoGlitch,
|
||||
BinaryBannerScroll = 0,
|
||||
RogLogoGlitch = 1,
|
||||
}
|
||||
|
||||
impl FromStr for AnimAwake {
|
||||
@@ -98,12 +115,17 @@ impl FromStr for AnimAwake {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||
#[cfg_attr(
|
||||
feature = "dbus",
|
||||
derive(Type, Value, OwnedValue),
|
||||
zvariant(signature = "s")
|
||||
)]
|
||||
#[typeshare]
|
||||
#[derive(Debug, Default, PartialEq, Eq, Copy, Clone, Deserialize, Serialize)]
|
||||
pub enum AnimSleeping {
|
||||
#[default]
|
||||
BannerSwipe,
|
||||
Starfield,
|
||||
BannerSwipe = 0,
|
||||
Starfield = 1,
|
||||
}
|
||||
|
||||
impl FromStr for AnimSleeping {
|
||||
@@ -118,12 +140,17 @@ impl FromStr for AnimSleeping {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||
#[cfg_attr(
|
||||
feature = "dbus",
|
||||
derive(Type, Value, OwnedValue),
|
||||
zvariant(signature = "s")
|
||||
)]
|
||||
#[typeshare]
|
||||
#[derive(Debug, Default, PartialEq, Eq, Copy, Clone, Deserialize, Serialize)]
|
||||
pub enum AnimShutdown {
|
||||
#[default]
|
||||
GlitchOut,
|
||||
SeeYa,
|
||||
GlitchOut = 0,
|
||||
SeeYa = 1,
|
||||
}
|
||||
|
||||
impl FromStr for AnimShutdown {
|
||||
@@ -145,8 +172,8 @@ impl FromStr for AnimShutdown {
|
||||
/// The currently known USB device is `19b6`.
|
||||
#[inline]
|
||||
pub fn get_anime_type() -> Result<AnimeType, AnimeError> {
|
||||
let dmi = sysfs_class::DmiId::default();
|
||||
let board_name = dmi.board_name()?;
|
||||
let dmi = DMIID::new().map_err(|_| AnimeError::NoDevice)?; // TODO: better error
|
||||
let board_name = dmi.board_name;
|
||||
|
||||
if board_name.contains("GA401I") || board_name.contains("GA401Q") {
|
||||
return Ok(AnimeType::GA401);
|
||||
|
||||
@@ -20,12 +20,11 @@ dbus = ["zbus"]
|
||||
serde.workspace = true
|
||||
serde_derive.workspace = true
|
||||
zbus = { workspace = true, optional = true }
|
||||
dmi_id = { path = "../dmi-id" }
|
||||
|
||||
# cli and logging
|
||||
log.workspace = true
|
||||
|
||||
# Device control
|
||||
sysfs-class.workspace = true # used for backlight control and baord ID
|
||||
typeshare.workspace = true
|
||||
|
||||
ron = { version = "*", optional = true }
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "FA506Q",
|
||||
@@ -12,6 +13,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "FA507",
|
||||
@@ -19,6 +21,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "FX505D",
|
||||
@@ -26,6 +29,15 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "FX505G",
|
||||
layout_name: "fx505d",
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "FX506H",
|
||||
@@ -33,6 +45,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "FX506L",
|
||||
@@ -40,6 +53,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "FX507Z",
|
||||
@@ -47,6 +61,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "FX516P",
|
||||
@@ -54,6 +69,15 @@
|
||||
basic_modes: [Static, Breathe, Strobe],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "FX705D",
|
||||
layout_name: "fx505d",
|
||||
basic_modes: [Static, Breathe, Strobe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "G512",
|
||||
@@ -61,6 +85,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "G512LV",
|
||||
@@ -68,6 +93,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "G513I",
|
||||
@@ -75,6 +101,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: Zoned([ZonedKbLeft, ZonedKbLeftMid, ZonedKbRightMid, ZonedKbRight, LightbarRight, LightbarRightCorner, LightbarRightBottom, LightbarLeftBottom, LightbarLeftCorner, LightbarLeft]),
|
||||
power_zones: [Keyboard, Lightbar],
|
||||
),
|
||||
(
|
||||
board_name: "G513QE",
|
||||
@@ -82,6 +109,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "G513QM",
|
||||
@@ -89,6 +117,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||
basic_zones: [],
|
||||
advanced_type: PerKey,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "G513QR",
|
||||
@@ -96,6 +125,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||
basic_zones: [],
|
||||
advanced_type: PerKey,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "G513QY",
|
||||
@@ -103,6 +133,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: PerKey,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "G513RC",
|
||||
@@ -110,6 +141,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: Zoned([ZonedKbLeft, ZonedKbLeftMid, ZonedKbRightMid, ZonedKbRight, LightbarRight, LightbarRightCorner, LightbarRightBottom, LightbarLeftBottom, LightbarLeftCorner, LightbarLeft]),
|
||||
power_zones: [Keyboard, Lightbar],
|
||||
),
|
||||
(
|
||||
board_name: "G513RM",
|
||||
@@ -117,6 +149,15 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: Zoned([ZonedKbLeft, ZonedKbLeftMid, ZonedKbRightMid, ZonedKbRight, LightbarRight, LightbarRightCorner, LightbarRightBottom, LightbarLeftBottom, LightbarLeftCorner, LightbarLeft]),
|
||||
power_zones: [Keyboard, Lightbar],
|
||||
),
|
||||
(
|
||||
board_name: "G513RW",
|
||||
layout_name: "g513i-per-key",
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||
basic_zones: [],
|
||||
advanced_type: PerKey,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "G531",
|
||||
@@ -124,6 +165,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||
basic_zones: [],
|
||||
advanced_type: PerKey,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "G531",
|
||||
@@ -131,6 +173,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: PerKey,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "G531GD",
|
||||
@@ -138,6 +181,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "G531GT",
|
||||
@@ -145,6 +189,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "G531GU",
|
||||
@@ -152,6 +197,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "G531GV",
|
||||
@@ -159,6 +205,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "G531GW",
|
||||
@@ -166,6 +213,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "G532",
|
||||
@@ -173,6 +221,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||
basic_zones: [],
|
||||
advanced_type: PerKey,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "G533Q",
|
||||
@@ -180,6 +229,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||
basic_zones: [],
|
||||
advanced_type: PerKey,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "G533Z",
|
||||
@@ -187,6 +237,15 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||
basic_zones: [],
|
||||
advanced_type: PerKey,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "G614J",
|
||||
layout_name: "g634j-per-key",
|
||||
basic_modes: [Static, Breathe, Pulse, Strobe, Rainbow],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard, Lightbar],
|
||||
),
|
||||
(
|
||||
board_name: "G634J",
|
||||
@@ -194,6 +253,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||
basic_zones: [],
|
||||
advanced_type: PerKey,
|
||||
power_zones: [Keyboard, Lightbar, Logo, RearGlow],
|
||||
),
|
||||
(
|
||||
board_name: "G712LI",
|
||||
@@ -201,6 +261,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "G712LV",
|
||||
@@ -208,6 +269,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "G712LW",
|
||||
@@ -215,6 +277,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "G713IC",
|
||||
@@ -222,6 +285,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||
basic_zones: [],
|
||||
advanced_type: PerKey,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "G713QM",
|
||||
@@ -229,6 +293,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "G713QR",
|
||||
@@ -236,6 +301,15 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||
basic_zones: [],
|
||||
advanced_type: PerKey,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "G713RC",
|
||||
layout_name: "gx502",
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: Zoned([ZonedKbLeft, ZonedKbLeftMid, ZonedKbRightMid, ZonedKbRight, LightbarRight, LightbarRightCorner, LightbarRightBottom, LightbarLeftBottom, LightbarLeftCorner, LightbarLeft]),
|
||||
power_zones: [Keyboard, Lightbar],
|
||||
),
|
||||
(
|
||||
board_name: "G713RM",
|
||||
@@ -243,6 +317,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "G713RS",
|
||||
@@ -250,6 +325,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||
basic_zones: [],
|
||||
advanced_type: PerKey,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "G713RW",
|
||||
@@ -257,6 +333,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "G731",
|
||||
@@ -264,6 +341,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: PerKey,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "G731GT",
|
||||
@@ -271,6 +349,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "G731GU",
|
||||
@@ -278,6 +357,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "G731GV",
|
||||
@@ -285,6 +365,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "G731GW",
|
||||
@@ -292,6 +373,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "G733C",
|
||||
@@ -299,6 +381,15 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||
basic_zones: [Logo, BarLeft, BarRight],
|
||||
advanced_type: PerKey,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "G733PZ",
|
||||
layout_name: "g733pz-per-key",
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||
basic_zones: [],
|
||||
advanced_type: PerKey,
|
||||
power_zones: [Keyboard, Lightbar],
|
||||
),
|
||||
(
|
||||
board_name: "G733Q",
|
||||
@@ -306,6 +397,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||
basic_zones: [],
|
||||
advanced_type: PerKey,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "G733Z",
|
||||
@@ -313,6 +405,31 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||
basic_zones: [],
|
||||
advanced_type: PerKey,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "G814JI",
|
||||
layout_name: "g814ji-per-key",
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||
basic_zones: [],
|
||||
advanced_type: PerKey,
|
||||
power_zones: [Keyboard, Lightbar],
|
||||
),
|
||||
(
|
||||
board_name: "G814JZ",
|
||||
layout_name: "g814ji-per-key",
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||
basic_zones: [],
|
||||
advanced_type: PerKey,
|
||||
power_zones: [Keyboard, Lightbar],
|
||||
),
|
||||
(
|
||||
board_name: "G834JZ",
|
||||
layout_name: "g814ji-per-key",
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||
basic_zones: [],
|
||||
advanced_type: PerKey,
|
||||
power_zones: [Keyboard, Lightbar, Logo, RearGlow],
|
||||
),
|
||||
(
|
||||
board_name: "GA401Q",
|
||||
@@ -320,6 +437,7 @@
|
||||
basic_modes: [Static, Breathe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "GA402R",
|
||||
@@ -327,6 +445,15 @@
|
||||
basic_modes: [Static, Breathe, Pulse, Rainbow],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "GA402X",
|
||||
layout_name: "ga401q",
|
||||
basic_modes: [Static, Breathe, Pulse, Rainbow],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "GA503Q",
|
||||
@@ -334,6 +461,7 @@
|
||||
basic_modes: [Static, Breathe, Pulse, Rainbow, Strobe],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "GA503QE",
|
||||
@@ -341,6 +469,7 @@
|
||||
basic_modes: [Static, Breathe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "GA503R",
|
||||
@@ -348,6 +477,7 @@
|
||||
basic_modes: [Static, Breathe, Pulse, Rainbow, Strobe],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "GL503",
|
||||
@@ -355,6 +485,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "GL503V",
|
||||
@@ -362,6 +493,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "GL504G",
|
||||
@@ -369,6 +501,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4, Logo, BarLeft, BarRight],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "GL531",
|
||||
@@ -376,6 +509,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||
basic_zones: [],
|
||||
advanced_type: PerKey,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "GL553VE",
|
||||
@@ -383,6 +517,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "GL703G",
|
||||
@@ -390,6 +525,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "GM501G",
|
||||
@@ -397,6 +533,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "GU502",
|
||||
@@ -404,6 +541,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||
basic_zones: [],
|
||||
advanced_type: PerKey,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "GU502G",
|
||||
@@ -411,6 +549,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||
basic_zones: [],
|
||||
advanced_type: PerKey,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "GU502L",
|
||||
@@ -418,6 +557,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||
basic_zones: [],
|
||||
advanced_type: PerKey,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "GU502LU",
|
||||
@@ -425,6 +565,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "GU603H",
|
||||
@@ -432,6 +573,15 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: Zoned([SingleZone]),
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "GU603VV",
|
||||
layout_name: "ga401q",
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: Zoned([SingleZone]),
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "GU603Z",
|
||||
@@ -439,6 +589,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: Zoned([SingleZone]),
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "GU604V",
|
||||
@@ -446,6 +597,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: Zoned([SingleZone]),
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "GV301Q",
|
||||
@@ -453,6 +605,7 @@
|
||||
basic_modes: [Static, Breathe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "GV301V",
|
||||
@@ -460,6 +613,7 @@
|
||||
basic_modes: [Static, Breathe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "GV301VIC",
|
||||
@@ -467,6 +621,7 @@
|
||||
basic_modes: [Static, Breathe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "GV601R",
|
||||
@@ -474,13 +629,15 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "GV601VI",
|
||||
board_name: "GV601V",
|
||||
layout_name: "ga401q",
|
||||
basic_modes: [Static, Breathe, Pulse, Strobe],
|
||||
basic_modes: [Static, Breathe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
advanced_type: Zoned([SingleZone]),
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "GV604V",
|
||||
@@ -488,6 +645,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "GX502",
|
||||
@@ -495,6 +653,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||
basic_zones: [],
|
||||
advanced_type: PerKey,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "GX531",
|
||||
@@ -502,6 +661,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse],
|
||||
basic_zones: [Key1, Key2, Key3, Key4],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "GX550L",
|
||||
@@ -509,6 +669,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||
basic_zones: [],
|
||||
advanced_type: PerKey,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "GX551Q",
|
||||
@@ -516,6 +677,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: PerKey,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "GX650P",
|
||||
@@ -523,6 +685,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||
basic_zones: [],
|
||||
advanced_type: PerKey,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "GX701",
|
||||
@@ -530,6 +693,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||
basic_zones: [],
|
||||
advanced_type: PerKey,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "GX703H",
|
||||
@@ -537,6 +701,7 @@
|
||||
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "GZ301V",
|
||||
@@ -544,6 +709,7 @@
|
||||
basic_modes: [Static, Breathe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
(
|
||||
board_name: "GZ301VIC",
|
||||
@@ -551,5 +717,14 @@
|
||||
basic_modes: [Static, Breathe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
])
|
||||
(
|
||||
board_name: "RC71L",
|
||||
layout_name: "ga401q",
|
||||
basic_modes: [Static, Breathe, Pulse],
|
||||
basic_zones: [],
|
||||
advanced_type: None,
|
||||
power_zones: [Keyboard],
|
||||
),
|
||||
])
|
||||
|
||||
398
rog-aura/data/layouts/g733pz-per-key_US.ron
Normal file
398
rog-aura/data/layouts/g733pz-per-key_US.ron
Normal file
@@ -0,0 +1,398 @@
|
||||
(
|
||||
locale: "US",
|
||||
key_shapes: {
|
||||
"regular": Led(
|
||||
width: 1.0,
|
||||
height: 1.0,
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
"regular2": Led(
|
||||
width: 1.0,
|
||||
height: 1.0,
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
"rog_row": Led(
|
||||
width: 1.0,
|
||||
height: 0.6,
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.6,
|
||||
),
|
||||
"rog_row_blocking": Blank(
|
||||
width: 1.2,
|
||||
height: 0.0,
|
||||
),
|
||||
"func_key": Led(
|
||||
width: 1.0,
|
||||
height: 0.6,
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.0,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
"func_space": Blank(
|
||||
width: 0.5,
|
||||
height: 0.0,
|
||||
),
|
||||
"esc_func_spacing": Blank(
|
||||
width: 1.2,
|
||||
height: 0.0,
|
||||
),
|
||||
"backspace": Led(
|
||||
width: 2.0,
|
||||
height: 1.0,
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
"bkslash": Led(
|
||||
width: 1.4,
|
||||
height: 1.0,
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
"tab": Led(
|
||||
width: 1.6,
|
||||
height: 1.0,
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
"capsplonk": Led(
|
||||
width: 1.9,
|
||||
height: 1.0,
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
"return": Led(
|
||||
width: 2.3,
|
||||
height: 1.0,
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
"lshift": Led(
|
||||
width: 2.5,
|
||||
height: 1.0,
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
"rshift": Led(
|
||||
width: 2.9,
|
||||
height: 1.0,
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
"lctrl": Led(
|
||||
width: 1.4,
|
||||
height: 1.0,
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
"spacebar": Led(
|
||||
width: 6.0,
|
||||
height: 1.0,
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
"rctrl": Led(
|
||||
width: 1.2,
|
||||
height: 1.0,
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
"up_arrow": Led(
|
||||
width: 1.0,
|
||||
height: 0.6,
|
||||
pad_left: 1.5,
|
||||
pad_right: 1.3,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.0,
|
||||
),
|
||||
"arrows_spacer": Blank(
|
||||
width: 14.2,
|
||||
height: 0.0,
|
||||
),
|
||||
"arrows": Led(
|
||||
width: 1.0,
|
||||
height: 0.6,
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: -0.3,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
"numpad_tall": Led(
|
||||
width: 1.0,
|
||||
height: 2.2,
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: -1.2,
|
||||
),
|
||||
"numpad_wide": Led(
|
||||
width: 2.2,
|
||||
height: 1.0,
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
"lightbar_left": Led(
|
||||
width: 0.4,
|
||||
height: 3.0,
|
||||
pad_left: -1.0,
|
||||
pad_right: 0.1,
|
||||
pad_top: -2.7,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
"lightbar_corner_left": Led(
|
||||
width: 0.4,
|
||||
height: 0.4,
|
||||
pad_left: -0.5,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.5,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
"lightbar_bottom": Led(
|
||||
width: 11.85,
|
||||
height: 0.4,
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.5,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
"lightbar_corner_right": Led(
|
||||
width: 0.4,
|
||||
height: 0.4,
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.5,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
"lightbar_right": Led(
|
||||
width: 0.4,
|
||||
height: 3.0,
|
||||
pad_left: -0.5,
|
||||
pad_right: 0.1,
|
||||
pad_top: -2.7,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
},
|
||||
key_rows: [
|
||||
(
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
row: [
|
||||
(Blocking, "rog_row_blocking"),
|
||||
(Blocking, "rog_row_blocking"),
|
||||
(VolDown, "rog_row"),
|
||||
(VolUp, "rog_row"),
|
||||
(MicMute, "rog_row"),
|
||||
(RogFan, "rog_row"),
|
||||
(RogApp, "rog_row"),
|
||||
],
|
||||
),
|
||||
(
|
||||
pad_left: 0.1,
|
||||
pad_top: 0.1,
|
||||
row: [
|
||||
(Esc, "func_key"),
|
||||
(Spacing, "esc_func_spacing"),
|
||||
(F1, "func_key"),
|
||||
(F2, "func_key"),
|
||||
(F3, "func_key"),
|
||||
(F4, "func_key"),
|
||||
(Spacing, "func_space"),
|
||||
(F5, "func_key"),
|
||||
(F6, "func_key"),
|
||||
(F7, "func_key"),
|
||||
(F8, "func_key"),
|
||||
(Spacing, "func_space"),
|
||||
(F9, "func_key"),
|
||||
(F10, "func_key"),
|
||||
(F11, "func_key"),
|
||||
(F12, "func_key"),
|
||||
(Spacing, "func_space"),
|
||||
(Del, "func_key"),
|
||||
(NumPadPause, "func_key"),
|
||||
(NumPadPrtSc, "func_key"),
|
||||
(NumPadHome, "func_key"),
|
||||
],
|
||||
),
|
||||
(
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
row: [
|
||||
(Tilde, "regular"),
|
||||
(N1, "regular"),
|
||||
(N2, "regular"),
|
||||
(N3, "regular"),
|
||||
(N4, "regular"),
|
||||
(N5, "regular"),
|
||||
(N6, "regular"),
|
||||
(N7, "regular"),
|
||||
(N8, "regular"),
|
||||
(N9, "regular"),
|
||||
(N0, "regular"),
|
||||
(Hyphen, "regular"),
|
||||
(Equals, "regular"),
|
||||
(Backspace, "backspace"),
|
||||
(Spacing, "func_space"),
|
||||
(NumLock, "regular"),
|
||||
(FwdSlash, "regular"),
|
||||
(Star, "regular"),
|
||||
(Hyphen, "regular"),
|
||||
],
|
||||
),
|
||||
(
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
row: [
|
||||
(Tab, "tab"),
|
||||
(Q, "regular"),
|
||||
(W, "regular"),
|
||||
(E, "regular"),
|
||||
(R, "regular"),
|
||||
(T, "regular"),
|
||||
(Y, "regular"),
|
||||
(U, "regular"),
|
||||
(I, "regular"),
|
||||
(O, "regular"),
|
||||
(P, "regular"),
|
||||
(LBracket, "regular"),
|
||||
(RBracket, "regular"),
|
||||
(BackSlash, "bkslash"),
|
||||
(Spacing, "func_space"),
|
||||
(N7, "regular"),
|
||||
(N8, "regular"),
|
||||
(N9, "regular"),
|
||||
(NumPadPlus, "numpad_tall"),
|
||||
],
|
||||
),
|
||||
(
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
row: [
|
||||
(Caps, "capsplonk"),
|
||||
(A, "regular"),
|
||||
(S, "regular"),
|
||||
(D, "regular"),
|
||||
(F, "regular"),
|
||||
(G, "regular"),
|
||||
(H, "regular"),
|
||||
(J, "regular"),
|
||||
(K, "regular"),
|
||||
(L, "regular"),
|
||||
(SemiColon, "regular"),
|
||||
(Quote, "regular"),
|
||||
(Return, "return"),
|
||||
(Spacing, "func_space"),
|
||||
(N4, "regular"),
|
||||
(N5, "regular"),
|
||||
(N6, "regular"),
|
||||
],
|
||||
),
|
||||
(
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
row: [
|
||||
(LShift, "lshift"),
|
||||
(Z, "regular"),
|
||||
(X, "regular"),
|
||||
(C, "regular"),
|
||||
(V, "regular"),
|
||||
(B, "regular"),
|
||||
(N, "regular"),
|
||||
(M, "regular"),
|
||||
(Comma, "regular"),
|
||||
(Period, "regular"),
|
||||
(FwdSlash, "regular"),
|
||||
(Rshift, "rshift"),
|
||||
(Spacing, "func_space"),
|
||||
(N1, "regular"),
|
||||
(N2, "regular"),
|
||||
(N3, "regular"),
|
||||
(NumPadEnter, "numpad_tall"),
|
||||
],
|
||||
),
|
||||
(
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
row: [
|
||||
(LCtrl, "lctrl"),
|
||||
(LFn, "regular2"),
|
||||
(Meta, "regular2"),
|
||||
(LAlt, "regular2"),
|
||||
(Spacebar, "spacebar"),
|
||||
(RAlt, "regular2"),
|
||||
(RCtrl, "rctrl"),
|
||||
(Up, "up_arrow"),
|
||||
(Spacing, "func_space"),
|
||||
(N0, "numpad_wide"),
|
||||
(NumPadDel, "regular"),
|
||||
],
|
||||
),
|
||||
(
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
row: [
|
||||
(Spacing, "arrows_spacer"),
|
||||
(Left, "arrows"),
|
||||
(Down, "arrows"),
|
||||
(Right, "arrows"),
|
||||
],
|
||||
),
|
||||
(
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
row: [
|
||||
(LightbarLeft, "lightbar_left"),
|
||||
(LightbarLeftCorner, "lightbar_corner_left"),
|
||||
(LightbarLeftBottom, "lightbar_bottom"),
|
||||
(LightbarRightBottom, "lightbar_bottom"),
|
||||
(LightbarRightCorner, "lightbar_corner_right"),
|
||||
(LightbarRight, "lightbar_right"),
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
343
rog-aura/data/layouts/g814ji-per-key_US.ron
Normal file
343
rog-aura/data/layouts/g814ji-per-key_US.ron
Normal file
@@ -0,0 +1,343 @@
|
||||
(
|
||||
locale: "US",
|
||||
key_shapes: {
|
||||
"lightbar_left": Led(
|
||||
width: 0.4,
|
||||
height: 3.0,
|
||||
pad_left: -1.0,
|
||||
pad_right: 0.1,
|
||||
pad_top: -2.7,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
"lightbar_corner_left": Led(
|
||||
width: 0.4,
|
||||
height: 0.4,
|
||||
pad_left: -0.5,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.5,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
"lightbar_bottom": Led(
|
||||
width: 11.6,
|
||||
height: 0.4,
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.5,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
"lightbar_corner_right": Led(
|
||||
width: 0.4,
|
||||
height: 0.4,
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.5,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
"lightbar_right": Led(
|
||||
width: 0.4,
|
||||
height: 3.0,
|
||||
pad_left: -0.5,
|
||||
pad_right: 0.1,
|
||||
pad_top: -2.7,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
"rog_row_spacing": Blank(
|
||||
width: 1.2,
|
||||
height: 0.0,
|
||||
),
|
||||
"arrow_spacing": Blank(
|
||||
width: 0.7,
|
||||
height: 0.0,
|
||||
),
|
||||
"rog_row": Led(
|
||||
width: 1.0,
|
||||
height: 0.8,
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.2,
|
||||
pad_bottom: 0.6,
|
||||
),
|
||||
"regular": Led(
|
||||
width: 1.0,
|
||||
height: 1.0,
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
"func_key": Led(
|
||||
width: 1.0,
|
||||
height: 0.7,
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.0,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
"func_space": Blank(
|
||||
width: 0.5,
|
||||
height: 0.0,
|
||||
),
|
||||
"esc_func_spacing": Blank(
|
||||
width: 1.2,
|
||||
height: 0.0,
|
||||
),
|
||||
"backspace": Led(
|
||||
width: 2.0,
|
||||
height: 1.0,
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
"bkslash": Led(
|
||||
width: 1.4,
|
||||
height: 1.0,
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
"tab": Led(
|
||||
width: 1.6,
|
||||
height: 1.0,
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
"rshift": Led(
|
||||
width: 1.7,
|
||||
height: 1.0,
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
"capsplonk": Led(
|
||||
width: 1.9,
|
||||
height: 1.0,
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
"return": Led(
|
||||
width: 2.3,
|
||||
height: 1.0,
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
"lshift": Led(
|
||||
width: 2.5,
|
||||
height: 1.0,
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
"lctrl": Led(
|
||||
width: 1.4,
|
||||
height: 1.0,
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
"spacebar": Led(
|
||||
width: 5.7,
|
||||
height: 1.0,
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
),
|
||||
"numpad_tall": Led(
|
||||
width: 1.0,
|
||||
height: 2.2,
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: -1.2,
|
||||
),
|
||||
},
|
||||
key_rows: [
|
||||
(
|
||||
pad_left: 0.1,
|
||||
pad_top: 0.1,
|
||||
row: [
|
||||
(Blocking, "rog_row_spacing"),
|
||||
(Blocking, "rog_row_spacing"),
|
||||
(VolDown, "rog_row"),
|
||||
(VolUp, "rog_row"),
|
||||
(MicMute, "rog_row"),
|
||||
(RogFan, "rog_row"),
|
||||
(RogApp, "rog_row"),
|
||||
],
|
||||
),
|
||||
(
|
||||
pad_left: 0.1,
|
||||
pad_top: 0.1,
|
||||
row: [
|
||||
(Esc, "func_key"),
|
||||
(Spacing, "esc_func_spacing"),
|
||||
(F1, "func_key"),
|
||||
(F2, "func_key"),
|
||||
(F3, "func_key"),
|
||||
(F4, "func_key"),
|
||||
(Spacing, "func_space"),
|
||||
(F5, "func_key"),
|
||||
(F6, "func_key"),
|
||||
(F7, "func_key"),
|
||||
(F8, "func_key"),
|
||||
(Spacing, "func_space"),
|
||||
(F9, "func_key"),
|
||||
(F10, "func_key"),
|
||||
(F11, "func_key"),
|
||||
(F12, "func_key"),
|
||||
(Del, "func_key"),
|
||||
(NumPadPause, "func_key"),
|
||||
(NumPadPrtSc, "func_key"),
|
||||
(NumPadHome, "func_key"),
|
||||
],
|
||||
),
|
||||
(
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
row: [
|
||||
(Tilde, "regular"),
|
||||
(N1, "regular"),
|
||||
(N2, "regular"),
|
||||
(N3, "regular"),
|
||||
(N4, "regular"),
|
||||
(N5, "regular"),
|
||||
(N6, "regular"),
|
||||
(N7, "regular"),
|
||||
(N8, "regular"),
|
||||
(N9, "regular"),
|
||||
(N0, "regular"),
|
||||
(Hyphen, "regular"),
|
||||
(Equals, "regular"),
|
||||
(Backspace, "backspace"),
|
||||
(NumLock, "regular"),
|
||||
(FwdSlash, "regular"),
|
||||
(Star, "regular"),
|
||||
(Hyphen, "regular"),
|
||||
],
|
||||
),
|
||||
(
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
row: [
|
||||
(Tab, "tab"),
|
||||
(Q, "regular"),
|
||||
(W, "regular"),
|
||||
(E, "regular"),
|
||||
(R, "regular"),
|
||||
(T, "regular"),
|
||||
(Y, "regular"),
|
||||
(U, "regular"),
|
||||
(I, "regular"),
|
||||
(O, "regular"),
|
||||
(P, "regular"),
|
||||
(LBracket, "regular"),
|
||||
(RBracket, "regular"),
|
||||
(BackSlash, "bkslash"),
|
||||
(N7, "regular"),
|
||||
(N8, "regular"),
|
||||
(N9, "regular"),
|
||||
(NumPadPlus, "numpad_tall"),
|
||||
],
|
||||
),
|
||||
(
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
row: [
|
||||
(Caps, "capsplonk"),
|
||||
(A, "regular"),
|
||||
(S, "regular"),
|
||||
(D, "regular"),
|
||||
(F, "regular"),
|
||||
(G, "regular"),
|
||||
(H, "regular"),
|
||||
(J, "regular"),
|
||||
(K, "regular"),
|
||||
(L, "regular"),
|
||||
(SemiColon, "regular"),
|
||||
(Quote, "regular"),
|
||||
(Return, "return"),
|
||||
(N4, "regular"),
|
||||
(N5, "regular"),
|
||||
(N6, "regular"),
|
||||
],
|
||||
),
|
||||
(
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
row: [
|
||||
(LShift, "lshift"),
|
||||
(Z, "regular"),
|
||||
(X, "regular"),
|
||||
(C, "regular"),
|
||||
(V, "regular"),
|
||||
(B, "regular"),
|
||||
(N, "regular"),
|
||||
(M, "regular"),
|
||||
(Comma, "regular"),
|
||||
(Period, "regular"),
|
||||
(FwdSlash, "regular"),
|
||||
(Rshift, "rshift"),
|
||||
(Up, "regular"),
|
||||
(N1, "regular"),
|
||||
(N2, "regular"),
|
||||
(N3, "regular"),
|
||||
(NumPadEnter, "numpad_tall"),
|
||||
],
|
||||
),
|
||||
(
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
row: [
|
||||
(LCtrl, "lctrl"),
|
||||
(LFn, "regular"),
|
||||
(Meta, "regular"),
|
||||
(LAlt, "regular"),
|
||||
(Spacebar, "spacebar"),
|
||||
(RAlt, "regular"),
|
||||
(PrtSc, "regular"),
|
||||
(RCtrl, "regular"),
|
||||
(Spacing, "arrow_spacing"),
|
||||
(Left, "regular"),
|
||||
(Down, "regular"),
|
||||
(Right, "regular"),
|
||||
(N0, "regular"),
|
||||
(NumPadDel, "regular"),
|
||||
],
|
||||
),
|
||||
(
|
||||
pad_left: 0.1,
|
||||
pad_right: 0.1,
|
||||
pad_top: 0.1,
|
||||
pad_bottom: 0.1,
|
||||
row: [
|
||||
(LightbarLeft, "lightbar_left"),
|
||||
(LightbarLeftCorner, "lightbar_corner_left"),
|
||||
(LightbarLeftBottom, "lightbar_bottom"),
|
||||
(LightbarRightBottom, "lightbar_bottom"),
|
||||
(LightbarRightCorner, "lightbar_corner_right"),
|
||||
(LightbarRight, "lightbar_right"),
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
@@ -1,5 +1,6 @@
|
||||
use log::warn;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use typeshare::typeshare;
|
||||
#[cfg(feature = "dbus")]
|
||||
use zbus::zvariant::Type;
|
||||
|
||||
@@ -190,6 +191,7 @@ impl LedCode {
|
||||
}
|
||||
|
||||
/// Represents the per-key raw USB packets
|
||||
#[typeshare]
|
||||
pub type UsbPackets = Vec<Vec<u8>>;
|
||||
|
||||
/// A `UsbPackets` contains all data to change the full set of keyboard
|
||||
@@ -199,6 +201,7 @@ pub type UsbPackets = Vec<Vec<u8>>;
|
||||
/// to the keyboard EC. One row controls one group of keys, these keys are not
|
||||
/// necessarily all on the same row of the keyboard, with some splitting between
|
||||
/// two rows.
|
||||
#[typeshare]
|
||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct LedUsbPackets {
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
use dmi_id::DMIID;
|
||||
use log::{error, info, warn};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use typeshare::typeshare;
|
||||
use zbus::zvariant::{OwnedValue, Type, Value};
|
||||
|
||||
use crate::usb::AuraDevice;
|
||||
use crate::{AdvancedAuraType, AuraModeNum, AuraZone};
|
||||
|
||||
pub const ASUS_LED_MODE_CONF: &str = "/usr/share/asusd/aura_support.ron";
|
||||
pub const ASUS_LED_MODE_USER_CONF: &str = "/etc/asusd/asusd_user_ledmodes.ron";
|
||||
pub const ASUS_KEYBOARD_DEVICES: [AuraDevice; 7] = [
|
||||
pub const ASUS_KEYBOARD_DEVICES: [AuraDevice; 8] = [
|
||||
AuraDevice::Tuf,
|
||||
AuraDevice::X1854,
|
||||
AuraDevice::X1869,
|
||||
@@ -14,11 +17,34 @@ pub const ASUS_KEYBOARD_DEVICES: [AuraDevice; 7] = [
|
||||
AuraDevice::X18c6,
|
||||
AuraDevice::X19b6,
|
||||
AuraDevice::X1a30,
|
||||
AuraDevice::X1abe,
|
||||
];
|
||||
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq, Deserialize, Serialize)]
|
||||
pub struct LedSupportFile(Vec<LaptopLedData>);
|
||||
|
||||
/// The powerr zones this laptop supports
|
||||
#[typeshare]
|
||||
#[cfg_attr(
|
||||
feature = "dbus",
|
||||
derive(Type, Value, OwnedValue),
|
||||
zvariant(signature = "u")
|
||||
)]
|
||||
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Default, Copy, Clone)]
|
||||
pub enum PowerZones {
|
||||
/// The logo on some laptop lids
|
||||
#[default]
|
||||
Logo = 0,
|
||||
/// The full keyboard (not zones)
|
||||
Keyboard = 1,
|
||||
/// The lightbar, typically on the front of the laptop
|
||||
Lightbar = 2,
|
||||
/// The leds that may be placed around the edge of the laptop lid
|
||||
Lid = 3,
|
||||
/// The led strip on the rear of some laptops
|
||||
RearGlow = 4,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, Serialize)]
|
||||
pub struct LaptopLedData {
|
||||
/// Found via `cat /sys/class/dmi/id/board_name`, e.g `GU603ZW`.
|
||||
@@ -33,26 +59,17 @@ pub struct LaptopLedData {
|
||||
pub basic_modes: Vec<AuraModeNum>,
|
||||
pub basic_zones: Vec<AuraZone>,
|
||||
pub advanced_type: AdvancedAuraType,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
|
||||
pub struct LaptopLedData456 {
|
||||
pub prod_family: String,
|
||||
pub board_names: Vec<String>,
|
||||
pub standard: Vec<AuraModeNum>,
|
||||
pub multizone: Vec<AuraZone>,
|
||||
pub per_key: bool,
|
||||
pub power_zones: Vec<PowerZones>,
|
||||
}
|
||||
|
||||
impl LaptopLedData {
|
||||
pub fn get_data() -> Self {
|
||||
let dmi = sysfs_class::DmiId::default();
|
||||
let board_name = dmi.board_name().expect("Could not get board_name");
|
||||
let dmi = DMIID::new().unwrap_or_default();
|
||||
// let prod_family = dmi.product_family().expect("Could not get
|
||||
// product_family");
|
||||
|
||||
if let Some(modes) = LedSupportFile::load_from_config() {
|
||||
if let Some(data) = modes.matcher(&board_name) {
|
||||
if let Some(modes) = LedSupportFile::load_from_supoprt_db() {
|
||||
if let Some(data) = modes.matcher(&dmi.board_name) {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@@ -78,7 +95,12 @@ impl LedSupportFile {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn load_from_config() -> Option<Self> {
|
||||
/// Load `LedSupportFile` from the `aura_support.ron` file at
|
||||
/// `/usr/share/asusd/aura_support.ron` and append with data from
|
||||
/// `/etc/asusd/asusd_user_ledmodes.ron` if that file is available.
|
||||
///
|
||||
/// Returns `None` if neither file exists or does not parse correctly.
|
||||
pub fn load_from_supoprt_db() -> Option<Self> {
|
||||
let mut loaded = false;
|
||||
let mut data = LedSupportFile::default();
|
||||
// Load user configs first so they are first to be checked
|
||||
@@ -132,7 +154,7 @@ mod tests {
|
||||
|
||||
use super::LaptopLedData;
|
||||
use crate::advanced::LedCode;
|
||||
use crate::aura_detection::LedSupportFile;
|
||||
use crate::aura_detection::{LedSupportFile, PowerZones};
|
||||
// use crate::zoned::Zone;
|
||||
use crate::{AdvancedAuraType, AuraModeNum, AuraZone};
|
||||
|
||||
@@ -144,6 +166,7 @@ mod tests {
|
||||
basic_modes: vec![AuraModeNum::Static],
|
||||
basic_zones: vec![AuraZone::Key1, AuraZone::Logo, AuraZone::BarLeft],
|
||||
advanced_type: AdvancedAuraType::Zoned(vec![LedCode::LightbarRight]),
|
||||
power_zones: vec![PowerZones::Keyboard, PowerZones::RearGlow],
|
||||
};
|
||||
|
||||
assert!(ron::to_string(&led).is_ok());
|
||||
|
||||
@@ -8,23 +8,50 @@ use std::fmt::Display;
|
||||
use std::str::FromStr;
|
||||
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use typeshare::typeshare;
|
||||
#[cfg(feature = "dbus")]
|
||||
use zbus::zvariant::Type;
|
||||
use zbus::zvariant::{OwnedValue, Type, Value};
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::LED_MSG_LEN;
|
||||
|
||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Deserialize, Serialize)]
|
||||
#[typeshare]
|
||||
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Deserialize, Serialize)]
|
||||
#[cfg_attr(
|
||||
feature = "dbus",
|
||||
derive(Type, Value, OwnedValue),
|
||||
zvariant(signature = "u")
|
||||
)]
|
||||
pub enum LedBrightness {
|
||||
Off,
|
||||
Low,
|
||||
Med,
|
||||
High,
|
||||
Off = 0,
|
||||
Low = 1,
|
||||
#[default]
|
||||
Med = 2,
|
||||
High = 3,
|
||||
}
|
||||
|
||||
impl From<u32> for LedBrightness {
|
||||
fn from(bright: u32) -> Self {
|
||||
impl LedBrightness {
|
||||
pub const fn next(&self) -> Self {
|
||||
match self {
|
||||
Self::Off => Self::Low,
|
||||
Self::Low => Self::Med,
|
||||
Self::Med => Self::High,
|
||||
Self::High => Self::Off,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn prev(&self) -> Self {
|
||||
match self {
|
||||
Self::Off => Self::High,
|
||||
Self::Low => Self::Off,
|
||||
Self::Med => Self::Low,
|
||||
Self::High => Self::Med,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u8> for LedBrightness {
|
||||
fn from(bright: u8) -> Self {
|
||||
match bright {
|
||||
0 => LedBrightness::Off,
|
||||
1 => LedBrightness::Low,
|
||||
@@ -34,13 +61,24 @@ impl From<u32> for LedBrightness {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Copy, Deserialize, Serialize)]
|
||||
pub struct Colour(pub u8, pub u8, pub u8);
|
||||
impl From<LedBrightness> for u8 {
|
||||
fn from(l: LedBrightness) -> Self {
|
||||
l as u8
|
||||
}
|
||||
}
|
||||
|
||||
#[typeshare]
|
||||
#[cfg_attr(feature = "dbus", derive(Type, Value, OwnedValue))]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Copy, Deserialize, Serialize)]
|
||||
pub struct Colour {
|
||||
pub r: u8,
|
||||
pub g: u8,
|
||||
pub b: u8,
|
||||
}
|
||||
|
||||
impl Default for Colour {
|
||||
fn default() -> Self {
|
||||
Colour(166, 0, 0)
|
||||
Colour { r: 166, g: 0, b: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,50 +92,56 @@ impl FromStr for Colour {
|
||||
let r = u8::from_str_radix(&s[0..2], 16).or(Err(Error::ParseColour))?;
|
||||
let g = u8::from_str_radix(&s[2..4], 16).or(Err(Error::ParseColour))?;
|
||||
let b = u8::from_str_radix(&s[4..6], 16).or(Err(Error::ParseColour))?;
|
||||
Ok(Colour(r, g, b))
|
||||
Ok(Colour { r, g, b })
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&[f32; 3]> for Colour {
|
||||
fn from(c: &[f32; 3]) -> Self {
|
||||
Self(
|
||||
(255.0 * c[0]) as u8,
|
||||
(255.0 * c[1]) as u8,
|
||||
(255.0 * c[2]) as u8,
|
||||
)
|
||||
Self {
|
||||
r: (255.0 * c[0]) as u8,
|
||||
g: (255.0 * c[1]) as u8,
|
||||
b: (255.0 * c[2]) as u8,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Colour> for [f32; 3] {
|
||||
fn from(c: Colour) -> Self {
|
||||
[c.0 as f32 / 255.0, c.1 as f32 / 255.0, c.2 as f32 / 255.0]
|
||||
[c.r as f32 / 255.0, c.g as f32 / 255.0, c.b as f32 / 255.0]
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&[u8; 3]> for Colour {
|
||||
fn from(c: &[u8; 3]) -> Self {
|
||||
Self(c[0], c[1], c[2])
|
||||
Self {
|
||||
r: c[0],
|
||||
g: c[1],
|
||||
b: c[2],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Colour> for [u8; 3] {
|
||||
fn from(c: Colour) -> Self {
|
||||
[c.0, c.1, c.2]
|
||||
[c.r, c.g, c.b]
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Deserialize, Serialize)]
|
||||
#[typeshare]
|
||||
#[cfg_attr(
|
||||
feature = "dbus",
|
||||
derive(Type, Value, OwnedValue),
|
||||
zvariant(signature = "s")
|
||||
)]
|
||||
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Deserialize, Serialize)]
|
||||
pub enum Speed {
|
||||
Low = 0xe1,
|
||||
#[default]
|
||||
Med = 0xeb,
|
||||
High = 0xf5,
|
||||
}
|
||||
impl Default for Speed {
|
||||
fn default() -> Self {
|
||||
Speed::Med
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Speed {
|
||||
type Err = Error;
|
||||
|
||||
@@ -124,19 +168,21 @@ impl From<Speed> for u8 {
|
||||
/// Used for Rainbow mode.
|
||||
///
|
||||
/// Enum corresponds to the required integer value
|
||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Deserialize, Serialize)]
|
||||
#[typeshare]
|
||||
#[cfg_attr(
|
||||
feature = "dbus",
|
||||
derive(Type, Value, OwnedValue),
|
||||
zvariant(signature = "s")
|
||||
)]
|
||||
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Deserialize, Serialize)]
|
||||
pub enum Direction {
|
||||
Right,
|
||||
Left,
|
||||
Up,
|
||||
Down,
|
||||
}
|
||||
impl Default for Direction {
|
||||
fn default() -> Self {
|
||||
Direction::Right
|
||||
}
|
||||
#[default]
|
||||
Right = 0,
|
||||
Left = 1,
|
||||
Up = 2,
|
||||
Down = 3,
|
||||
}
|
||||
|
||||
impl FromStr for Direction {
|
||||
type Err = Error;
|
||||
|
||||
@@ -153,9 +199,14 @@ impl FromStr for Direction {
|
||||
}
|
||||
|
||||
/// Enum of modes that convert to the actual number required by a USB HID packet
|
||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||
#[typeshare]
|
||||
#[cfg_attr(
|
||||
feature = "dbus",
|
||||
derive(Type, Value, OwnedValue),
|
||||
zvariant(signature = "u")
|
||||
)]
|
||||
#[derive(
|
||||
Debug, Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Copy, Deserialize, Serialize,
|
||||
Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Deserialize, Serialize,
|
||||
)]
|
||||
pub enum AuraModeNum {
|
||||
#[default]
|
||||
@@ -241,27 +292,38 @@ impl From<u8> for AuraModeNum {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AuraEffect> for AuraModeNum {
|
||||
fn from(value: AuraEffect) -> Self {
|
||||
value.mode
|
||||
}
|
||||
}
|
||||
|
||||
/// Base effects have no zoning, while multizone is 1-4
|
||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||
#[typeshare]
|
||||
#[cfg_attr(
|
||||
feature = "dbus",
|
||||
derive(Type, Value, OwnedValue),
|
||||
zvariant(signature = "u")
|
||||
)]
|
||||
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Deserialize, Serialize)]
|
||||
pub enum AuraZone {
|
||||
/// Used if keyboard has no zones, or if setting all
|
||||
#[default]
|
||||
None,
|
||||
None = 0,
|
||||
/// Leftmost zone
|
||||
Key1,
|
||||
Key1 = 1,
|
||||
/// Zone after leftmost
|
||||
Key2,
|
||||
Key2 = 2,
|
||||
/// Zone second from right
|
||||
Key3,
|
||||
Key3 = 3,
|
||||
/// Rightmost zone
|
||||
Key4,
|
||||
Key4 = 4,
|
||||
/// Logo on the lid (or elsewhere?)
|
||||
Logo,
|
||||
Logo = 5,
|
||||
/// The left part of a lightbar (typically on the front of laptop)
|
||||
BarLeft,
|
||||
BarLeft = 6,
|
||||
/// The right part of a lightbar
|
||||
BarRight,
|
||||
BarRight = 7,
|
||||
}
|
||||
|
||||
impl FromStr for AuraZone {
|
||||
@@ -288,7 +350,8 @@ impl FromStr for AuraZone {
|
||||
/// ```rust
|
||||
/// // let bytes: [u8; LED_MSG_LEN] = mode.into();
|
||||
/// ```
|
||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||
#[typeshare]
|
||||
#[cfg_attr(feature = "dbus", derive(Type, Value, OwnedValue))]
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct AuraEffect {
|
||||
/// The effect type
|
||||
@@ -335,14 +398,20 @@ impl Default for AuraEffect {
|
||||
Self {
|
||||
mode: AuraModeNum::Static,
|
||||
zone: AuraZone::None,
|
||||
colour1: Colour(166, 0, 0),
|
||||
colour2: Colour(0, 0, 0),
|
||||
colour1: Colour { r: 166, g: 0, b: 0 },
|
||||
colour2: Colour { r: 0, g: 0, b: 0 },
|
||||
speed: Speed::Med,
|
||||
direction: Direction::Right,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for AuraEffect {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AuraParameters {
|
||||
pub zone: bool,
|
||||
pub colour1: bool,
|
||||
@@ -408,14 +477,14 @@ impl From<&AuraEffect> for [u8; LED_MSG_LEN] {
|
||||
msg[1] = 0xb3;
|
||||
msg[2] = aura.zone as u8;
|
||||
msg[3] = aura.mode as u8;
|
||||
msg[4] = aura.colour1.0;
|
||||
msg[5] = aura.colour1.1;
|
||||
msg[6] = aura.colour1.2;
|
||||
msg[4] = aura.colour1.r;
|
||||
msg[5] = aura.colour1.g;
|
||||
msg[6] = aura.colour1.b;
|
||||
msg[7] = aura.speed as u8;
|
||||
msg[8] = aura.direction as u8;
|
||||
msg[10] = aura.colour2.0;
|
||||
msg[11] = aura.colour2.1;
|
||||
msg[12] = aura.colour2.2;
|
||||
msg[10] = aura.colour2.r;
|
||||
msg[11] = aura.colour2.g;
|
||||
msg[12] = aura.colour2.b;
|
||||
msg
|
||||
}
|
||||
}
|
||||
@@ -427,14 +496,14 @@ impl From<&AuraEffect> for Vec<u8> {
|
||||
msg[1] = 0xb3;
|
||||
msg[2] = aura.zone as u8;
|
||||
msg[3] = aura.mode as u8;
|
||||
msg[4] = aura.colour1.0;
|
||||
msg[5] = aura.colour1.1;
|
||||
msg[6] = aura.colour1.2;
|
||||
msg[4] = aura.colour1.r;
|
||||
msg[5] = aura.colour1.g;
|
||||
msg[6] = aura.colour1.b;
|
||||
msg[7] = aura.speed as u8;
|
||||
msg[8] = aura.direction as u8;
|
||||
msg[10] = aura.colour2.0;
|
||||
msg[11] = aura.colour2.1;
|
||||
msg[12] = aura.colour2.2;
|
||||
msg[10] = aura.colour2.r;
|
||||
msg[11] = aura.colour2.g;
|
||||
msg[12] = aura.colour2.b;
|
||||
msg
|
||||
}
|
||||
}
|
||||
@@ -448,7 +517,11 @@ mod tests {
|
||||
let st = AuraEffect {
|
||||
mode: AuraModeNum::Static,
|
||||
zone: AuraZone::None,
|
||||
colour1: Colour(0xff, 0x11, 0xdd),
|
||||
colour1: Colour {
|
||||
r: 0xff,
|
||||
g: 0x11,
|
||||
b: 0xdd,
|
||||
},
|
||||
colour2: Colour::default(),
|
||||
speed: Speed::Med,
|
||||
direction: Direction::Right,
|
||||
@@ -468,8 +541,12 @@ mod tests {
|
||||
let mut st = AuraEffect {
|
||||
mode: AuraModeNum::Static,
|
||||
zone: AuraZone::Key1,
|
||||
colour1: Colour(0xff, 0, 0),
|
||||
colour2: Colour(0, 0, 0),
|
||||
colour1: Colour {
|
||||
r: 0xff,
|
||||
g: 0,
|
||||
b: 0,
|
||||
},
|
||||
colour2: Colour { r: 0, g: 0, b: 0 },
|
||||
speed: Speed::Low,
|
||||
direction: Direction::Left,
|
||||
};
|
||||
@@ -480,7 +557,11 @@ mod tests {
|
||||
assert_eq!(<[u8; LED_MSG_LEN]>::from(&st)[..9], capture[..9]);
|
||||
|
||||
st.zone = AuraZone::Key2;
|
||||
st.colour1 = Colour(0xff, 0xff, 0);
|
||||
st.colour1 = Colour {
|
||||
r: 0xff,
|
||||
g: 0xff,
|
||||
b: 0,
|
||||
};
|
||||
let capture = [
|
||||
0x5d, 0xb3, 0x02, 0x00, 0xff, 0xff, 0x00, 0xe1, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0,
|
||||
@@ -488,7 +569,11 @@ mod tests {
|
||||
assert_eq!(<[u8; LED_MSG_LEN]>::from(&st)[..9], capture[..9]);
|
||||
|
||||
st.zone = AuraZone::Key3;
|
||||
st.colour1 = Colour(0, 0xff, 0xff);
|
||||
st.colour1 = Colour {
|
||||
r: 0,
|
||||
g: 0xff,
|
||||
b: 0xff,
|
||||
};
|
||||
let capture = [
|
||||
0x5d, 0xb3, 0x03, 0x00, 0x00, 0xff, 0xff, 0xe1, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0,
|
||||
@@ -496,7 +581,11 @@ mod tests {
|
||||
assert_eq!(<[u8; LED_MSG_LEN]>::from(&st)[..9], capture[..9]);
|
||||
|
||||
st.zone = AuraZone::Key4;
|
||||
st.colour1 = Colour(0xff, 0x00, 0xff);
|
||||
st.colour1 = Colour {
|
||||
r: 0xff,
|
||||
g: 0x00,
|
||||
b: 0xff,
|
||||
};
|
||||
let capture = [
|
||||
0x5d, 0xb3, 0x04, 0x00, 0xff, 0x00, 0xff, 0xe1, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0,
|
||||
@@ -504,7 +593,11 @@ mod tests {
|
||||
assert_eq!(<[u8; LED_MSG_LEN]>::from(&st)[..9], capture[..9]);
|
||||
|
||||
st.zone = AuraZone::Logo;
|
||||
st.colour1 = Colour(0x2c, 0xff, 0x00);
|
||||
st.colour1 = Colour {
|
||||
r: 0x2c,
|
||||
g: 0xff,
|
||||
b: 0x00,
|
||||
};
|
||||
let capture = [
|
||||
0x5d, 0xb3, 0x05, 0x00, 0x2c, 0xff, 0x00, 0xe1, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0,
|
||||
@@ -512,7 +605,11 @@ mod tests {
|
||||
assert_eq!(<[u8; LED_MSG_LEN]>::from(&st)[..9], capture[..9]);
|
||||
|
||||
st.zone = AuraZone::BarLeft;
|
||||
st.colour1 = Colour(0xff, 0x00, 0x00);
|
||||
st.colour1 = Colour {
|
||||
r: 0xff,
|
||||
g: 0x00,
|
||||
b: 0x00,
|
||||
};
|
||||
let capture = [
|
||||
0x5d, 0xb3, 0x06, 0x00, 0xff, 0x00, 0x00, 0xe1, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0,
|
||||
@@ -520,7 +617,11 @@ mod tests {
|
||||
assert_eq!(<[u8; LED_MSG_LEN]>::from(&st)[..9], capture[..9]);
|
||||
|
||||
st.zone = AuraZone::BarRight;
|
||||
st.colour1 = Colour(0xff, 0x00, 0xcd);
|
||||
st.colour1 = Colour {
|
||||
r: 0xff,
|
||||
g: 0x00,
|
||||
b: 0xcd,
|
||||
};
|
||||
let capture = [
|
||||
0x5d, 0xb3, 0x07, 0x00, 0xff, 0x00, 0xcd, 0xe1, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0,
|
||||
|
||||
162
rog-aura/src/deprecated.rs
Normal file
162
rog-aura/src/deprecated.rs
Normal file
@@ -0,0 +1,162 @@
|
||||
//! Older code that is not useful but stillr elevant as a reference
|
||||
|
||||
/// # Bits for newer 0x18c6, 0x19B6, 0x1a30, keyboard models
|
||||
///
|
||||
/// | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Label |
|
||||
/// |--------|---------|---------|---------|----------|
|
||||
/// |00000001| 00000000| 00000000| 00000000|boot_logo_|
|
||||
/// |00000010| 00000000| 00000000| 00000000|boot_keyb_|
|
||||
/// |00000100| 00000000| 00000000| 00000000|awake_logo|
|
||||
/// |00001000| 00000000| 00000000| 00000000|awake_keyb|
|
||||
/// |00010000| 00000000| 00000000| 00000000|sleep_logo|
|
||||
/// |00100000| 00000000| 00000000| 00000000|sleep_keyb|
|
||||
/// |01000000| 00000000| 00000000| 00000000|shut_logo_|
|
||||
/// |10000000| 00000000| 00000000| 00000000|shut_keyb_|
|
||||
/// |00000000| 00000010| 00000000| 00000000|boot_bar__|
|
||||
/// |00000000| 00000100| 00000000| 00000000|awake_bar_|
|
||||
/// |00000000| 00001000| 00000000| 00000000|sleep_bar_|
|
||||
/// |00000000| 00010000| 00000000| 00000000|shut_bar__|
|
||||
/// |00000000| 00000000| 00000001| 00000000|boot_lid__|
|
||||
/// |00000000| 00000000| 00000010| 00000000|awkae_lid_|
|
||||
/// |00000000| 00000000| 00000100| 00000000|sleep_lid_|
|
||||
/// |00000000| 00000000| 00001000| 00000000|shut_lid__|
|
||||
/// |00000000| 00000000| 00000000| 00000001|boot_rear_|
|
||||
/// |00000000| 00000000| 00000000| 00000010|awake_rear|
|
||||
/// |00000000| 00000000| 00000000| 00000100|sleep_rear|
|
||||
/// |00000000| 00000000| 00000000| 00001000|shut_rear_|
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
#[repr(u32)]
|
||||
pub enum AuraDevRog2 {
|
||||
BootLogo = 1,
|
||||
BootKeyb = 1 << 1,
|
||||
AwakeLogo = 1 << 2,
|
||||
AwakeKeyb = 1 << 3,
|
||||
SleepLogo = 1 << 4,
|
||||
SleepKeyb = 1 << 5,
|
||||
ShutdownLogo = 1 << 6,
|
||||
ShutdownKeyb = 1 << 7,
|
||||
BootBar = 1 << (7 + 2),
|
||||
AwakeBar = 1 << (7 + 3),
|
||||
SleepBar = 1 << (7 + 4),
|
||||
ShutdownBar = 1 << (7 + 5),
|
||||
BootLid = 1 << (15 + 1),
|
||||
AwakeLid = 1 << (15 + 2),
|
||||
SleepLid = 1 << (15 + 3),
|
||||
ShutdownLid = 1 << (15 + 4),
|
||||
BootRearGlow = 1 << (23 + 1),
|
||||
AwakeRearGlow = 1 << (23 + 2),
|
||||
SleepRearGlow = 1 << (23 + 3),
|
||||
ShutdownRearGlow = 1 << (23 + 4),
|
||||
}
|
||||
|
||||
impl From<AuraDevRog2> for u32 {
|
||||
fn from(a: AuraDevRog2) -> Self {
|
||||
a as u32
|
||||
}
|
||||
}
|
||||
|
||||
impl AuraDevRog2 {
|
||||
pub fn to_bytes(control: &[Self]) -> [u8; 4] {
|
||||
let mut a: u32 = 0;
|
||||
for n in control {
|
||||
a |= *n as u32;
|
||||
}
|
||||
[
|
||||
(a & 0xff) as u8,
|
||||
((a & 0xff00) >> 8) as u8,
|
||||
((a & 0xff0000) >> 16) as u8,
|
||||
((a & 0xff000000) >> 24) as u8,
|
||||
]
|
||||
}
|
||||
|
||||
pub const fn dev_id() -> &'static str {
|
||||
"0x196b"
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::deprecated::AuraDevRog2;
|
||||
|
||||
#[test]
|
||||
fn check_0x19b6_control_bytes_binary_rep() {
|
||||
fn to_binary_string(bytes: &[AuraDevRog2]) -> String {
|
||||
let bytes = AuraDevRog2::to_bytes(bytes);
|
||||
format!(
|
||||
"{:08b}, {:08b}, {:08b}, {:08b}",
|
||||
bytes[0], bytes[1], bytes[2], bytes[3]
|
||||
)
|
||||
}
|
||||
|
||||
let boot_logo_ = to_binary_string(&[AuraDevRog2::BootLogo]);
|
||||
let boot_keyb_ = to_binary_string(&[AuraDevRog2::BootKeyb]);
|
||||
let sleep_logo = to_binary_string(&[AuraDevRog2::SleepLogo]);
|
||||
let sleep_keyb = to_binary_string(&[AuraDevRog2::SleepKeyb]);
|
||||
let awake_logo = to_binary_string(&[AuraDevRog2::AwakeLogo]);
|
||||
let awake_keyb = to_binary_string(&[AuraDevRog2::AwakeKeyb]);
|
||||
let shut_logo_ = to_binary_string(&[AuraDevRog2::ShutdownLogo]);
|
||||
let shut_keyb_ = to_binary_string(&[AuraDevRog2::ShutdownKeyb]);
|
||||
let boot_bar__ = to_binary_string(&[AuraDevRog2::BootBar]);
|
||||
let awake_bar_ = to_binary_string(&[AuraDevRog2::AwakeBar]);
|
||||
let sleep_bar_ = to_binary_string(&[AuraDevRog2::SleepBar]);
|
||||
let shut_bar__ = to_binary_string(&[AuraDevRog2::ShutdownBar]);
|
||||
let boot_lid__ = to_binary_string(&[AuraDevRog2::BootLid]);
|
||||
let awkae_lid_ = to_binary_string(&[AuraDevRog2::AwakeLid]);
|
||||
let sleep_lid_ = to_binary_string(&[AuraDevRog2::SleepLid]);
|
||||
let shut_lid__ = to_binary_string(&[AuraDevRog2::ShutdownLid]);
|
||||
let boot_rear_ = to_binary_string(&[AuraDevRog2::BootRearGlow]);
|
||||
let awake_rear = to_binary_string(&[AuraDevRog2::AwakeRearGlow]);
|
||||
let sleep_rear = to_binary_string(&[AuraDevRog2::SleepRearGlow]);
|
||||
let shut_rear_ = to_binary_string(&[AuraDevRog2::ShutdownRearGlow]);
|
||||
|
||||
assert_eq!(boot_logo_, "00000001, 00000000, 00000000, 00000000");
|
||||
assert_eq!(boot_keyb_, "00000010, 00000000, 00000000, 00000000");
|
||||
assert_eq!(awake_logo, "00000100, 00000000, 00000000, 00000000");
|
||||
assert_eq!(awake_keyb, "00001000, 00000000, 00000000, 00000000");
|
||||
assert_eq!(sleep_logo, "00010000, 00000000, 00000000, 00000000");
|
||||
assert_eq!(sleep_keyb, "00100000, 00000000, 00000000, 00000000");
|
||||
assert_eq!(shut_logo_, "01000000, 00000000, 00000000, 00000000");
|
||||
assert_eq!(shut_keyb_, "10000000, 00000000, 00000000, 00000000");
|
||||
//
|
||||
assert_eq!(boot_bar__, "00000000, 00000010, 00000000, 00000000");
|
||||
assert_eq!(awake_bar_, "00000000, 00000100, 00000000, 00000000");
|
||||
assert_eq!(sleep_bar_, "00000000, 00001000, 00000000, 00000000");
|
||||
assert_eq!(shut_bar__, "00000000, 00010000, 00000000, 00000000");
|
||||
//
|
||||
assert_eq!(boot_lid__, "00000000, 00000000, 00000001, 00000000");
|
||||
assert_eq!(awkae_lid_, "00000000, 00000000, 00000010, 00000000");
|
||||
assert_eq!(sleep_lid_, "00000000, 00000000, 00000100, 00000000");
|
||||
assert_eq!(shut_lid__, "00000000, 00000000, 00001000, 00000000");
|
||||
//
|
||||
assert_eq!(boot_rear_, "00000000, 00000000, 00000000, 00000001");
|
||||
assert_eq!(awake_rear, "00000000, 00000000, 00000000, 00000010");
|
||||
assert_eq!(sleep_rear, "00000000, 00000000, 00000000, 00000100");
|
||||
assert_eq!(shut_rear_, "00000000, 00000000, 00000000, 00001000");
|
||||
|
||||
// All on
|
||||
let byte1 = [
|
||||
AuraDevRog2::BootLogo,
|
||||
AuraDevRog2::BootKeyb,
|
||||
AuraDevRog2::SleepLogo,
|
||||
AuraDevRog2::SleepKeyb,
|
||||
AuraDevRog2::AwakeLogo,
|
||||
AuraDevRog2::AwakeKeyb,
|
||||
AuraDevRog2::ShutdownLogo,
|
||||
AuraDevRog2::ShutdownKeyb,
|
||||
AuraDevRog2::BootBar,
|
||||
AuraDevRog2::AwakeBar,
|
||||
AuraDevRog2::SleepBar,
|
||||
AuraDevRog2::ShutdownBar,
|
||||
AuraDevRog2::AwakeLid,
|
||||
AuraDevRog2::BootLid,
|
||||
AuraDevRog2::SleepLid,
|
||||
AuraDevRog2::ShutdownLid,
|
||||
AuraDevRog2::AwakeRearGlow,
|
||||
AuraDevRog2::BootRearGlow,
|
||||
AuraDevRog2::SleepRearGlow,
|
||||
AuraDevRog2::ShutdownRearGlow,
|
||||
];
|
||||
let out = to_binary_string(&byte1);
|
||||
assert_eq!(out, "11111111, 00011110, 00001111, 00001111");
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user