Compare commits

..

210 Commits

Author SHA1 Message Date
Denis Benato
e9c5315bda Feat: Remove supergfxctl notification daemon 2026-01-13 22:05:34 +01:00
Denis Benato
b521a9ffc1 Fix: avoid using deprecated functions 2026-01-13 21:49:14 +01:00
Denis Benato
5e48923db1 Feat: update dependencies 2026-01-13 21:29:58 +01:00
Denis Benato
392436808d Fix text of armoury usage 2026-01-13 20:54:53 +01:00
Denis Benato
3d9a08d7e0 Silence the server 2026-01-13 20:18:49 +01:00
Denis Benato
ff103f98af Chore: change text of an error 2026-01-13 20:14:45 +01:00
Denis Benato
d05182ae64 chore: make the settings save code prettier 2026-01-13 19:29:37 +01:00
Denis Benato
a4957a6eeb Modify changelog and cargo fmt 2026-01-10 13:58:09 +01:00
Denis Benato
dda750cf33 Merge branch 'Support_additional_ga403_2025' into 'devel'
Add slash support for additional ga403 2025 models

See merge request asus-linux/asusctl!238
2026-01-10 12:54:01 +00:00
James Lademann
0b5e04393a Add slash support for additional ga403 2025 models 2026-01-10 12:54:01 +00:00
Denis Benato
c9c9a022a4 Merge branch 'fix/one-shot-charge-persistence' into 'devel'
fix: one-shot charging loses original charge limit after restart

See merge request asus-linux/asusctl!242
2026-01-10 12:51:30 +00:00
bitr8
aa063c20fd fix: persist base_charge_control_end_threshold for one-shot charging
base_charge_control_end_threshold was marked #[serde(skip)] so it only
lived in memory. triggering one-shot charge then restarting asusd would
permanently lose the original charge limit.

- remove #[serde(skip)] so the field gets persisted
- add serde default of 0 for backwards compat (skips restore for
  upgraded configs missing the field)
- add comments explaining Default vs serde default asymmetry
2026-01-05 17:23:59 +11:00
Denis Benato
8551908452 Merge branch 'devel' into 'devel'
slashctl: Add "static" LED profile

See merge request asus-linux/asusctl!240
2025-12-24 00:09:19 +00:00
Denis Benato
5ecb174b8f Merge branch 'main' into 'devel'
feat (rog-aura): Add support to FA617NT and FA617XT and update layout_name on FA617NS and FA617XS models

See merge request asus-linux/asusctl!241
2025-12-23 23:48:32 +00:00
Denis Benato
fa266bff5b Merge branch 'main' into 'devel'
Add G614JU support

See merge request asus-linux/asusctl!239
2025-12-23 23:43:41 +00:00
Seom1177
f53f1f360f Feat: update layout_name for FA617NS and FA617XS models in aura_support.ron 2025-12-22 09:06:06 -05:00
Seom1177
da19216b78 Feat: add support for FA617NT and FA617XT models to aura_support.ron 2025-12-22 09:02:25 -05:00
Some Otters
46efd4190f slashctl: Add "static" LED profile
See https://gitlab.com/asus-linux/reverse-engineering/-/blob/master/slash-bar/packets.txt?ref_type=heads . Tested working on a GU605CR
2025-12-22 10:59:17 +00:00
Hamidreza Khorsand
ed3022e25e Add G614JU support 2025-12-19 01:21:16 +03:30
Denis Benato
7c10d6c6d9 Fix: fans control for LowPower and Quiet 2025-12-18 21:53:42 +01:00
Denis Benato
af5f3a5c71 Fix: memorize last applied brightness settings 2025-12-18 15:07:14 +01:00
Denis Benato
7d5ec5f2c7 Update CHANGELOG.md 2025-12-18 03:40:03 +01:00
Denis Benato
1c8acf6de3 Feat: implement keyboard control for TUFs via asus-armoury 2025-12-18 02:10:45 +01:00
Denis Benato
7b644e7ad6 Merge branch 'main' into 'devel'
fix: add systemd scriptlets to restart asusd on package upgrade

See merge request asus-linux/asusctl!237
2025-12-15 18:12:29 +00:00
Denis Benato
0f02fe868c Fix: re-add G835L 2025-12-15 19:11:09 +01:00
Ali Abdelaal
abd3100e30 Merge upstream main, keep systemd scriptlets 2025-12-15 15:47:18 +00:00
Ali Abdelaal
6f651c2b85 Add systemd scriptlets to restart asusd on upgrade 2025-12-15 15:36:45 +00:00
Denis Benato
93ec5d1bce Feat: improve anime matrix detection 2025-12-14 15:05:10 +01:00
Denis Benato
5aea7f51c0 Chore: fix CHANGELOG.md styling 2025-12-14 15:00:51 +01:00
Denis Benato
d03d8ce67f Release: v6.2.0 2025-12-13 14:41:12 +01:00
Denis Benato
ae3693e0d9 Feat: add aura support for G614F models 2025-12-13 14:17:49 +01:00
Denis Benato
c8b9248eda Chore: update CHANGELOG.md 2025-12-13 13:56:46 +01:00
Denis Benato
22098794fe Fix: ensure upper/lower case doesn't fail the match 2025-12-13 13:48:33 +01:00
Denis Benato
10d49f4fc8 Fix: rever silly change in anime type detection 2025-12-13 13:46:29 +01:00
Denis Benato
5aba2854b0 Feat: add support for GU605C* models 2025-12-13 13:45:55 +01:00
Denis Benato
ea32ad6e0a Feat: add support for FX607V 2025-12-13 13:36:46 +01:00
Denis Benato
ee0e612c04 Feat: add AniMe support for G835LW 2025-12-13 13:35:56 +01:00
Denis Benato
e565ce748a Feat: GA403WR -> GA403W 2025-12-13 13:21:58 +01:00
Denis Benato
7024941663 Chore: fix changelog styling 2025-12-13 13:14:37 +01:00
Denis Benato
817a0165b5 Merge branch 'ga403wr' into 'devel'
add support for ga403wr, zephyrus g14 2025

See merge request asus-linux/asusctl!235
2025-12-13 12:14:19 +00:00
Denis Benato
efcd038f40 Merge branch 'main' into 'devel'
Fix: restore spec file for fedora copr builds

See merge request asus-linux/asusctl!236
2025-12-13 12:06:36 +00:00
Ali
375d99b8fc Fix: restore spec file for fedora copr builds 2025-12-13 12:06:36 +00:00
Ali Abdelaal
3a206eb76f Add asusctl as dependency for rog-gui subpackage 2025-12-11 23:49:24 +00:00
Ali Abdelaal
4449838282 Fix: remove cargo_prep which deletes Cargo.lock 2025-12-11 22:55:49 +00:00
Ali Abdelaal
58d740f77a Fix: use direct cargo build instead of cargo_build macro 2025-12-11 22:52:46 +00:00
Ali Abdelaal
f0488d9750 Build with --locked for reproducible builds 2025-12-11 22:47:00 +00:00
Ali Abdelaal
f1b9ae6f71 Fix: rewrite install section to handle Fedora rpm target dir 2025-12-11 21:48:40 +00:00
Ali Abdelaal
db5de3b854 Fix: add asusctl dir to files, remove duplicate aura_support.ron 2025-12-11 21:17:00 +00:00
Ali Abdelaal
7a3d39b8f1 Add fontconfig BuildRequires for Fedora COPR build 2025-12-11 21:01:16 +00:00
Ali Abdelaal
7a5d6325c0 Restore distro-packaging spec file for Fedora COPR builds 2025-12-11 20:46:03 +00:00
rustysec
574b954866 add support for ga403wr, zephyrus g14 2025 2025-11-29 23:49:24 -08:00
Denis Benato
a811f20f65 Release: v6.1.22 2025-11-29 02:57:34 +01:00
Denis Benato
0c9c263be6 Chore: update CHANGELOG.md 2025-11-29 02:52:27 +01:00
Denis Benato
6571c04bfe Merge branch 'devel' 2025-11-29 02:51:29 +01:00
Denis Benato
e48acbb8a2 Chore: update CHANGELOG.md 2025-11-29 02:51:16 +01:00
Denis Benato
f33496ef68 Merge branch 'main' into 'main'
Support the ROG Strix G18 (2025) G815

See merge request asus-linux/asusctl!234
2025-11-29 01:50:33 +00:00
Denis Benato
cd3176b565 Feat: improve a debug message 2025-11-29 02:48:22 +01:00
Denis Benato
7595613d7e Fix: add EXPERTBOOK to udev rules 2025-11-29 02:00:23 +01:00
Adam Bierman
b8d0245e7a Support G815L 2025-11-27 03:20:26 +00:00
Adam Bierman
54bd2ec800 Update file aura_support.ron 2025-11-27 02:44:30 +00:00
Denis Benato
b6c8566565 Feat: Treat dGPU attributes the same as PPT attributes for power-profile 2025-11-23 17:12:55 +01:00
Denis Benato
052c096014 Fix: use the correct name for nv_tgp 2025-11-23 16:56:47 +01:00
Denis Benato
81cbe3c522 Chore(Makefile): install cargo-vendor-filterer 2025-11-20 14:04:35 +01:00
Denis Benato
09f7492bec Release: fuck fedora 2025-11-20 02:59:41 +01:00
Denis Benato
6adfb2cf48 Fix: Release process 2025-11-18 23:03:58 +01:00
Denis Benato
a2a56792a8 Chore: changelog for 6.1.20 2025-11-18 22:56:42 +01:00
Denis Benato
317daf4ed1 Release: 6.1.20 2025-11-18 22:50:35 +01:00
Denis Benato
eb0d9514b5 Merge branch 'devel' 2025-11-18 22:36:27 +01:00
LucaP
d324b1bce5 Feat: Added support for G635L* models. Lightbar, Logo, Matrix 2025-11-18 22:32:49 +01:00
Denis Benato
d1c7385146 Merge branch 'main' into 'main'
Feat: Added support for G635L* models. Lightbar, Logo, Matrix

See merge request asus-linux/asusctl!233
2025-11-18 21:31:13 +00:00
Denis Benato
48a4935fc7 Fix: don't spam the console 2025-11-18 21:36:48 +01:00
LucaP
7e917b91a5 Feat: Added support for G635L* models. Lightbar, Logo, Matrix 2025-11-17 20:12:30 +02:00
Denis Benato
45f8b8ffb0 Chore: attempt another CI fix 2025-11-16 14:43:40 +01:00
Denis Benato
031a36242b Chore: Spare memory on CI 2025-11-16 14:17:24 +01:00
Denis Benato
8ad26ad136 Fix: CI testing 2025-11-15 18:57:14 +01:00
Denis Benato
907d4694f3 Merge branch 'devel' 2025-11-15 18:17:38 +01:00
Denis Benato
1dcc4ff502 Update CHANGELOG.md 2025-11-15 18:15:55 +01:00
Denis Benato
cf232047b0 Merge branch 'patch-1' into 'main'
Add aura support for G614FR (ROG Strix G16 2025)

See merge request asus-linux/asusctl!232
2025-11-15 15:08:19 +00:00
Henry Zhang
ff99ec9a39 Add aura support for G614FR (ROG Strix G16 2025) 2025-11-15 16:13:38 +08:00
Denis Benato
8a19374a41 Merge branch 'aura-support-fa617xs' into 'main'
Add aura support for ASUS TUF Gaming A16 (FA617XS, AMD Advantage Edition)

Closes #696

See merge request asus-linux/asusctl!231
2025-11-14 06:56:21 +00:00
AB
4cec1f49b4 Add FA617XS (TUF A16 AMD Advantage Edition) support to aura_support.ron 2025-11-12 16:29:38 +05:30
Denis Benato
01aae200f3 Fix: do not crash if no battery is present 2025-11-11 22:41:54 +01:00
Denis Benato
4c6db9f0a9 Chore: ignore push-blocking features that would make older rust toolchains error 2025-11-11 22:21:32 +01:00
Denis Benato
7207d3287a Chore: avoid rebuilding after make 2025-11-11 22:03:45 +01:00
Denis Benato
1b2d8d83fc Chore: prepare for 6.1.18 release 2025-11-11 21:55:42 +01:00
Denis Benato
6d8db91583 Chore: reduce trace logging from libraries 2025-11-11 21:49:00 +01:00
Denis Benato
20c3628476 Chore: update dependencies 2025-11-11 21:44:27 +01:00
Denis Benato
4edecfce1c Merge commit '34699a7021a85e1c0ba3d6ac0876c6beb8ae394f' 2025-11-11 21:39:01 +01:00
Denis Benato
34699a7021 Fix: notifications not respecting settings 2025-11-06 02:57:20 +01:00
Denis Benato
ef311689ec Fix: do not stall the boot process 2025-11-06 00:55:20 +01:00
Denis Benato
8ee0281b4f Fix: fedora build 2025-11-05 22:40:58 +01:00
Denis Benato
d8504b5430 Changelog for 6.1.17 2025-11-05 21:14:21 +01:00
Denis Benato
5c4d833fbd Prepare for 6.1.17 2025-11-05 21:09:18 +01:00
Denis Benato
698999e828 cargo fmt and README.md restyle 2025-11-05 20:02:43 +01:00
Denis Benato
0eae9e55c6 Merge branch 'devel' 2025-11-05 19:54:21 +01:00
Denis Benato
07171888a1 Merge branch 'main' into 'main'
feat: Allow setting default profile for ac and battery

See merge request asus-linux/asusctl!229
2025-11-05 18:53:53 +00:00
matszwe02
9321fde6af feat: Allow setting default profile for ac and battery 2025-11-05 01:44:31 +01:00
Denis Benato
f90d0a6673 Merge branch 'devel' into 'devel'
Add install-data-asusd_user to install-data in Makefile

See merge request asus-linux/asusctl!228
2025-10-29 18:49:50 +00:00
Synby
bbd03c128d Edit Makefile
add install-data-asusd_user to install-data
2025-10-29 17:23:29 +00:00
Denis Benato
132a2f3665 Chore: complete the switch back to stable 2025-10-23 14:50:40 +02:00
Denis Benato
180566e5f1 Fix: share a single HID device
Avoid opening multiple handles to the same device whenever possible.
2025-10-22 22:05:17 +02:00
Denis Benato
c9e76f3273 Chore: prepare for 6.1.16 release 2025-10-20 19:15:36 +02:00
Denis Benato
2997ae83ff Merge branch 'devel' 2025-10-20 04:08:20 +02:00
Denis Benato
151d681e16 feat: expose MCU Powersave toggle on rogcc 2025-10-20 03:47:09 +02:00
Denis Benato
90b3f43a36 Chore: add more debugging 2025-10-20 02:49:47 +02:00
Denis Benato
a345b09ce1 Chore: type abttery -> battery 2025-10-20 02:46:07 +02:00
Denis Benato
f26b0d8de5 Merge branch 'profile-match' into 'main'
Allow flexible profile cli input for LowPower

See merge request asus-linux/asusctl!226
2025-10-20 00:40:54 +00:00
yanganto
9366b0ec04 Allow flexible profile cli input for LowPower 2025-10-20 00:40:54 +00:00
Denis Benato
415712143b Feat: add screen_auto_brightness 2025-10-20 02:08:59 +02:00
Denis Benato
60fce30a06 Chore: flush out requirement for nightly 2025-10-20 00:39:17 +02:00
Denis Benato
d8f06230fa Chore: Added support for FX607J 2025-10-19 23:02:45 +02:00
Denis Benato
834464a527 Fix: fixed ac_command/bat_command 2025-10-19 23:00:23 +02:00
Denis Benato
4faa96298a Chore: Added supprot for G614JIR 2025-10-19 22:32:05 +02:00
Denis Benato
78c574b761 chore_ add supprot for GU605CR 2025-10-19 21:27:33 +02:00
Denis Benato
9785eafd53 Modified to README.md to not mislead users attempting to compile it 2025-10-19 20:45:49 +02:00
Denis Benato
51cad9ea7e chore: make the startup more verbose 2025-10-16 15:17:27 +02:00
Denis Benato
319373faea chore: Prepare for 6.1.15 release 2025-10-14 01:57:03 +02:00
Denis Benato
f6aa3e3d01 Merge branch 'devel' 2025-10-14 01:50:20 +02:00
Denis Benato
d11fc20bab feat: apply the proper configuration depending on the plug status 2025-10-13 21:36:01 +02:00
Denis Benato
b0e1b21e4b chore: cargo clippy fix 2025-10-12 22:34:20 +02:00
Denis Benato
1c1daaa6d2 chore: reimplement default for FanCurveCPU 2025-10-12 19:47:26 +02:00
HiFiPhile
c3b5de843f Add TX Air rule 2025-10-12 19:44:30 +02:00
Denis Benato
09dcfb4065 Fix multiple warnings 2025-10-12 19:43:07 +02:00
Denis Benato
b2e7211bbe chore: cargo fmt 2025-10-12 19:43:05 +02:00
Denis Benato
1ab1adf937 Merge branch 'tx_air' into 'main'
Add TX Air (TUF Chinese version) udev rule

See merge request asus-linux/asusctl!227
2025-10-12 17:42:09 +00:00
HiFiPhile
a21bf779b0 Add TX Air rule 2025-10-12 13:20:07 +02:00
Denis Benato
0dba22529c feat: change limits dynamically 2025-10-11 20:51:57 +02:00
Denis Benato
180d63620b Fix multiple warnings 2025-10-08 01:19:38 +02:00
Denis Benato
daea1f538c chore: cargo fmt 2025-10-08 01:01:43 +02:00
Denis Benato
f5e2484797 chore: release 6.1.14 2025-10-08 00:56:25 +02:00
Denis Benato
7105ae40c6 chore: attempt to fix tests 2025-10-08 00:35:09 +02:00
Denis Benato
33f9900ef9 chore: fix formatting 2025-10-08 00:19:43 +02:00
Denis Benato
1aa1c62e40 chore: update spec file version to 6.1.13 2025-10-07 23:47:09 +02:00
Denis Benato
3a18ef4c7b chore: Prepare for 6.1.13 release 2025-10-07 23:47:02 +02:00
Denis Benato
9dcce77302 chore: fix a warning 2025-10-06 19:37:30 +02:00
Denis Benato
995df9b51b fix: fix building due to a double-borrow 2025-10-06 19:29:29 +02:00
Denis Benato
84c8babdb7 fix: make the startup path more robust 2025-10-06 19:19:31 +02:00
Denis Benato
1014f97b6f fix: apply panel overdrive and other properties on asusd startup 2025-10-05 23:13:41 +02:00
Denis Benato
3c023be57d chore: update changelog for the upcoming release 2025-10-05 17:29:51 +02:00
Denis Benato
eff20c84d6 chore: add ubuntu install instructions 2025-10-05 17:29:12 +02:00
Denis Benato
f8984eb7e9 chore: update crates 2025-10-05 17:18:24 +02:00
Denis Benato
2ffd2a1e1f chore: compile packages on make install 2025-10-05 16:58:03 +02:00
Denis Benato
341bd081f8 chore: fix makefile 2025-10-05 16:45:29 +02:00
Denis Benato
52af4203a1 Merge remote-tracking branch 'github/main' 2025-10-05 16:15:36 +02:00
Denis Benato
e5a6088392 Merge pull request #84 from evertvorster/patch-1
Update asusd.rules to have absolute path
2025-10-05 16:15:20 +02:00
Denis Benato
6ee5dfb352 chore: require power-profile-daemon on fedora 2025-10-05 16:07:58 +02:00
Evert Vorster
3f8336fc5e Update asusd.rules
Added the absolute path for systemctl. No modern distrobution installs it anywhere else.
2025-10-05 16:02:48 +02:00
Denis Benato
8fc7e8f3a7 Merge remote-tracking branch 'gitlab/main' 2025-10-05 16:02:08 +02:00
Denis Benato
098b1f2668 chore: add *.patch to gitignore 2025-10-05 15:57:20 +02:00
Denis Benato
20df3ad2f2 Merge remote-tracking branch 'github/main' 2025-10-05 15:52:50 +02:00
Denis Benato
7aaadad6da Merge pull request #39 from rashadgasimli/main
Add Azerbaijani language
2025-10-05 15:48:37 +02:00
Luke Jones
be60c1ba02 Merge pull request #69 from kxxt/tx
Add udev match for TX Gaming
2025-06-10 12:28:47 +12:00
kxxt
698a8e8677 Add udev match for TX Gaming 2025-05-29 20:38:05 +08:00
fluke
ce6420eeac Merge branch 'aura-support-fx706heb' into 'main'
Add AURA support definition for 2021 TUF F17

See merge request asus-linux/asusctl!225
2025-05-19 08:53:03 +00:00
fluke
f5f5e4f720 Edit FX706HEB to become FX706H and match more models 2025-05-19 08:52:11 +00:00
Brandon Tolbird
c08503826b Add AURA support definition for 2021 TUF F17
(FX706HEB)
2025-05-18 22:20:42 +00:00
Luke Jones
685345d656 chore: update spec file version to 6.1.12 2025-04-06 13:51:55 +12:00
Luke Jones
59aab24a4a Fix unbouneded loop and prep new version 2025-04-06 13:26:53 +12:00
Luke Jones
c3f0e61ebc chore: update spec file version to 6.1.11 2025-04-05 21:51:35 +13:00
Luke Jones
c143536cd0 Prep new release 2025-04-06 07:55:06 +12:00
Luke Jones
2a168e93d3 chore: update translations 2025-04-06 07:36:21 +12:00
Luke Jones
c3570a23f1 feature: add UI controls fro screenpad 2025-04-06 07:36:21 +12:00
Luke Jones
9db6cb5545 feature: watch primary backlight and sync screenpad to it 2025-04-06 02:41:46 +12:00
Luke Jones
836575c0a8 feature: screenpad settings config store 2025-04-06 02:09:45 +13:00
Luke Jones
61f2216c25 fix: minor clippy fix 2025-04-06 01:04:03 +13:00
Luke Jones
7f5b3ef376 feature: add support for screenpad brightness 2025-04-06 01:04:03 +13:00
fluke
257471a36c Merge branch 'fix/anime-flicker' into 'main'
Fix anime flickering when repeatedly setting images in a tight loop

See merge request asus-linux/asusctl!223
2025-03-27 21:13:25 +00:00
I-Al-Istannen
568f3e848f Fix anime flickering when repeatedly setting images in a tight loop 2025-03-27 21:05:23 +01:00
fluke
0c9b58755f Merge branch 'pt_BR-translation' into 'main'
Include pt_BR translations file.

See merge request asus-linux/asusctl!222
2025-03-25 01:18:33 +00:00
PabloKiryu
1b47fb7873 Include pt_BR translations file. 2025-03-18 00:32:25 -03:00
Denis Benato
df93209839 chore: Install LICENSE file 2025-03-13 01:28:06 +01:00
Denis Benato
11ee7827e9 chore: Add packaging instructions for deb
This commits adds .deb packaging support for all applications in this repository.
2025-03-12 18:18:08 +00:00
Denis Benato
c337de5139 chore(Makefile): split up install by package 2025-03-12 16:54:35 +01:00
Luke Jones
d55c2befed chore: update spec file version to 6.1.10 2025-03-04 09:21:53 +13:00
Luke Jones
4cd9918e1a asusd: single line fix for profile switching 2025-03-04 09:21:52 +13:00
Luke Jones
3a900f23fe ROGCC: better handling of fan curve profile 2025-03-03 20:20:09 +13:00
Luke Jones
aee465aced chore: update spec file version to 6.1.9 2025-03-03 19:58:37 +13:00
Luke Jones
192e5ccaa3 ROGCC: better handling of platform profile 2025-03-03 18:22:26 +13:00
Luke Jones
f164583792 ROGCC: fix fancurve quiet fans incorrect enablement 2025-03-02 20:50:57 +13:00
Luke Jones
b4d657b866 ROGCC: fix PPT sliders 2025-03-02 20:39:16 +13:00
Luke Jones
f7bf7aeef9 ROGCC: fix displaying ppt-toggle switch 2025-03-02 16:24:17 +13:00
Luke Jones
2cd4c4850f Extra debug output in ROGCC 2025-03-02 15:15:06 +13:00
Luke Jones
805ccfe451 Merge pull request #51 from sergik776/main
Added translation files for rog-control-center (RU)
2025-03-01 19:47:04 +13:00
Luke Jones
5655f63dff Cleanup 2025-03-01 16:27:50 +13:00
sergik776
a2795e4d78 Full translation into Russian 2025-02-26 10:51:33 +02:00
sergik776
0684c16bf5 Full translation into Russian 2025-02-26 10:24:17 +02:00
Luke Jones
a08ca3af98 chore: update spec file version to 6.1.8 2025-02-22 12:45:20 +13:00
Luke Jones
efa379e778 Add opensuse CI 2025-02-21 17:12:47 +13:00
Luke Jones
5cbf0816fe chore: update translations 2025-02-18 22:12:56 +13:00
Luke Jones
2951d3926c Update git hooks 2025-02-18 22:12:54 +13:00
Luke Jones
eb19d59d52 Update distro packaging 2025-02-18 22:12:53 +13:00
guylamar2006
3e4d594b05 Fix thread 'main' panicked at asusctl/src/main.rs:85:14: 2025-02-17 21:13:42 +00:00
Luke Jones
ae8ce83583 Fix slash enable 2025-02-17 11:38:29 +13:00
Luke Jones
5c3348a9f5 Add small env fixes for Ally
Signed-off-by: Luke Jones <luke@ljones.dev>
2025-02-16 23:18:58 +13:00
Luke Jones
f299ffeb6e Disable skia again, new release 2025-02-16 21:46:04 +13:00
Luke Jones
21c468cf02 Update supergfx
Signed-off-by: Luke Jones <luke@ljones.dev>
2025-02-16 11:50:56 +13:00
Luke Jones
7f12f62ad5 Temp 2025-02-16 09:38:33 +13:00
Luke Jones
5fb0e26331 Fix git losing the last set of fixes. Prep new release
Signed-off-by: Luke Jones <luke@ljones.dev>
2025-02-14 22:23:11 +13:00
Luke Jones
4dd29952c8 Fix the handling of of the kernel change from "quiet" to "low-power"
A coming kernel change will convert "quiet" to "low-power" due to how
platform_profile can now have multiple registered handlers.
(kernel 6.14 est)

Fixes #609
2025-02-14 20:02:08 +13:00
Luke Jones
2c006699f2 Reformat with trailing comma 2025-02-14 20:00:11 +13:00
Luke Jones
0bdf0474c9 Small error message fix 2025-02-14 20:00:11 +13:00
Kamo Kuma
66196ceb17 systemctl is-enabled can return 'linked' even if service is enabled. 2025-02-10 21:00:21 -05:00
Luke Jones
b2726f3a67 Fix: charge control 2025-02-10 22:18:34 +13:00
Luke Jones
663f87d5e2 Checkpoint 2025-02-10 13:56:26 +13:00
Luke Jones
377bb4d6ad Merge branch 'private/Rohitrajak1807/G513RW-ledfix' into 'main'
Add ROG G513RW led cfgs

See merge request asus-linux/asusctl!217
2025-02-10 00:55:33 +00:00
Rohit Rajak
98e60db2da Add ROG G513RW led cfgs 2025-02-10 00:55:33 +00:00
sergik776
a206591e97 Added translation files for rog-control-center (RU) 2025-01-28 20:09:20 +02:00
Rəşad Qasımlı
c5c5a9ac67 Update rog-control-center.mo 2024-07-20 14:35:45 +04:00
Rəşad Qasımlı
b84bc61f3d Update the information about translator 2024-07-20 00:59:47 +04:00
Rəşad Qasımlı
b4e38e0814 Add Azerbaijani language 2024-07-19 23:47:41 +04:00
152 changed files with 9237 additions and 4305 deletions

53
.cargo-husky/hooks/post-commit Executable file
View File

@@ -0,0 +1,53 @@
#!/bin/sh
set -e
ROOT_DIR=$(git rev-parse --show-toplevel)
AURA_DATA="${ROOT_DIR}/rog-aura/data/aura_support.ron"
SPEC_FILE="${ROOT_DIR}/distro-packaging/asusctl.spec"
TRANSLATION="${ROOT_DIR}/rog-control-center/translations/en/rog-control-center.po"
VERSION=$(grep -Pm1 'version = "(\d+.\d+.\d+.*)"' "${ROOT_DIR}/Cargo.toml" | cut -d'"' -f2)
if [ -z "$VERSION" ]; then
echo "Error: Could not extract version from Cargo.toml"
exit 1
fi
if [ ! -f "$SPEC_FILE" ]; then
echo "Error: Spec file not found at ${SPEC_FILE}"
exit 1
fi
# Update spec file
sed -i "s/^%define version.*/%define version ${VERSION}/" "$SPEC_FILE"
if git diff --quiet "$SPEC_FILE"; then
echo "No changes to spec file"
else
git add "$SPEC_FILE"
git commit --no-verify -m "chore: update spec file version to ${VERSION}"
echo "Updated spec file version to ${VERSION}"
fi
# Update translations only if UI files changed
if git diff-tree -r HEAD@{1} HEAD --name-only | grep -q "^rog-control-center/ui/"; then
echo 'find -name \*.slint | xargs slint-tr-extractor -o ${TRANSLATION}'
find -name \*.slint | xargs slint-tr-extractor -o $TRANSLATION
if git diff --quiet "$TRANSLATION"; then
echo "No changes to translation file"
else
git add "$TRANSLATION"
git commit --no-verify -m "chore: update translations"
echo "Updated ${TRANSLATION}"
fi
else
echo "No changes in rog-control-center/ui/, skipping translation update"
fi
# Update aura data
cargo test --package rog_aura --lib -- aura_detection::tests::check_data_file_parse --exact
cargo test --package rog_aura --lib -- aura_detection::tests::find_data_file_groups --exact
if git diff --quiet "$AURA_DATA"; then
echo "No changes to aura data file"
else
git add "$AURA_DATA"
git commit --no-verify -m "chore: update aura data"
echo "Updated $AURA_DATA"
fi

View File

@@ -1,18 +1,6 @@
#!/bin/sh #!/bin/sh
set -e set -e
echo 'find -name \*.slint | xargs slint-tr-extractor -o rog-control-center/translations/en/rog-control-center.po' echo '+cargo fmt --all -- --check'
find -name \*.slint | xargs slint-tr-extractor -o rog-control-center/translations/en/rog-control-center.po cargo fmt --all -- --check
git add -u
echo '+cargo +nightly fmt --all -- --check'
cargo +nightly fmt --all -- --check
echo '+cargo clippy --all -- -D warnings'
cargo clippy --all -- -D warnings
echo '+cargo test --all'
cargo test --all -- --test-threads=1
echo '+cargo cranky'
cargo cranky

View File

@@ -2,8 +2,8 @@
set -e set -e
echo '+cargo +nightly fmt --all -- --check' echo '+cargo fmt --all -- --check'
cargo +nightly fmt --all -- --check cargo fmt --all -- --check
echo '+cargo clippy --all -- -D warnings' echo '+cargo clippy --all -- -D warnings'
cargo clippy --all -- -D warnings cargo clippy --all -- -D warnings
echo '+cargo cranky' echo '+cargo cranky'

1
.gitignore vendored
View File

@@ -9,6 +9,7 @@ vendor_*
.vscode .vscode
.~lock.* .~lock.*
*.ods# *.ods#
*.patch
# gnome extension # gnome extension
node-modules node-modules

View File

@@ -1,22 +1,26 @@
image: rust:latest image: rust:latest
# Use shallow clone to reduce checkout size
variables:
GIT_DEPTH: "1"
# Put cargo home and target under project dir so we can clean them easily
CARGO_HOME: "$CI_PROJECT_DIR/.cargo"
CARGO_TARGET_DIR: "$CI_PROJECT_DIR/ci-target"
GIT_SUBMODULE_STRATEGY: normal
# Cache only cargo registries/git metadata to speed dependency fetches.
# Avoid caching compiled `target` artifacts which are large and easily fill disk.
.rust_cache: &rust_cache .rust_cache: &rust_cache
cache: cache:
# key: $CI_COMMIT_REF_SLUG key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
paths: paths:
# Don't include `incremental` to save space - .cargo/registry
# Debug - .cargo/git
- target/debug/build/
- target/debug/deps/
- target/debug/.fingerprint/
- target/debug/.cargo-lock
# Release
- target/release/build/
- target/release/deps/
- target/release/.fingerprint/
- target/release/.cargo-lock
before_script: before_script:
- df -h
- echo "Cleaning stale targets to free space if present"
- rm -rf "$CI_PROJECT_DIR/target" "$CI_PROJECT_DIR/ci-target" || true
- apt-get update -qq && apt-get install -y -qq libudev-dev libgtk-3-dev grep llvm clang libclang-dev libsdl2-dev libsdl2-gfx-dev - apt-get update -qq && apt-get install -y -qq libudev-dev libgtk-3-dev grep llvm clang libclang-dev libsdl2-dev libsdl2-gfx-dev
stages: stages:
@@ -31,20 +35,24 @@ format:
- tags - tags
<<: *rust_cache <<: *rust_cache
script: script:
- echo "nightly" > rust-toolchain - rustup component add rustfmt || true
- rustup component add rustfmt
- cargo fmt --check - cargo fmt --check
after_script:
- du -sh "$CI_PROJECT_DIR/ci-target" || true
- rm -rf "$CI_PROJECT_DIR/ci-target" || true
check: check:
except: except:
- tags - tags
<<: *rust_cache <<: *rust_cache
script: script:
- rustup component add clippy - rustup component add clippy || true
- cargo check - cargo check --locked --workspace
# deny currently catches too much # deny currently catches too much
#- cargo install cargo-deny && cargo deny #- cargo install cargo-deny && cargo deny
- cargo install cargo-cranky && cargo cranky - cargo install cargo-cranky && cargo cranky
after_script:
- rm -rf "$CI_PROJECT_DIR/ci-target" || true
test: test:
except: except:
@@ -52,7 +60,9 @@ test:
<<: *rust_cache <<: *rust_cache
script: script:
- mkdir -p .git/hooks > /dev/null - mkdir -p .git/hooks > /dev/null
- cargo test --all -- --test-threads=1 - cargo test --locked --all
after_script:
- rm -rf "$CI_PROJECT_DIR/ci-target" || true
release: release:
only: only:
@@ -60,11 +70,15 @@ release:
<<: *rust_cache <<: *rust_cache
script: script:
- cargo install cargo-vendor-filterer - cargo install cargo-vendor-filterer
- make && make vendor - cargo fetch
- make FROZEN=1 && make vendor
artifacts: artifacts:
paths: paths:
- vendor_asusctl*.tar.xz - vendor_asusctl*.tar.xz
- cargo-config - cargo-config
expire_in: 1 week
after_script:
- rm -rf vendor vendor_asusctl*.tar.xz "$CI_PROJECT_DIR/ci-target" || true
pages: pages:
stage: deploy stage: deploy
@@ -72,14 +86,14 @@ pages:
- tags - tags
<<: *rust_cache <<: *rust_cache
script: script:
- cargo doc --document-private-items --no-deps --workspace - cargo doc --locked --document-private-items --no-deps --workspace
- rm -rf public - rm -rf public
- mkdir public - mkdir public
- cp -R target/doc/* public - cp -R ci-target/doc/* public
- cp extra/index.html public - cp extra/index.html public
artifacts: artifacts:
paths: paths:
- public - public
expire_in: 1 week
variables: after_script:
GIT_SUBMODULE_STRATEGY: normal - rm -rf "$CI_PROJECT_DIR/ci-target" || true

View File

@@ -2,8 +2,148 @@
## [Unreleased] ## [Unreleased]
### Changed
- Added support for TUF keyboard powerstate control
- Improved AniMe Matrix support thanks to @Seom1177 !
- Fixed a bug with one-shot battery change, thanks @bitr8 !
## [6.2.0]
### Changed
- Added aura support for FX607V: thanks @jomp16
- Added testing support for G835LW
- Added support for GU605C models slash lighting: thanks @Otters
- Restore fedora: thanks @ali205412
- Add support to G614F models slash lighting
## [6.1.22]
### Changed
- Allow configuration of nv_tgp
- Treat dGPU attributes as power profiles
- Add EXPERTBOOK DMI match to ensure the service is loaded
- Support G815L thanks to @solost !
## [6.1.21]
### Changed
- Kill Fedora: screw your cursed cargo bullshit
- Restore CI building
## [6.1.20]
### Changed
- Addded support for G635L: thanks @luca_pisl !
- Suppress verbose output in applications too, not just daemon
## [6.1.18]
### Changed
- Add aura support for G614FR (ROG Strix G16 2025)
- all notifications now respects the timeout
- improve udev daemon-starting rule
- reduce log noise
## [v6.1.17]
### Changed
- Fix Makefile
- Share a single HID device
## [v6.1.16]
### Changed
- Expose more properties via rog-control-center
- Add support for a few more models
## [v6.1.15]
### Changed
- Reflect the current asus-armoury status on AC plug connection status change
## [v6.1.14]
### Changed
- Fix formatting
- Attempt to fix tests
## [v6.1.13]
### Changed
- Fix a problem in reloading the service (@evertvorster)
- Add Azerbaijani language (@rashadgasimli)
- Add Ubuntu installation instructions
## [v6.1.12]
### Changed
- Fix an unbounded event loop caused by other processes causing a "modify" event on the screen backlight brightness.
## [v6.1.11]
### Changed
- Fix anime flickering issue when using custom anims (@I-Al-Istannen)
- Include pt_BR translations file (@PabloKiryu)
## Added
- Support for the screenpad brightness on some Laptops. This includes syncing to the primary screen brightness, and a gamma adjustment to set brightness scaling.
- Add asusctl CLI options
- Add UI options
- Add a fake gamma correction (`asusctl backlight --sync-screenpad-brightness`, 1.5 for example sets screenpad low brightness lower than primary, and scales upwards)
### Changed
- asusd: single line fix for profile switching
## [v6.1.9]
### Changed
- ROGCC: better handling of platform profiles
## [v6.1.8]
### Changed
- Testing CI for opensuse RPM build
- ROGCC: Fixes to showing the PPT enablement toggle
- ROGCC: Fixes to how PPT and NV sliders work and enable/disable
- RGOCC: Fix quiet fan-curves availability
## [v6.1.7]
### Changed
- Fix Slash display enable
## [v6.1.6]
### Changed
- Disable skia bindings for UI again. It causes failures in build pipelines and requires extra dependencies.
## [v6.1.5]
### Changed
- Update dependencies
- Fix fan-curve proxy type signatures
## [v6.1.4]
### Changed
- Fix git doing me a dirty
## [v6.1.3]
### Changed
- Many small bugfixes such as for platform profile switching
## [v6.1.2]
### Changed
- Try a slightly different tact to fix charge control slider
## [v6.1.1]
### Changed ### Changed
- Fix aura data matching - Fix aura data matching
- Fix charge control slider
## [v6.1.0] ## [v6.1.0]

3893
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
[workspace.package] [workspace.package]
version = "6.1.0" version = "6.2.0"
rust-version = "1.82" rust-version = "1.82"
license = "MPL-2.0" license = "MPL-2.0"
readme = "README.md" readme = "README.md"
@@ -43,8 +43,9 @@ dirs = "^4.0"
smol = "^2.0" smol = "^2.0"
mio = "0.8.11" mio = "0.8.11"
zbus = "5.1" futures-util = "0.3.31"
logind-zbus = { version = "5.0.0" } #, default-features = false, features = ["non_blocking"] } zbus = "5.13.1"
logind-zbus = { version = "5.2.0" } #, default-features = false, features = ["non_blocking"] }
serde = { version = "^1.0", features = ["serde_derive"] } serde = { version = "^1.0", features = ["serde_derive"] }
ron = "*" ron = "*"
@@ -56,16 +57,16 @@ glam = { version = "^0.22", features = ["serde"] }
gumdrop = "^0.8" gumdrop = "^0.8"
udev = { version = "^0.8", features = ["mio"] } udev = { version = "^0.8", features = ["mio"] }
rusb = "^0.9" rusb = "^0.9"
inotify = "^0.10.0" inotify = "^0.10"
png_pong = "^0.8" png_pong = "^0.8"
pix = "^0.13" pix = "^0.13"
tinybmp = "^0.4.0" tinybmp = "^0.4"
gif = "^0.12.0" gif = "^0.12"
versions = "6.2" versions = "6.2"
notify-rust = { version = "4.11.0", features = ["z", "async"] } notify-rust = { version = "4.11.5", features = ["z", "async"] }
sg = { git = "https://github.com/flukejones/sg-rs.git" } sg = { git = "https://github.com/flukejones/sg-rs.git" }
@@ -76,15 +77,15 @@ lto = "fat"
debug = false debug = false
opt-level = 3 opt-level = 3
panic = "abort" panic = "abort"
codegen-units = 1 # codegen-units = 1
[profile.dev] [profile.dev]
opt-level = 1 opt-level = 1
codegen-units = 16 # codegen-units = 1
[profile.dev.package."*"] [profile.dev.package."*"]
opt-level = 1 opt-level = 1
codegen-units = 16 # codegen-units = 1
[profile.bench] [profile.bench]
debug = false debug = false

View File

@@ -48,7 +48,7 @@ The LED controller (e.g, aura) enables setting many of the factory modes availab
#### Supported laptops #### Supported laptops
There are over 60 supported laptops as of 01-01-2023. Please see [the rog-aura crate readme for further details](/rog-aura/README.md). There are over 80 supported laptops as of 01-01-2023. Please see [the rog-aura crate readme for further details](/rog-aura/README.md).
### Charge control ### Charge control
@@ -420,13 +420,13 @@ To switch to next/previous Aura modes you will need to bind both the aura keys (
**Next** **Next**
``` ```
asusctl led-mode -n asusctl aura -n
``` ```
**Previous** **Previous**
``` ```
asusctl led-mode -p asusctl aura -p
``` ```
To switch Fan/Thermal profiles you need to bind the Fn+F5 key to `asusctl profile -n`. To switch Fan/Thermal profiles you need to bind the Fn+F5 key to `asusctl profile -n`.

View File

@@ -17,6 +17,8 @@ BIN_D := asusd
BIN_U := asusd-user BIN_U := asusd-user
LEDCFG := aura_support.ron LEDCFG := aura_support.ron
DESTDIR_REALPATH = $(shell realpath $(DESTDIR))
SRC := Cargo.toml Cargo.lock Makefile $(shell find -type f -wholename '**/src/*.rs') SRC := Cargo.toml Cargo.lock Makefile $(shell find -type f -wholename '**/src/*.rs')
STRIP_BINARIES ?= 0 STRIP_BINARIES ?= 0
@@ -35,6 +37,15 @@ ifeq ($(X11),1)
ARGS += --features "rog-control-center/x11" ARGS += --features "rog-control-center/x11"
endif endif
# Always use the versions in Cargo.lock by default
ARGS += --locked
# Allow optionally freezing the build to avoid any network access and enforce Cargo.lock strictly
FROZEN ?= 0
ifeq ($(FROZEN),1)
ARGS += --frozen
endif
VENDORED ?= 0 VENDORED ?= 0
ifeq ($(VENDORED),1) ifeq ($(VENDORED),1)
ARGS += --frozen ARGS += --frozen
@@ -48,24 +59,38 @@ clean:
distclean: distclean:
rm -rf .cargo vendor vendor.tar.xz rm -rf .cargo vendor vendor.tar.xz
install-program: target/$(TARGET)/$(BIN_D): $(SRC)
$(INSTALL_PROGRAM) "./target/$(TARGET)/$(BIN_ROG)" "$(DESTDIR)$(bindir)/$(BIN_ROG)" $(MAKE) build
$(INSTALL_PROGRAM) "./target/$(TARGET)/$(BIN_C)" "$(DESTDIR)$(bindir)/$(BIN_C)" target/$(TARGET)/$(BIN_C): $(SRC)
$(MAKE) build
target/$(TARGET)/$(BIN_U): $(SRC)
$(MAKE) build
target/$(TARGET)/$(BIN_ROG): $(SRC)
$(MAKE) build
install-asusd: target/$(TARGET)/$(BIN_D)
$(INSTALL_PROGRAM) "./target/$(TARGET)/$(BIN_D)" "$(DESTDIR)$(bindir)/$(BIN_D)" $(INSTALL_PROGRAM) "./target/$(TARGET)/$(BIN_D)" "$(DESTDIR)$(bindir)/$(BIN_D)"
install-asusctl: target/$(TARGET)/$(BIN_C)
$(INSTALL_PROGRAM) "./target/$(TARGET)/$(BIN_C)" "$(DESTDIR)$(bindir)/$(BIN_C)"
install-asusd_user: target/$(TARGET)/$(BIN_U)
$(INSTALL_PROGRAM) "./target/$(TARGET)/$(BIN_U)" "$(DESTDIR)$(bindir)/$(BIN_U)" $(INSTALL_PROGRAM) "./target/$(TARGET)/$(BIN_U)" "$(DESTDIR)$(bindir)/$(BIN_U)"
install-data: install-rog_gui: target/$(TARGET)/$(BIN_ROG)
$(INSTALL_PROGRAM) "./target/$(TARGET)/$(BIN_ROG)" "$(DESTDIR)$(bindir)/$(BIN_ROG)"
.PHONY: install-asusd install-asusctl install-asusd_user install-rog_gui
install-program: install-asusd install-asusctl install-asusd_user install-rog_gui
install-data-rog_gui:
$(INSTALL_DATA) "./rog-control-center/data/$(BIN_ROG).desktop" "$(DESTDIR)$(datarootdir)/applications/$(BIN_ROG).desktop" $(INSTALL_DATA) "./rog-control-center/data/$(BIN_ROG).desktop" "$(DESTDIR)$(datarootdir)/applications/$(BIN_ROG).desktop"
$(INSTALL_DATA) "./rog-control-center/data/$(BIN_ROG).png" "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/$(BIN_ROG).png" $(INSTALL_DATA) "./rog-control-center/data/$(BIN_ROG).png" "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/$(BIN_ROG).png"
cd rog-aura/data/layouts && find . -type f -name "*.ron" -exec $(INSTALL_DATA) "{}" "$(DESTDIR)$(datarootdir)/rog-gui/layouts/{}" \; cd rog-aura/data/layouts && find . -type f -name "*.ron" -exec $(INSTALL_DATA) "{}" "$(DESTDIR_REALPATH)$(datarootdir)/rog-gui/layouts/{}" \;
$(INSTALL_DATA) "./data/$(BIN_D).rules" "$(DESTDIR)$(libdir)/udev/rules.d/99-$(BIN_D).rules"
$(INSTALL_DATA) "./rog-aura/data/$(LEDCFG)" "$(DESTDIR)$(datarootdir)/asusd/$(LEDCFG)"
$(INSTALL_DATA) "./data/$(BIN_D).conf" "$(DESTDIR)$(datarootdir)/dbus-1/system.d/$(BIN_D).conf"
$(INSTALL_DATA) "./data/$(BIN_D).service" "$(DESTDIR)$(libdir)/systemd/system/$(BIN_D).service"
$(INSTALL_DATA) "./data/$(BIN_U).service" "$(DESTDIR)$(libdir)/systemd/user/$(BIN_U).service"
$(INSTALL_DATA) "./data/icons/asus_notif_yellow.png" "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_yellow.png" $(INSTALL_DATA) "./data/icons/asus_notif_yellow.png" "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_yellow.png"
$(INSTALL_DATA) "./data/icons/asus_notif_green.png" "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_green.png" $(INSTALL_DATA) "./data/icons/asus_notif_green.png" "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_green.png"
@@ -81,9 +106,24 @@ install-data:
$(INSTALL_DATA) "./data/icons/scalable/gpu-vfio.svg" "$(DESTDIR)$(datarootdir)/icons/hicolor/scalable/status/gpu-vfio.svg" $(INSTALL_DATA) "./data/icons/scalable/gpu-vfio.svg" "$(DESTDIR)$(datarootdir)/icons/hicolor/scalable/status/gpu-vfio.svg"
$(INSTALL_DATA) "./data/icons/scalable/notification-reboot.svg" "$(DESTDIR)$(datarootdir)/icons/hicolor/scalable/status/notification-reboot.svg" $(INSTALL_DATA) "./data/icons/scalable/notification-reboot.svg" "$(DESTDIR)$(datarootdir)/icons/hicolor/scalable/status/notification-reboot.svg"
cd rog-anime/data && find "./anime" -type f -exec $(INSTALL_DATA) "{}" "$(DESTDIR)$(datarootdir)/asusd/{}" \; install-data-asusd:
$(INSTALL_DATA) "./data/$(BIN_D).rules" "$(DESTDIR)$(libdir)/udev/rules.d/99-$(BIN_D).rules"
$(INSTALL_DATA) "./rog-aura/data/$(LEDCFG)" "$(DESTDIR)$(datarootdir)/asusd/$(LEDCFG)"
$(INSTALL_DATA) "./data/$(BIN_D).conf" "$(DESTDIR)$(datarootdir)/dbus-1/system.d/$(BIN_D).conf"
$(INSTALL_DATA) "./data/$(BIN_D).service" "$(DESTDIR)$(libdir)/systemd/system/$(BIN_D).service"
cd rog-anime/data && find "./anime" -type f -exec $(INSTALL_DATA) "{}" "$(DESTDIR_REALPATH)$(datarootdir)/asusd/{}" \;
install-data-asusd_user:
$(INSTALL_DATA) "./data/$(BIN_U).service" "$(DESTDIR)$(libdir)/systemd/user/$(BIN_U).service"
.PHONY: install-data-asusd install-data-asusd_user
install-data: install-data-asusd install-data-asusd_user install-data-rog_gui
install: install-program install-data install: install-program install-data
$(INSTALL_DATA) "./LICENSE" "$(DESTDIR)$(datarootdir)/asusctl/LICENSE"
uninstall: uninstall:
rm -f "$(DESTDIR)$(bindir)/$(BIN_ROG)" rm -f "$(DESTDIR)$(bindir)/$(BIN_ROG)"
@@ -118,6 +158,8 @@ vendor:
mv .cargo/config ./cargo-config mv .cargo/config ./cargo-config
rm -rf .cargo rm -rf .cargo
rm -rf vendor rm -rf vendor
# Ensure cargo-vendor-filterer is installed (CI installs it already)
command -v cargo-vendor-filterer >/dev/null 2>&1 || cargo install --locked cargo-vendor-filterer
cargo vendor-filterer --all-features --platform x86_64-unknown-linux-gnu vendor cargo vendor-filterer --all-features --platform x86_64-unknown-linux-gnu vendor
tar pcfJ vendor_asusctl_$(VERSION).tar.xz vendor tar pcfJ vendor_asusctl_$(VERSION).tar.xz vendor
rm -rf vendor rm -rf vendor

View File

@@ -46,13 +46,13 @@ See the [rog-aura readme](./rog-aura/README.md) for more details.
Most ASUS gaming laptops that have a USB keyboard. If `lsusb` shows something similar Most ASUS gaming laptops that have a USB keyboard. If `lsusb` shows something similar
to this: to this:
``` ```plain
Bus 001 Device 002: ID 0b05:1866 ASUSTek Computer, Inc. N-KEY Device Bus 001 Device 002: ID 0b05:1866 ASUSTek Computer, Inc. N-KEY Device
``` ```
or or
``` ```plain
Bus 003 Device 002: ID 0b05:19b6 ASUSTek Computer, Inc. [unknown] Bus 003 Device 002: ID 0b05:19b6 ASUSTek Computer, Inc. [unknown]
``` ```
@@ -74,43 +74,56 @@ The list is a bit outdated as many features have been enabled in the Linux kerne
- [x] Toggle bios setting for boot/POST sound - [x] Toggle bios setting for boot/POST sound
- [x] Toggle GPU MUX (g-sync, or called MUX on 2022+ laptops) - [x] Toggle GPU MUX (g-sync, or called MUX on 2022+ laptops)
# GUI ## GUI
A gui is now in the repo - ROG Control Center. At this time it is still a WIP, but it has almost all features in place already. A gui is now in the repo - ROG Control Center. At this time it is still a WIP, but it has almost all features in place already.
**NOTE**: Xorg is not supported. **NOTE**: Xorg is not supported.
# BUILDING ## BUILDING
Rust and cargo are required, they can be installed from [rustup.rs](https://rustup.rs/) or from the distro repos if newer than 1.75. Rust and cargo are required, they can be installed from [rustup.rs](https://rustup.rs/).
Distro packaging should work with the stable toolchain. If your distro does not provide a recent Rust toolchain, install rustup and use the stable toolchain.
**fedora:** **fedora:**
dnf install cmake clang-devel libxkbcommon-devel systemd-devel expat-devel pcre2-devel libzstd-devel gtk3-devel ```sh
make dnf install cmake clang-devel libxkbcommon-devel systemd-devel expat-devel pcre2-devel libzstd-devel gtk3-devel
sudo make install make
sudo make install
```
**openSUSE:** **openSUSE:**
Works with KDE Plasma (without GTK packages) Works with KDE Plasma (without GTK packages)
zypper in -t pattern devel_basis ```sh
zypper in rustup make cmake clang-devel libxkbcommon-devel systemd-devel expat-devel pcre2-devel libzstd-devel gtk3-devel zypper in -t pattern devel_basis
make zypper in rustup make cmake clang-devel libxkbcommon-devel systemd-devel expat-devel pcre2-devel libzstd-devel gtk3-devel
sudo make install make
sudo make install
```
**Debian(unsuported):** **Debian(unsuported):**
officially unsuported,but you can still try and test it by yourself(some features may not be available). officially unsuported,but you can still try and test it by yourself(some features may not be available).
sudo apt install libclang-dev libudev-dev libfontconfig-dev build-essential cmake libxkbcommon-dev ```sh
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh sudo apt install libclang-dev libudev-dev libfontconfig-dev build-essential cmake libxkbcommon-dev
make curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
sudo make install make
sudo make install
```
**Ubuntu, Popos (unsuported):** **Ubuntu, Popos (unsuported):**
instructions removed as outdated ```sh
sudo apt install make cargo gcc pkg-config openssl libasound2-dev cmake build-essential python3 libfreetype6-dev libexpat1-dev libxcb-composite0-dev libssl-dev libx11-dev libfontconfig1-dev curl libclang-dev libudev-dev checkinstall libseat-dev libinput-dev libxkbcommon-dev libgbm-dev
make
sudo make install
```
## Installing ## Installing
@@ -128,15 +141,15 @@ You may also need to activate the service for debian install. If running Pop!\_O
If you are upgrading from a previous installed version, you will need to restart the service or reboot. If you are upgrading from a previous installed version, you will need to restart the service or reboot.
``` ```sh
$ systemctl daemon-reload && systemctl restart asusd systemctl daemon-reload && systemctl restart asusd
``` ```
## Uninstalling ## Uninstalling
Run `sudo make uninstall` in the source repo, and remove `/etc/asusd/`. Run `sudo make uninstall` in the source repo, and remove `/etc/asusd/`.
# Contributing ## Contributing
See `CONTRIBUTING.md`. Additionally, also do `cargo clean` and `cargo test` on first checkout to ensure the commit hooks are used (via `cargo-husky`). See `CONTRIBUTING.md`. Additionally, also do `cargo clean` and `cargo test` on first checkout to ensure the commit hooks are used (via `cargo-husky`).
@@ -144,17 +157,17 @@ Generation of the bindings with `make bindings` requires `typeshare` to be insta
Dbus introsepction XML requires with `make introspection` requires `anime_sim` to be running before starting `asusd`. Dbus introsepction XML requires with `make introspection` requires `anime_sim` to be running before starting `asusd`.
# OTHER ## OTHER
## AniMe Matrix simulator ### 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. 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 ### Supporting more laptops
Please file a support request. Please file a support request.
# License & Trademarks ## License & Trademarks
Mozilla Public License 2 (MPL-2.0) Mozilla Public License 2 (MPL-2.0)

View File

@@ -27,3 +27,15 @@ zbus.workspace = true
[dev-dependencies] [dev-dependencies]
rog_dbus = { path = "../rog-dbus" } rog_dbus = { path = "../rog-dbus" }
[package.metadata.deb]
license-file = ["../LICENSE", "4"]
extended-description = """\
An utility for Linux to control many aspects of various ASUS laptops
but can also be used with non-asus laptops with reduced features."""
depends = "$auto"
section = "utility"
priority = "optional"
assets = [
["target/release/asusctl", "usr/bin/", "755"],
]

View File

@@ -23,7 +23,7 @@ fn main() -> Result<(), Box<dyn Error>> {
Path::new(&args[1]), Path::new(&args[1]),
None, None,
args[2].parse::<f32>().unwrap(), args[2].parse::<f32>().unwrap(),
AnimeType::GA401 AnimeType::GA401,
)?; )?;
let anime_type = get_anime_type(); let anime_type = get_anime_type();

View File

@@ -21,11 +21,14 @@ fn main() {
let brightness = args[2].parse::<f32>().unwrap(); let brightness = args[2].parse::<f32>().unwrap();
let anime_type = get_anime_type(); let anime_type = get_anime_type();
let mut seq = Sequences::new(anime_type); let mut seq = Sequences::new(anime_type);
seq.insert(0, &ActionLoader::AsusAnimation { seq.insert(
0,
&ActionLoader::AsusAnimation {
file: path.into(), file: path.into(),
time: rog_anime::AnimTime::Infinite, time: rog_anime::AnimTime::Infinite,
brightness brightness,
}) },
)
.unwrap(); .unwrap();
loop { loop {

View File

@@ -27,10 +27,10 @@ fn main() -> Result<(), Box<dyn Error>> {
args[3].parse::<f32>().unwrap(), args[3].parse::<f32>().unwrap(),
Vec2::new( Vec2::new(
args[4].parse::<f32>().unwrap(), args[4].parse::<f32>().unwrap(),
args[5].parse::<f32>().unwrap() args[5].parse::<f32>().unwrap(),
), ),
args[6].parse::<f32>().unwrap(), args[6].parse::<f32>().unwrap(),
anime_type anime_type,
)?; )?;
proxy.write(<AnimeDataBuffer>::try_from(&matrix)?).unwrap(); proxy.write(<AnimeDataBuffer>::try_from(&matrix)?).unwrap();

View File

@@ -30,10 +30,10 @@ fn main() -> Result<(), Box<dyn Error>> {
args[3].parse::<f32>().unwrap(), args[3].parse::<f32>().unwrap(),
Vec2::new( Vec2::new(
args[4].parse::<f32>().unwrap(), args[4].parse::<f32>().unwrap(),
args[5].parse::<f32>().unwrap() args[5].parse::<f32>().unwrap(),
), ),
args[6].parse::<f32>().unwrap(), args[6].parse::<f32>().unwrap(),
anime_type anime_type,
)?; )?;
loop { loop {

View File

@@ -36,10 +36,10 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
Colour { Colour {
r: 200, r: 200,
g: 110, g: 110,
b: 0 b: 0,
}, },
100, 100,
10 10,
)); ));
seq.push(zone); seq.push(zone);

View File

@@ -40,7 +40,7 @@ pub struct AnimeCommand {
#[options(no_short, meta = "", help = "Off with his head!!!")] #[options(no_short, meta = "", help = "Off with his head!!!")]
pub off_with_his_head: Option<bool>, pub off_with_his_head: Option<bool>,
#[options(command)] #[options(command)]
pub command: Option<AnimeActions> pub command: Option<AnimeActions>,
} }
#[derive(Options)] #[derive(Options)]
@@ -54,7 +54,7 @@ pub enum AnimeActions {
#[options(help = "display an animated diagonal/pixel-perfect GIF")] #[options(help = "display an animated diagonal/pixel-perfect GIF")]
PixelGif(AnimeGifDiagonal), PixelGif(AnimeGifDiagonal),
#[options(help = "change which builtin animations are shown")] #[options(help = "change which builtin animations are shown")]
SetBuiltins(Builtins) SetBuiltins(Builtins),
} }
#[derive(Options)] #[derive(Options)]
@@ -82,7 +82,7 @@ pub struct Builtins {
)] )]
pub shutdown: AnimShutdown, pub shutdown: AnimShutdown,
#[options(meta = "", help = "set/apply the animations <true/false>")] #[options(meta = "", help = "set/apply the animations <true/false>")]
pub set: Option<bool> pub set: Option<bool>,
} }
#[derive(Options)] #[derive(Options)]
@@ -100,7 +100,7 @@ pub struct AnimeImage {
#[options(meta = "", default = "0.0", help = "the angle in radians")] #[options(meta = "", default = "0.0", help = "the angle in radians")]
pub angle: f32, pub angle: f32,
#[options(meta = "", default = "1.0", help = "brightness 0.0-1.0")] #[options(meta = "", default = "1.0", help = "brightness 0.0-1.0")]
pub bright: f32 pub bright: f32,
} }
#[derive(Options)] #[derive(Options)]
@@ -110,7 +110,7 @@ pub struct AnimeImageDiagonal {
#[options(meta = "", help = "full path to the png to display")] #[options(meta = "", help = "full path to the png to display")]
pub path: String, pub path: String,
#[options(meta = "", default = "1.0", help = "brightness 0.0-1.0")] #[options(meta = "", default = "1.0", help = "brightness 0.0-1.0")]
pub bright: f32 pub bright: f32,
} }
#[derive(Options)] #[derive(Options)]
@@ -134,7 +134,7 @@ pub struct AnimeGif {
default = "1", default = "1",
help = "how many loops to play - 0 is infinite" help = "how many loops to play - 0 is infinite"
)] )]
pub loops: u32 pub loops: u32,
} }
#[derive(Options)] #[derive(Options)]
@@ -150,5 +150,5 @@ pub struct AnimeGifDiagonal {
default = "1", default = "1",
help = "how many loops to play - 0 is infinite" help = "how many loops to play - 0 is infinite"
)] )]
pub loops: u32 pub loops: u32,
} }

View File

@@ -17,7 +17,7 @@ pub struct LedPowerCommand1 {
#[options(meta = "", help = "Control boot animations <true/false>")] #[options(meta = "", help = "Control boot animations <true/false>")]
pub boot: Option<bool>, pub boot: Option<bool>,
#[options(meta = "", help = "Control suspend animations <true/false>")] #[options(meta = "", help = "Control suspend animations <true/false>")]
pub sleep: Option<bool> pub sleep: Option<bool>,
} }
#[derive(Options, Debug)] #[derive(Options, Debug)]
@@ -25,7 +25,7 @@ pub struct LedPowerCommand2 {
#[options(help = "print help message")] #[options(help = "print help message")]
pub help: bool, pub help: bool,
#[options(command)] #[options(command)]
pub command: Option<SetAuraZoneEnabled> pub command: Option<SetAuraZoneEnabled>,
} }
#[derive(Options, Debug)] #[derive(Options, Debug)]
@@ -42,7 +42,7 @@ pub enum SetAuraZoneEnabled {
#[options(help = "")] #[options(help = "")]
RearGlow(AuraPowerStates), RearGlow(AuraPowerStates),
#[options(help = "")] #[options(help = "")]
Ally(AuraPowerStates) Ally(AuraPowerStates),
} }
#[derive(Debug, Clone, Options)] #[derive(Debug, Clone, Options)]
@@ -56,12 +56,12 @@ pub struct AuraPowerStates {
#[options(help = "defaults to false if option unused")] #[options(help = "defaults to false if option unused")]
pub sleep: bool, pub sleep: bool,
#[options(help = "defaults to false if option unused")] #[options(help = "defaults to false if option unused")]
pub shutdown: bool pub shutdown: bool,
} }
#[derive(Options)] #[derive(Options)]
pub struct LedBrightness { pub struct LedBrightness {
level: Option<u8> level: Option<u8>,
} }
impl LedBrightness { impl LedBrightness {
pub fn new(level: Option<u8>) -> Self { pub fn new(level: Option<u8>) -> Self {
@@ -96,7 +96,7 @@ impl ToString for LedBrightness {
Some(0x00) => "low", Some(0x00) => "low",
Some(0x01) => "med", Some(0x01) => "med",
Some(0x02) => "high", Some(0x02) => "high",
_ => "unknown" _ => "unknown",
}; };
s.to_owned() s.to_owned()
} }
@@ -113,7 +113,7 @@ pub struct SingleSpeed {
meta = "", meta = "",
help = "set the zone for this effect e.g, 0, 1, one, logo, lightbar-left" help = "set the zone for this effect e.g, 0, 1, one, logo, lightbar-left"
)] )]
pub zone: AuraZone pub zone: AuraZone,
} }
#[derive(Debug, Clone, Options, Default)] #[derive(Debug, Clone, Options, Default)]
@@ -129,7 +129,7 @@ pub struct SingleSpeedDirection {
meta = "", meta = "",
help = "set the zone for this effect e.g, 0, 1, one, logo, lightbar-left" help = "set the zone for this effect e.g, 0, 1, one, logo, lightbar-left"
)] )]
pub zone: AuraZone pub zone: AuraZone,
} }
#[derive(Debug, Clone, Default, Options)] #[derive(Debug, Clone, Default, Options)]
@@ -143,7 +143,7 @@ pub struct SingleColour {
meta = "", meta = "",
help = "set the zone for this effect e.g, 0, 1, one, logo, lightbar-left" help = "set the zone for this effect e.g, 0, 1, one, logo, lightbar-left"
)] )]
pub zone: AuraZone pub zone: AuraZone,
} }
#[derive(Debug, Clone, Default, Options)] #[derive(Debug, Clone, Default, Options)]
@@ -159,7 +159,7 @@ pub struct SingleColourSpeed {
meta = "", meta = "",
help = "set the zone for this effect e.g, 0, 1, one, logo, lightbar-left" help = "set the zone for this effect e.g, 0, 1, one, logo, lightbar-left"
)] )]
pub zone: AuraZone pub zone: AuraZone,
} }
#[derive(Debug, Clone, Options, Default)] #[derive(Debug, Clone, Options, Default)]
@@ -177,10 +177,11 @@ pub struct TwoColourSpeed {
meta = "", meta = "",
help = "set the zone for this effect e.g, 0, 1, one, logo, lightbar-left" help = "set the zone for this effect e.g, 0, 1, one, logo, lightbar-left"
)] )]
pub zone: AuraZone pub zone: AuraZone,
} }
#[derive(Debug, Clone, Default, Options)] #[derive(Debug, Clone, Default, Options)]
#[allow(dead_code)]
pub struct MultiZone { pub struct MultiZone {
#[options(help = "print help message")] #[options(help = "print help message")]
help: bool, help: bool,
@@ -191,10 +192,11 @@ pub struct MultiZone {
#[options(short = "c", meta = "", help = "set the RGB value e.g, ff00ff")] #[options(short = "c", meta = "", help = "set the RGB value e.g, ff00ff")]
pub colour3: Colour, pub colour3: Colour,
#[options(short = "d", meta = "", help = "set the RGB value e.g, ff00ff")] #[options(short = "d", meta = "", help = "set the RGB value e.g, ff00ff")]
pub colour4: Colour pub colour4: Colour,
} }
#[derive(Debug, Clone, Default, Options)] #[derive(Debug, Clone, Default, Options)]
#[allow(dead_code)]
pub struct MultiColourSpeed { pub struct MultiColourSpeed {
#[options(help = "print help message")] #[options(help = "print help message")]
help: bool, help: bool,
@@ -207,7 +209,7 @@ pub struct MultiColourSpeed {
#[options(short = "d", meta = "", help = "set the RGB value e.g, ff00ff")] #[options(short = "d", meta = "", help = "set the RGB value e.g, ff00ff")]
pub colour4: Colour, pub colour4: Colour,
#[options(no_long, meta = "", help = "set the speed: low, med, high")] #[options(no_long, meta = "", help = "set the speed: low, med, high")]
pub speed: Speed pub speed: Speed,
} }
/// Byte value for setting the built-in mode. /// Byte value for setting the built-in mode.
@@ -239,7 +241,7 @@ pub enum SetAuraBuiltin {
#[options(help = "set a vertical line zooming from left")] #[options(help = "set a vertical line zooming from left")]
Comet(SingleColour), // 11 Comet(SingleColour), // 11
#[options(help = "set a wide vertical line zooming from left")] #[options(help = "set a wide vertical line zooming from left")]
Flash(SingleColour) // 12 Flash(SingleColour), // 12
} }
impl Default for SetAuraBuiltin { impl Default for SetAuraBuiltin {

View File

@@ -26,7 +26,7 @@ pub struct CliStart {
#[options(help = "Toggle one-shot battery charge to 100%")] #[options(help = "Toggle one-shot battery charge to 100%")]
pub one_shot_chg: bool, pub one_shot_chg: bool,
#[options(command)] #[options(command)]
pub command: Option<CliCommand> pub command: Option<CliCommand>,
} }
#[derive(Options)] #[derive(Options)]
@@ -53,7 +53,9 @@ pub enum CliCommand {
help = "Change platform settings. This is a new interface exposed by the asus-armoury \ help = "Change platform settings. This is a new interface exposed by the asus-armoury \
driver, some of the settings will be the same as the older platform interface" driver, some of the settings will be the same as the older platform interface"
)] )]
Armoury(ArmouryCommand) Armoury(ArmouryCommand),
#[options(name = "backlight", help = "Set screen backlight levels")]
Backlight(BacklightCommand),
} }
#[derive(Debug, Clone, Options)] #[derive(Debug, Clone, Options)]
@@ -71,7 +73,17 @@ pub struct ProfileCommand {
pub profile_get: bool, pub profile_get: bool,
#[options(meta = "", help = "set the active profile")] #[options(meta = "", help = "set the active profile")]
pub profile_set: Option<PlatformProfile> pub profile_set: Option<PlatformProfile>,
#[options(short = "a", meta = "", help = "set the profile to use on AC power")]
pub profile_set_ac: Option<PlatformProfile>,
#[options(
short = "b",
meta = "",
help = "set the profile to use on battery power"
)]
pub profile_set_bat: Option<PlatformProfile>,
} }
#[derive(Options)] #[derive(Options)]
@@ -83,13 +95,13 @@ pub struct LedModeCommand {
#[options(help = "switch to previous aura mode")] #[options(help = "switch to previous aura mode")]
pub prev_mode: bool, pub prev_mode: bool,
#[options(command)] #[options(command)]
pub command: Option<SetAuraBuiltin> pub command: Option<SetAuraBuiltin>,
} }
#[derive(Options)] #[derive(Options)]
pub struct GraphicsCommand { pub struct GraphicsCommand {
#[options(help = "print help message")] #[options(help = "print help message")]
pub help: bool pub help: bool,
} }
#[derive(Options, Debug)] #[derive(Options, Debug)]
@@ -100,5 +112,23 @@ pub struct ArmouryCommand {
free, free,
help = "append each value name followed by the value to set. `-1` sets to default" help = "append each value name followed by the value to set. `-1` sets to default"
)] )]
pub free: Vec<String> pub free: Vec<String>,
}
#[derive(Options)]
pub struct BacklightCommand {
#[options(help = "print help message")]
pub help: bool,
#[options(meta = "", help = "Set screen brightness <0-100>")]
pub screenpad_brightness: Option<i32>,
#[options(
meta = "",
help = "Set screenpad gamma brightness 0.5 - 2.2, 1.0 == linear"
)]
pub screenpad_gamma: Option<f32>,
#[options(
meta = "",
help = "Set screenpad brightness to sync with primary display"
)]
pub sync_screenpad_brightness: Option<bool>,
} }

View File

@@ -45,5 +45,5 @@ pub struct FanCurveCommand {
help = "data format = 30c:1%,49c:2%,59c:3%,69c:4%,79c:31%,89c:49%,99c:56%,109c:58%. \ 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" `--mod-profile` required. If '%' is omitted the fan range is 0-255"
)] )]
pub data: Option<CurveData> pub data: Option<CurveData>,
} }

View File

@@ -9,7 +9,7 @@ use aura_cli::{LedPowerCommand1, LedPowerCommand2};
use dmi_id::DMIID; use dmi_id::DMIID;
use fan_curve_cli::FanCurveCommand; use fan_curve_cli::FanCurveCommand;
use gumdrop::{Opt, Options}; use gumdrop::{Opt, Options};
use log::{error, info}; use log::{error, info, LevelFilter};
use rog_anime::usb::get_anime_type; use rog_anime::usb::get_anime_type;
use rog_anime::{AnimTime, AnimeDataBuffer, AnimeDiagonal, AnimeGif, AnimeImage, AnimeType, Vec2}; use rog_anime::{AnimTime, AnimeDataBuffer, AnimeDiagonal, AnimeGif, AnimeImage, AnimeType, Vec2};
use rog_aura::keyboard::{AuraPowerState, LaptopAuraPower}; use rog_aura::keyboard::{AuraPowerState, LaptopAuraPower};
@@ -19,6 +19,7 @@ use rog_dbus::list_iface_blocking;
use rog_dbus::scsi_aura::ScsiAuraProxyBlocking; use rog_dbus::scsi_aura::ScsiAuraProxyBlocking;
use rog_dbus::zbus_anime::AnimeProxyBlocking; use rog_dbus::zbus_anime::AnimeProxyBlocking;
use rog_dbus::zbus_aura::AuraProxyBlocking; use rog_dbus::zbus_aura::AuraProxyBlocking;
use rog_dbus::zbus_backlight::BacklightProxyBlocking;
use rog_dbus::zbus_fan_curves::FanCurvesProxyBlocking; use rog_dbus::zbus_fan_curves::FanCurvesProxyBlocking;
use rog_dbus::zbus_platform::PlatformProxyBlocking; use rog_dbus::zbus_platform::PlatformProxyBlocking;
use rog_dbus::zbus_slash::SlashProxyBlocking; use rog_dbus::zbus_slash::SlashProxyBlocking;
@@ -43,12 +44,16 @@ mod scsi_cli;
mod slash_cli; mod slash_cli;
fn main() { fn main() {
// Ensure tracing spans are quiet by default unless user overrides
if std::env::var_os("RUST_LOG").is_none() {
std::env::set_var("RUST_LOG", "warn,tracing=error,zbus=error");
}
let mut logger = env_logger::Builder::new(); let mut logger = env_logger::Builder::new();
logger logger
.parse_default_env() .parse_default_env()
.target(env_logger::Target::Stdout) .filter_level(LevelFilter::Info)
.target(env_logger::Target::Stderr)
.format_timestamp(None) .format_timestamp(None)
.filter_level(log::LevelFilter::Debug)
.init(); .init();
let self_version = env!("CARGO_PKG_VERSION"); let self_version = env!("CARGO_PKG_VERSION");
@@ -74,22 +79,36 @@ fn main() {
println!("\nError: {e}\n"); println!("\nError: {e}\n");
print_info(); print_info();
}) { }) {
let asusd_version = platform_proxy let asusd_version = match platform_proxy.version() {
.version() Ok(version) => version,
.map_err(|e| { Err(e) => {
error!( error!(
"Could not get asusd version: {e:?}\nIs asusd.service running? {}", "Could not get asusd version: {e:?}\nIs asusd.service running? {}",
check_service("asusd") check_service("asusd")
); );
}) return;
.unwrap(); }
};
if asusd_version != self_version { if asusd_version != self_version {
println!("Version mismatch: asusctl = {self_version}, asusd = {asusd_version}"); println!("Version mismatch: asusctl = {self_version}, asusd = {asusd_version}");
return; return;
} }
let supported_properties = platform_proxy.supported_properties().unwrap(); let supported_properties = match platform_proxy.supported_properties() {
let supported_interfaces = list_iface_blocking().unwrap(); Ok(props) => props,
Err(e) => {
error!("Could not get supported properties: {e:?}");
return;
}
};
let supported_interfaces = match list_iface_blocking() {
Ok(ifaces) => ifaces,
Err(e) => {
error!("Could not get supported interfaces: {e:?}");
return;
}
};
if parsed.version { if parsed.version {
println!("asusctl v{}", env!("CARGO_PKG_VERSION")); println!("asusctl v{}", env!("CARGO_PKG_VERSION"));
@@ -106,7 +125,7 @@ fn main() {
fn print_error_help( fn print_error_help(
err: &dyn std::error::Error, err: &dyn std::error::Error,
supported_interfaces: &[String], supported_interfaces: &[String],
supported_properties: &[Properties] supported_properties: &[Properties],
) { ) {
check_service("asusd"); check_service("asusd");
println!("\nError: {}\n", err); println!("\nError: {}\n", err);
@@ -147,7 +166,7 @@ fn check_service(name: &str) -> bool {
fn find_iface<T>(iface_name: &str) -> Result<Vec<T>, Box<dyn std::error::Error>> fn find_iface<T>(iface_name: &str) -> Result<Vec<T>, Box<dyn std::error::Error>>
where where
T: ProxyImpl<'static> + From<zbus::Proxy<'static>> T: ProxyImpl<'static> + From<zbus::Proxy<'static>>,
{ {
let conn = zbus::blocking::Connection::system().unwrap(); let conn = zbus::blocking::Connection::system().unwrap();
let f = zbus::blocking::fdo::ObjectManagerProxy::new(&conn, "xyz.ljones.Asusd", "/").unwrap(); let f = zbus::blocking::fdo::ObjectManagerProxy::new(&conn, "xyz.ljones.Asusd", "/").unwrap();
@@ -174,7 +193,7 @@ where
T::builder(&conn) T::builder(&conn)
.path(path.clone())? .path(path.clone())?
.destination("xyz.ljones.Asusd")? .destination("xyz.ljones.Asusd")?
.build()? .build()?,
); );
} }
return Ok(ctrl); return Ok(ctrl);
@@ -187,7 +206,7 @@ fn do_parsed(
parsed: &CliStart, parsed: &CliStart,
supported_interfaces: &[String], supported_interfaces: &[String],
supported_properties: &[Properties], supported_properties: &[Properties],
conn: Connection conn: Connection,
) -> Result<(), Box<dyn std::error::Error>> { ) -> Result<(), Box<dyn std::error::Error>> {
match &parsed.command { match &parsed.command {
Some(CliCommand::Aura(mode)) => handle_led_mode(mode)?, Some(CliCommand::Aura(mode)) => handle_led_mode(mode)?,
@@ -204,6 +223,7 @@ fn do_parsed(
Some(CliCommand::Slash(cmd)) => handle_slash(cmd)?, Some(CliCommand::Slash(cmd)) => handle_slash(cmd)?,
Some(CliCommand::Scsi(cmd)) => handle_scsi(cmd)?, Some(CliCommand::Scsi(cmd)) => handle_scsi(cmd)?,
Some(CliCommand::Armoury(cmd)) => handle_armoury_command(cmd)?, Some(CliCommand::Armoury(cmd)) => handle_armoury_command(cmd)?,
Some(CliCommand::Backlight(cmd)) => handle_backlight(cmd)?,
None => { None => {
if (!parsed.show_supported if (!parsed.show_supported
&& parsed.kbd_bright.is_none() && parsed.kbd_bright.is_none()
@@ -259,12 +279,18 @@ fn do_parsed(
return false; return false;
} }
if command.trim().starts_with("platform") if command.trim().starts_with("armoury")
&& !supported_interfaces.contains(&"xyz.ljones.AsusArmoury".to_string()) && !supported_interfaces.contains(&"xyz.ljones.AsusArmoury".to_string())
{ {
return false; return false;
} }
if command.trim().starts_with("backlight")
&& !supported_interfaces.contains(&"xyz.ljones.Backlight".to_string())
{
return false;
}
if !dev_type.is_old_laptop() if !dev_type.is_old_laptop()
&& !dev_type.is_tuf_laptop() && !dev_type.is_tuf_laptop()
&& command.trim().starts_with("aura-power-old") && command.trim().starts_with("aura-power-old")
@@ -295,7 +321,7 @@ fn do_parsed(
let level = aura.brightness()?; let level = aura.brightness()?;
println!("Current keyboard led brightness: {level:?}"); println!("Current keyboard led brightness: {level:?}");
} }
Some(level) => aura.set_brightness(rog_aura::LedBrightness::from(level))? Some(level) => aura.set_brightness(rog_aura::LedBrightness::from(level))?,
} }
} }
} else { } else {
@@ -367,6 +393,46 @@ fn do_gfx() {
println!("This command will be removed in future"); println!("This command will be removed in future");
} }
fn handle_backlight(cmd: &BacklightCommand) -> Result<(), Box<dyn std::error::Error>> {
if (cmd.screenpad_brightness.is_none()
&& cmd.screenpad_gamma.is_none()
&& cmd.sync_screenpad_brightness.is_none())
|| cmd.help
{
println!("Missing arg or command\n\n{}", cmd.self_usage());
let backlights = find_iface::<BacklightProxyBlocking>("xyz.ljones.Backlight")?;
for backlight in backlights {
println!("Current screenpad settings:");
println!(" Brightness: {}", backlight.screenpad_brightness()?);
println!(" Gamma: {}", backlight.screenpad_gamma()?);
println!(
" Sync with primary: {}",
backlight.screenpad_sync_with_primary()?
);
}
return Ok(());
}
let backlights = find_iface::<BacklightProxyBlocking>("xyz.ljones.Backlight")?;
for backlight in backlights {
if let Some(brightness) = cmd.screenpad_brightness {
backlight.set_screenpad_brightness(brightness)?;
}
if let Some(gamma) = cmd.screenpad_gamma {
backlight.set_screenpad_gamma(gamma.to_string().as_str())?;
}
if let Some(sync) = cmd.sync_screenpad_brightness {
backlight.set_screenpad_sync_with_primary(sync)?;
}
}
Ok(())
}
fn handle_anime(cmd: &AnimeCommand) -> Result<(), Box<dyn std::error::Error>> { fn handle_anime(cmd: &AnimeCommand) -> Result<(), Box<dyn std::error::Error>> {
if (cmd.command.is_none() if (cmd.command.is_none()
&& cmd.enable_display.is_none() && cmd.enable_display.is_none()
@@ -444,7 +510,7 @@ fn handle_anime(cmd: &AnimeCommand) -> Result<(), Box<dyn std::error::Error>> {
image.angle, image.angle,
Vec2::new(image.x_pos, image.y_pos), Vec2::new(image.x_pos, image.y_pos),
image.bright, image.bright,
anime_type anime_type,
)?; )?;
proxy.write(<AnimeDataBuffer>::try_from(&matrix)?)?; proxy.write(<AnimeDataBuffer>::try_from(&matrix)?)?;
@@ -463,7 +529,7 @@ fn handle_anime(cmd: &AnimeCommand) -> Result<(), Box<dyn std::error::Error>> {
Path::new(&image.path), Path::new(&image.path),
None, None,
image.bright, image.bright,
anime_type anime_type,
)?; )?;
proxy.write(matrix.into_data_buffer(anime_type)?)?; proxy.write(matrix.into_data_buffer(anime_type)?)?;
@@ -485,7 +551,7 @@ fn handle_anime(cmd: &AnimeCommand) -> Result<(), Box<dyn std::error::Error>> {
Vec2::new(gif.x_pos, gif.y_pos), Vec2::new(gif.x_pos, gif.y_pos),
AnimTime::Count(1), AnimTime::Count(1),
gif.bright, gif.bright,
anime_type anime_type,
)?; )?;
let mut loops = gif.loops as i32; let mut loops = gif.loops as i32;
@@ -516,7 +582,7 @@ fn handle_anime(cmd: &AnimeCommand) -> Result<(), Box<dyn std::error::Error>> {
Path::new(&gif.path), Path::new(&gif.path),
AnimTime::Count(1), AnimTime::Count(1),
gif.bright, gif.bright,
anime_type anime_type,
)?; )?;
let mut loops = gif.loops as i32; let mut loops = gif.loops as i32;
@@ -549,7 +615,7 @@ fn handle_anime(cmd: &AnimeCommand) -> Result<(), Box<dyn std::error::Error>> {
boot: builtins.boot, boot: builtins.boot,
awake: builtins.awake, awake: builtins.awake,
sleep: builtins.sleep, sleep: builtins.sleep,
shutdown: builtins.shutdown shutdown: builtins.shutdown,
})?; })?;
} }
} }
@@ -575,6 +641,7 @@ fn handle_slash(cmd: &SlashCommand) -> Result<(), Box<dyn std::error::Error>> {
&& cmd.show_on_sleep.is_none() && cmd.show_on_sleep.is_none()
&& cmd.show_on_battery.is_none() && cmd.show_on_battery.is_none()
&& cmd.show_battery_warning.is_none() && cmd.show_battery_warning.is_none()
// && cmd.show_on_lid_closed.is_none()
&& cmd.mode.is_none() && cmd.mode.is_none()
&& !cmd.list && !cmd.list
&& !cmd.enable && !cmd.enable
@@ -620,6 +687,9 @@ fn handle_slash(cmd: &SlashCommand) -> Result<(), Box<dyn std::error::Error>> {
if let Some(show) = cmd.show_battery_warning { if let Some(show) = cmd.show_battery_warning {
proxy.set_show_battery_warning(show)?; proxy.set_show_battery_warning(show)?;
} }
// if let Some(show) = cmd.show_on_lid_closed {
// proxy.set_show_on_lid_closed(show)?;
// }
} }
if cmd.list { if cmd.list {
let res = SlashMode::list(); let res = SlashMode::list();
@@ -812,7 +882,7 @@ fn handle_led_power1(power: &LedPowerCommand1) -> Result<(), Box<dyn std::error:
fn handle_led_power_1_do_1866( fn handle_led_power_1_do_1866(
aura: &AuraProxyBlocking, aura: &AuraProxyBlocking,
power: &LedPowerCommand1 power: &LedPowerCommand1,
) -> Result<(), Box<dyn std::error::Error>> { ) -> Result<(), Box<dyn std::error::Error>> {
let mut states = Vec::new(); let mut states = Vec::new();
if power.keyboard { if power.keyboard {
@@ -821,7 +891,7 @@ fn handle_led_power_1_do_1866(
boot: power.boot.unwrap_or_default(), boot: power.boot.unwrap_or_default(),
awake: power.awake.unwrap_or_default(), awake: power.awake.unwrap_or_default(),
sleep: power.sleep.unwrap_or_default(), sleep: power.sleep.unwrap_or_default(),
shutdown: false shutdown: false,
}); });
} }
if power.lightbar { if power.lightbar {
@@ -830,7 +900,7 @@ fn handle_led_power_1_do_1866(
boot: power.boot.unwrap_or_default(), boot: power.boot.unwrap_or_default(),
awake: power.awake.unwrap_or_default(), awake: power.awake.unwrap_or_default(),
sleep: power.sleep.unwrap_or_default(), sleep: power.sleep.unwrap_or_default(),
shutdown: false shutdown: false,
}); });
} }
@@ -892,7 +962,7 @@ fn handle_led_power2(power: &LedPowerCommand2) -> Result<(), Box<dyn std::error:
aura_cli::SetAuraZoneEnabled::Lightbar(l) => set(PowerZones::Lightbar, l), aura_cli::SetAuraZoneEnabled::Lightbar(l) => set(PowerZones::Lightbar, l),
aura_cli::SetAuraZoneEnabled::Lid(l) => set(PowerZones::Lid, l), aura_cli::SetAuraZoneEnabled::Lid(l) => set(PowerZones::Lid, l),
aura_cli::SetAuraZoneEnabled::RearGlow(r) => set(PowerZones::RearGlow, r), aura_cli::SetAuraZoneEnabled::RearGlow(r) => set(PowerZones::RearGlow, r),
aura_cli::SetAuraZoneEnabled::Ally(r) => set(PowerZones::Ally, r) aura_cli::SetAuraZoneEnabled::Ally(r) => set(PowerZones::Ally, r),
} }
} }
@@ -906,14 +976,20 @@ fn handle_led_power2(power: &LedPowerCommand2) -> Result<(), Box<dyn std::error:
fn handle_throttle_profile( fn handle_throttle_profile(
conn: &Connection, conn: &Connection,
supported: &[Properties], supported: &[Properties],
cmd: &ProfileCommand cmd: &ProfileCommand,
) -> Result<(), Box<dyn std::error::Error>> { ) -> Result<(), Box<dyn std::error::Error>> {
if !supported.contains(&Properties::ThrottlePolicy) { if !supported.contains(&Properties::ThrottlePolicy) {
println!("Profiles not supported by either this kernel or by the laptop."); println!("Profiles not supported by either this kernel or by the laptop.");
return Err(ProfileError::NotSupported.into()); return Err(ProfileError::NotSupported.into());
} }
if !cmd.next && !cmd.list && cmd.profile_set.is_none() && !cmd.profile_get { if !cmd.next
&& !cmd.list
&& cmd.profile_set.is_none()
&& !cmd.profile_get
&& cmd.profile_set_ac.is_none()
&& cmd.profile_set_bat.is_none()
{
if !cmd.help { if !cmd.help {
println!("Missing arg or command\n"); println!("Missing arg or command\n");
} }
@@ -927,22 +1003,31 @@ fn handle_throttle_profile(
let proxy = PlatformProxyBlocking::new(conn)?; let proxy = PlatformProxyBlocking::new(conn)?;
let current = proxy.platform_profile()?; let current = proxy.platform_profile()?;
let choices = proxy.platform_profile_choices()?;
if cmd.next { if cmd.next {
proxy.set_platform_profile(current.next())?; proxy.set_platform_profile(PlatformProfile::next(current, &choices))?;
} else if let Some(profile) = cmd.profile_set { } else if let Some(profile) = cmd.profile_set {
proxy.set_platform_profile(profile)?; proxy.set_platform_profile(profile)?;
} else if let Some(profile) = cmd.profile_set_ac {
proxy.set_platform_profile_on_ac(profile)?;
} else if let Some(profile) = cmd.profile_set_bat {
proxy.set_platform_profile_on_battery(profile)?;
} }
if cmd.list { if cmd.list {
let res = PlatformProfile::list(); for p in &choices {
for p in &res {
println!("{:?}", p); println!("{:?}", p);
} }
} }
if cmd.profile_get { if cmd.profile_get {
println!("Active profile is {current:?}"); println!("Active profile is {current:?}");
println!("Profile on AC is {:?}", proxy.platform_profile_on_ac()?);
println!(
"Profile on Battery is {:?}",
proxy.platform_profile_on_battery()?
);
} }
Ok(()) Ok(())
@@ -950,7 +1035,7 @@ fn handle_throttle_profile(
fn handle_fan_curve( fn handle_fan_curve(
conn: &Connection, conn: &Connection,
cmd: &FanCurveCommand cmd: &FanCurveCommand,
) -> Result<(), Box<dyn std::error::Error>> { ) -> Result<(), Box<dyn std::error::Error>> {
let Ok(fan_proxy) = FanCurvesProxyBlocking::new(conn).map_err(|e| { let Ok(fan_proxy) = FanCurvesProxyBlocking::new(conn).map_err(|e| {
println!("Fan-curves not supported by either this kernel or by the laptop: {e:?}"); println!("Fan-curves not supported by either this kernel or by the laptop: {e:?}");
@@ -1045,7 +1130,7 @@ fn check_systemd_unit_enabled(name: &str) -> bool {
.output() .output()
{ {
let buf = String::from_utf8_lossy(&out.stdout); let buf = String::from_utf8_lossy(&out.stdout);
return buf.contains("enabled"); return buf.contains("enabled") || buf.contains("linked");
} }
false false
} }
@@ -1103,10 +1188,11 @@ fn print_firmware_attr(attr: &AsusArmouryProxyBlocking) -> Result<(), Box<dyn st
Ok(()) Ok(())
} }
#[allow(clippy::manual_is_multiple_of, clippy::nonminimal_bool)]
fn handle_armoury_command(cmd: &ArmouryCommand) -> Result<(), Box<dyn std::error::Error>> { fn handle_armoury_command(cmd: &ArmouryCommand) -> Result<(), Box<dyn std::error::Error>> {
{ {
if cmd.free.is_empty() || cmd.free.len() % 2 != 0 || cmd.help { if cmd.free.is_empty() || (cmd.free.len() % 2 != 0) || cmd.help {
const USAGE: &str = "Usage: asusctl platform panel_overdrive 1 nv_dynamic_boost 5"; const USAGE: &str = "Usage: asusctl armoury panel_overdrive 1 nv_dynamic_boost 5";
if cmd.free.len() % 2 != 0 { if cmd.free.len() % 2 != 0 {
println!( println!(
"Incorrect number of args, each attribute label must be paired with a setting:" "Incorrect number of args, each attribute label must be paired with a setting:"

View File

@@ -31,5 +31,5 @@ pub struct ScsiCommand {
pub colours: Vec<Colour>, pub colours: Vec<Colour>,
#[options(help = "list available animations")] #[options(help = "list available animations")]
pub list: bool pub list: bool,
} }

View File

@@ -26,10 +26,12 @@ pub struct SlashCommand {
pub show_on_sleep: Option<bool>, pub show_on_sleep: Option<bool>,
#[options(short = "b", meta = "", help = "Show the animation on battery")] #[options(short = "b", meta = "", help = "Show the animation on battery")]
pub show_on_battery: Option<bool>, pub show_on_battery: Option<bool>,
// #[options(short = "L", meta = "", help = "Show the animation on lid closed")]
// pub show_on_lid_closed: Option<bool>,
#[options( #[options(
short = "w", short = "w",
meta = "", meta = "",
help = "Show the low-battery warning animation" help = "Show the low-battery warning animation"
)] )]
pub show_battery_warning: Option<bool> pub show_battery_warning: Option<bool>,
} }

View File

@@ -32,3 +32,16 @@ config-traits = { path = "../config-traits" }
zbus.workspace = true zbus.workspace = true
env_logger.workspace = true env_logger.workspace = true
[package.metadata.deb]
license-file = ["../LICENSE", "4"]
extended-description = """\
An user utility for Linux to control fancy things on various ASUS laptops
like keyboard effects or anime matrix animation cycles."""
depends = "$auto"
section = "utility"
priority = "optional"
assets = [
["target/release/asusd-user", "usr/bin/", "755"],
["../asusd_user-fakeinstall/usr/lib/systemd/user/*", "usr/lib/systemd/user/", "644"],
]

View File

@@ -21,7 +21,7 @@ fn root_conf_dir() -> PathBuf {
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize)]
pub struct ConfigAnime { pub struct ConfigAnime {
pub name: String, pub name: String,
pub anime: Vec<ActionLoader> pub anime: Vec<ActionLoader>,
} }
impl ConfigAnime { impl ConfigAnime {
@@ -52,8 +52,8 @@ impl Default for ConfigAnime {
time: AnimTime::Fade(Fade::new( time: AnimTime::Fade(Fade::new(
Duration::from_secs(2), Duration::from_secs(2),
None, None,
Duration::from_secs(2) Duration::from_secs(2),
)) )),
}, },
ActionLoader::AsusAnimation { ActionLoader::AsusAnimation {
file: "/usr/share/asusd/anime/asus/rog/Sunset.gif".into(), file: "/usr/share/asusd/anime/asus/rog/Sunset.gif".into(),
@@ -61,8 +61,8 @@ impl Default for ConfigAnime {
time: AnimTime::Fade(Fade::new( time: AnimTime::Fade(Fade::new(
Duration::from_secs(6), Duration::from_secs(6),
None, None,
Duration::from_secs(3) Duration::from_secs(3),
)) )),
}, },
ActionLoader::ImageAnimation { ActionLoader::ImageAnimation {
file: "/usr/share/asusd/anime/custom/sonic-run.gif".into(), file: "/usr/share/asusd/anime/custom/sonic-run.gif".into(),
@@ -73,8 +73,8 @@ impl Default for ConfigAnime {
time: AnimTime::Fade(Fade::new( time: AnimTime::Fade(Fade::new(
Duration::from_secs(2), Duration::from_secs(2),
Some(Duration::from_secs(2)), Some(Duration::from_secs(2)),
Duration::from_secs(2) Duration::from_secs(2),
)) )),
}, },
ActionLoader::Image { ActionLoader::Image {
file: "/usr/share/asusd/anime/custom/rust.png".into(), file: "/usr/share/asusd/anime/custom/rust.png".into(),
@@ -84,9 +84,9 @@ impl Default for ConfigAnime {
time: AnimTime::Fade(Fade::new( time: AnimTime::Fade(Fade::new(
Duration::from_secs(2), Duration::from_secs(2),
Some(Duration::from_secs(1)), Some(Duration::from_secs(1)),
Duration::from_secs(2) Duration::from_secs(2),
)), )),
brightness: 0.6 brightness: 0.6,
}, },
ActionLoader::Pause(Duration::from_secs(1)), ActionLoader::Pause(Duration::from_secs(1)),
ActionLoader::ImageAnimation { ActionLoader::ImageAnimation {
@@ -95,9 +95,9 @@ impl Default for ConfigAnime {
angle: 0.0, angle: 0.0,
translation: Vec2::new(3.0, 2.0), translation: Vec2::new(3.0, 2.0),
brightness: 0.5, brightness: 0.5,
time: AnimTime::Count(2) time: AnimTime::Count(2),
}, },
] ],
} }
} }
} }
@@ -121,7 +121,7 @@ impl StdConfigLoad for ConfigAnime {}
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize)]
pub struct ConfigAura { pub struct ConfigAura {
pub name: String, pub name: String,
pub aura: AuraSequences pub aura: AuraSequences,
} }
impl ConfigAura { impl ConfigAura {
@@ -139,14 +139,14 @@ impl Default for ConfigAura {
Colour { Colour {
r: 255, r: 255,
g: 0, g: 0,
b: 20 b: 20,
}, },
Colour { Colour {
r: 20, r: 20,
g: 255, g: 255,
b: 0 b: 0,
}, },
Speed::Low Speed::Low,
)); ));
seq.push(key.clone()); seq.push(key.clone());
@@ -161,7 +161,7 @@ impl Default for ConfigAura {
LedCode::F, LedCode::F,
Colour { r: 255, g: 0, b: 0 }, Colour { r: 255, g: 0, b: 0 },
Colour { r: 255, g: 0, b: 0 }, Colour { r: 255, g: 0, b: 0 },
Speed::High Speed::High,
)); ));
seq.push(key); seq.push(key);
@@ -176,13 +176,13 @@ impl Default for ConfigAura {
LedCode::N9, LedCode::N9,
Colour { r: 0, g: 0, b: 255 }, Colour { r: 0, g: 0, b: 255 },
80, 80,
40 40,
)); ));
seq.push(key); seq.push(key);
Self { Self {
name: "aura-default".to_owned(), name: "aura-default".to_owned(),
aura: seq aura: seq,
} }
} }
} }
@@ -209,14 +209,14 @@ pub struct ConfigBase {
/// Name of active anime config file in the user config directory /// Name of active anime config file in the user config directory
pub active_anime: Option<String>, pub active_anime: Option<String>,
/// Name of active aura config file in the user config directory /// Name of active aura config file in the user config directory
pub active_aura: Option<String> pub active_aura: Option<String>,
} }
impl StdConfig for ConfigBase { impl StdConfig for ConfigBase {
fn new() -> Self { fn new() -> Self {
Self { Self {
active_anime: Some("anime-default".to_owned()), active_anime: Some("anime-default".to_owned()),
active_aura: Some("aura-default".to_owned()) active_aura: Some("aura-default".to_owned()),
} }
} }

View File

@@ -25,7 +25,7 @@ pub struct Timer {
/// Used only for `TimeType::Timer`, milliseonds to fade the image in for /// Used only for `TimeType::Timer`, milliseonds to fade the image in for
fade_in: u64, fade_in: u64,
/// Used only for `TimeType::Timer`, milliseonds to fade the image out for /// Used only for `TimeType::Timer`, milliseonds to fade the image out for
fade_out: u64 fade_out: u64,
} }
impl From<Timer> for AnimTime { impl From<Timer> for AnimTime {
@@ -46,7 +46,7 @@ impl From<Timer> for AnimTime {
} }
} }
TimeType::Count => AnimTime::Count(time.count as u32), TimeType::Count => AnimTime::Count(time.count as u32),
TimeType::Infinite => AnimTime::Infinite TimeType::Infinite => AnimTime::Infinite,
} }
} }
} }
@@ -55,7 +55,7 @@ impl From<Timer> for AnimTime {
pub enum TimeType { pub enum TimeType {
Timer, Timer,
Count, Count,
Infinite Infinite,
} }
/// The inner object exists to allow the zbus proxy to share it with a runner /// The inner object exists to allow the zbus proxy to share it with a runner
@@ -63,19 +63,19 @@ pub enum TimeType {
pub struct CtrlAnimeInner<'a> { pub struct CtrlAnimeInner<'a> {
sequences: Sequences, sequences: Sequences,
client: AnimeProxyBlocking<'a>, client: AnimeProxyBlocking<'a>,
do_early_return: Arc<AtomicBool> do_early_return: Arc<AtomicBool>,
} }
impl CtrlAnimeInner<'static> { impl CtrlAnimeInner<'static> {
pub fn new( pub fn new(
sequences: Sequences, sequences: Sequences,
client: AnimeProxyBlocking<'static>, client: AnimeProxyBlocking<'static>,
do_early_return: Arc<AtomicBool> do_early_return: Arc<AtomicBool>,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
Ok(Self { Ok(Self {
sequences, sequences,
client, client,
do_early_return do_early_return,
}) })
} }
@@ -130,7 +130,7 @@ pub struct CtrlAnime<'a> {
client: AnimeProxyBlocking<'a>, client: AnimeProxyBlocking<'a>,
inner: Arc<Mutex<CtrlAnimeInner<'a>>>, inner: Arc<Mutex<CtrlAnimeInner<'a>>>,
/// Must be the same Atomic as in CtrlAnimeInner /// Must be the same Atomic as in CtrlAnimeInner
inner_early_return: Arc<AtomicBool> inner_early_return: Arc<AtomicBool>,
} }
impl CtrlAnime<'static> { impl CtrlAnime<'static> {
@@ -138,13 +138,13 @@ impl CtrlAnime<'static> {
config: Arc<Mutex<ConfigAnime>>, config: Arc<Mutex<ConfigAnime>>,
inner: Arc<Mutex<CtrlAnimeInner<'static>>>, inner: Arc<Mutex<CtrlAnimeInner<'static>>>,
client: AnimeProxyBlocking<'static>, client: AnimeProxyBlocking<'static>,
inner_early_return: Arc<AtomicBool> inner_early_return: Arc<AtomicBool>,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
Ok(CtrlAnime { Ok(CtrlAnime {
config, config,
client, client,
inner, inner,
inner_early_return inner_early_return,
}) })
} }
@@ -174,7 +174,7 @@ impl CtrlAnime<'static> {
index: u32, index: u32,
file: &str, file: &str,
time: Timer, time: Timer,
brightness: f32 brightness: f32,
) -> zbus::fdo::Result<String> { ) -> zbus::fdo::Result<String> {
if let Ok(mut config) = self.config.try_lock() { if let Ok(mut config) = self.config.try_lock() {
let time: AnimTime = time.into(); let time: AnimTime = time.into();
@@ -182,7 +182,7 @@ impl CtrlAnime<'static> {
let action = ActionLoader::AsusAnimation { let action = ActionLoader::AsusAnimation {
file: file.into(), file: file.into(),
brightness, brightness,
time time,
}; };
// Must make the inner run loop return early // Must make the inner run loop return early
@@ -216,7 +216,7 @@ impl CtrlAnime<'static> {
angle: f32, angle: f32,
xy: (f32, f32), xy: (f32, f32),
time: Timer, time: Timer,
brightness: f32 brightness: f32,
) -> zbus::fdo::Result<String> { ) -> zbus::fdo::Result<String> {
if let Ok(mut config) = self.config.try_lock() { if let Ok(mut config) = self.config.try_lock() {
let time: AnimTime = time.into(); let time: AnimTime = time.into();
@@ -228,7 +228,7 @@ impl CtrlAnime<'static> {
angle, angle,
translation, translation,
brightness, brightness,
time time,
}; };
// Must make the inner run loop return early // Must make the inner run loop return early
@@ -261,7 +261,7 @@ impl CtrlAnime<'static> {
angle: f32, angle: f32,
xy: (f32, f32), xy: (f32, f32),
time: Timer, time: Timer,
brightness: f32 brightness: f32,
) -> zbus::fdo::Result<String> { ) -> zbus::fdo::Result<String> {
if let Ok(mut config) = self.config.try_lock() { if let Ok(mut config) = self.config.try_lock() {
let file = Path::new(&file); let file = Path::new(&file);
@@ -272,7 +272,7 @@ impl CtrlAnime<'static> {
angle, angle,
translation: Vec2::new(xy.0, xy.1), translation: Vec2::new(xy.0, xy.1),
brightness, brightness,
time time,
}; };
// Must make the inner run loop return early // Must make the inner run loop return early

View File

@@ -61,16 +61,16 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
CtrlAnimeInner::new( CtrlAnimeInner::new(
anime, anime,
anime_proxy_blocking.clone(), anime_proxy_blocking.clone(),
early_return.clone() early_return.clone(),
) )
.unwrap() .unwrap(),
)); ));
// Need new client object for dbus control part // Need new client object for dbus control part
let anime_control = CtrlAnime::new( let anime_control = CtrlAnime::new(
anime_config, anime_config,
inner.clone(), inner.clone(),
anime_proxy_blocking, anime_proxy_blocking,
early_return early_return,
) )
.unwrap(); .unwrap();
anime_control.add_to_server(&mut connection).await; anime_control.add_to_server(&mut connection).await;

View File

@@ -8,7 +8,7 @@ pub enum Error {
ConfigLoadFail, ConfigLoadFail,
ConfigLockFail, ConfigLockFail,
XdgVars, XdgVars,
Anime(AnimeError) Anime(AnimeError),
} }
impl fmt::Display for Error { impl fmt::Display for Error {
@@ -19,7 +19,7 @@ impl fmt::Display for Error {
Error::ConfigLoadFail => write!(f, "Failed to load user config"), Error::ConfigLoadFail => write!(f, "Failed to load user config"),
Error::ConfigLockFail => write!(f, "Failed to lock user config"), Error::ConfigLockFail => write!(f, "Failed to lock user config"),
Error::XdgVars => write!(f, "XDG environment vars appear unset"), Error::XdgVars => write!(f, "XDG environment vars appear unset"),
Error::Anime(err) => write!(f, "Anime error: {}", err) Error::Anime(err) => write!(f, "Anime error: {}", err),
} }
} }
} }

View File

@@ -32,7 +32,7 @@ trait Daemon {
file: &str, file: &str,
time: u32, time: u32,
count: u32, count: u32,
brightness: f64 brightness: f64,
) -> zbus::Result<String>; ) -> zbus::Result<String>;
/// InsertImage method /// InsertImage method
@@ -43,7 +43,7 @@ trait Daemon {
scale: f64, scale: f64,
angle: f64, angle: f64,
xy: &(f64, f64), xy: &(f64, f64),
brightness: f64 brightness: f64,
) -> zbus::Result<String>; ) -> zbus::Result<String>;
/// InsertImageGif method /// InsertImageGif method
@@ -56,7 +56,7 @@ trait Daemon {
xy: &(f64, f64), xy: &(f64, f64),
time: u32, time: u32,
count: u32, count: u32,
brightness: f64 brightness: f64,
) -> zbus::Result<String>; ) -> zbus::Result<String>;
/// InsertPause method /// InsertPause method

View File

@@ -34,6 +34,7 @@ tokio.workspace = true
log.workspace = true log.workspace = true
env_logger.workspace = true env_logger.workspace = true
futures-util.workspace = true
zbus.workspace = true zbus.workspace = true
logind-zbus.workspace = true logind-zbus.workspace = true
@@ -44,3 +45,18 @@ concat-idents.workspace = true
[dev-dependencies] [dev-dependencies]
cargo-husky.workspace = true cargo-husky.workspace = true
[package.metadata.deb]
license-file = ["../LICENSE", "4"]
extended-description = """\
The dbus server for asusctl and rog-control-center applications."""
depends = "$auto"
section = "utility"
priority = "optional"
assets = [
["target/release/asusd", "usr/bin/", "755"],
["../asusd-fakeinstall/usr/lib/systemd/system/*", "usr/lib/systemd/system/", "644"],
["../asusd-fakeinstall/usr/lib/udev/rules.d/*", "usr/lib/udev/rules.d/", "644"],
["../asusd-fakeinstall/usr/share/asusd/*", "usr/share/share/asusd/", "644"],
["../asusd-fakeinstall/usr/share/dbus-1/system.d/*", "usr/share/dbus-1/system.d/", "644"],
]

View File

@@ -1,12 +1,12 @@
use std::sync::Arc; use std::sync::Arc;
use ::zbus::export::futures_util::lock::Mutex;
use config_traits::StdConfig; use config_traits::StdConfig;
use log::{debug, error, info}; use log::{debug, error, info, warn};
use rog_platform::asus_armoury::{AttrValue, Attribute, FirmwareAttribute, FirmwareAttributes}; use rog_platform::asus_armoury::{AttrValue, Attribute, FirmwareAttribute, FirmwareAttributes};
use rog_platform::platform::{PlatformProfile, RogPlatform}; use rog_platform::platform::{PlatformProfile, RogPlatform};
use rog_platform::power::AsusPower; use rog_platform::power::AsusPower;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tokio::sync::Mutex;
use zbus::object_server::SignalEmitter; use zbus::object_server::SignalEmitter;
use zbus::zvariant::{ObjectPath, OwnedObjectPath, OwnedValue, Type, Value}; use zbus::zvariant::{ObjectPath, OwnedObjectPath, OwnedValue, Type, Value};
use zbus::{fdo, interface, Connection}; use zbus::{fdo, interface, Connection};
@@ -20,7 +20,7 @@ const MOD_NAME: &str = "asus_armoury";
#[derive(Debug, Default, Clone, Deserialize, Serialize, Type, Value, OwnedValue)] #[derive(Debug, Default, Clone, Deserialize, Serialize, Type, Value, OwnedValue)]
pub struct PossibleValues { pub struct PossibleValues {
strings: Vec<String>, strings: Vec<String>,
nums: Vec<i32> nums: Vec<i32>,
} }
fn dbus_path_for_attr(attr_name: &str) -> OwnedObjectPath { fn dbus_path_for_attr(attr_name: &str) -> OwnedObjectPath {
@@ -33,7 +33,7 @@ pub struct AsusArmouryAttribute {
config: Arc<Mutex<Config>>, config: Arc<Mutex<Config>>,
/// platform control required here for access to PPD or Throttle profile /// platform control required here for access to PPD or Throttle profile
platform: RogPlatform, platform: RogPlatform,
power: AsusPower power: AsusPower,
} }
impl AsusArmouryAttribute { impl AsusArmouryAttribute {
@@ -41,16 +41,39 @@ impl AsusArmouryAttribute {
attr: Attribute, attr: Attribute,
platform: RogPlatform, platform: RogPlatform,
power: AsusPower, power: AsusPower,
config: Arc<Mutex<Config>> config: Arc<Mutex<Config>>,
) -> Self { ) -> Self {
Self { Self {
attr, attr,
config, config,
platform, platform,
power power,
} }
} }
pub fn attribute_name(&self) -> String {
String::from(self.attr.name())
}
fn resolve_i32_value(refreshed: Option<i32>, cached: &AttrValue) -> i32 {
refreshed
.or(match cached {
AttrValue::Integer(i) => Some(*i),
_ => None,
})
.unwrap_or(-1)
}
pub async fn emit_limits(&self, connection: &Connection) -> Result<(), RogError> {
let path = dbus_path_for_attr(self.attr.name());
let signal = SignalEmitter::new(connection, path)?;
self.min_value_changed(&signal).await?;
self.max_value_changed(&signal).await?;
self.scalar_increment_changed(&signal).await?;
self.current_value_changed(&signal).await?;
Ok(())
}
pub async fn move_to_zbus(self, connection: &Connection) -> Result<(), RogError> { pub async fn move_to_zbus(self, connection: &Connection) -> Result<(), RogError> {
let path = dbus_path_for_attr(self.attr.name()); let path = dbus_path_for_attr(self.attr.name());
connection connection
@@ -64,9 +87,9 @@ impl AsusArmouryAttribute {
async fn watch_and_notify( async fn watch_and_notify(
&mut self, &mut self,
signal_ctxt: SignalEmitter<'static> signal_ctxt: SignalEmitter<'static>,
) -> Result<(), RogError> { ) -> Result<(), RogError> {
use zbus::export::futures_util::StreamExt; use futures_util::StreamExt;
let name = self.name(); let name = self.name();
macro_rules! watch_value_notify { macro_rules! watch_value_notify {
@@ -78,21 +101,27 @@ impl AsusArmouryAttribute {
let sig = signal_ctxt.clone(); let sig = signal_ctxt.clone();
tokio::spawn(async move { tokio::spawn(async move {
let mut buffer = [0; 32]; let mut buffer = [0; 32];
watch if let Ok(stream) = watch.into_event_stream(&mut buffer) {
.into_event_stream(&mut buffer) stream
.unwrap()
.for_each(|_| async { .for_each(|_| async {
debug!("{} changed", name); debug!("{} changed", name);
ctrl.$fn_prop_changed(&sig).await.ok(); ctrl.$fn_prop_changed(&sig).await.ok();
}) })
.await; .await;
} else {
info!(
"inotify event stream failed for {} ({}). You can ignore this \
if unsupported",
name, $attr_str
);
}
}); });
} }
Err(e) => info!( Err(e) => info!(
"inotify watch failed: {}. You can ignore this if your device does not \ "inotify watch failed: {}. You can ignore this if your device does not \
support the feature", support the feature",
e e
) ),
} }
}; };
} }
@@ -107,9 +136,43 @@ impl AsusArmouryAttribute {
} }
} }
#[derive(Clone, Default)]
pub struct ArmouryAttributeRegistry {
attrs: Vec<AsusArmouryAttribute>,
}
impl ArmouryAttributeRegistry {
pub fn push(&mut self, attr: AsusArmouryAttribute) {
self.attrs.push(attr);
}
pub async fn emit_limits(&self, connection: &Connection) -> Result<(), RogError> {
let mut last_err: Option<RogError> = None;
for attr in &self.attrs {
if let Err(e) = attr.emit_limits(connection).await {
error!(
"Failed to emit updated limits for attribute '{}': {e:?}",
attr.attribute_name()
);
last_err = Some(e);
}
}
if let Some(err) = last_err {
Err(err)
} else {
Ok(())
}
}
}
impl crate::Reloadable for AsusArmouryAttribute { impl crate::Reloadable for AsusArmouryAttribute {
async fn reload(&mut self) -> Result<(), RogError> { async fn reload(&mut self) -> Result<(), RogError> {
info!("Reloading {}", self.attr.name()); info!("Reloading {}", self.attr.name());
let name: FirmwareAttribute = self.attr.name().into();
// Treat dGPU attributes the same as PPT attributes for power-profile
// behaviour so they follow AC/DC tuning groups.
if name.is_ppt() || name.is_dgpu() {
let profile: PlatformProfile = self.platform.get_platform_profile()?.into(); let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
let power_plugged = self let power_plugged = self
.power .power
@@ -118,24 +181,61 @@ impl crate::Reloadable for AsusArmouryAttribute {
error!("Could not get power status: {e:?}"); error!("Could not get power status: {e:?}");
e e
}) })
.unwrap_or_default(); .unwrap_or_default()
let config = if power_plugged == 1 { == 1;
&self.config.lock().await.ac_profile_tunings
} else { let apply_value = {
&self.config.lock().await.dc_profile_tunings let config = self.config.lock().await;
}; config
if let Some(tuning) = config.get(&profile) { .select_tunings_ref(power_plugged, profile)
.and_then(|tuning| {
if tuning.enabled { if tuning.enabled {
if let Some(tune) = tuning.group.get(&self.name()) { tuning.group.get(&self.name()).copied()
} else {
None
}
})
};
if let Some(tune) = apply_value {
self.attr self.attr
.set_current_value(&AttrValue::Integer(*tune)) .set_current_value(&AttrValue::Integer(tune))
.map_err(|e| { .map_err(|e| {
error!("Could not set {} value: {e:?}", self.attr.name()); error!("Could not set {} value: {e:?}", self.attr.name());
self.attr.base_path_exists(); self.attr.base_path_exists();
e e
})?; })?;
info!("Set {} to {:?}", self.attr.name(), tune); info!(
"Restored PPT armoury setting {} to {:?}",
self.attr.name(),
tune
);
} else {
info!("Ignored restoring PPT armoury setting {} as tuning group is disabled or no saved value", self.attr.name());
} }
} else {
// Handle non-PPT attributes (boolean and other settings)
if let Some(saved_value) = self.config.lock().await.armoury_settings.get(&name) {
self.attr
.set_current_value(&AttrValue::Integer(*saved_value))
.map_err(|e| {
error!(
"Error restoring armoury setting {}: {e:?}",
self.attr.name()
);
self.attr.base_path_exists();
e
})?;
info!(
"Restored armoury setting {} to {:?}",
self.attr.name(),
saved_value
);
} else {
info!(
"No saved armoury setting for {}: skipping restore",
self.attr.name()
);
} }
} }
@@ -187,13 +287,13 @@ impl AsusArmouryAttribute {
async fn default_value(&self) -> i32 { async fn default_value(&self) -> i32 {
match self.attr.default_value() { match self.attr.default_value() {
AttrValue::Integer(i) => *i, AttrValue::Integer(i) => *i,
_ => -1 _ => -1,
} }
} }
async fn restore_default(&self) -> fdo::Result<()> { async fn restore_default(&self) -> fdo::Result<()> {
self.attr.restore_default()?; self.attr.restore_default()?;
if self.name().is_ppt() { if self.name().is_ppt() || self.name().is_dgpu() {
let profile: PlatformProfile = self.platform.get_platform_profile()?.into(); let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
let power_plugged = self let power_plugged = self
.power .power
@@ -226,39 +326,33 @@ impl AsusArmouryAttribute {
#[zbus(property)] #[zbus(property)]
async fn min_value(&self) -> i32 { async fn min_value(&self) -> i32 {
match self.attr.min_value() { Self::resolve_i32_value(self.attr.refresh_min_value(), self.attr.min_value())
AttrValue::Integer(i) => *i,
_ => -1
}
} }
#[zbus(property)] #[zbus(property)]
async fn max_value(&self) -> i32 { async fn max_value(&self) -> i32 {
match self.attr.max_value() { Self::resolve_i32_value(self.attr.refresh_max_value(), self.attr.max_value())
AttrValue::Integer(i) => *i,
_ => -1
}
} }
#[zbus(property)] #[zbus(property)]
async fn scalar_increment(&self) -> i32 { async fn scalar_increment(&self) -> i32 {
match self.attr.scalar_increment() { Self::resolve_i32_value(
AttrValue::Integer(i) => *i, self.attr.refresh_scalar_increment(),
_ => -1 self.attr.scalar_increment(),
} )
} }
#[zbus(property)] #[zbus(property)]
async fn possible_values(&self) -> Vec<i32> { async fn possible_values(&self) -> Vec<i32> {
match self.attr.possible_values() { match self.attr.possible_values() {
AttrValue::EnumInt(i) => i.clone(), AttrValue::EnumInt(i) => i.clone(),
_ => Vec::default() _ => Vec::default(),
} }
} }
#[zbus(property)] #[zbus(property)]
async fn current_value(&self) -> fdo::Result<i32> { async fn current_value(&self) -> fdo::Result<i32> {
if self.name().is_ppt() { if self.name().is_ppt() || self.name().is_dgpu() {
let profile: PlatformProfile = self.platform.get_platform_profile()?.into(); let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
let power_plugged = self let power_plugged = self
.power .power
@@ -267,16 +361,19 @@ impl AsusArmouryAttribute {
error!("Could not get power status: {e:?}"); error!("Could not get power status: {e:?}");
e e
}) })
.unwrap_or_default(); .unwrap_or_default()
let mut config = self.config.lock().await; == 1;
let tuning = config.select_tunings(power_plugged == 1, profile); let config = self.config.lock().await;
if let Some(tuning) = config.select_tunings_ref(power_plugged, profile) {
if let Some(tune) = tuning.group.get(&self.name()) { if let Some(tune) = tuning.group.get(&self.name()) {
return Ok(*tune); return Ok(*tune);
} else if let AttrValue::Integer(i) = self.attr.default_value() { }
}
if let AttrValue::Integer(i) = self.attr.default_value() {
return Ok(*i); return Ok(*i);
} }
return Err(fdo::Error::Failed( return Err(fdo::Error::Failed(
"Could not read current value".to_string() "Could not read current value".to_string(),
)); ));
} }
@@ -284,13 +381,13 @@ impl AsusArmouryAttribute {
return Ok(i); return Ok(i);
} }
Err(fdo::Error::Failed( Err(fdo::Error::Failed(
"Could not read current value".to_string() "Could not read current value".to_string(),
)) ))
} }
#[zbus(property)] #[zbus(property)]
async fn set_current_value(&mut self, value: i32) -> fdo::Result<()> { async fn set_current_value(&mut self, value: i32) -> fdo::Result<()> {
if self.name().is_ppt() { if self.name().is_ppt() || self.name().is_dgpu() {
let profile: PlatformProfile = self.platform.get_platform_profile()?.into(); let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
let power_plugged = self let power_plugged = self
.power .power
@@ -314,44 +411,44 @@ impl AsusArmouryAttribute {
self.attr self.attr
.set_current_value(&AttrValue::Integer(value)) .set_current_value(&AttrValue::Integer(value))
.map_err(|e| { .map_err(|e| {
error!("Could not set value: {e:?}"); error!(
"Could not set value to PPT property {}: {e:?}",
self.attr.name()
);
e e
})?; })?;
} else {
warn!(
"Tuning group is disabled: skipping setting value to PPT property {}",
self.attr.name()
);
} }
} else { } else {
self.attr self.attr
.set_current_value(&AttrValue::Integer(value)) .set_current_value(&AttrValue::Integer(value))
.map_err(|e| { .map_err(|e| {
error!("Could not set value: {e:?}"); error!(
"Could not set value {value} to attribute {}: {e:?}",
self.attr.name()
);
e e
})?; })?;
let has_attr = self let mut settings = self.config.lock().await;
.config settings
.lock()
.await
.armoury_settings .armoury_settings
.contains_key(&self.name()); .entry(self.name())
if has_attr { .and_modify(|setting| {
if let Some(setting) = self debug!("Set config for {} = {value}", self.attr.name());
.config *setting = value;
.lock() })
.await .or_insert_with(|| {
.armoury_settings debug!("Adding config for {} = {value}", self.attr.name());
.get_mut(&self.name()) value
{ });
*setting = value
}
} else {
debug!("Adding config for {}", self.attr.name());
self.config
.lock()
.await
.armoury_settings
.insert(self.name(), value);
debug!("Set config for {} = {:?}", self.attr.name(), value);
}
} }
// write config after setting value
self.config.lock().await.write(); self.config.lock().await.write();
Ok(()) Ok(())
} }
@@ -362,35 +459,63 @@ pub async fn start_attributes_zbus(
platform: RogPlatform, platform: RogPlatform,
power: AsusPower, power: AsusPower,
attributes: FirmwareAttributes, attributes: FirmwareAttributes,
config: Arc<Mutex<Config>> config: Arc<Mutex<Config>>,
) -> Result<(), RogError> { ) -> Result<ArmouryAttributeRegistry, RogError> {
let mut registry = ArmouryAttributeRegistry::default();
for attr in attributes.attributes() { for attr in attributes.attributes() {
let mut attr = AsusArmouryAttribute::new( let mut attr = AsusArmouryAttribute::new(
attr.clone(), attr.clone(),
platform.clone(), platform.clone(),
power.clone(), power.clone(),
config.clone() config.clone(),
); );
attr.reload().await?;
let path = dbus_path_for_attr(attr.attr.name()); let registry_attr = attr.clone();
let sig = zbus::object_server::SignalEmitter::new(conn, path)?;
attr.watch_and_notify(sig).await?;
attr.move_to_zbus(conn).await?; if let Err(e) = attr.reload().await {
error!(
"Skipping attribute '{}' due to reload error: {e:?}",
attr.attr.name()
);
break;
} }
Ok(())
let attr_name = attr.attribute_name();
let path = dbus_path_for_attr(attr_name.as_str());
match zbus::object_server::SignalEmitter::new(conn, path) {
Ok(sig) => {
if let Err(e) = attr.watch_and_notify(sig).await {
error!("Failed to start watcher for '{}': {e:?}", attr.attr.name());
}
}
Err(e) => {
error!(
"Failed to create SignalEmitter for '{}': {e:?}",
attr.attr.name()
);
}
}
if let Err(e) = attr.move_to_zbus(conn).await {
error!("Failed to register attribute '{attr_name}' on zbus: {e:?}");
continue;
}
registry.push(registry_attr);
}
Ok(registry)
} }
pub async fn set_config_or_default( pub async fn set_config_or_default(
attrs: &FirmwareAttributes, attrs: &FirmwareAttributes,
config: &mut Config, config: &mut Config,
power_plugged: bool, power_plugged: bool,
profile: PlatformProfile profile: PlatformProfile,
) { ) {
for attr in attrs.attributes().iter() { for attr in attrs.attributes().iter() {
let name: FirmwareAttribute = attr.name().into(); let name: FirmwareAttribute = attr.name().into();
if name.is_ppt() { if name.is_ppt() || name.is_dgpu() {
let tuning = config.select_tunings(power_plugged, profile); let tuning = config.select_tunings(power_plugged, profile);
if !tuning.enabled { if !tuning.enabled {
debug!("Tuning group is not enabled, skipping"); debug!("Tuning group is not enabled, skipping");
@@ -420,6 +545,20 @@ pub async fn set_config_or_default(
// config.write(); // config.write();
} }
} }
} else {
// Handle non-PPT attributes (boolean and other settings)
if let Some(saved_value) = config.armoury_settings.get(&name) {
attr.set_current_value(&AttrValue::Integer(*saved_value))
.map_err(|e| {
error!("Failed to set {}: {e}", <&str>::from(name));
})
.ok();
info!(
"Restored armoury setting for {} = {:?}",
<&str>::from(name),
saved_value
);
}
} }
} }
} }

View File

@@ -4,7 +4,7 @@ use config_traits::{StdConfig, StdConfigLoad};
use rog_anime::error::AnimeError; use rog_anime::error::AnimeError;
use rog_anime::usb::Brightness; use rog_anime::usb::Brightness;
use rog_anime::{ use rog_anime::{
ActionData, ActionLoader, AnimTime, Animations, AnimeType, DeviceState, Fade, Vec2 ActionData, ActionLoader, AnimTime, Animations, AnimeType, DeviceState, Fade, Vec2,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -15,14 +15,14 @@ pub struct AniMeConfigCached {
pub system: Vec<ActionData>, pub system: Vec<ActionData>,
pub boot: Vec<ActionData>, pub boot: Vec<ActionData>,
pub wake: Vec<ActionData>, pub wake: Vec<ActionData>,
pub shutdown: Vec<ActionData> pub shutdown: Vec<ActionData>,
} }
impl AniMeConfigCached { impl AniMeConfigCached {
pub fn init_from_config( pub fn init_from_config(
&mut self, &mut self,
config: &AniMeConfig, config: &AniMeConfig,
anime_type: AnimeType anime_type: AnimeType,
) -> Result<(), AnimeError> { ) -> Result<(), AnimeError> {
let mut sys = Vec::with_capacity(config.system.len()); let mut sys = Vec::with_capacity(config.system.len());
for ani in &config.system { for ani in &config.system {
@@ -68,7 +68,7 @@ pub struct AniMeConfig {
pub off_when_suspended: bool, pub off_when_suspended: bool,
pub off_when_lid_closed: bool, pub off_when_lid_closed: bool,
pub brightness_on_battery: Brightness, pub brightness_on_battery: Brightness,
pub builtin_anims: Animations pub builtin_anims: Animations,
} }
impl Default for AniMeConfig { impl Default for AniMeConfig {
@@ -87,7 +87,7 @@ impl Default for AniMeConfig {
off_when_suspended: true, off_when_suspended: true,
off_when_lid_closed: true, off_when_lid_closed: true,
brightness_on_battery: Brightness::Low, brightness_on_battery: Brightness::Low,
builtin_anims: Animations::default() builtin_anims: Animations::default(),
} }
} }
} }
@@ -118,7 +118,7 @@ impl From<&AniMeConfig> for DeviceState {
off_when_unplugged: config.off_when_unplugged, off_when_unplugged: config.off_when_unplugged,
off_when_suspended: config.off_when_suspended, off_when_suspended: config.off_when_suspended,
off_when_lid_closed: config.off_when_lid_closed, off_when_lid_closed: config.off_when_lid_closed,
brightness_on_battery: config.brightness_on_battery brightness_on_battery: config.brightness_on_battery,
} }
} }
} }
@@ -148,8 +148,8 @@ impl AniMeConfig {
time: AnimTime::Fade(Fade::new( time: AnimTime::Fade(Fade::new(
Duration::from_secs(2), Duration::from_secs(2),
Some(Duration::from_secs(2)), Some(Duration::from_secs(2)),
Duration::from_secs(2) Duration::from_secs(2),
)) )),
}, },
], ],
wake: vec![ wake: vec![
@@ -162,8 +162,8 @@ impl AniMeConfig {
time: AnimTime::Fade(Fade::new( time: AnimTime::Fade(Fade::new(
Duration::from_secs(2), Duration::from_secs(2),
Some(Duration::from_secs(2)), Some(Duration::from_secs(2)),
Duration::from_secs(2) Duration::from_secs(2),
)) )),
}, },
], ],
shutdown: vec![ shutdown: vec![
@@ -173,7 +173,7 @@ impl AniMeConfig {
angle: 0.0, angle: 0.0,
translation: Vec2::new(3.0, 2.0), translation: Vec2::new(3.0, 2.0),
brightness: 1.0, brightness: 1.0,
time: AnimTime::Infinite time: AnimTime::Infinite,
}, },
], ],
..Default::default() ..Default::default()

View File

@@ -11,7 +11,7 @@ use config_traits::StdConfig;
use log::{debug, error, info, warn}; use log::{debug, error, info, warn};
use rog_anime::usb::{ use rog_anime::usb::{
pkt_flush, pkt_set_brightness, pkt_set_enable_display, pkt_set_enable_powersave_anim, pkt_flush, pkt_set_brightness, pkt_set_enable_display, pkt_set_enable_powersave_anim,
pkts_for_init, Brightness pkts_for_init, Brightness,
}; };
use rog_anime::{ActionData, AnimeDataBuffer, AnimePacketType}; use rog_anime::{ActionData, AnimeDataBuffer, AnimePacketType};
use rog_platform::hid_raw::HidRaw; use rog_platform::hid_raw::HidRaw;
@@ -30,14 +30,14 @@ pub struct AniMe {
// set to force thread to exit // set to force thread to exit
thread_exit: Arc<AtomicBool>, thread_exit: Arc<AtomicBool>,
// Set to false when the thread exits // Set to false when the thread exits
thread_running: Arc<AtomicBool> thread_running: Arc<AtomicBool>,
} }
impl AniMe { impl AniMe {
pub fn new( pub fn new(
hid: Option<Arc<Mutex<HidRaw>>>, hid: Option<Arc<Mutex<HidRaw>>>,
usb: Option<Arc<Mutex<USBRaw>>>, usb: Option<Arc<Mutex<USBRaw>>>,
config: Arc<Mutex<AniMeConfig>> config: Arc<Mutex<AniMeConfig>>,
) -> Self { ) -> Self {
Self { Self {
hid, hid,
@@ -45,7 +45,7 @@ impl AniMe {
config, config,
cache: AniMeConfigCached::default(), cache: AniMeConfigCached::default(),
thread_exit: Arc::new(AtomicBool::new(false)), thread_exit: Arc::new(AtomicBool::new(false)),
thread_running: Arc::new(AtomicBool::new(false)) thread_running: Arc::new(AtomicBool::new(false)),
} }
} }
@@ -106,7 +106,7 @@ impl AniMe {
pub async fn set_builtins_enabled( pub async fn set_builtins_enabled(
&self, &self,
enabled: bool, enabled: bool,
bright: Brightness bright: Brightness,
) -> Result<(), RogError> { ) -> Result<(), RogError> {
self.write_bytes(&pkt_set_enable_powersave_anim(enabled)) self.write_bytes(&pkt_set_enable_powersave_anim(enabled))
.await?; .await?;

View File

@@ -5,7 +5,7 @@ use log::{debug, error, warn};
use logind_zbus::manager::ManagerProxy; use logind_zbus::manager::ManagerProxy;
use rog_anime::usb::{ use rog_anime::usb::{
pkt_set_brightness, pkt_set_builtin_animations, pkt_set_enable_display, pkt_set_brightness, pkt_set_builtin_animations, pkt_set_enable_display,
pkt_set_enable_powersave_anim, Brightness pkt_set_enable_powersave_anim, Brightness,
}; };
use rog_anime::{Animations, AnimeDataBuffer, DeviceState}; use rog_anime::{Animations, AnimeDataBuffer, DeviceState};
use zbus::object_server::SignalEmitter; use zbus::object_server::SignalEmitter;
@@ -41,7 +41,7 @@ impl AniMeZbus {
pub async fn start_tasks( pub async fn start_tasks(
mut self, mut self,
connection: &Connection, connection: &Connection,
path: OwnedObjectPath path: OwnedObjectPath,
) -> Result<(), RogError> { ) -> Result<(), RogError> {
// let task = zbus.clone(); // let task = zbus.clone();
self.reload() self.reload()
@@ -69,7 +69,11 @@ impl AniMeZbus {
/// it is restarted /// it is restarted
async fn write(&self, input: AnimeDataBuffer) -> zbus::fdo::Result<()> { async fn write(&self, input: AnimeDataBuffer) -> zbus::fdo::Result<()> {
let bright = self.0.config.lock().await.display_brightness; let bright = self.0.config.lock().await.display_brightness;
if self.0.config.lock().await.builtin_anims_enabled {
// This clears the display, causing flickers if done indiscriminately on every
// write. Therefore, we guard it behind a config check.
self.0.set_builtins_enabled(false, bright).await?; self.0.set_builtins_enabled(false, bright).await?;
}
self.0.thread_exit.store(true, Ordering::SeqCst); self.0.thread_exit.store(true, Ordering::SeqCst);
self.0.write_data_buffer(input).await.map_err(|err| { self.0.write_data_buffer(input).await.map_err(|err| {
warn!("ctrl_anime::run_animation:callback {}", err); warn!("ctrl_anime::run_animation:callback {}", err);
@@ -169,7 +173,7 @@ impl AniMeZbus {
async fn set_builtin_animations(&self, settings: Animations) { async fn set_builtin_animations(&self, settings: Animations) {
self.0 self.0
.write_bytes(&pkt_set_builtin_animations( .write_bytes(&pkt_set_builtin_animations(
settings.boot, settings.awake, settings.sleep, settings.shutdown settings.boot, settings.awake, settings.sleep, settings.shutdown,
)) ))
.await .await
.map_err(|err| { .map_err(|err| {
@@ -319,7 +323,7 @@ impl crate::CtrlTask for AniMeZbus {
inner inner
.write_bytes(&pkt_set_enable_display( .write_bytes(&pkt_set_enable_display(
!(sleeping && config.off_when_suspended) !(sleeping && config.off_when_suspended),
)) ))
.await .await
.map_err(|err| { .map_err(|err| {
@@ -330,7 +334,7 @@ impl crate::CtrlTask for AniMeZbus {
if config.builtin_anims_enabled { if config.builtin_anims_enabled {
inner inner
.write_bytes(&pkt_set_enable_powersave_anim( .write_bytes(&pkt_set_enable_powersave_anim(
!(sleeping && config.off_when_suspended) !(sleeping && config.off_when_suspended),
)) ))
.await .await
.map_err(|err| { .map_err(|err| {
@@ -433,7 +437,7 @@ impl crate::CtrlTask for AniMeZbus {
.ok(); .ok();
} }
} }
} },
) )
.await; .await;
@@ -460,7 +464,7 @@ impl crate::Reloadable for AniMeZbus {
builtin_anims.boot, builtin_anims.boot,
builtin_anims.awake, builtin_anims.awake,
builtin_anims.sleep, builtin_anims.sleep,
builtin_anims.shutdown builtin_anims.shutdown,
)) ))
.await?; .await?;
} }

View File

@@ -5,7 +5,7 @@ use log::{debug, info, warn};
use rog_aura::aura_detection::LedSupportData; use rog_aura::aura_detection::LedSupportData;
use rog_aura::keyboard::LaptopAuraPower; use rog_aura::keyboard::LaptopAuraPower;
use rog_aura::{ use rog_aura::{
AuraDeviceType, AuraEffect, AuraModeNum, AuraZone, Direction, LedBrightness, Speed, GRADIENT AuraDeviceType, AuraEffect, AuraModeNum, AuraZone, Direction, LedBrightness, Speed, GRADIENT,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -29,7 +29,7 @@ pub struct AuraConfig {
pub multizone_on: bool, pub multizone_on: bool,
pub enabled: LaptopAuraPower, pub enabled: LaptopAuraPower,
#[serde(skip)] #[serde(skip)]
pub per_key_mode_active: bool pub per_key_mode_active: bool,
} }
impl StdConfig for AuraConfig { impl StdConfig for AuraConfig {
@@ -74,7 +74,7 @@ impl AuraConfig {
multizone: None, multizone: None,
multizone_on: false, multizone_on: false,
enabled, enabled,
per_key_mode_active: false per_key_mode_active: false,
}; };
for n in &config.support_data.basic_modes { for n in &config.support_data.basic_modes {
@@ -82,8 +82,9 @@ impl AuraConfig {
config config
.builtins .builtins
.insert(*n, AuraEffect::default_with_mode(*n)); .insert(*n, AuraEffect::default_with_mode(*n));
}
if !config.support_data.basic_zones.is_empty() { if !config.support_data.basic_zones.is_empty() {
for n in &config.support_data.basic_modes {
let mut default = vec![]; let mut default = vec![];
for (i, tmp) in config.support_data.basic_zones.iter().enumerate() { for (i, tmp) in config.support_data.basic_zones.iter().enumerate() {
default.push(AuraEffect { default.push(AuraEffect {
@@ -92,7 +93,7 @@ impl AuraConfig {
colour1: *GRADIENT.get(i).unwrap_or(&GRADIENT[0]), colour1: *GRADIENT.get(i).unwrap_or(&GRADIENT[0]),
colour2: *GRADIENT.get(GRADIENT.len() - i).unwrap_or(&GRADIENT[6]), colour2: *GRADIENT.get(GRADIENT.len() - i).unwrap_or(&GRADIENT[6]),
speed: Speed::Med, speed: Speed::Med,
direction: Direction::Left direction: Direction::Left,
}); });
} }
if let Some(m) = config.multizone.as_mut() { if let Some(m) = config.multizone.as_mut() {
@@ -118,14 +119,14 @@ impl AuraConfig {
self.multizone_on = false; self.multizone_on = false;
} else { } else {
if let Some(multi) = self.multizone.as_mut() { if let Some(multi) = self.multizone.as_mut() {
if let Some(fx) = multi.get_mut(effect.mode()) { if let Some(fx_vec) = multi.get_mut(effect.mode()) {
for fx in fx.iter_mut() { for fx in fx_vec.iter_mut() {
if fx.zone == effect.zone { if fx.zone == effect.zone {
*fx = effect; *fx = effect;
return; return;
} }
} }
fx.push(effect); fx_vec.push(effect);
} else { } else {
multi.insert(*effect.mode(), vec![effect]); multi.insert(*effect.mode(), vec![effect]);
} }
@@ -156,7 +157,7 @@ impl AuraConfig {
colour1: *GRADIENT.get(i).unwrap_or(&GRADIENT[0]), colour1: *GRADIENT.get(i).unwrap_or(&GRADIENT[0]),
colour2: *GRADIENT.get(GRADIENT.len() - i).unwrap_or(&GRADIENT[6]), colour2: *GRADIENT.get(GRADIENT.len() - i).unwrap_or(&GRADIENT[6]),
speed: Speed::Med, speed: Speed::Med,
direction: Direction::Left direction: Direction::Left,
}); });
} }
if default.is_empty() { if default.is_empty() {
@@ -230,15 +231,29 @@ impl AuraConfig {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::sync::{Mutex, MutexGuard, OnceLock};
use rog_aura::keyboard::AuraPowerState; use rog_aura::keyboard::AuraPowerState;
use rog_aura::{ use rog_aura::{
AuraEffect, AuraModeNum, AuraZone, Colour, Direction, LedBrightness, PowerZones, Speed AuraEffect, AuraModeNum, AuraZone, Colour, Direction, LedBrightness, PowerZones, Speed,
}; };
use super::AuraConfig; use super::AuraConfig;
// Global mutex to serialize tests that rely on process-wide environment
// variables
static TEST_MUTEX: OnceLock<Mutex<()>> = OnceLock::new();
fn test_lock() -> MutexGuard<'static, ()> {
TEST_MUTEX
.get_or_init(|| Mutex::new(()))
.lock()
.expect("TEST_MUTEX poisoned")
}
#[test] #[test]
fn set_multizone_4key_config() { fn set_multizone_4key_config() {
let _guard = test_lock();
std::env::set_var("BOARD_NAME", ""); std::env::set_var("BOARD_NAME", "");
let mut config = AuraConfig::new("19b6"); let mut config = AuraConfig::new("19b6");
@@ -246,7 +261,7 @@ mod tests {
colour1: Colour { colour1: Colour {
r: 0xff, r: 0xff,
g: 0x00, g: 0x00,
b: 0xff b: 0xff,
}, },
zone: AuraZone::Key1, zone: AuraZone::Key1,
..Default::default() ..Default::default()
@@ -259,7 +274,7 @@ mod tests {
colour1: Colour { colour1: Colour {
r: 0x00, r: 0x00,
g: 0xff, g: 0xff,
b: 0xff b: 0xff,
}, },
zone: AuraZone::Key2, zone: AuraZone::Key2,
..Default::default() ..Default::default()
@@ -270,7 +285,7 @@ mod tests {
colour1: Colour { colour1: Colour {
r: 0xff, r: 0xff,
g: 0xff, g: 0xff,
b: 0x00 b: 0x00,
}, },
zone: AuraZone::Key3, zone: AuraZone::Key3,
..Default::default() ..Default::default()
@@ -281,7 +296,7 @@ mod tests {
colour1: Colour { colour1: Colour {
r: 0x00, r: 0x00,
g: 0xff, g: 0xff,
b: 0x00 b: 0x00,
}, },
zone: AuraZone::Key4, zone: AuraZone::Key4,
..Default::default() ..Default::default()
@@ -294,30 +309,43 @@ mod tests {
let res = config.multizone.unwrap(); let res = config.multizone.unwrap();
let sta = res.get(&AuraModeNum::Static).unwrap(); let sta = res.get(&AuraModeNum::Static).unwrap();
assert_eq!(sta.len(), 4); assert_eq!(sta.len(), 4);
assert_eq!(sta[0].colour1, Colour { assert_eq!(
sta[0].colour1,
Colour {
r: 0xff, r: 0xff,
g: 0x00, g: 0x00,
b: 0xff b: 0xff
}); }
assert_eq!(sta[1].colour1, Colour { );
assert_eq!(
sta[1].colour1,
Colour {
r: 0x00, r: 0x00,
g: 0xff, g: 0xff,
b: 0xff b: 0xff
}); }
assert_eq!(sta[2].colour1, Colour { );
assert_eq!(
sta[2].colour1,
Colour {
r: 0xff, r: 0xff,
g: 0xff, g: 0xff,
b: 0x00 b: 0x00
}); }
assert_eq!(sta[3].colour1, Colour { );
assert_eq!(
sta[3].colour1,
Colour {
r: 0x00, r: 0x00,
g: 0xff, g: 0xff,
b: 0x00 b: 0x00
}); }
);
} }
#[test] #[test]
fn set_multizone_multimode_config() { fn set_multizone_multimode_config() {
let _guard = test_lock();
std::env::set_var("BOARD_NAME", ""); std::env::set_var("BOARD_NAME", "");
let mut config = AuraConfig::new("19b6"); let mut config = AuraConfig::new("19b6");
@@ -366,51 +394,65 @@ mod tests {
#[test] #[test]
fn verify_0x1866_g531i() { fn verify_0x1866_g531i() {
let _guard = test_lock();
std::env::set_var("BOARD_NAME", "G513I"); std::env::set_var("BOARD_NAME", "G513I");
let mut config = AuraConfig::new("1866"); let mut config = AuraConfig::new("1866");
assert_eq!(config.brightness, LedBrightness::Med); assert_eq!(config.brightness, LedBrightness::Med);
assert_eq!(config.builtins.len(), 5); assert_eq!(config.builtins.len(), 5);
assert_eq!(config.builtins.first_entry().unwrap().get(), &AuraEffect { assert_eq!(
config.builtins.first_entry().unwrap().get(),
&AuraEffect {
mode: AuraModeNum::Static, mode: AuraModeNum::Static,
zone: AuraZone::None, zone: AuraZone::None,
colour1: Colour { r: 166, g: 0, b: 0 }, colour1: Colour { r: 166, g: 0, b: 0 },
colour2: Colour { r: 0, g: 0, b: 0 }, colour2: Colour { r: 0, g: 0, b: 0 },
speed: Speed::Med, speed: Speed::Med,
direction: Direction::Right direction: Direction::Right
}); }
);
assert_eq!(config.enabled.states.len(), 1); assert_eq!(config.enabled.states.len(), 1);
assert_eq!(config.enabled.states[0], AuraPowerState { assert_eq!(
config.enabled.states[0],
AuraPowerState {
zone: PowerZones::KeyboardAndLightbar, zone: PowerZones::KeyboardAndLightbar,
boot: true, boot: true,
awake: true, awake: true,
sleep: true, sleep: true,
shutdown: true shutdown: true
}); }
);
} }
#[test] #[test]
fn verify_0x19b6_g634j() { fn verify_0x19b6_g634j() {
let _guard = test_lock();
std::env::set_var("BOARD_NAME", "G634J"); std::env::set_var("BOARD_NAME", "G634J");
let mut config = AuraConfig::new("19b6"); let mut config = AuraConfig::new("19b6");
assert_eq!(config.brightness, LedBrightness::Med); assert_eq!(config.brightness, LedBrightness::Med);
assert_eq!(config.builtins.len(), 12); assert_eq!(config.builtins.len(), 12);
assert_eq!(config.builtins.first_entry().unwrap().get(), &AuraEffect { assert_eq!(
config.builtins.first_entry().unwrap().get(),
&AuraEffect {
mode: AuraModeNum::Static, mode: AuraModeNum::Static,
zone: AuraZone::None, zone: AuraZone::None,
colour1: Colour { r: 166, g: 0, b: 0 }, colour1: Colour { r: 166, g: 0, b: 0 },
colour2: Colour { r: 0, g: 0, b: 0 }, colour2: Colour { r: 0, g: 0, b: 0 },
speed: Speed::Med, speed: Speed::Med,
direction: Direction::Right direction: Direction::Right
}); }
);
assert_eq!(config.enabled.states.len(), 4); assert_eq!(config.enabled.states.len(), 4);
assert_eq!(config.enabled.states[0], AuraPowerState { assert_eq!(
config.enabled.states[0],
AuraPowerState {
zone: PowerZones::Keyboard, zone: PowerZones::Keyboard,
boot: true, boot: true,
awake: true, awake: true,
sleep: true, sleep: true,
shutdown: true shutdown: true
}); }
);
} }
} }

View File

@@ -19,7 +19,7 @@ pub mod trait_impls;
pub struct Aura { pub struct Aura {
pub hid: Option<Arc<Mutex<HidRaw>>>, pub hid: Option<Arc<Mutex<HidRaw>>>,
pub backlight: Option<Arc<Mutex<KeyboardBacklight>>>, pub backlight: Option<Arc<Mutex<KeyboardBacklight>>>,
pub config: Arc<Mutex<AuraConfig>> pub config: Arc<Mutex<AuraConfig>>,
} }
impl Aura { impl Aura {
@@ -28,7 +28,7 @@ impl Aura {
Ok(()) Ok(())
} }
pub async fn lock_config(&self) -> MutexGuard<AuraConfig> { pub async fn lock_config(&self) -> MutexGuard<'_, AuraConfig> {
self.config.lock().await self.config.lock().await
} }
@@ -91,13 +91,13 @@ impl Aura {
pub async fn write_effect_and_apply( pub async fn write_effect_and_apply(
&self, &self,
dev_type: AuraDeviceType, dev_type: AuraDeviceType,
mode: &AuraEffect mode: &AuraEffect,
) -> Result<(), RogError> { ) -> Result<(), RogError> {
if matches!(dev_type, AuraDeviceType::LaptopKeyboardTuf) { if matches!(dev_type, AuraDeviceType::LaptopKeyboardTuf) {
if let Some(platform) = &self.backlight { if let Some(platform) = &self.backlight {
let buf = [ let buf = [
1, mode.mode as u8, mode.colour1.r, mode.colour1.g, mode.colour1.b, 1, mode.mode as u8, mode.colour1.r, mode.colour1.g, mode.colour1.b,
mode.speed as u8 mode.speed as u8,
]; ];
platform.lock().await.set_kbd_rgb_mode(&buf)?; platform.lock().await.set_kbd_rgb_mode(&buf)?;
} }
@@ -121,7 +121,7 @@ impl Aura {
return Ok(()); return Ok(());
} }
Err(RogError::MissingFunction( Err(RogError::MissingFunction(
"No LED backlight control available".to_string() "No LED backlight control available".to_string(),
)) ))
} }
@@ -145,7 +145,7 @@ impl Aura {
0x01, 0x01,
p.new_to_byte() as u8, p.new_to_byte() as u8,
0x0, 0x0,
0x0 0x0,
]; ];
hid_raw.write_bytes(&msg)?; hid_raw.write_bytes(&msg)?;
return Ok(()); return Ok(());
@@ -154,7 +154,7 @@ impl Aura {
let bytes = config.enabled.to_bytes(config.led_type); let bytes = config.enabled.to_bytes(config.led_type);
let msg = [ let msg = [
0x5d, 0xbd, 0x01, bytes[0], bytes[1], bytes[2], bytes[3] 0x5d, 0xbd, 0x01, bytes[0], bytes[1], bytes[2], bytes[3],
]; ];
hid_raw.write_bytes(&msg)?; hid_raw.write_bytes(&msg)?;
} }
@@ -167,7 +167,7 @@ impl Aura {
pub async fn write_effect_block( pub async fn write_effect_block(
&self, &self,
config: &mut AuraConfig, config: &mut AuraConfig,
effect: &AuraLaptopUsbPackets effect: &AuraLaptopUsbPackets,
) -> Result<(), RogError> { ) -> Result<(), RogError> {
if config.brightness == LedBrightness::Off { if config.brightness == LedBrightness::Off {
config.brightness = LedBrightness::Med; config.brightness = LedBrightness::Med;
@@ -201,7 +201,7 @@ impl Aura {
let g = row[10]; let g = row[10];
let b = row[11]; let b = row[11];
tuf.lock().await.set_kbd_rgb_mode(&[ tuf.lock().await.set_kbd_rgb_mode(&[
0, 0, r, g, b, 0 0, 0, r, g, b, 0,
])?; ])?;
} }
} }
@@ -215,7 +215,7 @@ impl Aura {
let mut config = self.config.lock().await; let mut config = self.config.lock().await;
if config.ally_fix.is_none() { if config.ally_fix.is_none() {
let msg = [ let msg = [
0x5d, 0xbd, 0x01, 0xff, 0xff, 0xff, 0xff 0x5d, 0xbd, 0x01, 0xff, 0xff, 0xff, 0xff,
]; ];
hid_raw.lock().await.write_bytes(&msg)?; hid_raw.lock().await.write_bytes(&msg)?;
info!("Reset Ally power settings to base"); info!("Reset Ally power settings to base");

View File

@@ -28,7 +28,7 @@ impl AuraZbus {
mut self, mut self,
connection: &Connection, connection: &Connection,
// _signal_ctx: SignalEmitter<'static>, // _signal_ctx: SignalEmitter<'static>,
path: OwnedObjectPath path: OwnedObjectPath,
) -> Result<(), RogError> { ) -> Result<(), RogError> {
// let task = zbus.clone(); // let task = zbus.clone();
// let signal_ctx = signal_ctx.clone(); // let signal_ctx = signal_ctx.clone();
@@ -71,7 +71,13 @@ impl AuraZbus {
#[zbus(property)] #[zbus(property)]
async fn set_brightness(&mut self, brightness: LedBrightness) -> Result<(), ZbErr> { async fn set_brightness(&mut self, brightness: LedBrightness) -> Result<(), ZbErr> {
if let Some(bl) = self.0.backlight.as_ref() { if let Some(bl) = self.0.backlight.as_ref() {
return Ok(bl.lock().await.set_brightness(brightness.into())?); let res = bl.lock().await.set_brightness(brightness.into());
if res.is_ok() {
let mut config = self.0.config.lock().await;
config.brightness = brightness;
config.write();
}
return Ok(res?);
} }
Err(ZbErr::Failed("No sysfs brightness control".to_string())) Err(ZbErr::Failed("No sysfs brightness control".to_string()))
} }
@@ -144,7 +150,7 @@ impl AuraZbus {
let mode = config.current_mode; let mode = config.current_mode;
match config.builtins.get(&mode) { match config.builtins.get(&mode) {
Some(effect) => Ok(effect.clone()), Some(effect) => Ok(effect.clone()),
None => Err(ZbErr::Failed("Could not get the current effect".into())) None => Err(ZbErr::Failed("Could not get the current effect".into())),
} }
} else { } else {
Err(ZbErr::Failed("Aura control couldn't lock self".to_string())) Err(ZbErr::Failed("Aura control couldn't lock self".to_string()))
@@ -297,7 +303,7 @@ impl CtrlTask for AuraZbus {
move |_power_plugged| { move |_power_plugged| {
// power change // power change
async move {} async move {}
} },
) )
.await; .await;

View File

@@ -4,6 +4,7 @@
// - Add it to Zbus server // - Add it to Zbus server
// - If udev sees device removed then remove the zbus path // - If udev sees device removed then remove the zbus path
use std::collections::HashMap;
use std::sync::Arc; use std::sync::Arc;
use dmi_id::DMIID; use dmi_id::DMIID;
@@ -56,7 +57,7 @@ fn dbus_path_for_dev(parent: &Device) -> Option<OwnedObjectPath> {
if let Some(filename) = filename_partial(parent) { if let Some(filename) = filename_partial(parent) {
return Some( return Some(
ObjectPath::from_str_unchecked(&format!("{ASUS_ZBUS_PATH}/{MOD_NAME}/{filename}")) ObjectPath::from_str_unchecked(&format!("{ASUS_ZBUS_PATH}/{MOD_NAME}/{filename}"))
.into() .into(),
); );
} }
None None
@@ -91,24 +92,47 @@ fn dev_prop_matches(dev: &Device, prop: &str, value: &str) -> bool {
/// required. /// required.
pub struct AsusDevice { pub struct AsusDevice {
device: DeviceHandle, device: DeviceHandle,
dbus_path: OwnedObjectPath dbus_path: OwnedObjectPath,
hid_key: Option<String>,
} }
pub struct DeviceManager { pub struct DeviceManager {
_dbus_connection: Connection _dbus_connection: Connection,
_hid_handles: Arc<Mutex<HashMap<String, Arc<Mutex<HidRaw>>>>>,
} }
impl DeviceManager { impl DeviceManager {
#[allow(clippy::type_complexity)]
async fn get_or_create_hid_handle(
handles: &Arc<Mutex<HashMap<String, Arc<Mutex<HidRaw>>>>>,
endpoint: &Device,
) -> Result<(Arc<Mutex<HidRaw>>, String), RogError> {
let dev_node = endpoint
.devnode()
.ok_or_else(|| RogError::MissingFunction("hidraw devnode missing".to_string()))?;
let key = dev_node.to_string_lossy().to_string();
if let Some(existing) = handles.lock().await.get(&key).cloned() {
return Ok((existing, key));
}
let hidraw = HidRaw::from_device(endpoint.clone())?;
let handle = Arc::new(Mutex::new(hidraw));
handles.lock().await.insert(key.clone(), handle.clone());
Ok((handle, key))
}
async fn init_hid_devices( async fn init_hid_devices(
connection: &Connection, connection: &Connection,
device: Device device: Device,
handles: Arc<Mutex<HashMap<String, Arc<Mutex<HidRaw>>>>>,
) -> Result<Vec<AsusDevice>, RogError> { ) -> Result<Vec<AsusDevice>, RogError> {
let mut devices = Vec::new(); let mut devices = Vec::new();
if let Some(usb_device) = device.parent_with_subsystem_devtype("usb", "usb_device")? { if let Some(usb_device) = device.parent_with_subsystem_devtype("usb", "usb_device")? {
if let Some(usb_id) = usb_device.attribute_value("idProduct") { if let Some(usb_id) = usb_device.attribute_value("idProduct") {
if let Some(vendor_id) = usb_device.attribute_value("idVendor") { if let Some(vendor_id) = usb_device.attribute_value("idVendor") {
if vendor_id != "0b05" { if vendor_id != "0b05" {
debug!("Not ASUS vendor ID"); debug!("Not ASUS vendor ID: {}", vendor_id.to_string_lossy());
return Ok(devices); return Ok(devices);
} }
// Almost all devices are identified by the productId. // Almost all devices are identified by the productId.
@@ -116,13 +140,14 @@ impl DeviceManager {
// 1. Generate an interface path // 1. Generate an interface path
// 2. Create the device // 2. Create the device
// Use the top-level endpoint, not the parent // Use the top-level endpoint, not the parent
if let Ok(hidraw) = HidRaw::from_device(device) { if let Ok((dev, hid_key)) =
Self::get_or_create_hid_handle(&handles, &device).await
{
debug!("Testing device {usb_id:?}"); debug!("Testing device {usb_id:?}");
let dev = Arc::new(Mutex::new(hidraw));
// SLASH DEVICE // SLASH DEVICE
if let Ok(dev_type) = DeviceHandle::new_slash_hid( if let Ok(dev_type) = DeviceHandle::new_slash_hid(
dev.clone(), dev.clone(),
usb_id.to_str().unwrap_or_default() usb_id.to_str().unwrap_or_default(),
) )
.await .await
{ {
@@ -133,14 +158,15 @@ impl DeviceManager {
ctrl.start_tasks(connection, path.clone()).await.unwrap(); ctrl.start_tasks(connection, path.clone()).await.unwrap();
devices.push(AsusDevice { devices.push(AsusDevice {
device: dev_type, device: dev_type,
dbus_path: path dbus_path: path,
hid_key: Some(hid_key.clone()),
}); });
} }
} }
// ANIME MATRIX DEVICE // ANIME MATRIX DEVICE
if let Ok(dev_type) = DeviceHandle::maybe_anime_hid( if let Ok(dev_type) = DeviceHandle::maybe_anime_hid(
dev.clone(), dev.clone(),
usb_id.to_str().unwrap_or_default() usb_id.to_str().unwrap_or_default(),
) )
.await .await
{ {
@@ -151,14 +177,15 @@ impl DeviceManager {
ctrl.start_tasks(connection, path.clone()).await.unwrap(); ctrl.start_tasks(connection, path.clone()).await.unwrap();
devices.push(AsusDevice { devices.push(AsusDevice {
device: dev_type, device: dev_type,
dbus_path: path dbus_path: path,
hid_key: Some(hid_key.clone()),
}); });
} }
} }
// AURA LAPTOP DEVICE // AURA LAPTOP DEVICE
if let Ok(dev_type) = DeviceHandle::maybe_laptop_aura( if let Ok(dev_type) = DeviceHandle::maybe_laptop_aura(
Some(dev), Some(dev),
usb_id.to_str().unwrap_or_default() usb_id.to_str().unwrap_or_default(),
) )
.await .await
{ {
@@ -169,10 +196,13 @@ impl DeviceManager {
ctrl.start_tasks(connection, path.clone()).await.unwrap(); ctrl.start_tasks(connection, path.clone()).await.unwrap();
devices.push(AsusDevice { devices.push(AsusDevice {
device: dev_type, device: dev_type,
dbus_path: path dbus_path: path,
hid_key: Some(hid_key),
}); });
} }
} }
} else {
warn!("Failed to initialise shared hid handle for {usb_id:?}");
} }
} }
} }
@@ -181,7 +211,10 @@ impl DeviceManager {
} }
/// To be called on daemon startup /// To be called on daemon startup
async fn init_all_hid(connection: &Connection) -> Result<Vec<AsusDevice>, RogError> { async fn init_all_hid(
connection: &Connection,
handles: Arc<Mutex<HashMap<String, Arc<Mutex<HidRaw>>>>>,
) -> Result<Vec<AsusDevice>, RogError> {
// track and ensure we use only one hidraw per prod_id // track and ensure we use only one hidraw per prod_id
// let mut interfaces = HashSet::new(); // let mut interfaces = HashSet::new();
let mut devices: Vec<AsusDevice> = Vec::new(); let mut devices: Vec<AsusDevice> = Vec::new();
@@ -200,7 +233,7 @@ impl DeviceManager {
.scan_devices() .scan_devices()
.map_err(|e| PlatformError::IoPath("enumerator".to_owned(), e))? .map_err(|e| PlatformError::IoPath("enumerator".to_owned(), e))?
{ {
devices.append(&mut Self::init_hid_devices(connection, device).await?); devices.append(&mut Self::init_hid_devices(connection, device, handles.clone()).await?);
} }
Ok(devices) Ok(devices)
@@ -209,7 +242,7 @@ impl DeviceManager {
async fn init_scsi( async fn init_scsi(
connection: &Connection, connection: &Connection,
device: &Device, device: &Device,
path: OwnedObjectPath path: OwnedObjectPath,
) -> Option<AsusDevice> { ) -> Option<AsusDevice> {
// "ID_MODEL_ID" "1932" // "ID_MODEL_ID" "1932"
// "ID_VENDOR_ID" "0b05" // "ID_VENDOR_ID" "0b05"
@@ -227,7 +260,8 @@ impl DeviceManager {
ctrl.start_tasks(connection, path.clone()).await.unwrap(); ctrl.start_tasks(connection, path.clone()).await.unwrap();
return Some(AsusDevice { return Some(AsusDevice {
device: dev_type, device: dev_type,
dbus_path: path dbus_path: path,
hid_key: None,
}); });
} }
} }
@@ -275,10 +309,13 @@ impl DeviceManager {
Ok(devices) Ok(devices)
} }
pub async fn find_all_devices(connection: &Connection) -> Vec<AsusDevice> { pub async fn find_all_devices(
connection: &Connection,
handles: Arc<Mutex<HashMap<String, Arc<Mutex<HidRaw>>>>>,
) -> Vec<AsusDevice> {
let mut devices: Vec<AsusDevice> = Vec::new(); let mut devices: Vec<AsusDevice> = Vec::new();
// HID first, always // HID first, always
if let Ok(devs) = &mut Self::init_all_hid(connection).await { if let Ok(devs) = &mut Self::init_all_hid(connection, handles.clone()).await {
devices.append(devs); devices.append(devs);
} }
// USB after, need to check if HID picked something up and if so, skip it // USB after, need to check if HID picked something up and if so, skip it
@@ -305,7 +342,8 @@ impl DeviceManager {
ctrl.start_tasks(connection, path.clone()).await.unwrap(); ctrl.start_tasks(connection, path.clone()).await.unwrap();
devices.push(AsusDevice { devices.push(AsusDevice {
device: dev_type, device: dev_type,
dbus_path: path dbus_path: path,
hid_key: None,
}); });
} }
} else { } else {
@@ -327,7 +365,8 @@ impl DeviceManager {
{ {
devices.push(AsusDevice { devices.push(AsusDevice {
device: dev_type, device: dev_type,
dbus_path: path dbus_path: path,
hid_key: None,
}); });
} }
} }
@@ -354,7 +393,8 @@ impl DeviceManager {
ctrl.start_tasks(connection, path.clone()).await.unwrap(); ctrl.start_tasks(connection, path.clone()).await.unwrap();
devices.push(AsusDevice { devices.push(AsusDevice {
device: dev_type, device: dev_type,
dbus_path: path dbus_path: path,
hid_key: None,
}); });
} }
} }
@@ -370,16 +410,19 @@ impl DeviceManager {
pub async fn new(connection: Connection) -> Result<Self, RogError> { pub async fn new(connection: Connection) -> Result<Self, RogError> {
let conn_copy = connection.clone(); let conn_copy = connection.clone();
let devices = Self::find_all_devices(&conn_copy).await; let hid_handles = Arc::new(Mutex::new(HashMap::new()));
let devices = Self::find_all_devices(&conn_copy, hid_handles.clone()).await;
info!("Found {} valid devices on startup", devices.len()); info!("Found {} valid devices on startup", devices.len());
let devices = Arc::new(Mutex::new(devices)); let devices = Arc::new(Mutex::new(devices));
let manager = Self { let manager = Self {
_dbus_connection: connection _dbus_connection: connection,
_hid_handles: hid_handles.clone(),
}; };
// TODO: The /sysfs/ LEDs don't cause events, so they need to be manually // TODO: The /sysfs/ LEDs don't cause events, so they need to be manually
// checked for and added // checked for and added
let hid_handles_thread = hid_handles.clone();
std::thread::spawn(move || { std::thread::spawn(move || {
let mut monitor = MonitorBuilder::new()?.listen()?; let mut monitor = MonitorBuilder::new()?.listen()?;
let mut poll = Poll::new()?; let mut poll = Poll::new()?;
@@ -408,6 +451,7 @@ impl DeviceManager {
let devices = devices.clone(); let devices = devices.clone();
let conn_copy = conn_copy.clone(); let conn_copy = conn_copy.clone();
let hid_handles = hid_handles_thread.clone();
block_on(async move { block_on(async move {
// SCSCI devs // SCSCI devs
if subsys == "block" { if subsys == "block" {
@@ -483,6 +527,7 @@ impl DeviceManager {
// Iter in reverse so as to not screw up indexing // Iter in reverse so as to not screw up indexing
for index in removals.iter().rev() { for index in removals.iter().rev() {
let dev = devices.lock().await.remove(*index); let dev = devices.lock().await.remove(*index);
let hid_key = dev.hid_key.clone();
let path = path.clone(); let path = path.clone();
let res = match dev.device { let res = match dev.device {
DeviceHandle::Aura(_) => { DeviceHandle::Aura(_) => {
@@ -509,15 +554,21 @@ impl DeviceManager {
.remove::<ScsiZbus, _>(&path) .remove::<ScsiZbus, _>(&path)
.await? .await?
} }
_ => todo!() _ => todo!(),
}; };
info!("AuraManager removed: {path:?}, {res}"); info!("AuraManager removed: {path:?}, {res}");
if let Some(key) = hid_key {
hid_handles.lock().await.remove(&key);
}
} }
} }
} else if action == "add" { } else if action == "add" {
let evdev = event.device(); let evdev = event.device();
if let Ok(mut new_devs) = if let Ok(mut new_devs) = Self::init_hid_devices(
Self::init_hid_devices(&conn_copy, evdev) &conn_copy,
evdev,
hid_handles.clone(),
)
.await .await
.map_err(|e| error!("Couldn't add new device: {e:?}")) .map_err(|e| error!("Couldn't add new device: {e:?}"))
{ {

View File

@@ -14,7 +14,7 @@ pub struct ScsiConfig {
pub dev_type: AuraDeviceType, pub dev_type: AuraDeviceType,
pub enabled: bool, pub enabled: bool,
pub current_mode: AuraMode, pub current_mode: AuraMode,
pub modes: BTreeMap<AuraMode, AuraEffect> pub modes: BTreeMap<AuraMode, AuraEffect>,
} }
impl ScsiConfig { impl ScsiConfig {
@@ -38,61 +38,61 @@ impl Default for ScsiConfig {
(AuraMode::Off, AuraEffect::default_with_mode(AuraMode::Off)), (AuraMode::Off, AuraEffect::default_with_mode(AuraMode::Off)),
( (
AuraMode::Static, AuraMode::Static,
AuraEffect::default_with_mode(AuraMode::Static) AuraEffect::default_with_mode(AuraMode::Static),
), ),
( (
AuraMode::Breathe, AuraMode::Breathe,
AuraEffect::default_with_mode(AuraMode::Breathe) AuraEffect::default_with_mode(AuraMode::Breathe),
), ),
( (
AuraMode::Flashing, AuraMode::Flashing,
AuraEffect::default_with_mode(AuraMode::Flashing) AuraEffect::default_with_mode(AuraMode::Flashing),
), ),
( (
AuraMode::RainbowCycle, AuraMode::RainbowCycle,
AuraEffect::default_with_mode(AuraMode::RainbowCycle) AuraEffect::default_with_mode(AuraMode::RainbowCycle),
), ),
( (
AuraMode::RainbowWave, AuraMode::RainbowWave,
AuraEffect::default_with_mode(AuraMode::RainbowWave) AuraEffect::default_with_mode(AuraMode::RainbowWave),
), ),
( (
AuraMode::RainbowCycleBreathe, AuraMode::RainbowCycleBreathe,
AuraEffect::default_with_mode(AuraMode::RainbowCycleBreathe) AuraEffect::default_with_mode(AuraMode::RainbowCycleBreathe),
), ),
( (
AuraMode::ChaseFade, AuraMode::ChaseFade,
AuraEffect::default_with_mode(AuraMode::ChaseFade) AuraEffect::default_with_mode(AuraMode::ChaseFade),
), ),
( (
AuraMode::RainbowCycleChaseFade, AuraMode::RainbowCycleChaseFade,
AuraEffect::default_with_mode(AuraMode::RainbowCycleChaseFade) AuraEffect::default_with_mode(AuraMode::RainbowCycleChaseFade),
), ),
( (
AuraMode::Chase, AuraMode::Chase,
AuraEffect::default_with_mode(AuraMode::Chase) AuraEffect::default_with_mode(AuraMode::Chase),
), ),
( (
AuraMode::RainbowCycleChase, AuraMode::RainbowCycleChase,
AuraEffect::default_with_mode(AuraMode::RainbowCycleChase) AuraEffect::default_with_mode(AuraMode::RainbowCycleChase),
), ),
( (
AuraMode::RainbowCycleWave, AuraMode::RainbowCycleWave,
AuraEffect::default_with_mode(AuraMode::RainbowCycleWave) AuraEffect::default_with_mode(AuraMode::RainbowCycleWave),
), ),
( (
AuraMode::RainbowPulseChase, AuraMode::RainbowPulseChase,
AuraEffect::default_with_mode(AuraMode::RainbowPulseChase) AuraEffect::default_with_mode(AuraMode::RainbowPulseChase),
), ),
( (
AuraMode::RandomFlicker, AuraMode::RandomFlicker,
AuraEffect::default_with_mode(AuraMode::RandomFlicker) AuraEffect::default_with_mode(AuraMode::RandomFlicker),
), ),
( (
AuraMode::DoubleFade, AuraMode::DoubleFade,
AuraEffect::default_with_mode(AuraMode::DoubleFade) AuraEffect::default_with_mode(AuraMode::DoubleFade),
) ),
]) ]),
} }
} }
} }

View File

@@ -12,7 +12,7 @@ pub mod trait_impls;
#[derive(Clone)] #[derive(Clone)]
pub struct ScsiAura { pub struct ScsiAura {
device: Arc<Mutex<Device>>, device: Arc<Mutex<Device>>,
config: Arc<Mutex<ScsiConfig>> config: Arc<Mutex<ScsiConfig>>,
} }
impl ScsiAura { impl ScsiAura {
@@ -20,7 +20,7 @@ impl ScsiAura {
Self { device, config } Self { device, config }
} }
pub async fn lock_config(&self) -> MutexGuard<ScsiConfig> { pub async fn lock_config(&self) -> MutexGuard<'_, ScsiConfig> {
self.config.lock().await self.config.lock().await
} }

View File

@@ -22,7 +22,7 @@ impl ScsiZbus {
pub async fn start_tasks( pub async fn start_tasks(
self, self,
connection: &Connection, connection: &Connection,
path: OwnedObjectPath path: OwnedObjectPath,
) -> Result<(), RogError> { ) -> Result<(), RogError> {
connection connection
.object_server() .object_server()
@@ -87,7 +87,7 @@ impl ScsiZbus {
let mode = config.current_mode; let mode = config.current_mode;
match config.modes.get(&mode) { match config.modes.get(&mode) {
Some(effect) => Ok(effect.clone()), Some(effect) => Ok(effect.clone()),
None => Err(ZbErr::Failed("Could not get the current effect".into())) None => Err(ZbErr::Failed("Could not get the current effect".into())),
} }
} else { } else {
Err(ZbErr::Failed("Aura control couldn't lock self".to_string())) Err(ZbErr::Failed("Aura control couldn't lock self".to_string()))

View File

@@ -17,7 +17,8 @@ pub struct SlashConfig {
pub show_on_shutdown: bool, pub show_on_shutdown: bool,
pub show_on_sleep: bool, pub show_on_sleep: bool,
pub show_on_battery: bool, pub show_on_battery: bool,
pub show_battery_warning: bool pub show_battery_warning: bool,
pub show_on_lid_closed: bool,
} }
impl Default for SlashConfig { impl Default for SlashConfig {
@@ -32,7 +33,8 @@ impl Default for SlashConfig {
show_on_shutdown: true, show_on_shutdown: true,
show_on_sleep: true, show_on_sleep: true,
show_on_battery: true, show_on_battery: true,
show_battery_warning: true show_battery_warning: true,
show_on_lid_closed: true,
} }
} }
} }
@@ -58,7 +60,7 @@ impl From<&SlashConfig> for DeviceState {
slash_enabled: config.enabled, slash_enabled: config.enabled,
slash_brightness: config.brightness, slash_brightness: config.brightness,
slash_interval: config.display_interval, slash_interval: config.display_interval,
slash_mode: config.display_mode slash_mode: config.display_mode,
} }
} }
} }

View File

@@ -3,8 +3,7 @@ use std::sync::Arc;
use config::SlashConfig; use config::SlashConfig;
use rog_platform::hid_raw::HidRaw; use rog_platform::hid_raw::HidRaw;
use rog_platform::usb_raw::USBRaw; use rog_platform::usb_raw::USBRaw;
use rog_slash::usb::{get_options_packet, pkt_set_mode, pkts_for_init}; use rog_slash::usb::{slash_pkt_enable, slash_pkt_init, slash_pkt_options, slash_pkt_set_mode};
use rog_slash::SlashType;
use tokio::sync::{Mutex, MutexGuard}; use tokio::sync::{Mutex, MutexGuard};
use crate::error::RogError; use crate::error::RogError;
@@ -16,19 +15,19 @@ pub mod trait_impls;
pub struct Slash { pub struct Slash {
hid: Option<Arc<Mutex<HidRaw>>>, hid: Option<Arc<Mutex<HidRaw>>>,
usb: Option<Arc<Mutex<USBRaw>>>, usb: Option<Arc<Mutex<USBRaw>>>,
config: Arc<Mutex<SlashConfig>> config: Arc<Mutex<SlashConfig>>,
} }
impl Slash { impl Slash {
pub fn new( pub fn new(
hid: Option<Arc<Mutex<HidRaw>>>, hid: Option<Arc<Mutex<HidRaw>>>,
usb: Option<Arc<Mutex<USBRaw>>>, usb: Option<Arc<Mutex<USBRaw>>>,
config: Arc<Mutex<SlashConfig>> config: Arc<Mutex<SlashConfig>>,
) -> Self { ) -> Self {
Self { hid, usb, config } Self { hid, usb, config }
} }
pub async fn lock_config(&self) -> MutexGuard<SlashConfig> { pub async fn lock_config(&self) -> MutexGuard<'_, SlashConfig> {
self.config.lock().await self.config.lock().await
} }
@@ -46,22 +45,22 @@ impl Slash {
pub async fn do_initialization(&self) -> Result<(), RogError> { pub async fn do_initialization(&self) -> Result<(), RogError> {
// Don't try to initialise these models as the asus drivers already did // Don't try to initialise these models as the asus drivers already did
let config = self.config.lock().await; let config = self.config.lock().await;
if !matches!(config.slash_type, SlashType::GA605 | SlashType::GU605) { for pkt in &slash_pkt_init(config.slash_type) {
for pkt in &pkts_for_init(config.slash_type) {
self.write_bytes(pkt).await?; self.write_bytes(pkt).await?;
} }
} self.write_bytes(&slash_pkt_enable(config.slash_type, config.enabled))
.await?;
// Apply config upon initialization // Apply config upon initialization
let option_packets = get_options_packet( let option_packets = slash_pkt_options(
config.slash_type, config.slash_type,
config.enabled, config.enabled,
config.brightness, config.brightness,
config.display_interval config.display_interval,
); );
self.write_bytes(&option_packets).await?; self.write_bytes(&option_packets).await?;
let mode_packets = pkt_set_mode(config.slash_type, config.display_mode); let mode_packets = slash_pkt_set_mode(config.slash_type, config.display_mode);
// self.node.write_bytes(&mode_packets[0])?; // self.node.write_bytes(&mode_packets[0])?;
self.write_bytes(&mode_packets[1]).await?; self.write_bytes(&mode_packets[1]).await?;

View File

@@ -1,8 +1,9 @@
use config_traits::StdConfig; use config_traits::StdConfig;
use log::{debug, error, warn}; use log::{debug, error, warn};
use rog_slash::usb::{ use rog_slash::usb::{
get_battery_saver_packet, get_boot_packet, get_low_battery_packet, get_options_packet, slash_pkt_battery_saver, slash_pkt_boot, slash_pkt_enable, slash_pkt_lid_closed,
get_shutdown_packet, get_sleep_packet, pkt_save, pkt_set_mode slash_pkt_low_battery, slash_pkt_options, slash_pkt_save, slash_pkt_set_mode,
slash_pkt_shutdown, slash_pkt_sleep,
}; };
use rog_slash::{DeviceState, SlashMode}; use rog_slash::{DeviceState, SlashMode};
use zbus::zvariant::OwnedObjectPath; use zbus::zvariant::OwnedObjectPath;
@@ -23,7 +24,7 @@ impl SlashZbus {
pub async fn start_tasks( pub async fn start_tasks(
mut self, mut self,
connection: &Connection, connection: &Connection,
path: OwnedObjectPath path: OwnedObjectPath,
) -> Result<(), RogError> { ) -> Result<(), RogError> {
// let task = zbus.clone(); // let task = zbus.clone();
self.reload() self.reload()
@@ -58,11 +59,18 @@ impl SlashZbus {
config.brightness config.brightness
}; };
self.0 self.0
.write_bytes(&get_options_packet( .write_bytes(&slash_pkt_enable(config.slash_type, enabled))
.await
.map_err(|err| {
warn!("ctrl_slash::enable {}", err);
})
.ok();
self.0
.write_bytes(&slash_pkt_options(
config.slash_type, config.slash_type,
enabled, enabled,
brightness, brightness,
config.display_interval config.display_interval,
)) ))
.await .await
.map_err(|err| { .map_err(|err| {
@@ -88,11 +96,11 @@ impl SlashZbus {
let mut config = self.0.lock_config().await; let mut config = self.0.lock_config().await;
let enabled = brightness > 0; let enabled = brightness > 0;
self.0 self.0
.write_bytes(&get_options_packet( .write_bytes(&slash_pkt_options(
config.slash_type, config.slash_type,
enabled, enabled,
brightness, brightness,
config.display_interval config.display_interval,
)) ))
.await .await
.map_err(|err| { .map_err(|err| {
@@ -116,8 +124,8 @@ impl SlashZbus {
async fn set_interval(&self, interval: u8) { async fn set_interval(&self, interval: u8) {
let mut config = self.0.lock_config().await; let mut config = self.0.lock_config().await;
self.0 self.0
.write_bytes(&get_options_packet( .write_bytes(&slash_pkt_options(
config.slash_type, config.enabled, config.brightness, interval config.slash_type, config.enabled, config.brightness, interval,
)) ))
.await .await
.map_err(|err| { .map_err(|err| {
@@ -140,10 +148,12 @@ impl SlashZbus {
async fn set_mode(&self, mode: SlashMode) -> zbus::Result<()> { async fn set_mode(&self, mode: SlashMode) -> zbus::Result<()> {
let mut config = self.0.lock_config().await; let mut config = self.0.lock_config().await;
let command_packets = pkt_set_mode(config.slash_type, mode); let command_packets = slash_pkt_set_mode(config.slash_type, mode);
// self.node.write_bytes(&command_packets[0])?; // self.node.write_bytes(&command_packets[0])?;
self.0.write_bytes(&command_packets[1]).await?; self.0.write_bytes(&command_packets[1]).await?;
self.0.write_bytes(&pkt_save(config.slash_type)).await?; self.0
.write_bytes(&slash_pkt_save(config.slash_type))
.await?;
config.display_mode = mode; config.display_mode = mode;
config.write(); config.write();
@@ -167,7 +177,7 @@ impl SlashZbus {
async fn set_show_on_boot(&self, enable: bool) -> zbus::Result<()> { async fn set_show_on_boot(&self, enable: bool) -> zbus::Result<()> {
let mut config = self.0.lock_config().await; let mut config = self.0.lock_config().await;
self.0 self.0
.write_bytes(&get_boot_packet(config.slash_type, enable)) .write_bytes(&slash_pkt_boot(config.slash_type, enable))
.await?; .await?;
config.show_on_boot = enable; config.show_on_boot = enable;
config.write(); config.write();
@@ -184,7 +194,7 @@ impl SlashZbus {
async fn set_show_on_sleep(&self, enable: bool) -> zbus::Result<()> { async fn set_show_on_sleep(&self, enable: bool) -> zbus::Result<()> {
let mut config = self.0.lock_config().await; let mut config = self.0.lock_config().await;
self.0 self.0
.write_bytes(&get_sleep_packet(config.slash_type, enable)) .write_bytes(&slash_pkt_sleep(config.slash_type, enable))
.await?; .await?;
config.show_on_sleep = enable; config.show_on_sleep = enable;
config.write(); config.write();
@@ -201,7 +211,7 @@ impl SlashZbus {
async fn set_show_on_shutdown(&self, enable: bool) -> zbus::Result<()> { async fn set_show_on_shutdown(&self, enable: bool) -> zbus::Result<()> {
let mut config = self.0.lock_config().await; let mut config = self.0.lock_config().await;
self.0 self.0
.write_bytes(&get_shutdown_packet(config.slash_type, enable)) .write_bytes(&slash_pkt_shutdown(config.slash_type, enable))
.await?; .await?;
config.show_on_shutdown = enable; config.show_on_shutdown = enable;
config.write(); config.write();
@@ -218,7 +228,7 @@ impl SlashZbus {
async fn set_show_on_battery(&self, enable: bool) -> zbus::Result<()> { async fn set_show_on_battery(&self, enable: bool) -> zbus::Result<()> {
let mut config = self.0.lock_config().await; let mut config = self.0.lock_config().await;
self.0 self.0
.write_bytes(&get_battery_saver_packet(config.slash_type, enable)) .write_bytes(&slash_pkt_battery_saver(config.slash_type, enable))
.await?; .await?;
config.show_on_battery = enable; config.show_on_battery = enable;
config.write(); config.write();
@@ -235,12 +245,32 @@ impl SlashZbus {
async fn set_show_battery_warning(&self, enable: bool) -> zbus::Result<()> { async fn set_show_battery_warning(&self, enable: bool) -> zbus::Result<()> {
let mut config = self.0.lock_config().await; let mut config = self.0.lock_config().await;
self.0 self.0
.write_bytes(&get_low_battery_packet(config.slash_type, enable)) .write_bytes(&slash_pkt_low_battery(config.slash_type, enable))
.await?; .await?;
config.show_battery_warning = enable; config.show_battery_warning = enable;
config.write(); config.write();
Ok(()) Ok(())
} }
#[zbus(property)]
async fn show_on_lid_closed(&self) -> zbus::fdo::Result<bool> {
let config = self.0.lock_config().await;
Ok(config.show_on_lid_closed)
}
#[zbus(property)]
async fn set_show_on_lid_closed(&self, enable: bool) -> zbus::Result<()> {
let mut config = self.0.lock_config().await;
self.0
.write_bytes(&slash_pkt_lid_closed(config.slash_type, enable))
.await?;
self.0
.write_bytes(&slash_pkt_save(config.slash_type))
.await?;
config.show_on_lid_closed = enable;
config.write();
Ok(())
}
} }
impl Reloadable for SlashZbus { impl Reloadable for SlashZbus {
@@ -248,11 +278,11 @@ impl Reloadable for SlashZbus {
debug!("reloading slash settings"); debug!("reloading slash settings");
let config = self.0.lock_config().await; let config = self.0.lock_config().await;
self.0 self.0
.write_bytes(&get_options_packet( .write_bytes(&slash_pkt_options(
config.slash_type, config.slash_type,
config.enabled, config.enabled,
config.brightness, config.brightness,
config.display_interval config.display_interval,
)) ))
.await .await
.map_err(|err| { .map_err(|err| {
@@ -272,12 +302,12 @@ impl Reloadable for SlashZbus {
}; };
} }
write_bytes_with_warning!(get_boot_packet, show_on_boot, "show_on_boot"); write_bytes_with_warning!(slash_pkt_boot, show_on_boot, "show_on_boot");
write_bytes_with_warning!(get_sleep_packet, show_on_sleep, "show_on_sleep"); write_bytes_with_warning!(slash_pkt_sleep, show_on_sleep, "show_on_sleep");
write_bytes_with_warning!(get_shutdown_packet, show_on_shutdown, "show_on_shutdown"); write_bytes_with_warning!(slash_pkt_shutdown, show_on_shutdown, "show_on_shutdown");
write_bytes_with_warning!(get_battery_saver_packet, show_on_battery, "show_on_battery"); write_bytes_with_warning!(slash_pkt_battery_saver, show_on_battery, "show_on_battery");
write_bytes_with_warning!( write_bytes_with_warning!(
get_low_battery_packet, slash_pkt_low_battery,
show_battery_warning, show_battery_warning,
"show_battery_warning" "show_battery_warning"
); );

View File

@@ -31,7 +31,7 @@ pub enum _DeviceHandle {
LedClass(KeyboardBacklight), LedClass(KeyboardBacklight),
/// TODO /// TODO
MulticolourLed, MulticolourLed,
None None,
} }
#[derive(Clone)] #[derive(Clone)]
@@ -47,14 +47,14 @@ pub enum DeviceHandle {
TufLedClass(Arc<Mutex<HidRaw>>), TufLedClass(Arc<Mutex<HidRaw>>),
/// TODO /// TODO
MulticolourLed, MulticolourLed,
None None,
} }
impl DeviceHandle { impl DeviceHandle {
/// Try Slash HID. If one exists it is initialsed and returned. /// Try Slash HID. If one exists it is initialsed and returned.
pub async fn new_slash_hid( pub async fn new_slash_hid(
device: Arc<Mutex<HidRaw>>, device: Arc<Mutex<HidRaw>>,
prod_id: &str prod_id: &str,
) -> Result<Self, RogError> { ) -> Result<Self, RogError> {
debug!("Testing for HIDRAW Slash"); debug!("Testing for HIDRAW Slash");
let slash_type = SlashType::from_dmi(); let slash_type = SlashType::from_dmi();
@@ -93,7 +93,7 @@ impl DeviceHandle {
let slash = Slash::new( let slash = Slash::new(
None, None,
Some(Arc::new(Mutex::new(usb))), Some(Arc::new(Mutex::new(usb))),
Arc::new(Mutex::new(config)) Arc::new(Mutex::new(config)),
); );
slash.do_initialization().await?; slash.do_initialization().await?;
Ok(Self::Slash(slash)) Ok(Self::Slash(slash))
@@ -105,11 +105,11 @@ impl DeviceHandle {
/// Try AniMe Matrix HID. If one exists it is initialsed and returned. /// Try AniMe Matrix HID. If one exists it is initialsed and returned.
pub async fn maybe_anime_hid( pub async fn maybe_anime_hid(
_device: Arc<Mutex<HidRaw>>, _device: Arc<Mutex<HidRaw>>,
_prod_id: &str _prod_id: &str,
) -> Result<Self, RogError> { ) -> Result<Self, RogError> {
// TODO: can't use HIDRAW for anime at the moment // TODO: can't use HIDRAW for anime at the moment
Err(RogError::NotFound( Err(RogError::NotFound(
"Can't use anime over hidraw yet. Skip.".to_string() "Can't use anime over hidraw yet. Skip.".to_string(),
)) ))
// debug!("Testing for HIDRAW AniMe"); // debug!("Testing for HIDRAW AniMe");
@@ -144,13 +144,13 @@ impl DeviceHandle {
let mut anime = AniMe::new( let mut anime = AniMe::new(
None, None,
Some(Arc::new(Mutex::new(usb))), Some(Arc::new(Mutex::new(usb))),
Arc::new(Mutex::new(config)) Arc::new(Mutex::new(config)),
); );
anime.do_initialization().await?; anime.do_initialization().await?;
Ok(Self::AniMe(anime)) Ok(Self::AniMe(anime))
} else { } else {
Err(RogError::NotFound( Err(RogError::NotFound(
"No AnimeMatrix device found".to_string() "No AnimeMatrix device found".to_string(),
)) ))
} }
} }
@@ -174,7 +174,7 @@ impl DeviceHandle {
pub async fn maybe_laptop_aura( pub async fn maybe_laptop_aura(
device: Option<Arc<Mutex<HidRaw>>>, device: Option<Arc<Mutex<HidRaw>>>,
prod_id: &str prod_id: &str,
) -> Result<Self, RogError> { ) -> Result<Self, RogError> {
debug!("Testing for laptop aura"); debug!("Testing for laptop aura");
let aura_type = AuraDeviceType::from(prod_id); let aura_type = AuraDeviceType::from(prod_id);
@@ -201,7 +201,7 @@ impl DeviceHandle {
let aura = Aura { let aura = Aura {
hid: device, hid: device,
backlight, backlight,
config: Arc::new(Mutex::new(config)) config: Arc::new(Mutex::new(config)),
}; };
aura.do_initialization().await?; aura.do_initialization().await?;
Ok(Self::Aura(aura)) Ok(Self::Aura(aura))

View File

@@ -1,6 +1,6 @@
use std::collections::HashMap; use std::collections::HashMap;
use config_traits::{StdConfig, StdConfigLoad1}; use config_traits::{StdConfig, StdConfigLoad2};
use rog_platform::asus_armoury::FirmwareAttribute; use rog_platform::asus_armoury::FirmwareAttribute;
use rog_platform::cpu::CPUEPP; use rog_platform::cpu::CPUEPP;
use rog_platform::platform::PlatformProfile; use rog_platform::platform::PlatformProfile;
@@ -8,10 +8,16 @@ use serde::{Deserialize, Serialize};
const CONFIG_FILE: &str = "asusd.ron"; const CONFIG_FILE: &str = "asusd.ron";
/// Default value for base_charge_control_end_threshold when not present in config.
/// Returns 0 so restore_charge_limit() skips restoration for upgraded configs.
fn default_base_charge_limit() -> u8 {
0
}
#[derive(Default, Clone, Deserialize, Serialize, PartialEq)] #[derive(Default, Clone, Deserialize, Serialize, PartialEq)]
pub struct Tuning { pub struct Tuning {
pub enabled: bool, pub enabled: bool,
pub group: HashMap<FirmwareAttribute, i32> pub group: HashMap<FirmwareAttribute, i32>,
} }
type Tunings = HashMap<PlatformProfile, Tuning>; type Tunings = HashMap<PlatformProfile, Tuning>;
@@ -19,8 +25,8 @@ type Tunings = HashMap<PlatformProfile, Tuning>;
pub struct Config { pub struct Config {
// The current charge limit applied // The current charge limit applied
pub charge_control_end_threshold: u8, pub charge_control_end_threshold: u8,
/// Save charge limit for restoring /// Save charge limit for restoring after one-shot full charge
#[serde(skip)] #[serde(default = "default_base_charge_limit")]
pub base_charge_control_end_threshold: u8, pub base_charge_control_end_threshold: u8,
pub disable_nvidia_powerd_on_battery: bool, pub disable_nvidia_powerd_on_battery: bool,
/// An optional command/script to run when power is changed to AC /// An optional command/script to run when power is changed to AC
@@ -43,13 +49,19 @@ pub struct Config {
/// The energy_performance_preference for this platform profile /// The energy_performance_preference for this platform profile
pub profile_balanced_epp: CPUEPP, pub profile_balanced_epp: CPUEPP,
/// The energy_performance_preference for this platform profile /// The energy_performance_preference for this platform profile
pub profile_custom_epp: CPUEPP,
/// The energy_performance_preference for this platform profile
pub profile_performance_epp: CPUEPP, pub profile_performance_epp: CPUEPP,
pub ac_profile_tunings: Tunings, pub ac_profile_tunings: Tunings,
pub dc_profile_tunings: Tunings, pub dc_profile_tunings: Tunings,
pub armoury_settings: HashMap<FirmwareAttribute, i32>, pub armoury_settings: HashMap<FirmwareAttribute, i32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub screenpad_gamma: Option<f32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub screenpad_sync_primary: Option<bool>,
/// Temporary state for AC/Batt /// Temporary state for AC/Batt
#[serde(skip)] #[serde(skip)]
pub last_power_plugged: u8 pub last_power_plugged: u8,
} }
impl Config { impl Config {
@@ -61,12 +73,28 @@ impl Config {
}; };
config.entry(profile).or_insert_with(Tuning::default) config.entry(profile).or_insert_with(Tuning::default)
} }
pub fn select_tunings_ref(
&self,
power_plugged: bool,
profile: PlatformProfile,
) -> Option<&Tuning> {
let config = if power_plugged {
&self.ac_profile_tunings
} else {
&self.dc_profile_tunings
};
config.get(&profile)
}
} }
impl Default for Config { impl Default for Config {
fn default() -> Self { fn default() -> Self {
Self { Self {
charge_control_end_threshold: 100, charge_control_end_threshold: 100,
// NOTE: This is intentionally 100 (not 0 like the serde default).
// New installs get 100 (no limit). Upgraded configs missing this
// field get 0 via serde, which skips restore_charge_limit().
base_charge_control_end_threshold: 100, base_charge_control_end_threshold: 100,
disable_nvidia_powerd_on_battery: true, disable_nvidia_powerd_on_battery: true,
ac_command: Default::default(), ac_command: Default::default(),
@@ -79,10 +107,13 @@ impl Default for Config {
profile_quiet_epp: CPUEPP::Power, profile_quiet_epp: CPUEPP::Power,
profile_balanced_epp: CPUEPP::BalancePower, profile_balanced_epp: CPUEPP::BalancePower,
profile_performance_epp: CPUEPP::Performance, profile_performance_epp: CPUEPP::Performance,
profile_custom_epp: CPUEPP::Performance,
ac_profile_tunings: HashMap::default(), ac_profile_tunings: HashMap::default(),
dc_profile_tunings: HashMap::default(), dc_profile_tunings: HashMap::default(),
armoury_settings: HashMap::default(), armoury_settings: HashMap::default(),
last_power_plugged: Default::default() last_power_plugged: Default::default(),
screenpad_gamma: Default::default(),
screenpad_sync_primary: Default::default(),
} }
} }
} }
@@ -109,7 +140,64 @@ impl StdConfig for Config {
} }
} }
impl StdConfigLoad1<Config601> for Config {} impl StdConfigLoad2<Config611, Config601> for Config {}
#[derive(Deserialize, Serialize)]
pub struct Config611 {
pub charge_control_end_threshold: u8,
#[serde(skip)]
pub base_charge_control_end_threshold: u8,
pub disable_nvidia_powerd_on_battery: bool,
pub ac_command: String,
pub bat_command: String,
pub platform_profile_linked_epp: bool,
pub platform_profile_on_battery: PlatformProfile,
pub change_platform_profile_on_battery: bool,
pub platform_profile_on_ac: PlatformProfile,
pub change_platform_profile_on_ac: bool,
pub profile_quiet_epp: CPUEPP,
pub profile_balanced_epp: CPUEPP,
pub profile_custom_epp: CPUEPP,
pub profile_performance_epp: CPUEPP,
pub ac_profile_tunings: Tunings,
pub dc_profile_tunings: Tunings,
pub armoury_settings: HashMap<FirmwareAttribute, i32>,
#[serde(skip)]
pub last_power_plugged: u8,
}
impl From<Config611> for Config {
fn from(c: Config611) -> Self {
let mut config = Self {
// Restore the base charge limit
charge_control_end_threshold: c.charge_control_end_threshold,
base_charge_control_end_threshold: c.charge_control_end_threshold,
disable_nvidia_powerd_on_battery: c.disable_nvidia_powerd_on_battery,
ac_command: c.ac_command,
bat_command: c.bat_command,
platform_profile_linked_epp: c.platform_profile_linked_epp,
platform_profile_on_battery: c.platform_profile_on_battery,
change_platform_profile_on_battery: c.change_platform_profile_on_battery,
platform_profile_on_ac: c.platform_profile_on_ac,
change_platform_profile_on_ac: c.change_platform_profile_on_ac,
profile_quiet_epp: c.profile_quiet_epp,
profile_balanced_epp: c.profile_balanced_epp,
profile_performance_epp: c.profile_performance_epp,
profile_custom_epp: c.profile_performance_epp,
last_power_plugged: c.last_power_plugged,
ac_profile_tunings: HashMap::default(),
dc_profile_tunings: HashMap::default(),
armoury_settings: HashMap::default(),
screenpad_gamma: None,
screenpad_sync_primary: Default::default(),
};
config.ac_profile_tunings = c.ac_profile_tunings;
config.dc_profile_tunings = c.dc_profile_tunings;
config.armoury_settings = c.armoury_settings;
config
}
}
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize)]
pub struct Config601 { pub struct Config601 {
@@ -147,7 +235,7 @@ pub struct Config601 {
#[serde(skip_serializing_if = "Option::is_none", default)] #[serde(skip_serializing_if = "Option::is_none", default)]
pub nv_temp_target: Option<u8>, pub nv_temp_target: Option<u8>,
#[serde(skip)] #[serde(skip)]
pub last_power_plugged: u8 pub last_power_plugged: u8,
} }
impl From<Config601> for Config { impl From<Config601> for Config {
@@ -167,10 +255,13 @@ impl From<Config601> for Config {
profile_quiet_epp: c.profile_quiet_epp, profile_quiet_epp: c.profile_quiet_epp,
profile_balanced_epp: c.profile_balanced_epp, profile_balanced_epp: c.profile_balanced_epp,
profile_performance_epp: c.profile_performance_epp, profile_performance_epp: c.profile_performance_epp,
profile_custom_epp: c.profile_performance_epp,
last_power_plugged: c.last_power_plugged, last_power_plugged: c.last_power_plugged,
ac_profile_tunings: HashMap::default(), ac_profile_tunings: HashMap::default(),
dc_profile_tunings: HashMap::default(), dc_profile_tunings: HashMap::default(),
armoury_settings: HashMap::default() armoury_settings: HashMap::default(),
screenpad_gamma: None,
screenpad_sync_primary: Default::default(),
} }
} }
} }

348
asusd/src/ctrl_backlight.rs Normal file
View File

@@ -0,0 +1,348 @@
use std::sync::Arc;
use std::time::Duration;
use config_traits::StdConfig;
use log::{info, warn};
use rog_platform::backlight::{Backlight, BacklightType};
use tokio::sync::Mutex;
use zbus::fdo::Error as FdoErr;
use zbus::object_server::SignalEmitter;
use zbus::{interface, Connection};
use crate::config::Config;
use crate::error::RogError;
use crate::ASUS_ZBUS_PATH;
#[derive(Clone)]
pub struct CtrlBacklight {
backlights: Vec<Backlight>,
config: Arc<Mutex<Config>>,
}
impl CtrlBacklight {
pub fn new(config: Arc<Mutex<Config>>) -> Result<Self, RogError> {
let mut backlights = Vec::new();
if let Ok(primary) = Backlight::new(BacklightType::Primary) {
info!("Found primary display backlight");
backlights.push(primary);
}
if let Ok(screenpad) = Backlight::new(BacklightType::Screenpad) {
info!("Found screenpad backlight");
backlights.push(screenpad);
}
if backlights.is_empty() {
return Err(RogError::MissingFunction("No backlights found".into()));
}
Ok(Self { backlights, config })
}
fn get_backlight(&self, device_type: &BacklightType) -> Option<&Backlight> {
self.backlights
.iter()
.find(|b| b.device_type() == device_type)
}
async fn set_brightness_with_sync(
&self,
device_type: &BacklightType,
level: i32,
) -> Result<(), FdoErr> {
let sync = self
.config
.lock()
.await
.screenpad_sync_primary
.unwrap_or_default();
// If sync is enabled and we're setting screenpad brightness, set primary first
if sync && *device_type == BacklightType::Screenpad {
if let Some(primary) = self.get_backlight(&BacklightType::Primary) {
if let Ok(primary_max) = primary.get_max_brightness() {
let primary_scaled = level * primary_max / 100;
let _ = primary.set_brightness(primary_scaled);
}
}
}
if let Some(backlight) = self.get_backlight(device_type) {
let max = backlight.get_max_brightness().map_err(|e| {
warn!("Failed to get max brightness: {}", e);
FdoErr::Failed(format!("Failed to get max brightness: {}", e))
})?;
let gamma = self.config.lock().await.screenpad_gamma.unwrap_or(1.0);
let scaled = if *device_type == BacklightType::Screenpad {
// Apply non-linear scaling with the configurable gamma value only for Screenpad
let normalized_level = level as f32 / 100.0;
let gamma_corrected = normalized_level.powf(gamma);
(gamma_corrected * max as f32) as i32
} else {
// Linear scaling for other devices
level * max / 100
};
backlight.set_brightness(scaled).map_err(|e| {
warn!("Failed to set brightness: {}", e);
FdoErr::Failed(format!("Failed to set brightness: {}", e))
})?;
// If sync is enabled and we're setting primary brightness, set screenpad
// afterward
if sync && *device_type == BacklightType::Primary {
for other in self
.backlights
.iter()
.filter(|b| b.device_type() != device_type)
{
if let Ok(other_max) = other.get_max_brightness() {
let other_scaled = if other.device_type() == &BacklightType::Screenpad {
// Apply gamma only to Screenpad
let normalized_level = level as f32 / 100.0;
let gamma_corrected = normalized_level.powf(gamma);
(gamma_corrected * other_max as f32) as i32
} else {
// Linear scaling for other devices
level * other_max / 100
};
let _ = other.set_brightness(other_scaled);
}
}
}
Ok(())
} else {
Err(FdoErr::NotSupported(format!(
"Backlight {:?} not found",
device_type
)))
}
}
async fn get_brightness_percent(&self, device_type: &BacklightType) -> Result<i32, FdoErr> {
if let Some(backlight) = self.get_backlight(device_type) {
let brightness = backlight.get_brightness().map_err(|e| {
warn!("Failed to get brightness: {}", e);
FdoErr::Failed(format!("Failed to get brightness: {}", e))
})?;
let max = backlight.get_max_brightness().map_err(|e| {
warn!("Failed to get max brightness: {}", e);
FdoErr::Failed(format!("Failed to get max brightness: {}", e))
})?;
if *device_type == BacklightType::Screenpad {
let gamma = self.config.lock().await.screenpad_gamma.unwrap_or(1.0);
let normalized = brightness as f32 / max as f32;
let corrected = normalized.powf(1.0 / gamma);
Ok((corrected * 100.0).round() as i32)
} else {
Ok(brightness * 100 / max)
}
} else {
Err(FdoErr::NotSupported(format!(
"Backlight {:?} not found",
device_type
)))
}
}
pub async fn start_watch_primary(&self) -> Result<(), RogError> {
if self.get_backlight(&BacklightType::Screenpad).is_none() {
return Ok(());
}
if let Some(sync) = self.config.lock().await.screenpad_sync_primary {
if !sync {
return Ok(());
}
}
if let Some(backlight) = self.get_backlight(&BacklightType::Primary) {
let watch = backlight.monitor_brightness()?;
let backlights = self.clone();
tokio::spawn(async move {
let mut last_level = 0;
let mut buffer = [0; 32];
use futures_lite::StreamExt;
if let Ok(mut stream) = watch.into_event_stream(&mut buffer) {
loop {
let _ = stream.next().await;
let sync = backlights.config.lock().await.screenpad_sync_primary;
if let Some(sync) = sync {
if !sync {
continue;
}
} else if backlights
.config
.lock()
.await
.screenpad_sync_primary
.is_none()
{
continue;
}
let level = backlights
.get_brightness_percent(&BacklightType::Primary)
.await
.unwrap_or(60);
if last_level != level {
last_level = level;
backlights
.set_brightness_with_sync(&BacklightType::Screenpad, level)
.await
.ok();
}
// other processes cause "MODIFY" event and make this spin 100%, so sleep
tokio::time::sleep(Duration::from_millis(300)).await;
}
// watch
// .into_event_stream(&mut buffer)
// .unwrap()
// .for_each(|_| async {})
// .await;
}
});
}
Ok(())
}
}
#[interface(name = "xyz.ljones.Backlight")]
impl CtrlBacklight {
#[zbus(property)]
async fn screenpad_sync_with_primary(&self) -> bool {
self.config
.lock()
.await
.screenpad_sync_primary
.unwrap_or_default()
}
#[zbus(property)]
async fn set_screenpad_sync_with_primary(&self, sync: bool) -> Result<(), zbus::Error> {
self.config.lock().await.screenpad_sync_primary = Some(sync);
self.config.lock().await.write();
Ok(())
}
#[zbus(property)]
async fn screenpad_gamma(&self) -> String {
(self.config.lock().await.screenpad_gamma.unwrap_or(1.0)).to_string()
}
#[zbus(property)]
async fn set_screenpad_gamma(&self, value: &str) -> Result<(), zbus::Error> {
let gamma: f32 = value
.parse()
.map_err(|_| FdoErr::Failed("Invalid gamma value, must be a valid number".into()))?;
if gamma < 0.1 {
return Err(FdoErr::Failed("Gamma value must be greater than 0".into()).into());
}
if gamma > 2.0 {
return Err(FdoErr::Failed("Gamma value must be 2.0 or less".into()).into());
}
self.config.lock().await.screenpad_gamma = Some(gamma);
self.config.lock().await.write();
Ok(())
}
#[zbus(property)]
async fn primary_brightness(&self) -> Result<i32, FdoErr> {
self.get_brightness_percent(&BacklightType::Primary).await
}
#[zbus(property)]
async fn set_primary_brightness(
&self,
#[zbus(signal_context)] ctxt: SignalEmitter<'_>,
level: i32,
) -> Result<(), zbus::Error> {
if level > 100 {
return Err(FdoErr::Failed("Brightness level must be 0-100".into()).into());
}
self.set_brightness_with_sync(&BacklightType::Primary, level)
.await?;
self.primary_brightness_changed(&ctxt).await?;
Ok(())
}
#[zbus(property)]
async fn screenpad_brightness(&self) -> Result<i32, FdoErr> {
self.get_brightness_percent(&BacklightType::Screenpad).await
}
#[zbus(property)]
async fn set_screenpad_brightness(
&self,
// #[zbus(signal_context)] ctxt: SignalEmitter<'_>,
level: i32,
) -> Result<(), zbus::Error> {
if level > 100 {
return Err(FdoErr::Failed("Brightness level must be 0-100".into()).into());
}
self.set_brightness_with_sync(&BacklightType::Screenpad, level)
.await?;
// self.screenpad_brightness_changed(&ctxt).await?;
Ok(())
}
#[zbus(property)]
async fn screenpad_power(&self) -> Result<bool, FdoErr> {
if let Some(backlight) = self.get_backlight(&BacklightType::Screenpad) {
let power = backlight.get_bl_power().map_err(|e| {
warn!("Failed to get backlight power: {}", e);
FdoErr::Failed(format!("Failed to get backlight power: {}", e))
})?;
Ok(power == 0)
} else {
Err(FdoErr::NotSupported("Screenpad backlight not found".into()))
}
}
#[zbus(property)]
async fn set_screenpad_power(
&self,
#[zbus(signal_context)] ctxt: SignalEmitter<'_>,
power: bool,
) -> Result<(), zbus::Error> {
if let Some(backlight) = self.get_backlight(&BacklightType::Screenpad) {
backlight
.set_bl_power(if power { 0 } else { 1 })
.map_err(|e| {
warn!("Failed to set backlight power: {}", e);
FdoErr::Failed(format!("Failed to set backlight power: {}", e))
})?;
self.screenpad_power_changed(&ctxt).await?;
Ok(())
} else {
Err(FdoErr::NotSupported("Screenpad backlight not found".into()).into())
}
}
}
impl crate::ZbusRun for CtrlBacklight {
async fn add_to_server(self, server: &mut Connection) {
Self::add_to_server_helper(self, ASUS_ZBUS_PATH, server).await;
}
}
impl crate::Reloadable for CtrlBacklight {
async fn reload(&mut self) -> Result<(), RogError> {
info!("Reloading backlight settings");
Ok(())
}
}

View File

@@ -23,7 +23,7 @@ pub const FAN_CURVE_ZBUS_PATH: &str = "/xyz/ljones";
pub struct FanCurveConfig { pub struct FanCurveConfig {
pub profiles: FanCurveProfiles, pub profiles: FanCurveProfiles,
#[serde(skip)] #[serde(skip)]
pub current: PlatformProfile pub current: PlatformProfile,
} }
impl StdConfig for FanCurveConfig { impl StdConfig for FanCurveConfig {
@@ -47,7 +47,7 @@ impl StdConfigLoad for FanCurveConfig {}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct CtrlFanCurveZbus { pub struct CtrlFanCurveZbus {
config: Arc<Mutex<FanCurveConfig>>, config: Arc<Mutex<FanCurveConfig>>,
platform: RogPlatform platform: RogPlatform,
} }
// Non-zbus-derive impl // Non-zbus-derive impl
@@ -66,11 +66,8 @@ impl CtrlFanCurveZbus {
info!("Fetching default fan curves"); info!("Fetching default fan curves");
let current = platform.get_platform_profile()?; let current = platform.get_platform_profile()?;
for this in [ let profiles = platform.get_platform_profile_choices()?;
PlatformProfile::Balanced, for this in profiles {
PlatformProfile::Performance,
PlatformProfile::Quiet
] {
// For each profile we need to switch to it before we // For each profile we need to switch to it before we
// can read the existing values from hardware. The ACPI method used // can read the existing values from hardware. The ACPI method used
// for this is what limits us. // for this is what limits us.
@@ -93,7 +90,7 @@ impl CtrlFanCurveZbus {
return Ok(Self { return Ok(Self {
config: Arc::new(Mutex::new(config)), config: Arc::new(Mutex::new(config)),
platform platform,
}); });
} }
@@ -108,7 +105,7 @@ impl CtrlFanCurveZbus {
async fn set_fan_curves_enabled( async fn set_fan_curves_enabled(
&mut self, &mut self,
profile: PlatformProfile, profile: PlatformProfile,
enabled: bool enabled: bool,
) -> zbus::fdo::Result<()> { ) -> zbus::fdo::Result<()> {
self.config self.config
.lock() .lock()
@@ -130,7 +127,7 @@ impl CtrlFanCurveZbus {
&mut self, &mut self,
profile: PlatformProfile, profile: PlatformProfile,
fan: FanCurvePU, fan: FanCurvePU,
enabled: bool enabled: bool,
) -> zbus::fdo::Result<()> { ) -> zbus::fdo::Result<()> {
self.config self.config
.lock() .lock()
@@ -149,7 +146,7 @@ impl CtrlFanCurveZbus {
/// Get the fan-curve data for the currently active ThrottlePolicy /// Get the fan-curve data for the currently active ThrottlePolicy
async fn fan_curve_data( async fn fan_curve_data(
&mut self, &mut self,
profile: PlatformProfile profile: PlatformProfile,
) -> zbus::fdo::Result<Vec<CurveData>> { ) -> zbus::fdo::Result<Vec<CurveData>> {
let curve = self let curve = self
.config .config
@@ -166,7 +163,7 @@ impl CtrlFanCurveZbus {
async fn set_fan_curve( async fn set_fan_curve(
&mut self, &mut self,
profile: PlatformProfile, profile: PlatformProfile,
curve: CurveData curve: CurveData,
) -> zbus::fdo::Result<()> { ) -> zbus::fdo::Result<()> {
self.config self.config
.lock() .lock()
@@ -216,7 +213,7 @@ impl CtrlFanCurveZbus {
.lock() .lock()
.await .await
.profiles .profiles
.set_active_curve_to_defaults((&active).into(), &mut find_fan_curve_node()?)?; .set_active_curve_to_defaults(active.as_str().into(), &mut find_fan_curve_node()?)?;
self.platform.set_platform_profile(active.as_str())?; self.platform.set_platform_profile(active.as_str())?;
self.config.lock().await.write(); self.config.lock().await.write();
@@ -261,7 +258,7 @@ impl CtrlTask for CtrlFanCurveZbus {
.profiles .profiles
.write_profile_curve_to_platform( .write_profile_curve_to_platform(
profile, profile,
&mut find_fan_curve_node().unwrap() &mut find_fan_curve_node().unwrap(),
) )
.map_err(|e| warn!("write_profile_curve_to_platform, {}", e)) .map_err(|e| warn!("write_profile_curve_to_platform, {}", e))
.ok(); .ok();

View File

@@ -8,12 +8,12 @@ use rog_platform::asus_armoury::{AttrValue, FirmwareAttribute, FirmwareAttribute
use rog_platform::cpu::{CPUControl, CPUGovernor, CPUEPP}; use rog_platform::cpu::{CPUControl, CPUGovernor, CPUEPP};
use rog_platform::platform::{PlatformProfile, Properties, RogPlatform}; use rog_platform::platform::{PlatformProfile, Properties, RogPlatform};
use rog_platform::power::AsusPower; use rog_platform::power::AsusPower;
use zbus::export::futures_util::lock::Mutex; use tokio::sync::Mutex;
use zbus::fdo::Error as FdoErr; use zbus::fdo::Error as FdoErr;
use zbus::object_server::SignalEmitter; use zbus::object_server::SignalEmitter;
use zbus::{interface, Connection}; use zbus::{interface, Connection};
use crate::asus_armoury::set_config_or_default; use crate::asus_armoury::{set_config_or_default, ArmouryAttributeRegistry};
use crate::config::Config; use crate::config::Config;
use crate::error::RogError; use crate::error::RogError;
use crate::{task_watch_item, CtrlTask, ReloadAndNotify}; use crate::{task_watch_item, CtrlTask, ReloadAndNotify};
@@ -45,17 +45,22 @@ pub struct CtrlPlatform {
platform: RogPlatform, platform: RogPlatform,
attributes: FirmwareAttributes, attributes: FirmwareAttributes,
cpu_control: Option<CPUControl>, cpu_control: Option<CPUControl>,
config: Arc<Mutex<Config>> config: Arc<Mutex<Config>>,
connection: Connection,
armoury_registry: ArmouryAttributeRegistry,
} }
impl CtrlPlatform { impl CtrlPlatform {
#[allow(clippy::too_many_arguments)]
pub fn new( pub fn new(
platform: RogPlatform, platform: RogPlatform,
power: AsusPower, power: AsusPower,
attributes: FirmwareAttributes, attributes: FirmwareAttributes,
config: Arc<Mutex<Config>>, config: Arc<Mutex<Config>>,
config_path: &Path, config_path: &Path,
signal_context: SignalEmitter<'static> signal_context: SignalEmitter<'static>,
connection: Connection,
armoury_registry: ArmouryAttributeRegistry,
) -> Result<Self, RogError> { ) -> Result<Self, RogError> {
let config1 = config.clone(); let config1 = config.clone();
let config_path = config_path.to_owned(); let config_path = config_path.to_owned();
@@ -67,12 +72,14 @@ impl CtrlPlatform {
config, config,
cpu_control: CPUControl::new() cpu_control: CPUControl::new()
.map_err(|e| error!("Couldn't get CPU control sysfs: {e}")) .map_err(|e| error!("Couldn't get CPU control sysfs: {e}"))
.ok() .ok(),
connection,
armoury_registry,
}; };
let mut inotify_self = ret_self.clone(); let mut inotify_self = ret_self.clone();
tokio::spawn(async move { tokio::spawn(async move {
use zbus::export::futures_util::StreamExt; use futures_util::StreamExt;
info!("Starting inotify watch for asusd config file"); info!("Starting inotify watch for asusd config file");
let mut buffer = [0; 32]; let mut buffer = [0; 32];
@@ -86,7 +93,7 @@ impl CtrlPlatform {
inotify::WatchMask::MODIFY inotify::WatchMask::MODIFY
| inotify::WatchMask::CLOSE_WRITE | inotify::WatchMask::CLOSE_WRITE
| inotify::WatchMask::ATTRIB | inotify::WatchMask::ATTRIB
| inotify::WatchMask::CREATE | inotify::WatchMask::CREATE,
) )
.inspect_err(|e| { .inspect_err(|e| {
if e.kind() == std::io::ErrorKind::NotFound { if e.kind() == std::io::ErrorKind::NotFound {
@@ -128,7 +135,7 @@ impl CtrlPlatform {
if limit > 0 if limit > 0
&& std::mem::replace( && std::mem::replace(
&mut self.config.lock().await.charge_control_end_threshold, &mut self.config.lock().await.charge_control_end_threshold,
limit limit,
) != limit ) != limit
{ {
self.power self.power
@@ -161,7 +168,7 @@ impl CtrlPlatform {
.map(|s| s.to_string()) .map(|s| s.to_string())
.collect() .collect()
}; };
if prog.len() > 1 { if (!prog.is_empty()) && (!prog[0].is_empty()) {
let mut cmd = Command::new(&prog[0]); let mut cmd = Command::new(&prog[0]);
for arg in prog.iter().skip(1) { for arg in prog.iter().skip(1) {
cmd.arg(arg); cmd.arg(arg);
@@ -210,7 +217,9 @@ impl CtrlPlatform {
match throttle { match throttle {
PlatformProfile::Balanced => self.config.lock().await.profile_balanced_epp, PlatformProfile::Balanced => self.config.lock().await.profile_balanced_epp,
PlatformProfile::Performance => self.config.lock().await.profile_performance_epp, PlatformProfile::Performance => self.config.lock().await.profile_performance_epp,
PlatformProfile::Quiet => self.config.lock().await.profile_quiet_epp PlatformProfile::Quiet => self.config.lock().await.profile_quiet_epp,
PlatformProfile::LowPower => self.config.lock().await.profile_quiet_epp,
PlatformProfile::Custom => self.config.lock().await.profile_custom_epp,
} }
} }
@@ -286,16 +295,39 @@ impl CtrlPlatform {
#[zbus(property)] #[zbus(property)]
fn charge_control_end_threshold(&self) -> Result<u8, FdoErr> { fn charge_control_end_threshold(&self) -> Result<u8, FdoErr> {
let limit = self.power.get_charge_control_end_threshold()?; if !self.power.has_charge_control_end_threshold() {
return Err(FdoErr::NotSupported(
"RogPlatform: charge_control_end_threshold not supported".to_owned(),
));
}
let limit = self.power.get_charge_control_end_threshold().map_err(|e| {
FdoErr::Failed(format!(
"Could not read charge_control_end_threshold: {e:?}"
))
})?;
Ok(limit) Ok(limit)
} }
#[zbus(property)] #[zbus(property)]
async fn set_charge_control_end_threshold(&mut self, limit: u8) -> Result<(), FdoErr> { async fn set_charge_control_end_threshold(&mut self, limit: u8) -> Result<(), FdoErr> {
if !self.power.has_charge_control_end_threshold() {
return Err(FdoErr::NotSupported(
"RogPlatform: charge_control_end_threshold not supported".to_owned(),
));
}
if !(20..=100).contains(&limit) { if !(20..=100).contains(&limit) {
return Err(RogError::ChargeLimit(limit))?; return Err(RogError::ChargeLimit(limit))?;
} }
self.power.set_charge_control_end_threshold(limit)?;
self.power
.set_charge_control_end_threshold(limit)
.map_err(|e| {
FdoErr::Failed(format!("Could not set charge_control_end_threshold: {e:?}"))
})?;
self.config.lock().await.charge_control_end_threshold = limit; self.config.lock().await.charge_control_end_threshold = limit;
self.config.lock().await.base_charge_control_end_threshold = limit; self.config.lock().await.base_charge_control_end_threshold = limit;
self.config.lock().await.write(); self.config.lock().await.write();
@@ -303,12 +335,22 @@ impl CtrlPlatform {
} }
async fn one_shot_full_charge(&self) -> Result<(), FdoErr> { async fn one_shot_full_charge(&self) -> Result<(), FdoErr> {
if !self.power.has_charge_control_end_threshold() {
return Err(FdoErr::NotSupported(
"RogPlatform: charge_control_end_threshold not supported".to_owned(),
));
}
let base_limit = std::mem::replace( let base_limit = std::mem::replace(
&mut self.config.lock().await.charge_control_end_threshold, &mut self.config.lock().await.charge_control_end_threshold,
100 100,
); );
if base_limit != 100 { if base_limit != 100 {
self.power.set_charge_control_end_threshold(100)?; self.power
.set_charge_control_end_threshold(100)
.map_err(|e| {
FdoErr::Failed(format!("Could not set one_shot_full_charge: {e:?}"))
})?;
self.config.lock().await.base_charge_control_end_threshold = base_limit; self.config.lock().await.base_charge_control_end_threshold = base_limit;
self.config.lock().await.write(); self.config.lock().await.write();
} }
@@ -319,11 +361,13 @@ impl CtrlPlatform {
/// If fan-curves are supported will also activate a fan curve for profile. /// If fan-curves are supported will also activate a fan curve for profile.
async fn next_platform_profile( async fn next_platform_profile(
&mut self, &mut self,
#[zbus(signal_context)] ctxt: SignalEmitter<'_> #[zbus(signal_context)] ctxt: SignalEmitter<'_>,
) -> Result<(), FdoErr> { ) -> Result<(), FdoErr> {
let policy: PlatformProfile = let policy: PlatformProfile =
platform_get_value!(self, platform_profile, "platform_profile").map(|n| n.into())?; platform_get_value!(self, platform_profile, "platform_profile").map(|n| n.into())?;
let policy = PlatformProfile::next(policy); let choices =
platform_get_value!(self, platform_profile_choices, "platform_profile_choices")?;
let policy = PlatformProfile::next(policy, &choices);
if self.platform.has_platform_profile() { if self.platform.has_platform_profile() {
let change_epp = self.config.lock().await.platform_profile_linked_epp; let change_epp = self.config.lock().await.platform_profile_linked_epp;
@@ -339,21 +383,27 @@ impl CtrlPlatform {
Ok(self.platform_profile_changed(&ctxt).await?) Ok(self.platform_profile_changed(&ctxt).await?)
} else { } else {
Err(FdoErr::NotSupported( Err(FdoErr::NotSupported(
"RogPlatform: platform_profile not supported".to_owned() "RogPlatform: platform_profile not supported".to_owned(),
)) ))
} }
} }
#[zbus(property)]
fn platform_profile_choices(&self) -> Result<Vec<PlatformProfile>, FdoErr> {
platform_get_value!(self, platform_profile_choices, "platform_profile_choices")
}
#[zbus(property)] #[zbus(property)]
fn platform_profile(&self) -> Result<PlatformProfile, FdoErr> { fn platform_profile(&self) -> Result<PlatformProfile, FdoErr> {
platform_get_value!(self, platform_profile, "platform_profile").map(|n| n.into()) let policy: PlatformProfile = self.platform.get_platform_profile()?.as_str().into();
Ok(policy)
} }
#[zbus(property)] #[zbus(property)]
async fn set_platform_profile( async fn set_platform_profile(
&mut self, &mut self,
#[zbus(signal_context)] ctxt: SignalEmitter<'_>, #[zbus(signal_context)] ctxt: SignalEmitter<'_>,
policy: PlatformProfile policy: PlatformProfile,
) -> Result<(), FdoErr> { ) -> Result<(), FdoErr> {
// TODO: watch for external changes // TODO: watch for external changes
if self.platform.has_platform_profile() { if self.platform.has_platform_profile() {
@@ -362,7 +412,15 @@ impl CtrlPlatform {
self.check_and_set_epp(epp, change_epp); self.check_and_set_epp(epp, change_epp);
self.config.lock().await.write(); self.config.lock().await.write();
// TODO: Need to get supported profiles here and ensure we translate to one
let choices = self.platform.get_platform_profile_choices()?;
if !choices.contains(&policy) {
return Err(FdoErr::NotSupported(format!(
"RogPlatform: platform_profile: {} not supported",
policy
)));
}
self.platform self.platform
.set_platform_profile(policy.into()) .set_platform_profile(policy.into())
.map_err(|err| { .map_err(|err| {
@@ -373,7 +431,7 @@ impl CtrlPlatform {
Ok(()) Ok(())
} else { } else {
Err(FdoErr::NotSupported( Err(FdoErr::NotSupported(
"RogPlatform: platform_profile not supported".to_owned() "RogPlatform: platform_profile not supported".to_owned(),
)) ))
} }
} }
@@ -399,7 +457,7 @@ impl CtrlPlatform {
async fn set_platform_profile_on_battery( async fn set_platform_profile_on_battery(
&mut self, &mut self,
#[zbus(signal_context)] ctxt: SignalEmitter<'_>, #[zbus(signal_context)] ctxt: SignalEmitter<'_>,
policy: PlatformProfile policy: PlatformProfile,
) -> Result<(), FdoErr> { ) -> Result<(), FdoErr> {
self.config.lock().await.platform_profile_on_battery = policy; self.config.lock().await.platform_profile_on_battery = policy;
self.set_platform_profile(ctxt, policy).await?; self.set_platform_profile(ctxt, policy).await?;
@@ -428,7 +486,7 @@ impl CtrlPlatform {
async fn set_platform_profile_on_ac( async fn set_platform_profile_on_ac(
&mut self, &mut self,
#[zbus(signal_context)] ctxt: SignalEmitter<'_>, #[zbus(signal_context)] ctxt: SignalEmitter<'_>,
policy: PlatformProfile policy: PlatformProfile,
) -> Result<(), FdoErr> { ) -> Result<(), FdoErr> {
self.config.lock().await.platform_profile_on_ac = policy; self.config.lock().await.platform_profile_on_ac = policy;
self.set_platform_profile(ctxt, policy).await?; self.set_platform_profile(ctxt, policy).await?;
@@ -593,7 +651,7 @@ impl ReloadAndNotify for CtrlPlatform {
async fn reload_and_notify( async fn reload_and_notify(
&mut self, &mut self,
signal_context: &SignalEmitter<'static>, signal_context: &SignalEmitter<'static>,
data: Self::Data data: Self::Data,
) -> Result<(), RogError> { ) -> Result<(), RogError> {
let mut config = self.config.lock().await; let mut config = self.config.lock().await;
if *config != data { if *config != data {
@@ -622,7 +680,9 @@ impl ReloadAndNotify for CtrlPlatform {
let epp = match profile { let epp = match profile {
PlatformProfile::Balanced => data.profile_balanced_epp, PlatformProfile::Balanced => data.profile_balanced_epp,
PlatformProfile::Performance => data.profile_performance_epp, PlatformProfile::Performance => data.profile_performance_epp,
PlatformProfile::Quiet => data.profile_quiet_epp PlatformProfile::Quiet => data.profile_quiet_epp,
PlatformProfile::LowPower => data.profile_quiet_epp,
PlatformProfile::Custom => data.profile_custom_epp,
}; };
warn!("setting epp to {epp:?}"); warn!("setting epp to {epp:?}");
self.check_and_set_epp(epp, true); self.check_and_set_epp(epp, true);
@@ -694,7 +754,7 @@ impl CtrlTask for CtrlPlatform {
platform1 platform1
.power .power
.set_charge_control_end_threshold( .set_charge_control_end_threshold(
platform1.config.lock().await.charge_control_end_threshold platform1.config.lock().await.charge_control_end_threshold,
) )
.ok(); .ok();
} }
@@ -709,6 +769,31 @@ impl CtrlTask for CtrlPlatform {
} }
if !sleeping { if !sleeping {
platform1.run_ac_or_bat_cmd(power_plugged > 0).await; platform1.run_ac_or_bat_cmd(power_plugged > 0).await;
if let Ok(profile) =
platform1.platform.get_platform_profile().map(|p| p.into())
{
let attrs = FirmwareAttributes::new();
{
let mut cfg = platform1.config.lock().await;
set_config_or_default(
&attrs,
&mut cfg,
power_plugged > 0,
profile,
)
.await;
}
if let Err(e) = platform1
.armoury_registry
.emit_limits(&platform1.connection)
.await
{
error!(
"Failed to emit armoury updates after power change: \
{e:?}"
);
}
}
} }
platform1.config.lock().await.last_power_plugged = power_plugged; platform1.config.lock().await.last_power_plugged = power_plugged;
} }
@@ -728,7 +813,7 @@ impl CtrlTask for CtrlPlatform {
platform2 platform2
.power .power
.set_charge_control_end_threshold( .set_charge_control_end_threshold(
lock.base_charge_control_end_threshold lock.base_charge_control_end_threshold,
) )
.map_err(|err| { .map_err(|err| {
warn!("CtrlCharge: charge_control_end_threshold {}", err); warn!("CtrlCharge: charge_control_end_threshold {}", err);
@@ -769,20 +854,24 @@ impl CtrlTask for CtrlPlatform {
{ {
// TODO: manage this better, shouldn't need to create every time // TODO: manage this better, shouldn't need to create every time
let attrs = FirmwareAttributes::new(); let attrs = FirmwareAttributes::new();
set_config_or_default( {
&attrs, let mut cfg = platform3.config.lock().await;
&mut *platform3.config.lock().await, set_config_or_default(&attrs, &mut cfg, power_plugged, profile).await;
power_plugged, }
profile if let Err(e) = platform3
) .armoury_registry
.await; .emit_limits(&platform3.connection)
.await
{
error!("Failed to emit armoury updates after AC/DC toggle: {e:?}");
}
platform3 platform3
.enable_ppt_group_changed(&signal_ctxt_copy) .enable_ppt_group_changed(&signal_ctxt_copy)
.await .await
.ok(); .ok();
} }
} }
} },
) )
.await; .await;
@@ -829,9 +918,12 @@ impl CtrlTask for CtrlPlatform {
&attrs, &attrs,
&mut *ctrl.config.lock().await, &mut *ctrl.config.lock().await,
power_plugged == 1, power_plugged == 1,
profile profile,
) )
.await; .await;
if let Err(e) = ctrl.armoury_registry.emit_limits(&ctrl.connection).await {
error!("Failed to emit armoury updates after profile change: {e:?}");
}
} }
} }
} }

View File

@@ -2,23 +2,26 @@ use std::env;
use std::error::Error; use std::error::Error;
use std::sync::Arc; use std::sync::Arc;
use ::zbus::export::futures_util::lock::Mutex;
use ::zbus::Connection; use ::zbus::Connection;
use asusd::asus_armoury::start_attributes_zbus; use asusd::asus_armoury::{start_attributes_zbus, ArmouryAttributeRegistry};
use asusd::aura_manager::DeviceManager; use asusd::aura_manager::DeviceManager;
use asusd::config::Config; use asusd::config::Config;
use asusd::ctrl_backlight::CtrlBacklight;
use asusd::ctrl_fancurves::CtrlFanCurveZbus; use asusd::ctrl_fancurves::CtrlFanCurveZbus;
use asusd::ctrl_platform::CtrlPlatform; use asusd::ctrl_platform::CtrlPlatform;
use asusd::{print_board_info, start_tasks, CtrlTask, DBUS_NAME}; use asusd::{print_board_info, start_tasks, CtrlTask, ZbusRun, DBUS_NAME};
use config_traits::{StdConfig, StdConfigLoad1}; use config_traits::{StdConfig, StdConfigLoad2};
use log::{error, info}; use log::{error, info};
use rog_platform::asus_armoury::FirmwareAttributes; use rog_platform::asus_armoury::FirmwareAttributes;
use rog_platform::platform::RogPlatform; use rog_platform::platform::RogPlatform;
use rog_platform::power::AsusPower; use rog_platform::power::AsusPower;
use tokio::sync::Mutex;
use zbus::fdo::ObjectManager; use zbus::fdo::ObjectManager;
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> { async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Starting asusd daemon...");
// console_subscriber::init(); // console_subscriber::init();
let mut logger = env_logger::Builder::new(); let mut logger = env_logger::Builder::new();
logger logger
@@ -30,7 +33,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let is_service = match env::var_os("IS_SERVICE") { let is_service = match env::var_os("IS_SERVICE") {
Some(val) => val == "1", Some(val) => val == "1",
None => true None => true,
}; };
if !is_service { if !is_service {
@@ -61,7 +64,9 @@ async fn start_daemon() -> Result<(), Box<dyn Error>> {
// Start zbus server // Start zbus server
let mut server = Connection::system().await?; let mut server = Connection::system().await?;
server.object_server().at("/", ObjectManager).await.unwrap(); if let Err(e) = server.object_server().at("/", ObjectManager).await {
error!("Failed to register ObjectManager at root '/': {e:?}");
}
let config = Config::new().load(); let config = Config::new().load();
let cfg_path = config.file_path(); let cfg_path = config.file_path();
@@ -71,36 +76,64 @@ async fn start_daemon() -> Result<(), Box<dyn Error>> {
let platform = RogPlatform::new()?; // TODO: maybe needs async mutex? let platform = RogPlatform::new()?; // TODO: maybe needs async mutex?
let power = AsusPower::new()?; // TODO: maybe needs async mutex? let power = AsusPower::new()?; // TODO: maybe needs async mutex?
let attributes = FirmwareAttributes::new(); let attributes = FirmwareAttributes::new();
start_attributes_zbus( let armoury_registry = match start_attributes_zbus(
&server, &server,
platform.clone(), platform.clone(),
power.clone(), power.clone(),
attributes.clone(), attributes.clone(),
config.clone() config.clone(),
) )
.await?; .await
{
Ok(registry) => {
info!("attribute on zbus initialized");
registry
}
Err(e) => {
error!("Failed to initialize firmware attributes over zbus: {e:?}");
ArmouryAttributeRegistry::default()
}
};
match CtrlFanCurveZbus::new() { match CtrlFanCurveZbus::new() {
Ok(ctrl) => { Ok(ctrl) => {
info!("FanCurves: found supported fancurves");
let sig_ctx = CtrlFanCurveZbus::signal_context(&server)?; let sig_ctx = CtrlFanCurveZbus::signal_context(&server)?;
start_tasks(ctrl, &mut server, sig_ctx).await?; start_tasks(ctrl, &mut server, sig_ctx).await?;
info!("FanCurves: initialized");
} }
Err(err) => { Err(err) => {
error!("FanCurves: {}", err); error!("FanCurves: {}", err);
} }
} }
match CtrlBacklight::new(config.clone()) {
Ok(backlight) => {
info!("Backlight: found supported backlight");
backlight.start_watch_primary().await?;
backlight.add_to_server(&mut server).await;
info!("Backlight: initialized");
}
Err(err) => {
error!("Backlight: {}", err);
}
}
match CtrlPlatform::new( match CtrlPlatform::new(
platform, platform,
power, power,
attributes, attributes,
config.clone(), config.clone(),
&cfg_path, &cfg_path,
CtrlPlatform::signal_context(&server)? CtrlPlatform::signal_context(&server)?,
server.clone(),
armoury_registry,
) { ) {
Ok(ctrl) => { Ok(ctrl) => {
info!("CtrlPlatform: initialized");
let sig_ctx = CtrlPlatform::signal_context(&server)?; let sig_ctx = CtrlPlatform::signal_context(&server)?;
start_tasks(ctrl, &mut server, sig_ctx).await?; start_tasks(ctrl, &mut server, sig_ctx).await?;
info!("CtrlPlatform: tasks started");
} }
Err(err) => { Err(err) => {
error!("CtrlPlatform: {}", err); error!("CtrlPlatform: {}", err);
@@ -109,10 +142,12 @@ async fn start_daemon() -> Result<(), Box<dyn Error>> {
let _ = DeviceManager::new(server.clone()).await?; let _ = DeviceManager::new(server.clone()).await?;
info!("DeviceManager initialized");
// Request dbus name after finishing initalizing all functions // Request dbus name after finishing initalizing all functions
server.request_name(DBUS_NAME).await?; server.request_name(DBUS_NAME).await?;
info!("Startup success, begining dbus server loop"); info!("Startup success on dbus name {DBUS_NAME}: begining dbus server loop");
loop { loop {
// This is just a blocker to idle and ensure the reator reacts // This is just a blocker to idle and ensure the reator reacts
server.executor().tick().await; server.executor().tick().await;

View File

@@ -37,7 +37,7 @@ pub enum RogError {
SystemdUnitAction(String), SystemdUnitAction(String),
SystemdUnitWaitTimeout(String), SystemdUnitWaitTimeout(String),
Command(String, std::io::Error), Command(String, std::io::Error),
ParseRon(ron::Error) ParseRon(ron::Error),
} }
impl fmt::Display for RogError { impl fmt::Display for RogError {
@@ -87,7 +87,7 @@ impl fmt::Display for RogError {
) )
} }
RogError::Command(func, error) => write!(f, "Command exec error: {}: {}", func, error), RogError::Command(func, error) => write!(f, "Command exec error: {}: {}", func, error),
RogError::ParseRon(error) => write!(f, "Parse config error: {}", error) RogError::ParseRon(error) => write!(f, "Parse config error: {}", error),
} }
} }
} }

View File

@@ -1,6 +1,7 @@
#![deny(unused_must_use)] #![deny(unused_must_use)]
/// Configuration loading, saving /// Configuration loading, saving
pub mod config; pub mod config;
pub mod ctrl_backlight;
/// Control platform profiles + fan-curves if available /// Control platform profiles + fan-curves if available
pub mod ctrl_fancurves; pub mod ctrl_fancurves;
/// Control ASUS bios function such as boot sound, Optimus/Dedicated gfx mode /// Control ASUS bios function such as boot sound, Optimus/Dedicated gfx mode
@@ -67,7 +68,7 @@ macro_rules! task_watch_item {
&self, &self,
signal_ctxt: SignalEmitter<'static>, signal_ctxt: SignalEmitter<'static>,
) -> Result<(), RogError> { ) -> Result<(), RogError> {
use zbus::export::futures_util::StreamExt; use futures_util::StreamExt;
let ctrl = self.clone(); let ctrl = self.clone();
concat_idents::concat_idents!(watch_fn = monitor_, $name { concat_idents::concat_idents!(watch_fn = monitor_, $name {
@@ -107,7 +108,7 @@ macro_rules! task_watch_item_notify {
&self, &self,
signal_ctxt: SignalEmitter<'static>, signal_ctxt: SignalEmitter<'static>,
) -> Result<(), RogError> { ) -> Result<(), RogError> {
use zbus::export::futures_util::StreamExt; use futures_util::StreamExt;
let ctrl = self.clone(); let ctrl = self.clone();
concat_idents::concat_idents!(watch_fn = monitor_, $name { concat_idents::concat_idents!(watch_fn = monitor_, $name {
@@ -149,7 +150,7 @@ pub trait ReloadAndNotify {
fn reload_and_notify( fn reload_and_notify(
&mut self, &mut self,
signal_context: &SignalEmitter<'static>, signal_context: &SignalEmitter<'static>,
data: Self::Data data: Self::Data,
) -> impl Future<Output = Result<(), RogError>> + Send; ) -> impl Future<Output = Result<(), RogError>> + Send;
} }
@@ -159,7 +160,7 @@ pub trait ZbusRun {
fn add_to_server_helper( fn add_to_server_helper(
iface: impl Interface, iface: impl Interface,
path: &str, path: &str,
server: &mut Connection server: &mut Connection,
) -> impl Future<Output = ()> + Send { ) -> impl Future<Output = ()> + Send {
async move { async move {
server server
@@ -188,7 +189,7 @@ pub trait CtrlTask {
/// separate thread. /// separate thread.
fn create_tasks( fn create_tasks(
&self, &self,
signal: SignalEmitter<'static> signal: SignalEmitter<'static>,
) -> impl Future<Output = Result<(), RogError>> + Send; ) -> impl Future<Output = Result<(), RogError>> + Send;
// /// Create a timed repeating task // /// Create a timed repeating task
@@ -212,7 +213,7 @@ pub trait CtrlTask {
mut on_prepare_for_sleep: F1, mut on_prepare_for_sleep: F1,
mut on_prepare_for_shutdown: F2, mut on_prepare_for_shutdown: F2,
mut on_lid_change: F3, mut on_lid_change: F3,
mut on_external_power_change: F4 mut on_external_power_change: F4,
) -> impl Future<Output = ()> + Send ) -> impl Future<Output = ()> + Send
where where
F1: FnMut(bool) -> Fut1 + Send + 'static, F1: FnMut(bool) -> Fut1 + Send + 'static,
@@ -222,7 +223,7 @@ pub trait CtrlTask {
Fut1: Future<Output = ()> + Send, Fut1: Future<Output = ()> + Send,
Fut2: Future<Output = ()> + Send, Fut2: Future<Output = ()> + Send,
Fut3: Future<Output = ()> + Send, Fut3: Future<Output = ()> + Send,
Fut4: Future<Output = ()> + Send Fut4: Future<Output = ()> + Send,
{ {
async { async {
let connection = Connection::system() let connection = Connection::system()
@@ -302,10 +303,10 @@ pub trait GetSupported {
pub async fn start_tasks<T>( pub async fn start_tasks<T>(
mut zbus: T, mut zbus: T,
connection: &mut Connection, connection: &mut Connection,
signal_ctx: SignalEmitter<'static> signal_ctx: SignalEmitter<'static>,
) -> Result<(), RogError> ) -> Result<(), RogError>
where where
T: ZbusRun + Reloadable + CtrlTask + Clone T: ZbusRun + Reloadable + CtrlTask + Clone,
{ {
let zbus_clone = zbus.clone(); let zbus_clone = zbus.clone();

View File

@@ -19,7 +19,7 @@ use serde::Serialize;
/// implemented, the rest are intended to be free methods. /// implemented, the rest are intended to be free methods.
pub trait StdConfig pub trait StdConfig
where where
Self: Serialize + DeserializeOwned Self: Serialize + DeserializeOwned,
{ {
/// Taking over the standard `new()` to ensure things can be generic /// Taking over the standard `new()` to ensure things can be generic
fn new() -> Self; fn new() -> Self;

View File

@@ -9,11 +9,14 @@ ENV{DMI_FAMILY}=="*Strix*", GOTO="asusd_start"
ENV{DMI_FAMILY}=="*Vivo*ook*", GOTO="asusd_start" ENV{DMI_FAMILY}=="*Vivo*ook*", GOTO="asusd_start"
ENV{DMI_FAMILY}=="*Zenbook*", GOTO="asusd_start" ENV{DMI_FAMILY}=="*Zenbook*", GOTO="asusd_start"
ENV{DMI_FAMILY}=="*ProArt*", GOTO="asusd_start" ENV{DMI_FAMILY}=="*ProArt*", GOTO="asusd_start"
ENV{DMI_FAMILY}=="*TX Air*", GOTO="asusd_start"
ENV{DMI_FAMILY}=="*TX Gaming*", GOTO="asusd_start"
ENV{DMI_FAMILY}=="*EXPERTBOOK*", GOTO="asusd_start"
# No match so # No match so
GOTO="asusd_end" GOTO="asusd_end"
LABEL="asusd_start" LABEL="asusd_start"
ACTION=="add|change", DRIVER=="asus-nb-wmi", TAG+="systemd", ENV{SYSTEMD_WANTS}="asusd.service" ACTION=="add|change", DRIVER=="asus-nb-wmi", TAG+="systemd", ENV{SYSTEMD_WANTS}+="asusd.service"
ACTION=="add|remove", DRIVER=="asus-nb-wmi", TAG+="systemd", RUN+="systemctl restart asusd.service" ACTION=="add|remove", DRIVER=="asus-nb-wmi", TAG+="systemd", ENV{SYSTEMD_WANTS}+="asusd.service"
LABEL="asusd_end" LABEL="asusd_end"

View File

@@ -6,7 +6,10 @@ After=nvidia-powerd.service systemd-udevd.service
[Service] [Service]
Environment=IS_SERVICE=1 Environment=IS_SERVICE=1
Environment=RUST_LOG="debug" # Reduce noisy span logs while keeping useful debug info for asusd and related crates.
# Keep global level at info but allow debug for our crates; silence tracing::span (very noisy)
# RUST_LOG format: <module>=<level>,... (levels: error,warn,info,debug,trace)
Environment=RUST_LOG="info,asusd=debug,rog_platform=debug,tracing::span=error,zbus::object_server=error,zbus::connection::handshake::common=error,zbus::connection::handshake::client=error"
# required to prevent init issues with hid_asus and MCU # required to prevent init issues with hid_asus and MCU
ExecStartPre=/bin/sleep 1 ExecStartPre=/bin/sleep 1
ExecStart=/usr/bin/asusd ExecStart=/usr/bin/asusd

120
distro-packaging/asusctl.spec Executable file → Normal file
View File

@@ -1,7 +1,7 @@
# #
# spec file for package asus-nb-ctrl # spec file for package asus-nb-ctrl
# #
# Copyright (c) 2020-2021 Luke Jones <luke@ljones.dev> # Copyright (c) 2020-2025 Luke Jones <luke@ljones.dev>
# #
# All modifications and additions to the file contributed by third parties # All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed # remain the property of their copyright owners, unless otherwise agreed
@@ -20,13 +20,14 @@
%global debug_package %{nil} %global debug_package %{nil}
%endif %endif
%define version 6.2.0
%define specrelease %{?dist} %define specrelease %{?dist}
%define pkg_release 3%{specrelease} %define pkg_release 1%{specrelease}
# Use hardening ldflags. # Use hardening ldflags.
%global rustflags -Clink-arg=-Wl,-z,relro,-z,now %global rustflags -Clink-arg=-Wl,-z,relro,-z,now
Name: asusctl Name: asusctl
Version: 6.0.7 Version: %{version}
Release: %{pkg_release} Release: %{pkg_release}
Summary: Control fan speeds, LEDs, graphics modes, and charge levels for ASUS notebooks Summary: Control fan speeds, LEDs, graphics modes, and charge levels for ASUS notebooks
License: MPLv2 License: MPLv2
@@ -34,28 +35,29 @@ License: MPLv2
Group: System Environment/Kernel Group: System Environment/Kernel
URL: https://gitlab.com/asus-linux/asusctl URL: https://gitlab.com/asus-linux/asusctl
Source: %{name}-%{version}.tar.gz Source: https://gitlab.com/asus-linux/asusctl/-/archive/%{version}/%{name}-%{version}.tar.gz
Source1: vendor_%{name}_%{version}.tar.xz
Source2: cargo-config
BuildRequires: cargo %if %{defined fedora}
BuildRequires: rust-packaging BuildRequires: rust-packaging
BuildRequires: systemd-rpm-macros BuildRequires: systemd-rpm-macros
%else
BuildRequires: cargo-packaging
%endif
BuildRequires: git
BuildRequires: clang-devel BuildRequires: clang-devel
BuildRequires: cargo
BuildRequires: cmake BuildRequires: cmake
BuildRequires: rust BuildRequires: rust
BuildRequires: rust-std-static BuildRequires: rust-std-static
BuildRequires: pkgconfig(expat) BuildRequires: pkgconfig(gbm)
BuildRequires: pkgconfig(dbus-1) BuildRequires: pkgconfig(libinput)
BuildRequires: pkgconfig(libseat)
BuildRequires: pkgconfig(libudev) BuildRequires: pkgconfig(libudev)
BuildRequires: pkgconfig(xkbcommon) BuildRequires: pkgconfig(xkbcommon)
BuildRequires: pkgconfig(libzstd) BuildRequires: pkgconfig(libzstd)
BuildRequires: pkgconfig(gtk+-3.0) BuildRequires: pkgconfig(fontconfig)
BuildRequires: pkgconfig(gdk-3.0)
BuildRequires: desktop-file-utils BuildRequires: desktop-file-utils
# expat-devel pcre2-devel
%description %description
asus-nb-ctrl is a utility for Linux to control many aspects of various 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. ASUS laptops but can also be used with non-Asus laptops with reduced features.
@@ -66,38 +68,93 @@ asus-nb-ctrl enables third-party apps to use the above with dbus methods.
%package rog-gui %package rog-gui
Summary: An experimental GUI for %{name} Summary: An experimental GUI for %{name}
Requires: %{name} = %{version}-%{release}
%description rog-gui %description rog-gui
A one-stop-shop GUI tool for asusd/asusctl. It aims to provide most controls, 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. a notification service, and ability to run in the background.
%prep %prep
# %setup -D -T -a 1 -c -n %{name}-%{version}/vendor
# %setup -D -T -a 0 -c
%autosetup %autosetup
%setup -D -T -a 1 mkdir -p .cargo
cat > .cargo/config.toml << 'EOF'
mv Cargo.lock{,.bak} [term]
%cargo_prep verbose = true
mv Cargo.lock{.bak,} [net]
sed -i 's|replace-with = "local-registry"|replace-with = "vendored-sources"|' .cargo/config offline = false
cat %{SOURCE2} >> .cargo/config EOF
%build %build
export RUSTFLAGS="%{rustflags}" export RUSTFLAGS="%{rustflags}"
%cargo_build %if %{defined fedora}
#cargo build --release --frozen --offline --config .cargo/config.toml /usr/bin/cargo build --release --locked
%else
/usr/bin/cargo auditable build --release --locked
%endif
%install %install
export RUSTFLAGS="%{rustflags}" export RUSTFLAGS="%{rustflags}"
mkdir -p "%{buildroot}/%{_bindir}" "%{buildroot}%{_docdir}"
%make_install
install -D -m 0644 README.md %{buildroot}/%{_docdir}/%{name}/README.md %define _target_dir target/release
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 # Install binaries
install -D -m 0755 %{_target_dir}/asusd %{buildroot}%{_bindir}/asusd
install -D -m 0755 %{_target_dir}/asusd-user %{buildroot}%{_bindir}/asusd-user
install -D -m 0755 %{_target_dir}/asusctl %{buildroot}%{_bindir}/asusctl
install -D -m 0755 %{_target_dir}/rog-control-center %{buildroot}%{_bindir}/rog-control-center
# Install systemd units
install -D -m 0644 data/asusd.service %{buildroot}%{_unitdir}/asusd.service
install -D -m 0644 data/asusd-user.service %{buildroot}%{_userunitdir}/asusd-user.service
# Install udev rules
install -D -m 0644 data/asusd.rules %{buildroot}%{_udevrulesdir}/99-asusd.rules
# Install dbus config
install -D -m 0644 data/asusd.conf %{buildroot}%{_datadir}/dbus-1/system.d/asusd.conf
# Install asusd data
install -D -m 0644 rog-aura/data/aura_support.ron %{buildroot}%{_datadir}/asusd/aura_support.ron
cp -r rog-anime/data/anime %{buildroot}%{_datadir}/asusd/
# Install rog-gui data
install -D -m 0644 rog-control-center/data/rog-control-center.desktop %{buildroot}%{_datadir}/applications/rog-control-center.desktop
install -D -m 0644 rog-control-center/data/rog-control-center.png %{buildroot}%{_datadir}/icons/hicolor/512x512/apps/rog-control-center.png
mkdir -p %{buildroot}%{_datadir}/rog-gui/layouts
cp -r rog-aura/data/layouts/*.ron %{buildroot}%{_datadir}/rog-gui/layouts/
# Install icons
install -D -m 0644 data/icons/asus_notif_yellow.png %{buildroot}%{_datadir}/icons/hicolor/512x512/apps/asus_notif_yellow.png
install -D -m 0644 data/icons/asus_notif_green.png %{buildroot}%{_datadir}/icons/hicolor/512x512/apps/asus_notif_green.png
install -D -m 0644 data/icons/asus_notif_blue.png %{buildroot}%{_datadir}/icons/hicolor/512x512/apps/asus_notif_blue.png
install -D -m 0644 data/icons/asus_notif_red.png %{buildroot}%{_datadir}/icons/hicolor/512x512/apps/asus_notif_red.png
install -D -m 0644 data/icons/asus_notif_orange.png %{buildroot}%{_datadir}/icons/hicolor/512x512/apps/asus_notif_orange.png
install -D -m 0644 data/icons/asus_notif_white.png %{buildroot}%{_datadir}/icons/hicolor/512x512/apps/asus_notif_white.png
install -D -m 0644 data/icons/scalable/gpu-compute.svg %{buildroot}%{_datadir}/icons/hicolor/scalable/status/gpu-compute.svg
install -D -m 0644 data/icons/scalable/gpu-hybrid.svg %{buildroot}%{_datadir}/icons/hicolor/scalable/status/gpu-hybrid.svg
install -D -m 0644 data/icons/scalable/gpu-integrated.svg %{buildroot}%{_datadir}/icons/hicolor/scalable/status/gpu-integrated.svg
install -D -m 0644 data/icons/scalable/gpu-nvidia.svg %{buildroot}%{_datadir}/icons/hicolor/scalable/status/gpu-nvidia.svg
install -D -m 0644 data/icons/scalable/gpu-vfio.svg %{buildroot}%{_datadir}/icons/hicolor/scalable/status/gpu-vfio.svg
install -D -m 0644 data/icons/scalable/notification-reboot.svg %{buildroot}%{_datadir}/icons/hicolor/scalable/status/notification-reboot.svg
# Install docs
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
# Install LICENSE to asusctl datadir
install -D -m 0644 LICENSE %{buildroot}%{_datadir}/asusctl/LICENSE
desktop-file-validate %{buildroot}%{_datadir}/applications/rog-control-center.desktop
%post
%systemd_post asusd.service
%preun
%systemd_preun asusd.service
%postun
%systemd_postun_with_restart asusd.service
%files %files
%license LICENSE %license LICENSE
@@ -107,8 +164,6 @@ desktop-file-validate %{buildroot}/%{_datadir}/applications/rog-control-center.d
%{_unitdir}/asusd.service %{_unitdir}/asusd.service
%{_userunitdir}/asusd-user.service %{_userunitdir}/asusd-user.service
%{_udevrulesdir}/99-asusd.rules %{_udevrulesdir}/99-asusd.rules
#%dir %{_sysconfdir}/asusd/
%{_datadir}/asusd/aura_support.ron
%{_datadir}/dbus-1/system.d/asusd.conf %{_datadir}/dbus-1/system.d/asusd.conf
%{_datadir}/icons/hicolor/512x512/apps/asus_notif_yellow.png %{_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_green.png
@@ -123,6 +178,7 @@ desktop-file-validate %{buildroot}/%{_datadir}/applications/rog-control-center.d
%{_datadir}/icons/hicolor/scalable/status/gpu-vfio.svg %{_datadir}/icons/hicolor/scalable/status/gpu-vfio.svg
%{_datadir}/icons/hicolor/scalable/status/notification-reboot.svg %{_datadir}/icons/hicolor/scalable/status/notification-reboot.svg
%{_docdir}/%{name}/ %{_docdir}/%{name}/
%{_datadir}/asusctl/
%{_datadir}/asusd/ %{_datadir}/asusd/
%files rog-gui %files rog-gui

View File

@@ -12,7 +12,7 @@ pub struct DMIID {
pub bios_vendor: String, pub bios_vendor: String,
pub bios_version: String, pub bios_version: String,
pub product_family: String, pub product_family: String,
pub product_name: String pub product_name: String,
} }
impl DMIID { impl DMIID {
@@ -77,7 +77,7 @@ impl DMIID {
product_name: device product_name: device
.attribute_value("product_name") .attribute_value("product_name")
.map(|s| s.to_string_lossy().to_string()) .map(|s| s.to_string_lossy().to_string())
.unwrap_or("Unknown".to_string()) .unwrap_or("Unknown".to_string()),
}); });
} }
Err("dmi not found".into()) Err("dmi not found".into())

View File

@@ -23,15 +23,15 @@ const PANE_LEN: usize = BLOCK_END - BLOCK_START;
/// First packet is for GA401 + GA402 /// First packet is for GA401 + GA402
pub const USB_PREFIX1: [u8; 7] = [ pub const USB_PREFIX1: [u8; 7] = [
0x5e, 0xc0, 0x02, 0x01, 0x00, 0x73, 0x02 0x5e, 0xc0, 0x02, 0x01, 0x00, 0x73, 0x02,
]; ];
/// Second packet is for GA401 + GA402 /// Second packet is for GA401 + GA402
pub const USB_PREFIX2: [u8; 7] = [ pub const USB_PREFIX2: [u8; 7] = [
0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02 0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02,
]; ];
/// Third packet is for GA402 matrix /// Third packet is for GA402 matrix
pub const USB_PREFIX3: [u8; 7] = [ pub const USB_PREFIX3: [u8; 7] = [
0x5e, 0xc0, 0x02, 0xe7, 0x04, 0x73, 0x02 0x5e, 0xc0, 0x02, 0xe7, 0x04, 0x73, 0x02,
]; ];
#[cfg_attr(feature = "dbus", derive(Type, Value, OwnedValue))] #[cfg_attr(feature = "dbus", derive(Type, Value, OwnedValue))]
@@ -40,7 +40,7 @@ pub struct Animations {
pub boot: AnimBooting, pub boot: AnimBooting,
pub awake: AnimAwake, pub awake: AnimAwake,
pub sleep: AnimSleeping, pub sleep: AnimSleeping,
pub shutdown: AnimShutdown pub shutdown: AnimShutdown,
} }
// TODO: move this out // TODO: move this out
@@ -54,7 +54,7 @@ pub struct DeviceState {
pub off_when_unplugged: bool, pub off_when_unplugged: bool,
pub off_when_suspended: bool, pub off_when_suspended: bool,
pub off_when_lid_closed: bool, pub off_when_lid_closed: bool,
pub brightness_on_battery: Brightness pub brightness_on_battery: Brightness,
} }
#[cfg_attr(feature = "dbus", derive(Type), zvariant(signature = "s"))] #[cfg_attr(feature = "dbus", derive(Type), zvariant(signature = "s"))]
@@ -63,20 +63,31 @@ pub enum AnimeType {
GA401, GA401,
GA402, GA402,
GU604, GU604,
G635L,
G835L,
#[default] #[default]
Unsupported Unsupported,
} }
impl FromStr for AnimeType { impl FromStr for AnimeType {
type Err = AnimeError; type Err = AnimeError;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> { fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
Ok(match s { let dmi = s.to_uppercase();
"ga401" | "GA401" => Self::GA401,
"ga402" | "GA402" => Self::GA402, if dmi.contains("GA401") {
"gu604" | "GU604" => Self::GU604, return Ok(Self::GA401);
_ => Self::Unsupported } else if dmi.contains("GA402") {
}) return Ok(Self::GA402);
} else if dmi.contains("GU604") {
return Ok(Self::GU604);
} else if dmi.contains("G635L") {
return Ok(Self::G635L);
} else if dmi.contains("G835L") {
return Ok(Self::G835L);
}
Ok(Self::Unsupported)
} }
} }
@@ -89,6 +100,8 @@ impl AnimeType {
AnimeType::GA402 AnimeType::GA402
} else if board_name.contains("GU604V") { } else if board_name.contains("GU604V") {
AnimeType::GU604 AnimeType::GU604
} else if board_name.contains("G635L") || board_name.contains("G635L") {
AnimeType::G635L
} else { } else {
AnimeType::Unsupported AnimeType::Unsupported
} }
@@ -98,7 +111,8 @@ impl AnimeType {
pub fn width(&self) -> usize { pub fn width(&self) -> usize {
match self { match self {
AnimeType::GU604 => 70, AnimeType::GU604 => 70,
_ => 74 AnimeType::G835L => 74,
_ => 74,
} }
} }
@@ -107,7 +121,8 @@ impl AnimeType {
match self { match self {
AnimeType::GA401 => 36, AnimeType::GA401 => 36,
AnimeType::GU604 => 43, AnimeType::GU604 => 43,
_ => 39 AnimeType::G835L => 39,
_ => 39,
} }
} }
@@ -116,7 +131,8 @@ impl AnimeType {
match self { match self {
AnimeType::GA401 => PANE_LEN * 2, AnimeType::GA401 => PANE_LEN * 2,
AnimeType::GU604 => PANE_LEN * 3, AnimeType::GU604 => PANE_LEN * 3,
_ => PANE_LEN * 3 AnimeType::G835L => PANE_LEN * 3,
_ => PANE_LEN * 3,
} }
} }
} }
@@ -127,7 +143,7 @@ impl AnimeType {
#[derive(Debug, Clone, Deserialize, Serialize)] #[derive(Debug, Clone, Deserialize, Serialize)]
pub struct AnimeDataBuffer { pub struct AnimeDataBuffer {
data: Vec<u8>, data: Vec<u8>,
anime: AnimeType anime: AnimeType,
} }
impl AnimeDataBuffer { impl AnimeDataBuffer {
@@ -137,7 +153,7 @@ impl AnimeDataBuffer {
AnimeDataBuffer { AnimeDataBuffer {
data: vec![0u8; len], data: vec![0u8; len],
anime anime,
} }
} }
@@ -180,7 +196,13 @@ impl TryFrom<AnimeDataBuffer> for AnimePacketType {
let mut buffers = match anime.anime { let mut buffers = match anime.anime {
AnimeType::GA401 => vec![[0; 640]; 2], AnimeType::GA401 => vec![[0; 640]; 2],
AnimeType::GA402 | AnimeType::GU604 | AnimeType::Unsupported => vec![[0; 640]; 3] AnimeType::GA402
| AnimeType::GU604
| AnimeType::G635L
| AnimeType::G835L
| AnimeType::Unsupported => {
vec![[0; 640]; 3]
}
}; };
for (idx, chunk) in anime.data.as_slice().chunks(PANE_LEN).enumerate() { for (idx, chunk) in anime.data.as_slice().chunks(PANE_LEN).enumerate() {
@@ -191,7 +213,11 @@ impl TryFrom<AnimeDataBuffer> for AnimePacketType {
if matches!( if matches!(
anime.anime, anime.anime,
AnimeType::GA402 | AnimeType::GU604 | AnimeType::Unsupported AnimeType::GA402
| AnimeType::GU604
| AnimeType::G635L
| AnimeType::G835L
| AnimeType::Unsupported
) { ) {
buffers[2][..7].copy_from_slice(&USB_PREFIX3); buffers[2][..7].copy_from_slice(&USB_PREFIX3);
} }

View File

@@ -20,7 +20,7 @@ impl AnimeDiagonal {
Self( Self(
anime_type, anime_type,
vec![vec![0; anime_type.width()]; anime_type.height()], vec![vec![0; anime_type.width()]; anime_type.height()],
duration duration,
) )
} }
@@ -49,7 +49,7 @@ impl AnimeDiagonal {
path: &Path, path: &Path,
duration: Option<Duration>, duration: Option<Duration>,
bright: f32, bright: f32,
anime_type: AnimeType anime_type: AnimeType,
) -> Result<Self> { ) -> Result<Self> {
let data = std::fs::read(path).map_err(|e| { let data = std::fs::read(path).map_err(|e| {
error!("Could not open {path:?}: {e:?}"); error!("Could not open {path:?}: {e:?}");
@@ -86,7 +86,7 @@ impl AnimeDiagonal {
png_pong::PngRaster::Rgba16(ras) => { png_pong::PngRaster::Rgba16(ras) => {
Self::pixels_from_16bit(ras, &mut matrix, bright, false); Self::pixels_from_16bit(ras, &mut matrix, bright, false);
} }
png_pong::PngRaster::Palette(..) => return Err(AnimeError::Format) png_pong::PngRaster::Palette(..) => return Err(AnimeError::Format),
}; };
Ok(matrix) Ok(matrix)
@@ -96,9 +96,9 @@ impl AnimeDiagonal {
ras: &pix::Raster<P>, ras: &pix::Raster<P>,
matrix: &mut AnimeDiagonal, matrix: &mut AnimeDiagonal,
bright: f32, bright: f32,
grey: bool grey: bool,
) where ) where
P: pix::el::Pixel<Chan = pix::chan::Ch8> P: pix::el::Pixel<Chan = pix::chan::Ch8>,
{ {
let width = ras.width(); let width = ras.width();
for (y, row) in ras.pixels().chunks(width as usize).enumerate() { for (y, row) in ras.pixels().chunks(width as usize).enumerate() {
@@ -121,9 +121,9 @@ impl AnimeDiagonal {
ras: &pix::Raster<P>, ras: &pix::Raster<P>,
matrix: &mut AnimeDiagonal, matrix: &mut AnimeDiagonal,
bright: f32, bright: f32,
grey: bool grey: bool,
) where ) where
P: pix::el::Pixel<Chan = pix::chan::Ch16> P: pix::el::Pixel<Chan = pix::chan::Ch16>,
{ {
let width = ras.width(); let width = ras.width();
for (y, row) in ras.pixels().chunks(width as usize).enumerate() { for (y, row) in ras.pixels().chunks(width as usize).enumerate() {
@@ -146,7 +146,7 @@ impl AnimeDiagonal {
match anime_type { match anime_type {
AnimeType::GA401 => self.to_ga401_packets(), AnimeType::GA401 => self.to_ga401_packets(),
AnimeType::GU604 => self.to_gu604_packets(), AnimeType::GU604 => self.to_gu604_packets(),
_ => self.to_ga402_packets() _ => self.to_ga402_packets(),
} }
} }
@@ -224,7 +224,7 @@ impl AnimeDiagonal {
x: usize, x: usize,
y: usize, y: usize,
start_index: &mut usize, start_index: &mut usize,
len: usize len: usize,
) { ) {
buf[*start_index..*start_index + len].copy_from_slice(&anime.get_row(x, y, len)); buf[*start_index..*start_index + len].copy_from_slice(&anime.get_row(x, y, len));
*start_index += len; *start_index += len;
@@ -307,7 +307,7 @@ impl AnimeDiagonal {
x: usize, x: usize,
y: usize, y: usize,
start_index: &mut usize, start_index: &mut usize,
len: usize len: usize,
) { ) {
buf[*start_index..*start_index + len].copy_from_slice(&anime.get_row(x, y, len)); buf[*start_index..*start_index + len].copy_from_slice(&anime.get_row(x, y, len));
*start_index += len; *start_index += len;

View File

@@ -24,7 +24,7 @@ pub enum AnimeError {
DataBufferLength, DataBufferLength,
PixelGifWidth(usize), PixelGifWidth(usize),
PixelGifHeight(usize), PixelGifHeight(usize),
ParseError(String) ParseError(String),
} }
impl fmt::Display for AnimeError { impl fmt::Display for AnimeError {
@@ -61,7 +61,7 @@ impl fmt::Display for AnimeError {
AnimeError::PixelGifHeight(n) => write!( AnimeError::PixelGifHeight(n) => write!(
f, f,
"The gif used for pixel-perfect gif is is taller than {n}" "The gif used for pixel-perfect gif is is taller than {n}"
) ),
} }
} }
} }

View File

@@ -16,7 +16,7 @@ pub struct AnimeFrame {
/// the `asusd` daemon over dbus or converted to USB packet with /// the `asusd` daemon over dbus or converted to USB packet with
/// `AnimePacketType::from(buffer)` /// `AnimePacketType::from(buffer)`
data: AnimeDataBuffer, data: AnimeDataBuffer,
delay: Duration delay: Duration,
} }
impl AnimeFrame { impl AnimeFrame {
@@ -44,7 +44,7 @@ pub enum AnimTime {
/// Run for infinite time /// Run for infinite time
Infinite, Infinite,
/// Fade in, play for, fade out /// Fade in, play for, fade out
Fade(Fade) Fade(Fade),
} }
impl Default for AnimTime { impl Default for AnimTime {
@@ -59,7 +59,7 @@ impl Default for AnimTime {
pub struct Fade { pub struct Fade {
fade_in: Duration, fade_in: Duration,
show_for: Option<Duration>, show_for: Option<Duration>,
fade_out: Duration fade_out: Duration,
} }
impl Fade { impl Fade {
@@ -67,7 +67,7 @@ impl Fade {
Self { Self {
fade_in, fade_in,
show_for, show_for,
fade_out fade_out,
} }
} }
@@ -100,7 +100,7 @@ impl AnimeGif {
file_name: &Path, file_name: &Path,
duration: AnimTime, duration: AnimTime,
brightness: f32, brightness: f32,
anime_type: AnimeType anime_type: AnimeType,
) -> Result<Self> { ) -> Result<Self> {
let mut matrix = AnimeDiagonal::new(anime_type, None); let mut matrix = AnimeDiagonal::new(anime_type, None);
@@ -142,7 +142,7 @@ impl AnimeGif {
frames.push(AnimeFrame { frames.push(AnimeFrame {
data: matrix.into_data_buffer(anime_type)?, data: matrix.into_data_buffer(anime_type)?,
delay: Duration::from_millis(wait as u64) delay: Duration::from_millis(wait as u64),
}); });
} }
Ok(Self(frames, duration)) Ok(Self(frames, duration))
@@ -154,7 +154,7 @@ impl AnimeGif {
file_name: &Path, file_name: &Path,
anime_type: AnimeType, anime_type: AnimeType,
duration: AnimTime, duration: AnimTime,
brightness: f32 brightness: f32,
) -> Result<Self> { ) -> Result<Self> {
let image = AnimeDiagonal::from_png(file_name, None, brightness, anime_type)?; let image = AnimeDiagonal::from_png(file_name, None, brightness, anime_type)?;
@@ -170,7 +170,7 @@ impl AnimeGif {
let single = AnimeFrame { let single = AnimeFrame {
data: image.into_data_buffer(anime_type)?, data: image.into_data_buffer(anime_type)?,
delay: Duration::from_millis(30) delay: Duration::from_millis(30),
}; };
let frames = vec![single; frame_count as usize]; let frames = vec![single; frame_count as usize];
@@ -187,7 +187,7 @@ impl AnimeGif {
translation: Vec2, translation: Vec2,
duration: AnimTime, duration: AnimTime,
brightness: f32, brightness: f32,
anime_type: AnimeType anime_type: AnimeType,
) -> Result<Self> { ) -> Result<Self> {
let mut frames = Vec::new(); let mut frames = Vec::new();
let mut decoder = gif::DecodeOptions::new(); let mut decoder = gif::DecodeOptions::new();
@@ -211,7 +211,7 @@ impl AnimeGif {
brightness, brightness,
pixels, pixels,
decoder.width() as u32, decoder.width() as u32,
anime_type anime_type,
)?; )?;
while let Some(frame) = decoder.read_next_frame()? { while let Some(frame) = decoder.read_next_frame()? {
@@ -226,7 +226,7 @@ impl AnimeGif {
brightness, brightness,
pixels, pixels,
width as u32, width as u32,
anime_type anime_type,
)?; )?;
} }
for (y, row) in frame.buffer.chunks(frame.width as usize * 4).enumerate() { for (y, row) in frame.buffer.chunks(frame.width as usize * 4).enumerate() {
@@ -239,7 +239,7 @@ impl AnimeGif {
(x + frame.left as usize) + ((y + frame.top as usize) * width as usize); (x + frame.left as usize) + ((y + frame.top as usize) * width as usize);
image.get_mut()[pos] = Pixel { image.get_mut()[pos] = Pixel {
color: ((px[0] as u32 + px[1] as u32 + px[2] as u32) / 3), color: ((px[0] as u32 + px[1] as u32 + px[2] as u32) / 3),
alpha: 1.0 alpha: 1.0,
}; };
} }
} }
@@ -247,7 +247,7 @@ impl AnimeGif {
frames.push(AnimeFrame { frames.push(AnimeFrame {
data: <AnimeDataBuffer>::try_from(&image)?, data: <AnimeDataBuffer>::try_from(&image)?,
delay: Duration::from_millis(wait as u64) delay: Duration::from_millis(wait as u64),
}); });
} }
Ok(Self(frames, duration)) Ok(Self(frames, duration))
@@ -265,7 +265,7 @@ impl AnimeGif {
translation: Vec2, translation: Vec2,
duration: AnimTime, duration: AnimTime,
brightness: f32, brightness: f32,
anime_type: AnimeType anime_type: AnimeType,
) -> Result<Self> { ) -> Result<Self> {
let image = let image =
AnimeImage::from_png(file_name, scale, angle, translation, brightness, anime_type)?; AnimeImage::from_png(file_name, scale, angle, translation, brightness, anime_type)?;
@@ -282,7 +282,7 @@ impl AnimeGif {
let single = AnimeFrame { let single = AnimeFrame {
data: <AnimeDataBuffer>::try_from(&image)?, data: <AnimeDataBuffer>::try_from(&image)?,
delay: Duration::from_millis(30) delay: Duration::from_millis(30),
}; };
let frames = vec![single; frame_count as usize]; let frames = vec![single; frame_count as usize];

View File

@@ -18,7 +18,7 @@ const HEIGHT: usize = 55;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct AnimeGrid { pub struct AnimeGrid {
anime_type: AnimeType, anime_type: AnimeType,
data: [[u8; WIDTH]; HEIGHT] data: [[u8; WIDTH]; HEIGHT],
} }
impl AnimeGrid { impl AnimeGrid {
@@ -26,7 +26,7 @@ impl AnimeGrid {
pub fn new(anime_type: AnimeType) -> Self { pub fn new(anime_type: AnimeType) -> Self {
Self { Self {
anime_type, anime_type,
data: [[0u8; WIDTH]; HEIGHT] data: [[0u8; WIDTH]; HEIGHT],
} }
} }
@@ -174,7 +174,7 @@ mod tests {
0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255,
0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0,
0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0,
]; ];
assert_eq!(matrix.data(), &data_cmp); assert_eq!(matrix.data(), &data_cmp);
} }

View File

@@ -13,7 +13,7 @@ use crate::AnimeType;
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub struct Pixel { pub struct Pixel {
pub color: u32, pub color: u32,
pub alpha: f32 pub alpha: f32,
} }
impl Default for Pixel { impl Default for Pixel {
@@ -21,7 +21,7 @@ impl Default for Pixel {
fn default() -> Self { fn default() -> Self {
Pixel { Pixel {
color: 0, color: 0,
alpha: 0.0 alpha: 0.0,
} }
} }
} }
@@ -76,7 +76,7 @@ pub struct AnimeImage {
/// The type of the display. The GA401 and GA402 use the same controller and /// The type of the display. The GA401 and GA402 use the same controller and
/// therefore same ID, so the identifier must be by laptop model in /// therefore same ID, so the identifier must be by laptop model in
/// `AnimeType`. /// `AnimeType`.
anime_type: AnimeType anime_type: AnimeType,
} }
impl AnimeImage { impl AnimeImage {
@@ -88,7 +88,7 @@ impl AnimeImage {
bright: f32, bright: f32,
pixels: Vec<Pixel>, pixels: Vec<Pixel>,
width: u32, width: u32,
anime_type: AnimeType anime_type: AnimeType,
) -> Result<Self> { ) -> Result<Self> {
if !(0.0..=1.0).contains(&bright) { if !(0.0..=1.0).contains(&bright) {
return Err(AnimeError::InvalidBrightness(bright)); return Err(AnimeError::InvalidBrightness(bright));
@@ -102,7 +102,7 @@ impl AnimeImage {
led_pos: Self::generate_image_positioning(anime_type), led_pos: Self::generate_image_positioning(anime_type),
img_pixels: pixels, img_pixels: pixels,
width, width,
anime_type anime_type,
}) })
} }
@@ -121,7 +121,7 @@ impl AnimeImage {
match anime_type { match anime_type {
AnimeType::GA401 => 0.8, AnimeType::GA401 => 0.8,
AnimeType::GU604 => 0.78, AnimeType::GU604 => 0.78,
_ => 0.77 _ => 0.77,
} }
} }
@@ -138,7 +138,7 @@ impl AnimeImage {
match anime_type { match anime_type {
AnimeType::GA401 => 0.3, AnimeType::GA401 => 0.3,
AnimeType::GU604 => 0.28, AnimeType::GU604 => 0.28,
_ => 0.283 _ => 0.283,
} }
} }
@@ -169,7 +169,7 @@ impl AnimeImage {
// first 5 rows for GA401 are always at X = 0 // first 5 rows for GA401 are always at X = 0
return 0; return 0;
} }
(y + 1) / 2 - 3 y.div_ceil(2) - 3
} }
AnimeType::GU604 => { AnimeType::GU604 => {
// first 9 rows start at zero // first 9 rows start at zero
@@ -185,7 +185,7 @@ impl AnimeImage {
return 0; return 0;
} }
// and then their offset grows by one every two rows // and then their offset grows by one every two rows
(y + 1) / 2 - 5 y.div_ceil(2) - 5
} }
} }
} }
@@ -213,7 +213,7 @@ impl AnimeImage {
// First 5 rows for GA401 are always 33 physical LEDs long // First 5 rows for GA401 are always 33 physical LEDs long
return 33; return 33;
} }
36 - (y + 1) / 2 36 - y.div_ceil(2)
} }
AnimeType::GU604 => { AnimeType::GU604 => {
if y <= 9 { if y <= 9 {
@@ -237,7 +237,7 @@ impl AnimeImage {
AnimeType::GA401 => (33.0 + 0.5) * Self::scale_x(anime_type), AnimeType::GA401 => (33.0 + 0.5) * Self::scale_x(anime_type),
AnimeType::GU604 => (38.0 + 0.5) * Self::scale_x(anime_type), AnimeType::GU604 => (38.0 + 0.5) * Self::scale_x(anime_type),
_ => (35.0 + 0.5) * Self::scale_x(anime_type) _ => (35.0 + 0.5) * Self::scale_x(anime_type),
} }
} }
@@ -246,7 +246,7 @@ impl AnimeImage {
match anime_type { match anime_type {
AnimeType::GA401 => 55, AnimeType::GA401 => 55,
AnimeType::GU604 => 62, AnimeType::GU604 => 62,
_ => 61 _ => 61,
} }
} }
@@ -257,7 +257,7 @@ impl AnimeImage {
AnimeType::GA401 => (54.0 + 1.0) * Self::scale_y(anime_type), AnimeType::GA401 => (54.0 + 1.0) * Self::scale_y(anime_type),
AnimeType::GU604 => 62.0 * Self::scale_y(anime_type), AnimeType::GU604 => 62.0 * Self::scale_y(anime_type),
// GA402 may not have dead pixels and require only the physical LED count // GA402 may not have dead pixels and require only the physical LED count
_ => 61.0 * Self::scale_y(anime_type) _ => 61.0 * Self::scale_y(anime_type),
} }
} }
@@ -267,11 +267,11 @@ impl AnimeImage {
AnimeType::GA401 => match y { AnimeType::GA401 => match y {
0 | 2 | 4 => 33, 0 | 2 | 4 => 33,
1 | 3 => 35, // Some rows are padded 1 | 3 => 35, // Some rows are padded
_ => 36 - y / 2 _ => 36 - y / 2,
}, },
AnimeType::GU604 => AnimeImage::width(anime_type, y), AnimeType::GU604 => AnimeImage::width(anime_type, y),
// GA402 does not have padding, equivalent to width // GA402 does not have padding, equivalent to width
_ => AnimeImage::width(anime_type, y) _ => AnimeImage::width(anime_type, y),
} }
} }
@@ -322,7 +322,7 @@ impl AnimeImage {
let x0 = led_from_px.mul_vec3(pos + Vec3::new(0.0, -0.5, 0.0)); let x0 = led_from_px.mul_vec3(pos + Vec3::new(0.0, -0.5, 0.0));
const GROUP: [f32; 4] = [ const GROUP: [f32; 4] = [
0.0, 0.5, 1.0, 1.5 0.0, 0.5, 1.0, 1.5,
]; ];
for u in &GROUP { for u in &GROUP {
for v in &GROUP { for v in &GROUP {
@@ -399,7 +399,7 @@ impl AnimeImage {
let led_from_cm = Mat3::from_scale(Vec2::new( let led_from_cm = Mat3::from_scale(Vec2::new(
1.0 / AnimeImage::scale_x(self.anime_type), 1.0 / AnimeImage::scale_x(self.anime_type),
1.0 / AnimeImage::scale_y(self.anime_type) 1.0 / AnimeImage::scale_y(self.anime_type),
)); ));
let transform = let transform =
@@ -422,7 +422,7 @@ impl AnimeImage {
angle: f32, angle: f32,
translation: Vec2, translation: Vec2,
bright: f32, bright: f32,
anime_type: AnimeType anime_type: AnimeType,
) -> Result<Self> { ) -> Result<Self> {
let data = std::fs::read(path).map_err(|e| { let data = std::fs::read(path).map_err(|e| {
error!("Could not open {path:?}: {e:?}"); error!("Could not open {path:?}: {e:?}");
@@ -466,7 +466,7 @@ impl AnimeImage {
width = ras.width(); width = ras.width();
Self::pixels_from_16bit(ras, false) Self::pixels_from_16bit(ras, false)
} }
png_pong::PngRaster::Palette(..) => return Err(AnimeError::Format) png_pong::PngRaster::Palette(..) => return Err(AnimeError::Format),
}; };
let mut matrix = AnimeImage::new( let mut matrix = AnimeImage::new(
@@ -476,7 +476,7 @@ impl AnimeImage {
bright, bright,
pixels, pixels,
width, width,
anime_type anime_type,
)?; )?;
matrix.update(); matrix.update();
@@ -485,7 +485,7 @@ impl AnimeImage {
fn pixels_from_8bit<P>(ras: &pix::Raster<P>, grey: bool) -> Vec<Pixel> fn pixels_from_8bit<P>(ras: &pix::Raster<P>, grey: bool) -> Vec<Pixel>
where where
P: pix::el::Pixel<Chan = pix::chan::Ch8> P: pix::el::Pixel<Chan = pix::chan::Ch8>,
{ {
ras.pixels() ras.pixels()
.iter() .iter()
@@ -497,14 +497,14 @@ impl AnimeImage {
+ (<u8>::from(px.two()) / 3) as u32 + (<u8>::from(px.two()) / 3) as u32
+ (<u8>::from(px.three()) / 3) as u32 + (<u8>::from(px.three()) / 3) as u32
}, },
alpha: <f32>::from(px.alpha()) alpha: <f32>::from(px.alpha()),
}) })
.collect() .collect()
} }
fn pixels_from_16bit<P>(ras: &pix::Raster<P>, grey: bool) -> Vec<Pixel> fn pixels_from_16bit<P>(ras: &pix::Raster<P>, grey: bool) -> Vec<Pixel>
where where
P: pix::el::Pixel<Chan = pix::chan::Ch16> P: pix::el::Pixel<Chan = pix::chan::Ch16>,
{ {
ras.pixels() ras.pixels()
.iter() .iter()
@@ -516,7 +516,7 @@ impl AnimeImage {
+ ((<u16>::from(px.two()) / 3) >> 8) as u32 + ((<u16>::from(px.two()) / 3) >> 8) as u32
+ ((<u16>::from(px.three()) / 3) >> 8) as u32 + ((<u16>::from(px.three()) / 3) >> 8) as u32
}, },
alpha: <f32>::from(px.alpha()) alpha: <f32>::from(px.alpha()),
}) })
.collect() .collect()
} }
@@ -653,7 +653,7 @@ mod tests {
Vec2::default(), Vec2::default(),
AnimTime::Infinite, AnimTime::Infinite,
1.0, 1.0,
AnimeType::GA402 AnimeType::GA402,
) )
.unwrap(); .unwrap();
matrix.frames()[0].frame(); matrix.frames()[0].frame();

View File

@@ -16,13 +16,13 @@ pub enum ActionLoader {
AsusAnimation { AsusAnimation {
file: PathBuf, file: PathBuf,
time: AnimTime, time: AnimTime,
brightness: f32 brightness: f32,
}, },
/// Image designed to be pixel perfect using the slanted template /// Image designed to be pixel perfect using the slanted template
AsusImage { AsusImage {
file: PathBuf, file: PathBuf,
time: AnimTime, time: AnimTime,
brightness: f32 brightness: f32,
}, },
/// Animated gif. If the file is a png a static gif is created using the /// Animated gif. If the file is a png a static gif is created using the
/// `time` properties /// `time` properties
@@ -32,7 +32,7 @@ pub enum ActionLoader {
angle: f32, angle: f32,
translation: Vec2, translation: Vec2,
time: AnimTime, time: AnimTime,
brightness: f32 brightness: f32,
}, },
Image { Image {
file: PathBuf, file: PathBuf,
@@ -40,10 +40,10 @@ pub enum ActionLoader {
angle: f32, angle: f32,
translation: Vec2, translation: Vec2,
time: AnimTime, time: AnimTime,
brightness: f32 brightness: f32,
}, },
/// A pause to be used between sequences /// A pause to be used between sequences
Pause(Duration) Pause(Duration),
} }
/// All the possible `AniMe` actions that can be used. The enum is intended to /// All the possible `AniMe` actions that can be used. The enum is intended to
@@ -64,7 +64,7 @@ pub enum ActionData {
/// Placeholder /// Placeholder
TimeDate, TimeDate,
/// Placeholder /// Placeholder
Matrix Matrix,
} }
impl ActionData { impl ActionData {
@@ -73,14 +73,14 @@ impl ActionData {
ActionLoader::AsusAnimation { ActionLoader::AsusAnimation {
file, file,
time, time,
brightness brightness,
} => ActionData::Animation(AnimeGif::from_diagonal_gif( } => ActionData::Animation(AnimeGif::from_diagonal_gif(
file, *time, *brightness, anime_type file, *time, *brightness, anime_type,
)?), )?),
ActionLoader::AsusImage { ActionLoader::AsusImage {
file, file,
time, time,
brightness brightness,
} => match time { } => match time {
AnimTime::Infinite => { AnimTime::Infinite => {
let image = AnimeDiagonal::from_png(file, None, *brightness, anime_type)?; let image = AnimeDiagonal::from_png(file, None, *brightness, anime_type)?;
@@ -88,8 +88,8 @@ impl ActionData {
ActionData::Image(Box::new(data)) ActionData::Image(Box::new(data))
} }
_ => ActionData::Animation(AnimeGif::from_diagonal_png( _ => ActionData::Animation(AnimeGif::from_diagonal_png(
file, anime_type, *time, *brightness file, anime_type, *time, *brightness,
)?) )?),
}, },
ActionLoader::ImageAnimation { ActionLoader::ImageAnimation {
file, file,
@@ -97,17 +97,17 @@ impl ActionData {
angle, angle,
translation, translation,
time, time,
brightness brightness,
} => { } => {
if let Some(ext) = file.extension() { if let Some(ext) = file.extension() {
if ext.to_string_lossy().to_lowercase() == "png" { if ext.to_string_lossy().to_lowercase() == "png" {
return Ok(ActionData::Animation(AnimeGif::from_png( return Ok(ActionData::Animation(AnimeGif::from_png(
file, *scale, *angle, *translation, *time, *brightness, anime_type file, *scale, *angle, *translation, *time, *brightness, anime_type,
)?)); )?));
} }
} }
ActionData::Animation(AnimeGif::from_gif( ActionData::Animation(AnimeGif::from_gif(
file, *scale, *angle, *translation, *time, *brightness, anime_type file, *scale, *angle, *translation, *time, *brightness, anime_type,
)?) )?)
} }
ActionLoader::Image { ActionLoader::Image {
@@ -116,23 +116,23 @@ impl ActionData {
angle, angle,
translation, translation,
brightness, brightness,
time time,
} => { } => {
match time { match time {
AnimTime::Infinite => { AnimTime::Infinite => {
// If no time then create a plain static image // If no time then create a plain static image
let image = AnimeImage::from_png( let image = AnimeImage::from_png(
file, *scale, *angle, *translation, *brightness, anime_type file, *scale, *angle, *translation, *brightness, anime_type,
)?; )?;
let data = <AnimeDataBuffer>::try_from(&image)?; let data = <AnimeDataBuffer>::try_from(&image)?;
ActionData::Image(Box::new(data)) ActionData::Image(Box::new(data))
} }
_ => ActionData::Animation(AnimeGif::from_png( _ => ActionData::Animation(AnimeGif::from_png(
file, *scale, *angle, *translation, *time, *brightness, anime_type file, *scale, *angle, *translation, *time, *brightness, anime_type,
)?) )?),
} }
} }
ActionLoader::Pause(duration) => ActionData::Pause(*duration) ActionLoader::Pause(duration) => ActionData::Pause(*duration),
}; };
Ok(a) Ok(a)
} }
@@ -171,7 +171,7 @@ impl Sequences {
pub fn iter(&self) -> ActionIterator<'_> { pub fn iter(&self) -> ActionIterator<'_> {
ActionIterator { ActionIterator {
actions: self, actions: self,
next_idx: 0 next_idx: 0,
} }
} }
} }
@@ -179,7 +179,7 @@ impl Sequences {
/// Iteractor helper for iterating over all the actions in `Sequences` /// Iteractor helper for iterating over all the actions in `Sequences`
pub struct ActionIterator<'a> { pub struct ActionIterator<'a> {
actions: &'a Sequences, actions: &'a Sequences,
next_idx: usize next_idx: usize,
} }
impl<'a> Iterator for ActionIterator<'a> { impl<'a> Iterator for ActionIterator<'a> {

View File

@@ -35,7 +35,7 @@ pub enum Brightness {
Low = 1, Low = 1,
#[default] #[default]
Med = 2, Med = 2,
High = 3 High = 3,
} }
impl FromStr for Brightness { impl FromStr for Brightness {
@@ -47,7 +47,7 @@ impl FromStr for Brightness {
"Low" | "low" => Brightness::Low, "Low" | "low" => Brightness::Low,
"Med" | "med" => Brightness::Med, "Med" | "med" => Brightness::Med,
"High" | "high" => Brightness::High, "High" | "high" => Brightness::High,
_ => Brightness::Med _ => Brightness::Med,
}) })
} }
} }
@@ -58,7 +58,7 @@ impl From<u8> for Brightness {
0 => Brightness::Off, 0 => Brightness::Off,
1 => Brightness::Low, 1 => Brightness::Low,
3 => Brightness::High, 3 => Brightness::High,
_ => Brightness::Med _ => Brightness::Med,
} }
} }
} }
@@ -84,7 +84,7 @@ impl From<Brightness> for i32 {
pub enum AnimBooting { pub enum AnimBooting {
#[default] #[default]
GlitchConstruction = 0, GlitchConstruction = 0,
StaticEmergence = 1 StaticEmergence = 1,
} }
impl FromStr for AnimBooting { impl FromStr for AnimBooting {
@@ -94,7 +94,7 @@ impl FromStr for AnimBooting {
match s { match s {
"GlitchConstruction" => Ok(Self::GlitchConstruction), "GlitchConstruction" => Ok(Self::GlitchConstruction),
"StaticEmergence" => Ok(Self::StaticEmergence), "StaticEmergence" => Ok(Self::StaticEmergence),
_ => Err(AnimeError::ParseError(s.to_owned())) _ => Err(AnimeError::ParseError(s.to_owned())),
} }
} }
} }
@@ -104,7 +104,7 @@ impl From<i32> for AnimBooting {
match value { match value {
0 => Self::GlitchConstruction, 0 => Self::GlitchConstruction,
1 => Self::StaticEmergence, 1 => Self::StaticEmergence,
_ => Self::default() _ => Self::default(),
} }
} }
} }
@@ -124,7 +124,7 @@ impl From<AnimBooting> for i32 {
pub enum AnimAwake { pub enum AnimAwake {
#[default] #[default]
BinaryBannerScroll = 0, BinaryBannerScroll = 0,
RogLogoGlitch = 1 RogLogoGlitch = 1,
} }
impl FromStr for AnimAwake { impl FromStr for AnimAwake {
@@ -134,7 +134,7 @@ impl FromStr for AnimAwake {
match s { match s {
"BinaryBannerScroll" => Ok(Self::BinaryBannerScroll), "BinaryBannerScroll" => Ok(Self::BinaryBannerScroll),
"RogLogoGlitch" => Ok(Self::RogLogoGlitch), "RogLogoGlitch" => Ok(Self::RogLogoGlitch),
_ => Err(AnimeError::ParseError(s.to_owned())) _ => Err(AnimeError::ParseError(s.to_owned())),
} }
} }
} }
@@ -144,7 +144,7 @@ impl From<i32> for AnimAwake {
match value { match value {
0 => Self::BinaryBannerScroll, 0 => Self::BinaryBannerScroll,
1 => Self::RogLogoGlitch, 1 => Self::RogLogoGlitch,
_ => Self::default() _ => Self::default(),
} }
} }
} }
@@ -164,7 +164,7 @@ impl From<AnimAwake> for i32 {
pub enum AnimSleeping { pub enum AnimSleeping {
#[default] #[default]
BannerSwipe = 0, BannerSwipe = 0,
Starfield = 1 Starfield = 1,
} }
impl FromStr for AnimSleeping { impl FromStr for AnimSleeping {
@@ -174,7 +174,7 @@ impl FromStr for AnimSleeping {
match s { match s {
"BannerSwipe" => Ok(Self::BannerSwipe), "BannerSwipe" => Ok(Self::BannerSwipe),
"Starfield" => Ok(Self::Starfield), "Starfield" => Ok(Self::Starfield),
_ => Err(AnimeError::ParseError(s.to_owned())) _ => Err(AnimeError::ParseError(s.to_owned())),
} }
} }
} }
@@ -184,7 +184,7 @@ impl From<i32> for AnimSleeping {
match value { match value {
0 => Self::BannerSwipe, 0 => Self::BannerSwipe,
1 => Self::Starfield, 1 => Self::Starfield,
_ => Self::default() _ => Self::default(),
} }
} }
} }
@@ -204,7 +204,7 @@ impl From<AnimSleeping> for i32 {
pub enum AnimShutdown { pub enum AnimShutdown {
#[default] #[default]
GlitchOut = 0, GlitchOut = 0,
SeeYa = 1 SeeYa = 1,
} }
impl FromStr for AnimShutdown { impl FromStr for AnimShutdown {
@@ -214,7 +214,7 @@ impl FromStr for AnimShutdown {
match s { match s {
"GlitchOut" => Ok(Self::GlitchOut), "GlitchOut" => Ok(Self::GlitchOut),
"SeeYa" => Ok(Self::SeeYa), "SeeYa" => Ok(Self::SeeYa),
_ => Err(AnimeError::ParseError(s.to_owned())) _ => Err(AnimeError::ParseError(s.to_owned())),
} }
} }
} }
@@ -224,7 +224,7 @@ impl From<i32> for AnimShutdown {
match value { match value {
0 => Self::GlitchOut, 0 => Self::GlitchOut,
1 => Self::SeeYa, 1 => Self::SeeYa,
_ => Self::default() _ => Self::default(),
} }
} }
} }
@@ -243,7 +243,7 @@ impl From<AnimShutdown> for i32 {
#[inline] #[inline]
pub fn get_anime_type() -> AnimeType { pub fn get_anime_type() -> AnimeType {
let dmi = DMIID::new().unwrap_or_default(); let dmi = DMIID::new().unwrap_or_default();
let board_name = dmi.board_name; let board_name = dmi.board_name.to_uppercase();
if board_name.contains("GA401I") || board_name.contains("GA401Q") { if board_name.contains("GA401I") || board_name.contains("GA401Q") {
AnimeType::GA401 AnimeType::GA401
@@ -251,6 +251,10 @@ pub fn get_anime_type() -> AnimeType {
AnimeType::GA402 AnimeType::GA402
} else if board_name.contains("GU604V") { } else if board_name.contains("GU604V") {
AnimeType::GU604 AnimeType::GU604
} else if board_name.contains("G635L") {
AnimeType::G635L
} else if board_name.contains("G835L") {
AnimeType::G835L
} else { } else {
AnimeType::Unsupported AnimeType::Unsupported
} }
@@ -326,7 +330,7 @@ pub const fn pkt_set_builtin_animations(
boot: AnimBooting, boot: AnimBooting,
awake: AnimAwake, awake: AnimAwake,
sleep: AnimSleeping, sleep: AnimSleeping,
shutdown: AnimShutdown shutdown: AnimShutdown,
) -> [u8; PACKET_SIZE] { ) -> [u8; PACKET_SIZE] {
let mut pkt = [0; PACKET_SIZE]; let mut pkt = [0; PACKET_SIZE];
pkt[0] = DEV_PAGE; pkt[0] = DEV_PAGE;

View File

@@ -52,7 +52,7 @@ mod tests {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]; ];
let pkt1_check = [ let pkt1_check = [
0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -100,7 +100,7 @@ mod tests {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]; ];
let mut matrix = AnimeImage::new( let mut matrix = AnimeImage::new(
@@ -110,7 +110,7 @@ mod tests {
0.0, 0.0,
vec![Pixel::default(); 1000], vec![Pixel::default(); 1000],
100, 100,
AnimeType::GA401 AnimeType::GA401,
) )
.unwrap(); .unwrap();
matrix.edge_outline(); matrix.edge_outline();
@@ -175,7 +175,7 @@ mod tests {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]; ];
let pkt1_check = [ let pkt1_check = [
0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -223,7 +223,7 @@ mod tests {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]; ];
let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));

View File

@@ -52,7 +52,7 @@ mod tests {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]; ];
let pkt1_check = [ let pkt1_check = [
0x5e, 0xc0, 0x2, 0x74, 0x2, 0x73, 0x2, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x5e, 0xc0, 0x2, 0x74, 0x2, 0x73, 0x2, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
@@ -100,7 +100,7 @@ mod tests {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]; ];
let pkt2_check = [ let pkt2_check = [
0x5e, 0xc0, 0x2, 0xe7, 0x4, 0x73, 0x2, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x5e, 0xc0, 0x2, 0xe7, 0x4, 0x73, 0x2, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
@@ -148,7 +148,7 @@ mod tests {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]; ];
let mut matrix = AnimeImage::new( let mut matrix = AnimeImage::new(
@@ -158,7 +158,7 @@ mod tests {
0.0, 0.0,
vec![Pixel::default(); 1000], vec![Pixel::default(); 1000],
100, 100,
AnimeType::GA402 AnimeType::GA402,
) )
.unwrap(); .unwrap();
matrix.edge_outline(); matrix.edge_outline();
@@ -218,7 +218,7 @@ mod tests {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]; ];
let pkt1_check = [ let pkt1_check = [
0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
@@ -266,7 +266,7 @@ mod tests {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]; ];
let pkt2_check = [ let pkt2_check = [
0x5e, 0xc0, 0x02, 0xe7, 0x04, 0x73, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x5e, 0xc0, 0x02, 0xe7, 0x04, 0x73, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
@@ -314,7 +314,7 @@ mod tests {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]; ];
let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
@@ -378,7 +378,7 @@ mod tests {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]; ];
let pkt1_check = [ let pkt1_check = [
0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -426,7 +426,7 @@ mod tests {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]; ];
let pkt2_check = [ let pkt2_check = [
0x5e, 0xc0, 0x02, 0xe7, 0x04, 0x73, 0x02, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x5e, 0xc0, 0x02, 0xe7, 0x04, 0x73, 0x02, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
@@ -474,7 +474,7 @@ mod tests {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]; ];
let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));

View File

@@ -52,7 +52,7 @@ mod tests {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]; ];
let pkt1_check = [ let pkt1_check = [
0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -100,7 +100,7 @@ mod tests {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]; ];
let pkt2_check = [ let pkt2_check = [
0x5e, 0xc0, 0x02, 0xe7, 0x04, 0x73, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0xc0, 0x02, 0xe7, 0x04, 0x73, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -148,7 +148,7 @@ mod tests {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]; ];
let mut matrix = AnimeImage::new( let mut matrix = AnimeImage::new(
@@ -158,7 +158,7 @@ mod tests {
0.0, 0.0,
vec![Pixel::default(); 1000], vec![Pixel::default(); 1000],
100, 100,
AnimeType::GU604 AnimeType::GU604,
) )
.unwrap(); .unwrap();
matrix.edge_outline(); matrix.edge_outline();
@@ -218,7 +218,7 @@ mod tests {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]; ];
let pkt1_check = [ let pkt1_check = [
0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -266,7 +266,7 @@ mod tests {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]; ];
let pkt2_check = [ let pkt2_check = [
0x5e, 0xc0, 0x02, 0xe7, 0x04, 0x73, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0xc0, 0x02, 0xe7, 0x04, 0x73, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -314,7 +314,7 @@ mod tests {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]; ];
let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));

View File

@@ -5,7 +5,7 @@
layout_name: "fa506i", layout_name: "fa506i",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -14,7 +14,7 @@
layout_name: "fa506i", layout_name: "fa506i",
basic_modes: [Static, Breathe, RainbowCycle], basic_modes: [Static, Breathe, RainbowCycle],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -23,7 +23,7 @@
layout_name: "fa506i", layout_name: "fa506i",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -32,16 +32,43 @@
layout_name: "fa507", layout_name: "fa507",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
device_name: "FA617NS", device_name: "FA617NS",
product_id: "", product_id: "",
layout_name: "fa617ns", layout_name: "fa507",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard],
),
(
device_name: "FA617NT",
product_id: "",
layout_name: "fa507",
basic_modes: [Static, Breathe, Pulse],
basic_zones: [],
advanced_type: r#None,
power_zones: [Keyboard],
),
(
device_name: "FA617XS",
product_id: "",
layout_name: "fa507",
basic_modes: [Static, Breathe, Pulse],
basic_zones: [],
advanced_type: r#None,
power_zones: [Keyboard],
),
(
device_name: "FA617XT",
product_id: "",
layout_name: "fa507",
basic_modes: [Static, Breathe, Pulse],
basic_zones: [],
advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -50,7 +77,7 @@
layout_name: "fx505d", layout_name: "fx505d",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -59,7 +86,7 @@
layout_name: "fa506i", layout_name: "fa506i",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -68,7 +95,7 @@
layout_name: "fa506i", layout_name: "fa506i",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -77,7 +104,7 @@
layout_name: "fa506i", layout_name: "fa506i",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -86,7 +113,25 @@
layout_name: "fa506i", layout_name: "fa506i",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard],
),
(
device_name: "FX607J",
product_id: "",
layout_name: "fa506i",
basic_modes: [Static, Breathe, Pulse],
basic_zones: [],
advanced_type: r#None,
power_zones: [Keyboard],
),
(
device_name: "FX607V",
product_id: "",
layout_name: "fa506i",
basic_modes: [Static, Breathe, RainbowCycle, Pulse],
basic_zones: [],
advanced_type: Zoned([SingleZone]),
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -95,7 +140,7 @@
layout_name: "fa506i", layout_name: "fa506i",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -104,7 +149,16 @@
layout_name: "fx505d", layout_name: "fx505d",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard],
),
(
device_name: "FX706H",
product_id: "",
layout_name: "fx505d",
basic_modes: [Static, Breathe, RainbowCycle],
basic_zones: [],
advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -113,7 +167,7 @@
layout_name: "g512", layout_name: "g512",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard, Lightbar], power_zones: [Keyboard, Lightbar],
), ),
( (
@@ -131,7 +185,7 @@
layout_name: "g513i", layout_name: "g513i",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard, Lightbar], power_zones: [Keyboard, Lightbar],
), ),
( (
@@ -161,13 +215,22 @@
advanced_type: Zoned([ZonedKbLeft, ZonedKbLeftMid, ZonedKbRightMid, ZonedKbRight, LightbarRight, LightbarRightCorner, LightbarRightBottom, LightbarLeftBottom, LightbarLeftCorner, LightbarLeft]), advanced_type: Zoned([ZonedKbLeft, ZonedKbLeftMid, ZonedKbRightMid, ZonedKbRight, LightbarRight, LightbarRightCorner, LightbarRightBottom, LightbarLeftBottom, LightbarLeftCorner, LightbarLeft]),
power_zones: [Keyboard, Lightbar], power_zones: [Keyboard, Lightbar],
), ),
(
device_name: "G513RW",
product_id: "",
layout_name: "g513i-per-key",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
basic_zones: [],
advanced_type: PerKey,
power_zones: [Keyboard, Lightbar],
),
( (
device_name: "G531G", device_name: "G531G",
product_id: "", product_id: "",
layout_name: "gx502", layout_name: "gx502",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -176,7 +239,7 @@
layout_name: "gx502", layout_name: "gx502",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -215,13 +278,31 @@
advanced_type: PerKey, advanced_type: PerKey,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
(
device_name: "G614FR",
product_id: "",
layout_name: "g634j-per-key",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
basic_zones: [],
advanced_type: PerKey,
power_zones: [Keyboard, Lightbar, Logo],
),
( (
device_name: "G614J", device_name: "G614J",
product_id: "", product_id: "",
layout_name: "g634j-per-key", layout_name: "g634j-per-key",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard, Lightbar],
),
(
device_name: "G614JIR",
product_id: "",
layout_name: "g513i-per-key",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
basic_zones: [],
advanced_type: PerKey,
power_zones: [Keyboard, Lightbar], power_zones: [Keyboard, Lightbar],
), ),
( (
@@ -230,16 +311,25 @@
layout_name: "g634j-per-key", layout_name: "g634j-per-key",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard, Lightbar], power_zones: [Keyboard, Lightbar],
), ),
(
device_name: "G614JU",
product_id: "",
layout_name: "g634j-per-key",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
basic_zones: [],
advanced_type: PerKey,
power_zones: [Keyboard, Lightbar, Logo],
),
( (
device_name: "G614JZ", device_name: "G614JZ",
product_id: "", product_id: "",
layout_name: "g634j-per-key", layout_name: "g634j-per-key",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard, Lightbar], power_zones: [Keyboard, Lightbar],
), ),
( (
@@ -251,13 +341,22 @@
advanced_type: PerKey, advanced_type: PerKey,
power_zones: [Keyboard, Lightbar, Logo, RearGlow], power_zones: [Keyboard, Lightbar, Logo, RearGlow],
), ),
(
device_name: "G635L",
product_id: "",
layout_name: "g635l-per-key",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
basic_zones: [],
advanced_type: PerKey,
power_zones: [Keyboard, Lightbar, Logo],
),
( (
device_name: "G712LI", device_name: "G712LI",
product_id: "", product_id: "",
layout_name: "gl503", layout_name: "gl503",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -266,7 +365,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -275,7 +374,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -284,7 +383,7 @@
layout_name: "gx502", layout_name: "gx502",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard, Lightbar], power_zones: [Keyboard, Lightbar],
), ),
( (
@@ -293,7 +392,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard, Lightbar], power_zones: [Keyboard, Lightbar],
), ),
( (
@@ -302,7 +401,7 @@
layout_name: "gx502", layout_name: "gx502",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard, Lightbar], power_zones: [Keyboard, Lightbar],
), ),
( (
@@ -311,7 +410,7 @@
layout_name: "gx502", layout_name: "gx502",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard, Lightbar], power_zones: [Keyboard, Lightbar],
), ),
( (
@@ -347,7 +446,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -365,7 +464,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4, BarLeft, BarRight], basic_zones: [Key1, Key2, Key3, Key4, BarLeft, BarRight],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard, Lightbar], power_zones: [Keyboard, Lightbar],
), ),
( (
@@ -383,7 +482,7 @@
layout_name: "g533q", layout_name: "g533q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -392,7 +491,7 @@
layout_name: "g533q", layout_name: "g533q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -401,7 +500,7 @@
layout_name: "g533q", layout_name: "g533q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -449,6 +548,15 @@
advanced_type: PerKey, advanced_type: PerKey,
power_zones: [Keyboard, Lightbar], power_zones: [Keyboard, Lightbar],
), ),
(
device_name: "G815L",
product_id: "",
layout_name: "g814ji-per-key",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
basic_zones: [],
advanced_type: PerKey,
power_zones: [Keyboard, Lightbar],
),
( (
device_name: "G834J", device_name: "G834J",
product_id: "", product_id: "",
@@ -464,7 +572,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -473,7 +581,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -482,7 +590,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -491,7 +599,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -500,7 +608,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -509,7 +617,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -518,7 +626,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -527,7 +635,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -536,7 +644,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -545,7 +653,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -554,7 +662,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -572,7 +680,7 @@
layout_name: "gl503", layout_name: "gl503",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -581,7 +689,7 @@
layout_name: "gl503", layout_name: "gl503",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -590,7 +698,7 @@
layout_name: "gl503", layout_name: "gl503",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4, Logo, BarLeft, BarRight], basic_zones: [Key1, Key2, Key3, Key4, Logo, BarLeft, BarRight],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -608,7 +716,7 @@
layout_name: "g533q", layout_name: "g533q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -617,7 +725,7 @@
layout_name: "gl503", layout_name: "gl503",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -626,7 +734,7 @@
layout_name: "fa507", layout_name: "fa507",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -674,6 +782,15 @@
advanced_type: Zoned([SingleZone]), advanced_type: Zoned([SingleZone]),
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
(
device_name: "GU605C",
product_id: "",
layout_name: "ga401q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [],
advanced_type: Zoned([SingleZone]),
power_zones: [Keyboard],
),
( (
device_name: "GU605M", device_name: "GU605M",
product_id: "", product_id: "",
@@ -689,7 +806,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -698,7 +815,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -707,7 +824,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -716,7 +833,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -734,7 +851,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -752,7 +869,7 @@
layout_name: "gx531-per-key", layout_name: "gx531-per-key",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [Key1, Key2, Key3, Key4], basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -806,7 +923,7 @@
layout_name: "gx531-per-key", layout_name: "gx531-per-key",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -815,7 +932,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -824,7 +941,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -833,8 +950,8 @@
layout_name: "", layout_name: "",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [None], power_zones: [r#None],
), ),
( (
device_name: "GZ301Z", device_name: "GZ301Z",
@@ -842,7 +959,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Keyboard], power_zones: [Keyboard],
), ),
( (
@@ -851,7 +968,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Ally], power_zones: [Ally],
), ),
( (
@@ -860,7 +977,7 @@
layout_name: "ga401q", layout_name: "ga401q",
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse], basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: None, advanced_type: r#None,
power_zones: [Ally], power_zones: [Ally],
), ),
]) ])

View File

@@ -0,0 +1,375 @@
(
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,
),
"regular_spacing": Blank(
width: 1.2,
height: 0.0,
),
"rog_row": Led(
width: 1.0,
height: 0.7,
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_space": Blank(
width: 0.6,
height: 0.0,
),
"backspace": Led(
width: 2.2,
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,
),
"backslash": 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: 2.0,
height: 1.0,
pad_left: 0.1,
pad_right: 0.1,
pad_top: 0.1,
pad_bottom: 0.1,
),
"return": Led(
width: 2.4,
height: 1.0,
pad_left: 0.1,
pad_right: 0.1,
pad_top: 0.1,
pad_bottom: 0.1,
),
"lshift": Led(
width: 2.6,
height: 1.0,
pad_left: 0.1,
pad_right: 0.1,
pad_top: 0.1,
pad_bottom: 0.1,
),
"rshift": Led(
width: 3.0,
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.8,
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: 0.8,
height: 0.8,
pad_left: 1.1,
pad_right: 1.1,
pad_top: 0.1,
pad_bottom: 0.1,
),
"arrows_spacer": Blank(
width: 15.0,
height: 0.0,
),
"arrows": Led(
width: 0.8,
height: 0.8,
pad_left: 0.1,
pad_right: 0.1,
pad_top: -0.1,
pad_bottom: 0.1,
),
"row_end_spacing": Blank(
width: 0.4,
height: 0.0,
),
"lid_logo": Led(
width: 2.6,
height: 1.2,
pad_left: 0.1,
pad_right: 0.1,
pad_top: 0.8,
pad_bottom: 0.0,
),
"lightbar_left": Led(
width: 0.6,
height: 3.6,
pad_left: -1.2,
pad_right: 0.2,
pad_top: -3.0,
pad_bottom: 0.3,
),
"lightbar_corner_left": Led(
width: 0.8,
height: 0.6,
pad_left: -0.6,
pad_right: 0.2,
pad_top: 0.8,
pad_bottom: 0.0,
),
"lightbar_bottom": Led(
width: 12.6,
height: 0.5,
pad_left: -0.1,
pad_right: -0.1,
pad_top: 0.8,
pad_bottom: 0.0,
),
"lightbar_corner_right": Led(
width: 0.8,
height: 0.6,
pad_left: 0.0,
pad_right: 0.2,
pad_top: 0.8,
pad_bottom: 0.0,
),
"lightbar_right": Led(
width: 0.6,
height: 3.6,
pad_left: -0.8,
pad_right: 0.2,
pad_top: -3.0,
pad_bottom: 0.3,
),
},
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_right: 0.1,
pad_top: 0.1,
pad_bottom: 0.1,
row: [
(Esc, "regular"),
(Spacing, "regular_spacing"),
(F1, "regular"),
(F2, "regular"),
(F3, "regular"),
(F4, "regular"),
(Spacing, "func_space"),
(F5, "regular"),
(F6, "regular"),
(F7, "regular"),
(F8, "regular"),
(Spacing, "func_space"),
(F9, "regular"),
(F10, "regular"),
(F11, "regular"),
(F12, "regular"),
(Spacing, "row_end_spacing"),
(Del, "regular"), // Should be super/insert
],
),
(
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, "row_end_spacing"),
(MediaPlay, "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, "backslash"),
(Spacing, "row_end_spacing"),
(MediaStop, "regular"),
],
),
(
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, "row_end_spacing"),
(MediaNext, "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, "row_end_spacing"),
(MediaPrev, "regular"),
],
),
(
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, "rctrl"),
(Up, "up_arrow"),
(Spacing, "row_end_spacing"),
(PrtSc, "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: 6.5,
pad_right: 6.5,
pad_top: 0.2,
pad_bottom: 0.1,
row: [
(LidLogo, "lid_logo"),
],
),
(
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"),
],
),
],
)

View File

@@ -54,7 +54,7 @@ pub struct LedSupportData {
#[serde(default)] #[serde(default)]
pub advanced_type: AdvancedAuraType, pub advanced_type: AdvancedAuraType,
/// If empty will default to `Keyboard` power zone /// If empty will default to `Keyboard` power zone
pub power_zones: Vec<PowerZones> pub power_zones: Vec<PowerZones>,
} }
impl LedSupportData { impl LedSupportData {
@@ -116,7 +116,7 @@ impl LedSupportFile {
basic_modes: vec![AuraModeNum::Static], basic_modes: vec![AuraModeNum::Static],
basic_zones: vec![], basic_zones: vec![],
advanced_type: AdvancedAuraType::None, advanced_type: AdvancedAuraType::None,
power_zones: vec![PowerZones::Keyboard] power_zones: vec![PowerZones::Keyboard],
} }
} }
@@ -164,6 +164,25 @@ impl LedSupportFile {
return Some(data); return Some(data);
} }
// If the system-wide files were not found (typical in CI or
// development environments), attempt to load the bundled
// `data/aura_support.ron` from the crate so tests and local runs
// behave the same as when the package is installed.
// Attempt to load a bundled `aura_support.ron` included at compile time.
// Using `include_str!` ensures the data is available regardless of
// runtime `CARGO_MANIFEST_DIR` or CI environment differences.
let bundled_buf = include_str!("../data/aura_support.ron");
if !bundled_buf.is_empty() {
if let Ok(tmp) = ron::from_str::<LedSupportFile>(bundled_buf) {
data.0.append(&mut tmp.0.clone());
data.0.sort_by(|a, b| a.device_name.cmp(&b.device_name));
info!("Loaded bundled LED support data (embedded)");
return Some(data);
} else {
warn!("Could not parse embedded bundled data file");
}
}
warn!("Does {} exist?", ASUS_LED_MODE_USER_CONF); warn!("Does {} exist?", ASUS_LED_MODE_USER_CONF);
None None
} }
@@ -200,7 +219,7 @@ mod tests {
power_zones: vec![ power_zones: vec![
PowerZones::Keyboard, PowerZones::Keyboard,
PowerZones::RearGlow, PowerZones::RearGlow,
] ],
}; };
assert!(ron::to_string(&led).is_ok()); assert!(ron::to_string(&led).is_ok());

View File

@@ -19,7 +19,7 @@ pub enum LedBrightness {
Low = 1, Low = 1,
#[default] #[default]
Med = 2, Med = 2,
High = 3 High = 3,
} }
impl LedBrightness { impl LedBrightness {
@@ -28,7 +28,7 @@ impl LedBrightness {
Self::Off => Self::Low, Self::Off => Self::Low,
Self::Low => Self::Med, Self::Low => Self::Med,
Self::Med => Self::High, Self::Med => Self::High,
Self::High => Self::Off Self::High => Self::Off,
} }
} }
@@ -37,7 +37,7 @@ impl LedBrightness {
Self::Off => Self::High, Self::Off => Self::High,
Self::Low => Self::Off, Self::Low => Self::Off,
Self::Med => Self::Low, Self::Med => Self::Low,
Self::High => Self::Med Self::High => Self::Med,
} }
} }
} }
@@ -48,7 +48,7 @@ impl From<u8> for LedBrightness {
0 => LedBrightness::Off, 0 => LedBrightness::Off,
1 => LedBrightness::Low, 1 => LedBrightness::Low,
3 => LedBrightness::High, 3 => LedBrightness::High,
_ => LedBrightness::Med _ => LedBrightness::Med,
} }
} }
} }
@@ -72,7 +72,7 @@ impl From<i32> for LedBrightness {
1 => LedBrightness::Low, 1 => LedBrightness::Low,
2 => LedBrightness::Med, 2 => LedBrightness::Med,
3 => LedBrightness::High, 3 => LedBrightness::High,
_ => LedBrightness::Med _ => LedBrightness::Med,
} }
} }
} }
@@ -82,7 +82,7 @@ impl From<i32> for LedBrightness {
pub struct Colour { pub struct Colour {
pub r: u8, pub r: u8,
pub g: u8, pub g: u8,
pub b: u8 pub b: u8,
} }
impl Default for Colour { impl Default for Colour {
@@ -110,7 +110,7 @@ impl From<&[f32; 3]> for Colour {
Self { Self {
r: (255.0 * c[0]) as u8, r: (255.0 * c[0]) as u8,
g: (255.0 * c[1]) as u8, g: (255.0 * c[1]) as u8,
b: (255.0 * c[2]) as u8 b: (255.0 * c[2]) as u8,
} }
} }
} }
@@ -120,7 +120,7 @@ impl From<Colour> for [f32; 3] {
[ [
c.r as f32 / 255.0, c.r as f32 / 255.0,
c.g as f32 / 255.0, c.g as f32 / 255.0,
c.b as f32 / 255.0 c.b as f32 / 255.0,
] ]
} }
} }
@@ -130,7 +130,7 @@ impl From<&[u8; 3]> for Colour {
Self { Self {
r: c[0], r: c[0],
g: c[1], g: c[1],
b: c[2] b: c[2],
} }
} }
} }
@@ -138,7 +138,7 @@ impl From<&[u8; 3]> for Colour {
impl From<Colour> for [u8; 3] { impl From<Colour> for [u8; 3] {
fn from(c: Colour) -> Self { fn from(c: Colour) -> Self {
[ [
c.r, c.g, c.b c.r, c.g, c.b,
] ]
} }
} }
@@ -153,7 +153,7 @@ pub enum Speed {
Low = 0xe1, Low = 0xe1,
#[default] #[default]
Med = 0xeb, Med = 0xeb,
High = 0xf5 High = 0xf5,
} }
impl FromStr for Speed { impl FromStr for Speed {
@@ -165,7 +165,7 @@ impl FromStr for Speed {
"low" => Ok(Speed::Low), "low" => Ok(Speed::Low),
"med" => Ok(Speed::Med), "med" => Ok(Speed::Med),
"high" => Ok(Speed::High), "high" => Ok(Speed::High),
_ => Err(Error::ParseSpeed) _ => Err(Error::ParseSpeed),
} }
} }
} }
@@ -175,7 +175,7 @@ impl From<i32> for Speed {
match value { match value {
0 => Self::Low, 0 => Self::Low,
2 => Self::High, 2 => Self::High,
_ => Self::Med _ => Self::Med,
} }
} }
} }
@@ -185,7 +185,7 @@ impl From<Speed> for i32 {
match value { match value {
Speed::Low => 0, Speed::Low => 0,
Speed::Med => 1, Speed::Med => 1,
Speed::High => 2 Speed::High => 2,
} }
} }
} }
@@ -195,7 +195,7 @@ impl From<Speed> for u8 {
match s { match s {
Speed::Low => 0, Speed::Low => 0,
Speed::Med => 1, Speed::Med => 1,
Speed::High => 2 Speed::High => 2,
} }
} }
} }
@@ -213,7 +213,7 @@ pub enum Direction {
Right = 0, Right = 0,
Left = 1, Left = 1,
Up = 2, Up = 2,
Down = 3 Down = 3,
} }
impl FromStr for Direction { impl FromStr for Direction {
@@ -226,7 +226,7 @@ impl FromStr for Direction {
"up" => Ok(Direction::Up), "up" => Ok(Direction::Up),
"down" => Ok(Direction::Down), "down" => Ok(Direction::Down),
"left" => Ok(Direction::Left), "left" => Ok(Direction::Left),
_ => Err(Error::ParseDirection) _ => Err(Error::ParseDirection),
} }
} }
} }
@@ -237,7 +237,7 @@ impl From<i32> for Direction {
1 => Self::Left, 1 => Self::Left,
2 => Self::Up, 2 => Self::Up,
3 => Self::Down, 3 => Self::Down,
_ => Self::Right _ => Self::Right,
} }
} }
} }
@@ -270,7 +270,7 @@ pub enum AuraModeNum {
Ripple = 8, Ripple = 8,
Pulse = 10, Pulse = 10,
Comet = 11, Comet = 11,
Flash = 12 Flash = 12,
} }
impl Display for AuraModeNum { impl Display for AuraModeNum {
@@ -299,7 +299,7 @@ impl From<&AuraModeNum> for &str {
AuraModeNum::Ripple => "Ripple", AuraModeNum::Ripple => "Ripple",
AuraModeNum::Pulse => "Pulse", AuraModeNum::Pulse => "Pulse",
AuraModeNum::Comet => "Comet", AuraModeNum::Comet => "Comet",
AuraModeNum::Flash => "Flash" AuraModeNum::Flash => "Flash",
} }
} }
} }
@@ -317,7 +317,7 @@ impl From<&str> for AuraModeNum {
"Pulse" => AuraModeNum::Pulse, "Pulse" => AuraModeNum::Pulse,
"Comet" => AuraModeNum::Comet, "Comet" => AuraModeNum::Comet,
"Flash" => AuraModeNum::Flash, "Flash" => AuraModeNum::Flash,
_ => AuraModeNum::Static _ => AuraModeNum::Static,
} }
} }
} }
@@ -336,7 +336,7 @@ impl From<u8> for AuraModeNum {
10 => AuraModeNum::Pulse, 10 => AuraModeNum::Pulse,
11 => AuraModeNum::Comet, 11 => AuraModeNum::Comet,
12 => AuraModeNum::Flash, 12 => AuraModeNum::Flash,
_ => AuraModeNum::Static _ => AuraModeNum::Static,
} }
} }
} }
@@ -359,6 +359,12 @@ impl From<AuraEffect> for AuraModeNum {
} }
} }
#[cfg(feature = "dbus")]
impl zbus::zvariant::Basic for AuraModeNum {
const SIGNATURE_CHAR: char = 'u';
const SIGNATURE_STR: &'static str = "u";
}
/// Base effects have no zoning, while multizone is 1-4 /// Base effects have no zoning, while multizone is 1-4
#[cfg_attr( #[cfg_attr(
feature = "dbus", feature = "dbus",
@@ -383,7 +389,7 @@ pub enum AuraZone {
/// The left part of a lightbar (typically on the front of laptop) /// The left part of a lightbar (typically on the front of laptop)
BarLeft = 6, BarLeft = 6,
/// The right part of a lightbar /// The right part of a lightbar
BarRight = 7 BarRight = 7,
} }
impl FromStr for AuraZone { impl FromStr for AuraZone {
@@ -400,7 +406,7 @@ impl FromStr for AuraZone {
"5" | "logo" => Ok(AuraZone::Logo), "5" | "logo" => Ok(AuraZone::Logo),
"6" | "lightbar-left" => Ok(AuraZone::BarLeft), "6" | "lightbar-left" => Ok(AuraZone::BarLeft),
"7" | "lightbar-right" => Ok(AuraZone::BarRight), "7" | "lightbar-right" => Ok(AuraZone::BarRight),
_ => Err(Error::ParseSpeed) _ => Err(Error::ParseSpeed),
} }
} }
} }
@@ -415,7 +421,7 @@ impl From<i32> for AuraZone {
5 => Self::Logo, 5 => Self::Logo,
6 => Self::BarLeft, 6 => Self::BarLeft,
7 => Self::BarRight, 7 => Self::BarRight,
_ => Self::default() _ => Self::default(),
} }
} }
} }
@@ -445,7 +451,7 @@ pub struct AuraEffect {
/// One of three speeds for modes that support speed (most that animate) /// One of three speeds for modes that support speed (most that animate)
pub speed: Speed, pub speed: Speed,
/// Up, down, left, right. Only Rainbow mode seems to use this /// Up, down, left, right. Only Rainbow mode seems to use this
pub direction: Direction pub direction: Direction,
} }
impl AuraEffect { impl AuraEffect {
@@ -481,7 +487,7 @@ impl Default for AuraEffect {
colour1: Colour { r: 166, g: 0, b: 0 }, colour1: Colour { r: 166, g: 0, b: 0 },
colour2: Colour { r: 0, g: 0, b: 0 }, colour2: Colour { r: 0, g: 0, b: 0 },
speed: Speed::Med, speed: Speed::Med,
direction: Direction::Right direction: Direction::Right,
} }
} }
} }
@@ -541,7 +547,7 @@ impl From<&AuraEffect> for Vec<u8> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{ use crate::{
AuraEffect, AuraModeNum, AuraZone, Colour, Direction, Speed, AURA_LAPTOP_LED_MSG_LEN AuraEffect, AuraModeNum, AuraZone, Colour, Direction, Speed, AURA_LAPTOP_LED_MSG_LEN,
}; };
#[test] #[test]
@@ -552,18 +558,18 @@ mod tests {
colour1: Colour { colour1: Colour {
r: 0xff, r: 0xff,
g: 0x11, g: 0x11,
b: 0xdd b: 0xdd,
}, },
colour2: Colour::default(), colour2: Colour::default(),
speed: Speed::Med, speed: Speed::Med,
direction: Direction::Right direction: Direction::Right,
}; };
let ar = <[u8; AURA_LAPTOP_LED_MSG_LEN]>::from(&st); let ar = <[u8; AURA_LAPTOP_LED_MSG_LEN]>::from(&st);
println!("{:02x?}", ar); println!("{:02x?}", ar);
let check = [ let check = [
0x5d, 0xb3, 0x0, 0x0, 0xff, 0x11, 0xdd, 0xeb, 0x0, 0x0, 0xa6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5d, 0xb3, 0x0, 0x0, 0xff, 0x11, 0xdd, 0xeb, 0x0, 0x0, 0xa6, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0 0x0,
]; ];
assert_eq!(ar, check); assert_eq!(ar, check);
} }
@@ -576,15 +582,15 @@ mod tests {
colour1: Colour { colour1: Colour {
r: 0xff, r: 0xff,
g: 0, g: 0,
b: 0 b: 0,
}, },
colour2: Colour { r: 0, g: 0, b: 0 }, colour2: Colour { r: 0, g: 0, b: 0 },
speed: Speed::Low, speed: Speed::Low,
direction: Direction::Left direction: Direction::Left,
}; };
let capture = [ let capture = [
0x5d, 0xb3, 0x01, 0x00, 0xff, 0x00, 0x00, 0xe1, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5d, 0xb3, 0x01, 0x00, 0xff, 0x00, 0x00, 0xe1, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0 0x0, 0x0,
]; ];
assert_eq!( assert_eq!(
<[u8; AURA_LAPTOP_LED_MSG_LEN]>::from(&st)[..9], <[u8; AURA_LAPTOP_LED_MSG_LEN]>::from(&st)[..9],
@@ -595,11 +601,11 @@ mod tests {
st.colour1 = Colour { st.colour1 = Colour {
r: 0xff, r: 0xff,
g: 0xff, g: 0xff,
b: 0 b: 0,
}; };
let capture = [ let capture = [
0x5d, 0xb3, 0x02, 0x00, 0xff, 0xff, 0x00, 0xe1, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5d, 0xb3, 0x02, 0x00, 0xff, 0xff, 0x00, 0xe1, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0 0x0, 0x0,
]; ];
assert_eq!( assert_eq!(
<[u8; AURA_LAPTOP_LED_MSG_LEN]>::from(&st)[..9], <[u8; AURA_LAPTOP_LED_MSG_LEN]>::from(&st)[..9],
@@ -610,11 +616,11 @@ mod tests {
st.colour1 = Colour { st.colour1 = Colour {
r: 0, r: 0,
g: 0xff, g: 0xff,
b: 0xff b: 0xff,
}; };
let capture = [ let capture = [
0x5d, 0xb3, 0x03, 0x00, 0x00, 0xff, 0xff, 0xe1, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5d, 0xb3, 0x03, 0x00, 0x00, 0xff, 0xff, 0xe1, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0 0x0, 0x0,
]; ];
assert_eq!( assert_eq!(
<[u8; AURA_LAPTOP_LED_MSG_LEN]>::from(&st)[..9], <[u8; AURA_LAPTOP_LED_MSG_LEN]>::from(&st)[..9],
@@ -625,11 +631,11 @@ mod tests {
st.colour1 = Colour { st.colour1 = Colour {
r: 0xff, r: 0xff,
g: 0x00, g: 0x00,
b: 0xff b: 0xff,
}; };
let capture = [ let capture = [
0x5d, 0xb3, 0x04, 0x00, 0xff, 0x00, 0xff, 0xe1, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5d, 0xb3, 0x04, 0x00, 0xff, 0x00, 0xff, 0xe1, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0 0x0, 0x0,
]; ];
assert_eq!( assert_eq!(
<[u8; AURA_LAPTOP_LED_MSG_LEN]>::from(&st)[..9], <[u8; AURA_LAPTOP_LED_MSG_LEN]>::from(&st)[..9],
@@ -640,11 +646,11 @@ mod tests {
st.colour1 = Colour { st.colour1 = Colour {
r: 0x2c, r: 0x2c,
g: 0xff, g: 0xff,
b: 0x00 b: 0x00,
}; };
let capture = [ let capture = [
0x5d, 0xb3, 0x05, 0x00, 0x2c, 0xff, 0x00, 0xe1, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5d, 0xb3, 0x05, 0x00, 0x2c, 0xff, 0x00, 0xe1, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0 0x0, 0x0,
]; ];
assert_eq!( assert_eq!(
<[u8; AURA_LAPTOP_LED_MSG_LEN]>::from(&st)[..9], <[u8; AURA_LAPTOP_LED_MSG_LEN]>::from(&st)[..9],
@@ -655,11 +661,11 @@ mod tests {
st.colour1 = Colour { st.colour1 = Colour {
r: 0xff, r: 0xff,
g: 0x00, g: 0x00,
b: 0x00 b: 0x00,
}; };
let capture = [ let capture = [
0x5d, 0xb3, 0x06, 0x00, 0xff, 0x00, 0x00, 0xe1, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5d, 0xb3, 0x06, 0x00, 0xff, 0x00, 0x00, 0xe1, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0 0x0, 0x0,
]; ];
assert_eq!( assert_eq!(
<[u8; AURA_LAPTOP_LED_MSG_LEN]>::from(&st)[..9], <[u8; AURA_LAPTOP_LED_MSG_LEN]>::from(&st)[..9],
@@ -670,11 +676,11 @@ mod tests {
st.colour1 = Colour { st.colour1 = Colour {
r: 0xff, r: 0xff,
g: 0x00, g: 0x00,
b: 0xcd b: 0xcd,
}; };
let capture = [ let capture = [
0x5d, 0xb3, 0x07, 0x00, 0xff, 0x00, 0xcd, 0xe1, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5d, 0xb3, 0x07, 0x00, 0xff, 0x00, 0xcd, 0xe1, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0 0x0, 0x0,
]; ];
assert_eq!( assert_eq!(
<[u8; AURA_LAPTOP_LED_MSG_LEN]>::from(&st)[..9], <[u8; AURA_LAPTOP_LED_MSG_LEN]>::from(&st)[..9],
@@ -684,7 +690,7 @@ mod tests {
st.mode = AuraModeNum::RainbowWave; st.mode = AuraModeNum::RainbowWave;
let capture = [ let capture = [
0x5d, 0xb3, 0x07, 0x03, 0xff, 0x00, 0xcd, 0xe1, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5d, 0xb3, 0x07, 0x03, 0xff, 0x00, 0xcd, 0xe1, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0 0x0, 0x0,
]; ];
assert_eq!( assert_eq!(
<[u8; AURA_LAPTOP_LED_MSG_LEN]>::from(&st)[..9], <[u8; AURA_LAPTOP_LED_MSG_LEN]>::from(&st)[..9],

View File

@@ -11,7 +11,7 @@ pub struct InputBased {
/// - temperature /// - temperature
/// - fan speed /// - fan speed
/// - time /// - time
input: Box<dyn InputForEffect> input: Box<dyn InputForEffect>,
} }
impl EffectState for InputBased { impl EffectState for InputBased {

View File

@@ -19,7 +19,7 @@ pub struct Breathe {
#[serde(skip)] #[serde(skip)]
count_flipped: bool, count_flipped: bool,
#[serde(skip)] #[serde(skip)]
use_colour1: bool use_colour1: bool,
} }
impl Breathe { impl Breathe {
@@ -31,7 +31,7 @@ impl Breathe {
speed, speed,
colour: colour1, colour: colour1,
count_flipped: false, count_flipped: false,
use_colour1: true use_colour1: true,
} }
} }
} }

View File

@@ -13,7 +13,7 @@ pub struct DoomFlicker {
#[serde(skip)] #[serde(skip)]
count: u8, count: u8,
#[serde(skip)] #[serde(skip)]
colour: Colour colour: Colour,
} }
impl DoomFlicker { impl DoomFlicker {
@@ -24,7 +24,7 @@ impl DoomFlicker {
count: 4, count: 4,
max_percentage, max_percentage,
min_percentage, min_percentage,
start_colour: colour start_colour: colour,
} }
} }
} }
@@ -53,13 +53,13 @@ impl EffectState for DoomFlicker {
let max_light = Colour { let max_light = Colour {
r: (start_colour.r as f32 / 100.0 * *max_percentage as f32) as u8, r: (start_colour.r as f32 / 100.0 * *max_percentage as f32) as u8,
g: (start_colour.g as f32 / 100.0 * *max_percentage as f32) as u8, g: (start_colour.g as f32 / 100.0 * *max_percentage as f32) as u8,
b: (start_colour.b as f32 / 100.0 * *max_percentage as f32) as u8 b: (start_colour.b as f32 / 100.0 * *max_percentage as f32) as u8,
}; };
// min light is a percentage of the set colour // min light is a percentage of the set colour
let min_light = Colour { let min_light = Colour {
r: (start_colour.r as f32 / 100.0 * *min_percentage as f32) as u8, r: (start_colour.r as f32 / 100.0 * *min_percentage as f32) as u8,
g: (start_colour.g as f32 / 100.0 * *min_percentage as f32) as u8, g: (start_colour.g as f32 / 100.0 * *min_percentage as f32) as u8,
b: (start_colour.b as f32 / 100.0 * *min_percentage as f32) as u8 b: (start_colour.b as f32 / 100.0 * *min_percentage as f32) as u8,
}; };
// Convert the 255 to percentage // Convert the 255 to percentage
@@ -96,7 +96,7 @@ pub struct DoomLightFlash {
#[serde(skip)] #[serde(skip)]
count: u8, count: u8,
#[serde(skip)] #[serde(skip)]
colour: Colour colour: Colour,
} }
impl DoomLightFlash { impl DoomLightFlash {
@@ -109,7 +109,7 @@ impl DoomLightFlash {
min_percentage, min_percentage,
start_colour: colour, start_colour: colour,
max_time: 32, max_time: 32,
min_time: 7 min_time: 7,
} }
} }
} }
@@ -135,13 +135,13 @@ impl EffectState for DoomLightFlash {
let max_light = Colour { let max_light = Colour {
r: (start_colour.r as f32 / 100.0 * *max_percentage as f32) as u8, r: (start_colour.r as f32 / 100.0 * *max_percentage as f32) as u8,
g: (start_colour.g as f32 / 100.0 * *max_percentage as f32) as u8, g: (start_colour.g as f32 / 100.0 * *max_percentage as f32) as u8,
b: (start_colour.b as f32 / 100.0 * *max_percentage as f32) as u8 b: (start_colour.b as f32 / 100.0 * *max_percentage as f32) as u8,
}; };
// min light is a percentage of the set colour // min light is a percentage of the set colour
let min_light = Colour { let min_light = Colour {
r: (start_colour.r as f32 / 100.0 * *min_percentage as f32) as u8, r: (start_colour.r as f32 / 100.0 * *min_percentage as f32) as u8,
g: (start_colour.g as f32 / 100.0 * *min_percentage as f32) as u8, g: (start_colour.g as f32 / 100.0 * *min_percentage as f32) as u8,
b: (start_colour.b as f32 / 100.0 * *min_percentage as f32) as u8 b: (start_colour.b as f32 / 100.0 * *min_percentage as f32) as u8,
}; };
if *colour == max_light { if *colour == max_light {

View File

@@ -32,7 +32,7 @@ pub const RNDTABLE: [i32; 256] = [
206, 163, 45, 63, 90, 168, 114, 59, 33, 159, 95, 28, 139, 123, 98, 125, 196, 15, 70, 194, 253, 206, 163, 45, 63, 90, 168, 114, 59, 33, 159, 95, 28, 139, 123, 98, 125, 196, 15, 70, 194, 253,
54, 14, 109, 226, 71, 17, 161, 93, 186, 87, 244, 138, 20, 52, 123, 251, 26, 36, 17, 46, 52, 54, 14, 109, 226, 71, 17, 161, 93, 186, 87, 244, 138, 20, 52, 123, 251, 26, 36, 17, 46, 52,
231, 232, 76, 31, 221, 84, 37, 216, 165, 212, 106, 197, 242, 98, 43, 39, 175, 254, 145, 190, 231, 232, 76, 31, 221, 84, 37, 216, 165, 212, 106, 197, 242, 98, 43, 39, 175, 254, 145, 190,
84, 118, 222, 187, 136, 120, 163, 236, 249 84, 118, 222, 187, 136, 120, 163, 236, 249,
]; ];
pub fn p_random() -> i32 { pub fn p_random() -> i32 {
@@ -67,7 +67,7 @@ pub(crate) trait EffectState {
#[derive(Debug, Deserialize, Serialize, Default)] #[derive(Debug, Deserialize, Serialize, Default)]
pub struct AdvancedEffects { pub struct AdvancedEffects {
effects: Vec<Effect>, effects: Vec<Effect>,
zoned: bool zoned: bool,
} }
impl AdvancedEffects { impl AdvancedEffects {
@@ -75,7 +75,7 @@ impl AdvancedEffects {
pub fn new(zoned: bool) -> Self { pub fn new(zoned: bool) -> Self {
Self { Self {
effects: Default::default(), effects: Default::default(),
zoned zoned,
} }
} }
@@ -186,7 +186,7 @@ pub enum Effect {
Static(Static), Static(Static),
Breathe(Breathe), Breathe(Breathe),
DoomFlicker(DoomFlicker), DoomFlicker(DoomFlicker),
DoomLightFlash(DoomLightFlash) DoomLightFlash(DoomLightFlash),
} }
impl Default for Effect { impl Default for Effect {
@@ -207,12 +207,14 @@ mod tests {
fn single_key_next_state_then_create() { fn single_key_next_state_then_create() {
let layout = KeyLayout::default_layout(); let layout = KeyLayout::default_layout();
let mut seq = AdvancedEffects::new(false); let mut seq = AdvancedEffects::new(false);
seq.effects seq.effects.push(Effect::Static(Static::new(
.push(Effect::Static(Static::new(LedCode::F, Colour { LedCode::F,
Colour {
r: 255, r: 255,
g: 127, g: 127,
b: 0 b: 0,
}))); },
)));
seq.next_state(&layout); seq.next_state(&layout);
let packets = seq.create_packets(); let packets = seq.create_packets();
@@ -232,14 +234,14 @@ mod tests {
Colour { Colour {
r: 255, r: 255,
g: 127, g: 127,
b: 0 b: 0,
}, },
Colour { Colour {
r: 127, r: 127,
g: 0, g: 0,
b: 255 b: 255,
}, },
Speed::Med Speed::Med,
))); )));
let s = let s =
@@ -274,10 +276,10 @@ mod tests {
Colour { Colour {
r: 255, r: 255,
g: 127, g: 127,
b: 80 b: 80,
}, },
100, 100,
10 10,
))); )));
seq.next_state(&layout); seq.next_state(&layout);

View File

@@ -8,14 +8,14 @@ use crate::{effect_state_impl, Colour};
pub struct Static { pub struct Static {
led: LedCode, led: LedCode,
/// The starting colour /// The starting colour
colour: Colour colour: Colour,
} }
impl Static { impl Static {
pub fn new(address: LedCode, colour: Colour) -> Self { pub fn new(address: LedCode, colour: Colour) -> Self {
Self { Self {
led: address, led: address,
colour colour,
} }
} }
} }

View File

@@ -8,7 +8,7 @@ pub enum Error {
ParseBrightness, ParseBrightness,
IoPath(String, std::io::Error), IoPath(String, std::io::Error),
Ron(ron::Error), Ron(ron::Error),
RonParse(ron::error::SpannedError) RonParse(ron::error::SpannedError),
} }
impl fmt::Display for Error { impl fmt::Display for Error {
@@ -21,7 +21,7 @@ impl fmt::Display for Error {
Error::ParseBrightness => write!(f, "Could not parse brightness"), Error::ParseBrightness => write!(f, "Could not parse brightness"),
Error::IoPath(path, io) => write!(f, "IO Error: {path}, {io}"), Error::IoPath(path, io) => write!(f, "IO Error: {path}, {io}"),
Error::Ron(e) => write!(f, "RON Parse Error: {e}"), Error::Ron(e) => write!(f, "RON Parse Error: {e}"),
Error::RonParse(e) => write!(f, "RON Parse Error: {e}") Error::RonParse(e) => write!(f, "RON Parse Error: {e}"),
} }
} }
} }

View File

@@ -164,7 +164,7 @@ pub enum LedCode {
/// To be ignored by effects /// To be ignored by effects
Spacing, Spacing,
/// To be ignored by effects /// To be ignored by effects
Blocking Blocking,
} }
impl LedCode { impl LedCode {
@@ -210,7 +210,7 @@ pub struct LedUsbPackets {
/// Wether or not this packet collection is zoned. The determines which /// Wether or not this packet collection is zoned. The determines which
/// starting bytes are used and what the indexing is for lightbar RGB /// starting bytes are used and what the indexing is for lightbar RGB
/// colours /// colours
zoned: bool zoned: bool,
} }
impl Default for LedUsbPackets { impl Default for LedUsbPackets {
@@ -244,7 +244,7 @@ impl LedUsbPackets {
} }
Self { Self {
usb_packets: set, usb_packets: set,
zoned: false zoned: false,
} }
} }
@@ -274,7 +274,7 @@ impl LedUsbPackets {
} }
Self { Self {
usb_packets: vec![pkt], usb_packets: vec![pkt],
zoned: true zoned: true,
} }
} }
@@ -633,7 +633,7 @@ impl From<&LedCode> for &str {
LedCode::ZonedKbLeft => "Left Zone (zone 1)", LedCode::ZonedKbLeft => "Left Zone (zone 1)",
LedCode::ZonedKbLeftMid => "Center-left Zone (zone 2)", LedCode::ZonedKbLeftMid => "Center-left Zone (zone 2)",
LedCode::ZonedKbRightMid => "Center-right Zone (zone 3)", LedCode::ZonedKbRightMid => "Center-right Zone (zone 3)",
LedCode::ZonedKbRight => "Right Zone (zone 4)" LedCode::ZonedKbRight => "Right Zone (zone 4)",
} }
} }
} }

View File

@@ -26,12 +26,12 @@ pub enum KeyShape {
pad_left: f32, pad_left: f32,
pad_right: f32, pad_right: f32,
pad_top: f32, pad_top: f32,
pad_bottom: f32 pad_bottom: f32,
}, },
Blank { Blank {
width: f32, width: f32,
height: f32 height: f32,
} },
} }
impl KeyShape { impl KeyShape {
@@ -41,7 +41,7 @@ impl KeyShape {
pad_left: f32, pad_left: f32,
pad_right: f32, pad_right: f32,
pad_top: f32, pad_top: f32,
pad_bottom: f32 pad_bottom: f32,
) -> Self { ) -> Self {
Self::Led { Self::Led {
width, width,
@@ -49,7 +49,7 @@ impl KeyShape {
pad_left, pad_left,
pad_right, pad_right,
pad_top, pad_top,
pad_bottom pad_bottom,
} }
} }
@@ -66,7 +66,7 @@ impl KeyShape {
pad_left, pad_left,
pad_right, pad_right,
pad_top, pad_top,
pad_bottom pad_bottom,
} => { } => {
*width *= scale; *width *= scale;
*height *= scale; *height *= scale;
@@ -97,7 +97,7 @@ pub struct KeyRow {
row: Vec<(LedCode, String)>, row: Vec<(LedCode, String)>,
/// The final data structure merged key_shapes and rows /// The final data structure merged key_shapes and rows
#[serde(skip)] #[serde(skip)]
built_row: Vec<(LedCode, KeyShape)> built_row: Vec<(LedCode, KeyShape)>,
} }
impl KeyRow { impl KeyRow {
@@ -106,7 +106,7 @@ impl KeyRow {
pad_left, pad_left,
pad_top, pad_top,
row, row,
built_row: Default::default() built_row: Default::default(),
} }
} }
@@ -132,7 +132,7 @@ impl KeyRow {
pad_bottom, pad_bottom,
.. ..
} => height + pad_top + pad_bottom, } => height + pad_top + pad_bottom,
KeyShape::Blank { height, .. } => *height KeyShape::Blank { height, .. } => *height,
}; };
if h < height { if h < height {
@@ -156,7 +156,7 @@ impl KeyRow {
pad_right, pad_right,
.. ..
} => w += width + pad_left + pad_right, } => w += width + pad_left + pad_right,
KeyShape::Blank { width, .. } => w += width KeyShape::Blank { width, .. } => w += width,
} }
} }
w w
@@ -185,7 +185,7 @@ pub struct KeyLayout {
/// Should be copied from the `LaptopLedData` as laptops may have the same /// Should be copied from the `LaptopLedData` as laptops may have the same
/// layout, but different EC features. /// layout, but different EC features.
#[serde(skip)] #[serde(skip)]
advanced_type: AdvancedAuraType advanced_type: AdvancedAuraType,
} }
impl KeyLayout { impl KeyLayout {
@@ -195,7 +195,7 @@ impl KeyLayout {
if buf.is_empty() { if buf.is_empty() {
Err(Error::IoPath( Err(Error::IoPath(
path.to_string_lossy().to_string(), path.to_string_lossy().to_string(),
std::io::ErrorKind::InvalidData.into() std::io::ErrorKind::InvalidData.into(),
)) ))
} else { } else {
let mut data = ron::from_str::<Self>(&buf)?; let mut data = ron::from_str::<Self>(&buf)?;
@@ -332,10 +332,13 @@ impl KeyLayout {
advanced_type: AdvancedAuraType::None, advanced_type: AdvancedAuraType::None,
key_shapes: HashMap::from([( key_shapes: HashMap::from([(
"regular".to_owned(), "regular".to_owned(),
KeyShape::new_led(1.0, 1.0, 0.1, 0.1, 0.1, 0.1) KeyShape::new_led(1.0, 1.0, 0.1, 0.1, 0.1, 0.1),
)]), )]),
key_rows: vec![ key_rows: vec![
KeyRow::new(0.1, 0.1, vec![ KeyRow::new(
0.1,
0.1,
vec![
(LedCode::Esc, "regular".to_owned()), (LedCode::Esc, "regular".to_owned()),
(LedCode::F1, "regular".to_owned()), (LedCode::F1, "regular".to_owned()),
(LedCode::F2, "regular".to_owned()), (LedCode::F2, "regular".to_owned()),
@@ -350,8 +353,12 @@ impl KeyLayout {
(LedCode::F10, "regular".to_owned()), (LedCode::F10, "regular".to_owned()),
(LedCode::F11, "regular".to_owned()), (LedCode::F11, "regular".to_owned()),
(LedCode::F12, "regular".to_owned()), (LedCode::F12, "regular".to_owned()),
]), ],
KeyRow::new(0.1, 0.1, vec![ ),
KeyRow::new(
0.1,
0.1,
vec![
(LedCode::Tilde, "regular".to_owned()), (LedCode::Tilde, "regular".to_owned()),
(LedCode::N1, "regular".to_owned()), (LedCode::N1, "regular".to_owned()),
(LedCode::N2, "regular".to_owned()), (LedCode::N2, "regular".to_owned()),
@@ -366,8 +373,12 @@ impl KeyLayout {
(LedCode::Hyphen, "regular".to_owned()), (LedCode::Hyphen, "regular".to_owned()),
(LedCode::Equals, "regular".to_owned()), (LedCode::Equals, "regular".to_owned()),
(LedCode::Backspace, "regular".to_owned()), (LedCode::Backspace, "regular".to_owned()),
]), ],
KeyRow::new(0.1, 0.1, vec![ ),
KeyRow::new(
0.1,
0.1,
vec![
(LedCode::Tab, "regular".to_owned()), (LedCode::Tab, "regular".to_owned()),
(LedCode::Q, "regular".to_owned()), (LedCode::Q, "regular".to_owned()),
(LedCode::W, "regular".to_owned()), (LedCode::W, "regular".to_owned()),
@@ -382,8 +393,12 @@ impl KeyLayout {
(LedCode::LBracket, "regular".to_owned()), (LedCode::LBracket, "regular".to_owned()),
(LedCode::RBracket, "regular".to_owned()), (LedCode::RBracket, "regular".to_owned()),
(LedCode::BackSlash, "regular".to_owned()), (LedCode::BackSlash, "regular".to_owned()),
]), ],
KeyRow::new(0.1, 0.1, vec![ ),
KeyRow::new(
0.1,
0.1,
vec![
(LedCode::Caps, "regular".to_owned()), (LedCode::Caps, "regular".to_owned()),
(LedCode::A, "regular".to_owned()), (LedCode::A, "regular".to_owned()),
(LedCode::S, "regular".to_owned()), (LedCode::S, "regular".to_owned()),
@@ -397,8 +412,12 @@ impl KeyLayout {
(LedCode::SemiColon, "regular".to_owned()), (LedCode::SemiColon, "regular".to_owned()),
(LedCode::Quote, "regular".to_owned()), (LedCode::Quote, "regular".to_owned()),
(LedCode::Return, "regular".to_owned()), (LedCode::Return, "regular".to_owned()),
]), ],
KeyRow::new(0.1, 0.1, vec![ ),
KeyRow::new(
0.1,
0.1,
vec![
(LedCode::LShift, "regular".to_owned()), (LedCode::LShift, "regular".to_owned()),
(LedCode::Z, "regular".to_owned()), (LedCode::Z, "regular".to_owned()),
(LedCode::X, "regular".to_owned()), (LedCode::X, "regular".to_owned()),
@@ -411,8 +430,12 @@ impl KeyLayout {
(LedCode::Period, "regular".to_owned()), (LedCode::Period, "regular".to_owned()),
(LedCode::FwdSlash, "regular".to_owned()), (LedCode::FwdSlash, "regular".to_owned()),
(LedCode::Rshift, "regular".to_owned()), (LedCode::Rshift, "regular".to_owned()),
]), ],
KeyRow::new(0.1, 0.1, vec![ ),
KeyRow::new(
0.1,
0.1,
vec![
(LedCode::LCtrl, "regular".to_owned()), (LedCode::LCtrl, "regular".to_owned()),
(LedCode::LFn, "regular".to_owned()), (LedCode::LFn, "regular".to_owned()),
(LedCode::Meta, "regular".to_owned()), (LedCode::Meta, "regular".to_owned()),
@@ -421,8 +444,9 @@ impl KeyLayout {
(LedCode::RAlt, "regular".to_owned()), (LedCode::RAlt, "regular".to_owned()),
(LedCode::PrtSc, "regular".to_owned()), (LedCode::PrtSc, "regular".to_owned()),
(LedCode::RCtrl, "regular".to_owned()), (LedCode::RCtrl, "regular".to_owned()),
]), ],
] ),
],
} }
} }
} }

View File

@@ -16,5 +16,5 @@ pub enum AdvancedAuraType {
#[default] #[default]
None, None,
Zoned(Vec<LedCode>), Zoned(Vec<LedCode>),
PerKey PerKey,
} }

View File

@@ -23,7 +23,7 @@ pub struct AuraPowerState {
pub awake: bool, pub awake: bool,
pub sleep: bool, pub sleep: bool,
/// Ignored for pre-2021 and Tuf /// Ignored for pre-2021 and Tuf
pub shutdown: bool pub shutdown: bool,
} }
impl Default for AuraPowerState { impl Default for AuraPowerState {
@@ -34,7 +34,7 @@ impl Default for AuraPowerState {
boot: true, boot: true,
awake: true, awake: true,
sleep: true, sleep: true,
shutdown: true shutdown: true,
} }
} }
} }
@@ -46,7 +46,7 @@ impl AuraPowerState {
boot: true, boot: true,
awake: true, awake: true,
sleep: true, sleep: true,
shutdown: true shutdown: true,
} }
} }
@@ -140,7 +140,7 @@ impl AuraPowerState {
| ((self.sleep as u32) << (23 + 3)) | ((self.sleep as u32) << (23 + 3))
| ((self.shutdown as u32) << (23 + 4)) | ((self.shutdown as u32) << (23 + 4))
} }
PowerZones::None | PowerZones::KeyboardAndLightbar => 0 PowerZones::None | PowerZones::KeyboardAndLightbar => 0,
} }
} }
} }
@@ -148,7 +148,7 @@ impl AuraPowerState {
#[cfg_attr(feature = "dbus", derive(Type, Value, OwnedValue))] #[cfg_attr(feature = "dbus", derive(Type, Value, OwnedValue))]
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] #[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct LaptopAuraPower { pub struct LaptopAuraPower {
pub states: Vec<AuraPowerState> pub states: Vec<AuraPowerState>,
} }
impl LaptopAuraPower { impl LaptopAuraPower {
@@ -206,19 +206,19 @@ impl LaptopAuraPower {
// 3. KeyboardAndLightbar // 3. KeyboardAndLightbar
if support_data.power_zones.contains(&PowerZones::Lightbar) { if support_data.power_zones.contains(&PowerZones::Lightbar) {
Self { Self {
states: vec![AuraPowerState::default_for(PowerZones::KeyboardAndLightbar)] states: vec![AuraPowerState::default_for(PowerZones::KeyboardAndLightbar)],
} }
} else { } else {
Self { Self {
states: vec![AuraPowerState::default_for(PowerZones::Keyboard)] states: vec![AuraPowerState::default_for(PowerZones::Keyboard)],
} }
} }
} }
AuraDeviceType::LaptopKeyboardTuf => Self { AuraDeviceType::LaptopKeyboardTuf => Self {
states: vec![AuraPowerState::default_for(PowerZones::Keyboard)] states: vec![AuraPowerState::default_for(PowerZones::Keyboard)],
}, },
AuraDeviceType::ScsiExtDisk => todo!(), AuraDeviceType::ScsiExtDisk => todo!(),
AuraDeviceType::AnimeOrSlash => todo!() AuraDeviceType::AnimeOrSlash => todo!(),
} }
} }
@@ -266,7 +266,7 @@ impl LaptopAuraPower {
self.new_to_bytes() self.new_to_bytes()
} }
AuraDeviceType::ScsiExtDisk => todo!("scsi disk not implemented yet"), AuraDeviceType::ScsiExtDisk => todo!("scsi disk not implemented yet"),
AuraDeviceType::AnimeOrSlash => todo!("anime/slash not implemented yet") AuraDeviceType::AnimeOrSlash => todo!("anime/slash not implemented yet"),
} }
} }
} }
@@ -285,7 +285,7 @@ enum OldAuraPower {
Boot = 0xc31209, Boot = 0xc31209,
Sleep = 0x300804, Sleep = 0x300804,
Keyboard = 0x080000, Keyboard = 0x080000,
Lightbar = 0x040500 Lightbar = 0x040500,
} }
impl BitOr<OldAuraPower> for OldAuraPower { impl BitOr<OldAuraPower> for OldAuraPower {
@@ -332,9 +332,9 @@ mod test {
boot: false, boot: false,
awake: true, awake: true,
sleep: false, sleep: false,
shutdown: false shutdown: false,
}, },
] ],
}; };
let bytes = power.to_bytes(AuraDeviceType::LaptopKeyboardPre2021); let bytes = power.to_bytes(AuraDeviceType::LaptopKeyboardPre2021);
println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]); println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]);
@@ -347,9 +347,9 @@ mod test {
boot: false, boot: false,
awake: true, awake: true,
sleep: false, sleep: false,
shutdown: false shutdown: false,
}, },
] ],
}; };
let bytes = power.to_bytes(AuraDeviceType::LaptopKeyboardPre2021); let bytes = power.to_bytes(AuraDeviceType::LaptopKeyboardPre2021);
println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]); println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]);
@@ -369,16 +369,16 @@ mod test {
boot: true, boot: true,
awake: true, awake: true,
sleep: true, sleep: true,
shutdown: false shutdown: false,
}, },
AuraPowerState { AuraPowerState {
zone: PowerZones::Lightbar, zone: PowerZones::Lightbar,
boot: true, boot: true,
awake: true, awake: true,
sleep: true, sleep: true,
shutdown: false shutdown: false,
}, },
] ],
}; };
let bytes = power.to_bytes(AuraDeviceType::LaptopKeyboardPre2021); let bytes = power.to_bytes(AuraDeviceType::LaptopKeyboardPre2021);
println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]); println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]);
@@ -394,9 +394,9 @@ mod test {
boot: true, boot: true,
awake: false, awake: false,
sleep: false, sleep: false,
shutdown: false shutdown: false,
}, },
] ],
}); });
let boot_keyb_ = to_binary_string_post2021(&LaptopAuraPower { let boot_keyb_ = to_binary_string_post2021(&LaptopAuraPower {
states: vec![ states: vec![
@@ -405,9 +405,9 @@ mod test {
boot: true, boot: true,
awake: false, awake: false,
sleep: false, sleep: false,
shutdown: false shutdown: false,
}, },
] ],
}); });
let sleep_logo = to_binary_string_post2021(&LaptopAuraPower { let sleep_logo = to_binary_string_post2021(&LaptopAuraPower {
states: vec![ states: vec![
@@ -416,9 +416,9 @@ mod test {
boot: false, boot: false,
awake: false, awake: false,
sleep: true, sleep: true,
shutdown: false shutdown: false,
}, },
] ],
}); });
let sleep_keyb = to_binary_string_post2021(&LaptopAuraPower { let sleep_keyb = to_binary_string_post2021(&LaptopAuraPower {
states: vec![ states: vec![
@@ -427,9 +427,9 @@ mod test {
boot: false, boot: false,
awake: false, awake: false,
sleep: true, sleep: true,
shutdown: false shutdown: false,
}, },
] ],
}); });
let awake_logo = to_binary_string_post2021(&LaptopAuraPower { let awake_logo = to_binary_string_post2021(&LaptopAuraPower {
states: vec![ states: vec![
@@ -438,9 +438,9 @@ mod test {
boot: false, boot: false,
awake: true, awake: true,
sleep: false, sleep: false,
shutdown: false shutdown: false,
}, },
] ],
}); });
let awake_keyb = to_binary_string_post2021(&LaptopAuraPower { let awake_keyb = to_binary_string_post2021(&LaptopAuraPower {
states: vec![ states: vec![
@@ -449,9 +449,9 @@ mod test {
boot: false, boot: false,
awake: true, awake: true,
sleep: false, sleep: false,
shutdown: false shutdown: false,
}, },
] ],
}); });
let shut_logo_ = to_binary_string_post2021(&LaptopAuraPower { let shut_logo_ = to_binary_string_post2021(&LaptopAuraPower {
states: vec![ states: vec![
@@ -460,9 +460,9 @@ mod test {
boot: false, boot: false,
awake: false, awake: false,
sleep: false, sleep: false,
shutdown: true shutdown: true,
}, },
] ],
}); });
let shut_keyb_ = to_binary_string_post2021(&LaptopAuraPower { let shut_keyb_ = to_binary_string_post2021(&LaptopAuraPower {
states: vec![ states: vec![
@@ -471,9 +471,9 @@ mod test {
boot: false, boot: false,
awake: false, awake: false,
sleep: false, sleep: false,
shutdown: true shutdown: true,
}, },
] ],
}); });
let boot_bar__ = to_binary_string_post2021(&LaptopAuraPower { let boot_bar__ = to_binary_string_post2021(&LaptopAuraPower {
states: vec![ states: vec![
@@ -482,9 +482,9 @@ mod test {
boot: true, boot: true,
awake: false, awake: false,
sleep: false, sleep: false,
shutdown: false shutdown: false,
}, },
] ],
}); });
let awake_bar_ = to_binary_string_post2021(&LaptopAuraPower { let awake_bar_ = to_binary_string_post2021(&LaptopAuraPower {
states: vec![ states: vec![
@@ -493,9 +493,9 @@ mod test {
boot: false, boot: false,
awake: true, awake: true,
sleep: false, sleep: false,
shutdown: false shutdown: false,
}, },
] ],
}); });
let sleep_bar_ = to_binary_string_post2021(&LaptopAuraPower { let sleep_bar_ = to_binary_string_post2021(&LaptopAuraPower {
states: vec![ states: vec![
@@ -504,9 +504,9 @@ mod test {
boot: false, boot: false,
awake: false, awake: false,
sleep: true, sleep: true,
shutdown: false shutdown: false,
}, },
] ],
}); });
let shut_bar__ = to_binary_string_post2021(&LaptopAuraPower { let shut_bar__ = to_binary_string_post2021(&LaptopAuraPower {
states: vec![ states: vec![
@@ -515,9 +515,9 @@ mod test {
boot: false, boot: false,
awake: false, awake: false,
sleep: false, sleep: false,
shutdown: true shutdown: true,
}, },
] ],
}); });
let boot_lid__ = to_binary_string_post2021(&LaptopAuraPower { let boot_lid__ = to_binary_string_post2021(&LaptopAuraPower {
states: vec![ states: vec![
@@ -526,9 +526,9 @@ mod test {
boot: true, boot: true,
awake: false, awake: false,
sleep: false, sleep: false,
shutdown: false shutdown: false,
}, },
] ],
}); });
let awake_lid_ = to_binary_string_post2021(&LaptopAuraPower { let awake_lid_ = to_binary_string_post2021(&LaptopAuraPower {
states: vec![ states: vec![
@@ -537,9 +537,9 @@ mod test {
boot: false, boot: false,
awake: true, awake: true,
sleep: false, sleep: false,
shutdown: false shutdown: false,
}, },
] ],
}); });
let sleep_lid_ = to_binary_string_post2021(&LaptopAuraPower { let sleep_lid_ = to_binary_string_post2021(&LaptopAuraPower {
states: vec![ states: vec![
@@ -548,9 +548,9 @@ mod test {
boot: false, boot: false,
awake: false, awake: false,
sleep: true, sleep: true,
shutdown: false shutdown: false,
}, },
] ],
}); });
let shut_lid__ = to_binary_string_post2021(&LaptopAuraPower { let shut_lid__ = to_binary_string_post2021(&LaptopAuraPower {
states: vec![ states: vec![
@@ -559,9 +559,9 @@ mod test {
boot: false, boot: false,
awake: false, awake: false,
sleep: false, sleep: false,
shutdown: true shutdown: true,
}, },
] ],
}); });
let boot_rear_ = to_binary_string_post2021(&LaptopAuraPower { let boot_rear_ = to_binary_string_post2021(&LaptopAuraPower {
states: vec![ states: vec![
@@ -570,9 +570,9 @@ mod test {
boot: true, boot: true,
awake: false, awake: false,
sleep: false, sleep: false,
shutdown: false shutdown: false,
}, },
] ],
}); });
let awake_rear = to_binary_string_post2021(&LaptopAuraPower { let awake_rear = to_binary_string_post2021(&LaptopAuraPower {
states: vec![ states: vec![
@@ -581,9 +581,9 @@ mod test {
boot: false, boot: false,
awake: true, awake: true,
sleep: false, sleep: false,
shutdown: false shutdown: false,
}, },
] ],
}); });
let sleep_rear = to_binary_string_post2021(&LaptopAuraPower { let sleep_rear = to_binary_string_post2021(&LaptopAuraPower {
states: vec![ states: vec![
@@ -592,9 +592,9 @@ mod test {
boot: false, boot: false,
awake: false, awake: false,
sleep: true, sleep: true,
shutdown: false shutdown: false,
}, },
] ],
}); });
let shut_rear_ = to_binary_string_post2021(&LaptopAuraPower { let shut_rear_ = to_binary_string_post2021(&LaptopAuraPower {
states: vec![ states: vec![
@@ -603,9 +603,9 @@ mod test {
boot: false, boot: false,
awake: false, awake: false,
sleep: false, sleep: false,
shutdown: true shutdown: true,
}, },
] ],
}); });
assert_eq!(boot_logo_, "00000001, 00000000, 00000000, 00000000"); assert_eq!(boot_logo_, "00000001, 00000000, 00000000, 00000000");
@@ -655,7 +655,7 @@ mod test {
zone: PowerZones::RearGlow, zone: PowerZones::RearGlow,
..Default::default() ..Default::default()
}, },
] ],
}); });
assert_eq!(byte1, "11111111, 00011110, 00001111, 00001111"); assert_eq!(byte1, "11111111, 00011110, 00001111, 00001111");
} }

View File

@@ -29,40 +29,40 @@ pub const VERSION: &str = env!("CARGO_PKG_VERSION");
pub const RED: Colour = Colour { pub const RED: Colour = Colour {
r: 0xff, r: 0xff,
g: 0x00, g: 0x00,
b: 0x00 b: 0x00,
}; };
pub const GREEN: Colour = Colour { pub const GREEN: Colour = Colour {
r: 0x00, r: 0x00,
g: 0xff, g: 0xff,
b: 0x00 b: 0x00,
}; };
pub const BLUE: Colour = Colour { pub const BLUE: Colour = Colour {
r: 0x00, r: 0x00,
g: 0x00, g: 0x00,
b: 0xff b: 0xff,
}; };
pub const VIOLET: Colour = Colour { pub const VIOLET: Colour = Colour {
r: 0x9b, r: 0x9b,
g: 0x26, g: 0x26,
b: 0xb6 b: 0xb6,
}; };
pub const TEAL: Colour = Colour { pub const TEAL: Colour = Colour {
r: 0x00, r: 0x00,
g: 0x7c, g: 0x7c,
b: 0x80 b: 0x80,
}; };
pub const YELLOW: Colour = Colour { pub const YELLOW: Colour = Colour {
r: 0xff, r: 0xff,
g: 0xef, g: 0xef,
b: 0x00 b: 0x00,
}; };
pub const ORANGE: Colour = Colour { pub const ORANGE: Colour = Colour {
r: 0xff, r: 0xff,
g: 0xa4, g: 0xa4,
b: 0x00 b: 0x00,
}; };
pub const GRADIENT: [Colour; 7] = [ pub const GRADIENT: [Colour; 7] = [
RED, VIOLET, BLUE, TEAL, GREEN, YELLOW, ORANGE RED, VIOLET, BLUE, TEAL, GREEN, YELLOW, ORANGE,
]; ];
#[cfg_attr(feature = "dbus", derive(Type, Value, OwnedValue))] #[cfg_attr(feature = "dbus", derive(Type, Value, OwnedValue))]
@@ -76,7 +76,7 @@ pub enum AuraDeviceType {
ScsiExtDisk = 3, ScsiExtDisk = 3,
Ally = 4, Ally = 4,
AnimeOrSlash = 5, AnimeOrSlash = 5,
Unknown = 255 Unknown = 255,
} }
impl AuraDeviceType { impl AuraDeviceType {
@@ -110,7 +110,7 @@ impl From<&str> for AuraDeviceType {
"1abe" | "1b4c" => Self::Ally, "1abe" | "1b4c" => Self::Ally,
"19b3" | "193b" => Self::AnimeOrSlash, "19b3" | "193b" => Self::AnimeOrSlash,
"19b6" => Self::LaptopKeyboard2021, "19b6" => Self::LaptopKeyboard2021,
_ => Self::Unknown _ => Self::Unknown,
} }
} }
} }
@@ -138,5 +138,5 @@ pub enum PowerZones {
KeyboardAndLightbar = 5, KeyboardAndLightbar = 5,
/// Ally specific for creating correct packet /// Ally specific for creating correct packet
Ally = 6, Ally = 6,
None = 255 None = 255,
} }

View File

@@ -1,7 +1,7 @@
// Only these two packets must be 17 bytes // Only these two packets must be 17 bytes
pub const AURA_LAPTOP_LED_APPLY: [u8; 17] = [ pub const AURA_LAPTOP_LED_APPLY: [u8; 17] = [
0x5d, 0xb4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 0x5d, 0xb4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
]; ];
pub const AURA_LAPTOP_LED_SET: [u8; 17] = [ pub const AURA_LAPTOP_LED_SET: [u8; 17] = [
0x5d, 0xb5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 0x5d, 0xb5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
]; ];

View File

@@ -12,7 +12,7 @@ edition.workspace = true
default = [] default = []
mocking = [] mocking = []
x11 = ["slint/backend-winit-x11"] x11 = ["slint/backend-winit-x11"]
# Requires RUSTFLAGS="--cfg tokio_unstable" # Optional tokio debug feature does not require nightly; remove RUSTFLAGS note.
tokio-debug = ["console-subscriber"] tokio-debug = ["console-subscriber"]
[dependencies] [dependencies]
@@ -41,6 +41,7 @@ zbus.workspace = true
dirs.workspace = true dirs.workspace = true
notify-rust.workspace = true notify-rust.workspace = true
concat-idents.workspace = true concat-idents.workspace = true
futures-util.workspace = true
versions.workspace = true versions.workspace = true
@@ -48,12 +49,26 @@ versions.workspace = true
git = "https://github.com/slint-ui/slint.git" git = "https://github.com/slint-ui/slint.git"
default-features = false default-features = false
features = [ features = [
"gettext",
"compat-1-2", "compat-1-2",
"gettext",
"backend-winit-wayland", "backend-winit-wayland",
"renderer-winit-femtovg", "renderer-femtovg",
# "renderer-skia-opengl", # "renderer-skia-opengl",
] ]
[build-dependencies.slint-build] [build-dependencies.slint-build]
git = "https://github.com/slint-ui/slint.git" git = "https://github.com/slint-ui/slint.git"
[package.metadata.deb]
license-file = ["../LICENSE", "4"]
extended-description = """\
The dbus server for asusctl and rog-control-center applications."""
depends = "$auto"
section = "utility"
priority = "optional"
assets = [
["target/release/rog-control-center", "usr/bin/", "755"],
["../rog_gui-fakeinstall/usr/share/applications/*", "usr/share/share/applications/", "644"],
["../rog_gui-fakeinstall/usr/share/icons/hicolor/512x512/apps/*", "usr/share/icons/hicolor/512x512/apps", "644"],
["../rog_gui-fakeinstall/usr/share/icons/hicolor/scalable/status/*", "usr/share/icons/hicolor/scalable/status", "644"],
]

View File

@@ -18,7 +18,7 @@ fn main() {
CompilerConfiguration::new() CompilerConfiguration::new()
// .embed_resources(EmbedResourcesKind::EmbedFiles) // .embed_resources(EmbedResourcesKind::EmbedFiles)
.with_include_paths(vec![include]) .with_include_paths(vec![include])
.with_style("fluent".into()) .with_style("fluent".into()),
) )
.unwrap(); .unwrap();
} }

View File

@@ -23,5 +23,5 @@ pub struct CliStart {
help = "put ROGCC in layout viewing mode - this is helpful for finding existing layouts \ help = "put ROGCC in layout viewing mode - this is helpful for finding existing layouts \
that might match your laptop" that might match your laptop"
)] )]
pub layout_viewing: bool pub layout_viewing: bool,
} }

View File

@@ -21,7 +21,7 @@ pub struct Config {
pub fullscreen_width: u32, pub fullscreen_width: u32,
pub fullscreen_height: u32, pub fullscreen_height: u32,
// This field must be last // This field must be last
pub notifications: EnabledNotifications pub notifications: EnabledNotifications,
} }
impl Default for Config { impl Default for Config {
@@ -36,7 +36,7 @@ impl Default for Config {
fullscreen_height: 1080, fullscreen_height: 1080,
notifications: EnabledNotifications::default(), notifications: EnabledNotifications::default(),
ac_command: String::new(), ac_command: String::new(),
bat_command: String::new() bat_command: String::new(),
} }
} }
} }
@@ -77,7 +77,7 @@ pub struct Config461 {
pub enable_dgpu_notifications: bool, pub enable_dgpu_notifications: bool,
pub dark_mode: bool, pub dark_mode: bool,
// This field must be last // This field must be last
pub enabled_notifications: EnabledNotifications pub enabled_notifications: EnabledNotifications,
} }
impl From<Config461> for Config { impl From<Config461> for Config {
@@ -92,7 +92,7 @@ impl From<Config461> for Config {
start_fullscreen: false, start_fullscreen: false,
fullscreen_width: 1920, fullscreen_width: 1920,
fullscreen_height: 1080, fullscreen_height: 1080,
notifications: c.enabled_notifications notifications: c.enabled_notifications,
} }
} }
} }

View File

@@ -9,7 +9,8 @@ pub enum Error {
ConfigLockFail, ConfigLockFail,
XdgVars, XdgVars,
Zbus(zbus::Error), Zbus(zbus::Error),
Notification(notify_rust::error::Error) ZbusFdo(zbus::fdo::Error),
Notification(notify_rust::error::Error),
} }
impl fmt::Display for Error { impl fmt::Display for Error {
@@ -21,7 +22,8 @@ impl fmt::Display for Error {
Error::ConfigLockFail => write!(f, "Failed to lock user config"), Error::ConfigLockFail => write!(f, "Failed to lock user config"),
Error::XdgVars => write!(f, "XDG environment vars appear unset"), Error::XdgVars => write!(f, "XDG environment vars appear unset"),
Error::Zbus(err) => write!(f, "Error: {}", err), Error::Zbus(err) => write!(f, "Error: {}", err),
Error::Notification(err) => write!(f, "Notification Error: {}", err) Error::ZbusFdo(err) => write!(f, "Error: {}", err),
Error::Notification(err) => write!(f, "Notification Error: {}", err),
} }
} }
} }
@@ -40,6 +42,12 @@ impl From<zbus::Error> for Error {
} }
} }
impl From<zbus::fdo::Error> for Error {
fn from(err: zbus::fdo::Error) -> Self {
Error::ZbusFdo(err)
}
}
impl From<notify_rust::error::Error> for Error { impl From<notify_rust::error::Error> for Error {
fn from(err: notify_rust::error::Error) -> Self { fn from(err: notify_rust::error::Error) -> Self {
Error::Notification(err) Error::Notification(err)

View File

@@ -38,5 +38,5 @@ pub enum Page {
System, System,
AuraEffects, AuraEffects,
AnimeMatrix, AnimeMatrix,
FanCurves FanCurves,
} }

View File

@@ -8,7 +8,7 @@ use std::time::Duration;
use config_traits::{StdConfig, StdConfigLoad1}; use config_traits::{StdConfig, StdConfigLoad1};
use dmi_id::DMIID; use dmi_id::DMIID;
use gumdrop::Options; use gumdrop::Options;
use log::{info, warn, LevelFilter}; use log::{debug, info, warn, LevelFilter};
use rog_control_center::cli_options::CliStart; use rog_control_center::cli_options::CliStart;
use rog_control_center::config::Config; use rog_control_center::config::Config;
use rog_control_center::error::Result; use rog_control_center::error::Result;
@@ -17,26 +17,43 @@ use rog_control_center::slint::ComponentHandle;
use rog_control_center::tray::init_tray; use rog_control_center::tray::init_tray;
use rog_control_center::ui::setup_window; use rog_control_center::ui::setup_window;
use rog_control_center::zbus_proxies::{ use rog_control_center::zbus_proxies::{
AppState, ROGCCZbus, ROGCCZbusProxyBlocking, ZBUS_IFACE, ZBUS_PATH AppState, ROGCCZbus, ROGCCZbusProxyBlocking, ZBUS_IFACE, ZBUS_PATH,
}; };
use rog_control_center::{print_versions, MainWindow}; use rog_control_center::{print_versions, MainWindow};
use tokio::runtime::Runtime; use tokio::runtime::Runtime;
#[tokio::main] #[tokio::main]
async fn main() -> Result<()> { async fn main() -> Result<()> {
// Ensure tracing spans are quiet by default unless user overrides
if std::env::var_os("RUST_LOG").is_none() {
std::env::set_var("RUST_LOG", "warn,tracing=error,zbus=error");
}
let mut logger = env_logger::Builder::new(); let mut logger = env_logger::Builder::new();
logger logger
.filter_level(LevelFilter::Warn)
.parse_default_env() .parse_default_env()
.target(env_logger::Target::Stdout) .filter_level(LevelFilter::Info)
.parse_default_env()
.target(env_logger::Target::Stderr)
.format_timestamp(None) .format_timestamp(None)
.init(); .init();
// If we're running under gamescope we have to set WAYLAND_DISPLAY for winit to // If we're running under gamescope we have to set WAYLAND_DISPLAY for winit to
// use // use
if let Ok(gamescope) = env::var("GAMESCOPE_WAYLAND_DISPLAY") { if let Ok(gamescope) = env::var("GAMESCOPE_WAYLAND_DISPLAY") {
debug!("Gamescope detected");
if !gamescope.is_empty() {
debug!("Setting WAYLAND_DISPLAY to {}", gamescope);
env::set_var("WAYLAND_DISPLAY", gamescope); env::set_var("WAYLAND_DISPLAY", gamescope);
} }
// gamescope-0
else if let Ok(wayland) = env::var("WAYLAND_DISPLAY") {
debug!("Wayland display detected");
if wayland.is_empty() {
debug!("Setting WAYLAND_DISPLAY to gamescope-0");
env::set_var("WAYLAND_DISPLAY", "gamescope-0");
}
}
}
// Try to open a proxy and check for app state first // Try to open a proxy and check for app state first
{ {
@@ -63,7 +80,7 @@ async fn main() -> Result<()> {
.unwrap(); .unwrap();
if asusd_version != self_version { if asusd_version != self_version {
println!("Version mismatch: asusctl = {self_version}, asusd = {asusd_version}"); println!("Version mismatch: asusctl = {self_version}, asusd = {asusd_version}");
return Ok(()); // return Ok(());
} }
// start tokio // start tokio
@@ -90,7 +107,7 @@ async fn main() -> Result<()> {
let board_name = dmi.board_name; let board_name = dmi.board_name;
let prod_family = dmi.product_family; let prod_family = dmi.product_family;
info!("Running on {board_name}, product: {prod_family}"); info!("Running on {board_name}, product: {prod_family}");
let is_rog_ally = prod_family == "RC71L" || prod_family == "RC72L"; let is_rog_ally = board_name == "RC71L" || board_name == "RC72L" || prod_family == "ROG Ally";
let args: Vec<String> = args().skip(1).collect(); let args: Vec<String> = args().skip(1).collect();
@@ -161,6 +178,32 @@ async fn main() -> Result<()> {
thread::spawn(move || { thread::spawn(move || {
let mut state = AppState::StartingUp; let mut state = AppState::StartingUp;
loop { loop {
if is_rog_ally {
let config_copy_2 = config.clone();
let newui = setup_window(config.clone());
newui.window().on_close_requested(move || {
exit(0);
});
let ui_copy = newui.as_weak();
newui
.window()
.set_rendering_notifier(move |s, _| {
if let slint::RenderingState::BeforeRendering = s {
let config = config_copy_2.clone();
ui_copy
.upgrade_in_event_loop(move |w| {
let fullscreen =
config.lock().is_ok_and(|c| c.start_fullscreen);
if fullscreen && !w.window().is_fullscreen() {
w.window().set_fullscreen(fullscreen);
}
})
.ok();
}
})
.ok();
} else {
// save as a var, don't hold the lock the entire time or deadlocks happen // save as a var, don't hold the lock the entire time or deadlocks happen
if let Ok(app_state) = app_state.lock() { if let Ok(app_state) = app_state.lock() {
state = *app_state; state = *app_state;
@@ -205,8 +248,9 @@ async fn main() -> Result<()> {
let config = config_copy_2.clone(); let config = config_copy_2.clone();
ui_copy ui_copy
.upgrade_in_event_loop(move |w| { .upgrade_in_event_loop(move |w| {
let fullscreen = let fullscreen = config
config.lock().is_ok_and(|c| c.start_fullscreen); .lock()
.is_ok_and(|c| c.start_fullscreen);
if fullscreen && !w.window().is_fullscreen() { if fullscreen && !w.window().is_fullscreen() {
w.window().set_fullscreen(fullscreen); w.window().set_fullscreen(fullscreen);
} }
@@ -232,6 +276,7 @@ async fn main() -> Result<()> {
} }
} }
} }
}
}); });
slint::run_event_loop_until_quit().unwrap(); slint::run_event_loop_until_quit().unwrap();

View File

@@ -5,7 +5,7 @@ use rog_aura::{AuraEffect, AuraModeNum, AuraZone};
use rog_platform::platform::GpuMode; use rog_platform::platform::GpuMode;
use rog_platform::supported::{ use rog_platform::supported::{
AdvancedAura, AnimeSupportedFunctions, ChargeSupportedFunctions, LedSupportedFunctions, AdvancedAura, AnimeSupportedFunctions, ChargeSupportedFunctions, LedSupportedFunctions,
PlatformProfileFunctions, RogBiosSupportedFunctions, SupportedFunctions PlatformProfileFunctions, RogBiosSupportedFunctions, SupportedFunctions,
}; };
use rog_profiles::fan_curve_set::{CurveData, FanCurveSet}; use rog_profiles::fan_curve_set::{CurveData, FanCurveSet};
use supergfxctl::pci_device::{GfxMode, GfxPower}; use supergfxctl::pci_device::{GfxMode, GfxPower};
@@ -16,7 +16,7 @@ const NOPE: &str = "";
#[derive(Default)] #[derive(Default)]
pub struct DaemonProxyBlocking<'a> { pub struct DaemonProxyBlocking<'a> {
_phantom: &'a str _phantom: &'a str,
} }
impl<'a> DaemonProxyBlocking<'a> { impl<'a> DaemonProxyBlocking<'a> {
@@ -35,7 +35,7 @@ impl<'a> DaemonProxyBlocking<'a> {
#[derive(Default)] #[derive(Default)]
pub struct RogDbusClientBlocking<'a> { pub struct RogDbusClientBlocking<'a> {
_phantom: &'a str _phantom: &'a str,
} }
impl<'a> RogDbusClientBlocking<'a> { impl<'a> RogDbusClientBlocking<'a> {
@@ -126,16 +126,16 @@ impl Profile {
pub fn fan_curve_data(&self, _p: rog_profiles::Profile) -> Result<FanCurveSet> { pub fn fan_curve_data(&self, _p: rog_profiles::Profile) -> Result<FanCurveSet> {
let mut curve = FanCurveSet::default(); let mut curve = FanCurveSet::default();
curve.cpu.pwm = [ curve.cpu.pwm = [
30, 40, 60, 100, 140, 180, 200, 250 30, 40, 60, 100, 140, 180, 200, 250,
]; ];
curve.cpu.temp = [ curve.cpu.temp = [
20, 30, 40, 50, 70, 80, 90, 100 20, 30, 40, 50, 70, 80, 90, 100,
]; ];
curve.gpu.pwm = [ curve.gpu.pwm = [
40, 80, 100, 140, 170, 200, 230, 250 40, 80, 100, 140, 170, 200, 230, 250,
]; ];
curve.gpu.temp = [ curve.gpu.temp = [
20, 30, 40, 50, 70, 80, 90, 100 20, 30, 40, 50, 70, 80, 90, 100,
]; ];
Ok(curve) Ok(curve)
} }
@@ -204,7 +204,7 @@ impl Led {
AuraDevRog2::AwakeKeyb, AuraDevRog2::AwakeKeyb,
AuraDevRog2::SleepLogo, AuraDevRog2::SleepLogo,
AuraDevRog2::AwakeLogo, AuraDevRog2::AwakeLogo,
] ],
}) })
} }
@@ -242,11 +242,11 @@ impl Supported {
Ok(SupportedFunctions { Ok(SupportedFunctions {
anime_ctrl: AnimeSupportedFunctions(true), anime_ctrl: AnimeSupportedFunctions(true),
charge_ctrl: ChargeSupportedFunctions { charge_ctrl: ChargeSupportedFunctions {
charge_level_set: true charge_level_set: true,
}, },
platform_profile: PlatformProfileFunctions { platform_profile: PlatformProfileFunctions {
platform_profile: true, platform_profile: true,
fan_curves: true fan_curves: true,
}, },
keyboard_led: LedSupportedFunctions { keyboard_led: LedSupportedFunctions {
dev_id: AuraDevice::X19b6, dev_id: AuraDevice::X19b6,
@@ -267,7 +267,7 @@ impl Supported {
AuraZone::BarRight, AuraZone::BarRight,
AuraZone::Logo, AuraZone::Logo,
], ],
advanced_type: AdvancedAura::PerKey advanced_type: AdvancedAura::PerKey,
}, },
rog_bios_ctrl: RogBiosSupportedFunctions { rog_bios_ctrl: RogBiosSupportedFunctions {
post_sound: true, post_sound: true,
@@ -275,8 +275,8 @@ impl Supported {
panel_overdrive: true, panel_overdrive: true,
dgpu_disable: true, dgpu_disable: true,
mini_led_mode: true, mini_led_mode: true,
egpu_enable: true egpu_enable: true,
} },
}) })
} }
} }

View File

@@ -10,16 +10,12 @@ use std::sync::{Arc, Mutex};
use std::time::Duration; use std::time::Duration;
use log::{debug, error, info, warn}; use log::{debug, error, info, warn};
use notify_rust::{Hint, Notification, Timeout, Urgency}; use notify_rust::{Hint, Notification, Timeout};
use rog_platform::platform::GpuMode;
use rog_platform::power::AsusPower; use rog_platform::power::AsusPower;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use supergfxctl::actions::UserActionRequired as GfxUserAction; use supergfxctl::pci_device::GfxPower;
use supergfxctl::pci_device::{GfxMode, GfxPower};
use supergfxctl::zbus_proxy::DaemonProxy as SuperProxy;
use tokio::runtime::Runtime; use tokio::runtime::Runtime;
use tokio::task::JoinHandle; use tokio::task::JoinHandle;
use zbus::export::futures_util::StreamExt;
use crate::config::Config; use crate::config::Config;
use crate::error::Result; use crate::error::Result;
@@ -31,7 +27,7 @@ const NOTIF_HEADER: &str = "ROG Control";
pub struct EnabledNotifications { pub struct EnabledNotifications {
pub enabled: bool, pub enabled: bool,
pub receive_notify_gfx: bool, pub receive_notify_gfx: bool,
pub receive_notify_gfx_status: bool pub receive_notify_gfx_status: bool,
} }
impl Default for EnabledNotifications { impl Default for EnabledNotifications {
@@ -39,7 +35,7 @@ impl Default for EnabledNotifications {
Self { Self {
enabled: true, enabled: true,
receive_notify_gfx: true, receive_notify_gfx: true,
receive_notify_gfx_status: true receive_notify_gfx_status: true,
} }
} }
} }
@@ -92,7 +88,7 @@ fn start_dpu_status_mon(config: Arc<Mutex<Config>>) {
pub fn start_notifications( pub fn start_notifications(
config: Arc<Mutex<Config>>, config: Arc<Mutex<Config>>,
rt: &Runtime rt: &Runtime,
) -> Result<Vec<JoinHandle<()>>> { ) -> Result<Vec<JoinHandle<()>>> {
// Setup the AC/BAT commands that will run on power status change // Setup the AC/BAT commands that will run on power status change
let config_copy = config.clone(); let config_copy = config.clone();
@@ -116,26 +112,26 @@ pub fn start_notifications(
if p == 0 && p != last_state { if p == 0 && p != last_state {
let prog: Vec<&str> = bat.split_whitespace().collect(); let prog: Vec<&str> = bat.split_whitespace().collect();
if prog.len() > 1 { if (!prog.is_empty()) && (!prog[0].is_empty()) {
let mut cmd = Command::new(prog[0]); let mut cmd = Command::new(prog[0]);
for arg in prog.iter().skip(1) { for arg in prog.iter().skip(1) {
cmd.arg(*arg); cmd.arg(*arg);
} }
cmd.spawn() cmd.spawn()
.map_err(|e| error!("AC command error: {e:?}")) .map_err(|e| error!("Battery power command error: {e:?}"))
.ok(); .ok();
} }
} else if p != last_state { } else if p != last_state {
let prog: Vec<&str> = ac.split_whitespace().collect(); let prog: Vec<&str> = ac.split_whitespace().collect();
if prog.len() > 1 { if (!prog.is_empty()) && (!prog[0].is_empty()) {
let mut cmd = Command::new(prog[0]); let mut cmd = Command::new(prog[0]);
for arg in prog.iter().skip(1) { for arg in prog.iter().skip(1) {
cmd.arg(*arg); cmd.arg(*arg);
} }
cmd.spawn() cmd.spawn()
.map_err(|e| error!("AC command error: {e:?}")) .map_err(|e| error!("AC power command error: {e:?}"))
.ok(); .ok();
} }
} }
@@ -145,12 +141,8 @@ pub fn start_notifications(
} }
}); });
let enabled_notifications_copy = config.clone(); info!("Attempting to start plain dgpu status monitor");
let no_supergfx = move |e: &zbus::Error| { start_dpu_status_mon(config.clone());
error!("zbus signal: receive_notify_gfx_status: {e}");
warn!("Attempting to start plain dgpu status monitor");
start_dpu_status_mon(enabled_notifications_copy.clone());
};
// GPU MUX Mode notif // GPU MUX Mode notif
// TODO: need to get armoury attrs and iter to find // TODO: need to get armoury attrs and iter to find
@@ -189,90 +181,12 @@ pub fn start_notifications(
// Ok::<(), zbus::Error>(()) // Ok::<(), zbus::Error>(())
// }); // });
let enabled_notifications_copy = config.clone();
// GPU Mode change/action notif
tokio::spawn(async move {
let conn = zbus::Connection::system().await.inspect_err(|e| {
no_supergfx(e);
})?;
let proxy = SuperProxy::builder(&conn).build().await.inspect_err(|e| {
no_supergfx(e);
})?;
let _ = proxy.mode().await.inspect_err(|e| {
no_supergfx(e);
})?;
let proxy_copy = proxy.clone();
let mut p = proxy.receive_notify_action().await?;
tokio::spawn(async move {
info!("Started zbus signal thread: receive_notify_action");
while let Some(e) = p.next().await {
if let Ok(out) = e.args() {
let action = out.action();
let mode = convert_gfx_mode(proxy.mode().await.unwrap_or_default());
match action {
supergfxctl::actions::UserActionRequired::Reboot => {
do_mux_notification("Graphics mode change requires reboot", &mode)
}
_ => do_gfx_action_notif(<&str>::from(action), *action, mode)
}
.map_err(|e| {
error!("zbus signal: do_gfx_action_notif: {e}");
e
})
.ok();
}
}
});
let mut p = proxy_copy.receive_notify_gfx_status().await?;
tokio::spawn(async move {
info!("Started zbus signal thread: receive_notify_gfx_status");
let mut last_status = GfxPower::Unknown;
while let Some(e) = p.next().await {
if let Ok(out) = e.args() {
let status = out.status;
if status != GfxPower::Unknown && status != last_status {
if let Ok(config) = enabled_notifications_copy.lock() {
if !config.notifications.receive_notify_gfx_status
|| !config.notifications.enabled
{
continue;
}
}
// Required check because status cycles through
// active/unknown/suspended
do_gpu_status_notif("dGPU status changed:", &status)
.show_async()
.await
.unwrap()
.on_close(|_| ());
}
last_status = status;
}
}
});
Ok::<(), zbus::Error>(())
});
Ok(vec![blocking]) Ok(vec![blocking])
} }
fn convert_gfx_mode(gfx: GfxMode) -> GpuMode {
match gfx {
GfxMode::Hybrid => GpuMode::Optimus,
GfxMode::Integrated => GpuMode::Integrated,
GfxMode::NvidiaNoModeset => GpuMode::Optimus,
GfxMode::Vfio => GpuMode::Vfio,
GfxMode::AsusEgpu => GpuMode::Egpu,
GfxMode::AsusMuxDgpu => GpuMode::Ultimate,
GfxMode::None => GpuMode::Error
}
}
fn base_notification<T>(message: &str, data: &T) -> Notification fn base_notification<T>(message: &str, data: &T) -> Notification
where where
T: Display T: Display,
{ {
let mut notif = Notification::new(); let mut notif = Notification::new();
notif notif
@@ -290,100 +204,8 @@ fn do_gpu_status_notif(message: &str, data: &GfxPower) -> Notification {
GfxPower::Off => "asus_notif_green", GfxPower::Off => "asus_notif_green",
GfxPower::AsusDisabled => "asus_notif_white", GfxPower::AsusDisabled => "asus_notif_white",
GfxPower::AsusMuxDiscreet | GfxPower::Active => "asus_notif_red", GfxPower::AsusMuxDiscreet | GfxPower::Active => "asus_notif_red",
GfxPower::Unknown => "gpu-integrated" GfxPower::Unknown => "gpu-integrated",
}; };
notif.icon(icon); notif.icon(icon);
notif notif
} }
fn do_gfx_action_notif(message: &str, action: GfxUserAction, mode: GpuMode) -> Result<()> {
if matches!(action, GfxUserAction::Reboot) {
do_mux_notification("Graphics mode change requires reboot", &mode).ok();
return Ok(());
}
let mut notif = Notification::new();
notif
.appname(NOTIF_HEADER)
.summary(&format!("Changing to {mode}. {message}"))
//.hint(Hint::Resident(true))
.hint(Hint::Category("device".into()))
.urgency(Urgency::Critical)
.timeout(Timeout::Never)
.icon("dialog-warning")
.hint(Hint::Transient(true));
if matches!(action, GfxUserAction::Logout) {
notif.action("gfx-mode-session-action", "Logout");
let handle = notif.show()?;
if let Ok(desktop) = std::env::var("XDG_CURRENT_DESKTOP") {
if desktop.to_lowercase() == "gnome" {
handle.wait_for_action(|id| {
if id == "gfx-mode-session-action" {
let mut cmd = Command::new("gnome-session-quit");
cmd.spawn().ok();
} else if id == "__closed" {
// TODO: cancel the switching
}
});
} else if desktop.to_lowercase() == "kde" {
handle.wait_for_action(|id| {
if id == "gfx-mode-session-action" {
let mut cmd = Command::new("qdbus");
cmd.args([
"org.kde.ksmserver", "/KSMServer", "logout", "1", "0", "0"
]);
cmd.spawn().ok();
} else if id == "__closed" {
// TODO: cancel the switching
}
});
} else {
// todo: handle alternatives
}
}
} else {
notif.show()?;
}
Ok(())
}
/// Actual `GpuMode` unused as data is never correct until switched by reboot
fn do_mux_notification(message: &str, m: &GpuMode) -> Result<()> {
let mut notif = base_notification(message, &m.to_string());
notif
.action("gfx-mode-session-action", "Reboot")
.urgency(Urgency::Critical)
.icon("system-reboot-symbolic")
.hint(Hint::Transient(true));
let handle = notif.show()?;
std::thread::spawn(|| {
if let Ok(desktop) = std::env::var("XDG_CURRENT_DESKTOP") {
if desktop.to_lowercase() == "gnome" {
handle.wait_for_action(|id| {
if id == "gfx-mode-session-action" {
let mut cmd = Command::new("gnome-session-quit");
cmd.arg("--reboot");
cmd.spawn().ok();
} else if id == "__closed" {
// TODO: cancel the switching
}
});
} else if desktop.to_lowercase() == "kde" {
handle.wait_for_action(|id| {
if id == "gfx-mode-session-action" {
let mut cmd = Command::new("qdbus");
cmd.args([
"org.kde.ksmserver", "/KSMServer", "logout", "1", "1", "0"
]);
cmd.spawn().ok();
} else if id == "__closed" {
// TODO: cancel the switching
}
});
}
}
});
Ok(())
}

View File

@@ -24,7 +24,7 @@ struct Icons {
rog_red: Icon, rog_red: Icon,
rog_green: Icon, rog_green: Icon,
rog_white: Icon, rog_white: Icon,
gpu_integrated: Icon gpu_integrated: Icon,
} }
static ICONS: OnceLock<Icons> = OnceLock::new(); static ICONS: OnceLock<Icons> = OnceLock::new();
@@ -32,7 +32,10 @@ static ICONS: OnceLock<Icons> = OnceLock::new();
fn read_icon(file: &Path) -> Icon { fn read_icon(file: &Path) -> Icon {
let mut path = PathBuf::from(TRAY_ICON_PATH); let mut path = PathBuf::from(TRAY_ICON_PATH);
path.push(file); path.push(file);
let mut file = OpenOptions::new().read(true).open(path).unwrap(); let mut file = OpenOptions::new()
.read(true)
.open(&path)
.unwrap_or_else(|_| panic!("Missing icon: {:?}", path));
let mut bytes = Vec::new(); let mut bytes = Vec::new();
file.read_to_end(&mut bytes).unwrap(); file.read_to_end(&mut bytes).unwrap();
@@ -48,14 +51,14 @@ fn read_icon(file: &Path) -> Icon {
Icon { Icon {
width: width as i32, width: width as i32,
height: height as i32, height: height as i32,
data: img.into_raw() data: img.into_raw(),
} }
} }
struct AsusTray { struct AsusTray {
current_title: String, current_title: String,
current_icon: Icon, current_icon: Icon,
proxy: ROGCCZbusProxyBlocking<'static> proxy: ROGCCZbusProxyBlocking<'static>,
} }
impl ksni::Tray for AsusTray { impl ksni::Tray for AsusTray {
@@ -103,7 +106,7 @@ async fn set_tray_icon_and_tip(
mode: GfxMode, mode: GfxMode,
power: GfxPower, power: GfxPower,
tray: &mut Handle<AsusTray>, tray: &mut Handle<AsusTray>,
supergfx_active: bool supergfx_active: bool,
) { ) {
if let Some(icons) = ICONS.get() { if let Some(icons) = ICONS.get() {
let icon = match power { let icon = match power {
@@ -162,12 +165,12 @@ pub fn init_tray(_supported_properties: Vec<Properties>, config: Arc<Mutex<Confi
let tray_init = AsusTray { let tray_init = AsusTray {
current_title: TRAY_LABEL.to_string(), current_title: TRAY_LABEL.to_string(),
current_icon: rog_red.clone(), current_icon: rog_red.clone(),
proxy proxy,
}; };
// TODO: return an error to the UI // TODO: return an error to the UI
let mut tray; let mut tray;
match tray_init.spawn_without_dbus_name().await { match tray_init.disable_dbus_name(true).spawn().await {
Ok(t) => tray = t, Ok(t) => tray = t,
Err(e) => { Err(e) => {
log::error!( log::error!(
@@ -187,7 +190,7 @@ pub fn init_tray(_supported_properties: Vec<Properties>, config: Arc<Mutex<Confi
rog_red: rog_red.clone(), rog_red: rog_red.clone(),
rog_green, rog_green,
rog_white, rog_white,
gpu_integrated gpu_integrated,
}); });
let mut has_supergfx = false; let mut has_supergfx = false;
@@ -215,8 +218,8 @@ pub fn init_tray(_supported_properties: Vec<Properties>, config: Arc<Mutex<Confi
may not be running or installed" may not be running or installed"
) )
} }
_ => warn!("Couldn't get mode from supergfxd: {e:?}") _ => warn!("Couldn't get mode from supergfxd: {e:?}"),
} },
} }
info!("Started ROGTray"); info!("Started ROGTray");

View File

@@ -1,6 +1,6 @@
use crate::slint_generatedMainWindow::{ use crate::slint_generatedMainWindow::{
AuraDevType as SlintDeviceType, AuraPowerState as SlintAuraPowerState, AuraDevType as SlintDeviceType, AuraPowerState as SlintAuraPowerState,
LaptopAuraPower as SlintLaptopAuraPower LaptopAuraPower as SlintLaptopAuraPower,
}; };
impl From<rog_aura::AuraEffect> for crate::slint_generatedMainWindow::AuraEffect { impl From<rog_aura::AuraEffect> for crate::slint_generatedMainWindow::AuraEffect {
@@ -10,20 +10,20 @@ impl From<rog_aura::AuraEffect> for crate::slint_generatedMainWindow::AuraEffect
red: m.colour1.r, red: m.colour1.r,
green: m.colour1.g, green: m.colour1.g,
blue: m.colour1.b, blue: m.colour1.b,
alpha: 255 alpha: 255,
} }
.into(), .into(),
colour2: RgbaColor { colour2: RgbaColor {
red: m.colour2.r, red: m.colour2.r,
green: m.colour2.g, green: m.colour2.g,
blue: m.colour2.b, blue: m.colour2.b,
alpha: 255 alpha: 255,
} }
.into(), .into(),
direction: m.direction.into(), direction: m.direction.into(),
mode: m.mode.into(), mode: m.mode.into(),
speed: m.speed.into(), speed: m.speed.into(),
zone: m.zone.into() zone: m.zone.into(),
} }
} }
} }
@@ -36,17 +36,17 @@ impl From<crate::slint_generatedMainWindow::AuraEffect> for rog_aura::AuraEffect
colour1: rog_aura::Colour { colour1: rog_aura::Colour {
r: c1.red, r: c1.red,
g: c1.green, g: c1.green,
b: c1.blue b: c1.blue,
}, },
colour2: rog_aura::Colour { colour2: rog_aura::Colour {
r: c2.red, r: c2.red,
g: c2.green, g: c2.green,
b: c2.blue b: c2.blue,
}, },
direction: m.direction.into(), direction: m.direction.into(),
mode: m.mode.into(), mode: m.mode.into(),
speed: m.speed.into(), speed: m.speed.into(),
zone: m.zone.into() zone: m.zone.into(),
} }
} }
} }
@@ -66,7 +66,7 @@ impl From<PowerZones> for SlintPowerZones {
PowerZones::RearGlow => SlintPowerZones::RearGlow, PowerZones::RearGlow => SlintPowerZones::RearGlow,
PowerZones::KeyboardAndLightbar => SlintPowerZones::KeyboardAndLightbar, PowerZones::KeyboardAndLightbar => SlintPowerZones::KeyboardAndLightbar,
PowerZones::Ally => SlintPowerZones::Ally, PowerZones::Ally => SlintPowerZones::Ally,
PowerZones::None => SlintPowerZones::Keyboard PowerZones::None => SlintPowerZones::Keyboard,
} }
} }
} }
@@ -80,7 +80,7 @@ impl From<SlintPowerZones> for PowerZones {
SlintPowerZones::Lid => PowerZones::Lid, SlintPowerZones::Lid => PowerZones::Lid,
SlintPowerZones::RearGlow => PowerZones::RearGlow, SlintPowerZones::RearGlow => PowerZones::RearGlow,
SlintPowerZones::KeyboardAndLightbar => PowerZones::KeyboardAndLightbar, SlintPowerZones::KeyboardAndLightbar => PowerZones::KeyboardAndLightbar,
SlintPowerZones::Ally => PowerZones::Ally SlintPowerZones::Ally => PowerZones::Ally,
} }
} }
} }
@@ -92,7 +92,7 @@ impl From<SlintAuraPowerState> for AuraPowerState {
boot: value.boot, boot: value.boot,
awake: value.awake, awake: value.awake,
sleep: value.sleep, sleep: value.sleep,
shutdown: value.shutdown shutdown: value.shutdown,
} }
} }
} }
@@ -106,7 +106,7 @@ impl From<AuraPowerState> for SlintAuraPowerState {
sleep: value.sleep, sleep: value.sleep,
shutdown: value.shutdown, shutdown: value.shutdown,
zone, zone,
zone_name_idx: zone as i32 zone_name_idx: zone as i32,
} }
} }
} }
@@ -120,7 +120,7 @@ impl From<&AuraPowerState> for SlintAuraPowerState {
sleep: value.sleep, sleep: value.sleep,
shutdown: value.shutdown, shutdown: value.shutdown,
zone, zone,
zone_name_idx: zone as i32 zone_name_idx: zone as i32,
} }
} }
} }
@@ -140,7 +140,7 @@ impl From<LaptopAuraPower> for SlintLaptopAuraPower {
let converted: Vec<SlintAuraPowerState> = let converted: Vec<SlintAuraPowerState> =
value.states.iter().map(SlintAuraPowerState::from).collect(); value.states.iter().map(SlintAuraPowerState::from).collect();
Self { Self {
states: ModelRc::from(converted.as_slice()) states: ModelRc::from(converted.as_slice()),
} }
} }
} }
@@ -154,7 +154,7 @@ impl From<SlintDeviceType> for AuraDeviceType {
SlintDeviceType::ScsiExtDisk => Self::ScsiExtDisk, SlintDeviceType::ScsiExtDisk => Self::ScsiExtDisk,
SlintDeviceType::Unknown => Self::Unknown, SlintDeviceType::Unknown => Self::Unknown,
SlintDeviceType::Ally => Self::Ally, SlintDeviceType::Ally => Self::Ally,
SlintDeviceType::AnimeOrSlash => Self::AnimeOrSlash SlintDeviceType::AnimeOrSlash => Self::AnimeOrSlash,
} }
} }
} }
@@ -168,7 +168,7 @@ impl From<AuraDeviceType> for SlintDeviceType {
AuraDeviceType::ScsiExtDisk => SlintDeviceType::ScsiExtDisk, AuraDeviceType::ScsiExtDisk => SlintDeviceType::ScsiExtDisk,
AuraDeviceType::Unknown => SlintDeviceType::Unknown, AuraDeviceType::Unknown => SlintDeviceType::Unknown,
AuraDeviceType::Ally => SlintDeviceType::Ally, AuraDeviceType::Ally => SlintDeviceType::Ally,
AuraDeviceType::AnimeOrSlash => SlintDeviceType::AnimeOrSlash AuraDeviceType::AnimeOrSlash => SlintDeviceType::AnimeOrSlash,
} }
} }
} }

View File

@@ -8,7 +8,9 @@ impl From<Profile> for PlatformProfile {
match value { match value {
Profile::Balanced => PlatformProfile::Balanced, Profile::Balanced => PlatformProfile::Balanced,
Profile::Performance => PlatformProfile::Performance, Profile::Performance => PlatformProfile::Performance,
Profile::Quiet => PlatformProfile::Quiet Profile::Quiet => PlatformProfile::Quiet,
Profile::LowPower => PlatformProfile::LowPower,
Profile::Custom => PlatformProfile::Custom,
} }
} }
} }
@@ -18,7 +20,9 @@ impl From<PlatformProfile> for Profile {
match value { match value {
PlatformProfile::Balanced => Profile::Balanced, PlatformProfile::Balanced => Profile::Balanced,
PlatformProfile::Performance => Profile::Performance, PlatformProfile::Performance => Profile::Performance,
PlatformProfile::Quiet => Profile::Quiet PlatformProfile::Quiet => Profile::Quiet,
PlatformProfile::LowPower => Profile::LowPower,
PlatformProfile::Custom => Profile::Custom,
} }
} }
} }
@@ -28,7 +32,7 @@ impl From<FanType> for FanCurvePU {
match value { match value {
FanType::CPU => FanCurvePU::CPU, FanType::CPU => FanCurvePU::CPU,
FanType::Middle => FanCurvePU::MID, FanType::Middle => FanCurvePU::MID,
FanType::GPU => FanCurvePU::GPU FanType::GPU => FanCurvePU::GPU,
} }
} }
} }
@@ -38,7 +42,7 @@ impl From<FanCurvePU> for FanType {
match value { match value {
FanCurvePU::CPU => FanType::CPU, FanCurvePU::CPU => FanType::CPU,
FanCurvePU::GPU => FanType::GPU, FanCurvePU::GPU => FanType::GPU,
FanCurvePU::MID => FanType::Middle FanCurvePU::MID => FanType::Middle,
} }
} }
} }

View File

@@ -50,7 +50,7 @@ macro_rules! set_ui_callbacks {
tokio::spawn(async move { tokio::spawn(async move {
let mut x = proxy_copy.receive().await; let mut x = proxy_copy.receive().await;
concat_idents::concat_idents!(set = set_, $proxy_fn { concat_idents::concat_idents!(set = set_, $proxy_fn {
use zbus::export::futures_util::StreamExt; use futures_util::StreamExt;
while let Some(e) = x.next().await { while let Some(e) = x.next().await {
if let Ok(out) = e.get().await { if let Ok(out) = e.get().await {
handle_copy.upgrade_in_event_loop(move |handle| { handle_copy.upgrade_in_event_loop(move |handle| {
@@ -68,7 +68,7 @@ pub fn show_toast(
success: SharedString, success: SharedString,
fail: SharedString, fail: SharedString,
handle: Weak<MainWindow>, handle: Weak<MainWindow>,
result: zbus::Result<()> result: zbus::Result<()>,
) { ) {
match result { match result {
Ok(_) => { Ok(_) => {
@@ -78,7 +78,7 @@ pub fn show_toast(
log::warn!("{fail}: {e}"); log::warn!("{fail}: {e}");
handle.unwrap().invoke_show_toast(fail) handle.unwrap().invoke_show_toast(fail)
}) })
.ok() .ok(),
}; };
} }
@@ -86,8 +86,13 @@ pub fn setup_window(config: Arc<Mutex<Config>>) -> MainWindow {
slint::set_xdg_app_id("rog-control-center") slint::set_xdg_app_id("rog-control-center")
.map_err(|e| warn!("Couldn't set application ID: {e:?}")) .map_err(|e| warn!("Couldn't set application ID: {e:?}"))
.ok(); .ok();
let ui = MainWindow::new().unwrap(); let ui = MainWindow::new()
ui.window().show().unwrap(); .map_err(|e| warn!("Couldn't create main window: {e:?}"))
.unwrap();
ui.window()
.show()
.map_err(|e| warn!("Couldn't show main window: {e:?}"))
.unwrap();
let available = list_iface_blocking().unwrap_or_default(); let available = list_iface_blocking().unwrap_or_default();
ui.set_sidebar_items_avilable( ui.set_sidebar_items_avilable(
@@ -98,9 +103,9 @@ pub fn setup_window(config: Arc<Mutex<Config>>) -> MainWindow {
available.contains(&"xyz.ljones.Anime".to_string()), available.contains(&"xyz.ljones.Anime".to_string()),
available.contains(&"xyz.ljones.FanCurves".to_string()), available.contains(&"xyz.ljones.FanCurves".to_string()),
true, true,
true true,
] ]
.into() .into(),
); );
ui.on_exit_app(move || { ui.on_exit_app(move || {

View File

@@ -51,9 +51,9 @@ pub fn setup_anime_page(ui: &MainWindow, _states: Arc<Mutex<Config>>) {
boot: boot.into(), boot: boot.into(),
awake: awake.into(), awake: awake.into(),
sleep: sleep.into(), sleep: sleep.into(),
shutdown: shutdown.into() shutdown: shutdown.into(),
}) })
.await .await,
); );
}); });
}); });
@@ -62,7 +62,7 @@ pub fn setup_anime_page(ui: &MainWindow, _states: Arc<Mutex<Config>>) {
let anime_copy = anime.clone(); let anime_copy = anime.clone();
tokio::spawn(async move { tokio::spawn(async move {
let mut x = anime_copy.receive_builtin_animations_changed().await; let mut x = anime_copy.receive_builtin_animations_changed().await;
use zbus::export::futures_util::StreamExt; use futures_util::StreamExt;
while let Some(e) = x.next().await { while let Some(e) = x.next().await {
if let Ok(out) = e.get().await { if let Ok(out) = e.get().await {
handle_copy handle_copy

View File

@@ -9,7 +9,7 @@ use slint::{ComponentHandle, Model, RgbaColor, SharedString};
use crate::config::Config; use crate::config::Config;
use crate::ui::show_toast; use crate::ui::show_toast;
use crate::{ use crate::{
set_ui_callbacks, set_ui_props_async, AuraPageData, MainWindow, PowerZones as SlintPowerZones set_ui_callbacks, set_ui_props_async, AuraPageData, MainWindow, PowerZones as SlintPowerZones,
}; };
fn decode_hex(s: &str) -> RgbaColor<u8> { fn decode_hex(s: &str) -> RgbaColor<u8> {
@@ -19,7 +19,7 @@ fn decode_hex(s: &str) -> RgbaColor<u8> {
alpha: 255, alpha: 255,
red: 0, red: 0,
green: 0, green: 0,
blue: 0 blue: 0,
}; };
} }
let c: Vec<u8> = (0..s.len()) let c: Vec<u8> = (0..s.len())
@@ -30,7 +30,7 @@ fn decode_hex(s: &str) -> RgbaColor<u8> {
alpha: 255, alpha: 255,
red: *c.first().unwrap_or(&255), red: *c.first().unwrap_or(&255),
green: *c.get(1).unwrap_or(&128), green: *c.get(1).unwrap_or(&128),
blue: *c.get(2).unwrap_or(&32) blue: *c.get(2).unwrap_or(&32),
} }
} }
@@ -198,7 +198,7 @@ pub fn setup_aura_page(ui: &MainWindow, _states: Arc<Mutex<Config>>) {
"Aura power settings changed".into(), "Aura power settings changed".into(),
"Failed to set Aura power settings".into(), "Failed to set Aura power settings".into(),
handle_copy, handle_copy,
proxy_copy.set_led_power(power).await proxy_copy.set_led_power(power).await,
); );
}); });
}); });
@@ -211,7 +211,7 @@ pub fn setup_aura_page(ui: &MainWindow, _states: Arc<Mutex<Config>>) {
// spawn required since the while let never exits // spawn required since the while let never exits
tokio::spawn(async move { tokio::spawn(async move {
let mut x = proxy_copy.receive_led_mode_data_changed().await; let mut x = proxy_copy.receive_led_mode_data_changed().await;
use zbus::export::futures_util::StreamExt; use futures_util::StreamExt;
while let Some(e) = x.next().await { while let Some(e) = x.next().await {
if let Ok(out) = e.get().await { if let Ok(out) = e.get().await {
handle_copy handle_copy

Some files were not shown because too many files have changed in this diff Show More