Compare commits

...

1298 Commits

Author SHA1 Message Date
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
Luke Jones
11ac46df11 Edit README.md 2025-02-08 02:39:30 +00:00
Luke Jones
05bec93644 Edit README.md 2025-02-08 02:33:08 +00:00
Luke Jones
c77e7cf1ce Fix: correction to wrong matching function used for aura data find
Closes #607
2025-02-07 09:45:05 +13:00
Luke Jones
d30f7dc2ea Merge branch 'main' into 'main'
feat (rog-aura): ASUS TUF FA617NS AURA Support

See merge request asus-linux/asusctl!214
2025-02-05 02:58:05 +00:00
Luke Jones
759606fca3 Merge branch 'aura' into 'main'
Update 'led-mode' -> 'aura' in example command.

See merge request asus-linux/asusctl!215
2025-02-05 02:57:38 +00:00
Luke Jones
25ed8bdeed Fix spelling mistake 2025-02-05 14:35:17 +13:00
Luke Jones
de61a15b7a Prep 6.1.0 2025-02-04 18:52:55 +13:00
Luke Jones
16700e55f4 ROGCC: refactor many more parts of the PPT settings 2025-02-04 18:50:48 +13:00
Luke Jones
5833a011ce Merge branch 'g513rc-zonefix' into 'main'
Add basic zones for G513RC

See merge request asus-linux/asusctl!216
2025-02-03 04:08:29 +00:00
loystonpais
62577ee0e4 Add basic zones for G513RC 2025-02-03 07:36:32 +05:30
Luke Jones
dac35996b1 Enable use of GAMESCOPE_WAYLAND_DISPLAY 2025-02-02 20:02:51 +13:00
Luke Jones
5c2bcad7c6 Various UI fixes 2025-02-01 20:31:09 +13:00
sergik776
a206591e97 Added translation files for rog-control-center (RU) 2025-01-28 20:09:20 +02:00
armdebug
81f6c18a24 Update 'led-mode' -> 'aura' in example command.
led-mode is renamed to aura in 19ffcf3376
2025-01-28 02:18:56 +05:30
riarumoda
bcc3d42789 feat (rog-aura): ASUS TUF FA617NS AURA Support 2025-01-23 15:14:52 +08:00
Luke Jones
36c34cb3dd Merge branch 'fix/anime-animation-crash' into 'main'
fix: Use spawn instead of spawn_local in anime animation callback

Closes #588

See merge request asus-linux/asusctl!213
2025-01-22 02:05:04 +00:00
I-Al-Istannen
9b82b875f1 fix: Use spawn instead of spawn_local in anime animation callback
Closes #588
2025-01-21 21:04:20 +01:00
Luke D. Jones
bddccc696f Update deps 2025-01-21 19:49:20 +13:00
Luke D. Jones
51e9f10087 Prep 6.1.0-rc7 2025-01-21 16:44:58 +13:00
Luke D. Jones
911ff8690e feature: rework PPT tuning handling more
1. Per profile, per-ac/dc
2. Do not apply unless group is enabled
3. Better reset/disable handling
4. Selecting a profile defaults PPT to off/disabled
2025-01-21 16:39:34 +13:00
Luke D. Jones
25823dc6b7 asusd: anime: don't cause async deadlocks damnit
Same old song, an async mutex lock being held for a wide scope.
In particular being held for a scope that includes a function call which
also tries to get the lock.

Fix it by copy/clone of the config interior values required.

Fixes #588
2025-01-21 12:24:24 +13:00
Luke D. Jones
cba8e1a473 Add extra debug logging to anime path 2025-01-20 13:43:38 +13:00
Luke D. Jones
fb98827a1a Prep 6.1.0-rc6 2025-01-19 23:35:32 +13:00
Luke D. Jones
b9296862df Move entirely to using only platform-profile
throttle_thermal_policy is not ideal anymore and may be
removed from kernel in the future.
2025-01-19 21:52:32 +13:00
Luke D. Jones
450205f9a9 Bug fix: correctly set charge limit from UI 2025-01-19 17:29:36 +13:00
Luke D. Jones
82431ee25b Prep 6.1.0-rc5 2025-01-19 16:11:48 +13:00
Luke D. Jones
f11aea02a8 Add help and reset to UI for ppt values 2025-01-19 16:01:57 +13:00
Luke D. Jones
2d6d669c22 PPT restor defaults (WIP) 2025-01-19 12:02:22 +13:00
Luke D. Jones
f9cebf9221 Per-AC/DC per-profile tunings enabled 2025-01-19 11:33:48 +13:00
Luke D. Jones
a00808313e Prep 6.1.0-rc4 2025-01-18 23:11:46 +13:00
Luke D. Jones
3426591d32 Finalise per-profile PPT settings 2025-01-18 22:46:50 +13:00
Luke D. Jones
ef3b6636f5 Allow each performance profile to have different PPT values 2025-01-18 21:54:37 +13:00
Luke D. Jones
ee9e0a1e31 Fix: ROGCC: fix anime matrix settings 2025-01-18 21:27:57 +13:00
Luke D. Jones
9e84997cbf Fix: ROGCC: don't crash out if no tray area available 2025-01-18 20:54:25 +13:00
Luke D. Jones
2b22f82b72 Cleanup unsafe sysfs interfaces. Bugfixes for UI 2025-01-16 23:56:12 +13:00
Luke D. Jones
7a1b45071d Correct changelog rc3 tag 2025-01-15 22:25:24 +13:00
Luke D. Jones
ad63c429cb Bugfix: urgent small fixes 2025-01-15 22:19:46 +13:00
Luke D. Jones
a790d9a499 Remove dangerous use of ppt* in platform, add use of ppt_pl3_fppt in asus_armoury handler 2025-01-13 23:18:19 +13:00
Luke D. Jones
be51a1ab77 Disable strip in Makefile 2025-01-13 22:38:30 +13:00
Luke D. Jones
d9a88e7cc3 Notify user via message in UI if asus-armoury not loaded 2025-01-13 14:32:13 +13:00
Luke D. Jones
d785e17f95 Allow version in makefile to have '-rc*' 2025-01-12 18:52:45 +13:00
Luke D. Jones
efe64119c6 Prep 6.1.0-rc2 2025-01-12 17:53:32 +13:00
Luke D. Jones
128bc3fce1 Update readme, slash configs 2025-01-12 17:51:43 +13:00
Luke D. Jones
2123f369ad Small clippy cleanups 2025-01-04 20:04:07 +13:00
Luke D. Jones
2b7a2a5be3 Remove typeshare use 2025-01-03 16:37:22 +13:00
Luke D. Jones
1d9e89ef3d Update deps 2025-01-02 19:08:48 +13:00
Luke D. Jones
4011b3ebd4 ROGCC: begin using the new asus_armoury API 2025-01-01 14:47:08 +13:00
Luke D. Jones
f7456f0144 Allow changing of platform values with cli 2024-12-29 12:03:50 +13:00
Luke D. Jones
2ed2d82e03 Better print of firmware attributes in CLI 2024-12-29 11:36:22 +13:00
Luke D. Jones
d40f4733e2 Fix: prevent event loop error in ROGCC
Leftover code from parts of the refactor and tray crate change were
causing the app to crash due to the UI trying to issue a command on the
slint thread when the slint thread had not been created yet.

Closes #579
2024-12-28 22:06:16 +13:00
Luke Jones
98dc155e41 Merge branch 'feat/add-g533qs' into 'main'
feat(rog-aura): 🎸 Add G533QS aura support

See merge request asus-linux/asusctl!210
2024-12-28 04:32:17 +00:00
Luke D. Jones
fd3384decc Minor test of platform attributes 2024-12-28 10:56:34 +13:00
Luke D. Jones
a1a9c7077a Rename dbus. Add asus_armoury client source 2024-12-26 21:36:07 +13:00
Luke D. Jones
62aa1fe04f Add initial dbus draft of asus_armoury attrs 2024-12-26 16:41:17 +13:00
Luke D. Jones
a7b98c67ee Prep 6.1.0-rc1 2024-12-25 19:28:32 +13:00
Luke D. Jones
e7bbd99178 Stop GUI thread hogging CPU 2024-12-25 11:29:10 +13:00
Luke D. Jones
e2d3f99d91 Try better to capture TUF keyboard control 2024-12-25 10:31:43 +13:00
Luke D. Jones
1cad5afc0d FirmwareAttributes: further work 2024-12-24 21:50:32 +13:00
Luke D. Jones
fd31ac458d Prepare for rc1 2024-12-24 18:01:19 +13:00
Luke D. Jones
6292b3361d Re-add TUF LED support 2024-12-24 17:13:05 +13:00
Luke D. Jones
ab7a4bbad3 Refactor ROGCC to use dbus to communicate with self instead of pipe file 2024-12-24 17:13:05 +13:00
Luke D. Jones
0f2d89858e SCSI support: ROG Arion external drive LED control 2024-12-24 17:13:05 +13:00
Luke D. Jones
19ffcf3376 Refactor: Make all Aura type devices use "device_manager"
Open the door to adding many other types of "aura" devices later.
2024-12-24 17:13:05 +13:00
kamack38
72c0b24ead feat(rog-aura): 🎸 Add G533QS aura support 2024-12-23 00:18:46 +01:00
Luke D. Jones
0ddfe76c31 Minor prep 2024-12-18 11:21:40 +13:00
Luke D. Jones
c05c8ba648 Fix: prevent an aura manager deadlock 2024-12-18 10:33:14 +13:00
Luke D. Jones
ccdc576319 Switch tray to knsi crate. Many things to do 2024-12-17 22:14:13 +13:00
Luke Jones
39b16ffc91 Merge branch 'one-shot-charge' into 'main'
feat: One-shot full charge charge

See merge request asus-linux/asusctl!207
2024-12-14 22:07:47 +00:00
AlbertGG
72ff1ab3ab feat: One-shot full charge charge 2024-12-14 22:07:46 +00:00
Luke D. Jones
e7c4619ee9 Update deps 2024-11-28 16:32:42 +13:00
Luke Jones
71fcb382ea Merge branch 'G733ZW_Aura' into 'main'
G733Z(W) Aura Update

See merge request asus-linux/asusctl!208
2024-11-21 02:46:57 +00:00
Michael Campbell
e5b2e3ef11 G733Z(W) Aura Update 2024-11-21 01:25:15 +00:00
Luke Jones
dfd39522a8 Merge branch 'feature/ga605w-aura' into 'main'
feat(rog-aura): add GA605W aura support

See merge request asus-linux/asusctl!206
2024-11-13 20:13:43 +00:00
Tobias Kantusch
2759c28196 feat(rog-aura): add GA605W aura support
This adds support for aura effects on GA605W laptops.
The model is basically the same as the GU605, just with
an AMD chip, so the configuration is simply copied.
2024-11-09 23:07:59 +01:00
Luke Jones
207e199016 Merge branch 'FA506N-rainbow' into 'main'
Fa506 n rainbow

See merge request asus-linux/asusctl!203
2024-11-04 08:15:30 +00:00
Luke Jones
5f8cbdb94b Merge branch 'disable-kms' into 'main'
rog-control-center: Disable slint KMS backend

See merge request asus-linux/asusctl!204
2024-11-04 07:54:11 +00:00
Luke Jones
0853c16d5e Merge branch 'GLLM1-main-patch-64861' into 'main'
Update asusd.rules for ProArt laptops

See merge request asus-linux/asusctl!205
2024-11-04 07:51:53 +00:00
GLLM
0be04726ca Update asusd.rules for ProArt laptops (tested on P16, aka H7606W) 2024-11-03 20:14:06 +00:00
Kenny Levinsen
a672a86cc4 rog-control-center: Disable slint KMS backend
The slint KMS backend is meant to run an application without a display
server and with direct, exclusive display and input control, which is a
very specific use-case for e.g. embedded applications.

Disable the KMS backend and avoid a bunch of dependencies.
2024-11-02 20:54:24 +01:00
Lu Robles
c7ff3b44dc FA506N: use RainbowCycle instead of RainbowWave 2024-10-26 16:42:18 +02:00
Luke Jones
f0ebda9ecd Merge branch 'fa506n' into 'main'
rog-aura: fa506n: use the correct rainbow mode

See merge request asus-linux/asusctl!202
2024-10-23 14:08:45 +00:00
Sid Pranjale
b984176cd0 rog-aura: fa506n: use the correct rainbow mode 2024-10-23 17:40:29 +05:30
Luke Jones
599b1cc9ad Merge branch 'fa506n' into 'main'
rog-aura: add modes for FA506N

See merge request asus-linux/asusctl!201
2024-10-23 10:37:42 +00:00
Sid Pranjale
d93df8752e rog-aura: add modes for FA506N 2024-10-23 15:23:13 +05:30
Luke Jones
8a9564bbfa Merge branch 'main' into 'main'
add install instructions for debian(light fan can work for my G614JV)

See merge request asus-linux/asusctl!182
2024-09-08 08:07:21 +00:00
Pd.ch
5455e345b2 add install instructions for debian(light fan can work for my G614JV) 2024-09-08 08:07:21 +00:00
Luke D. Jones
520101fea1 rog-platform: Adjust current_value again, read and write directly to file path 2024-09-07 17:43:31 +12:00
Luke D. Jones
e866b4eeb1 rog-platform: change current_value() to &mut 2024-09-07 17:05:33 +12:00
Luke D. Jones
c5c46738ee Fix ally power config 2024-09-03 12:45:07 +12:00
Luke D. Jones
27ed95bd3e Fixes to config loading and updating 2024-08-31 11:16:51 +12:00
Luke D. Jones
ea9ca79a8f Point release 2024-08-30 21:32:06 +12:00
Luke D. Jones
4a97f173be Unify the aura data more. Prep for better format 2024-08-30 21:29:13 +12:00
Luke D. Jones
8f35220c5f Add Ally 1 and X as "old" style devices for power
These have a slightly different power settings data which needs to be verified.
We can use the old style for now.

Closes #542
2024-08-30 18:35:26 +12:00
Luke D. Jones
c3880d055d Fix cli args for led mode 2024-08-26 19:16:11 +12:00
Luke D. Jones
b661f67084 Many updates 2024-08-26 17:53:10 +12:00
Luke Jones
abd2ca8601 Merge branch 'main' into 'main'
Fix vendored build with feature rog-control-center/x11

See merge request asus-linux/asusctl!197
2024-08-26 04:48:12 +00:00
Luke Jones
0905ed8ad4 Merge branch 'g614jz-aura' into 'main'
Add G614JZ/JJ  (2023 Strix G16) Aura support

See merge request asus-linux/asusctl!195
2024-08-26 04:47:42 +00:00
Luke Jones
c1268d4aad Merge branch 'Chaser_1-main-patch-70824' into 'main'
Fixed a typo in README.md

See merge request asus-linux/asusctl!199
2024-08-15 10:17:59 +00:00
Christian Haser
5ed47abc32 Update README.md 2024-08-15 08:36:30 +00:00
The0919
718bb8b86f Add cargo vendor-filter all-features 2024-08-03 03:11:32 -04:00
Luke D. Jones
5ab9642b79 Update G713P 2024-07-25 23:10:57 +12:00
Luke D. Jones
14acab9a9c Add Ally X config 2024-07-25 22:52:19 +12: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
Luke Jones
e4dd485dd4 Merge branch 'main' into 'main'
Add FX517Z to aura_support

See merge request asus-linux/asusctl!196
2024-07-15 22:35:05 +00:00
Carl Dunning
ab1d75e5ec Add FX517Z to aura_support 2024-07-15 13:30:05 +01:00
ulville
e4c5df6cca Add G614JJ Aura support 2024-07-10 20:47:18 +03:00
ulville
9ee7ee26a2 Add G614JZ (2023 Strix G16) Aura support
This laptop has a 4 zone led keyboard.
Tested on my own device. G614J model
probably also has the same 4 basic zone
support but I can't test it
2024-07-10 00:47:14 +03:00
Luke Jones
e8ebdacb91 Merge branch 'fhui16776-main-patch-11114' into 'main'
Add 2023 G14 model to aura_support.ron

See merge request asus-linux/asusctl!191
2024-07-01 06:31:13 +00:00
Luke Jones
b97921fea2 Merge branch 'main' into 'main'
Simplified Chinese translation

See merge request asus-linux/asusctl!194
2024-06-24 00:16:41 +00:00
UM-Li
a3423195a6 Simplified Chinese translation 2024-06-19 10:41:16 +02:00
Luke Jones
f55edfbae0 Merge branch 'gu605-slash-support' into 'main'
Add slash detection for GU605

Closes #523

See merge request asus-linux/asusctl!193
2024-06-17 00:35:24 +00:00
banditopazzo
3e065b6715 Add slash detection for GU605 2024-06-16 17:58:49 +02:00
Luke D. Jones
f14d1ad61e Prep 6.0.11 release 2024-06-09 20:11:55 +12:00
Luke D. Jones
85d4e9cabd Update aura_support.ron 2024-06-09 12:20:32 +12:00
Luke Jones
e47a9cffd7 Merge branch 'aura-G513RM' into 'main'
Aura support for G513RM

See merge request asus-linux/asusctl!192
2024-06-07 22:23:56 +00:00
GingerBreadMuncher
ca93dc7215 Aura support for G513RM 2024-06-07 20:52:19 +00:00
fhui16776 fhui16776
93a646773c Add 2023 G14 model to aura_support.ron 2024-06-07 09:23:22 +00:00
Luke D. Jones
1cba693469 Update G713 aura spec 2024-06-07 09:22:59 +12:00
Luke D. Jones
166149b351 Remove a debug statement 2024-05-26 21:21:54 +12:00
Luke Jones
1b11b6d8fb Merge branch 'main' into 'main'
Resolve "AniMe Broken on GA402XZ"

Closes #512

See merge request asus-linux/asusctl!190
2024-05-26 21:19:40 +12:00
Mihir Patil
02568299df Fix AniMe on GA402XZ 2024-05-26 03:58:06 -04:00
Luke D. Jones
acdc93596c Ranem rainbow/strobe effects 2024-05-24 22:43:58 +12:00
Luke D. Jones
22e26adfb6 Update lang 2024-05-24 20:01:19 +12:00
Luke D. Jones
4730e645ba Fix sortof notifs 2024-05-24 18:49:23 +12:00
Luke D. Jones
d203fab70d Prep 6.0.10 2024-05-24 14:01:35 +12:00
Luke D. Jones
792fae3ed7 Enable tray and notifs without supergfx 2024-05-24 13:00:56 +12:00
Luke D. Jones
e443ab00c9 Adjust anime init sequence 2024-05-21 22:36:18 +12:00
Luke D. Jones
aee54f5756 Adjust G513Q support to match device specs 2024-05-21 10:11:56 +12:00
Luke D. Jones
00904e9603 Don't panic if -ENODEV on fan_curve enable 2024-05-19 22:38:45 +12:00
Luke D. Jones
b1212585e2 Add GA401I to aura_support
Closes #501
2024-05-18 22:56:24 +12:00
Luke D. Jones
faca084cff Prep new release 2024-05-18 13:13:35 +12:00
Luke Jones
89dc0b3501 Merge branch 'tokio_console' into 'main'
Fix GUI taking 100% of CPU core

Closes #480

See merge request asus-linux/asusctl!189
2024-05-18 01:10:33 +00:00
Luke D. Jones
ea988279a8 Fix GUI taking 100% of CPU core
Closes #480
2024-05-18 12:59:26 +12:00
Luke D. Jones
219bd559b6 tokio instrument 2024-05-18 11:21:33 +12:00
Luke D. Jones
ad1ef9b8a2 Update deps 2024-05-17 22:31:28 +12:00
Luke D. Jones
59795c605c Add G512LI and G513RS to aura_support.ron 2024-05-17 22:14:40 +12:00
Luke D. Jones
a36ac2b6d3 Add a warning log for missing laptop model 2024-05-17 22:09:30 +12:00
Luke Jones
a20837f252 Merge branch '505-invalid-paths-in-etc-asusd-anime-ron-result-in-broken-anime-control' into 'main'
Resolve "Invalid paths in /etc/asusd/anime.ron result in broken anime control"

Closes #505

See merge request asus-linux/asusctl!188
2024-05-17 10:09:12 +00:00
Luke D. Jones
1353fe3fdb Rename and recreate the default Anime config if cache setup fails 2024-05-17 21:54:37 +12:00
Luke D. Jones
770bd12a5c Add G513RS to laptop DB 2024-05-17 18:56:51 +12:00
Luke Jones
af2f5592f0 Merge pull request #29 from chrnin/fix/udev-for-zenbook
add Zenbook to asusd.rules
2024-05-17 11:37:36 +12:00
Luke D. Jones
9686c41ac4 Fix pipeline 2024-05-17 11:35:36 +12:00
Luke D. Jones
fbdb0514d2 Prep new release 2024-05-17 10:18:54 +12:00
Luke D. Jones
1f5650d26b Add tests, G513L laptop 2024-05-17 09:41:40 +12:00
Luke D. Jones
14db97c476 Update G513 model DB entry 2024-05-15 10:04:02 +12:00
Luke D. Jones
66a501ecf6 Prepare new release 2024-05-14 17:35:44 +12:00
Luke D. Jones
6b129763d4 Reimplement the 0x1866 keyboard power settings 2024-05-14 10:18:56 +12:00
Luke D. Jones
a0368d4345 Temporary fix of old keyboard+lightbar 2024-05-13 23:53:25 +12:00
Luke D. Jones
f2f090a88f Use backup hidraw brightness write if read-back value fails 2024-05-13 16:18:00 +12:00
Luke D. Jones
6c7e1a6467 Add option for enable/disable apply AC/Bat policy on change 2024-05-12 21:37:04 +12:00
Luke Jones
92ca7bc70d Merge branch 'main' into 'main'
rog-control-center Turkish language support added

See merge request asus-linux/asusctl!185
2024-05-11 08:31:20 +00:00
Winfried
dd1e6b845b rog-control-center Turkish language support added 2024-05-11 10:52:19 +03:00
Luke D. Jones
882fa9bed8 don't setup page data if unsupported 2024-05-11 11:52:26 +12:00
Luke D. Jones
9c7dfb4030 Small fixups 2024-05-11 11:09:02 +12:00
Luke D. Jones
f855908c82 Better everything 2024-05-11 11:03:13 +12:00
Luke D. Jones
293a087b8a Fixups 2024-05-10 23:14:48 +12:00
Luke D. Jones
fd72a04bb8 Sanitize the dbus path for aura devices (remove '.' chars) 2024-05-10 19:37:38 +12:00
Luke D. Jones
f131a3fa70 More logigng. Adjust the aura init process. Fix TUF led power 2024-05-10 18:58:05 +12:00
Luke D. Jones
ccf8d8df91 Prep 6.0.5 version 2024-05-10 12:44:46 +12:00
Luke D. Jones
b970d364f7 Fix test 2024-05-10 12:36:34 +12:00
Luke D. Jones
1da68ea69d Try to mitigate the lack of kbd_brightness on some laptops 2024-05-10 12:22:36 +12:00
Luke D. Jones
e62e7e8eca Cleanup sys config 2024-05-10 10:26:32 +12:00
Luke D. Jones
1b1d10c461 Try to better handle pre-2021 laptops with lightbar 2024-05-10 10:04:51 +12:00
Stefan Boca
14ea0f6d83 Update GA402XV supported aura modes 2024-05-08 19:20:17 -07:00
Luke Jones
5107a6c39c Merge branch 'FAYZER77-main-patch-34823' into 'main'
Change 733C model profile to add support for Lid LED, and remove unneeded basic zones entries

See merge request asus-linux/asusctl!183
2024-05-08 23:12:56 +00:00
FAYZER77
2c77ec9e24 Change 733C model profile to add support for Lid LED, and remove unneeded basic zones entries 2024-05-08 23:08:19 +00:00
Luke D. Jones
817a66bdf1 Prep 6.0.4 2024-05-09 11:00:51 +12:00
Luke D. Jones
664a3d5533 Match G533Q to 0x8166 keyboard ID explicitly
Should close #438
2024-05-09 10:01:48 +12:00
Luke D. Jones
37bc5e45b9 Fix: ensure property derive is on all property methods for slash 2024-05-09 09:34:02 +12:00
Luke D. Jones
a18692ef1e Fix up colour sliders
- Fixup colour sliders for UI
- Correctly drop tokio runtime
2024-05-08 22:55:11 +12:00
Luke D. Jones
1b023d0f5f Fix and prep new 6.0.2 release 2024-05-08 16:27:40 +12:00
Luke D. Jones
74f74e73c4 Update deps, point release 2024-05-07 13:56:25 +12:00
Luke D. Jones
9c7df9ad39 Update deps, point release 2024-05-07 12:58:17 +12:00
Luke D. Jones
94adf5d24d Revert back to zbus 4.1 2024-05-06 23:54:36 +12:00
Luke D. Jones
8dbdb68175 Increase tray icon sleep time 2024-05-06 23:14:51 +12:00
Luke D. Jones
89002eb5ec Use fluent-dark instead of cosmic due to compile times 2024-05-06 23:01:03 +12:00
Luke D. Jones
dc9ef8cf54 Remove unused deps 2024-05-06 13:25:07 +12:00
Luke D. Jones
667697d042 Cleanup deps 2024-05-06 10:58:11 +12:00
Luke D. Jones
bc92fa11f9 Update all cargo.toml. Support G713P 2024-05-06 09:45:35 +12:00
Luke D. Jones
f5d5681b49 Prep changelog 2024-05-05 20:52:38 +12:00
Luke D. Jones
1c8e50843b Cleanup files, prep new release 2024-05-05 20:22:56 +12:00
Luke D. Jones
487d140bd5 Anime: Better prevent await blocking. Prevent Slash taking over anime USB dev 2024-05-05 10:56:55 +12:00
Luke D. Jones
661ea8d3bf Fix fedora install instruction 2024-04-19 11:11:58 +12:00
Luke D. Jones
28d1ed6ab3 Fix broke logix 2024-04-18 14:40:39 +12:00
Luke D. Jones
903b978e86 Add missing files 2024-04-18 13:55:02 +12:00
Luke D. Jones
519f6bd46b Cleanup notifs, sys state, ac/bat commands 2024-04-18 13:48:23 +12:00
Luke D. Jones
a94a8ca28d Support the GU605M keyboard 2024-04-18 10:08:40 +12:00
Luke D. Jones
f9dca2da5d Re-add TUF keyboard support 2024-04-17 21:39:58 +12:00
Luke Jones
df88ff1acb Update asusd.service 2024-04-17 06:11:00 +00:00
Luke Jones
cb5aa0f170 Update asusd.service 2024-04-17 06:10:44 +00:00
Luke D. Jones
4ea79f966e Add updated translation + aura_support.ron 2024-04-17 14:18:27 +12:00
Luke D. Jones
b8bc1a01b3 Fix colour hex in gui 2024-04-17 12:46:36 +12:00
Luke D. Jones
0e5d1815bd Bump alpha version 2024-04-17 11:55:19 +12:00
Luke D. Jones
64e8cb65d0 Many cleanup and fix 2024-04-17 11:54:14 +12:00
Christophe Ninucci
7122fbaca8 add Zenbook to asusd.rules 2024-04-14 11:30:39 +02:00
Luke D. Jones
3142353f98 Fix tests 2024-04-11 13:18:03 +12:00
Luke D. Jones
484ca692ad Refactoring led support data 2024-04-10 21:14:47 +12:00
Luke D. Jones
1ebdfada96 Update discord invite 2024-04-10 18:09:41 +12:00
Luke D. Jones
3bc9dfcda1 Support GA402N keyboard 2024-04-10 17:04:21 +12:00
Luke D. Jones
895e5d2ca3 Support GA402N keyboard 2024-04-10 17:04:08 +12:00
Luke D. Jones
564992719e Fixes to slash merge 2024-04-10 09:13:26 +12:00
Luke Jones
a737d240be Merge pull request #23 from jschoubben/main
Add support for 2024 G14 Slash lighting (GA403UI)
2024-04-10 08:55:17 +12:00
Luke Jones
d89c1ebf26 Merge branch 'main' into main 2024-04-10 08:54:54 +12:00
Luke D. Jones
be7686bb46 Dump deps and version 2024-04-09 21:24:55 +12:00
Luke D. Jones
4f70055f85 Complete building 2024-04-09 21:02:09 +12:00
Luke D. Jones
91ca049298 Unify the laptop aura power stuff 2024-04-09 12:13:42 +12:00
Luke D. Jones
635d0378ac Bump deps 2024-04-06 14:10:18 +13:00
Luke D. Jones
1c729316f7 Refactor, rename, organise rog-aura stuff better 2024-04-05 21:20:34 +13:00
Luke D. Jones
4701c019a8 Major cleanup of older gui state code 2024-04-05 20:19:07 +13:00
Luke D. Jones
ca0d8bda4b Update readme. Fix tray startup 2024-04-05 16:00:20 +13:00
Luke D. Jones
a271ffbb10 rcc: run as app only on Ally 2024-04-04 09:58:40 +13:00
Luke D. Jones
00babaf949 Update translations 2024-04-03 16:15:09 +13:00
Luke D. Jones
2f844ac151 Cleanup 2024-04-03 16:15:09 +13:00
Luke D. Jones
5178bf1d1a Update readme 2024-04-03 16:15:09 +13:00
jochen@g14
116afb9b6c Initialize slash from config file 2024-03-31 01:08:26 +01:00
jochen@g14
4468a58487 Use enable/disable commands and cleanup build warnings 2024-03-31 00:34:44 +01:00
jochen@g14
2f73577e91 Fix Cargo.toml 2024-03-30 23:33:30 +01:00
jochen@g14
c1cffc8f59 Remove example file since it's not correct 2024-03-30 23:29:55 +01:00
jochen@g14
6d8f85c154 Minor changes to reflect original files 2024-03-30 23:27:33 +01:00
jochen@g14
0674e7f61c Changes after my own PR review 2024-03-30 23:23:37 +01:00
jochen@g14
fde2f3ba15 Fixed issues with asusctl-slash command 2024-03-30 21:19:55 +01:00
jochen@g14
70493d1a93 Fix error in makefile 2024-03-30 19:39:42 +01:00
jochen@g14
c20d0a76a0 Fix build after merge 2024-03-30 19:00:22 +01:00
jochen@g14
e6952e241a Merge from main 2024-03-30 18:44:15 +01:00
jochen@g14
b40812928a Imlement Display and FromStr traits for SlashMode 2024-03-30 18:42:42 +01:00
jochen@g14
8cdc9773c9 Added working implementation of the G14 Slash ledstrip 2024-03-30 18:41:31 +01:00
Luke Jones
8d30282edf Update default.md 2024-03-28 01:03:30 +00:00
Luke D. Jones
4ba44560a9 Update deps 2024-03-27 19:27:22 +13:00
jochen@g14
cdc9ca7b58 Try to implement slash bar functionality - part 1 2024-03-25 01:54:05 +01:00
Luke D. Jones
7eae7c5664 Change aura manager task to blocking. Remove idle tasks that keep hanging 2024-03-24 21:14:54 +13:00
Luke D. Jones
739a0ffa63 aura debugging 2024-03-24 10:55:20 +13:00
Luke D. Jones
637360095c Shift init actions up a few calls to prevent over-eager init 2024-03-23 23:27:26 +13:00
Luke D. Jones
4b34ab83fb Initial pass of async task sync in aura 2024-03-23 23:15:38 +13:00
Luke D. Jones
ac605cbc00 Narrow the search space of aura devices down 2024-03-23 14:30:00 +13:00
Luke D. Jones
4b38e5daa6 Further adjustments to aura 2024-03-23 13:07:20 +13:00
Luke D. Jones
1c007b4216 Small refinement to aura control init 2024-03-23 11:45:20 +13:00
Luke D. Jones
193f9dfa1e Extra logging for aura 2024-03-23 11:27:20 +13:00
Jochen@Jinbe
1366422d96 Play around and add rog-slash 2024-03-22 22:05:27 +01:00
Luke D. Jones
4e778a3d28 Refactor HidRaw 2024-03-22 19:47:24 +13:00
Luke D. Jones
be05508110 Try to ensure all aura are detected at start 2024-03-22 17:36:58 +13:00
Luke D. Jones
9119229d41 Update deps 2024-03-20 23:12:52 +13:00
Luke D. Jones
5c43c31331 Manage add/remove aura
Serialize aura config filename
2024-03-20 23:00:25 +13:00
Luke D. Jones
014604724f Fix clippy lints 2024-03-15 19:41:38 +13:00
Luke D. Jones
7d076368e9 Adjust organization of rog control src 2024-03-15 17:19:54 +13:00
Luke D. Jones
5d6ed5c365 Remove old screenshits 2024-03-14 22:17:42 +13:00
Luke D. Jones
a2b8f0f93c Minor updates 2024-03-14 22:10:14 +13:00
Luke D. Jones
5fe8416c65 Only apply fan curve for profile if *on* that profile, but still save config 2024-03-14 21:28:06 +13:00
Luke D. Jones
1b4d7a95af Minor corrections 2024-03-14 21:24:28 +13:00
Luke D. Jones
e8627fde4c Fix applying disabled and enabled fan curves 2024-03-14 21:11:18 +13:00
Luke D. Jones
6b0edc6da1 Enable fan curves 2024-03-14 17:17:55 +13:00
Luke D. Jones
f6ad631a0f Update readme 2024-03-14 11:19:31 +13:00
Luke D. Jones
f6393a3926 Further fan-curve graph work 2024-03-13 23:30:06 +13:00
Luke D. Jones
d51384c3a1 Fix the fan curve defaults again 2024-03-13 21:19:01 +13:00
Luke D. Jones
78f18959fb Populate fan curve data 2024-03-13 20:18:41 +13:00
Luke D. Jones
7a661a585e Add missing file 2024-03-13 19:14:29 +13:00
Luke D. Jones
f4f7a1e648 Check in the fan curve work 2024-03-13 18:57:38 +13:00
Luke D. Jones
b6e3e5e823 Remove a dbg 2024-03-13 14:08:43 +13:00
Luke D. Jones
41b1bd23d6 Fix fancurves 2024-03-13 14:08:08 +13:00
Luke D. Jones
69458a0595 Minor fix to graph widget 2024-03-12 22:06:56 +13:00
Luke D. Jones
5fd107df27 Initial fan graph widget 2024-03-12 21:33:39 +13:00
Luke D. Jones
2558057e9f Use mix instead of interpolate 2024-03-12 00:09:54 +13:00
Luke D. Jones
8111daaf1d Use mix instead of interpolate 2024-03-12 00:08:54 +13:00
Luke D. Jones
672acb234f Make aura settings apply instantly 2024-03-11 23:27:07 +13:00
Luke D. Jones
9725062fb9 Refactor and cleanup theming 2024-03-11 22:26:26 +13:00
Luke D. Jones
c7b1624313 Remove dbg statements 2024-03-11 12:53:38 +13:00
Luke D. Jones
67b97f1d43 Update ci and readme 2024-03-10 23:29:50 +13:00
Luke D. Jones
6498fd1349 Move rog<->slint type conversions to module 2024-03-10 21:12:36 +13:00
Luke D. Jones
e371229b6c Update support for boot_sound kernel patch 2024-03-10 20:53:03 +13:00
Luke D. Jones
0fac33a8ff Update pipeline 2024-03-09 23:49:42 +13:00
Luke D. Jones
b0da062577 Clean up debug info 2024-03-09 23:30:15 +13:00
Luke D. Jones
ca41bd59de Begin implmenting keyboard power states 2024-03-09 23:18:30 +13:00
Luke D. Jones
efcad3f6f9 Small colour correction 2024-03-06 22:41:55 +13:00
Luke D. Jones
fa2255cbaf Atempt better aura colour mix 2024-03-06 22:35:16 +13:00
Luke D. Jones
02b9bac899 Clean up the tray code 2024-03-04 13:28:19 +13:00
Luke D. Jones
a1fcf5023c Force tray process to exit if Quit 2024-03-03 22:41:57 +13:00
Luke D. Jones
2f8ea80e6d Replace shitty gtk tray with betrayer 2024-03-03 22:26:52 +13:00
Luke D. Jones
b798cf6a4e Minor adjust to rgb bright slider 2024-03-03 13:30:46 +13:00
Luke D. Jones
3da848d131 Init with colour sliders in approx position 2024-03-03 12:57:45 +13:00
Luke D. Jones
a88c33c201 MOrE 2024-03-02 23:49:11 +13:00
Luke D. Jones
7b0f037cba Trying different strategies for non-blocking UI 2024-02-25 23:21:11 +13:00
Luke D. Jones
91b1456d06 Formulate slint patterns 2024-02-25 19:24:20 +13:00
Luke D. Jones
c3b02a2bb0 Fix the IPC 2024-02-25 13:09:13 +13:00
Luke D. Jones
8e4b7d53f4 More updating to zbus 4.0.1 2024-02-24 21:56:52 +13:00
Luke D. Jones
a44145f487 Update to zbus 4.0.1 2024-02-24 21:56:29 +13:00
Luke D. Jones
bb7b3a81fb Bump version 2024-02-24 21:50:52 +13:00
Luke D. Jones
19607d71c3 Prep 5.0.8 release 2024-02-24 17:09:24 +13:00
Luke D. Jones
96f281d789 Remove the use of bytes in zbus signatures 2024-02-23 21:50:53 +13:00
Luke D. Jones
7613eded95 Sane defaults for asusd config 2024-02-23 14:40:00 +13:00
Luke D. Jones
50eccd2b1d Formatting and fixes 2024-02-23 12:36:16 +13:00
Luke Jones
ba54007102 Merge branch 'bugfix/persistent-theme' into 'main'
Reintroduce persistent dark/light mode

See merge request asus-linux/asusctl!180
2024-02-19 19:44:59 +00:00
Filip Binkiewicz
a028f5375f Reintroduce persistent dark/light mode 2024-02-19 19:27:56 +00:00
Luke Jones
9ec02cd727 Merge branch 'dearner-main-patch-22870' into 'main'
Added G814JZ to aura_support.ron (uses G814JI keymap)

See merge request asus-linux/asusctl!179
2024-02-14 01:40:26 +00:00
Chris Dearner
4b46ece09a Added G814JZ to aura_support.ron (uses G814JI keymap) 2024-02-05 12:49:49 +00:00
Luke D. Jones
086bbd0908 Fix the broken pipe error 2024-02-02 23:26:41 +13:00
Luke D. Jones
c94eaa473e Update TS bindings 2024-01-24 22:37:10 +13:00
Luke D. Jones
b1b809834b Reload and apply settings if config file externally changed 2024-01-24 12:19:34 +13:00
Luke D. Jones
84183288ec Fix inotify watch failing thanks to vim idiocy 2024-01-23 22:44:20 +13:00
Luke D. Jones
86cbef83b6 Reload asusd.ron if changed 2024-01-22 21:54:19 +13:00
Luke D. Jones
006fb632c4 Doc and feature fixes 2024-01-22 19:33:40 +13:00
Luke D. Jones
e3636ed8ce Update smithay-client-toolkit 2024-01-22 12:06:42 +13:00
Luke D. Jones
cfd207f251 Remove async-trait crate and set min rustc 1.75 2024-01-15 18:22:41 +13:00
Luke D. Jones
d4c68546e7 Added ability to change what EPP is linked with each throttle profile 2024-01-15 18:00:27 +13:00
Luke D. Jones
6f4a7e16dc Fixes to RCC 2024-01-05 14:21:31 +13:00
Luke D. Jones
f64253d633 Various bugfixes 2024-01-05 13:53:57 +13:00
Luke D. Jones
124c17aadc Add default issue template 2024-01-04 14:30:11 +13:00
Luke D. Jones
ab40f9fcbf Add FX705D led support 2024-01-04 09:23:37 +13:00
Luke D. Jones
5cdfa5a8d4 Fix to suspend process in anime thread to let custom anims run on wake 2023-12-27 11:24:39 +13:00
Luke D. Jones
ce870cd5ed Revert egui update due to a lot of issues arising from window closing 2023-12-27 10:13:26 +13:00
Luke D. Jones
4541d2e1ba Update dbus introspection 2023-12-26 11:56:47 +13:00
Luke D. Jones
b525411fd3 Minor fixes in asusctl 2023-12-25 21:24:05 +13:00
Luke D. Jones
a867496f13 Re-enable ROGCC fan curves 2023-12-24 10:30:33 +13:00
Luke D. Jones
f421b8ee3b Fix to apply led effect in rogcc 2023-12-23 21:45:19 +13:00
Luke D. Jones
82780feb4b Update readme 2023-12-23 10:37:46 +13:00
Luke D. Jones
1e5443e206 Bugfix release 2023-12-22 11:39:17 +13:00
Luke D. Jones
027a591d26 Add cargo-vendor-filterer to pipeline 2023-12-17 21:44:33 +13:00
Luke D. Jones
e90375828d Fix: nuke some async deadlocks in fan-curves 2023-12-17 21:41:07 +13:00
Luke D. Jones
75b4d67072 Fix: force Anime power/wakeup disabled to prevent idiotic random wakes 2023-12-15 19:15:14 +13:00
Luke D. Jones
9aa332de3b New release 2023-12-15 11:50:49 +13:00
Luke D. Jones
5efd7fc6a7 Fix: Corrections to dbus signature for some keyboard power settings
Closes #423
2023-12-15 11:48:20 +13:00
Luke D. Jones
0aafe24a02 Fix: correctiosn to asusd.service
Closes #424
2023-12-15 11:48:20 +13:00
Luke D. Jones
dda6d343d9 Fix: correction to switching next fan profile
Closes #425
2023-12-15 11:48:18 +13:00
Luke D. Jones
6f39307080 remember how to tag releases 2023-12-12 22:00:37 +13:00
Luke Jones
ef63789faa Merge branch 'main' into 'main'
Added missing button, and fixed layout for Strix G18

See merge request asus-linux/asusctl!176
2023-12-12 08:58:31 +00:00
Sunehildeep Singh
c422e77ba6 Added missing button, and fixed layout for Strix G18 2023-12-12 08:58:31 +00:00
Luke D. Jones
3c234dd3c4 Release 5.0.0 2023-12-12 21:54:24 +13:00
Luke Jones
c420dd820a Merge branch '419-support-for-strix-g18-aura-g814ji-already-done-need-merge' into 'main'
Draft: Resolve "Support For Strix G18 AURA (G814JI) - Already Done, need merge"

Closes #419

See merge request asus-linux/asusctl!175
2023-12-10 20:03:55 +00:00
Luke D. Jones
a3e6fec163 Add g814ji and layout 2023-12-11 08:56:17 +13:00
Luke D. Jones
9b4e76be87 Update examples 2023-12-11 08:49:32 +13:00
Luke D. Jones
7b2125cbdf fic async deadlock in platform control 2023-12-08 20:06:22 +13:00
Luke D. Jones
694a644cc6 Revert "Fix: change epp change watch to a loop to prevent deadlock"
This reverts commit c06f78990f.
2023-12-08 20:06:22 +13:00
Luke D. Jones
922aa0c352 platform example testing 2023-12-08 17:33:27 +13:00
Luke D. Jones
c06f78990f Fix: change epp change watch to a loop to prevent deadlock 2023-12-07 20:04:21 +13:00
Luke D. Jones
5c8bb6e6ea Ensure thermal policy is set on resume and relaod 2023-12-05 19:26:49 +13:00
Luke Jones
993131d0a9 Merge branch 'fluke/dbus-refactor' into 'main'
Fluke/dbus refactor

See merge request asus-linux/asusctl!173
2023-12-03 20:44:01 +00:00
Luke Jones
0a69c23288 Fluke/dbus refactor 2023-12-03 20:44:01 +00:00
Luke D. Jones
f6e4cc0626 Cleanup after changes from Platform dbus rework 2023-11-18 22:36:55 +13:00
Luke D. Jones
1f696508e7 rog-platform: refactor all related parts 2023-11-18 21:57:46 +13:00
Luke D. Jones
fa043adc99 rog-platform: add CPU and GPU tunings
rog-platform: add tunables to supported dat

Anime: fixes to how some power options work
2023-11-17 17:16:03 +13:00
Luke D. Jones
b9c2d929b3 anime: rework sleep logic 2023-11-16 13:57:42 +13:00
Luke D. Jones
eda1e920df Update changelog 2023-11-15 18:29:35 +13:00
Luke D. Jones
0de2c9e424 Anime: remove sleep animation config 2023-11-15 18:27:58 +13:00
Luke D. Jones
e88e7be8ae Anime: expose new options in CLI 2023-11-15 17:45:52 +13:00
Luke D. Jones
e470d3acc0 Anime: add dbus methods 2023-11-15 17:23:44 +13:00
Luke D. Jones
f5b3f0bc38 Fix lints on examples 2023-11-15 17:23:35 +13:00
Luke D. Jones
19497c94e0 Anime: fix data struct 2023-11-15 16:56:50 +13:00
Luke D. Jones
670eee23e8 Anime: small cleanup 2023-11-15 16:45:30 +13:00
Luke D. Jones
26309776e9 Fix test 2023-11-15 14:47:52 +13:00
Luke D. Jones
a7d5057976 Anime: propagate property config 2023-11-15 14:46:42 +13:00
Luke D. Jones
8eb9b1d4eb Anime: refactor power stuff 2023-11-15 14:29:38 +13:00
Luke D. Jones
71ee9e43ba Fix gnome-45 extension version 2023-11-14 16:49:17 +13:00
Luke D. Jones
f1b0e1288a Add missing crates 2023-11-13 11:28:34 +13:00
Luke D. Jones
35c7fd10b3 Drop sysfs_class and create dmi_id for getting identifying info with udev 2023-11-08 14:00:35 +13:00
Luke D. Jones
4c50dc259c rog-control-center: ensure brightness slider works correctly 2023-11-08 13:59:07 +13:00
Luke D. Jones
0fd0aeff88 Support Rog Ally LED modes (basic) 2023-11-07 17:24:38 +13:00
Luke Jones
fd37f41ef1 Merge branch 'sctk-0.16.1' into 'main'
cargo update -p smithay-client-toolkit v0.16.0 -> v0.16.1

Closes #407

See merge request asus-linux/asusctl!172
2023-10-11 06:30:37 +00:00
Cole Mickens
1307997122 cargo update -p smithay-client-toolkit v0.16.0 -> v0.16.1 2023-10-11 08:15:04 +02:00
Luke Jones
85187d2d8d Merge branch 'add_laptop_G513RW' into 'main'
Added preliminary support for G513RW

See merge request asus-linux/asusctl!171
2023-09-16 05:51:15 +00:00
Edwin Clement
e29a568195 Added preliminary support for G513RW 2023-09-15 20:03:02 -04:00
Luke D. Jones
6c375a9951 Prep new release 2023-09-08 13:22:15 +12:00
Luke D. Jones
4641e19c43 Fix bad keybaord layout 2023-09-04 10:19:57 +12:00
Luke D. Jones
91f0c2ea14 Fix loading of fan curves
Closes #402

Signed-off-by: Luke D. Jones <luke@ljones.dev>
2023-09-04 10:18:48 +12:00
Luke Jones
b4a8cb9de2 Merge branch 'srivatsarog-main-patch-78688' into 'main'
Update aura_support.ron

See merge request asus-linux/asusctl!169
2023-09-03 08:45:39 +00:00
Luke Jones
67bbcdb964 Merge branch 'main' into 'srivatsarog-main-patch-78688'
# Conflicts:
#   rog-aura/data/aura_support.ron
2023-09-03 08:37:52 +00:00
Luke Jones
8acfe0a9e8 Merge branch 'main' into 'main'
aura: Support for G733PZ

See merge request asus-linux/asusctl!167
2023-09-03 08:36:20 +00:00
Luke D. Jones
5f6e6ec382 gex: rename gnome-44, add gnome-45 2023-08-31 14:36:01 +12:00
Luke D. Jones
cf92526d87 Set cargo resolver 2023-08-31 12:42:31 +12:00
Luke D. Jones
f290594562 Prep release 2023-08-26 21:40:45 +12:00
Luke D. Jones
423bd54f79 Fixes: bugfixes in aura config loading 2023-08-26 21:35:38 +12:00
Luke Jones
ea0eaef8a6 Update README.md 2023-08-24 10:22:26 +00:00
Luke Jones
ef62a26148 Merge branch 'main' into 'main'
add aura support for GU603VV

See merge request asus-linux/asusctl!170
2023-08-20 06:13:20 +00:00
Yifan Zhu
2f916fa4e5 add aura support for GU603VV 2023-08-20 06:13:20 +00:00
Luke D. Jones
e42fd10404 Update deps 2023-08-14 13:20:40 +12:00
Luke D. Jones
93edd1b632 Add gv601v singlezone advanced 2023-08-13 18:22:21 +12:00
Luke D. Jones
6957a08d83 Fix: Corrections in anime detection
Closes #387
2023-08-11 09:48:22 +12:00
Luke D. Jones
98569b98e7 Remove a dbg!() x2 2023-08-10 09:50:01 +12:00
Luke D. Jones
573568d6e2 Remove a dbg!() 2023-08-10 09:49:13 +12:00
Luke D. Jones
3ec37a4dac Fix: For anime look for usbraw device before hidraw device
Closes #387
2023-08-02 14:14:08 +12:00
Luke D. Jones
11483b28a6 Fix: Further refine the CLI for fan curve control
Should close #385
2023-08-01 19:30:33 +12:00
Luke D. Jones
2cce83d164 Fix: asusd should reload defualt fan-curves if the config file fails
Closes #385
2023-08-01 09:30:54 +12:00
Luke D. Jones
42b92f3b87 Fix: reimplement fetching of fan curves on CLI
Partial close of #385
2023-08-01 09:18:27 +12:00
gabi
b652fd15a2 Update aura_support.ron 2023-07-28 06:16:39 +00:00
Luke D. Jones
9154aaa97c Add distro packaging dir + spec file for fedora 2023-07-27 10:13:10 +12:00
Interfector18
9e65921c0a aura: Support for G733PZ 2023-07-24 17:44:59 +02:00
Luke D. Jones
8d8b5e5f51 aura: support GV601V LED modes 2023-07-24 14:07:01 +12:00
Luke D. Jones
9418b63454 Bump new release 2023-07-24 10:23:05 +12:00
Luke D. Jones
2d396a49da Update crate versions 2023-07-24 10:14:24 +12:00
Luke D. Jones
a6d89a622b Various cleanup. Add GA402X LED modes 2023-07-24 10:04:10 +12:00
Luke D. Jones
51bcb0082b profiles: add mid fan curve support 2023-07-24 09:29:56 +12:00
Luke D. Jones
eb54250e4d aura: support FX505G 2023-07-24 09:28:09 +12:00
Luke D. Jones
eafc831231 gex: update xml and aura power parsing 2023-07-12 14:21:57 +12:00
Luke D. Jones
c625e97b7b Update changelog 2023-07-11 21:08:10 +12:00
Luke D. Jones
fea56879d6 Update changelog 2023-07-11 21:06:27 +12:00
Luke D. Jones
03052e129b aura: update dbus xml 2023-07-11 21:02:40 +12:00
Luke D. Jones
3dbc893905 aura: update bindings 2023-07-11 21:00:42 +12:00
Luke D. Jones
50152961c7 aura: refactor modern rog power settings 2023-07-11 20:59:43 +12:00
Luke D. Jones
8be0e7e6bf gex: update laptop feature toggle to switch primary 2023-07-06 22:00:59 +12:00
Luke D. Jones
d6d4a00fc3 gex: add keyboard LED mode setting 2023-07-04 21:22:30 +12:00
Luke D. Jones
611140716c gex: map more of dbus methods and notifs 2023-07-04 20:08:42 +12:00
Luke D. Jones
a09f7b5275 gex: parse led power from dbus 2023-07-04 18:49:52 +12:00
Luke D. Jones
823958492e rename keyboard led power dbus methods 2023-07-04 10:17:11 +12:00
Luke D. Jones
668135eab3 Update readme 2023-07-03 23:06:19 +12:00
Luke D. Jones
622e07505d gex: begin adding aura control dbus 2023-07-03 23:04:06 +12:00
Luke D. Jones
5c159d2294 Set toolchain to stable 2023-07-03 20:14:14 +12:00
Luke D. Jones
6cfa09a02b Update readme 2023-07-03 16:20:46 +12:00
Luke D. Jones
95666cc40b Update deps 2023-07-03 16:07:38 +12:00
Luke D. Jones
458d58c87c Update changelog 2023-07-03 16:05:46 +12:00
Luke D. Jones
7328ebdda3 gex: cleanup and rename 2023-07-03 15:51:26 +12:00
Luke D. Jones
14d043bbc3 RCC: add tray enable/disable, move app settings to page 2023-07-03 15:02:25 +12:00
Luke D. Jones
98dec6403c gex: adjust tsconfig 2023-07-02 21:58:50 +12:00
Luke D. Jones
3546f5bd21 gex: add toggle for anime powersave anim 2023-07-02 21:09:17 +12:00
Luke D. Jones
db1683de46 gex: temporary checking of which primary quicktoggle to use 2023-07-02 19:15:55 +12:00
Luke D. Jones
669c8ac3c7 gex: make quickmenu a module 2023-07-02 17:30:20 +12:00
Luke D. Jones
4f3a6ce1c6 gex: trial of using qucik submenu toggles 2023-07-02 11:37:36 +12:00
Luke Jones
6d3918ccf0 clean up bindings 2023-07-01 12:00:46 +00:00
Luke D. Jones
b002187b39 gex: trial of updating quicktoggle with dbus signal 2023-07-01 23:14:54 +12:00
Luke D. Jones
13965b2261 gex: add eslint, cleanup parsing of some stuff 2023-07-01 21:47:31 +12:00
Luke D. Jones
b182fbd323 gex: add anime power quicktoggle 2023-07-01 20:09:28 +12:00
Luke D. Jones
19b28f202c gex: Add slider for charge control 2023-07-01 19:17:02 +12:00
Luke D. Jones
ed51a7fa14 gex: fix and update 2023-07-01 18:03:05 +12:00
Luke D. Jones
c94358a8f3 gex: itemize the quicks and indicators 2023-07-01 17:18:11 +12:00
Luke D. Jones
2a8ca0a39a asusd: cleanup platform notifs, prevent more duplications 2023-07-01 12:31:40 +12:00
Luke D. Jones
83455a5ba3 Update deps 2023-06-30 15:57:18 +12:00
Luke D. Jones
bc776deb70 gex: more cleanup 2023-06-30 11:30:09 +12:00
Luke D. Jones
59b1059aee gex: cleanup 2023-06-30 10:43:19 +12:00
Luke D. Jones
dbe80d1914 gex: simplify build 2023-06-29 23:05:00 +12:00
Luke D. Jones
e325ebed18 gex: working quicktoggle example 2023-06-29 20:48:15 +12:00
Luke D. Jones
a743bda6e0 gex: cleanup 2023-06-29 17:42:57 +12:00
Luke D. Jones
15e6782e10 gex: map anime dbus data 2023-06-29 15:16:21 +12:00
Luke D. Jones
6b058c9922 gex: trial of dbus mthods 2023-06-29 12:58:11 +12:00
Luke D. Jones
fc8879ac24 gex: dbus class template 2023-06-28 22:50:56 +12:00
Luke D. Jones
4d2d5707a1 Begin reimplement gex to use generated bindings and dbus xml 2023-06-28 21:54:17 +12:00
Luke D. Jones
439c830311 Cleanup rog-aura usb tests 2023-06-28 10:07:11 +12:00
Luke D. Jones
91223d4ced Regenerate dbus xml 2023-06-27 22:19:29 +12:00
Luke D. Jones
7b17a13ce7 ridiculous refactor to allow enums to be dbus strings for better TS generation 2023-06-27 21:16:13 +12:00
Luke D. Jones
fca7d23a31 Update pipeline 2023-06-26 13:54:07 +12:00
Luke D. Jones
0122138b3b Add index.html 2023-06-26 13:43:06 +12:00
Luke D. Jones
7b495e7587 rcc: instant apply keyboard settings 2023-06-26 12:28:48 +12:00
Luke D. Jones
970cf9ae59 Support for G634J LED modes (layout is in progress) 2023-06-26 12:01:21 +12:00
Luke D. Jones
ad990c6ae1 Move G513I* to G513I in arua DB to catch full series of this range
Closes #336
2023-06-26 11:52:14 +12:00
Luke D. Jones
cd8cc013a4 Aura: set the LED brightness if settign a mode
Closes #355
2023-06-26 11:33:05 +12:00
Luke D. Jones
acf41c1783 Add support for mini_led_mode get/set
- asusd get/set, zbus methods
- Rog control center notification, tray menu, UI entry
2023-06-26 10:44:58 +12:00
Luke D. Jones
03c9f06569 asusctl: remove the panics from CLI
closes #364
2023-06-26 09:41:42 +12:00
Luke D. Jones
036a5018e0 Removed a duplication of charge limit notification 2023-06-25 21:15:27 +12:00
Luke D. Jones
81529b7374 Update GL503 led config 2023-06-25 20:59:26 +12:00
Luke D. Jones
2289af3ef6 Update discord link.
Closes #363
2023-06-25 20:51:17 +12:00
Luke D. Jones
633ffdf962 Support for GV601VI LED modes
Closes #370
2023-06-25 20:49:28 +12:00
Luke D. Jones
cb88c9f0e2 Fix: prevent multiple notifications from profile change 2023-06-25 20:43:43 +12:00
Luke D. Jones
8b77078a6f Animatrix: simulators, add features 2023-06-25 18:29:19 +12:00
Luke D. Jones
3d6d92ae7d Animatrix: gu604 sim 2023-06-25 16:36:19 +12:00
Luke D. Jones
55723b7b77 animatrix mapping: gu604 2023-06-25 11:39:56 +12:00
Luke D. Jones
7796ba0603 Animatrix sim: fixxess 2023-06-24 22:02:21 +12:00
Luke D. Jones
d3aababef5 animatrix simulator for ga402 2023-06-24 19:00:25 +12:00
Luke D. Jones
4611c08085 Add the missing dirs, dumbarse 2023-06-24 13:15:11 +12:00
Luke D. Jones
0a008a653a Animatrix: Default to GA402 style if Unknown, use default-workspace.
Also rename daemon crates to the bin names they use to be less confusing.

Signed-off-by: Luke D. Jones <luke@ljones.dev>
2023-06-24 12:57:03 +12:00
Luke D. Jones
cd5daa17d0 Anime: Enabled setting builtin animations 2023-06-21 13:34:08 +12:00
Luke D. Jones
a0529e0efd Better organise anime tests 2023-06-21 10:09:06 +12:00
Luke D. Jones
3e0aeea6c6 Add inotify::WatchMask::MODIFY to inotify watch mask.
Closes #362
2023-06-20 22:23:54 +12:00
Luke D. Jones
e2fb1d44b5 Anime: Diagonal asus gifs done 2023-06-20 21:58:27 +12:00
Luke D. Jones
04543eeca0 Aura: add support for Rear Glow power modes 2023-06-18 19:48:08 +12:00
Luke D. Jones
68ee62fef1 Anime: add base brightness control (dbus, cli) 2023-06-16 11:50:38 +12:00
Luke D. Jones
e523e4e9a2 Anime: GU604 images correct 2023-06-16 10:43:15 +12:00
Luke D. Jones
ea2d80cc44 Anime: incorrect dimensions and pitch 2023-06-16 00:34:45 +12:00
Luke D. Jones
40e00c4739 Anime: fixups, GU604 support 2023-06-15 23:53:24 +12:00
Luke D. Jones
cdc42193d1 Update deps 2023-06-14 20:30:42 +12:00
Luke D. Jones
3a18506510 Add "Unknown" to (not really) supported AniMe list
Intention is to allow users to at least control the power state of the
device (turn off) if the phyciscal display isn't yet supported.

Partial address of #354
2023-06-14 20:25:27 +12:00
Luke D. Jones
fa671e53d8 Add sdl32 to gitlab pipeline 2023-06-14 20:25:27 +12:00
Luke D. Jones
002dc8516d Half-arsed visuals for virtual anime 2023-06-14 20:25:27 +12:00
Luke D. Jones
2a38f69cc4 Begin implementing virtual devices for testing and stuff 2023-06-14 20:25:27 +12:00
Luke Jones
a14a37d0da Merge branch 'optional-stripping' into 'main'
Optional symbol stripping in Makefile

See merge request asus-linux/asusctl!165
2023-06-13 23:17:22 +00:00
Greg Land
b105ff5180 Optional symbol stripping in Makefile
Packaging systems have options to handle symbol stripping.  This lets
the users of the software enable or disable symbol stripping based on
their own preference or need.
2023-06-13 19:01:08 -04:00
Luke Jones
d202fcd97a Merge branch 'fix-install-program-target' into 'main'
Fixed issue preventing debug builds using Makefile

See merge request asus-linux/asusctl!163
2023-06-13 21:41:56 +00:00
Greg Land
15732ecd82 Fixed issue preventing debug builds using Makefile
install-program was always assuming that release was the only target
directory that could exist.  This would cause install-program to fail
with DEBUG=1 passed to the makefile.

DEBUG flag now correctly sets a TARGET and sets the build profile to dev
for debug builds.
2023-06-13 13:30:23 -04:00
Luke Jones
8508110ba0 Merge branch 'fix-g513qy' into 'main'
Fix broken Aura on G513QY

See merge request asus-linux/asusctl!162
2023-06-07 07:09:00 +00:00
CryoByte33
cafb64d57b Fix broken Aura on G513QY 2023-06-07 04:36:38 +02:00
Luke D. Jones
7515eafc45 Rmeove notification handle tracking limit
Fixes issue with KDE profile change notif disappearing.

closes #353
2023-05-20 19:07:40 +12:00
Luke D. Jones
b6c6f10bdf Fix test 2023-05-20 19:05:22 +12:00
Luke D. Jones
35352a8a7c Support for GL503V LED modes 2023-05-20 19:04:18 +12:00
Luke Jones
0c3bebdeb9 Merge branch 'main' into 'main'
Add led modes for GV601VI

See merge request asus-linux/asusctl!161
2023-05-16 22:57:50 +00:00
Mateo Juric
1394c12967 Add led modes for GV601VI 2023-05-17 00:04:36 +02:00
Luke D. Jones
cbc1f6f5bb Modify two TUF aura DB entries to match full range 2023-04-27 19:46:17 +12:00
Luke D. Jones
7ae0f896cf Update deps 2023-04-27 16:08:52 +12:00
Luke D. Jones
fb0374512d Fix rog-control-center not reopening if is set 2023-04-27 16:01:07 +12:00
Luke D. Jones
14f031ad34 Better update of aura modes if supported list changed 2023-04-27 10:57:45 +12:00
Luke D. Jones
bee5508099 Prep new release 2023-04-26 22:00:22 +12:00
Luke D. Jones
c741204200 Prep new release 2023-04-26 21:59:13 +12:00
Luke D. Jones
858c9841a7 Update deps 2023-04-26 21:35:48 +12:00
Luke D. Jones
fdc7d88a70 More tweaks to notifications 2023-04-26 12:49:29 +12:00
Luke D. Jones
da3017bb89 Update supergfx dep 2023-04-26 12:32:26 +12:00
Luke D. Jones
641e762e80 Update deps 2023-04-26 11:24:50 +12:00
Luke D. Jones
25ecfda095 Various tray and notification improvements 2023-04-26 10:57:13 +12:00
Luke D. Jones
31af8f9511 Use egui without wayland feature due to segfault 2023-04-25 14:44:31 +12:00
Luke D. Jones
8db783d9b4 Better handling of supergfx version check, aura config updates 2023-04-25 13:57:07 +12:00
Luke D. Jones
45a354880a Add support for GV604 LEDs 2023-04-25 12:13:20 +12:00
Luke D. Jones
ca1c67e803 Begin fixing up support of basic modes + supergfx 2023-04-25 10:27:09 +12:00
Luke D. Jones
c819fa458a Optimise keyboard detection 2023-04-24 22:23:42 +12:00
Luke D. Jones
869ab90299 Add 0x18c6 keyboard 2023-04-24 20:54:51 +12:00
Luke D. Jones
c40029f5e7 Merge branch 'fluke/18c6-keyboard' 2023-04-24 20:15:11 +12:00
Luke Jones
e864dfb0e7 Merge branch 'feature/persistent-theme' into 'main'
Persistent dark / light mode

See merge request asus-linux/asusctl!160
2023-04-22 21:29:36 +00:00
Filip
476b394add Persistent dark / light mode 2023-04-22 21:29:36 +00:00
Luke D. Jones
4ea5480e66 Add support for GX650P LED modes 2023-04-21 11:01:54 +12:00
Luke Jones
cfc46a2b70 Merge branch 'guv604vi-support' into 'main'
Add led modes for GU604VI

See merge request asus-linux/asusctl!159
2023-04-20 22:32:50 +00:00
bno1
235763a615 Add led modes for GU604V 2023-04-21 00:36:00 +03:00
Luke D. Jones
6e19c16e70 Begin adding 18c6 keyboard support
This keyboard is found in ROG Flow Z13 machines. A kernel patch is also
required for full support.

Addresses #344.
2023-04-19 12:08:30 +12:00
Luke D. Jones
6ea550b6ff Update egui and supergfxctl deps
Requires running with supergfxctl v5.1.0-RC5 if installed
2023-04-19 10:12:14 +12:00
Luke Jones
dd30c8092b Merge branch 'pr-makefile-split' into 'main'
Makefile: split install into install-{program,data}

See merge request asus-linux/asusctl!158
2023-04-10 08:04:40 +00:00
Cole Mickens
2bd751f841 Makefile: split install into install-{program,data} 2023-04-09 18:44:55 -05:00
Luke Jones
7a6aafded7 Merge branch 'fluke/fix-anime-loops' into 'main'
Bugfix: Adjust how sub-llops and part of anime animation handle

See merge request asus-linux/asusctl!157
2023-04-08 03:40:32 +00:00
Luke Jones
940b93a75f Merge branch 'zpl/fix-anime-loops_fix' into 'fluke/fix-anime-loops'
fix: sleep-animation

See merge request asus-linux/asusctl!156
2023-04-04 21:36:48 +00:00
Armas Spann
5c70fec29a fix: sleep-animation 2023-04-04 01:20:25 +02:00
Luke Jones
8ac505e0dd Merge branch 'main' into 'main'
Add support for FX506LH keyboard layout

See merge request asus-linux/asusctl!155
2023-04-03 08:13:07 +00:00
Luke D. Jones
3bdb03b1d8 Bugfix: Adjust how sub-llops and part of anime animation handle
Attempts to address #332
2023-04-03 20:01:06 +12:00
Winfried
4ac4909881 Add support for FX506LH keyboard layout 2023-03-29 15:12:03 +03:00
Luke D. Jones
ec5e6d2e7c Add support for G533Z keyboard and modes
Closes #327
2023-03-20 08:52:23 +01:00
Luke D. Jones
5600c51ba0 Fix remove the leftover initial config writes on new() for some controllers
Closes #320
2023-01-25 09:27:12 +13:00
Luke D. Jones
cb5856c4dc Update fedora build instruction 2023-01-18 20:40:25 +13:00
Luke Jones
aad6f6350b Update README.md 2023-01-17 20:54:46 +00:00
Luke D. Jones
1ec45a6449 Update gitlab CI 2023-01-16 15:17:37 +13:00
Luke Jones
bb612283fe Update .gitlab-ci.yml file 2023-01-16 02:00:34 +00:00
Luke Jones
bcba11d4ec Update .gitlab-ci.yml file 2023-01-16 01:59:50 +00:00
Luke Jones
7eab94bc7f Update .gitlab-ci.yml file 2023-01-16 01:57:55 +00:00
Luke D. Jones
e73bbedb41 Properly enable pipeline cache? 2023-01-16 14:50:50 +13:00
Luke D. Jones
a83ccbd33d Add git hooks via cargo-husky. Many many cleanups. 2023-01-16 13:23:30 +13:00
Luke Jones
b5b7799018 Merge branch 'readme-popos-instructions-typo-fix' into 'main'
Fixed typo in the instructions for Pop_OS installation commands

See merge request asus-linux/asusctl!152
2023-01-15 21:04:36 +00:00
Andres Sanchez
24ecb92621 Fixed typo in the instructions for Pop_OS installation commands 2023-01-15 11:41:10 -05:00
Luke Jones
a811417f5d Merge branch 'fluke/aura_advanced' into 'main'
Fluke/aura advanced

See merge request asus-linux/asusctl!151
2023-01-15 09:36:03 +00:00
Luke D. Jones
b012a01cad Update deps, prep RC 2023-01-15 22:27:44 +13:00
Luke D. Jones
e6a9c88695 RCC: Adjust check for dgpu status change 2023-01-11 18:17:45 +13:00
Luke Jones
048a7afa55 Merge branch 'fluke/aura_advanced' into 'main'
Convert repeated code in config-traits to a macro

See merge request asus-linux/asusctl!149
2023-01-09 10:32:54 +00:00
Luke D. Jones
53b854ef6d Convert repeated code in config-traits to a macro 2023-01-09 23:19:29 +13:00
Luke Jones
fac635d07d Merge branch 'fluke/aura_advanced' into 'main'
Fluke/aura advanced

See merge request asus-linux/asusctl!148
2023-01-08 09:28:23 +00:00
Luke D. Jones
9cc62d63c9 Add checks to rename configs if required 2023-01-08 22:00:32 +13:00
Luke D. Jones
ab3007d53d daemon-user: refactor config files 2023-01-08 21:23:16 +13:00
Luke D. Jones
00839aaa6f Refactor config_trait crate and add doc comment examples 2023-01-08 20:41:17 +13:00
Luke D. Jones
5133d398eb Add extra doc comments to config-trait 2023-01-07 21:20:53 +13:00
Luke D. Jones
90b711c7b9 Break config-traits out in to crate 2023-01-07 20:46:00 +13:00
Luke D. Jones
ea5e5db490 ROGCC: add note re: aura in gui 2023-01-07 12:02:58 +13:00
Luke D. Jones
ef6ca9e51e Add support for GL703GE keyboard layout 2023-01-07 11:56:56 +13:00
Luke D. Jones
022a144705 Fix profile controller not detecting if platform_profile is changed
Closes #313
2023-01-07 11:45:01 +13:00
Luke Jones
8011ba3009 Merge branch 'fluke/config-traits' into 'main'
Fluke/config traits

See merge request asus-linux/asusctl!147
2023-01-06 06:57:07 +00:00
Luke D. Jones
d93b870726 Split fan-curve config to own file 2023-01-06 19:47:42 +13:00
Luke D. Jones
e4f79a3e6f Config files use generic traits 2023-01-06 12:03:12 +13:00
Luke Jones
54273cfb60 Merge branch 'main' into 'main'
Parameter fix for 'asusctl bios --help' (asus-linux/asusctl#299)

See merge request asus-linux/asusctl!146
2023-01-05 07:11:12 +00:00
Luke D. Jones
0dd4b2d6b5 Update readme with popos build instructions
Closes #302
2023-01-05 20:08:39 +13:00
Luke D. Jones
a2d850bbcb Update readme with new build requirements 2023-01-05 20:06:17 +13:00
Luke D. Jones
19f82493de Better config fie handling for the asusd daemon
Should address #304
2023-01-05 19:56:51 +13:00
Luke D. Jones
cbce854d1b Format 2023-01-04 09:34:56 +13:00
Luke D. Jones
ee0600d50d Adjust service file 2023-01-03 20:21:14 +13:00
Luke D. Jones
3d145ab9bd Slightly adjust keyboard widget 2023-01-03 20:21:14 +13:00
Luke D. Jones
1cbffedaeb Advanced Aura feature
Groundwork for 'advanced' aura modes
Add single zone + Doom light flash
Fix mocking for ROGCC
Better prepare & change to mapping of keyboard layouts to models and functions
Refactor and begin using new key layout stuff
Enable first arg to rogcc to set layout in mocking feature mode
Complete refactor of key layouts, and to RON serde
2023-01-03 20:21:11 +13:00
Luke D. Jones
e3ecaa92bd Add disable_nvidia_powerd_on_battery option 2023-01-03 20:17:52 +13:00
Luke D. Jones
067738b94f Fix pipeline 2022-12-28 21:34:16 +13:00
Luke D. Jones
29b22cd18e Fix incorrect stop/start order of nvidia-powerd on AC plug/unplug 2022-12-28 21:30:29 +13:00
Luke D. Jones
c2aa81bfe3 asusd: fixing a blocking op 2022-12-25 22:22:52 +13:00
mclang
5e9c612269 Fixes 'asusctl bios --help' (issue #299) 2022-12-19 20:33:44 +02:00
Luke D. Jones
8dcb209026 ROGCC: Don't notify user if changing to same mux mode 2022-12-10 21:42:52 +13:00
Luke D. Jones
bdb6c5b2ff Prep 4.5.6 release 2022-12-10 21:08:52 +13:00
Luke D. Jones
a318fbceec asusd: check if nvidia-powerd enabled before toggling 2022-12-10 21:05:27 +13:00
Luke D. Jones
8feacf863a asusd: Very basic support for running a command on AC/Battery switching 2022-12-10 20:51:00 +13:00
Luke D. Jones
0c62582515 ROGCC: Very basic support for running a command on AC/Battery switching 2022-12-10 20:17:45 +13:00
Luke D. Jones
3c575e4d2a ROGCC: Minor correction to tray menu 2022-12-10 19:37:20 +13:00
Luke D. Jones
dbfd73da5e ROGCC: Better handle the use of GPU MUX without supergfxd 2022-12-10 19:30:30 +13:00
Luke D. Jones
b1ee449b97 Adjust profile task to help TUF laptops notify 2022-12-09 10:03:45 +13:00
Luke D. Jones
245c035dc9 Fix tasks not always running correctly on boot/sleep/wake/shutdown 2022-12-08 20:12:55 +13:00
Luke D. Jones
07daa0df61 Fix: ROGCC: show option for LED notifications 2022-12-08 16:27:00 +13:00
Luke D. Jones
c7893b16f9 Fix: ROGCC: Remove unwrap causing panic on main thread
Closes #293
2022-12-08 11:14:01 +13:00
Luke Jones
8e8681c190 Merge branch 'main' into 'main'
add led modes for FX506HC

See merge request asus-linux/asusctl!144
2022-12-07 20:29:23 +00:00
HerrWinfried
b26c6a55f0 add led modes for FX506HC 2022-12-07 11:41:49 +00:00
Luke D. Jones
93d472fe74 Use correct defaults for GfxMode and GfxPower 2022-12-07 12:31:52 +13:00
Luke D. Jones
5469c73f11 Adjust gitlab pipeline to ignore checks for tags 2022-12-07 11:55:09 +13:00
Luke D. Jones
ad95765954 Add missing files 2022-12-07 11:50:17 +13:00
Luke D. Jones
e42a5bc3e9 ROGCC: don't require supergfxd to be running
Prep fixes for new tag and release
2022-12-07 11:47:27 +13:00
Luke D. Jones
28347e87eb Prep new minor release 2022-12-06 20:10:03 +13:00
Luke D. Jones
b34cb672c3 Fix: ROGCC: log and show more errors on startup 2022-12-06 14:28:35 +13:00
Luke D. Jones
559ddc9a22 Fix: ROGCC: remove unused arg in fan curve widget 2022-12-06 10:08:11 +13:00
Luke D. Jones
a8c014881f Version bump for RC 2022-12-06 09:48:24 +13:00
Luke D. Jones
f417032ed9 Fix: ROGCC: apply changes to correct fan curve profile
The fan curve profile changes were applying to the currently *active*
profile and not the GUI selected profile being changed. Fixed.

Also clarify the buttons for fan curve apply.
2022-12-06 09:47:48 +13:00
Luke D. Jones
616fb3aea6 chore: cranky cleanups 2022-12-05 20:31:39 +13:00
Luke D. Jones
6e6e057995 Update changelog 2022-12-05 19:44:50 +13:00
Luke D. Jones
085e63ebab Merge commit 'fdadffcdde82' because of borked HEAD after pull 2022-12-05 19:44:08 +13:00
Luke D. Jones
fdadffcdde Fix: ROGCC: Correctly deny badly formed fan graphs
Closes #286
2022-12-05 19:40:00 +13:00
Luke Jones
5f51527dd7 Merge branch 'piivanov-main-patch-89025' into 'main'
Add led modes for G713RM

See merge request asus-linux/asusctl!143
2022-12-04 20:53:46 +00:00
Peter Ivanov
39525980a0 Add led modes for G713RM 2022-12-04 17:39:32 +00:00
Luke D. Jones
83a0b570e0 Cause great pain to self with cargo-deny + cargo-cranky 2022-12-04 22:10:08 +13:00
Luke D. Jones
2bfbce36b0 Bump dependencies 2022-12-04 22:09:28 +13:00
Luke D. Jones
2705b08dca Cause great pain to self with cargo-deny + cargo-cranky 2022-12-04 21:49:47 +13:00
Luke D. Jones
2fca7a09c4 bump dependencies 2022-12-04 20:16:33 +13:00
Luke Jones
ef0da62c55 Merge branch 'maxbachmann-main-patch-99498' into 'main'
add led modes for G513RM

See merge request asus-linux/asusctl!141
2022-12-04 01:48:10 +00:00
maxbachmann
9dab120bcf add led modes for G513RM 2022-12-03 22:03:35 +00:00
Luke D. Jones
14bf07ba79 Version bump for dep updates 2022-12-02 16:39:46 +13:00
Luke D. Jones
e76d01eaed Update dependencies 2022-12-02 16:37:33 +13:00
Luke Jones
072a066f28 Merge branch 'fixed_readme_dependency_list_for_fedora' into 'main'
rust/cargo is also needed

See merge request asus-linux/asusctl!140
2022-12-01 20:11:39 +00:00
A. Binzxxxxxx
165c6f8ab3 rust/cargo is also needed 2022-12-01 20:06:28 +00:00
Luke Jones
5728a9af62 Update README.md 2022-11-22 21:54:51 +00:00
Luke Jones
17a880b2c5 Merge branch 'main' into 'main'
Fix VivoBook detection

See merge request asus-linux/asusctl!139
2022-11-20 19:48:29 +00:00
RushingAlien
6ba9b9d75d Fix VivoBook detection 2022-11-19 22:06:34 +07:00
Luke Jones
eb1f6c83ce Merge branch 'fix-gitlab-ci' into 'main'
Fix GitLab CI

See merge request asus-linux/asusctl!138
2022-11-16 20:06:06 +00:00
Herohtar
af653ea405 Don't install unnecessary packages 2022-11-16 12:26:14 -06:00
Herohtar
bc13891cdf Install required libgtk-3-dev package 2022-11-16 12:25:29 -06:00
Luke D. Jones
aad4dc909e Bump version 2022-11-16 20:33:23 +13:00
Luke D. Jones
ad79adcbfa ROGCC: splatter log messages everywhere. Rename state control 2022-11-16 20:32:11 +13:00
Luke D. Jones
73b1a7050a ROGCC: Make zbus notifications fully manage pagestates 2022-11-15 22:26:17 +13:00
Luke D. Jones
762bfea102 ROGCC: share PageState so tray can use it. zbus notifs update this 2022-11-15 11:12:41 +13:00
Luke D. Jones
b41fdf5cfe ROGCC: add status for dgpu, charge ctl, panel-od to systray 2022-11-14 11:05:52 +13:00
Luke D. Jones
bf13ebebd3 Set tray icon after init 2022-11-13 21:00:33 +13:00
Luke D. Jones
3a73e3a526 Try to prevent tray loop stalling 2022-11-13 12:52:52 +13:00
Luke D. Jones
1211400d7b 4.5.1-RC1 2022-11-11 20:13:00 +13:00
Luke D. Jones
ff9edb9876 Enable system tray status for dGPU and actions 2022-11-11 20:09:43 +13:00
Luke D. Jones
20f8251dd3 Adjust FA506IE led mode match to FA506I 2022-11-10 09:14:17 +13:00
Luke Jones
902dfed67c Merge branch 'add-asus-tuf-gaming-a15-led-modes' into 'main'
Add led_data for 2022 ASUS TUF Gaming A15 FA506IE

See merge request asus-linux/asusctl!137
2022-11-09 20:12:04 +00:00
Luke D. Jones
5e08b4416d Bump version 2022-11-10 09:11:52 +13:00
Herohtar
44c3ab7294 Add led_data for 2022 ASUS TUF Gaming A15 FA506IE 2022-11-09 12:03:23 -06:00
Luke D. Jones
be40474f79 Update app icons 2022-11-09 21:47:41 +13:00
Luke Jones
3654da2ff8 Merge branch 'tuxfanou/building_opensuse' into 'main'
Add openSUSE requirements to build asusctl

See merge request asus-linux/asusctl!136
2022-11-08 20:20:46 +00:00
Luke Jones
60bbad4ab6 Merge branch 'feat-add-vivobook-family' into 'main'
Add Vivobook to asusd rules

See merge request asus-linux/asusctl!135
2022-11-08 20:19:00 +00:00
Sarang S
0a59d5c041 Add Vivobook to asusd rules 2022-11-08 20:19:00 +00:00
Stéphane Burdin
1506fc44d3 Add openSUSE requirements to build asusctl 2022-11-08 16:14:53 +01:00
Luke D. Jones
aad31610f2 Add missing file 2022-11-08 22:03:42 +13:00
Luke D. Jones
a6fe7645e9 Tray icons 2022-11-08 21:55:09 +13:00
Luke D. Jones
4f8745ae19 Prep release 4.5.0 2022-11-07 21:36:28 +13:00
Luke D. Jones
5f4e950819 Update deps. Fixes to runtime 2022-11-07 09:47:15 +13:00
Luke D. Jones
efc752cce6 ROGCC: Use tokio instead of smol 2022-11-07 09:00:46 +13:00
Luke D. Jones
37553a5fdd Remove some dbg! statements 2022-11-06 22:28:00 +13:00
Luke D. Jones
cd5a85a843 Clarify gpu mux notif 2022-11-06 22:17:46 +13:00
Luke D. Jones
7385844a9b Fix rogcc not closing when run-in-background 2022-11-06 21:58:33 +13:00
Luke D. Jones
0b71104833 Fix rog-control-center notifs 2022-11-06 15:21:43 +13:00
Luke D. Jones
688e3a7358 Send signals using the correct context for each 2022-11-06 12:48:19 +13:00
Luke D. Jones
58ff566d65 Fix inclusion of supergfxctl lib 2022-11-04 21:31:45 +13:00
Luke D. Jones
1332ac803c Add notification of dGPU state change 2022-11-04 21:29:47 +13:00
Luke D. Jones
ba1d3f045d Add missing file 2022-10-11 22:25:49 +13:00
Luke D. Jones
e0ed52092a Refined AC monitoring 2022-10-11 22:13:54 +13:00
Luke D. Jones
921637f979 Make some ledmodes more generic matched across models 2022-10-10 13:19:15 +13:00
Luke D. Jones
f6498337fe RCC: disable vsync due to NoAvailablePixelFormat error: 2022-10-04 11:37:23 +13:00
Luke D. Jones
3a640a3269 Bump rc version 2022-10-01 14:57:49 +13:00
Luke D. Jones
e938f1f9ec Minor fixes to attr writes 2022-10-01 14:57:25 +13:00
Luke D. Jones
600d0ae3d9 Clippy run 2022-09-30 15:10:56 +13:00
Luke D. Jones
8569edf684 Try official latest docker image 2022-09-29 18:17:28 +13:00
Luke D. Jones
52af4ad2b2 Use 'latest' rustdocker image 2022-09-29 18:06:54 +13:00
Luke D. Jones
cde1b4f252 Shift all deps to workspace versioning 2022-09-29 17:08:28 +13:00
Luke Jones
2a4754cfc4 Merge branch 'ledmodes_for_rogflowx16' into 'main'
Added LED modes for ROG Flow X16

See merge request asus-linux/asusctl!134
2022-09-27 20:05:12 +00:00
Rino
51c97fa350 Added LED modes for ROG Flow X16 2022-09-27 12:44:49 +00:00
Luke D. Jones
c968dce009 Cleanup notifications some 2022-09-24 18:44:10 +12:00
Luke Jones
b2b6707f2e Merge branch 'fluke/inotify' into 'main'
Fluke/inotify

See merge request asus-linux/asusctl!133
2022-09-24 02:39:44 +00:00
Luke D. Jones
7939b00aa3 Check inotify paths are valid. Add dgu/egpu/ac_online checks 2022-09-24 14:34:15 +12:00
Luke D. Jones
30550aaa91 Further improve the daemon controller pattern and reduce cloned code 2022-09-23 20:07:43 +12:00
Luke D. Jones
7ea1f41286 Convert chunk of daemon to use async mutex 2022-09-23 10:50:09 +12:00
Luke D. Jones
9608d190b9 Use tokio in asusctl 2022-09-22 22:36:16 +12:00
Luke D. Jones
3b9cf474a7 inotify relies on tokio, so a switch is required.. 2022-09-22 12:55:15 +12:00
Luke D. Jones
283cb7e589 Previous inotify macro was blocking. Needs async closures... 2022-09-21 22:41:24 +12:00
Luke D. Jones
5d87747d96 Is smol blocking or inotify blocking it? 2022-09-21 22:17:55 +12:00
Luke D. Jones
56285916cd daemon: inotify for panel_od and gu_mux_mode 2022-09-21 19:04:28 +12:00
Luke D. Jones
a44a1bfa89 Add GU603Z to ledmodes 2022-09-20 21:02:58 +12:00
Luke D. Jones
0c97cf710d Trial single inotify test 2022-09-20 20:57:39 +12:00
Luke D. Jones
62c7338b2d Use loops to ensure settings apply where a mutex is tried 2022-09-15 13:29:00 +12:00
Luke Jones
af24623178 Merge branch 'zephyrus-m16-ledmodes' into 'main'
Add ledmodes for 2021 Zephyrus M16 models

See merge request asus-linux/asusctl!132
2022-09-14 04:52:47 +00:00
Albert Geantă
facb7f7f49 Add ledmodes for 2021 Zephyrus M16 models 2022-09-13 11:05:05 +03:00
Luke D. Jones
e38ab624e9 Add libfontconfig1-dev to CI env 2022-08-29 21:18:43 +12:00
Luke D. Jones
d76cb3b95a Minor update to changelog 2022-08-29 21:07:27 +12:00
Luke D. Jones
910f529a9b Release 4.4.0 2022-08-29 21:04:45 +12:00
Luke D. Jones
7583d070d3 daemon: add check to avoid accidental use of TUF led control 2022-08-29 20:53:14 +12:00
Luke D. Jones
1f85e30e42 Add CLI for 0x19b6 Lid LED 2022-08-29 18:17:19 +12:00
Luke D. Jones
d1bdf4dc7e rog-aura: Add lid zone 2022-08-29 17:09:26 +12:00
Luke D. Jones
79b108ceb7 rog-gui: don't reset selection when enable fan-curve 2022-08-29 13:44:59 +12:00
Luke D. Jones
7d14e8d900 rog-gui: add reset-curve button 2022-08-29 13:27:25 +12:00
Luke D. Jones
493d61cf19 rog-profiles: fixup populating default curves if none 2022-08-29 13:27:25 +12:00
Luke D. Jones
fb08d83999 rog-gui: sort fan curve by name 2022-08-29 13:27:25 +12:00
Luke Jones
71241b7127 Merge branch 'new-hyperlink' into 'main'
Changed hyperlink from achived code

See merge request asus-linux/asusctl!131
2022-08-28 06:18:53 +00:00
Alex carter
09963534d8 Changed hyperlink from achived code 2022-08-28 15:20:00 +10:00
Luke D. Jones
64322044ac rog-aura: tested effects on TUF, works 2022-08-27 22:30:57 +12:00
Luke D. Jones
1a132d847f Update readme 2022-08-27 21:01:17 +12:00
Luke D. Jones
952a974e83 Bump various versions 2022-08-27 20:53:59 +12:00
Luke D. Jones
ebbfa58a76 rog-aura: Add flicker effect 2022-08-27 20:52:43 +12:00
Luke D. Jones
414d610bd2 Test battery search 2022-08-27 11:18:15 +12:00
Luke D. Jones
bff98ddf7b power: rc4, remove energy_full_design check 2022-08-26 21:09:52 +12:00
Luke D. Jones
97481cd45e rog-aura: add per-zone effects 2022-08-26 18:29:24 +12:00
Luke Jones
4f39c01139 Merge branch 'AlexanderRavenheart-main-patch-32476' into 'main'
Update asusd-ledmodes.toml: added board name G513RC

See merge request asus-linux/asusctl!130
2022-08-25 20:43:30 +00:00
Luke D. Jones
40987ecd5d rog-aura: add basic per-key support 2022-08-25 21:45:36 +12:00
Luke D. Jones
f378c54815 Remove println from example 2022-08-25 18:29:53 +12:00
Luke D. Jones
a8a99ac1d1 rog-aura: reorganise per-key effects 2022-08-25 18:25:04 +12:00
Luke D. Jones
503aa20257 rog-aura: don't start effect on red 2022-08-25 14:11:31 +12:00
Luke D. Jones
8c67836650 Implement simple 'breathe' per-key effect 2022-08-25 14:08:53 +12:00
Luke D. Jones
3fc839820e Version bump 2022-08-24 22:29:56 +12:00
Luke D. Jones
0ef524a94b rog-aura: bringup the per-key LED stuff again 2022-08-24 22:01:13 +12:00
Alexandru Rudi
f8cfacda47 Update asusd-ledmodes.toml: added board name G513RC 2022-08-24 04:28:45 +00:00
Luke D. Jones
f3876100ae rog-platform: Add extra check types to find battery
Closes #243
2022-08-24 10:11:32 +12:00
Luke D. Jones
fa1feaf9d9 rog-platform: additional check against manufacturer attr
Should close #242
2022-08-22 09:01:08 +12:00
Luke D. Jones
45641c928d Rename all instances of dgpu_only to gpu_mux 2022-08-21 21:39:01 +12:00
Luke D. Jones
eba9dc8a52 daemon: update an old log comment. Don't reload panel_od if not available
Closes #242
2022-08-21 21:28:52 +12:00
Luke D. Jones
a32527d1df Doc updates 2022-08-21 20:23:55 +12:00
Luke D. Jones
1f697b5ff1 daemon: Vastly improved task creation 2022-08-21 20:15:36 +12:00
Luke D. Jones
92009ef96c profiles: error if fan curve parse is less than 8
Closes #225
2022-08-20 22:05:22 +12:00
Luke D. Jones
3fe5896596 daemon: fix keyboard brightness setting
Closes #241
2022-08-20 21:42:18 +12:00
Luke D. Jones
f8cdde2adf rog-platform: add power (basics)
- Refactor the macros
- Add inotify creator for each attribute
2022-08-20 21:07:34 +12:00
Luke Jones
033f2141ef Merge branch 'alex39-main-patch-50587' into 'main'
Update asusd-ledmodes.toml - added G713RS

See merge request asus-linux/asusctl!129
2022-08-17 00:37:47 +00:00
AlexEdimensionz
f86bab6f8c Update asusd-ledmodes.toml - added G713RS
This is my laptop model and i confirm that "G713RS" is in the correct config group (tested all the modes)
2022-08-17 00:20:25 +00:00
Luke D. Jones
4951bce961 Add missing files :( 2022-08-17 11:16:19 +12:00
Luke D. Jones
fb92d65fa0 Prep for new release 2022-08-17 10:32:24 +12:00
Luke D. Jones
24fa075a44 Extend GpuMode to include other modes 2022-08-12 22:10:49 +12:00
Luke D. Jones
a0f7cf3acd Rename RogBios bits to Platform. Better GPU MUX support. 2022-08-12 21:51:04 +12:00
Luke D. Jones
d35707f2e4 Merge rog-supported in to rog-platform 2022-08-12 17:45:29 +12:00
Luke Jones
b20bde8116 Merge branch 'fluke/kernel-patch-leds' into 'main'
Create rog-platform, refactor rogcc ipc-file handling

See merge request asus-linux/asusctl!128
2022-08-12 04:40:59 +00:00
Luke D. Jones
308fba9413 Create rog-platform, refactor rogcc ipc-file handling
- Create new rog-platform crate to manage all i/o in a universal way
  + kbd-led handling
  + platform handling (asus-nb-wmi)
  + hidraw
  + usbraw
- Refactor how ROGCC handles IPC for background open, run-in-bg
2022-08-12 15:22:06 +12:00
Luke D. Jones
45268bfb2b Add note and screenshots of GUI 2022-08-06 09:36:47 +12:00
Luke D. Jones
004982cea7 ROGCC: group fan profile buttons with cpu/gpu buttons with enable/disable 2022-08-04 20:25:15 +12:00
Luke D. Jones
5ab24a624e Version bump 2022-08-03 09:52:37 +12:00
Luke D. Jones
700633e080 ROGCC: Remove power setting from correct array 2022-08-03 09:48:00 +12:00
Luke D. Jones
773c9902a5 Release 4.3.3 2022-08-02 15:11:02 +12:00
Luke D. Jones
e05d5bd143 Version bump. Add early-error display 2022-08-02 15:09:25 +12:00
Luke D. Jones
3e244d7d3d ROGCC: effect visuals. daemon: support TUF RGB 2022-08-02 14:25:27 +12:00
Luke D. Jones
ba4589f986 ROGCC: effect visual test 2022-08-02 09:27:10 +12:00
Luke Jones
083134fc73 Merge branch 'support-g713rw' into 'main'
Add G713RW to asusd-ledmodes.toml

See merge request asus-linux/asusctl!125
2022-07-31 21:27:43 +00:00
Luke Jones
3cc04fba60 Merge branch 'danielphan2003-main-patch-53505' into 'main'
Use INSTALL_DATA for toml and gif files

See merge request asus-linux/asusctl!127
2022-07-31 21:27:17 +00:00
Daniel Phan
3a00e4f1a3 Use INSTALL_DATA for toml and gif files 2022-07-31 15:34:25 +00:00
Luke D. Jones
eb78fb613c New udev rules to work with both TUF and ROG 2022-07-30 23:08:47 +12:00
Luke D. Jones
d0b9aee85a daemon: Re-enable aura control for TUF
Closes #228
2022-07-30 20:52:43 +12:00
Luke Jones
3e94ef05fb Merge branch 'fix/anime-brightness-ignores-first-6-leds' into 'main'
Fix brightness setting ignoring the first 6 leds

Closes #230

See merge request asus-linux/asusctl!126
2022-07-29 21:15:06 +00:00
Ivan Voskoboinyk
fbb025875b Fix brightness setting ignoring the first 6 leds
Fixes #230
2022-07-29 15:29:16 +00:00
Yevhen Kolomeiko
ae816bd13c Add G713RW to asusd-ledmodes.toml 2022-07-29 11:41:19 +00:00
Luke D. Jones
14f0693511 rog-aura: add gap between numpad on gl504 2022-07-29 19:22:47 +12:00
Luke D. Jones
de7fb4a942 ROGCC: use the correct colourspace for colour picker 2022-07-29 18:59:52 +12:00
Luke D. Jones
4164b4645d ROGCC: split keyboard layout into widget 2022-07-29 16:08:55 +12:00
Luke D. Jones
649b14fd0d rog-aura: stand-off the rog row 2022-07-29 16:03:39 +12:00
Luke D. Jones
6d97ef13a1 rog-aura: adjustment of layouts and key sizes 2022-07-29 15:56:03 +12:00
Luke D. Jones
7abad979c8 rog-aura: adjustment of layouts and key sizes 2022-07-29 15:35:03 +12:00
Luke D. Jones
0ec1574219 rog-aura: Cleanup layouts, add gl504_US.toml 2022-07-29 12:07:16 +12:00
Luke D. Jones
03042dd5c3 Remove accidental board name test 2022-07-29 11:26:38 +12:00
Luke D. Jones
3330e4973f rog-aura: add proper labels for keys via &str into 2022-07-29 11:15:37 +12:00
Luke D. Jones
5e06aeabe9 rog-aura: fix up G533 layout 2022-07-29 10:54:59 +12:00
Luke D. Jones
e99d8766fc ROGCC: rog-aura: Keyboard layout templates and definitions
This also removes shell completitions as these are not maintained.
2022-07-29 09:19:49 +12:00
Luke D. Jones
8f65b7e334 ROGCC: add enable/disable aura options depending on mode 2022-07-27 11:39:55 +12:00
Luke D. Jones
5a54b830bf ROGCC: style change 2022-07-26 22:35:51 +12:00
Luke D. Jones
85e08510f7 ROGCC: style change 2022-07-26 22:20:00 +12:00
Luke D. Jones
d56eeb7fb2 ROGCC: split widgets from pages 2022-07-26 21:39:30 +12:00
Luke D. Jones
bbc520a7f2 Update deps 2022-07-26 19:30:50 +12:00
Luke D. Jones
10e43c64ca ROGCC: rename config file 2022-07-26 19:16:46 +12:00
Luke D. Jones
38be25174a Add verbose output for fan-curve detection. Add mocking to GUI.
asusd: Verbose output of fan-curves on startup
ROGCC: Try to mock more of GUI state
2022-07-26 18:59:21 +12:00
Luke D. Jones
2584d69930 Update deps 2022-07-25 21:38:00 +12:00
Luke D. Jones
523f39cf9c Version bump for RC 2022-07-25 21:34:33 +12:00
Luke D. Jones
669760223e Clean up erroneously included files 2022-07-25 21:32:58 +12:00
Luke D. Jones
71ec13fa9f ROGCC: Attempt to add LED brightness 2022-07-25 21:21:32 +12:00
Luke D. Jones
409528b286 ROGCC: Better control of notifs, add panel_od 2022-07-25 20:55:30 +12:00
Luke D. Jones
17df3cf01d Add rog-control-center to the workspace 2022-07-25 16:43:48 +12:00
Luke D. Jones
808a1d2470 Fix misnamed led dbus method 2022-07-25 14:22:29 +12:00
Luke D. Jones
840c500b5e Switch a keyboard prod_id to enum 2022-07-25 14:07:29 +12:00
Luke D. Jones
42dc360d16 Bump daemon version 2022-07-25 12:43:17 +12:00
Luke D. Jones
f6183597c9 Trial BTreeMap<AuraModeNum, AuraEffect> return for led dbus 2022-07-25 10:26:47 +12:00
Luke D. Jones
79a45c4f10 Add to/from [f32;3] for Colour] 2022-07-25 09:51:25 +12:00
Luke D. Jones
19370215c0 Cleanup 2022-07-24 20:55:09 +12:00
Luke D. Jones
030dd661b8 Switch zbus led_mode to return AuraModeNum 2022-07-24 20:45:20 +12:00
Luke D. Jones
1fc12d9855 Make CurveData members public 2022-07-24 10:50:28 +12:00
Luke D. Jones
6c1b2b70ea Make FanCurveSet members public 2022-07-24 10:47:40 +12:00
Luke D. Jones
23f9af35bf Add Hash derive to Profile 2022-07-24 09:43:22 +12:00
Luke D. Jones
526626b80c Minor tweaks on derives 2022-07-24 09:28:00 +12:00
Luke Jones
10eaaac54b Merge branch 'sova/G713IC-led-support' into 'main'
Add LED support for G713IC

See merge request asus-linux/asusctl!124
2022-07-21 12:39:43 +00:00
SoVa
901a3ddcc9 Add LED support for G713IC 2022-07-21 14:18:33 +02:00
Luke Jones
e6ebf72a11 Merge branch 'main' into 'main'
Fix some typos.

See merge request asus-linux/asusctl!123
2022-07-21 07:59:16 +00:00
Luke D. Jones
cd7e748c88 Prep new release 2022-07-21 19:36:17 +12:00
成超(Cheng Chao)
a313359ef6 Fix some typos. 2022-07-21 12:46:44 +08:00
Luke Jones
f222eef6b7 Update CHANGELOG.md 2022-07-21 03:40:04 +00:00
Luke Jones
e6f3aeb851 Merge branch 'fluke/multi-led-power' into 'main'
Make LED power more universal

Closes #219

See merge request asus-linux/asusctl!122
2022-07-21 03:39:11 +00:00
Luke D. Jones
22605e57cc Properly set full defaults for LED power 2022-07-21 14:56:30 +12:00
Luke D. Jones
02fb7addf4 Make LED power more universal
Closes #219
2022-07-21 14:48:16 +12:00
Luke Jones
bdbb403a0e Merge branch 'fluke/errors' into 'main'
Improve error handling in some cases

See merge request asus-linux/asusctl!121
2022-07-20 09:01:55 +00:00
Luke D. Jones
7a8bede92f Return error if a pixel-gif is larger than the anime-display dimensions 2022-07-20 20:52:03 +12:00
Luke D. Jones
a71a40b509 Make rog-anime more tolerent of faults 2022-07-20 20:17:43 +12:00
Luke D. Jones
42fc5a5392 Minor doc comment change 2022-07-18 15:43:09 +12:00
Luke D. Jones
5017a0ea9b Add extra multizone test 2022-07-18 14:11:54 +12:00
Luke D. Jones
05f7b0060f Prep new release 2022-07-18 14:01:32 +12:00
Luke Jones
1043da5328 Merge branch 'fluke/multizone-defaults' into 'main'
Create defaults on missing zones

See merge request asus-linux/asusctl!120
2022-07-18 01:50:35 +00:00
Luke D. Jones
959ad35afa Create defaults on missing zones 2022-07-18 13:40:42 +12:00
Luke Jones
1e10255d01 Merge branch 'fluke/multizone-fixes' into 'main'
Fluke/multizone fixes

See merge request asus-linux/asusctl!119
2022-07-17 10:02:32 +00:00
Luke D. Jones
c72693bc53 Fix test for CI 2022-07-17 22:02:01 +12:00
Luke D. Jones
2297aad5e5 Fix test 2022-07-17 21:49:15 +12:00
Luke D. Jones
f39c0db680 Add more support detection for bios/system level components 2022-07-17 21:02:39 +12:00
Luke D. Jones
23353c77f3 Add panel_od support 2022-07-17 20:31:47 +12:00
Luke D. Jones
fee1486db6 Correctly save multizone config 2022-07-17 19:23:08 +12:00
Luke D. Jones
39c4253b24 Add GA401I Anime support 2022-07-17 15:08:18 +12:00
Luke D. Jones
84e924f46a Add doc comments for bytes of 0x1866 power control 2022-07-16 22:52:36 +12:00
Luke D. Jones
43364398b4 Add LED support for GX703HS
Closes #207
2022-07-16 15:11:37 +12:00
Luke D. Jones
3f09f221f4 Bump versions 2022-07-16 15:03:42 +12:00
Luke Jones
4ed922154b Merge branch 'validate-anime-brightness' into 'main'
Enforce valid image brightness in daemon and asusctl

See merge request asus-linux/asusctl!118
2022-07-16 03:00:22 +00:00
I Al Istannen
c0e36295b7 Enforce valid image brightness in daemon and asusctl 2022-07-16 03:00:22 +00:00
Luke D. Jones
ef04549c8e Bump versions 2022-07-16 13:45:23 +12:00
Luke D. Jones
a117c300d5 Add support for /etc/asusd/asusd-user-ledmodes.toml 2022-07-16 13:40:57 +12:00
Luke D. Jones
6956f7dffc Re-enable cargo test in pipeline 2022-07-15 23:54:30 +12:00
Luke D. Jones
fe49913550 Updated changelog 2022-07-15 23:54:20 +12:00
Luke D. Jones
89ddade2a3 Updated changelog 2022-07-15 23:54:07 +12:00
Luke Jones
bcb3d53ade Merge branch 'readme_cargo' into 'main'
cargo added to installation

See merge request asus-linux/asusctl!115
2022-07-15 11:31:05 +00:00
Luke Jones
9ab9028d79 Merge branch 'fluke/ga402-anime' into 'main'
First pass of Anime update for new matrix display

See merge request asus-linux/asusctl!113
2022-07-15 11:30:28 +00:00
Luke Jones
8de6447562 Merge branch 'fluke/ga402-anime' into 'fluke/ga402-anime'
AnimeImage patch for GA402

See merge request asus-linux/asusctl!116
2022-07-15 11:23:43 +00:00
I-Al-Istannen
2512cea19d Slightly adjust G402 scaling, add some more documentation 2022-07-15 13:12:34 +02:00
Luke D. Jones
eabe78af71 tmp 2022-07-15 23:00:01 +12:00
Luke D. Jones
16c4ee609e Add GA402 anime-matrix packet unit test 2022-07-15 20:40:16 +12:00
Luke D. Jones
37d586c5de Additional comments in animeimage 2022-07-15 20:38:07 +12:00
Luke D. Jones
e66847c263 Add commenting to AnimeImage to help with GA402 2022-07-15 20:37:30 +12:00
I-Al-Istannen
a2c8a226a4 Complete anime diagonal gif support for GA402 2022-07-15 20:37:30 +12:00
Luke D. Jones
f3f6fadfe2 Fix anime exampels 2022-07-15 20:37:30 +12:00
Luke D. Jones
ff76c356c5 First pass of Anime update for new matrix display
Co-authored with @I-Al-Istannen

Part of #189
2022-07-15 20:37:30 +12:00
Luke D. Jones
a22808aff3 Add note in cargo.toml re: lto 2022-07-15 10:21:11 +12:00
Luke D. Jones
f39fd6dfbb Use hashset in aura power config 2022-07-15 09:30:10 +12:00
Luke Jones
95598f2a76 Merge branch 'fluke/multizone' into 'main'
Multizone support plus rebuild of LED power control

Closes #213

See merge request asus-linux/asusctl!117
2022-07-14 11:20:22 +00:00
Luke D. Jones
535e104ccc Rebuild of LED power control 2022-07-14 23:05:33 +12:00
saswatasarkar13
522cee42e5 cargo added to installation 2022-07-14 14:57:04 +05:30
Luke D. Jones
51656dc13f Initial multizone fixup work 2022-07-14 15:09:28 +12:00
Luke D. Jones
abd412b5d5 Save and restore kb bright only on shutdown/sleep/boot/wak
Closes #213
2022-07-14 13:05:51 +12:00
Luke D. Jones
4d8c05cd92 Add more multizone support 2022-07-14 13:05:41 +12:00
Luke Jones
f2ca8081af Merge branch 'user.sv4.apps-main-patch-52927' into 'main'
Fan curve kernel requirement message update.

See merge request asus-linux/asusctl!112
2022-07-12 01:55:42 +00:00
User
7539011be5 Update main.rs 2022-07-09 10:41:29 +00:00
Luke D. Jones
5117427143 Add GA503R LED modes
Closes #205
2022-06-26 11:57:15 +12:00
Luke D. Jones
e95986b830 Update changelog 2022-06-24 23:12:04 +12:00
Luke D. Jones
5311972345 Set keyboard brightness on resume. Refactor some tasks 2022-06-24 23:09:45 +12:00
Luke D. Jones
967295fba7 Fixes to anime-matrix system thread handling 2022-06-21 23:29:44 +12:00
Luke D. Jones
5403c5fb4f Update changelog 2022-06-20 23:16:25 +12:00
Luke D. Jones
65986c3114 prep new release 2022-06-20 23:13:17 +12:00
Luke D. Jones
13a90b00f3 Adjust how thread exit is handled for anime controller 2022-06-20 22:43:12 +12:00
Luke Jones
2ee7fc9910 Merge branch '191-full-power-states-combinations' into 'main'
Combination for power state leds boot/sleep/all/keys/side LEDS

Closes #191

See merge request asus-linux/asusctl!111
2022-06-19 22:03:23 +00:00
mpiffault
a0a0efabbb Combination for power state leds boot/sleep/all/keys/side LEDS 2022-06-19 22:03:23 +00:00
Luke Jones
9a50278b98 Merge branch 'fluke/async-tasks' into 'main'
Fixes to tasks

See merge request asus-linux/asusctl!110
2022-06-12 03:42:09 +00:00
Luke D. Jones
9519a35e32 Fixes to tasks 2022-06-12 15:34:38 +12:00
Luke Jones
578d5fd541 Merge branch 'fix/199-multizone-commands-not-displayed' into 'main'
Fixes #199 multizone commands not displayed

Closes #199

See merge request asus-linux/asusctl!109
2022-06-12 03:32:11 +00:00
Martin Piffault
642bc5dda1 output multizone commands required 2022-06-07 22:31:53 +02:00
Martin Piffault
88274abdb5 init multizone_led_mode and per_key_led_mode from LaptopLedData 2022-06-07 22:30:37 +02:00
Luke Jones
aea65f5c5f Merge branch 'fluke/async-tasks' into 'main'
Re-enable notif for profile change

See merge request asus-linux/asusctl!108
2022-06-07 00:13:24 +00:00
Luke D. Jones
edfbfde13b Re-enable notif for profile change 2022-06-07 12:08:36 +12:00
Luke Jones
dcc676d60a Merge branch 'fluke/async-tasks' into 'main'
Added tasks for reload keyboard bright, and for charge control

See merge request asus-linux/asusctl!107
2022-06-06 23:53:41 +00:00
Luke D. Jones
561f61116c Added tasks for reload keyboard bright, and for charge control 2022-06-07 11:49:12 +12:00
Luke Jones
6a4594466b Merge branch 'fluke/async-tasks' into 'main'
Async tasks

See merge request asus-linux/asusctl!106
2022-06-06 13:00:10 +00:00
Luke D. Jones
af216ee08c Async tasks 2022-06-07 00:54:33 +12:00
Luke D. Jones
e493113450 update changelog 2022-06-06 18:25:27 +12:00
Luke D. Jones
74e1d5bdc4 Add brightness to anime zbus notif 2022-06-06 18:24:08 +12:00
Luke D. Jones
5c0ad3e590 Re-enable notification on anime power-state change 2022-06-06 18:18:35 +12:00
Luke D. Jones
6e872ecab9 Add diagonal-template.png to rog-anime/data/anime/custom/
Closes #163
2022-06-06 17:20:38 +12:00
Luke D. Jones
46a4cde77f Add G512 to LED support list
Closes #174
2022-06-06 17:02:41 +12:00
Luke D. Jones
fc7c444107 Add GU502LV LED support
Closes #187
2022-06-06 16:57:50 +12:00
Luke D. Jones
822438e0d2 Version bumps 2022-06-06 14:53:30 +12:00
Luke D. Jones
de43a37e9e Use smol async for daemon and daemon-user 2022-06-06 14:34:59 +12:00
Luke D. Jones
d4b2d2f403 Use smol async for asus-notify 2022-06-06 13:57:03 +12:00
Luke D. Jones
6e33eab136 Update anime examples 2022-06-06 13:11:54 +12:00
Luke D. Jones
1e4bc85fee Partial asusd-user update 2022-06-06 01:33:14 +12:00
Luke D. Jones
31fff75f08 Update more deps 2022-06-06 00:41:07 +12:00
Luke D. Jones
f0620154c8 Update changelog 2022-06-06 00:21:05 +12:00
Luke D. Jones
711aa1e4be Add support for GA402R
Closes #196
2022-06-06 00:14:28 +12:00
Luke D. Jones
854f2d75b3 Format 2022-06-06 00:09:23 +12:00
Luke D. Jones
a85e2f6130 Finalise zbus3 conversion 2022-06-06 00:08:59 +12:00
Luke Jones
bac2ba6f09 Merge branch 'mpiffault-main-patch-00521' into 'main'
Update asusd-ledmodes.toml to support Asus Rog Strix G15 G513QM

See merge request asus-linux/asusctl!103
2022-06-05 02:58:49 +00:00
Luke Jones
47e5270f9c Merge branch 'feat/side-leds-toggle-support' into 'main'
Adds support to enable/disable side leds #191

See merge request asus-linux/asusctl!104
2022-06-05 02:58:24 +00:00
Luke Jones
68cbf09e9f Merge branch 'fix/aura-help-options-display' into 'main'
Fixes all available led-mode commands not displaying with `asusctl led-mode --help`

See merge request asus-linux/asusctl!105
2022-06-05 02:54:31 +00:00
Martin Piffault
9f18c88153 fix all available options not being displayed in led-mode help 2022-06-04 14:47:40 +02:00
Martin Piffault
c6caafdcb7 adds support to enable/disable side leds 2022-05-31 17:00:21 +02:00
mpiffault
b22a3e1a59 Update asusd-ledmodes.toml to support Asus Rog Strix G15 G513QM 2022-05-30 08:06:26 +00:00
Luke Jones
b6934bbf63 Merge branch 'as/issue_176_1' into 'main'
Fix for fan_curve related integer divison bug

Closes #176

See merge request asus-linux/asusctl!102
2022-04-08 21:18:47 +00:00
Armas Spann
3cd6eb13a9 fixed interger division bug and related tests, as well as a comment bug 2022-04-07 01:16:06 +02:00
Luke Jones
272be2aaad Merge branch 'as/issue_176' into 'main'
fix for #176 - fancurve percentage check not handled correctly

Closes #176

See merge request asus-linux/asusctl!101
2022-04-05 21:37:23 +00:00
Armas Spann
99dd6ce77f fix for #176 - fancurve percentage check not handled correctly 2022-04-05 23:33:43 +02:00
Luke Jones
fc14455da4 Merge branch 'ankushmishra9-main-patch-66732' into 'main'
Fixed formatting of install instructions

See merge request asus-linux/asusctl!96
2022-02-07 22:59:34 +00:00
Luke Jones
26a52dae23 Merge branch 'main' into 'main'
add g513ic led

See merge request asus-linux/asusctl!94
2022-01-19 20:13:34 +00:00
Ankush Mishra
75864d33a6 Fixed formatting of install instructions 2022-01-19 17:57:06 +00:00
Luke Jones
63a97b6665 Merge branch 'main' into 'main'
fixed a small typo

See merge request asus-linux/asusctl!95
2022-01-15 20:51:52 +00:00
AlenPaulVarghese
21a37a3bb0 fixed a small typo 2022-01-14 18:49:15 +00:00
dada513
de586b5368 add g513ic led 2022-01-11 10:08:45 +00:00
Luke D. Jones
ba40c3f739 Update dependencies 2021-12-19 21:01:47 +13:00
Luke D. Jones
31eff037a2 Bump to version 4.0.7 2021-12-19 21:00:58 +13:00
Luke D. Jones
630dee0b2a Update notes in CLI tool 2021-12-19 20:57:50 +13:00
Luke Jones
9110f06ed5 Update README.md
Remove whitespace and rustup from fedora build section
2021-12-17 21:18:00 +00:00
Luke Jones
2b0eceaa9d Merge branch 'main' into 'main'
Update of README for building and installing

See merge request asus-linux/asusctl!93
2021-12-17 21:16:56 +00:00
Peter Ross
c96e1babe5 Update README.md 2021-12-16 15:23:08 +00:00
Peter Ross
9388cbde5d Update README.md 2021-12-16 15:16:35 +00:00
Luke D. Jones
e739cddd6a Update patch links 2021-12-04 16:04:56 +13:00
Luke Jones
8cee6e0fc4 Remove Ubuntu repo instructions 2021-11-14 21:51:56 +00:00
Luke Jones
bcf516afeb Merge branch 'sonnyp-main-patch-01923' into 'main'
Update kernel support for Linux 5.15

See merge request asus-linux/asusctl!88
2021-11-12 00:23:54 +00:00
Luke Jones
b0e3e81b7f Merge branch 'fix/platform-functions/profile-support' into 'main'
Fix incorrect power profile support validation.

See merge request asus-linux/asusctl!89
2021-11-12 00:23:22 +00:00
Luke Jones
ce6a1215a3 Merge branch 'LordVicky-main-patch-24845' into 'main'
Update asusd-ledmodes.toml to support Asus Rog Strix G15 G513QE

See merge request asus-linux/asusctl!90
2021-11-12 00:22:51 +00:00
LordVicky
f54c1dc7d0 Fix typo 2021-11-09 07:32:39 +00:00
LordVicky
43aaae8d47 Update asusd-ledmodes.toml to support Asus Rog Strix G15 G513QE 2021-11-09 07:28:57 +00:00
Alexander Narsudinov
ca463a2944 Fix incorrect power profile support validation.
Before this patch power profile support validation used wrong flag from PlatformProfileFunctions struct.
2021-11-07 15:11:31 +03:00
Sonny Piers
20e22589dc Update kernel support for Linux 5.15 2021-11-04 11:47:47 +00:00
Luke D. Jones
38d047cb8a Update changelog 2021-11-01 16:03:40 +13:00
Luke D. Jones
1d977199f3 Fix cli for bios/g-sync 2021-11-01 10:57:40 +13:00
Luke Jones
5041019d77 Merge branch 'fluke/anime-cli' into 'main'
Fluke/anime cli

See merge request asus-linux/asusctl!87
2021-10-30 20:28:36 +00:00
Luke D. Jones
aa3835d3b3 Bump versions 2021-10-31 09:24:07 +13:00
Luke D. Jones
678505811d Add additional anime cli commands for image types 2021-10-28 23:43:50 +13:00
Luke D. Jones
a925cbaed5 Bump version 2021-10-27 23:19:31 +13:00
Luke Jones
7d2201d873 Merge branch 'fluke/bugfixes' into 'main'
Add led modes for G513QR

Closes #144 and #143

See merge request asus-linux/asusctl!86
2021-10-27 10:18:31 +00:00
Luke D. Jones
c0c1608d44 Update deps 2021-10-27 23:15:25 +13:00
Luke D. Jones
7bc6c83a04 Check and pass error if charge limit not in 20-100 range
Closes #144
2021-10-27 23:04:44 +13:00
Luke D. Jones
3f0df82f2d Parse percentages in fan curve only if '%' provided otherwise range is 0-255 2021-10-27 22:42:32 +13:00
Luke D. Jones
328ff0251b Add led modes for G513QR
Closes #143
2021-10-27 22:35:48 +13:00
Luke Jones
c52582a413 Merge branch 'fluke/bugfixes' into 'main'
Bugfixes

Closes #139 and #140

See merge request asus-linux/asusctl!85
2021-10-02 07:34:55 +00:00
Luke D. Jones
3aa6eee306 Bugfixes
- Spawn tasks on individual threads
- Don't force a default of fan-curve on reload
- Add missing profile commands
- Begin obsoleting the graphics switch command in favour of supergfxctl
- Slim down the notification daemon to pure ASUS notifications

Bad behaviour in fan-curve new function that was forcing a re-init
to default on reload. Remove this and only save config again after
loading the config file and writing a curve (hidden side effect of
write is that a zeroed array is defaulted to read-from-system - this
needs to be changed too).

Closes #140, #139
2021-10-02 20:31:14 +13:00
Luke Jones
7d47faba0e Merge branch 'plasma-logout' into 'main'
Add kde logout prompt as fallback to gnome-session-quit

See merge request asus-linux/asusctl!82
2021-09-21 08:07:43 +00:00
Luke Jones
f6fb477898 Merge branch 'main' into 'main'
Updated asusd-ledmodes.toml with ROG Strix G713QM

See merge request asus-linux/asusctl!83
2021-09-21 08:06:59 +00:00
Abhijith M
8963960d4b Updated asusd-ledmodes.toml with ROG Strix G713QM 2021-09-21 02:09:53 +00:00
Janghyub Seo
ef973f676b Add kde logout prompt as fallback to gnome-session-quit 2021-09-19 02:13:11 +09:00
Luke D. Jones
812f9ea30e Add lock update 2021-09-16 22:38:09 +12:00
Luke Jones
ff843b1241 Merge branch 'main' into 'main'
Add G533QS to supported models

See merge request asus-linux/asusctl!81
2021-09-16 10:30:09 +00:00
George Dumitrescu
59e7af149d Add G533QS to supported models 2021-09-16 10:07:48 +03:00
Luke D. Jones
6f14c85287 Revert supergfxctl deps to git 2021-09-16 16:03:41 +12:00
Luke D. Jones
ac0dec4dbf Bump daemon version for release 2021-09-16 11:20:17 +12:00
Luke D. Jones
e3d192412e Bugfixes 2021-09-16 11:19:05 +12:00
Luke Jones
9fadb6db30 Merge branch 'necessary129-main-patch-69023' into 'main'
Add another Strix G17 model

See merge request asus-linux/asusctl!80
2021-09-15 00:06:31 +00:00
Shamil K
f8a1b71866 Add another Strix G17 model 2021-09-14 12:00:04 +00:00
Luke Jones
c0a55acba7 Merge branch 'main' into 'main'
Adding ROG Flow X13 to LED modes known devices

See merge request asus-linux/asusctl!79
2021-09-14 11:45:56 +00:00
Joseph Ferano
4f232de634 Adding ROG Flow X13 to LED modes known devices 2021-09-14 18:05:42 +07:00
Luke Jones
d351ebdaa0 Merge branch 'fluke/fan_curves_v13' into 'main'
Fluke/fan curves v13

See merge request asus-linux/asusctl!78
2021-09-14 02:55:51 +00:00
Luke D. Jones
ab195e1d84 Fan curve enablement
- Add CtrlProfileTask
- Add method to reset active profile curve to platform default
- Wrap the zbus methods for profiles + fan curves
- Enable CLI args for fan curves
- CLI mod and save curves
2021-09-14 14:52:15 +12:00
Luke D. Jones
7041d77256 Fix asusd-ledmodes.toml 2021-09-11 17:03:32 +12:00
Luke D. Jones
99dd052d54 Bump version in readme 2021-09-11 00:27:21 +12:00
Luke Jones
de9942609e Merge branch 'fluke/fan_curves_v9' into 'main'
Fluke/fan curves v9

See merge request asus-linux/asusctl!77
2021-09-10 12:26:14 +00:00
Luke D. Jones
b939a9d331 Fetch and store fan curve correctly 2021-09-11 00:25:46 +12:00
Luke D. Jones
0a565a7a5c Fleshing out functions and zbus controls 2021-09-08 23:33:42 +12:00
Luke D. Jones
bfaa478a4a Begin syncing changes with patch series 2021-09-07 20:20:37 +12:00
Luke Jones
f895a5623e Merge branch 'doc-ubuntu' into 'main'
Add ubuntu repo install commands

See merge request asus-linux/asusctl!76
2021-09-06 03:48:19 +00:00
Guy Sheffer
b7c869bd64 Add ubuntu repo install commands 2021-09-05 10:55:16 +03:00
Luke D. Jones
5f677bc3b9 Provide extra help tips. Update manual 2021-08-29 21:30:30 +12:00
Luke D. Jones
ccfadc2fcb Updates to asusctl cli app 2021-08-28 11:47:01 +12:00
Luke D. Jones
c6cc304a42 Clean up unwrap()'s. Print out info in asusctl if error 2021-08-28 11:07:47 +12:00
Luke D. Jones
3d41a7978a Fix crash when platform_profile not supported
Closes #130
2021-08-28 09:33:23 +12:00
Luke D. Jones
43fc467d58 Fix rm of not installed components 2021-08-28 00:25:51 +12:00
Luke D. Jones
6aba60f604 Try to re-get AniMe dev handle on write error 2021-08-27 22:31:50 +12:00
Luke D. Jones
a13dedf500 Cleanup 2021-08-27 20:46:04 +12:00
dragonn
cb490f23e9 Requesting dbus name after finishing initalizaction 2021-08-27 20:45:37 +12:00
Luke Jones
7dc8a743b9 Merge branch 'fluke/platform_curves' into 'main'
platform_profile + fan curve support

Closes #129 and #128

See merge request asus-linux/asusctl!75
2021-08-27 08:27:10 +00:00
Luke D. Jones
52f3b5a7bf Charge limit: try to support BAT<n>
Closes #128
2021-08-27 20:22:15 +12:00
Luke D. Jones
e89e7ca10f Add LED brightness pre/next cycle
Closes #129
2021-08-27 20:15:15 +12:00
Luke D. Jones
2431dd9e93 Remove supergfxctl to own repo 2021-08-26 16:06:57 +12:00
Luke D. Jones
453d3091c1 Bump major versions 2021-08-26 14:23:28 +12:00
Luke D. Jones
8db37491f3 Mention breaking changes in log 2021-08-26 13:57:19 +12:00
Luke D. Jones
cf915b9e00 Move anime data. Twiddle supergfxctl 2021-08-26 13:53:54 +12:00
Luke D. Jones
326ca37847 rog-supported crate 2021-08-26 13:17:17 +12:00
Luke D. Jones
498e604531 Major update to supergfx and others 2021-08-26 11:44:11 +12:00
Luke D. Jones
60b7f3be69 Begin cleanup 2021-08-25 11:42:32 +12:00
Luke D. Jones
6ceb5cf939 Major restructure to move gfx control out to crate 2021-08-25 11:16:23 +12:00
Luke D. Jones
0ed97db4c1 Temporary checkpoint 2021-08-24 12:35:57 +12:00
Luke D. Jones
8fcd05c2bb Append small extra help to bios option cli 2021-08-12 10:35:37 +12:00
Luke D. Jones
6de4590f27 Update fan curve to use git repo 2021-08-12 10:21:09 +12:00
Luke Jones
b097fd4da9 Merge branch 'fluke/anime' into 'main'
AniMe: more png colour type support

Closes #122 and #121

See merge request asus-linux/asusctl!73
2021-08-11 08:31:33 +00:00
Luke D. Jones
2a8e05707d AniMe: more png colour type support
Closes #121, #122
2021-08-11 20:27:44 +12:00
Luke Jones
a54e112978 Merge branch 'no_star_for_you' into 'main'
Remove Star from G513IH supported modes

See merge request asus-linux/asusctl!72
2021-08-04 01:04:57 +00:00
pshem
5785eb981d Remove Star from G513IH supported modes 2021-08-02 10:06:48 +01:00
Luke Jones
49234af08b Merge branch 'fluke/profiles' into 'main'
Fluke/profiles

See merge request asus-linux/asusctl!71
2021-08-01 22:53:38 +00:00
Luke D. Jones
8f5717def8 Version bump, various fixes 2021-08-02 10:50:17 +12:00
Luke D. Jones
9e55c0b2ca Fix incorrect name match of Star keyboard effect 2021-08-02 10:28:50 +12:00
Luke Jones
dd6ee91364 Merge branch 'main' into 'main'
Enable multizone support on Strix 513IH

See merge request asus-linux/asusctl!69
2021-08-01 22:03:30 +00:00
Luke Jones
efbb838ca1 Merge branch 'G513QY-ledmodes' into 'main'
add G513QY ledmodes

See merge request asus-linux/asusctl!70
2021-08-01 21:27:59 +00:00
Sonny Piers
daf7d39d41 add G513QY ledmodes 2021-08-01 23:12:59 +02:00
pshem
28b1194924 Fix multizone support on Strix 513IH 2021-08-01 18:00:04 +01:00
Luke Jones
73d95ca187 Merge branch 'fluke/profiles' into 'main'
fix: Profile select by name is correctly choosing

Closes #96 and #100

See merge request asus-linux/asusctl!68
2021-07-31 12:19:28 +00:00
Luke D. Jones
00b7c6482f fix: remove the parsing for root supported functions 2021-08-01 00:15:38 +12:00
Luke D. Jones
29c26e8c89 fix: Profile select by name is correctly choosing
Closes #100 #96
2021-08-01 00:10:11 +12:00
Luke D. Jones
fb124dd228 Fix clippy warnings 2021-07-31 23:09:23 +12:00
Luke D. Jones
0599be02dc fix: remove dbg!() output 2021-07-31 23:03:17 +12:00
Luke Jones
81a88263a9 Merge branch 'fluke/cli-fixes' into 'main'
Fluke/cli fixes

See merge request asus-linux/asusctl!67
2021-07-31 11:00:43 +00:00
Luke D. Jones
cea1fd2540 Fix small issues with CLI 2021-07-31 22:57:17 +12:00
Luke Jones
f2ced3bc7c Merge branch 'main' into 'main'
Add Zephyrus M GM501GS

Closes #109

See merge request asus-linux/asusctl!66
2021-07-30 23:48:58 +00:00
pshem
dc2a05894b Add Zephyrus M GM501GS 2021-07-30 17:45:00 +01:00
Luke D. Jones
9ee962ad09 systemd: sleep 2 after unit init 2021-07-30 14:35:44 +12:00
Luke Jones
eb7ef0af4f Merge branch 'main' into 'main'
add a protection to not allow running asusd in terminal

Closes #104

See merge request asus-linux/asusctl!64
2021-07-30 00:12:17 +00:00
Luke Jones
dc51120c27 Merge branch 'main' into 'main'
Add G533QR and 513IH to ledmodes

See merge request asus-linux/asusctl!65
2021-07-30 00:11:05 +00:00
pshem
fc4c2c4346 Add support for 513IH led modes 2021-07-24 19:34:09 +01:00
pshem
3f6be037c1 Add G533QR to ledmodes 2021-07-24 14:39:11 +01:00
Luke Jones
0a80c97f02 Update README.md 2021-07-13 04:36:39 +00:00
dragonn
88abafc728 add a protection to not allow running asusd in terminal 2021-07-09 18:40:38 +02:00
Luke Jones
ac880a0363 Merge branch 'fluke/gfx-mode-changes' into 'main'
Fluke/gfx mode changes

See merge request asus-linux/asusctl!63
2021-06-10 21:06:56 +00:00
Luke D. Jones
baebd51d99 Better control of gfx modes 2021-06-11 09:03:50 +12:00
Luke D. Jones
226620eb53 Fix up modes and icons 2021-06-07 19:19:49 +12:00
Luke D. Jones
1b34079d14 Trial of blocking vfio/compute unless in integrated mode 2021-06-07 11:02:21 +12:00
Luke D. Jones
8deeffcdad Minor fix to compute/vfio switch 2021-06-06 21:33:31 +12:00
Luke D. Jones
b7e45d7305 Bump versions for release 2021-06-06 21:02:07 +12:00
Luke D. Jones
d9077db234 Bugfix configs 2021-06-06 20:58:19 +12:00
Luke D. Jones
439b006342 Force change to integrated if in nvidia or hybrid mode
Force change to integrated if in nvidia or hybrid mode and user tries
to switch to vfio or compute
2021-06-06 13:44:34 +12:00
Luke D. Jones
ffa74d52e5 Fix LED brightness apply on resume 2021-06-06 12:12:17 +12:00
Luke Jones
6ccdd703e6 Merge branch 'fluke/anime-fade' into 'main'
Fluke/anime fade

See merge request asus-linux/asusctl!62
2021-05-31 01:07:17 +00:00
Luke D. Jones
bb910344b8 Basic fade in/out of gifs 2021-05-31 10:06:35 +12:00
Luke D. Jones
b9c4ff9ca7 Add GA503Q led modes 2021-05-30 10:20:17 +12:00
Luke D. Jones
62a18d4e57 Minor cleanup of bios controller 2021-05-29 15:33:47 +12:00
Luke D. Jones
f520e381a9 Attempt to provide more info to users gfx switching 2021-05-29 11:42:15 +12:00
Luke D. Jones
1dd543ddf3 Simplify the notifier 2021-05-27 13:22:08 +12:00
Luke Jones
a7ef63bd8a Merge branch 'formatted_supported_functions_message' into 'main'
Improving message formatting of supported functions

See merge request asus-linux/asusctl!61
2021-05-26 19:44:47 +00:00
KoStard
db43c0f2a4 Improving message formatting of supported functions
- Implementing fmt::Display for SupportedFunctions and sub-structs
2021-05-26 20:09:44 +04:00
Luke D. Jones
f0e5bb4ad1 dbus: send/recv notifications for bios options 2021-05-26 21:17:45 +12:00
Luke D. Jones
36bba75c50 bugfix: fix profile fan modes and creating 2021-05-26 09:24:18 +12:00
Luke Jones
b2dc610c0b Merge branch 'fluke/extras' into 'main'
bugfix: fix profile cycling

See merge request asus-linux/asusctl!60
2021-05-25 09:46:26 +00:00
Luke D. Jones
42d0eb0aba bugfix: fix profile cycling 2021-05-25 21:44:01 +12:00
Luke Jones
c14768182c Merge branch 'fluke/extras' into 'main'
Update config & dbus parts, cleanup deps, device power states

See merge request asus-linux/asusctl!59
2021-05-24 10:13:46 +00:00
Luke D. Jones
ef7e2135bf Prep for release 2021-05-24 22:10:30 +12:00
Luke D. Jones
2b58e259de Update config & dbus parts, cleanup deps, device power states
- Add extra config options and dbus methods
- Add power state signals for anime and led
- Refactor to use channels for dbus signal handler send/recv
- Split out profiles independant parts to a rog-profiles crate
- Cleanup dependencies
- Fix some dbus Supported issues
2021-05-24 18:56:21 +12:00
Luke D. Jones
ba03e8feb8 gfx: tmp informational only store of vfio/compute mode 2021-05-18 09:54:26 +12:00
Luke D. Jones
7771c6b8da gfx: Remove option for vfio/compute save 2021-05-18 09:18:36 +12:00
Luke D. Jones
04c9285ee6 add GX550L led modes 2021-05-17 12:25:16 +12:00
Luke D. Jones
bf4141e4b8 Additional info in manual 2021-05-16 15:59:39 +12:00
Luke D. Jones
233315f668 Small fix to heading in manual 2021-05-16 15:24:30 +12:00
Luke D. Jones
8332fb12f1 Update documents 2021-05-16 15:17:46 +12:00
Luke D. Jones
594e69f9b7 Minor readme update 2021-05-15 22:58:42 +12:00
Luke Jones
0aac0ce495 Merge branch 'fluke/refactor-patterns' into 'main'
bugfix: don't deadlock on change compute/vfio/compute

Closes #88 and #86

See merge request asus-linux/asusctl!58
2021-05-15 10:25:03 +00:00
Luke D. Jones
e24b4858a4 bugfix: don't deadlock on change compute/vfio/compute
Closes: #86 #88
2021-05-15 22:22:36 +12:00
Luke D. Jones
cf2b459e48 Add legal statement for trademarks 2021-05-06 12:29:12 +12:00
Luke D. Jones
895179fdad Add legal statement for trademarks 2021-05-06 12:27:59 +12:00
Luke Jones
fe3e8792eb Merge branch 'readmefix' into 'main'
corrected auto-builds url

See merge request asus-linux/asusctl!56
2021-05-03 18:53:15 +00:00
Aaron Johnson
1916641e2e corrected auto-builds url 2021-05-03 12:58:33 -05:00
Luke Jones
3ea0737be9 Merge branch 'fluke/refactor-patterns' into 'main'
Fluke/refactor patterns

See merge request asus-linux/asusctl!55
2021-04-26 03:53:21 +00:00
Luke D. Jones
c67373a830 bugfix: add version to user daemon. Fix multiple anime config 2021-04-26 15:49:35 +12:00
Luke D. Jones
41cbf4d353 Refactor dameon gfx 2021-04-25 22:53:38 +12:00
Luke Jones
7a4c14f7b8 Merge branch 'fluke/aura-crate' into 'main'
Release prep

See merge request asus-linux/asusctl!54
2021-04-25 03:07:13 +00:00
Luke D. Jones
f52a4d464a Release prep 2021-04-25 14:52:26 +12:00
Luke Jones
aa71592a31 Merge branch 'fluke/aura-crate' into 'main'
profiles: add dbus methods to change active profile

Closes #68, #73, and #81

See merge request asus-linux/asusctl!53
2021-04-25 02:37:31 +00:00
Luke D. Jones
dc6e8f8dcb profiles: add dbus methods to change active profile
Closes #81, #73, #68
2021-04-25 14:33:41 +12:00
Luke D. Jones
1a4836246f aura: support keyboard LED enable/disable with awake/sleep 2021-04-25 12:28:09 +12:00
Luke D. Jones
ab80b0742f gfx: asusd config option to not save compute/vfio mode switch 2021-04-20 21:10:23 +12:00
Luke D. Jones
6926aeed20 gfx: enable correct rebootless compute mode switch 2021-04-20 19:33:55 +12:00
Luke D Jones
f95e42e4b9 Reload LED mode on boot 2021-04-19 10:05:37 +12:00
Luke D Jones
82bee6b86e Update asusd unit for selinux 2021-04-15 19:43:09 +12:00
Luke D Jones
bd9bc8bcff anime: services for system sequences 2021-04-14 23:14:57 +12:00
Luke D Jones
8a6d364304 anime: initial system config work 2021-04-12 17:35:04 +12:00
Luke D Jones
64d99a3e05 gfx: partial save and recover of mode change
Properly set and recover to last mode for g-sync laptops

Partial close of #75
2021-04-12 10:49:08 +12:00
Luke D Jones
59f54b76f6 aura: split out all aura related files to rog-aura crate 2021-04-12 10:31:36 +12:00
Luke D Jones
6f36d91281 Begin rog-aura crate 2021-04-12 10:31:36 +12:00
Luke D Jones
e9f1fa01fc index on anime-cli: 0657c6c anime: prep rog-anime for publish, rename *all* AniMe~ to Anime 2021-04-12 10:31:36 +12:00
Luke D Jones
0d3a5d266b Changelog 2021-04-12 10:31:07 +12:00
Luke D Jones
cc28cee8bd anime: fix init 2021-04-11 22:47:21 +12:00
Luke D Jones
6ebf0c2bb2 Update makefile 2021-04-11 20:39:15 +12:00
Luke D Jones
77c658c94e Release 3.4.0 2021-04-11 20:36:31 +12:00
Luke Jones
df64a51372 Merge branch 'fluke/anime-cli' into 'main'
anime: prep rog-anime for publish, rename *all* AniMe~ to Anime

See merge request asus-linux/asusctl!50
2021-04-11 06:54:05 +00:00
Luke D Jones
0657c6cc74 anime: prep rog-anime for publish, rename *all* AniMe~ to Anime 2021-04-11 16:26:52 +12:00
Luke Jones
f116905e85 Merge branch 'fluke/anime-cli' into 'main'
anime: add zbus methods

See merge request asus-linux/asus-nb-ctrl!49
2021-04-10 09:58:56 +00:00
Luke D Jones
e515741efa anime: add zbus methods 2021-04-10 21:54:08 +12:00
Luke Jones
d516abdc92 Merge branch 'fluke/anime-cli' into 'main'
anime: tweak gif animation time types

See merge request asus-linux/asus-nb-ctrl!48
2021-04-09 11:21:35 +00:00
Luke D Jones
ece565de1c anime: tweak gif animation time types 2021-04-09 23:17:50 +12:00
Luke Jones
eb83d1a835 Merge branch 'fluke/anime-cli' into 'main'
anime: CLI and user-daemon work

See merge request asus-linux/asus-nb-ctrl!47
2021-04-09 08:45:06 +00:00
Luke D Jones
7d0f15d738 anime: CLI and user-daemon work 2021-04-09 20:41:25 +12:00
Luke Jones
8010da0891 Merge branch 'fluke/anime-cli' into 'main'
Fluke/anime cli

See merge request asus-linux/asus-nb-ctrl!46
2021-04-07 07:28:35 +00:00
Luke D Jones
aa500c35c4 daemon: revert zbus to 1.9.1 in daemon 2021-04-07 15:05:55 +12:00
Luke D Jones
2af33a0416 daemon: revert zbus to 1.9.1 in daemon 2021-04-07 15:05:26 +12:00
Luke D Jones
9b4ed6eb62 anime: discard frames if specified 2021-04-06 22:03:06 +12:00
Luke D Jones
47c1ca9fe4 anime: gif-image 2021-04-06 21:43:57 +12:00
Luke Jones
3cd624daf0 Merge branch 'fluke/anime-cli' into 'main'
Anime: Tweak the diagonal data to be more correct

See merge request asus-linux/asus-nb-ctrl!45
2021-04-06 02:01:41 +00:00
Luke D Jones
fa16864a3e Tweak the diagonal to be more correct 2021-04-06 13:56:02 +12:00
Luke Jones
bfc31b06d5 Merge branch 'fluke/anime-diag' into 'main'
Fluke/anime diag

See merge request asus-linux/asus-nb-ctrl!44
2021-04-05 09:12:04 +00:00
Luke D Jones
d854f7da1b Prepare for user saving of anime sequences 2021-04-05 21:06:53 +12:00
Luke D Jones
6d746b21a5 Anime gifs 2021-04-05 17:12:00 +12:00
Luke D Jones
226c083a51 Diagonal data structure 2021-04-05 00:02:05 +12:00
Luke Jones
de59d00949 Merge branch 'fluke/gfx-zbus-cleanup' into 'main'
Fluke/gfx zbus cleanup (incorrectly named branch)

Closes #72

See merge request asus-linux/asus-nb-ctrl!42
2021-04-03 08:46:17 +00:00
Luke D Jones
7ff01f12e9 Add extra models to ledmodes
- Configurable anime example
- Gfx power states as enum

Closes #72
2021-04-03 21:42:39 +13:00
Luke Jones
fbc248177a Merge branch 'fluke/gfx-vfio-optional' into 'main'
Put vfio behind config option

See merge request asus-linux/asus-nb-ctrl!43
2021-04-02 23:54:36 +00:00
Luke D Jones
fc3d7653f5 Add missing if condition for vfio 2021-04-03 12:50:13 +13:00
Luke D Jones
2dc70ea6af Put vfio behind config option 2021-04-03 09:59:36 +13:00
Luke D Jones
01345b28a5 Add extra models to ledmodes 2021-03-29 19:36:30 +13:00
Luke Jones
4eeacea832 Merge branch 'fluke/vfio' into 'main'
Bugfix vfio/integrated

See merge request asus-linux/asus-nb-ctrl!41
2021-03-24 23:04:23 +00:00
Luke D Jones
6bf0fdd117 Bugfix vfio/integrated 2021-03-25 11:14:59 +13:00
Luke Jones
7fcde7df17 Merge branch 'fluke/vfio-builtin' into 'main'
Fluke/vfio builtin

See merge request asus-linux/asus-nb-ctrl!40
2021-03-24 06:45:35 +00:00
Luke D Jones
543b0b817f Try remove nouveau 2021-03-24 19:44:40 +13:00
Luke D Jones
5a7d31fdf6 Bugfixes to session handler. Add extra profile commands
- Better handling of session tracking
- List all profile data
- Get active profile name
- Get active profile data
2021-03-24 16:30:13 +13:00
Luke D Jones
301c532b65 Formatting 2021-03-23 13:45:57 +13:00
Luke D Jones
df7ae4d014 Fix: non-rgb keyboard backlight control 2021-03-23 13:44:07 +13:00
Luke D Jones
96ceef1bdb Prep v3.2.1 2021-03-22 16:45:05 +13:00
Luke Jones
bc72b93625 Merge branch 'fluke/led-work' into 'main'
Fluke/led work

See merge request asus-linux/asus-nb-ctrl!39
2021-03-22 03:43:05 +00:00
Luke D Jones
03b338bdfa Strongly type the Led brightness 2021-03-22 16:36:10 +13:00
Luke D Jones
7a51cd1c70 Cleaned up 2021-03-22 11:03:56 +13:00
Luke D Jones
0449a4b06b Initial cleanup 2021-03-22 10:24:28 +13:00
Luke D Jones
bc46fa2b1e Prep new release 2021-03-21 21:52:30 +13:00
Luke Jones
759ddeb270 Merge branch 'fluke/vm-mode' into 'main'
Fluke/vm mode

See merge request asus-linux/asus-nb-ctrl!38
2021-03-21 08:50:23 +00:00
Luke D Jones
538e111e78 VFIO mode enabled 2021-03-21 21:50:03 +13:00
Luke D Jones
45ab568f7a Changelog update 2021-03-20 21:41:22 +13:00
Luke Jones
b32089843a Merge branch 'profile_remove' into 'main'
Added --remove ability to profile subcommand

See merge request asus-linux/asus-nb-ctrl!37
2021-03-20 08:40:04 +00:00
Luke Jones
d960aacf4f Merge branch 'fluke/optimising' into 'main'
Massive refactor of led control

Closes #53 and #63

See merge request asus-linux/asus-nb-ctrl!36
2021-03-20 08:30:39 +00:00
Tony Dwire
1c48ab227d Added --remove ability to profile subcommand 2021-03-19 22:24:59 -05:00
Luke D Jones
6528ec95c2 Massive refactor of led control
- Write brightness to kernel LED class path

Closes #63, #53
2021-03-20 11:58:47 +13:00
Luke Jones
53ee6015d0 Merge branch 'main' into 'main'
Added --list for profiles

See merge request asus-linux/asus-nb-ctrl!35
2021-03-17 01:50:16 +00:00
Tony
ad150903af Forwarded error from ProfileProxy::profile_names instead of 'expecting' there. Handled error up in main by logging. Reorganized code in ctrl_fan_cpu to keep consistent code structure 2021-03-17 01:50:16 +00:00
Luke Jones
c29afaf751 Merge branch 'fluke/optimising' into 'main'
Fluke/optimising

See merge request asus-linux/asus-nb-ctrl!34
2021-03-16 08:12:01 +00:00
Luke D Jones
cec4016862 Refactored gfx switch session monitor 2021-03-16 21:09:17 +13:00
Luke Jones
c697d94a00 Merge branch 'main' into 'main'
added fish completion

See merge request asus-linux/asus-nb-ctrl!32
2021-03-14 08:30:39 +00:00
Luke D Jones
35438e2e77 Move logind-zbus to own crate and publish 2021-03-13 22:07:31 +13:00
alenpaul2001
716b524d70 updated Makefile 2021-03-13 01:01:22 +05:30
alenpaul2001
cffd5672b2 added fish completion 2021-03-13 00:40:46 +05:30
Luke D Jones
82bb032336 Bump crate deps 2021-03-12 22:09:40 +13:00
Luke D Jones
ae4f7f9949 Buildup of logind dbus methods 2021-03-12 22:00:31 +13:00
Luke D Jones
875ff6d354 Begin implementing logind dbus crate 2021-03-12 16:55:52 +13:00
Luke D Jones
842fa48fac Refresh sessions list every 3rd active check 2021-03-12 15:04:37 +13:00
Luke D Jones
8a63dce85f Bugfix: destroy the deref clone stackoverflow 2021-03-11 23:42:38 +13:00
Luke Jones
01386599f4 Merge branch 'fluke/hotfixing' into 'main'
Graphics switching now waits for user sessions to end

See merge request asus-linux/asus-nb-ctrl!31
2021-03-11 08:17:41 +00:00
Luke D Jones
4310b4b742 Graphics switching now waits for user sessions to end 2021-03-11 21:13:41 +13:00
Luke D Jones
89f4dd6ec4 Prep release 2021-03-11 12:32:34 +13:00
Luke Jones
85e0b79fb9 Merge branch 'fluke/testing-gfx-switch' into 'main'
More verbose and thorough checks for gfx switching

See merge request asus-linux/asus-nb-ctrl!30
2021-03-10 23:28:02 +00:00
Luke D Jones
fba5f26f7e More verbose and thorough checks for gfx switching
- Small fixes
- Cleanup bios help
- g-sync warnings on toggling
2021-03-11 12:24:01 +13:00
Luke D Jones
90b0fc434d Hotfix: graphics help display 2021-03-10 21:23:35 +13:00
Luke D Jones
6743d5bc78 Add display-manager restart check 2021-03-10 18:42:44 +13:00
Luke D Jones
def0259d24 Bump version 2021-03-10 16:47:22 +13:00
Luke D Jones
a678f54f59 :sadface: 2021-03-10 16:45:06 +13:00
Luke D Jones
ebe7e61355 Slightly change how module load error is reported 2021-03-10 16:30:42 +13:00
Luke D Jones
bda58c9695 Trial of logging for gfx switch 2021-03-10 16:21:53 +13:00
Luke D Jones
e335133bf8 refactor help again 2021-03-10 16:17:22 +13:00
Luke D Jones
47432524e1 Further improve CLI feedback 2021-03-10 16:01:04 +13:00
Luke D Jones
707b3bcc2d Notify on manually select profile 2021-03-10 15:24:24 +13:00
Luke D Jones
60014b8a40 Customise initial help for laptop 2021-03-10 14:43:48 +13:00
Luke D Jones
2e4ce27f6b Hotfix: try to handle module remove gracefully
Try to handle module remove more gracefully if in-use when the
display manager is shutting down
2021-03-10 14:07:08 +13:00
Luke D Jones
b8384c55c3 Bump changelog version 2021-03-10 11:21:09 +13:00
Luke D Jones
dfe1f02101 Hotfix: Catch some edge-cases exposed on fedora 34 2021-03-10 11:20:19 +13:00
Luke D Jones
7c2fb0be81 Hotfix: Nvidia module handling improved 2021-03-10 10:15:59 +13:00
Luke D Jones
b05f680650 Test and create /etc/X11/xorg.conf.d/ if not exist 2021-03-10 09:20:59 +13:00
Luke D Jones
2a9a436f9c Add nvidia-uvm to module list 2021-03-10 07:34:03 +13:00
Luke D Jones
0d6faf3fda Mark as new release 2021-03-09 17:23:19 +13:00
Luke Jones
aede000218 Merge branch 'fluke/rebootless-gfx-switch' into 'main'
Fluke/rebootless gfx switch

See merge request asus-linux/asus-nb-ctrl!29
2021-03-09 04:20:29 +00:00
Luke D Jones
176ab0a639 Rebootless graphics switching
This changes out how the current graphics switching works, enabling
asusd to stop/start the display-manager to enable/disable PCI devices
and add/remove drivers as required.

All existing graphics modes and commands still work as normal.

G-Sync enable is now only through the bios setting, and on reboot
will set all relevant settings to Nvidia mode.
2021-03-09 16:45:43 +13:00
Luke D Jones
4efb2caa56 GU502LU led-modes 2021-03-07 21:48:44 +13:00
Luke D Jones
6f81f86483 Version bump 2021-02-22 11:48:08 +13:00
Luke D Jones
b64b8a38e4 cargo update, update udev rules 2021-02-22 11:34:47 +13:00
Luke Jones
ff56170ac5 Merge branch 'main' into 'main'
added G531GD stock_led_modes

See merge request asus-linux/asus-nb-ctrl!28
2021-02-21 08:47:51 +00:00
alenpaul2001
733f1f827e added G531GD stock_led_modes 2021-02-21 13:00:04 +05:30
Luke Jones
ac903a05da Merge branch 'donate-button' into 'main'
Test donate button

See merge request asus-linux/asus-nb-ctrl!27
2021-02-19 21:39:49 +00:00
Luke D Jones
838e6f789b Test donate button 2021-02-20 10:36:28 +13:00
Luke D Jones
d462393e8b Add 'users' group to dbus config 2021-02-20 10:15:38 +13:00
Luke D Jones
e98cf8d50b Add 0x19b6 to supported keyb list 2021-02-19 19:32:14 +13:00
Luke
eb173fc9dc CI pipe fix 2021-02-14 22:45:37 +13:00
Luke
50756046cf Cleanup fan+cpu+config 2021-02-07 00:25:40 +13:00
Luke
629bdc2213 Large code cleanup 2021-02-06 23:18:01 +13:00
Luke
39bbe33831 Further refinement 2021-02-06 08:53:02 +13:00
Luke
00bd556d7a Initial refactor 2021-02-06 08:53:02 +13:00
Luke
12061ea9df Fix 'Supported' dbus method 2021-02-06 08:52:35 +13:00
Luke Jones
580ed72e73 Merge branch 'asere/anime_compatibility' into 'next'
Adding asusd rules to restart asusd service when anime is detected too late

See merge request asus-linux/asus-nb-ctrl!18
2021-02-04 00:31:04 +00:00
Asere
c01f0892a5 adding asusd rules to restart asusd service when anime is detected too late 2021-02-03 16:44:44 +01:00
Luke Jones
0fed34b12e Merge branch 'fluke/crate-refactor' into 'next'
split out types, dbus

See merge request asus-linux/asus-nb-ctrl!21
2021-02-03 10:07:10 +00:00
Luke
0af68baf7b split out types, dbus 2021-02-03 23:06:54 +13:00
Luke Jones
161e3c4d3b Merge branch 'fluke/zbus-migrate' into 'next'
Migrate to use zbus for all dbus requirements

See merge request asus-linux/asus-nb-ctrl!20
2021-02-03 03:47:16 +00:00
Luke
4720af2cb8 Migrate to use zbus for all dbus requirements 2021-02-03 16:46:48 +13:00
Luke Jones
06d37aa009 Merge branch 'fluke/1854-device' into 'next'
Try to fix up multizone modes

See merge request asus-linux/asus-nb-ctrl!19
2021-02-01 22:09:17 +00:00
Luke
c6fa860b2e Try to fix up multizone modes
- Write set+apply after each array in multizone
- Remove misc bad logic
- Use same code path as 0x1866 device to configure led support
- Remove duplicate code
- Set correct speeds for multizone
2021-02-02 11:08:45 +13:00
Luke
4fe9ab70e5 Merge branch 'fluke/1854-device' into next 2021-01-31 10:00:48 +13:00
Luke
920e4e86f5 Trial fix for 1854 2021-01-31 10:00:06 +13:00
Luke
720dc0c177 v2.2.2 prep 2021-01-31 09:59:24 +13:00
Luke Jones
b3a555cab9 Merge branch 'fluke/asus_bios_settings' into 'next'
Bugfixes and improvements

Closes #48

See merge request asus-linux/asus-nb-ctrl!17
2021-01-27 01:16:39 +00:00
Luke
cf13b4f71b Bugfixes and improvements
- fix CLI feedback for reboot/restartx. Update readme
- dracut force driver include for nvidia dedicated
- change fan-mode CLI tag

Closes #48
2021-01-27 14:13:02 +13:00
Luke Jones
cd0b9fe350 Merge branch 'fluke/asus_bios_settings' into 'next'
Fluke/asus bios settings

See merge request asus-linux/asus-nb-ctrl!15
2021-01-26 08:08:13 +00:00
Luke
82900f4645 CLI args for bios. Cleanup and improve
- dbus method for 'supported modes'
- add dedicated gfx safety
- bring ctrl-gfx back in to main control for better integration
- safely upgrade config files
2021-01-26 21:07:19 +13:00
Luke
703bba9ffd Correct changelog 2021-01-10 22:34:45 +13:00
Luke Jones
73706154a4 Merge branch 'fluke/fixes' into 'next'
Fixes

See merge request asus-linux/asus-nb-ctrl!14
2021-01-10 09:31:46 +00:00
Luke
c9b2a0c777 Fixes
- Adjust gfx controller to assume that the graphics driver is loaded if the
  mode is set for nvidia/hybrid
- Small code adjustments for error handling
2021-01-10 22:27:56 +13:00
Luke
54cc51fe5d Minor update to deps 2021-01-09 13:48:13 +13:00
Luke
81645d0777 Update deps and fmt 2021-01-09 13:42:46 +13:00
Luke Jones
d61c180ee5 Update discord link 2020-12-20 21:21:53 +00:00
Luke Jones
a668800fd9 Merge branch 'asere/anime_better_options' into 'next'
Better anime options & gumdrop error Display

See merge request asus-linux/asus-nb-ctrl!12
2020-12-20 21:18:51 +00:00
Asere
3bdc11c994 Better anime options & gumdrop error Display 2020-11-25 18:37:36 +01:00
Luke Jones
b496139063 Merge branch 'StaticRocket-next-patch-05672' into 'next'
Update paths and variables to follow GNU Make standards

See merge request asus-linux/asus-nb-ctrl!13
2020-11-08 00:17:44 +00:00
Randolph Sapp
607483629a Don't rebuild during install
Rebuild during all
2020-11-08 00:17:44 +00:00
Luke D Jones
5c8d138cef Update readme 2020-10-25 20:37:53 +13:00
Luke D Jones
e3db1f7c4c Add notification dbus signal for aura next/prev 2020-10-25 19:34:40 +13:00
Luke D Jones
de3b803f14 Add DBUS methods to toggle next/previous aura mode 2020-10-25 15:49:14 +13:00
Luke D Jones
0558f919c4 Add DBUS method to toggle to next profile 2020-10-25 15:02:35 +13:00
Luke Jones
68ea73c847 Merge branch 'asere/anime_on_off' into 'next'
AniMe: adding --on and --off options to turn on/off (and accept/reject write requests)

See merge request asus-linux/asus-nb-ctrl!11
2020-10-25 01:14:12 +00:00
Luke Jones
96ddb7132d Merge branch 'asere/show_keyboard_brightness' into 'next'
Improving user experience by showing current keyboard led brightness

See merge request asus-linux/asus-nb-ctrl!10
2020-10-25 01:12:21 +00:00
Asere
d36ac44603 updating option "-k" to show current brightness: asusctl -k 2020-10-23 02:00:08 +02:00
Asere
5d06c87943 AniMe: adding --on and --off options to turn on/off (and accept/reject write requests) 2020-10-22 14:09:05 +02:00
Luke D Jones
588e3c0102 Panic if config file is bad 2020-10-22 08:28:12 +13:00
Luke D Jones
6ce32c1cab Fix one super silly bug
closes #30
2020-10-22 08:16:00 +13:00
Luke Jones
a23c51e5db Adding Anime commands to asusctl 2020-10-11 22:46:06 +00:00
Asere
3845071ba3 adding Anime feature: led brightness command to asusctl, and updating dbus client 2020-10-12 00:11:26 +02:00
Luke Jones
a48b3634bf Merge branch 'next' into 'next'
Add some basic zsh completions for asusctl

See merge request asus-linux/asus-nb-ctrl!8
2020-10-05 00:38:34 +00:00
Luke Jones
806882b2e9 Merge branch 'next' into 'next'
fixed fan presets for profiles

See merge request asus-linux/asus-nb-ctrl!7
2020-10-05 00:37:43 +00:00
Luke D Jones
9ac3c46fe6 Actually enable/disable gfx switch control 2020-10-05 09:32:46 +13:00
Luke D Jones
6817a1c027 Bump dbus autogen 2020-10-05 09:31:07 +13:00
Dylan Jones
cf2be1b12b Add some basic zsh completions for asusctl 2020-09-30 13:28:05 -04:00
Luke D Jones
9ffeb19c8c Bump version 2020-09-29 21:30:23 +13:00
Cuong
a7f6e8bd24 fixed fan presets for profiles 2020-09-28 10:04:57 +00:00
Luke Jones
f61f62c219 Merge branch 'feature/dbus-profile-name' into 'next'
 Add ActiveProfileName() dbus method returning name of current profile

See merge request asus-linux/asus-nb-ctrl!5
2020-09-26 08:50:03 +00:00
Andreas Streichardt
bb70fd7b71 Add ActiveProfileName() dbus method returning name of current profile 2020-09-26 09:05:50 +02:00
Luke D Jones
b80c860b7a Fix args to systemctl for reboot 2020-09-25 21:05:47 +12:00
Luke D Jones
3c7544f034 Explicitly state arch is not supported 2020-09-25 14:14:21 +12:00
Luke D Jones
6746c2b654 Update changelog 2020-09-24 09:04:49 +12:00
Luke D Jones
8d59f89438 Add verbose error for LED node missing 2020-09-24 08:18:10 +12:00
Luke D Jones
5753160e91 Don't throw away do_task error, log it 2020-09-24 08:10:05 +12:00
Luke D Jones
622cd9d943 Fix timeout for GFX switching 2020-09-24 08:00:37 +12:00
Luke D Jones
2daa7f0811 Git internal version from crate version 2020-09-23 22:12:47 +12:00
Luke D Jones
05c53df0ed Better description of config panic 2020-09-23 21:24:25 +12:00
Luke D Jones
a7419cbc4c Remove many unwraps or change to maps 2020-09-23 20:47:33 +12:00
Luke D Jones
67ad38a7e6 Ditch the gsync line in screen settings file. Oops
- Add force option to `systemctl reboot`. Be careful.
2020-09-23 16:51:46 +12:00
Luke Jones
e572ae2c62 Update Makefile 2020-09-23 02:32:25 +00:00
Luke Jones
24962eedc1 Merge branch 'testing' into 'next'
Bugfixes and improvements

Closes #11

See merge request asus-linux/asus-nb-ctrl!4
2020-09-23 01:05:15 +00:00
Luke D Jones
368d279ca5 Add "info" output for gfx driver check 2020-09-23 12:59:15 +12:00
Luke D Jones
9e4cc329ed Add "info" output for gfx driver check 2020-09-22 09:54:37 +12:00
Luke D Jones
d4702a166a Support Zephyrus M GU502GV
closes #11
2020-09-22 09:47:20 +12:00
Luke D Jones
925c709097 Minor CLI output correction 2020-09-21 20:55:47 +12:00
Luke D Jones
411788f72c Remove triple-buffer line 2020-09-21 20:44:31 +12:00
Luke D Jones
4e4ea0035e Add missing gfx dbus signal 2020-09-21 20:41:28 +12:00
347 changed files with 52836 additions and 6959 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

6
.cargo-husky/hooks/pre-commit Executable file
View File

@@ -0,0 +1,6 @@
#!/bin/sh
set -e
echo '+cargo fmt --all -- --check'
cargo fmt --all -- --check
git add -u

10
.cargo-husky/hooks/pre-push Executable file
View File

@@ -0,0 +1,10 @@
#!/bin/sh
set -e
echo '+cargo fmt --all -- --check'
cargo fmt --all -- --check
echo '+cargo clippy --all -- -D warnings'
cargo clippy --all -- -D warnings
echo '+cargo cranky'
cargo cranky

23
.editorconfig Normal file
View File

@@ -0,0 +1,23 @@
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
[*.rs]
indent_size = 4
[tests/**/*.rs]
charset = utf-8
end_of_line = unset
indent_size = unset
indent_style = unset
trim_trailing_whitespace = unset
insert_final_newline = unset

22
.gitignore vendored
View File

@@ -1,2 +1,22 @@
/target
vendor.tar.xz
vendor.tar.xz
cargo-config
.idea
vendor
vendor-*
vendor_*
.vscode-ctags
.vscode
.~lock.*
*.ods#
*.patch
# gnome extension
node-modules
bindings/ts/*.d.ts
bindings/ts/*.js.map
desktop-extensions/gnome*/dist
desktop-extensions/gnome*/@types/gir-generated
desktop-extensions/gnome*/node_modules
desktop-extensions/gnome*/schemas/gschemas.compiled
desktop-extensions/gnome*/*.zip

View File

@@ -1,26 +1,84 @@
image: rustdocker/rust:stable
image: rust:latest
.rust_cache: &rust_cache
cache:
# key: $CI_COMMIT_REF_SLUG
paths:
# Don't include `incremental` to save space
# Debug
- 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:
- apt-get update -qq && apt-get install -y -qq libdbus-1-dev libclang-dev libudev-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:
- test
- build
- format
- check
- test
- release
- deploy
format:
except:
- tags
<<: *rust_cache
script:
- rustup component add rustfmt || true
- cargo fmt --check
check:
except:
- tags
<<: *rust_cache
script:
- rustup component add clippy || true
- cargo check --locked --workspace
# deny currently catches too much
#- cargo install cargo-deny && cargo deny
- cargo install cargo-cranky && cargo cranky
test:
except:
- tags
<<: *rust_cache
script:
- cargo check #+nightly check --features "clippy"
- mkdir -p .git/hooks > /dev/null
- cargo test --locked --all
build:
release:
only:
- next
- tags
<<: *rust_cache
script:
- make && make vendor
- cargo install cargo-vendor-filterer
- make FROZEN=1 && make vendor
artifacts:
paths:
- vendor_asus-nb-ctrl_*.tar.xz
- cargo-config
- vendor_asusctl*.tar.xz
- cargo-config
pages:
stage: deploy
only:
- tags
<<: *rust_cache
script:
- cargo doc --locked --document-private-items --no-deps --workspace
- rm -rf public
- mkdir public
- cp -R target/doc/* public
- cp extra/index.html public
artifacts:
paths:
- public
variables:
GIT_SUBMODULE_STRATEGY: normal

View File

@@ -0,0 +1,32 @@
## Issue description
(** I can not support distros which are outdated by default. This includes Ubuntu at least 50% of the time, and definitely includes Mint. **)
(Summarize the bug encountered)
## Steps to reproduce
(How can the issue be reproduced)
## What is the current bug behavior?
(What actually happens)
## What is the expected correct behavior?
(What you should see instead)
## Relevant logs and/or screenshots
(run `journalctl -b -u asusd > ~/asusd.log` and attach `~/asusd.log`)
(Paste any relevant logs - use code blocks (```) to format console output, logs, and code, as
it's very hard to read otherwise.)
## System details
- Distro:
- Kernel: (`uname -r`)
- Desktop:
- Xorg or wayland: ??
/label ~bug ~reproducable ~needs-investigation

File diff suppressed because it is too large Load Diff

7074
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,16 +1,97 @@
[workspace.package]
version = "6.1.17"
rust-version = "1.82"
license = "MPL-2.0"
readme = "README.md"
authors = ["Luke <luke@ljones.dev>"]
repository = "https://gitlab.com/asus-linux/asusctl"
homepage = "https://gitlab.com/asus-linux/asusctl"
description = "Laptop feature control for ASUS ROG laptops and others"
edition = "2021"
[workspace]
members = ["asus-notify", "asus-nb-ctrl", "asus-nb", "ctrl-gfx"]
resolver = "2"
members = [
"asusctl",
"asusd",
"asusd-user",
"config-traits",
"dmi-id",
"rog-platform",
"rog-dbus",
"rog-anime",
"rog-aura",
"rog-profiles",
"rog-control-center",
"rog-slash",
"simulators",
"rog-scsi",
]
default-members = ["asusctl", "asusd", "asusd-user", "rog-control-center"]
[workspace.dependencies]
tokio = { version = "^1.39.0", default-features = false, features = [
"macros",
"sync",
"time",
"rt",
"rt-multi-thread",
] }
concat-idents = "^1.1"
dirs = "^4.0"
smol = "^2.0"
mio = "0.8.11"
futures-util = "0.3.31"
zbus = "5.5.0"
logind-zbus = { version = "5.2.0" } #, default-features = false, features = ["non_blocking"] }
serde = { version = "^1.0", features = ["serde_derive"] }
ron = "*"
log = "^0.4"
env_logger = "^0.10.0"
glam = { version = "^0.22", features = ["serde"] }
gumdrop = "^0.8"
udev = { version = "^0.8", features = ["mio"] }
rusb = "^0.9"
inotify = "^0.10.0"
png_pong = "^0.8"
pix = "^0.13"
tinybmp = "^0.4.0"
gif = "^0.12.0"
versions = "6.2"
notify-rust = { version = "4.11.5", features = ["z", "async"] }
sg = { git = "https://github.com/flukejones/sg-rs.git" }
[profile.release]
lto = true
# thin = 57s, asusd = 9.0M
# fat = 72s, asusd = 6.4M
lto = "fat"
debug = false
opt-level = 3
panic = "abort"
# codegen-units = 1
[profile.dev]
debug = false
opt-level = 1
# codegen-units = 1
[profile.dev.package."*"]
opt-level = 1
# codegen-units = 1
[profile.bench]
debug = false
opt-level = 3
[workspace.dependencies.cargo-husky]
version = "1"
default-features = false
features = ["user-hooks"]

121
Cranky.toml Normal file
View File

@@ -0,0 +1,121 @@
# https://github.com/ericseppanen/cargo-cranky
# cargo install cargo-cranky && cargo cranky
error = [
"clippy::all",
"clippy::await_holding_lock",
"clippy::bool_to_int_with_if",
"clippy::char_lit_as_u8",
"clippy::checked_conversions",
"clippy::dbg_macro",
"clippy::debug_assert_with_mut_call",
"clippy::disallowed_methods",
"clippy::disallowed_script_idents",
"clippy::doc_link_with_quotes",
"clippy::doc_markdown",
"clippy::empty_enum",
"clippy::enum_glob_use",
"clippy::equatable_if_let",
"clippy::exit",
"clippy::expl_impl_clone_on_copy",
"clippy::explicit_deref_methods",
"clippy::explicit_into_iter_loop",
"clippy::explicit_iter_loop",
"clippy::fallible_impl_from",
"clippy::filter_map_next",
"clippy::flat_map_option",
"clippy::float_cmp_const",
"clippy::fn_params_excessive_bools",
"clippy::fn_to_numeric_cast_any",
"clippy::from_iter_instead_of_collect",
"clippy::if_let_mutex",
"clippy::implicit_clone",
"clippy::imprecise_flops",
"clippy::index_refutable_slice",
"clippy::inefficient_to_string",
"clippy::invalid_upcast_comparisons",
"clippy::iter_not_returning_iterator",
"clippy::iter_on_empty_collections",
"clippy::iter_on_single_items",
"clippy::large_digit_groups",
"clippy::large_stack_arrays",
"clippy::large_types_passed_by_value",
"clippy::let_unit_value",
"clippy::linkedlist",
"clippy::lossy_float_literal",
"clippy::macro_use_imports",
"clippy::manual_assert",
"clippy::manual_instant_elapsed",
"clippy::manual_ok_or",
"clippy::manual_string_new",
"clippy::map_err_ignore",
"clippy::map_flatten",
"clippy::map_unwrap_or",
"clippy::match_on_vec_items",
"clippy::match_same_arms",
"clippy::match_wild_err_arm",
"clippy::match_wildcard_for_single_variants",
"clippy::mem_forget",
"clippy::mismatched_target_os",
"clippy::mismatching_type_param_order",
"clippy::missing_enforced_import_renames",
# "clippy::missing_errors_doc",
"clippy::missing_safety_doc",
"clippy::mut_mut",
"clippy::mutex_integer",
"clippy::needless_borrow",
"clippy::needless_continue",
"clippy::needless_for_each",
"clippy::needless_pass_by_value",
"clippy::negative_feature_names",
"clippy::nonstandard_macro_braces",
"clippy::option_option",
"clippy::path_buf_push_overwrite",
"clippy::ptr_as_ptr",
"clippy::rc_mutex",
"clippy::ref_option_ref",
"clippy::rest_pat_in_fully_bound_structs",
"clippy::same_functions_in_if_condition",
"clippy::semicolon_if_nothing_returned",
"clippy::single_match_else",
"clippy::str_to_string",
"clippy::string_add_assign",
"clippy::string_add",
"clippy::string_lit_as_bytes",
"clippy::string_to_string",
"clippy::todo",
"clippy::trailing_empty_array",
"clippy::trait_duplication_in_bounds",
"clippy::unimplemented",
"clippy::unnecessary_wraps",
"clippy::unnested_or_patterns",
"clippy::unused_peekable",
"clippy::unused_rounding",
# "clippy::unused_self",
"clippy::useless_transmute",
"clippy::verbose_file_reads",
"clippy::zero_sized_map_values",
"elided_lifetimes_in_paths",
"future_incompatible",
"nonstandard_style",
"rust_2018_idioms",
"rust_2021_prelude_collisions",
"rustdoc::missing_crate_level_docs",
"semicolon_in_expressions_from_macros",
"trivial_numeric_casts",
"unused_extern_crates",
"unused_import_braces",
"unused_lifetimes",
]
allow = [
# TODO(emilk): enable more lints
"clippy::cloned_instead_of_copied",
"clippy::derive_partial_eq_without_eq",
"clippy::type_complexity",
"clippy::undocumented_unsafe_blocks",
"trivial_casts",
"unsafe_op_in_unsafe_fn", # `unsafe_op_in_unsafe_fn` may become the default in future Rust versions: https://github.com/rust-lang/rust/issues/71668
"unused_qualifications",
]

446
MANUAL.md Normal file
View File

@@ -0,0 +1,446 @@
# asusctrl manual
**NOTE:** this manual is in need of an update in some places. If you find issues please file issue reports.
`asusd` is a utility for Linux to control many aspects of various ASUS laptops
but can also be used with non-asus laptops with reduced features.
## Programs Available
- `asusd`: The main system daemon. It is autostarted by a udev rule and systemd unit.
- `asusd-user`: The user level daemon. Currently will run an anime sequence, with RGB keyboard sequences soon.
- `asusctl`: The CLI for interacting with the system daemon
## `asusd`
`asusd` is the main system-level daemon which will control/load/save various settings in a safe way for the user, along with exposing a _safe_ dbus interface for these interactions. This section covers only the daemon plus the various configuration file options.
The functionality that `asusd` exposes is:
- anime control
- led keyboard control (aura)
- charge limiting
- bios/efivar control
- power profile switching
- fan curves (if supported, this is auto-detected)
each of these will be detailed in sections.
### AniMe control
Controller for the fancy AniMe matrix display on the lid of some machines. This controller is a work in progress.
#### Config options
If you have an AniMe device a few system-level config options are enabled for you in `/etc/asusd/anime.conf`;
1. `"system": [],`: currently unused, is intended to be a default continuous sequence in future versions
2. `"boot": [],`: a sequence that plays on system boot (when asusd is loaded)
3. `"wake": [],`: a sequence that plays when waking from suspend
4. `"shutdown": [],`: a sequence that plays when shutdown begins
5. `"brightness": <FLOAT>`: global brightness control, where `<FLOAT> is 0.0-1.0
Some default examples are provided but are minimal. The full range of configuration options will be covered in another section of this manual.
### Led keyboard control
The LED controller (e.g, aura) enables setting many of the factory modes available if a laptop supports them. It also enables per-key RGB settings but this is a WIP and will likely be similar to how AniMe sequences can be created.
#### Supported laptops
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
Almost all modern ASUS laptops have charging limit control now. This can be controlled in `/etc/asusd/asusd.conf`.
```json
"bat_charge_limit": 80,
```
where the number is a percentage.
### Bios control
Some options that you find in Armory Crate are available under this controller, so far there is:
- POST sound: this is the sound you hear on bios boot post
- GPU MUX: this controls if the dGPU is the _only_ GPU, making it the main GPU and disabling the iGPU
These options are not written to the config file as they are stored in efivars. The only way to change these is to use the exposed safe dbus methods, or use the `asusctl` CLI tool.
### Profiles
asusctl can support setting a power profile via platform_profile drivers. This requires [power-profiles-daemon](https://gitlab.freedesktop.org/hadess/power-profiles-daemon) v0.10.0 minimum. It also requires the kernel patch for platform_profile support to be applied form [here](https://lkml.org/lkml/2021/8/18/1022) - this patch is merged to 5.15 kernel upstream.
A common use of asusctl is to bind the `fn+f5` (fan) key to `asusctl profile -n` to cycle through the 3 profiles:
1. Balanced
2. Performance
3. Quiet
#### Fan curves
Fan curve support requires a laptop that supports it (this is detected automatically) and the kernel patch from [here](https://lkml.org/lkml/2021/10/23/250) which is accepted for the 5.17 kernel release .
The fan curve format can be of varying formats:
- `30c:0%,40c:5%,50c:10%,60c:20%,70c:35%,80c:55%,90c:65%,100c:65%"`
- `30:0,40:5,50:10,60:20,70:35,80:55,90:65,100:65"`
- `30 0,40 5,50 10,60 20,70 35,80 55,90 65,100 65"`
- `30 0 40 5 50 10 60 20 70 35 80 55 90 65 100 65"`
the order must always be the same "temperature:percentage", lowest from left to rigth being highest.
The config file is located at `/etc/asusd/profile.conf` and is self-descriptive. On first run it is populated with the system EC defaults.
### Support controller
There is one more controller; the support controller. The sole pupose of this controller is to querie all the other controllers for information about their support level for the host laptop. Returns a json string.
## asusd-user
`asusd-user` is a usermode daemon. The intended purpose is to provide a method for users to run there own custom per-key keyboard effects and modes, AniMe sequences, and possibly their own profiles - all without overwriting the _base_ system config. As such some parts of the system daemon will migrate to the user daemon over time with the expectation that the Linux system runs both.
As of now only AniMe is active in this with configuration in `~/.config/rog/`. On first run defaults are created that are intended to work as examples.
The main config is `~/.config/rog/rog-user.cfg`
#### Config options: Aura, per-key and zoned
I'm unsure of how many laptops this works on, so please try it.
`led_type: Key` works only on actual per-key RGB keyboards.
`led_type: Zone` works on zoned laptops.
`led_type: Zone` set to `None` works on zoned ROG laptops, unzoned ROG laptops, and TUF laptops (and yes this does mean an audio EQ can be done now).
`~/.config/rog/rog-user.cfg` contains a setting `"active_aura": "<FILENAME>"` where `<FILENAME>` is the name of the Aura config to use, located in the same directory and without the file postfix, e.g, `"active_anime": "aura-default"`
An Aura config itself is a file with contents:
```ron
(
name: "aura-default",
aura: (
effects: [
Breathe((
led: W,
start_colour1: (255, 0, 20),
start_colour2: (20, 255, 0),
speed: Low,
)),
Breathe((
led: A,
start_colour1: (255, 0, 20),
start_colour2: (20, 255, 0),
speed: Low,
)),
Breathe((
led: S,
start_colour1: (255, 0, 20),
start_colour2: (20, 255, 0),
speed: Low,
)),
Breathe((
led: D,
start_colour1: (255, 0, 20),
start_colour2: (20, 255, 0),
speed: Low,
)),
Breathe((
led: F,
start_colour1: (255, 0, 0),
start_colour2: (255, 0, 0),
speed: High,
)),
Static((
led: RCtrl,
colour: (0, 0, 255),
)),
Static((
led: LCtrl,
colour: (0, 0, 255),
)),
Static((
led: Esc,
colour: (0, 0, 255),
)),
DoomFlicker((
led: N9,
start_colour: (0, 0, 255),
max_percentage: 80,
min_percentage: 40,
)),
],
zoned: false,
),
)
```
If your laptop supports multizone, `"led"` can also be `"Zone": <one of the following>`
- `SingleZone` // Keyboards with only one zone
- `ZonedKbLeft` // keyboard left
- `ZonedKbLeftMid` // keyboard left-middle
- `ZonedKbRightMid` // etc
- `ZonedKbRight`
- `LightbarRight`
- `LightbarRightCorner`
- `LightbarRightBottom`
- `LightbarLeftBottom`
- `LightbarLeftCorner`
- `LightbarLeft`
Single zone example:
```ron
(
name: "aura-default",
aura: (
effects: [
DoomFlicker((
led: SingleZone,
start_colour: (200, 40, 5),
max_percentage: 80,
min_percentage: 40,
)),
],
zoned: true,
),
)
```
At the moment there are only three effects available as shown in the example. More will come in the future
but this may take me some time.
#### Config options: AniMe
`~/.config/rog/rog-user.cfg` contains a setting `"active_anime": "<FILENAME>"` where `<FILENAME>` is the name of the AniMe config to use, located in the same directory and without the file postfix, e.g, `"active_anime": "anime-doom"`
An AniMe config itself is a file with contents:
```json
{
"name": "<FILENAME>",
"anime": []
}
```
`<FILENAME>` is used as a reference internally. `"anime": []` is an array of sequences (WIP).
##### "anime" array options
Each object in the array can be one of:
1. AsusAnimation
2. ImageAnimation
3. Image
4. Pause
##### AsusAnimation
`AsusAnimation` is specifically for running the gif files that Armory Crate comes with. `asusctl` includes all of these in `/usr/share/asusd/anime/asus/`
```json
"AsusAnimation": {
"file": "<FILE_PATH>",
"time": <TIME>,
"brightness": <FLOAT>
}
```
##### AsusImage
Virtually the same as `AsusAnimation` but for png files, typically created in the same "slanted" style using a template (`diagonal-template.png`) as the ASUS gifs for pixel perfection.
```json
"AsusImage": {
"file": "<FILE_PATH>",
"time": <TIME>,
"brightness": <FLOAT>
}
```
##### ImageAnimation
`ImageAnimation` can play _any_ gif of any size.
```json
"ImageAnimation": {
"file": "<FILE_PATH>",
"scale": <FLOAT>,
"angle": <FLOAT>,
"translation": [
<FLOAT>,
<FLOAT>
],
"time": <TIME>,
"brightness": <FLOAT>
}
},
```
##### Image
`Image` currently requires 8bit greyscale png. It will be able to use most in future.
```json
{
"Image": {
"file": "<FILE_PATH>",
"scale": <FLOAT>,
"angle": <FLOAT>,
"translation": [
<FLOAT>,
<FLOAT>
],
"time": <TIME>,
"brightness": <FLOAT>
}
},
```
##### Pause
A `Pause` is handy for after an `Image` to hold the `Image` on the AniMe for a period.
```json
{
"Pause": {
"secs": <INT>,
"nanos": <INT>
}
},
```
##### Options for objects
**<FILE_PATH>**
Must be full path: `"/usr/share/asusd/anime/asus/gaming/Controller.gif"` or `/home/luke/Downloads/random.gif`.
**<FLOAT>**
A number from 0.0-1.0.
- `brightness`: If it is brightness it is combined with the system daemon global brightness
- `scale`: 1.0 is the original size with lower number shrinking, larger growing
- `angle`: Rotation angle in radians
- `translation`: Shift the image X -/+, and y -/+
**<TIME>**
Time is the length of time to run the gif for:
```json
"time": {
"Time": {
"secs": 5,
"nanos": 0
}
},
```
A cycle is how many gif loops to run:
```json
"time": {
"Cycles": 2
},
```
`Infinite` means that this gif will never end:
```json
"time": "Infinite",
```
`Fade` allows an image or gif to fade in and out, and remain at max brightness to n time:
```json
"time": {
"Fade": {
"fade_in": {
"secs": 2,
"nanos": 0
},
"show_for": {
"secs": 1,
"nanos": 0
},
"fade_out": {
"secs": 2,
"nanos": 0
}
}
},
```
`show_for` can be `null`, if it is `null` then the `show_for` becomes `gif_time_length - fade_in - fade_out`.
This is period for which the gif or image will be max brightness (as set).
**<INT>**
A plain non-float integer.
## asusctl
`asusctl` is a commandline interface which intends to be the main method of interacting with `asusd`. It can be used in any place a terminal app can be used.
This program will query `asusd` for the `Support` level of the laptop and show or hide options according to this support level.
Most commands are self-explanatory.
### CLI Usage and help
Commands are given by:
```
asusctl <option> <command> <command-options>
```
Help is available through:
```
asusctl --help
asusctl <command> --help
```
Some commands may have subcommands:
```
asusctl <command> <subcommand> --help
```
### Keybinds
To switch to next/previous Aura modes you will need to bind both the aura keys (if available) to one of:
**Next**
```
asusctl aura -n
```
**Previous**
```
asusctl aura -p
```
To switch Fan/Thermal profiles you need to bind the Fn+F5 key to `asusctl profile -n`.
# License & Trademarks
Mozilla Public License 2 (MPL-2.0)
---
ASUS and ROG Trademark is either a US registered trademark or trademark of ASUSTeK Computer Inc. in the United States and/or other countries.
Reference to any ASUS products, services, processes, or other information and/or use of ASUS Trademarks does not constitute or imply endorsement, sponsorship, or recommendation thereof by ASUS.
The use of ROG and ASUS trademarks within this website and associated tools and libraries is only to provide a recognisable identifier to users to enable them to associate that these tools will work with ASUS ROG laptops.
---

175
Makefile
View File

@@ -1,36 +1,57 @@
prefix ?= /usr
sysconfdir ?= /etc
VERSION := $(shell /usr/bin/grep -Pm1 'version = "(\d+.\d+.\d+.*)"' Cargo.toml | cut -d'"' -f2)
INSTALL = install
INSTALL_PROGRAM = ${INSTALL} -D -m 0755
INSTALL_DATA = ${INSTALL} -D -m 0644
prefix = /usr
exec_prefix = $(prefix)
bindir = $(exec_prefix)/bin
libdir = $(exec_prefix)/lib
includedir = $(prefix)/include
datarootdir = $(prefix)/share
datadir = $(datarootdir)
libdir = $(exec_prefix)/lib
zshcpl = $(datarootdir)/zsh/site-functions
SRC = Cargo.toml Cargo.lock Makefile $(shell find -type f -wholename '**/src/*.rs')
BIN_ROG := rog-control-center
BIN_C := asusctl
BIN_D := asusd
BIN_U := asusd-user
LEDCFG := aura_support.ron
.PHONY: all clean distclean install uninstall update
DESTDIR_REALPATH = $(shell realpath $(DESTDIR))
BIN_C=asusctl
BIN_D=asusd
BIN_N=asus-notify
LEDCFG=asusd-ledmodes.toml
X11CFG=90-nvidia-screen-G05.conf
UDEVRULES=90-nvidia-pm.rules
VERSION:=$(shell grep -Pm1 'version = "(\d.\d.\d)"' asus-nb-ctrl/Cargo.toml | cut -d'"' -f2)
SRC := Cargo.toml Cargo.lock Makefile $(shell find -type f -wholename '**/src/*.rs')
STRIP_BINARIES ?= 0
DEBUG ?= 0
ifeq ($(DEBUG),0)
ARGS += "--release"
ARGS += --release
TARGET = release
else
ARGS += --profile dev
TARGET = debug
endif
X11 ?= 0
ifeq ($(X11),1)
ARGS += --features "rog-control-center/x11"
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
ifeq ($(VENDORED),1)
ARGS += "--frozen"
ARGS += --frozen
endif
all: target/release/$(BIN_D)
all: build
clean:
cargo clean
@@ -38,32 +59,87 @@ clean:
distclean:
rm -rf .cargo vendor vendor.tar.xz
install: all
install -D -m 0755 "target/release/$(BIN_C)" "$(DESTDIR)$(bindir)/$(BIN_C)"
install -D -m 0755 "target/release/$(BIN_D)" "$(DESTDIR)$(bindir)/$(BIN_D)"
install -D -m 0755 "target/release/$(BIN_N)" "$(DESTDIR)$(bindir)/$(BIN_N)"
install -D -m 0644 "data/$(UDEVRULES)" "$(DESTDIR)/lib/udev/rules.d/$(UDEVRULES)"
install -D -m 0644 "data/$(BIN_D).rules" "$(DESTDIR)/lib/udev/rules.d/99-$(BIN_D).rules"
install -D -m 0644 "data/$(LEDCFG)" "$(DESTDIR)$(sysconfdir)/asusd/$(LEDCFG)"
install -D -m 0644 "data/$(BIN_D).conf" "$(DESTDIR)$(sysconfdir)/dbus-1/system.d/$(BIN_D).conf"
install -D -m 0644 "data/$(X11CFG)" "$(DESTDIR)$(sysconfdir)/X11/xorg.conf.d/$(X11CFG)"
install -D -m 0644 "data/$(BIN_D).service" "$(DESTDIR)/lib/systemd/system/$(BIN_D).service"
install -D -m 0644 "data/$(BIN_N).service" "$(DESTDIR)/lib/systemd/user/$(BIN_N).service"
install -D -m 0644 "data/icons/asus_notif_yellow.png" "$(DESTDIR)/usr/share/icons/hicolor/512x512/apps/asus_notif_yellow.png"
install -D -m 0644 "data/icons/asus_notif_green.png" "$(DESTDIR)/usr/share/icons/hicolor/512x512/apps/asus_notif_green.png"
install -D -m 0644 "data/icons/asus_notif_red.png" "$(DESTDIR)/usr/share/icons/hicolor/512x512/apps/asus_notif_red.png"
target/$(TARGET)/$(BIN_D): build
target/$(TARGET)/$(BIN_C): build
target/$(TARGET)/$(BIN_U): build
target/$(TARGET)/$(BIN_ROG): build
install-asusd: target/$(TARGET)/$(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-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).png" "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/$(BIN_ROG).png"
cd rog-aura/data/layouts && find . -type f -name "*.ron" -exec $(INSTALL_DATA) "{}" "$(DESTDIR_REALPATH)$(datarootdir)/rog-gui/layouts/{}" \;
$(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_blue.png" "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_blue.png"
$(INSTALL_DATA) "./data/icons/asus_notif_red.png" "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_red.png"
$(INSTALL_DATA) "./data/icons/asus_notif_orange.png" "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_orange.png"
$(INSTALL_DATA) "./data/icons/asus_notif_white.png" "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_white.png"
$(INSTALL_DATA) "./data/icons/scalable/gpu-compute.svg" "$(DESTDIR)$(datarootdir)/icons/hicolor/scalable/status/gpu-compute.svg"
$(INSTALL_DATA) "./data/icons/scalable/gpu-hybrid.svg" "$(DESTDIR)$(datarootdir)/icons/hicolor/scalable/status/gpu-hybrid.svg"
$(INSTALL_DATA) "./data/icons/scalable/gpu-integrated.svg" "$(DESTDIR)$(datarootdir)/icons/hicolor/scalable/status/gpu-integrated.svg"
$(INSTALL_DATA) "./data/icons/scalable/gpu-nvidia.svg" "$(DESTDIR)$(datarootdir)/icons/hicolor/scalable/status/gpu-nvidia.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-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_DATA) "./LICENSE" "$(DESTDIR)$(datarootdir)/asusctl/LICENSE"
uninstall:
rm -f "$(DESTDIR)$(bindir)/$(BIN_ROG)"
rm -r "$(DESTDIR)$(datarootdir)/applications/$(BIN_ROG).desktop"
rm -r "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/$(BIN_ROG).png"
rm -f "$(DESTDIR)$(bindir)/$(BIN_C)"
rm -f "$(DESTDIR)$(bindir)/$(BIN_D)"
rm -f "$(DESTDIR)$(bindir)/$(BIN_N)"
rm -f "$(DESTDIR)/lib/udev/rules.d/$(UDEVRULES)"
rm -f "$(DESTDIR)/lib/udev/rules.d/99-$(BIN_D).rules"
rm -f "$(DESTDIR)$(sysconfdir)/dbus-1/system.d/$(BIN_D).conf"
rm -f "$(DESTDIR)$(sysconfdir)/X11/xorg.conf.d/$(X11CFG)"
rm -f "$(DESTDIR)/lib/systemd/system/$(BIN_D).service"
rm -r "$(DESTDIR)/lib/systemd/user/$(BIN_N).service"
rm -r "$(DESTDIR)/usr/share/icons/hicolor/512x512/apps/asus_notif_*"
rm -f "$(DESTDIR)$(libdir)/udev/rules.d/99-$(BIN_D).rules"
rm -f "$(DESTDIR)/etc/asusd/$(LEDCFG)"
rm -f "$(DESTDIR)$(datarootdir)/dbus-1/system.d/$(BIN_D).conf"
rm -f "$(DESTDIR)$(libdir)/systemd/system/$(BIN_D).service"
rm -r "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_yellow.png"
rm -r "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_green.png"
rm -r "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/asus_notif_red.png"
rm -r "$(DESTDIR)$(datarootdir)/icons/hicolor/scalable/status/gpu-compute.svg"
rm -r "$(DESTDIR)$(datarootdir)/icons/hicolor/scalable/status/gpu-hybrid.svg"
rm -r "$(DESTDIR)$(datarootdir)/icons/hicolor/scalable/status/gpu-integrated.svg"
rm -r "$(DESTDIR)$(datarootdir)/icons/hicolor/scalable/status/gpu-nvidia.svg"
rm -r "$(DESTDIR)$(datarootdir)/icons/hicolor/scalable/status/gpu-vfio.svg"
rm -r "$(DESTDIR)$(datarootdir)/icons/hicolor/scalable/status/notification-reboot.svg"
rm -rf "$(DESTDIR)$(datarootdir)/asusd"
rm -rf "$(DESTDIR)$(datarootdir)/rog-gui"
update:
cargo update
@@ -74,12 +150,27 @@ vendor:
echo 'directory = "vendor"' >> .cargo/config
mv .cargo/config ./cargo-config
rm -rf .cargo
tar pcfJ vendor_asus-nb-ctrl_$(VERSION).tar.xz vendor
rm -rf vendor
cargo vendor-filterer --all-features --platform x86_64-unknown-linux-gnu vendor
tar pcfJ vendor_asusctl_$(VERSION).tar.xz vendor
rm -rf vendor
target/release/$(BIN_D): $(SRC)
translate:
find -name \*.slint | xargs slint-tr-extractor -o rog-control-center/translations/en/rog-control-center.po
build:
ifeq ($(VENDORED),1)
cargo vendor
@echo "version = $(VERSION)"
tar pxf vendor_asus-nb-ctrl_$(VERSION).tar.xz
tar pxf vendor_asusctl_$(VERSION).tar.xz
endif
cargo build $(ARGS)
ifeq ($(STRIP_BINARIES),1)
strip -s ./target/$(TARGET)/$(BIN_C)
strip -s ./target/$(TARGET)/$(BIN_D)
strip -s ./target/$(TARGET)/$(BIN_U)
strip -s ./target/$(TARGET)/$(BIN_ROG)
endif
.PHONY: all clean distclean install uninstall update build bindings

274
README.md
View File

@@ -1,222 +1,182 @@
# ASUS NB Ctrl
# `asusctl` for ASUS ROG
**NOTICE:**
[![Become a Patron!](https://github.com/codebard/patron-button-and-widgets-by-codebard/blob/master/images/become_a_patron_button.png?raw=true)](https://www.patreon.com/bePatron?u=7602281) [![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/V7V5CLU67) - [Asus Linux Website](https://asus-linux.org/)
This program requires the kernel patch [here](https://www.spinics.net/lists/linux-input/msg68977.html) to be applied.
Alternatively you may use the dkms module for 'hid-asus-rog` from one of the
repositories [here](https://download.opensuse.org/repositories/home:/luke_nukem:/asus/).
**WARNING:** Many features are developed in tandem with kernel patches. If you see a feature is missing you either need a patched kernel or latest release.
The patch enables the following in kernel:
`asusd` is a utility for Linux to control many aspects of various ASUS laptops
but can also be used with non-asus laptops with reduced features.
- All hotkeys (FN+Key combos)
- Control of keyboard brightness using FN+Key combos (not RGB)
- FN+F5 (fan) to toggle fan modes
Now includes a GUI, `rog-control-center`.
You will not get RGB control in kernel (yet), and asusd is still required to
change modes and RGB settings. The previous version of this program is named
`rog-core` and takes full control of the interfaces required - if you can't
apply the kernel patches then `rog-core` is still highly usable.
## Kernel support
Many other patches for these laptops, AMD and Intel based, are working their way
in to the kernel.
Due to on-going driver work the minimum suggested kernel version is always **the latest*, as improvements and fixes are continuous.
---
asusd is a utility for Linux to control many aspects of various ASUS laptops.
Support for some new features is not avilable unless you run a patched kernel with the work I am doing [in this github repo](https://github.com/flukejones/linux/tree/wip/ally-6.13). Use the linked branch, or `wip/ally-6.12`. Everything that is done here is upstreamed eventually (a long process).
Z13 devices will need [these](https://lore.kernel.org/linux-input/20240416090402.31057-1-luke@ljones.dev/T/#t)
## X11 support
X11 is not supported at all, as in I will not help you with X11 issues if there are any due to limited time and it being unmaintained itself. You can however build `rog-control-center` with it enabled `cargo build --features "rog-control-center/x11"`.
## Goals
The main goal of this work is to provide a safe and easy to use abstraction over various laptop features via DBUS, and to provide some helpful defaults and other behaviour such as toggling throttle/profile on AC/battery change.
1. Provide safe dbus interface
2. Respect the users resources: be small, light, and fast
Point 4? asusd currently uses a tiny fraction of cpu time, and less than 1Mb of ram, the way
a system-level daemon should. Languages such as JS and python should never be used for system level daemons (please stop).
## Keyboard LEDs
The level of support for laptops is dependent on folks submitting data to include in [`./rog-aura/data/layouts/aura_support.ron`](./rog-aura/data/layouts/aura_support.ron), typically installed in `/usr/share/asusd/aura_support.ron`. This is because the controller used for keyboards and LEDs is used across many years and many laptop models, all with different firmware configurations - the only way to track this is with the file mentioned above. Why not just enable all by default? Because it confuses people.
See the [rog-aura readme](./rog-aura/README.md) for more details.
## Discord
[Discord server link](https://discord.gg/PVyFzWj)
[![Discord](https://img.shields.io/badge/Discord-7289DA?style=for-the-badge&logo=discord&logoColor=white)](https://discord.gg/B8GftRW2Hd)
## SUPPORTED LAPTOPS
Most ASUS gaming laptops that have a USB keyboard. If `lsusb` shows something similar
to this:
```
```plain
Bus 001 Device 002: ID 0b05:1866 ASUSTek Computer, Inc. N-KEY Device
```
or
```plain
Bus 003 Device 002: ID 0b05:19b6 ASUSTek Computer, Inc. [unknown]
```
then it may work without tweaks. Technically all other functions except the LED
and AniMe parts should work regardless of your latop make. Eventually this project
will probably suffer another rename once it becomes generic enough to do so.
and AniMe parts should work regardless of your latop make.
## Implemented
- [X] System daemon
- [X] User notifications daemon
- [X] Setting/modifying built-in LED modes
- [X] Per-key LED setting
- [X] Fancy LED modes (See examples)
- [X] Saving settings for reload
- [X] Logging - required for journalctl
- [X] AniMatrix display on G14 models that include it
- [X] Set battery charge limit (with kernel supporting this)
- [X] Fancy fan control on G14 + G15 thanks to @Yarn1
- [X] Graphics mode switching between iGPU, dGPU, and On-Demand
The list is a bit outdated as many features have been enabled in the Linux kernel with upstream patches and then supported in asusctl suite.
## FUNCTIONS
- [x] System daemon
- [x] GUI app (includes tray and notifications)
- [x] Setting/modifying built-in LED modes
- [x] Per-key LED setting
- [x] Fancy LED modes (See examples) (currently being reworked)
- [x] AniMatrix display on G14 and M16 models that include it
- [x] Set battery charge limit (with kernel supporting this)
- [x] Fan curve control on supported laptops (G14/G15, some TUF like FA507)
- [x] Toggle bios setting for boot/POST sound
- [x] Toggle GPU MUX (g-sync, or called MUX on 2022+ laptops)
### Graphics switching
## GUI
A new feature has been added to enable switching graphics modes. This can be disabled
in the config with `"manage_gfx": false,`. Please be aware it is a work in progress.
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.
The CLI option for this does not require root until it asks for it, and provides
instructions.
**NOTE**: Xorg is not supported.
### KEYBOARD BACKLIGHT MODES
## BUILDING
Models GA401, GA502, GU502 support LED brightness change only (no RGB).
Rust and cargo are required, they can be installed from [rustup.rs](https://rustup.rs/).
If you model isn't getting the correct led modes, you can edit the file
`/etc/asusd/asusd-ledmodes.toml`, the LED Mode numbers are as follows:
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.
```
0 STATIC
1 BREATHING
2 STROBE
3 RAINBOW
4 STAR
5 RAIN
6 HIGHLIGHT
7 LASER
8 RIPPLE
10 PULSE
11 COMET
12 FLASH
13 MULTISTATIC
255 PER_KEY
**fedora:**
```sh
dnf install cmake clang-devel libxkbcommon-devel systemd-devel expat-devel pcre2-devel libzstd-devel gtk3-devel
make
sudo make install
```
use `cat /sys/class/dmi/id/product_name` to get details about your laptop.
**openSUSE:**
## Requirements for compiling
Works with KDE Plasma (without GTK packages)
- `rustc` + `cargo` + `make`
- `libusb-1.0-0-dev`
- `libdbus-1-dev`
- `llvm`
- `libclang-dev`
- `libudev-dev`
```sh
zypper in -t pattern devel_basis
zypper in rustup make cmake clang-devel libxkbcommon-devel systemd-devel expat-devel pcre2-devel libzstd-devel gtk3-devel
make
sudo make install
```
**Debian(unsuported):**
officially unsuported,but you can still try and test it by yourself(some features may not be available).
```sh
sudo apt install libclang-dev libudev-dev libfontconfig-dev build-essential cmake libxkbcommon-dev
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
make
sudo make install
```
**Ubuntu, Popos (unsuported):**
```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
Packaging and auto-builds are available [here](https://build.opensuse.org/package/show/home:luke_nukem:asus/asus-nb-ctrl)
- Fedora copr = https://copr.fedorainfracloud.org/coprs/lukenukem/asus-linux/
- openSUSE = https://download.opensuse.org/repositories/home:/luke_nukem:/asus/
Download repositories are available [here](https://download.opensuse.org/repositories/home:/luke_nukem:/asus/)
---
Run `make` then `sudo make install` then reboot.
=======
The default init method is to use the udev rule, this ensures that the service is
started when the device is initialised and ready.
You may also need to activate the service for debian install. If running Pop!\_OS, I suggest disabling `system76-power` gnome-shell extension and systemd service.
## Upgrading
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
```
You may also need to activate the service for debian install. If running Pop!_OS, I suggest disabling `system76-power` gnome-shell extension and systemd service.
## Uninstalling
Run `sudo make uninstall` in the source repo, and remove `/etc/asusd/`.
## Updating
## Contributing
If there has been a config file format change your config will be overwritten. This will
become less of an issue once the feature set is nailed down. Work is happening to enable
parsing of older configs and transferring settings to new.
See `CONTRIBUTING.md`. Additionally, also do `cargo clean` and `cargo test` on first checkout to ensure the commit hooks are used (via `cargo-husky`).
# Usage
Generation of the bindings with `make bindings` requires `typeshare` to be installed.
**NOTE! Fan mode toggling requires a newer kernel**. I'm unsure when the patches
required for it got merged - I've tested with the 5.6.6 kernel and above only.
To see if the fan-mode changed cat either:
Dbus introsepction XML requires with `make introspection` requires `anime_sim` to be running before starting `asusd`.
- `cat /sys/devices/platform/asus-nb-wmi/throttle_thermal_policy` or
- `cat /sys/devices/platform/asus-nb-wmi/fan_boost_mode`
## OTHER
The numbers are 0 = Normal/Balanced, 1 = Boost, 2 = Silent.
### AniMe Matrix simulator
Running the program as a daemon manually will require root. Standard (non-daemon)
mode expects to be communicating with the daemon mode over dbus.
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.
Commands are given by:
```
asusctl <option> <command> <command-options>
```
Help is available through:
```
asusctl --help
asusctl <command> --help
```
Some commands may have subcommands:
```
asusctl <command> <subcommand> --help
```
## Daemon mode
If the daemon service is enabled then on boot the following will be reloaded from save:
- LED brightness
- Last used built-in mode
- fan-boost/thermal mode
- battery charging limit
The daemon also saves the settings per mode as the keyboard does not do this
itself - this means cycling through modes with the Aura keys will use the
settings that were used via CLI.
Daemon mode creates a config file at `/etc/asusd/asusd.conf` which you can edit a
little of. Most parts will be byte arrays, but you can adjust things like
`mode_performance`.
## User daemon for notification via dbus
If you have a notifications handler set up, or are using KDE or Gnome then you
can enable the user service to get basic notifications when something changes.
```
systemctl --user enable asus-notify.service
systemctl --user start asus-notify.service
```
# Other
## DBUS Input
See [README_DBUS.md](./README_DBUS.md).
## AniMe input
You will want to look at what MeuMeu has done with [https://github.com/Meumeu/ZephyrusBling/](https://github.com/Meumeu/ZephyrusBling/)
## Supporting more laptops
### Supporting more laptops
Please file a support request.
## Notes:
- If charge limit or fan modes are not working, then you may require a kernel newer than 5.6.10.
- AniMe device check is performed on start, if your device has one it will be detected.
- GA14/GA401 and GA15/GA502/GU502, You will need kernel [patches](https://lab.retarded.farm/zappel/asus-rog-zephyrus-g14/-/tree/master/kernel_patches), these are on their way to the kernel upstream.
# License
## License & Trademarks
Mozilla Public License 2 (MPL-2.0)
# Credits
---
- [flukejones](https://github.com/flukejones/), project maintainer.
- [tuxuser](https://github.com/tuxuser/)
- [aspann](https://github.com/aspann)
- [meumeu](https://github.com/Meumeu)
- Anyone missed? Please contact me
ASUS and ROG Trademark is either a US registered trademark or trademark of ASUSTeK Computer Inc. in the United States and/or other countries.
Reference to any ASUS products, services, processes, or other information and/or use of ASUS Trademarks does not constitute or imply endorsement, sponsorship, or recommendation thereof by ASUS.
The use of ROG and ASUS trademarks within this website and associated tools and libraries is only to provide a recognisable identifier to users to enable them to associate that these tools will work with ASUS ROG laptops.
---

View File

@@ -1,109 +0,0 @@
# DBUS Guide
**WARNING: In progress updates**
Interface name = org.asuslinux.Daemon
Paths:
- `/org/asuslinux/Gfx`
+ `SetVendor` (string)
+ `NotifyVendor` (recv vendor label string)
- `/org/asuslinux/Led`
+ `LedMode` (AuraMode as json)
+ `LedModes` (array[AuraMode] as json)
+ `SetLedMode` (AuraMode -> json)
+ `NotifyLed` (recv json data)
- `/org/asuslinux/Anime`
+ `SetAnime` (byte array data)
- `/org/asuslinux/Charge`
+ `Limit` (u8)
+ `SetLimit` (u8)
+ `NotifyCharge` (recv i8)
- `/org/asuslinux/Profile`
+ `Profile` (recv current profile data as json string)
+ `Profiles` (recv profiles data as json string (map))
+ `SetProfile` (event -> json)
+ `NotifyProfile` (recv current profile name)
All `Notify*` methods are signals.
### SetLed
This method expects a string of JSON as input. The JSON is of format such:
```
{
"Static": {
"colour": [ 255, 0, 0]
}
}
```
The possible contents of a mode are:
- `"colour": [u8, u8, u8],`
- `"speed": <String>,` <Low, Med, High>
- `"direction": <String>,` <Up, Down, Left, Right>
Modes may or may not be available for a specific laptop (TODO: dbus getter for
supported modes). Modes are:
- `"Static": { "colour": <colour> },`
- `"Pulse": { "colour": <colour> },`
- `"Comet": { "colour": <colour> },`
- `"Flash": { "colour": <colour> },`
- `"Strobe": { "speed": <speed> },`
- `"Rain": { "speed": <speed> },`
- `"Laser": { "colour": <colour>, "speed": <speed> },`
- `"Ripple": { "colour": <colour>, "speed": <speed> },`
- `"Highlight": { "colour": <colour>, "speed": <speed> },`
- `"Rainbow": { "direction": <direction>, "speed": <speed> },`
- `"Breathe": { "colour": <colour>, "colour2": <colour>, "speed": <speed> },`
- `"Star": { "colour": <colour>, "colour2": <colour>, "speed": <speed> },`
- `"MultiStatic": { "colour1": <colour>, "colour2": <colour>, , "colour3": <colour>, "colour4": <colour> },`
Additionally to the above there is `"RGB": [[u8; 64]; 11]` which is for per-key
setting of LED's but this requires some refactoring to make it easily useable over
dbus.
Lastly, there is `"LedBrightness": <u8>` which accepts 0-3 for off, low, med, high.
### SetFanMode
Accepts an integer from the following:
- `0`: Normal
- `1`: Boost mode
- `2`: Silent mode
## dbus-send examples OUTDATED
```
dbus-send --system --type=method_call --dest=org.asuslinux.Daemon /org/asuslinux/Daemon org.asuslinux.Daemon.SetKeyBacklight string:'{"Static": {"colour": [ 80, 0, 40]}}'
```
```
dbus-send --system --type=method_call --dest=org.asuslinux.Daemon /org/asuslinux/Daemon org.asuslinux.Daemon.SetKeyBacklight string:'{"Star":{"colour":[0,255,255],"colour2":[0,0,0],"speed":"Med"}}'
```
**Note:** setting colour2 to `[0,0,255]` activates random star colour. Colour2 has no effect on the
mode otherwise.
```
dbus-send --system --type=method_call --dest=org.asuslinux.Daemon /org/asuslinux/Daemon org.asuslinux.Daemon.SetKeyBacklight string:'{"Star":{"colour":[0,255,255],"colour2":[0,0,255],"speed":"Med"}}'
```
```
dbus-send --system --type=method_call --dest=org.asuslinux.Daemon /org/asuslinux/Daemon org.asuslinux.Daemon.SetKeyBacklight string:'{"LedBrightness":3}'
```
```
dbus-send --system --type=method_call --dest=org.asuslinux.Daemon /org/asuslinux/Daemon org.asuslinux.Daemon.SetFanMode byte:'2'
```
Monitoring dbus while sending commands via `rog-core` will give you the json structure if you are otherwise unsure, e.g: `dbus-monitor --system |grep -A2 asuslinux`.
## Getting an introspection .xml
```
dbus-send --system --print-reply --dest=org.asuslinux.Daemon /org/asuslinux/Charge org.freedesktop.DBus.Introspectable.Introspect > xml/asusd-charge.xml
```

View File

@@ -1,7 +0,0 @@
# TODO
- There is lots of code duplication. This should be turned in to macros (dbus stuff etc)
- Add a little more information to profile notifications such as freq min/max, fan curves
- Finish splitting out controllers to own crates
- Finish move to zbus in client when zbus has client signal watch
- Consider a rename again because the project is getting a lot less ASUS centric

1016
asus-nb-ctrl/Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,52 +0,0 @@
[package]
name = "asus-nb-ctrl"
version = "2.0.0"
license = "MPL-2.0"
readme = "README.md"
authors = ["Luke <luke@ljones.dev>"]
repository = "https://gitlab.com/asus-linux/asus-nb-ctrl"
homepage = "https://gitlab.com/asus-linux/asus-nb-ctrl"
description = "A daemon app for ASUS GX502 and similar laptops to control missing features"
edition = "2018"
[lib]
name = "daemon"
path = "src/lib.rs"
[[bin]]
name = "asusctl"
path = "src/main.rs"
[[bin]]
name = "asusd"
path = "src/daemon.rs"
[dependencies]
ctrl-gfx = { path = "../ctrl-gfx" }
asus-nb = { path = "../asus-nb" }
rusb = "^0.6.0"
udev = "^0.4.0"
# cli and logging
gumdrop = "^0.8.0"
log = "^0.4.8"
env_logger = "^0.7.1"
# async
zbus = "1.1.1"
zvariant = "2.2.0"
#tokio = { version = "^0.2.4", features = ["rt-threaded", "sync"] }
# serialisation
serde = "^1.0"
serde_derive = "^1.0"
serde_json = "^1.0"
toml = "0.4.6"
# Device control
sysfs-class = "^0.1.2" # used for backlight control and baord ID
rog_fan_curve = { version = "0.1.5", features = ["serde"] }
# cpu power management
intel-pstate = "^0.2.1"
yansi-term = "^0.1"

View File

@@ -1,166 +0,0 @@
use asus_nb::aura_modes::AuraModes;
use log::{error, warn};
use rog_fan_curve::Curve;
use serde_derive::{Deserialize, Serialize};
use std::collections::BTreeMap;
use std::fs::{File, OpenOptions};
use std::io::{Read, Write};
pub static CONFIG_PATH: &str = "/etc/asusd/asusd.conf";
#[derive(Default, Deserialize, Serialize)]
pub struct Config {
pub gfx_managed: bool,
pub active_profile: String,
pub toggle_profiles: Vec<String>,
// TODO: remove power_profile
pub power_profile: u8,
pub bat_charge_limit: u8,
pub kbd_led_brightness: u8,
pub kbd_backlight_mode: u8,
pub kbd_backlight_modes: Vec<AuraModes>,
pub power_profiles: BTreeMap<String, Profile>,
}
impl Config {
/// `load` will attempt to read the config, but if it is not found it
/// will create a new default config and write that out.
pub fn load(mut self, supported_led_modes: &[u8]) -> Self {
let mut file = OpenOptions::new()
.read(true)
.write(true)
.create(true)
.open(&CONFIG_PATH)
.unwrap(); // okay to cause panic here
let mut buf = String::new();
if let Ok(l) = file.read_to_string(&mut buf) {
if l == 0 {
self = Config::create_default(&mut file, &supported_led_modes);
} else {
self = serde_json::from_str(&buf).unwrap_or_else(|_| {
warn!(
"Could not deserialise {}. Overwriting with default",
CONFIG_PATH
);
Config::create_default(&mut file, &supported_led_modes)
});
}
}
self
}
fn create_default(file: &mut File, supported_led_modes: &[u8]) -> Self {
// create a default config here
let mut config = Config::default();
config.gfx_managed = true;
config.bat_charge_limit = 100;
config.kbd_backlight_mode = 0;
config.kbd_led_brightness = 1;
for n in supported_led_modes {
config.kbd_backlight_modes.push(AuraModes::from(*n))
}
let profile = Profile::default();
config.power_profiles.insert("normal".into(), profile);
let mut profile = Profile::default();
profile.fan_preset = 1;
config.power_profiles.insert("boost".into(), profile);
let mut profile = Profile::default();
profile.fan_preset = 2;
config.power_profiles.insert("silent".into(), profile);
config.toggle_profiles.push("normal".into());
config.toggle_profiles.push("boost".into());
config.toggle_profiles.push("silent".into());
config.active_profile = "normal".into();
// Should be okay to unwrap this as is since it is a Default
let json = serde_json::to_string_pretty(&config).unwrap();
file.write_all(json.as_bytes())
.unwrap_or_else(|_| panic!("Could not write {}", CONFIG_PATH));
config
}
pub fn read(&mut self) {
let mut file = OpenOptions::new()
.read(true)
.open(&CONFIG_PATH)
.unwrap_or_else(|err| panic!("Error reading {}: {}", CONFIG_PATH, err));
let mut buf = String::new();
if let Ok(l) = file.read_to_string(&mut buf) {
if l == 0 {
warn!("File is empty {}", CONFIG_PATH);
} else {
let x: Config = serde_json::from_str(&buf)
.unwrap_or_else(|_| panic!("Could not deserialise {}", CONFIG_PATH));
*self = x;
}
}
}
pub fn read_new() -> Result<Config, Box<dyn std::error::Error>> {
let mut file = OpenOptions::new()
.read(true)
.open(&CONFIG_PATH)
.unwrap_or_else(|err| panic!("Error reading {}: {}", CONFIG_PATH, err));
let mut buf = String::new();
file.read_to_string(&mut buf)?;
let x: Config = serde_json::from_str(&buf)?;
Ok(x)
}
pub fn write(&self) {
let mut file = File::create(CONFIG_PATH).expect("Couldn't overwrite config");
let json = serde_json::to_string_pretty(self).expect("Parse config to JSON failed");
file.write_all(json.as_bytes())
.unwrap_or_else(|err| error!("Could not write config: {}", err));
}
pub fn set_mode_data(&mut self, mode: AuraModes) {
let byte: u8 = (&mode).into();
for (index, n) in self.kbd_backlight_modes.iter().enumerate() {
if byte == u8::from(n) {
// Consume it, OMNOMNOMNOM
self.kbd_backlight_modes[index] = mode;
break;
}
}
}
pub fn get_led_mode_data(&self, num: u8) -> Option<&AuraModes> {
for mode in &self.kbd_backlight_modes {
if u8::from(mode) == num {
return Some(mode);
}
}
None
}
}
#[derive(Deserialize, Serialize)]
pub struct Profile {
pub min_percentage: u8,
pub max_percentage: u8,
pub turbo: bool,
pub fan_preset: u8,
pub fan_curve: Option<Curve>,
}
#[deprecated]
pub type CPUSettings = Profile;
impl Default for Profile {
fn default() -> Self {
Profile {
min_percentage: 0,
max_percentage: 100,
turbo: false,
fan_preset: 0,
fan_curve: None,
}
}
}

View File

@@ -1,205 +0,0 @@
const INIT_STR: &str = "ASUS Tech.Inc.";
const PACKET_SIZE: usize = 640;
// Only these two packets must be 17 bytes
const DEV_PAGE: u8 = 0x5e;
// These bytes are in [1] position of the array
const WRITE: u8 = 0xc0;
const INIT: u8 = 0xc2;
const APPLY: u8 = 0xc3;
const SET: u8 = 0xc4;
use asus_nb::error::AuraError;
use log::{error, info, warn};
use rusb::{Device, DeviceHandle};
use std::convert::TryInto;
use std::error::Error;
use std::time::Duration;
use zbus::dbus_interface;
#[allow(dead_code)]
#[derive(Debug)]
pub enum AnimatrixCommand {
Apply,
Set,
WriteImage(Vec<Vec<u8>>),
//ReloadLast,
}
pub struct CtrlAnimeDisplay {
handle: DeviceHandle<rusb::GlobalContext>,
initialised: bool,
}
//AnimatrixWrite
pub trait Dbus {
fn set_anime(&mut self, input: Vec<Vec<u8>>);
}
impl crate::ZbusAdd for CtrlAnimeDisplay {
fn add_to_server(self, server: &mut zbus::ObjectServer) {
server
.at(&"/org/asuslinux/Anime".try_into().unwrap(), self)
.unwrap();
}
}
#[dbus_interface(name = "org.asuslinux.Daemon")]
impl Dbus for CtrlAnimeDisplay {
fn set_anime(&mut self, input: Vec<Vec<u8>>) {
self.do_command(AnimatrixCommand::WriteImage(input))
.unwrap_or_else(|err| warn!("{}", err));
}
}
impl CtrlAnimeDisplay {
#[inline]
pub fn new() -> Result<CtrlAnimeDisplay, Box<dyn Error>> {
// We don't expect this ID to ever change
let device = CtrlAnimeDisplay::get_device(0x0b05, 0x193b)?;
let mut device = device.open()?;
device.reset()?;
device.set_auto_detach_kernel_driver(true).map_err(|err| {
error!("Auto-detach kernel driver failed: {}", err);
err
})?;
device.claim_interface(0).map_err(|err| {
error!("Could not claim device interface: {}", err);
err
})?;
info!("Device has an AniMe Matrix display");
Ok(CtrlAnimeDisplay {
handle: device,
initialised: false,
})
}
#[inline]
fn get_device(vendor: u16, product: u16) -> Result<Device<rusb::GlobalContext>, rusb::Error> {
for device in rusb::devices()?.iter() {
let device_desc = device.device_descriptor()?;
if device_desc.vendor_id() == vendor && device_desc.product_id() == product {
return Ok(device);
}
}
Err(rusb::Error::NoDevice)
}
pub fn do_command(&mut self, command: AnimatrixCommand) -> Result<(), AuraError> {
if !self.initialised {
self.do_initialization()?
}
match command {
AnimatrixCommand::WriteImage(effect) => self.write_image(effect)?,
AnimatrixCommand::Set => self.do_set()?,
AnimatrixCommand::Apply => self.do_apply()?,
//AnimatrixCommand::ReloadLast => self.reload_last_builtin(&config).await?,
}
Ok(())
}
/// Should only be used if the bytes you are writing are verified correct
#[inline]
fn write_bytes(&self, message: &[u8]) -> Result<(), AuraError> {
match self.handle.write_control(
0x21, // request_type
0x09, // request
0x35e, // value
0x00, // index
message,
Duration::from_millis(200),
) {
Ok(_) => {}
Err(err) => match err {
rusb::Error::Timeout => {}
_ => error!("Failed to write to led interrupt: {}", err),
},
}
Ok(())
}
/// Write an Animatrix image
///
/// The expected input here is *two* Vectors, 640 bytes in length. The two vectors
/// are each one half of the full image write.
///
/// After each write a flush is written, it is assumed that this tells the device to
/// go ahead and display the written bytes
///
/// # Note:
/// The vectors are expected to contain the full sequence of bytes as follows
///
/// - Write pane 1: 0x5e 0xc0 0x02 0x01 0x00 0x73 0x02 .. <led brightness>
/// - Write pane 2: 0x5e 0xc0 0x02 0x74 0x02 0x73 0x02 .. <led brightness>
///
/// Where led brightness is 0..255, low to high
#[inline]
fn write_image(&mut self, image: Vec<Vec<u8>>) -> Result<(), AuraError> {
for row in image.iter() {
self.write_bytes(row)?;
}
self.do_flush()?;
Ok(())
}
#[inline]
fn do_initialization(&mut self) -> Result<(), AuraError> {
let mut init = [0; PACKET_SIZE];
init[0] = DEV_PAGE; // This is the USB page we're using throughout
for (idx, byte) in INIT_STR.as_bytes().iter().enumerate() {
init[idx + 1] = *byte
}
self.write_bytes(&init)?;
// clear the init array and write other init message
for ch in init.iter_mut() {
*ch = 0;
}
init[0] = DEV_PAGE; // write it to be sure?
init[1] = INIT;
self.write_bytes(&init)?;
self.initialised = true;
Ok(())
}
#[inline]
fn do_flush(&mut self) -> Result<(), AuraError> {
let mut flush = [0; PACKET_SIZE];
flush[0] = DEV_PAGE;
flush[1] = WRITE;
flush[2] = 0x03;
self.write_bytes(&flush)?;
Ok(())
}
#[inline]
fn do_set(&mut self) -> Result<(), AuraError> {
let mut flush = [0; PACKET_SIZE];
flush[0] = DEV_PAGE;
flush[1] = SET;
flush[2] = 0x01;
flush[3] = 0x80;
self.write_bytes(&flush)?;
Ok(())
}
#[inline]
fn do_apply(&mut self) -> Result<(), AuraError> {
let mut flush = [0; PACKET_SIZE];
flush[0] = DEV_PAGE;
flush[1] = APPLY;
flush[2] = 0x01;
flush[3] = 0x80;
self.write_bytes(&flush)?;
Ok(())
}
}

View File

@@ -1,103 +0,0 @@
use crate::{config::Config, error::RogError};
//use crate::dbus::DbusEvents;
use log::{info, warn};
use std::convert::TryInto;
use std::fs::OpenOptions;
use std::io::Write;
use std::path::Path;
use std::sync::Arc;
use std::sync::Mutex;
use zbus::dbus_interface;
static BAT_CHARGE_PATH: &str = "/sys/class/power_supply/BAT0/charge_control_end_threshold";
pub struct CtrlCharge {
path: &'static str,
config: Arc<Mutex<Config>>,
}
trait Dbus {
fn set_limit(&mut self, charge: u8);
fn limit(&self) -> i8;
fn notify_charge(&self, limit: u8) -> zbus::Result<()>;
}
#[dbus_interface(name = "org.asuslinux.Daemon")]
impl Dbus for CtrlCharge {
fn set_limit(&mut self, limit: u8) {
if let Ok(mut config) = self.config.try_lock() {
self.set(limit, &mut config).unwrap();
self.notify_charge(limit).unwrap();
}
}
fn limit(&self) -> i8 {
if let Ok(config) = self.config.try_lock() {
return config.bat_charge_limit as i8;
}
-1
}
#[dbus_interface(signal)]
fn notify_charge(&self, limit: u8) -> zbus::Result<()>;
}
impl crate::ZbusAdd for CtrlCharge {
fn add_to_server(self, server: &mut zbus::ObjectServer) {
server
.at(&"/org/asuslinux/Charge".try_into().unwrap(), self)
.unwrap();
}
}
impl crate::Reloadable for CtrlCharge {
fn reload(&mut self) -> Result<(), RogError> {
if let Ok(mut config) = self.config.try_lock() {
config.read();
info!("Reloaded battery charge limit");
self.set(config.bat_charge_limit, &mut config)?;
}
Ok(())
}
}
impl CtrlCharge {
pub fn new(config: Arc<Mutex<Config>>) -> Result<Self, RogError> {
let path = CtrlCharge::get_battery_path()?;
info!("Device has battery charge threshold control");
Ok(CtrlCharge { path, config })
}
fn get_battery_path() -> Result<&'static str, RogError> {
if Path::new(BAT_CHARGE_PATH).exists() {
Ok(BAT_CHARGE_PATH)
} else {
Err(RogError::MissingFunction(
"Charge control not available".into(),
))
}
}
pub(super) fn set(&self, limit: u8, config: &mut Config) -> Result<(), RogError> {
if limit < 20 || limit > 100 {
warn!(
"Unable to set battery charge limit, must be between 20-100: requested {}",
limit
);
}
let mut file = OpenOptions::new()
.write(true)
.open(self.path)
.map_err(|err| RogError::Path(self.path.into(), err))?;
file.write_all(limit.to_string().as_bytes())
.map_err(|err| RogError::Write(self.path.into(), err))?;
info!("Battery charge limit: {}", limit);
config.read();
config.bat_charge_limit = limit;
config.write();
Ok(())
}
}

View File

@@ -1,381 +0,0 @@
use crate::config::{Config, Profile};
use asus_nb::profile::ProfileEvent;
use log::{info, warn};
use std::convert::TryInto;
use std::fs::OpenOptions;
use std::io::{Read, Write};
use std::path::Path;
use std::str::FromStr;
use std::sync::Arc;
use std::sync::Mutex;
use zbus::dbus_interface;
static FAN_TYPE_1_PATH: &str = "/sys/devices/platform/asus-nb-wmi/throttle_thermal_policy";
static FAN_TYPE_2_PATH: &str = "/sys/devices/platform/asus-nb-wmi/fan_boost_mode";
static AMD_BOOST_PATH: &str = "/sys/devices/system/cpu/cpufreq/boost";
pub struct CtrlFanAndCPU {
pub path: &'static str,
config: Arc<Mutex<Config>>,
}
pub struct DbusFanAndCpu {
inner: Arc<Mutex<CtrlFanAndCPU>>,
}
impl DbusFanAndCpu {
pub fn new(inner: Arc<Mutex<CtrlFanAndCPU>>) -> Self {
Self { inner }
}
}
#[dbus_interface(name = "org.asuslinux.Daemon")]
impl DbusFanAndCpu {
fn set_profile(&self, profile: String) {
if let Ok(event) = serde_json::from_str(&profile) {
if let Ok(mut ctrl) = self.inner.try_lock() {
if let Ok(mut cfg) = ctrl.config.clone().try_lock() {
cfg.read();
ctrl.handle_profile_event(&event, &mut cfg)
.unwrap_or_else(|err| warn!("{}", err));
self.notify_profile(&cfg.active_profile)
.unwrap_or_else(|_| ());
}
}
}
}
fn profile(&mut self) -> String {
if let Ok(ctrl) = self.inner.try_lock() {
if let Ok(mut cfg) = ctrl.config.try_lock() {
cfg.read();
if let Some(profile) = cfg.power_profiles.get(&cfg.active_profile) {
if let Ok(json) = serde_json::to_string(profile) {
return json;
}
}
}
}
"Failed".to_string()
}
fn profiles(&mut self) -> String {
if let Ok(ctrl) = self.inner.try_lock() {
if let Ok(mut cfg) = ctrl.config.try_lock() {
cfg.read();
if let Ok(json) = serde_json::to_string(&cfg.power_profiles) {
return json;
}
}
}
"Failed".to_string()
}
#[dbus_interface(signal)]
fn notify_profile(&self, profile: &str) -> zbus::Result<()>;
}
impl crate::ZbusAdd for DbusFanAndCpu {
fn add_to_server(self, server: &mut zbus::ObjectServer) {
server
.at(&"/org/asuslinux/Profile".try_into().unwrap(), self)
.unwrap();
}
}
impl crate::Reloadable for CtrlFanAndCPU {
fn reload(&mut self) -> Result<(), RogError> {
if let Ok(mut config) = self.config.clone().try_lock() {
let mut file = OpenOptions::new()
.write(true)
.open(self.path)
.map_err(|err| RogError::Path(self.path.into(), err))?;
file.write_all(format!("{}\n", config.power_profile).as_bytes())
.map_err(|err| RogError::Write(self.path.into(), err))?;
let profile = config.active_profile.clone();
self.set(&profile, &mut config)?;
info!(
"Reloaded fan mode: {:?}",
FanLevel::from(config.power_profile)
);
}
Ok(())
}
}
impl crate::CtrlTask for CtrlFanAndCPU {
fn do_task(&mut self) -> Result<(), RogError> {
let mut file = OpenOptions::new()
.read(true)
.open(self.path)
.map_err(|err| RogError::Path(self.path.into(), err))?;
let mut buf = [0u8; 1];
file.read_exact(&mut buf)
.map_err(|err| RogError::Read(self.path.into(), err))?;
if let Some(num) = char::from(buf[0]).to_digit(10) {
if let Ok(mut config) = self.config.clone().try_lock() {
if config.power_profile != num as u8 {
config.read();
let mut i = config
.toggle_profiles
.iter()
.position(|x| x == &config.active_profile)
.map(|i| i + 1)
.unwrap_or(0);
if i >= config.toggle_profiles.len() {
i = 0;
}
let new_profile = config
.toggle_profiles
.get(i)
.unwrap_or(&config.active_profile)
.clone();
self.set(&new_profile, &mut config)?;
info!("Profile was changed: {}", &new_profile);
}
}
return Ok(());
}
Err(RogError::DoTask("Fan-level could not be parsed".into()))
}
}
impl CtrlFanAndCPU {
pub fn new(config: Arc<Mutex<Config>>) -> Result<Self, RogError> {
let path = CtrlFanAndCPU::get_fan_path()?;
info!("Device has thermal throttle control");
Ok(CtrlFanAndCPU { path, config })
}
fn get_fan_path() -> Result<&'static str, RogError> {
if Path::new(FAN_TYPE_1_PATH).exists() {
Ok(FAN_TYPE_1_PATH)
} else if Path::new(FAN_TYPE_2_PATH).exists() {
Ok(FAN_TYPE_2_PATH)
} else {
Err(RogError::MissingFunction(
"Fan mode not available, you may require a v5.8 series kernel or newer".into(),
))
}
}
pub(super) fn do_update(&mut self, config: &mut Config) -> Result<(), RogError> {
config.read();
let mut i = config
.toggle_profiles
.iter()
.position(|x| x == &config.active_profile)
.map(|i| i + 1)
.unwrap_or(0);
if i >= config.toggle_profiles.len() {
i = 0;
}
let new_profile = config
.toggle_profiles
.get(i)
.unwrap_or(&config.active_profile)
.clone();
self.set(&new_profile, config)?;
info!("Profile was changed: {}", &new_profile);
Ok(())
}
pub(super) fn set_fan_mode(&mut self, preset: u8, config: &mut Config) -> Result<(), RogError> {
let mode = config.active_profile.clone();
let mut fan_ctrl = OpenOptions::new()
.write(true)
.open(self.path)
.map_err(|err| RogError::Path(self.path.into(), err))?;
config.read();
let mut mode_config = config
.power_profiles
.get_mut(&mode)
.ok_or_else(|| RogError::MissingProfile(mode.clone()))?;
config.power_profile = preset;
mode_config.fan_preset = preset;
config.write();
fan_ctrl
.write_all(format!("{}\n", preset).as_bytes())
.map_err(|err| RogError::Write(self.path.into(), err))?;
info!("Fan mode set to: {:?}", FanLevel::from(preset));
self.set_pstate_for_fan_mode(&mode, config)?;
self.set_fan_curve_for_fan_mode(&mode, config)?;
Ok(())
}
fn handle_profile_event(
&mut self,
event: &ProfileEvent,
config: &mut Config,
) -> Result<(), RogError> {
match event {
ProfileEvent::Toggle => self.do_update(config)?,
ProfileEvent::ChangeMode(mode) => {
self.set_fan_mode(*mode, config)?;
}
ProfileEvent::Cli(command) => {
let profile_key = match command.profile.as_ref() {
Some(k) => k.clone(),
None => config.active_profile.clone(),
};
let mut profile = if command.create {
config
.power_profiles
.entry(profile_key.clone())
.or_insert_with(Profile::default)
} else {
config
.power_profiles
.get_mut(&profile_key)
.ok_or_else(|| RogError::MissingProfile(profile_key.clone()))?
};
if command.turbo.is_some() {
profile.turbo = command.turbo.unwrap();
}
if let Some(min_perc) = command.min_percentage {
profile.min_percentage = min_perc;
}
if let Some(max_perc) = command.max_percentage {
profile.max_percentage = max_perc;
}
if let Some(ref preset) = command.preset {
profile.fan_preset = preset.into();
}
if let Some(ref curve) = command.curve {
profile.fan_curve = Some(curve.clone());
}
self.set(&profile_key, config)?;
}
}
Ok(())
}
fn set(&mut self, profile: &str, config: &mut Config) -> Result<(), RogError> {
let mode_config = config
.power_profiles
.get(profile)
.ok_or_else(|| RogError::MissingProfile(profile.into()))?;
let mut fan_ctrl = OpenOptions::new()
.write(true)
.open(self.path)
.map_err(|err| RogError::Path(self.path.into(), err))?;
fan_ctrl
.write_all(format!("{}\n", mode_config.fan_preset).as_bytes())
.map_err(|err| RogError::Write(self.path.into(), err))?;
config.power_profile = mode_config.fan_preset;
self.set_pstate_for_fan_mode(profile, config)?;
self.set_fan_curve_for_fan_mode(profile, config)?;
config.active_profile = profile.into();
config.write();
Ok(())
}
fn set_pstate_for_fan_mode(&self, mode: &str, config: &mut Config) -> Result<(), RogError> {
info!("Setting pstate");
let mode_config = config
.power_profiles
.get(mode)
.ok_or_else(|| RogError::MissingProfile(mode.into()))?;
// Set CPU pstate
if let Ok(pstate) = intel_pstate::PState::new() {
pstate.set_min_perf_pct(mode_config.min_percentage)?;
pstate.set_max_perf_pct(mode_config.max_percentage)?;
pstate.set_no_turbo(!mode_config.turbo)?;
info!(
"Intel CPU Power: min: {}%, max: {}%, turbo: {}",
mode_config.min_percentage, mode_config.max_percentage, mode_config.turbo
);
} else {
info!("Setting pstate for AMD CPU");
// must be AMD CPU
let mut file = OpenOptions::new()
.write(true)
.open(AMD_BOOST_PATH)
.map_err(|err| RogError::Path(self.path.into(), err))?;
let boost = if mode_config.turbo { "1" } else { "0" }; // opposite of Intel
file.write_all(boost.as_bytes())
.map_err(|err| RogError::Write(AMD_BOOST_PATH.into(), err))?;
info!("AMD CPU Turbo: {}", boost);
}
Ok(())
}
fn set_fan_curve_for_fan_mode(&self, mode: &str, config: &Config) -> Result<(), RogError> {
let mode_config = &config
.power_profiles
.get(mode)
.ok_or_else(|| RogError::MissingProfile(mode.into()))?;
if let Some(ref curve) = mode_config.fan_curve {
use rog_fan_curve::{Board, Fan};
if let Some(board) = Board::from_board_name() {
curve.apply(board, Fan::Cpu)?;
curve.apply(board, Fan::Gpu)?;
} else {
warn!("Fan curve unsupported on this board.")
}
}
Ok(())
}
}
use crate::error::RogError;
#[derive(Debug)]
pub enum FanLevel {
Normal,
Boost,
Silent,
}
impl FromStr for FanLevel {
type Err = RogError;
fn from_str(s: &str) -> Result<Self, RogError> {
match s.to_lowercase().as_str() {
"normal" => Ok(FanLevel::Normal),
"boost" => Ok(FanLevel::Boost),
"silent" => Ok(FanLevel::Silent),
_ => Err(RogError::ParseFanLevel),
}
}
}
impl From<u8> for FanLevel {
fn from(n: u8) -> Self {
match n {
0 => FanLevel::Normal,
1 => FanLevel::Boost,
2 => FanLevel::Silent,
_ => FanLevel::Normal,
}
}
}
impl From<FanLevel> for u8 {
fn from(n: FanLevel) -> Self {
match n {
FanLevel::Normal => 0,
FanLevel::Boost => 1,
FanLevel::Silent => 2,
}
}
}

View File

@@ -1,394 +0,0 @@
// Only these two packets must be 17 bytes
static LED_APPLY: [u8; 17] = [0x5d, 0xb4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
static LED_SET: [u8; 17] = [0x5d, 0xb5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
use crate::{config::Config, error::RogError, laptops::HELP_ADDRESS};
use asus_nb::{aura_brightness_bytes, aura_modes::AuraModes, fancy::KeyColourArray, LED_MSG_LEN};
use log::{info, warn};
use std::convert::TryInto;
use std::fs::OpenOptions;
use std::io::{Read, Write};
use std::sync::Arc;
use std::sync::Mutex;
use zbus::dbus_interface;
pub struct CtrlKbdBacklight {
led_node: Option<String>,
#[allow(dead_code)]
kbd_node: Option<String>,
pub bright_node: String,
supported_modes: Vec<u8>,
flip_effect_write: bool,
config: Arc<Mutex<Config>>,
}
pub struct DbusKbdBacklight {
inner: Arc<Mutex<CtrlKbdBacklight>>,
}
impl DbusKbdBacklight {
pub fn new(inner: Arc<Mutex<CtrlKbdBacklight>>) -> Self {
Self { inner }
}
}
trait Dbus {
fn set_led(&mut self, data: String);
fn ledmode(&self) -> String;
fn notify_led(&self, data: &str) -> zbus::Result<()>;
}
impl crate::ZbusAdd for DbusKbdBacklight {
fn add_to_server(self, server: &mut zbus::ObjectServer) {
server
.at(&"/org/asuslinux/Led".try_into().unwrap(), self)
.unwrap();
}
}
#[dbus_interface(name = "org.asuslinux.Daemon")]
impl DbusKbdBacklight {
fn set_led_mode(&mut self, data: String) {
if let Ok(data) = serde_json::from_str(&data) {
if let Ok(mut ctrl) = self.inner.try_lock() {
if let Ok(mut cfg) = ctrl.config.clone().try_lock() {
match &data {
AuraModes::PerKey(_) => {
ctrl.do_command(data, &mut cfg)
.unwrap_or_else(|err| warn!("{}", err));
}
_ => {
let json = serde_json::to_string(&data).unwrap();
ctrl.do_command(data, &mut cfg)
.unwrap_or_else(|err| warn!("{}", err));
self.notify_led(&json).unwrap();
}
}
}
}
} else {
warn!("SetKeyBacklight could not deserialise");
}
}
fn led_mode(&self) -> String {
if let Ok(ctrl) = self.inner.try_lock() {
if let Ok(cfg) = ctrl.config.clone().try_lock() {
if let Some(mode) = cfg.get_led_mode_data(cfg.kbd_backlight_mode) {
if let Ok(json) = serde_json::to_string(&mode) {
return json;
}
}
}
}
warn!("SetKeyBacklight could not deserialise");
"SetKeyBacklight could not deserialise".to_string()
}
fn led_modes(&self) -> String {
if let Ok(ctrl) = self.inner.try_lock() {
if let Ok(cfg) = ctrl.config.clone().try_lock() {
if let Ok(json) = serde_json::to_string(&cfg.kbd_backlight_modes) {
return json;
}
}
}
warn!("SetKeyBacklight could not deserialise");
"SetKeyBacklight could not deserialise".to_string()
}
#[dbus_interface(signal)]
fn notify_led(&self, data: &str) -> zbus::Result<()>;
}
impl crate::Reloadable for CtrlKbdBacklight {
fn reload(&mut self) -> Result<(), RogError> {
// set current mode (if any)
if let Ok(mut config) = self.config.clone().try_lock() {
if self.supported_modes.len() > 1 {
if self.supported_modes.contains(&config.kbd_backlight_mode) {
let mode = config
.get_led_mode_data(config.kbd_backlight_mode)
.ok_or(RogError::NotSupported)?
.to_owned();
self.write_mode(&mode)?;
info!("Reloaded last used mode");
} else {
warn!(
"An unsupported mode was set: {}, reset to first mode available",
<&str>::from(&<AuraModes>::from(config.kbd_backlight_mode))
);
for (idx, mode) in config.kbd_backlight_modes.iter_mut().enumerate() {
if !self.supported_modes.contains(&mode.into()) {
config.kbd_backlight_modes.remove(idx);
config.write();
break;
}
}
config.kbd_backlight_mode = self.supported_modes[0];
// TODO: do a recursive call with a boxed dyn future later
let mode = config
.get_led_mode_data(config.kbd_backlight_mode)
.ok_or(RogError::NotSupported)?
.to_owned();
self.write_mode(&mode)?;
info!("Reloaded last used mode");
}
}
// Reload brightness
let bright = config.kbd_led_brightness;
let bytes = aura_brightness_bytes(bright);
self.write_bytes(&bytes)?;
info!("Reloaded last used brightness");
}
Ok(())
}
}
impl crate::CtrlTask for CtrlKbdBacklight {
fn do_task(&mut self) -> Result<(), RogError> {
let mut file = OpenOptions::new()
.read(true)
.open(&self.bright_node)
.map_err(|err| RogError::Path((&self.bright_node).into(), err))?;
let mut buf = [0u8; 1];
file.read_exact(&mut buf)
.map_err(|err| RogError::Read("buffer".into(), err))?;
if let Some(num) = char::from(buf[0]).to_digit(10) {
if let Ok(mut config) = self.config.clone().try_lock() {
if config.kbd_led_brightness != num as u8 {
config.read();
config.kbd_led_brightness = num as u8;
config.write();
}
}
return Ok(());
}
Err(RogError::ParseLED)
}
}
impl CtrlKbdBacklight {
#[inline]
pub fn new(
id_product: &str,
condev_iface: Option<&String>,
supported_modes: Vec<u8>,
config: Arc<Mutex<Config>>,
) -> Self {
// TODO: return error if *all* nodes are None
CtrlKbdBacklight {
led_node: Self::get_node_failover(id_product, None, Self::scan_led_node).ok(),
kbd_node: Self::get_node_failover(id_product, condev_iface, Self::scan_kbd_node).ok(),
// TODO: Check for existance
bright_node: "/sys/class/leds/asus::kbd_backlight/brightness".to_string(),
supported_modes,
flip_effect_write: false,
config,
}
}
fn get_node_failover(
id_product: &str,
iface: Option<&String>,
fun: fn(&str, Option<&String>) -> Result<String, RogError>,
) -> Result<String, RogError> {
for n in 0..=2 {
// 0,1,2 inclusive
match fun(id_product, iface) {
Ok(o) => return Ok(o),
Err(e) => {
if n == 2 {
warn!("Looking for node: {}", e.to_string());
std::thread::sleep(std::time::Duration::from_secs(1));
} else {
break;
}
}
}
}
// Shouldn't be possible to reach this...
Err(RogError::NotFound(format!("{}, {:?}", id_product, iface)))
}
fn scan_led_node(id_product: &str, _: Option<&String>) -> Result<String, RogError> {
let mut enumerator = udev::Enumerator::new().map_err(|err| {
warn!("{}", err);
RogError::Udev("enumerator failed".into(), err)
})?;
enumerator.match_subsystem("hidraw").map_err(|err| {
warn!("{}", err);
RogError::Udev("match_subsystem failed".into(), err)
})?;
for device in enumerator.scan_devices().map_err(|err| {
warn!("{}", err);
RogError::Udev("scan_devices failed".into(), err)
})? {
if let Some(parent) = device
.parent_with_subsystem_devtype("usb", "usb_device")
.map_err(|err| {
warn!("{}", err);
RogError::Udev("parent_with_subsystem_devtype failed".into(), err)
})?
{
if parent.attribute_value("idProduct").unwrap() == id_product {
// && device.parent().unwrap().sysnum().unwrap() == 3
if let Some(dev_node) = device.devnode() {
info!("Using device at: {:?} for LED control", dev_node);
return Ok(dev_node.to_string_lossy().to_string());
}
}
}
}
warn!("Did not find a hidraw node for LED control, your device may be unsupported or require a kernel patch, see: {}", HELP_ADDRESS);
Err(RogError::MissingFunction(
"ASUS LED device node not found".into(),
))
}
fn scan_kbd_node(id_product: &str, iface: Option<&String>) -> Result<String, RogError> {
let mut enumerator = udev::Enumerator::new().map_err(|err| {
warn!("{}", err);
RogError::Udev("enumerator failed".into(), err)
})?;
enumerator.match_subsystem("input").map_err(|err| {
warn!("{}", err);
RogError::Udev("match_subsystem failed".into(), err)
})?;
enumerator
.match_property("ID_MODEL_ID", id_product)
.map_err(|err| {
warn!("{}", err);
RogError::Udev("match_property failed".into(), err)
})?;
for device in enumerator.scan_devices().map_err(|err| {
warn!("{}", err);
err
}).map_err(|err| {
warn!("{}", err);
RogError::Udev("scan_devices failed".into(), err)
})? {
if let Some(dev_node) = device.devnode() {
if let Some(inum) = device.property_value("ID_USB_INTERFACE_NUM") {
if let Some(iface) = iface {
if inum == iface.as_str() {
info!("Using device at: {:?} for keyboard polling", dev_node);
return Ok(dev_node.to_string_lossy().to_string());
}
}
}
}
}
warn!("Did not find keyboard consumer device node, if expected functions are missing please file an issue at {}", HELP_ADDRESS);
Err(RogError::MissingFunction(
"ASUS keyboard 'Consumer Device' node not found".into(),
))
}
pub fn do_command(&mut self, mode: AuraModes, config: &mut Config) -> Result<(), RogError> {
self.set_and_save(mode, config)
}
/// Should only be used if the bytes you are writing are verified correct
#[inline]
fn write_bytes(&self, message: &[u8]) -> Result<(), RogError> {
if let Some(led_node) = &self.led_node {
if let Ok(mut file) = OpenOptions::new().write(true).open(led_node) {
file.write_all(message).unwrap();
return Ok(());
}
}
Err(RogError::NotSupported)
}
/// Write an effect block
#[inline]
fn write_effect(&mut self, effect: &[Vec<u8>]) -> Result<(), RogError> {
if self.flip_effect_write {
for row in effect.iter().rev() {
self.write_bytes(row)?;
}
} else {
for row in effect.iter() {
self.write_bytes(row)?;
}
}
self.flip_effect_write = !self.flip_effect_write;
Ok(())
}
/// Used to set a builtin mode and save the settings for it
///
/// This needs to be universal so that settings applied by dbus stick
#[inline]
fn set_and_save(&mut self, mode: AuraModes, config: &mut Config) -> Result<(), RogError> {
match mode {
AuraModes::LedBrightness(n) => {
let bytes: [u8; LED_MSG_LEN] = (&mode).into();
self.write_bytes(&bytes)?;
config.read();
config.kbd_led_brightness = n;
config.write();
info!("LED brightness set to {:#?}", n);
}
AuraModes::PerKey(v) => {
if v.is_empty() || v[0].is_empty() {
let bytes = KeyColourArray::get_init_msg();
self.write_bytes(&bytes)?;
} else {
self.write_effect(&v)?;
}
}
_ => {
config.read();
let mode_num: u8 = u8::from(&mode);
self.write_mode(&mode)?;
config.kbd_backlight_mode = mode_num;
config.set_mode_data(mode);
config.write();
}
}
Ok(())
}
#[inline]
fn write_mode(&mut self, mode: &AuraModes) -> Result<(), RogError> {
match mode {
AuraModes::PerKey(v) => {
if v.is_empty() || v[0].is_empty() {
let bytes = KeyColourArray::get_init_msg();
self.write_bytes(&bytes)?;
} else {
self.write_effect(v)?;
}
}
_ => {
let mode_num: u8 = u8::from(mode);
match mode {
AuraModes::MultiStatic(_) => {
if self.supported_modes.contains(&mode_num) {
let bytes: [[u8; LED_MSG_LEN]; 4] = mode.into();
for array in bytes.iter() {
self.write_bytes(array)?;
}
}
}
_ => {
if self.supported_modes.contains(&mode_num) {
let bytes: [u8; LED_MSG_LEN] = mode.into();
self.write_bytes(&bytes)?;
}
}
}
self.write_bytes(&LED_SET)?;
// Changes won't persist unless apply is set
self.write_bytes(&LED_APPLY)?;
}
}
Ok(())
}
}

View File

@@ -1,139 +0,0 @@
use ctrl_gfx::ctrl_gfx::CtrlGraphics;
use daemon::config::Config;
use daemon::ctrl_anime::CtrlAnimeDisplay;
use daemon::ctrl_charge::CtrlCharge;
use daemon::ctrl_fan_cpu::{CtrlFanAndCPU, DbusFanAndCpu};
use daemon::ctrl_leds::{CtrlKbdBacklight, DbusKbdBacklight};
use daemon::laptops::match_laptop;
use asus_nb::DBUS_NAME;
use daemon::{CtrlTask, Reloadable, ZbusAdd};
use log::LevelFilter;
use log::{error, info, warn};
use std::error::Error;
use std::io::Write;
use std::sync::Arc;
use std::sync::Mutex;
use zbus::fdo;
use zbus::Connection;
pub fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut logger = env_logger::Builder::new();
logger
.target(env_logger::Target::Stdout)
.format(|buf, record| writeln!(buf, "{}: {}", record.level(), record.args()))
.filter(None, LevelFilter::Info)
.init();
info!("Version: {}", daemon::VERSION);
start_daemon()?;
Ok(())
}
// Timing is such that:
// - interrupt write is minimum 1ms (sometimes lower)
// - read interrupt must timeout, minimum of 1ms
// - for a single usb packet, 2ms total.
// - to maintain constant times of 1ms, per-key colours should use
// the effect endpoint so that the complete colour block is written
// as fast as 1ms per row of the matrix inside it. (10ms total time)
//
// DBUS processing takes 6ms if not tokiod
fn start_daemon() -> Result<(), Box<dyn Error>> {
let laptop = match_laptop();
let config = if let Some(laptop) = laptop.as_ref() {
Config::default().load(laptop.supported_modes())
} else {
Config::default().load(&[])
};
let connection = Connection::new_system()?;
fdo::DBusProxy::new(&connection)?
.request_name(DBUS_NAME, fdo::RequestNameFlags::ReplaceExisting.into())?;
let mut object_server = zbus::ObjectServer::new(&connection);
let config = Arc::new(Mutex::new(config));
match CtrlCharge::new(config.clone()) {
Ok(mut ctrl) => {
// Do a reload of any settings
ctrl.reload()
.unwrap_or_else(|err| warn!("Battery charge limit: {}", err));
// Then register to dbus server
ctrl.add_to_server(&mut object_server);
}
Err(err) => {
error!("charge_control: {}", err);
}
}
match CtrlAnimeDisplay::new() {
Ok(ctrl) => {
ctrl.add_to_server(&mut object_server);
}
Err(err) => {
error!("AniMe control: {}", err);
}
}
match CtrlGraphics::new() {
Ok(mut ctrl) => {
ctrl.reload()
.unwrap_or_else(|err| warn!("Gfx controller: {}", err));
ctrl.add_to_server(&mut object_server);
}
Err(err) => {
error!("Gfx control: {}", err);
}
}
// Collect tasks for task thread
let mut tasks: Vec<Arc<Mutex<dyn CtrlTask + Send>>> = Vec::new();
match CtrlFanAndCPU::new(config.clone()) {
Ok(mut ctrl) => {
ctrl.reload()
.unwrap_or_else(|err| warn!("Profile control: {}", err));
let tmp = Arc::new(Mutex::new(ctrl));
DbusFanAndCpu::new(tmp.clone()).add_to_server(&mut object_server);
tasks.push(tmp);
}
Err(err) => {
error!("Profile control: {}", err);
}
};
if let Some(laptop) = laptop {
let ctrl = CtrlKbdBacklight::new(
laptop.usb_product(),
laptop.condev_iface(),
laptop.supported_modes().to_owned(),
config,
);
let tmp = Arc::new(Mutex::new(ctrl));
DbusKbdBacklight::new(tmp.clone()).add_to_server(&mut object_server);
tasks.push(tmp);
}
// TODO: implement messaging between threads to check fails
// These tasks generally read a sys path or file to check for a
// change
let _handle = std::thread::Builder::new()
.name("asusd watch".to_string())
.spawn(move || loop {
std::thread::sleep(std::time::Duration::from_millis(100));
for ctrl in tasks.iter() {
if let Ok(mut lock) = ctrl.try_lock() {
lock.do_task().unwrap();
}
}
});
loop {
if let Err(err) = object_server.try_handle_next() {
eprintln!("{}", err);
}
}
}

View File

@@ -1,58 +0,0 @@
use std::fmt;
use std::convert::From;
use intel_pstate::PStateError;
use rog_fan_curve::CurveError;
#[derive(Debug)]
pub enum RogError {
ParseFanLevel,
ParseVendor,
ParseLED,
MissingProfile(String),
Udev(String, std::io::Error),
Path(String, std::io::Error),
Read(String, std::io::Error),
Write(String, std::io::Error),
NotSupported,
NotFound(String),
IntelPstate(PStateError),
FanCurve(CurveError),
DoTask(String),
MissingFunction(String),
}
impl fmt::Display for RogError {
// This trait requires `fmt` with this exact signature.
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
RogError::ParseFanLevel => write!(f, "Parse profile error"),
RogError::ParseVendor => write!(f, "Parse gfx vendor error"),
RogError::ParseLED => write!(f, "Parse LED error"),
RogError::MissingProfile(profile) => write!(f, "Profile does not exist {}", profile),
RogError::Udev(deets, error) => write!(f, "udev {}: {}", deets, error),
RogError::Path(path, error) => write!(f, "Path {}: {}", path, error),
RogError::Read(path, error) => write!(f, "Read {}: {}", path, error),
RogError::Write(path, error) => write!(f, "Write {}: {}", path, error),
RogError::NotSupported => write!(f, "Not supported"),
RogError::NotFound(deets) => write!(f, "Not found: {}", deets),
RogError::IntelPstate(err) => write!(f, "Intel pstate error: {}", err),
RogError::FanCurve(err) => write!(f, "Custom fan-curve error: {}", err),
RogError::DoTask(deets) => write!(f, "Task error: {}", deets),
RogError::MissingFunction(deets) => write!(f, "Missing functionality: {}", deets),
}
}
}
impl std::error::Error for RogError {}
impl From<PStateError> for RogError {
fn from(err: PStateError) -> Self {
RogError::IntelPstate(err)
}
}
impl From<CurveError> for RogError {
fn from(err: CurveError) -> Self {
RogError::FanCurve(err)
}
}

View File

@@ -1,144 +0,0 @@
use asus_nb::aura_modes::{AuraModes, BREATHING, STATIC, STROBE};
use log::{info, warn};
use serde_derive::{Deserialize, Serialize};
use std::fs::OpenOptions;
use std::io::Read;
pub static LEDMODE_CONFIG_PATH: &str = "/etc/asusd/asusd-ledmodes.toml";
pub static HELP_ADDRESS: &str = "https://gitlab.com/asus-linux/asus-nb-ctrl";
pub struct LaptopBase {
usb_product: String,
condev_iface: Option<String>, // required for finding the Consumer Device interface
supported_modes: Vec<u8>,
}
impl LaptopBase {
pub fn usb_product(&self) -> &str {
&self.usb_product
}
pub fn condev_iface(&self) -> Option<&String> {
self.condev_iface.as_ref()
}
pub fn supported_modes(&self) -> &[u8] {
&self.supported_modes
}
}
pub fn match_laptop() -> Option<LaptopBase> {
for device in rusb::devices().unwrap().iter() {
let device_desc = device.device_descriptor().unwrap();
if device_desc.vendor_id() == 0x0b05 {
match device_desc.product_id() {
0x1866 => {
let laptop = select_1866_device("1866".to_owned());
print_modes(&laptop.supported_modes);
return Some(laptop);
}
0x1869 => return Some(select_1866_device("1869".to_owned())),
0x1854 => {
info!("Found GL753 or similar");
return Some(LaptopBase {
usb_product: "1854".to_string(),
condev_iface: None,
supported_modes: vec![STATIC, BREATHING, STROBE],
});
}
_ => {}
}
}
}
warn!(
"Unsupported laptop, please request support at {}",
HELP_ADDRESS
);
warn!("Continuing with minimal support");
None
}
fn select_1866_device(prod: String) -> LaptopBase {
let dmi = sysfs_class::DmiId::default();
let board_name = dmi.board_name().expect("Could not get board_name");
let prod_family = dmi.product_family().expect("Could not get product_family");
let prod_name = dmi.product_name().expect("Could not get product_name");
info!("Product name: {}", prod_name.trim());
info!("Board name: {}", board_name.trim());
let mut laptop = LaptopBase {
usb_product: prod,
condev_iface: Some("02".to_owned()),
supported_modes: vec![],
};
if let Some(modes) = LEDModeGroup::load_from_config() {
if let Some(led_modes) = modes.matcher(&prod_family, &board_name) {
laptop.supported_modes = led_modes;
return laptop;
}
}
laptop
}
fn print_modes(supported_modes: &[u8]) {
if !supported_modes.is_empty() {
info!("Supported Keyboard LED modes are:");
for mode in supported_modes {
let mode = <&str>::from(&<AuraModes>::from(*mode));
info!("- {}", mode);
}
info!(
"If these modes are incorrect or missing please request support at {}",
HELP_ADDRESS
);
} else {
info!("No RGB control available");
}
}
#[derive(Debug, Deserialize, Serialize)]
struct LEDModeGroup {
led_modes: Vec<LEDModes>,
}
impl LEDModeGroup {
/// Consumes the LEDModes
fn matcher(self, prod_family: &str, board_name: &str) -> Option<Vec<u8>> {
for led_modes in self.led_modes {
if prod_family.contains(&led_modes.prod_family) {
for board in led_modes.board_names {
if board_name.contains(&board) {
info!("Matched to {} {}", led_modes.prod_family, board);
return Some(led_modes.led_modes);
}
}
}
}
None
}
fn load_from_config() -> Option<Self> {
if let Ok(mut file) = OpenOptions::new().read(true).open(&LEDMODE_CONFIG_PATH) {
let mut buf = String::new();
if let Ok(l) = file.read_to_string(&mut buf) {
if l == 0 {
warn!("{} is empty", LEDMODE_CONFIG_PATH);
} else {
return Some(toml::from_str(&buf).unwrap_or_else(|_| {
panic!("Could not deserialise {}", LEDMODE_CONFIG_PATH)
}));
}
}
}
warn!("Does {} exist?", LEDMODE_CONFIG_PATH);
None
}
}
#[derive(Debug, Deserialize, Serialize)]
struct LEDModes {
prod_family: String,
board_names: Vec<String>,
led_modes: Vec<u8>,
}

View File

@@ -1,40 +0,0 @@
#![deny(unused_must_use)]
/// Configuration loading, saving
pub mod config;
///
pub mod ctrl_anime;
///
pub mod ctrl_charge;
///
pub mod ctrl_fan_cpu;
///
pub mod ctrl_leds;
///
/// Laptop matching to determine capabilities
pub mod laptops;
mod error;
use config::Config;
use crate::error::RogError;
use zbus::ObjectServer;
pub static VERSION: &str = "2.0.0";
pub trait Reloadable {
fn reload(&mut self) -> Result<(), RogError>;
}
pub trait ZbusAdd {
fn add_to_server(self, server: &mut ObjectServer);
}
pub trait CtrlTask {
fn do_task(&mut self) -> Result<(), RogError>;
}
pub trait CtrlTaskComplex {
type A;
fn do_task(&mut self, config: &mut Config, event: Self::A);
}

View File

@@ -1,133 +0,0 @@
use asus_nb::{
cli_options::{LedBrightness, SetAuraBuiltin},
core_dbus::AuraDbusClient,
profile::{ProfileCommand, ProfileEvent},
};
use ctrl_gfx::vendors::GfxVendors;
use daemon::ctrl_fan_cpu::FanLevel;
use gumdrop::Options;
use log::LevelFilter;
use std::io::Write;
use yansi_term::Colour::Green;
use yansi_term::Colour::Red;
#[derive(Options)]
struct CLIStart {
#[options(help = "print help message")]
help: bool,
#[options(help = "show program version number")]
version: bool,
#[options(meta = "VAL", help = "<off, low, med, high>")]
kbd_bright: Option<LedBrightness>,
#[options(meta = "PWR", help = "<silent, normal, boost>")]
pwr_profile: Option<FanLevel>,
#[options(meta = "CHRG", help = "<20-100>")]
chg_limit: Option<u8>,
#[options(help = "Set graphics mode: <nvidia, hybrid, compute, integrated>")]
graphics: Option<GfxVendors>,
#[options(command)]
command: Option<Command>,
}
#[derive(Options)]
enum Command {
#[options(help = "Set the keyboard lighting from built-in modes")]
LedMode(LedModeCommand),
#[options(help = "Create and configure profiles")]
Profile(ProfileCommand),
}
#[derive(Options)]
struct LedModeCommand {
#[options(help = "print help message")]
help: bool,
#[options(command, required)]
command: Option<SetAuraBuiltin>,
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut logger = env_logger::Builder::new();
logger
.target(env_logger::Target::Stdout)
.format(|buf, record| writeln!(buf, "{}: {}", record.level(), record.args()))
.filter(None, LevelFilter::Info)
.init();
let parsed = CLIStart::parse_args_default_or_exit();
if parsed.version {
println!("Version: {}", daemon::VERSION);
}
let writer = AuraDbusClient::new()?;
match parsed.command {
Some(Command::LedMode(mode)) => {
if let Some(command) = mode.command {
writer.write_builtin_mode(&command.into())?
}
}
Some(Command::Profile(command)) => {
writer.write_profile_command(&ProfileEvent::Cli(command))?
}
None => (),
}
if let Some(brightness) = parsed.kbd_bright {
writer.write_brightness(brightness.level())?;
}
if let Some(fan_level) = parsed.pwr_profile {
writer.write_fan_mode(fan_level.into())?;
}
if let Some(chg_limit) = parsed.chg_limit {
writer.write_charge_limit(chg_limit)?;
}
if let Some(gfx) = parsed.graphics {
println!("Updating settings, please wait...");
println!("If this takes longer than 30s, ctrl+c then check journalctl");
writer.write_gfx_mode(gfx)?;
let res = writer.wait_gfx_changed()?;
match res.as_str() {
"reboot" => println!(
"{}\n{}",
Green.paint("\nGraphics vendor mode changed successfully\n"),
Red.paint("\nPlease reboot to complete switch to iGPU\n")
),
"restartx" => {
println!(
"{}",
Green.paint("\nGraphics vendor mode changed successfully\n")
);
restart_x()?;
std::process::exit(1)
}
_ => std::process::exit(-1),
}
std::process::exit(-1)
}
Ok(())
}
fn restart_x() -> Result<(), Box<dyn std::error::Error>> {
println!("Restart X server? y/n");
let mut buf = String::new();
std::io::stdin().read_line(&mut buf).expect("Input failed");
let input = buf.chars().next().unwrap() as char;
if input == 'Y' || input == 'y' {
println!("Restarting X server");
let status = std::process::Command::new("systemctl")
.arg("restart")
.arg("display-manager.service")
.status()?;
if !status.success() {
println!("systemctl: display-manager returned with {}", status);
}
} else {
println!("{}", Red.paint("Cancelled. Please restart X when ready"));
}
Ok(())
}

View File

@@ -1,25 +0,0 @@
[package]
name = "asus-nb"
version = "2.0.0"
license = "MPL-2.0"
readme = "README.md"
authors = ["Luke <luke@ljones.dev>"]
repository = "https://gitlab.com/asus-linux/asus-nb-ctrl"
homepage = "https://gitlab.com/asus-linux/asus-nb-ctrl"
description = "A small library of effect types and conversions for ROG Aura"
edition = "2018"
[dependencies]
gumdrop = "^0.8"
dbus = { version = "^0.8" }
serde = "^1.0"
serde_derive = "^1.0"
serde_json = "^1.0"
yansi-term = "^0.1"
rog_fan_curve = { version = "0.1", features = ["serde"] }
zbus = "1.1.1"
zvariant = "2.2.0"
ctrl-gfx = { path = "../ctrl-gfx" }
[dev-dependencies]
tinybmp = "^0.2.3"

View File

@@ -1,41 +0,0 @@
use asus_nb::anime_dbus::AniMeDbusWriter;
use asus_nb::anime_matrix::{AniMeMatrix, AniMePacketType, HEIGHT, WIDTH};
use tinybmp::{Bmp, Pixel};
fn main() {
let mut writer = AniMeDbusWriter::new().unwrap();
let bmp =
Bmp::from_slice(include_bytes!("non-skewed_r.bmp")).expect("Failed to parse BMP image");
let pixels: Vec<Pixel> = bmp.into_iter().collect();
//assert_eq!(pixels.len(), 56 * 56);
// Try an outline, top and right
let mut matrix = AniMeMatrix::new();
// Aligned left
for px in pixels {
if (px.x as usize / 2) < WIDTH && (px.y as usize) < HEIGHT && px.x % 2 == 0 {
matrix.get_mut()[px.y as usize][px.x as usize / 2] = px.color as u8;
}
}
// Throw an alignment border up
// {
// let tmp = matrix.get_mut();
// for x in tmp[0].iter_mut() {
// *x = 0xff;
// }
// for row in tmp.iter_mut() {
// row[row.len() - 1] = 0xff;
// }
// }
matrix.debug_print();
let mut matrix: AniMePacketType = AniMePacketType::from(matrix);
// println!("{:?}", matrix[0].to_vec());
// println!("{:?}", matrix[1].to_vec());
writer.write_image(&mut matrix).unwrap();
}

View File

@@ -1,98 +0,0 @@
use asus_nb::{
core_dbus::AuraDbusClient,
fancy::{GX502Layout, Key, KeyColourArray, KeyLayout},
};
use std::collections::LinkedList;
#[derive(Debug, Clone)]
struct Ball {
position: (i32, i32),
direction: (i32, i32),
trail: LinkedList<(i32, i32)>,
}
impl Ball {
fn new(x: i32, y: i32, trail_len: u32) -> Self {
let mut trail = LinkedList::new();
for _ in 1..=trail_len {
trail.push_back((x, y));
}
Ball {
position: (x, y),
direction: (1, 1),
trail,
}
}
#[allow(clippy::if_same_then_else)]
fn update(&mut self, key_map: &[[Key; 17]]) {
let pos = self.position;
let dir = self.direction;
if pos.0 + dir.0 > key_map[pos.1 as usize].len() as i32 - 1 || pos.0 + dir.0 < 0 {
self.direction.0 *= -1;
} else if key_map[(pos.1) as usize][(pos.0 + dir.0) as usize] == Key::None {
self.direction.0 *= -1;
}
if pos.1 + dir.1 > key_map.len() as i32 - 1 || pos.1 + dir.1 < 0 {
self.direction.1 *= -1;
} else if key_map[(pos.1 + dir.1) as usize][(pos.0) as usize] == Key::None {
self.direction.1 *= -1;
}
self.trail.pop_front();
self.trail.push_back(self.position);
self.position.0 += self.direction.0;
self.position.1 += self.direction.1;
if self.position.0 > key_map[self.position.1 as usize].len() as i32 {
self.position.0 = key_map[self.position.1 as usize].len() as i32 - 1;
}
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut writer = AuraDbusClient::new()?;
let mut colours = KeyColourArray::new();
let layout = GX502Layout::default();
let mut balls = [Ball::new(2, 1, 12), Ball::new(4, 6, 12)];
writer.init_effect()?;
let rows = layout.get_rows();
loop {
for (n, ball) in balls.iter_mut().enumerate() {
ball.update(rows);
for (i, pos) in ball.trail.iter().enumerate() {
if let Some(c) = colours.key(rows[pos.1 as usize][pos.0 as usize]) {
*c.0 = 0;
*c.1 = 0;
*c.2 = 0;
if n == 0 {
*c.0 = i as u8 * (255 / ball.trail.len() as u8);
} else if n == 1 {
*c.1 = i as u8 * (255 / ball.trail.len() as u8);
} else if n == 2 {
*c.2 = i as u8 * (255 / ball.trail.len() as u8);
}
};
}
if let Some(c) = colours.key(rows[ball.position.1 as usize][ball.position.0 as usize]) {
*c.0 = 255;
*c.1 = 255;
*c.2 = 255;
};
}
writer.write_colour_block(&colours)?;
// can change 100 times per second, so need to slow it down
std::thread::sleep(std::time::Duration::from_millis(30));
}
}

View File

@@ -1,31 +0,0 @@
use asus_nb::{
core_dbus::AuraDbusClient,
fancy::{GX502Layout, KeyColourArray, KeyLayout},
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut writer = AuraDbusClient::new()?;
let layout = GX502Layout::default();
writer.init_effect()?;
let rows = layout.get_rows();
let mut column = 0;
loop {
let mut key_colours = KeyColourArray::new();
for row in rows {
if let Some(c) = key_colours.key(row[column as usize]) {
*c.0 = 255;
};
}
if column == rows[0].len() - 1 {
column = 0
} else {
column += 1;
}
writer.write_colour_block(&key_colours)?;
std::thread::sleep(std::time::Duration::from_millis(30));
}
}

View File

@@ -1,56 +0,0 @@
use asus_nb::{
core_dbus::AuraDbusClient,
fancy::{GX502Layout, Key, KeyColourArray, KeyLayout},
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut writer = AuraDbusClient::new()?;
let mut key_colours = KeyColourArray::new();
let layout = GX502Layout::default();
writer.init_effect()?;
let rows = layout.get_rows();
loop {
for (r, row) in rows.iter().enumerate() {
for (k, key) in row.iter().enumerate() {
if let Some(c) = key_colours.key(*key) {
*c.0 = 255;
};
// Last key of previous row
if k == 0 {
if r == 0 {
let k = &rows[rows.len() - 1][rows[rows.len() - 1].len() - 1];
if let Some(c) = key_colours.key(*k) {
*c.0 = 0;
};
} else {
let k = &rows[r - 1][rows[r - 1].len() - 1];
if let Some(c) = key_colours.key(*k) {
*c.0 = 0;
};
}
} else {
let k = &rows[r][k - 1];
if let Some(c) = key_colours.key(*k) {
*c.0 = 0;
};
}
if let Some(c) = key_colours.key(Key::Up) {
*c.0 = 255;
};
*key_colours.key(Key::Left).unwrap().0 = 255;
*key_colours.key(Key::Right).unwrap().0 = 255;
*key_colours.key(Key::Down).unwrap().0 = 255;
*key_colours.key(Key::W).unwrap().0 = 255;
*key_colours.key(Key::A).unwrap().0 = 255;
*key_colours.key(Key::S).unwrap().0 = 255;
*key_colours.key(Key::D).unwrap().0 = 255;
writer.write_colour_block(&key_colours)?;
std::thread::sleep(std::time::Duration::from_millis(100));
}
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -1,33 +0,0 @@
use asus_nb::{
core_dbus::AuraDbusClient,
fancy::{Key, KeyColourArray},
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut writer = AuraDbusClient::new()?;
let mut key_colours = KeyColourArray::new();
writer.init_effect()?;
loop {
let count = 49;
for _ in 0..count {
*key_colours.key(Key::ROG).unwrap().0 += 5;
*key_colours.key(Key::L).unwrap().0 += 5;
*key_colours.key(Key::I).unwrap().0 += 5;
*key_colours.key(Key::N).unwrap().0 += 5;
*key_colours.key(Key::U).unwrap().0 += 5;
*key_colours.key(Key::X).unwrap().0 += 5;
writer.write_colour_block(&key_colours)?;
}
for _ in 0..count {
*key_colours.key(Key::ROG).unwrap().0 -= 5;
*key_colours.key(Key::L).unwrap().0 -= 5;
*key_colours.key(Key::I).unwrap().0 -= 5;
*key_colours.key(Key::N).unwrap().0 -= 5;
*key_colours.key(Key::U).unwrap().0 -= 5;
*key_colours.key(Key::X).unwrap().0 -= 5;
writer.write_colour_block(&key_colours)?;
}
}
}

View File

@@ -1,40 +0,0 @@
use asus_nb::{
core_dbus::AuraDbusClient,
fancy::{GX502Layout, KeyColourArray, KeyLayout},
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut writer = AuraDbusClient::new()?;
let mut key_colours = KeyColourArray::new();
let layout = GX502Layout::default();
writer.init_effect()?;
let rows = layout.get_rows();
let mut fade = 50;
let mut flip = false;
loop {
for row in rows {
for (k, key) in row.iter().enumerate() {
if let Some(c) = key_colours.key(*key) {
*c.0 = 255 / fade / (k + 1) as u8;
};
}
}
writer.write_colour_block(&key_colours)?;
if flip {
if fade > 1 {
fade -= 1;
} else {
flip = !flip;
}
} else if fade < 17 {
fade += 1;
} else {
flip = !flip;
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

View File

@@ -1,79 +0,0 @@
use crate::anime_matrix::AniMePacketType;
use crate::{DBUS_IFACE, DBUS_NAME};
use dbus::channel::Sender;
use dbus::{blocking::Connection, Message};
use std::error::Error;
use std::sync::{
atomic::{AtomicBool, Ordering},
Arc,
};
use std::{thread, time::Duration};
pub const ANIME_PANE1_PREFIX: [u8; 7] = [0x5e, 0xc0, 0x02, 0x01, 0x00, 0x73, 0x02];
pub const ANIME_PANE2_PREFIX: [u8; 7] = [0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02];
/// Interface for the AniMe dot-matrix display
///
/// The resolution is 34x56 (1904) but only 1,215 LEDs in the top-left are used.
/// The display is available only on select GA401 models.
///
/// Actual image ration when displayed is stretched width.
///
/// Data structure should be nested array of [[u8; 33]; 56]
pub struct AniMeDbusWriter {
connection: Box<Connection>,
block_time: u64,
stop: Arc<AtomicBool>,
}
impl AniMeDbusWriter {
#[inline]
pub fn new() -> Result<Self, Box<dyn Error>> {
let connection = Connection::new_system()?;
Ok(AniMeDbusWriter {
connection: Box::new(connection),
block_time: 25,
stop: Arc::new(AtomicBool::new(false)),
})
}
pub fn write_image_to_buf(_buf: &mut AniMePacketType, _image_data: &[u8]) {
unimplemented!("Image format is in progress of being worked out")
}
/// Write an Animatrix image
///
/// The expected input here is *two* Vectors, 640 bytes in length. The two vectors
/// are each one half of the full image write.
///
/// After each write a flush is written, it is assumed that this tells the device to
/// go ahead and display the written bytes
///
/// # Note:
/// The vectors are expected to contain the full sequence of bytes as follows
///
/// - Write packet 1: 0x5e 0xc0 0x02 0x01 0x00 0x73 0x02 .. <led brightness>
/// - Write packet 2: 0x5e 0xc0 0x02 0x74 0x02 0x73 0x02 .. <led brightness>
///
/// Where led brightness is 0..255, low to high
#[inline]
pub fn write_image(&mut self, image: &mut AniMePacketType) -> Result<(), Box<dyn Error>> {
if image[0][0] != ANIME_PANE1_PREFIX[0] && image[0][6] != ANIME_PANE1_PREFIX[6] {
image[0][..7].copy_from_slice(&ANIME_PANE1_PREFIX);
}
if image[1][0] != ANIME_PANE2_PREFIX[0] && image[1][6] != ANIME_PANE2_PREFIX[6] {
image[1][..7].copy_from_slice(&ANIME_PANE2_PREFIX);
}
let mut msg =
Message::new_method_call(DBUS_NAME, "/org/asuslinux/Anime", DBUS_IFACE, "SetAnime")?
.append2(image[0].to_vec(), image[1].to_vec());
msg.set_no_reply(true);
self.connection.send(msg).unwrap();
thread::sleep(Duration::from_millis(self.block_time));
if self.stop.load(Ordering::Relaxed) {
panic!("Got signal to stop!");
}
Ok(())
}
}

View File

@@ -1,236 +0,0 @@
pub const WIDTH: usize = 34; // Width is definitely 34 items
pub const HEIGHT: usize = 56;
pub type AniMeBufferType = [[u8; WIDTH]; HEIGHT];
pub type AniMePacketType = [[u8; 640]; 2];
const BLOCK_START: usize = 7;
const BLOCK_END: usize = 634;
use yansi_term::Colour::RGB;
/// Helper structure for writing images.
///
/// See the examples for ways to write an image to `AniMeMatrix` format.
pub struct AniMeMatrix(AniMeBufferType);
impl Default for AniMeMatrix {
fn default() -> Self {
Self::new()
}
}
impl AniMeMatrix {
pub fn new() -> Self {
AniMeMatrix([[0u8; WIDTH]; HEIGHT])
}
pub fn get(&self) -> &AniMeBufferType {
&self.0
}
pub fn get_mut(&mut self) -> &mut AniMeBufferType {
&mut self.0
}
pub fn fill_with(&mut self, fill: u8) {
for row in self.0.iter_mut() {
for x in row.iter_mut() {
*x = fill;
}
}
}
pub fn debug_print(&self) {
// this is the index from right. It is used to progressively shorten rows
let mut prog_row_len = WIDTH - 2;
for (count, row) in self.0.iter().enumerate() {
// Write the top block of LEDs (first 7 rows)
if count < 6 {
if count % 2 != 0 {
print!(" ");
} else {
print!(" ");
}
let tmp = if count == 0 || count == 1 || count == 3 || count == 5 {
row[1..].iter()
} else {
row.iter()
};
for x in tmp {
print!(" {}", RGB(*x, *x, *x).paint(&format!("{:#04X}", x)));
}
println!();
} else {
// Switch to next block (looks like )
if count % 2 != 0 {
// Row after 6 is only 1 less, then rows after 7 follow pattern
if count == 7 {
prog_row_len -= 1;
} else {
prog_row_len -= 2;
}
} else {
prog_row_len += 1; // if count 6, 0
}
let index = row.len() - prog_row_len;
if count % 2 == 0 {
print!(" ");
}
for (i, x) in row.iter().enumerate() {
if i >= index {
print!(" {}", RGB(*x, *x, *x).paint(&format!("{:#04X}", x)));
} else {
print!(" ");
}
}
println!();
}
}
}
}
impl From<AniMeMatrix> for AniMePacketType {
/// Do conversion from the nested Vec in AniMeMatrix to the two required
/// packets suitable for sending over USB
#[inline]
fn from(anime: AniMeMatrix) -> Self {
let mut buffers = [[0; 640]; 2];
let mut write_index = BLOCK_START;
let mut write_block = &mut buffers[0];
let mut block1_done = false;
// this is the index from right. It is used to progressively shorten rows
let mut prog_row_len = WIDTH - 2;
for (count, row) in anime.0.iter().enumerate() {
// Write the top block of LEDs (first 7 rows)
if count < 6 {
for (i, x) in row.iter().enumerate() {
// Rows 0, 1, 3, 5 are short and misaligned
if count == 0 || count == 1 || count == 3 || count == 5 {
if i > 0 {
write_block[write_index - 1] = *x;
}
} else {
write_block[write_index] = *x;
}
write_index += 1;
}
} else {
// Switch to next block (looks like )
if count % 2 != 0 {
// Row after 6 is only 1 less, then rows after 7 follow pattern
if count == 7 {
prog_row_len -= 1;
} else {
prog_row_len -= 2;
}
} else {
prog_row_len += 1; // if count 6, 0
}
let index = row.len() - prog_row_len;
for n in row.iter().skip(index) {
// Require a special case to catch the correct end-of-packet which is
// 6 bytes from the end
if write_index == BLOCK_END && !block1_done {
block1_done = true;
write_block = &mut buffers[1];
write_index = BLOCK_START;
}
write_block[write_index] = *n;
write_index += 1;
}
}
}
buffers
}
}
#[cfg(test)]
mod tests {
use crate::anime_matrix::{AniMeMatrix, AniMePacketType};
#[test]
fn check_data_alignment() {
let mut matrix = AniMeMatrix::new();
{
let tmp = matrix.get_mut();
for row in tmp.iter_mut() {
row[row.len() - 1] = 0xff;
}
}
let matrix: AniMePacketType = AniMePacketType::from(matrix);
// The bytes at the right of the initial AniMeMatrix should always end up aligned in the
// same place after conversion to data packets
// Check against manually worked out right align
assert_eq!(
matrix[0].to_vec(),
[
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0,
0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0,
0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 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, 0, 0, 0, 0,
0, 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, 0, 0, 0, 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, 0, 0, 0, 0, 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, 0, 0, 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, 0, 0, 0, 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, 0, 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, 0, 0, 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, 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, 0, 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, 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
]
.to_vec()
);
assert_eq!(
matrix[1].to_vec(),
[
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 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, 0, 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, 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, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0,
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,
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,
0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 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, 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, 0, 0, 0, 0, 255, 0, 0, 0, 0, 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, 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, 0, 0, 0, 255, 0, 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, 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, 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, 0, 0, 0, 0, 0, 255, 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, 0, 0, 0, 0,
255, 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,
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, 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, 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, 255, 0, 0, 0,
0, 0, 0, 0
]
.to_vec()
);
}
}

View File

@@ -1,287 +0,0 @@
use crate::cli_options;
use crate::cli_options::SetAuraBuiltin;
use serde_derive::{Deserialize, Serialize};
pub const STATIC: u8 = 0x00;
pub const BREATHING: u8 = 0x01;
pub const STROBE: u8 = 0x02;
pub const RAINBOW: u8 = 0x03;
pub const STAR: u8 = 0x04;
pub const RAIN: u8 = 0x05;
pub const HIGHLIGHT: u8 = 0x06;
pub const LASER: u8 = 0x07;
pub const RIPPLE: u8 = 0x08;
pub const PULSE: u8 = 0x0a;
pub const COMET: u8 = 0x0b;
pub const FLASH: u8 = 0x0c;
pub const MULTISTATIC: u8 = 0x0d;
pub const PER_KEY: u8 = 0xff;
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Colour(pub u8, pub u8, pub u8);
impl From<cli_options::Colour> for Colour {
fn from(c: cli_options::Colour) -> Self {
Colour(c.0, c.1, c.2)
}
}
impl Default for Colour {
fn default() -> Self {
Colour(128, 0, 0)
}
}
#[derive(Debug, Copy, Clone, Deserialize, Serialize)]
pub enum Speed {
Low = 0xe1,
Med = 0xeb,
High = 0xf5,
}
impl From<cli_options::Speed> for Speed {
fn from(s: cli_options::Speed) -> Self {
match s {
cli_options::Speed::Low => Speed::Low,
cli_options::Speed::Med => Speed::Med,
cli_options::Speed::High => Speed::High,
}
}
}
impl Default for Speed {
fn default() -> Self {
Speed::Med
}
}
/// Used for Rainbow mode.
///
/// Enum corresponds to the required integer value
#[derive(Debug, Copy, Clone, Deserialize, Serialize)]
pub enum Direction {
Right,
Left,
Up,
Down,
}
impl From<cli_options::Direction> for Direction {
fn from(s: cli_options::Direction) -> Self {
match s {
cli_options::Direction::Right => Direction::Right,
cli_options::Direction::Left => Direction::Left,
cli_options::Direction::Up => Direction::Up,
cli_options::Direction::Down => Direction::Down,
}
}
}
impl Default for Direction {
fn default() -> Self {
Direction::Right
}
}
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
pub struct TwoColourSpeed {
pub colour: Colour,
pub colour2: Colour,
pub speed: Speed,
}
impl From<cli_options::TwoColourSpeed> for TwoColourSpeed {
fn from(mode: cli_options::TwoColourSpeed) -> Self {
TwoColourSpeed {
colour: mode.colour.into(),
colour2: mode.colour2.into(),
speed: mode.speed.into(),
}
}
}
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
pub struct SingleSpeed {
pub speed: Speed,
}
impl From<cli_options::SingleSpeed> for SingleSpeed {
fn from(mode: cli_options::SingleSpeed) -> Self {
SingleSpeed {
speed: mode.speed.into(),
}
}
}
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
pub struct SingleColour {
pub colour: Colour,
}
impl From<cli_options::SingleColour> for SingleColour {
fn from(mode: cli_options::SingleColour) -> Self {
SingleColour {
colour: mode.colour.into(),
}
}
}
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
pub struct MultiColour {
pub colour1: Colour,
pub colour2: Colour,
pub colour3: Colour,
pub colour4: Colour,
}
impl From<cli_options::MultiColour> for MultiColour {
fn from(mode: cli_options::MultiColour) -> Self {
MultiColour {
colour1: mode.colour1.into(),
colour2: mode.colour2.into(),
colour3: mode.colour3.into(),
colour4: mode.colour4.into(),
}
}
}
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
pub struct SingleSpeedDirection {
pub direction: Direction,
pub speed: Speed,
}
impl From<cli_options::SingleSpeedDirection> for SingleSpeedDirection {
fn from(mode: cli_options::SingleSpeedDirection) -> Self {
SingleSpeedDirection {
direction: mode.direction.into(),
speed: mode.speed.into(),
}
}
}
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
pub struct SingleColourSpeed {
pub colour: Colour,
pub speed: Speed,
}
impl From<cli_options::SingleColourSpeed> for SingleColourSpeed {
fn from(mode: cli_options::SingleColourSpeed) -> Self {
SingleColourSpeed {
colour: mode.colour.into(),
speed: mode.speed.into(),
}
}
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub enum AuraModes {
Static(SingleColour),
Breathe(TwoColourSpeed),
Strobe(SingleSpeed),
Rainbow(SingleSpeedDirection),
Star(TwoColourSpeed),
Rain(SingleSpeed),
Highlight(SingleColourSpeed),
Laser(SingleColourSpeed),
Ripple(SingleColourSpeed),
Pulse(SingleColour),
Comet(SingleColour),
Flash(SingleColour),
MultiStatic(MultiColour),
LedBrightness(u8),
// TODO: use a serializable structure for this (KeyColourArray)
PerKey(Vec<Vec<u8>>),
}
impl From<SetAuraBuiltin> for AuraModes {
fn from(mode: SetAuraBuiltin) -> Self {
match mode {
SetAuraBuiltin::Static(x) => AuraModes::Static(x.into()),
SetAuraBuiltin::Breathe(x) => AuraModes::Breathe(x.into()),
SetAuraBuiltin::Strobe(x) => AuraModes::Strobe(x.into()),
SetAuraBuiltin::Rainbow(x) => AuraModes::Rainbow(x.into()),
SetAuraBuiltin::Star(x) => AuraModes::Star(x.into()),
SetAuraBuiltin::Rain(x) => AuraModes::Rain(x.into()),
SetAuraBuiltin::Highlight(x) => AuraModes::Highlight(x.into()),
SetAuraBuiltin::Laser(x) => AuraModes::Laser(x.into()),
SetAuraBuiltin::Ripple(x) => AuraModes::Ripple(x.into()),
SetAuraBuiltin::Pulse(x) => AuraModes::Pulse(x.into()),
SetAuraBuiltin::Comet(x) => AuraModes::Comet(x.into()),
SetAuraBuiltin::Flash(x) => AuraModes::Flash(x.into()),
SetAuraBuiltin::MultiStatic(x) => AuraModes::MultiStatic(x.into()),
}
}
}
/// Very specific mode conversion required because numbering isn't linear
impl From<AuraModes> for u8 {
fn from(mode: AuraModes) -> Self {
u8::from(&mode)
}
}
/// Very specific mode conversion required because numbering isn't linear
impl From<&mut AuraModes> for u8 {
fn from(mode: &mut AuraModes) -> Self {
u8::from(&*mode)
}
}
/// Very specific mode conversion required because numbering isn't linear
impl From<&AuraModes> for u8 {
fn from(mode: &AuraModes) -> Self {
match mode {
AuraModes::Static(_) => STATIC,
AuraModes::Breathe(_) => BREATHING,
AuraModes::Strobe(_) => STROBE,
AuraModes::Rainbow(_) => RAINBOW,
AuraModes::Star(_) => STAR,
AuraModes::Rain(_) => RAIN,
AuraModes::Highlight(_) => HIGHLIGHT,
AuraModes::Laser(_) => LASER,
AuraModes::Ripple(_) => RIPPLE,
AuraModes::Pulse(_) => PULSE,
AuraModes::Comet(_) => COMET,
AuraModes::Flash(_) => FLASH,
AuraModes::MultiStatic(_) => MULTISTATIC,
AuraModes::PerKey(_) => PER_KEY,
_ => panic!("Invalid mode"),
}
}
}
impl From<&AuraModes> for &str {
fn from(mode: &AuraModes) -> Self {
match mode {
AuraModes::Static(_) => "Static",
AuraModes::Breathe(_) => "Breathing",
AuraModes::Strobe(_) => "Strobing",
AuraModes::Rainbow(_) => "Rainbow",
AuraModes::Star(_) => "Stars",
AuraModes::Rain(_) => "Rain",
AuraModes::Highlight(_) => "Keypress Highlight",
AuraModes::Laser(_) => "Keypress Laser",
AuraModes::Ripple(_) => "Keypress Ripple",
AuraModes::Pulse(_) => "Pulse",
AuraModes::Comet(_) => "Comet",
AuraModes::Flash(_) => "Flash",
AuraModes::MultiStatic(_) => "4-Zone Static Colours",
AuraModes::PerKey(_) => "RGB per-key",
_ => panic!("Invalid mode"),
}
}
}
/// Exists to convert back from correct bytes. PER_KEY byte intentionally left off as it
/// does not correspond to an actual pre-set mode, nor does brightness.
impl From<u8> for AuraModes {
fn from(byte: u8) -> Self {
match byte {
STATIC => AuraModes::Static(SingleColour::default()),
BREATHING => AuraModes::Breathe(TwoColourSpeed::default()),
STROBE => AuraModes::Strobe(SingleSpeed::default()),
RAINBOW => AuraModes::Rainbow(SingleSpeedDirection::default()),
STAR => AuraModes::Star(TwoColourSpeed::default()),
RAIN => AuraModes::Rain(SingleSpeed::default()),
HIGHLIGHT => AuraModes::Highlight(SingleColourSpeed::default()),
LASER => AuraModes::Laser(SingleColourSpeed::default()),
RIPPLE => AuraModes::Ripple(SingleColourSpeed::default()),
PULSE => AuraModes::Pulse(SingleColour::default()),
COMET => AuraModes::Comet(SingleColour::default()),
FLASH => AuraModes::Flash(SingleColour::default()),
MULTISTATIC => AuraModes::MultiStatic(MultiColour::default()),
PER_KEY => AuraModes::PerKey(vec![]),
_ => panic!("Invalid mode byte"),
}
}
}

View File

@@ -1,215 +0,0 @@
use crate::error::AuraError;
use gumdrop::Options;
use serde_derive::{Deserialize, Serialize};
use std::str::FromStr;
#[derive(Options)]
pub struct LedBrightness {
level: u8,
}
impl LedBrightness {
pub fn level(&self) -> u8 {
self.level
}
}
impl FromStr for LedBrightness {
type Err = AuraError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let s = s.to_lowercase();
match s.as_str() {
"off" => Ok(LedBrightness { level: 0x00 }),
"low" => Ok(LedBrightness { level: 0x01 }),
"med" => Ok(LedBrightness { level: 0x02 }),
"high" => Ok(LedBrightness { level: 0x03 }),
_ => {
println!("Missing required argument, must be one of:\noff,low,med,high\n");
Err(AuraError::ParseBrightness)
}
}
}
}
#[derive(Deserialize, Serialize)]
pub struct Colour(pub u8, pub u8, pub u8);
impl Default for Colour {
fn default() -> Self {
Colour(255, 0, 0)
}
}
impl FromStr for Colour {
type Err = AuraError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if s.len() < 6 {
return Err(AuraError::ParseColour);
}
let r = u8::from_str_radix(&s[0..2], 16).or(Err(AuraError::ParseColour))?;
let g = u8::from_str_radix(&s[2..4], 16).or(Err(AuraError::ParseColour))?;
let b = u8::from_str_radix(&s[4..6], 16).or(Err(AuraError::ParseColour))?;
Ok(Colour(r, g, b))
}
}
#[derive(Deserialize, Serialize)]
pub enum Speed {
Low = 0xe1,
Med = 0xeb,
High = 0xf5,
}
impl Default for Speed {
fn default() -> Self {
Speed::Med
}
}
impl FromStr for Speed {
type Err = AuraError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let s = s.to_lowercase();
match s.as_str() {
"low" => Ok(Speed::Low),
"med" => Ok(Speed::Med),
"high" => Ok(Speed::High),
_ => Err(AuraError::ParseSpeed),
}
}
}
/// Used for Rainbow mode.
///
/// Enum corresponds to the required integer value
#[derive(Deserialize, Serialize)]
pub enum Direction {
Right,
Left,
Up,
Down,
}
impl Default for Direction {
fn default() -> Self {
Direction::Right
}
}
impl FromStr for Direction {
type Err = AuraError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let s = s.to_lowercase();
match s.as_str() {
"right" => Ok(Direction::Right),
"up" => Ok(Direction::Up),
"down" => Ok(Direction::Down),
"left" => Ok(Direction::Left),
_ => Err(AuraError::ParseDirection),
}
}
}
#[derive(Default, Options, Deserialize, Serialize)]
pub struct TwoColourSpeed {
#[options(help = "print help message")]
help: bool,
#[options(no_long, meta = "HEX", help = "set the first RGB value e.g, ff00ff")]
pub colour: Colour,
#[options(no_long, meta = "HEX", help = "set the second RGB value e.g, ff00ff")]
pub colour2: Colour,
#[options(no_long, help = "set the speed: low, med, high")]
pub speed: Speed,
}
#[derive(Default, Options, Deserialize, Serialize)]
pub struct SingleSpeed {
#[options(help = "print help message")]
help: bool,
#[options(no_long, meta = "WORD", help = "set the speed: low, med, high")]
pub speed: Speed,
}
#[derive(Default, Options, Deserialize, Serialize)]
pub struct SingleColour {
#[options(help = "print help message")]
help: bool,
#[options(no_long, meta = "HEX", help = "set the RGB value e.g, ff00ff")]
pub colour: Colour,
}
#[derive(Default, Options, Deserialize, Serialize)]
pub struct MultiColour {
#[options(help = "print help message")]
help: bool,
#[options(meta = "HEX", help = "set the RGB value e.g, ff00ff")]
pub colour1: Colour,
#[options(meta = "HEX", help = "set the RGB value e.g, ff00ff")]
pub colour2: Colour,
#[options(meta = "HEX", help = "set the RGB value e.g, ff00ff")]
pub colour3: Colour,
#[options(meta = "HEX", help = "set the RGB value e.g, ff00ff")]
pub colour4: Colour,
}
#[derive(Default, Options, Deserialize, Serialize)]
pub struct SingleSpeedDirection {
#[options(help = "print help message")]
help: bool,
#[options(
no_long,
meta = "DIR",
help = "set the direction: up, down, left, right"
)]
pub direction: Direction,
#[options(no_long, help = "set the speed: low, med, high")]
pub speed: Speed,
}
#[derive(Default, Options, Deserialize, Serialize)]
pub struct SingleColourSpeed {
#[options(help = "print help message")]
help: bool,
#[options(no_long, meta = "HEX", help = "set the RGB value e.g, ff00ff")]
pub colour: Colour,
#[options(no_long, help = "set the speed: low, med, high")]
pub speed: Speed,
}
/// Byte value for setting the built-in mode.
///
/// Enum corresponds to the required integer value
#[derive(Options, Deserialize, Serialize)]
pub enum SetAuraBuiltin {
#[options(help = "set a single static colour")]
Static(SingleColour),
#[options(help = "pulse between one or two colours")]
Breathe(TwoColourSpeed),
#[options(help = "strobe through all colours")]
Strobe(SingleSpeed),
#[options(help = "rainbow cycling in one of four directions")]
Rainbow(SingleSpeedDirection),
#[options(help = "rain pattern mimicking raindrops")]
Star(TwoColourSpeed),
#[options(help = "rain pattern of three preset colours")]
Rain(SingleSpeed),
#[options(help = "pressed keys are highlighted to fade")]
Highlight(SingleColourSpeed),
#[options(help = "pressed keys generate horizontal laser")]
Laser(SingleColourSpeed),
#[options(help = "pressed keys ripple outwards like a splash")]
Ripple(SingleColourSpeed),
#[options(help = "set a rapid pulse")]
Pulse(SingleColour),
#[options(help = "set a vertical line zooming from left")]
Comet(SingleColour),
#[options(help = "set a wide vertical line zooming from left")]
Flash(SingleColour),
#[options(help = "4-zone multi-colour")]
MultiStatic(MultiColour),
}
impl Default for SetAuraBuiltin {
fn default() -> Self {
SetAuraBuiltin::Static(SingleColour {
help: false,
colour: Colour(255, 0, 0),
})
}
}

View File

@@ -1,273 +0,0 @@
use super::*;
use crate::fancy::KeyColourArray;
use crate::profile::ProfileEvent;
use ctrl_gfx::vendors::GfxVendors;
use dbus::channel::Sender;
use dbus::{blocking::Connection, Message};
use std::error::Error;
use std::sync::{
atomic::{AtomicBool, Ordering},
Arc, Mutex,
};
use std::{thread, time::Duration};
use crate::dbus_gfx::OrgAsuslinuxDaemonNotifyGfx;
use crate::dbus_ledmode::OrgAsuslinuxDaemonNotifyLed;
use crate::dbus_profile::OrgAsuslinuxDaemonNotifyProfile;
use crate::dbus_charge::OrgAsuslinuxDaemonNotifyCharge;
// Signals separated out
pub struct CtrlSignals {
pub gfx_signal: Arc<Mutex<Option<String>>>,
pub profile_signal: Arc<Mutex<Option<String>>>,
pub ledmode_signal: Arc<Mutex<Option<AuraModes>>>,
pub charge_signal: Arc<Mutex<Option<u8>>>,
}
impl CtrlSignals {
#[inline]
pub fn new(connection: &Connection) -> Result<Self, Box<dyn Error>> {
let proxy = connection.with_proxy(
"org.asuslinux.Daemon",
"/org/asuslinux/Gfx",
Duration::from_millis(5000),
);
let gfx_signal = Arc::new(Mutex::new(None));
let gfx_res1 = gfx_signal.clone();
let _x = proxy.match_signal(
move |sig: OrgAsuslinuxDaemonNotifyGfx, _: &Connection, _: &Message| {
if let Ok(mut lock) = gfx_res1.lock() {
*lock = Some(sig.vendor);
}
true
},
)?;
//
let proxy = connection.with_proxy(
"org.asuslinux.Daemon",
"/org/asuslinux/Profile",
Duration::from_millis(5000),
);
let profile_signal = Arc::new(Mutex::new(None));
let prof_res1 = profile_signal.clone();
let _x = proxy.match_signal(
move |sig: OrgAsuslinuxDaemonNotifyProfile, _: &Connection, _: &Message| {
if let Ok(mut lock) = prof_res1.lock() {
*lock = Some(sig.profile);
}
true
},
)?;
//
let proxy = connection.with_proxy(
"org.asuslinux.Daemon",
"/org/asuslinux/Led",
Duration::from_millis(5000),
);
let ledmode_signal = Arc::new(Mutex::new(None));
let led_res1 = ledmode_signal.clone();
let _x = proxy.match_signal(
move |sig: OrgAsuslinuxDaemonNotifyLed, _: &Connection, _: &Message| {
if let Ok(mut lock) = led_res1.lock() {
if let Ok(dat) = serde_json::from_str(&sig.data) {
*lock = Some(dat);
}
}
true
},
)?;
//
let proxy = connection.with_proxy(
"org.asuslinux.Daemon",
"/org/asuslinux/Charge",
Duration::from_millis(5000),
);
let charge_signal = Arc::new(Mutex::new(None));
let charge_res1 = charge_signal.clone();
let _x = proxy.match_signal(
move |sig: OrgAsuslinuxDaemonNotifyCharge, _: &Connection, _: &Message| {
if let Ok(mut lock) = charge_res1.lock() {
*lock = Some(sig.limit);
}
true
},
)?;
Ok(CtrlSignals {
gfx_signal,
profile_signal,
ledmode_signal,
charge_signal,
})
}
}
/// Simplified way to write a effect block
pub struct AuraDbusClient {
connection: Box<Connection>,
block_time: u64,
stop: Arc<AtomicBool>,
signals: CtrlSignals,
}
impl AuraDbusClient {
#[inline]
pub fn new() -> Result<Self, Box<dyn Error>> {
let connection = Connection::new_system()?;
let stop = Arc::new(AtomicBool::new(false));
let match_rule = dbus::message::MatchRule::new_signal(DBUS_IFACE, "NotifyLed");
let stop1 = stop.clone();
connection.add_match(match_rule, move |_: (), _, msg| {
if msg.read1::<&str>().is_ok() {
stop1.clone().store(true, Ordering::Relaxed);
}
true
})?;
let signals = CtrlSignals::new(&connection)?;
Ok(AuraDbusClient {
connection: Box::new(connection),
block_time: 33333,
stop,
signals,
})
}
pub fn wait_gfx_changed(&self) -> Result<String, Box<dyn Error>> {
loop {
self.connection.process(Duration::from_micros(500))?;
if let Ok(lock) = self.signals.gfx_signal.lock() {
if let Some(stuff) = lock.as_ref() {
return Ok(stuff.to_string());
}
}
}
}
/// This method must always be called before the very first write to initialise
/// the keyboard LED EC in the correct mode
#[inline]
pub fn init_effect(&self) -> Result<(), Box<dyn std::error::Error>> {
let mode = AuraModes::PerKey(vec![vec![]]);
let mut msg =
Message::new_method_call(DBUS_NAME, "/org/asuslinux/Led", DBUS_IFACE, "SetLedMode")?
.append1(serde_json::to_string(&mode)?);
msg.set_no_reply(true);
self.connection.send(msg).unwrap();
Ok(())
}
/// Write a single colour block.
///
/// Intentionally blocks for 10ms after sending to allow the block to
/// be written to the keyboard EC. This should not be async.
#[inline]
pub fn write_colour_block(
&mut self,
key_colour_array: &KeyColourArray,
) -> Result<(), Box<dyn Error>> {
let group = key_colour_array.get();
let mut vecs = Vec::with_capacity(group.len());
for v in group {
vecs.push(v.to_vec());
}
let mode = AuraModes::PerKey(vecs);
let mut msg =
Message::new_method_call(DBUS_NAME, "/org/asuslinux/Led", DBUS_IFACE, "SetLedMode")?
.append1(serde_json::to_string(&mode)?);
msg.set_no_reply(true);
self.connection.send(msg).unwrap();
thread::sleep(Duration::from_micros(self.block_time));
self.connection.process(Duration::from_micros(500))?;
if self.stop.load(Ordering::Relaxed) {
println!("Keyboard backlight was changed, exiting");
std::process::exit(1)
}
Ok(())
}
#[inline]
pub fn write_keyboard_leds(&self, mode: &AuraModes) -> Result<(), Box<dyn std::error::Error>> {
let mut msg =
Message::new_method_call(DBUS_NAME, "/org/asuslinux/Led", DBUS_IFACE, "SetLedMode")?
.append1(serde_json::to_string(mode)?);
msg.set_no_reply(true);
self.connection.send(msg).unwrap();
Ok(())
}
#[inline]
pub fn write_fan_mode(&self, level: u8) -> Result<(), Box<dyn std::error::Error>> {
let mut msg = Message::new_method_call(
DBUS_NAME,
"/org/asuslinux/Profile",
DBUS_IFACE,
"SetProfile",
)?
.append1(serde_json::to_string(&ProfileEvent::ChangeMode(level))?);
msg.set_no_reply(true);
self.connection.send(msg).unwrap();
Ok(())
}
#[inline]
pub fn write_gfx_mode(&self, vendor: GfxVendors) -> Result<(), Box<dyn std::error::Error>> {
let mut msg =
Message::new_method_call(DBUS_NAME, "/org/asuslinux/Gfx", DBUS_IFACE, "SetVendor")?
.append1(<&str>::from(&vendor));
msg.set_no_reply(true);
self.connection.send(msg).unwrap();
Ok(())
}
#[inline]
pub fn write_profile_command(
&self,
cmd: &ProfileEvent,
) -> Result<(), Box<dyn std::error::Error>> {
let mut msg = Message::new_method_call(
DBUS_NAME,
"/org/asuslinux/Profile",
DBUS_IFACE,
"SetProfile",
)?
.append1(serde_json::to_string(cmd)?);
msg.set_no_reply(true);
self.connection.send(msg).unwrap();
Ok(())
}
#[inline]
pub fn write_charge_limit(&self, level: u8) -> Result<(), Box<dyn std::error::Error>> {
let mut msg =
Message::new_method_call(DBUS_NAME, "/org/asuslinux/Charge", DBUS_IFACE, "SetLimit")?
.append1(level);
msg.set_no_reply(true);
self.connection.send(msg).unwrap();
Ok(())
}
#[inline]
pub fn write_builtin_mode(&self, mode: &AuraModes) -> Result<(), Box<dyn std::error::Error>> {
self.write_keyboard_leds(mode)
}
#[inline]
pub fn write_brightness(&self, level: u8) -> Result<String, Box<dyn std::error::Error>> {
self.write_keyboard_leds(&AuraModes::LedBrightness(level))?;
Ok(String::new())
}
}

View File

@@ -1,46 +0,0 @@
// This code was autogenerated with `dbus-codegen-rust -s -d org.asuslinux.Daemon -f org.asuslinux.Daemon -c blocking -p /org/asuslinux/Charge -m None`, see https://github.com/diwic/dbus-rs
use dbus as dbus;
#[allow(unused_imports)]
use dbus::arg;
use dbus::blocking;
pub trait OrgAsuslinuxDaemon {
fn set_limit(&self, limit: u8) -> Result<(), dbus::Error>;
fn limit(&self) -> Result<i16, dbus::Error>;
}
impl<'a, T: blocking::BlockingSender, C: ::std::ops::Deref<Target=T>> OrgAsuslinuxDaemon for blocking::Proxy<'a, C> {
fn set_limit(&self, limit: u8) -> Result<(), dbus::Error> {
self.method_call("org.asuslinux.Daemon", "SetLimit", (limit, ))
}
fn limit(&self) -> Result<i16, dbus::Error> {
self.method_call("org.asuslinux.Daemon", "Limit", ())
.and_then(|r: (i16, )| Ok(r.0, ))
}
}
#[derive(Debug)]
pub struct OrgAsuslinuxDaemonNotifyCharge {
pub limit: u8,
}
impl arg::AppendAll for OrgAsuslinuxDaemonNotifyCharge {
fn append(&self, i: &mut arg::IterAppend) {
arg::RefArg::append(&self.limit, i);
}
}
impl arg::ReadAll for OrgAsuslinuxDaemonNotifyCharge {
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
Ok(OrgAsuslinuxDaemonNotifyCharge {
limit: i.read()?,
})
}
}
impl dbus::message::SignalArgs for OrgAsuslinuxDaemonNotifyCharge {
const NAME: &'static str = "NotifyCharge";
const INTERFACE: &'static str = "org.asuslinux.Daemon";
}

View File

@@ -1,39 +0,0 @@
// This code was autogenerated with `dbus-codegen-rust -s -d org.asuslinux.Daemon -p /org/asuslinux/Gfx -m None -f org.asuslinux.Daemon -c blocking`, see https://github.com/diwic/dbus-rs
use dbus;
#[allow(unused_imports)]
use dbus::arg;
use dbus::blocking;
pub trait OrgAsuslinuxDaemon {
fn set_vendor(&self, vendor: &str) -> Result<(), dbus::Error>;
}
impl<'a, T: blocking::BlockingSender, C: ::std::ops::Deref<Target = T>> OrgAsuslinuxDaemon
for blocking::Proxy<'a, C>
{
fn set_vendor(&self, vendor: &str) -> Result<(), dbus::Error> {
self.method_call("org.asuslinux.Daemon", "SetVendor", (vendor,))
}
}
#[derive(Debug)]
pub struct OrgAsuslinuxDaemonNotifyGfx {
pub vendor: String,
}
impl arg::AppendAll for OrgAsuslinuxDaemonNotifyGfx {
fn append(&self, i: &mut arg::IterAppend) {
arg::RefArg::append(&self.vendor, i);
}
}
impl arg::ReadAll for OrgAsuslinuxDaemonNotifyGfx {
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
Ok(OrgAsuslinuxDaemonNotifyGfx { vendor: i.read()? })
}
}
impl dbus::message::SignalArgs for OrgAsuslinuxDaemonNotifyGfx {
const NAME: &'static str = "NotifyGfx";
const INTERFACE: &'static str = "org.asuslinux.Daemon";
}

View File

@@ -1,52 +0,0 @@
// This code was autogenerated with `dbus-codegen-rust -s -d org.asuslinux.Daemon -f org.asuslinux.Daemon -c blocking -p /org/asuslinux/Led -m None`, see https://github.com/diwic/dbus-rs
use dbus as dbus;
#[allow(unused_imports)]
use dbus::arg;
use dbus::blocking;
pub trait OrgAsuslinuxDaemon {
fn set_led_mode(&self, data: &str) -> Result<(), dbus::Error>;
fn led_mode(&self) -> Result<String, dbus::Error>;
fn led_modes(&self) -> Result<String, dbus::Error>;
}
impl<'a, T: blocking::BlockingSender, C: ::std::ops::Deref<Target=T>> OrgAsuslinuxDaemon for blocking::Proxy<'a, C> {
fn set_led_mode(&self, data: &str) -> Result<(), dbus::Error> {
self.method_call("org.asuslinux.Daemon", "SetLedMode", (data, ))
}
fn led_mode(&self) -> Result<String, dbus::Error> {
self.method_call("org.asuslinux.Daemon", "LedMode", ())
.and_then(|r: (String, )| Ok(r.0, ))
}
fn led_modes(&self) -> Result<String, dbus::Error> {
self.method_call("org.asuslinux.Daemon", "LedModes", ())
.and_then(|r: (String, )| Ok(r.0, ))
}
}
#[derive(Debug)]
pub struct OrgAsuslinuxDaemonNotifyLed {
pub data: String,
}
impl arg::AppendAll for OrgAsuslinuxDaemonNotifyLed {
fn append(&self, i: &mut arg::IterAppend) {
arg::RefArg::append(&self.data, i);
}
}
impl arg::ReadAll for OrgAsuslinuxDaemonNotifyLed {
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
Ok(OrgAsuslinuxDaemonNotifyLed {
data: i.read()?,
})
}
}
impl dbus::message::SignalArgs for OrgAsuslinuxDaemonNotifyLed {
const NAME: &'static str = "NotifyLed";
const INTERFACE: &'static str = "org.asuslinux.Daemon";
}

View File

@@ -1,51 +0,0 @@
// This code was autogenerated with `dbus-codegen-rust -s -d org.asuslinux.Daemon -f org.asuslinux.Daemon -c blocking -p /org/asuslinux/Profile -m None`, see https://github.com/diwic/dbus-rs
use dbus;
#[allow(unused_imports)]
use dbus::arg;
use dbus::blocking;
pub trait OrgAsuslinuxDaemon {
fn set_profile(&self, profile: &str) -> Result<(), dbus::Error>;
fn profile(&self) -> Result<String, dbus::Error>;
fn profiles(&self) -> Result<String, dbus::Error>;
}
impl<'a, T: blocking::BlockingSender, C: ::std::ops::Deref<Target = T>> OrgAsuslinuxDaemon
for blocking::Proxy<'a, C>
{
fn set_profile(&self, profile: &str) -> Result<(), dbus::Error> {
self.method_call("org.asuslinux.Daemon", "SetProfile", (profile,))
}
fn profile(&self) -> Result<String, dbus::Error> {
self.method_call("org.asuslinux.Daemon", "Profile", ())
.and_then(|r: (String,)| Ok(r.0))
}
fn profiles(&self) -> Result<String, dbus::Error> {
self.method_call("org.asuslinux.Daemon", "Profiles", ())
.and_then(|r: (String,)| Ok(r.0))
}
}
#[derive(Debug)]
pub struct OrgAsuslinuxDaemonNotifyProfile {
pub profile: String,
}
impl arg::AppendAll for OrgAsuslinuxDaemonNotifyProfile {
fn append(&self, i: &mut arg::IterAppend) {
arg::RefArg::append(&self.profile, i);
}
}
impl arg::ReadAll for OrgAsuslinuxDaemonNotifyProfile {
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
Ok(OrgAsuslinuxDaemonNotifyProfile { profile: i.read()? })
}
}
impl dbus::message::SignalArgs for OrgAsuslinuxDaemonNotifyProfile {
const NAME: &'static str = "NotifyProfile";
const INTERFACE: &'static str = "org.asuslinux.Daemon";
}

View File

@@ -1,40 +0,0 @@
use std::error::Error;
use std::fmt;
#[derive(Debug)]
pub enum AuraError {
ParseColour,
ParseSpeed,
ParseDirection,
ParseBrightness,
}
impl fmt::Display for AuraError {
// This trait requires `fmt` with this exact signature.
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
AuraError::ParseColour => write!(f, "Could not parse colour"),
AuraError::ParseSpeed => write!(f, "Could not parse speed"),
AuraError::ParseDirection => write!(f, "Could not parse direction"),
AuraError::ParseBrightness => write!(f, "Could not parse brightness"),
}
}
}
impl Error for AuraError {}
#[derive(Debug)]
pub enum GraphicsError {
ParseVendor,
}
impl fmt::Display for GraphicsError {
// This trait requires `fmt` with this exact signature.
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
GraphicsError::ParseVendor => write!(f, "Could not parse vendor name"),
}
}
}
impl Error for GraphicsError {}

View File

@@ -1,455 +0,0 @@
/// A `KeyColourArray` contains all data to change the full set of keyboard
/// key colours individually.
///
/// Each row of the internal array is a full HID packet that can be sent
/// to the keyboard EC. One row controls one group of keys, these keys are not
/// necessarily all on the same row of the keyboard, with some splitting between
/// two rows.
#[derive(Clone)]
pub struct KeyColourArray([[u8; 64]; 11]);
impl Default for KeyColourArray {
fn default() -> Self {
Self::new()
}
}
impl KeyColourArray {
pub fn new() -> Self {
let mut set = [[0u8; 64]; 11];
for (count, row) in set.iter_mut().enumerate() {
row[0] = 0x5d; // Report ID
row[1] = 0xbc; // Mode = custom??, 0xb3 is builtin
row[2] = 0x00;
row[3] = 0x01; // ??
row[4] = 0x01; // ??, 4,5,6 are normally RGB for builtin mode colours
row[5] = 0x01; // ??
row[6] = (count as u8) << 4; // Key group
if count == 10 {
row[7] = 0x08; // 0b00001000
} else {
row[7] = 0x10; // 0b00010000 addressing? flips for group a0
}
row[8] = 0x00;
}
KeyColourArray(set)
}
/// Initialise and clear the keyboard for custom effects
#[inline]
pub fn get_init_msg() -> Vec<u8> {
let mut init = vec![0u8; 64];
init[0] = 0x5d; // Report ID
init[1] = 0xbc; // Mode = custom??, 0xb3 is builtin
init
}
#[inline]
pub fn set(&mut self, key: Key, r: u8, g: u8, b: u8) {
if let Some((rr, gg, bb)) = self.key(key) {
*rr = r;
*gg = g;
*bb = b;
}
}
/// Indexes in to `KeyColourArray` at the correct row and column
/// to set a series of three bytes to the chosen R,G,B values
pub fn key(&mut self, key: Key) -> Option<(&mut u8, &mut u8, &mut u8)> {
// Tuples are indexes in to array
let (row, col) = match key {
Key::VolDown => (0, 15),
Key::VolUp => (0, 18),
Key::MicMute => (0, 21),
Key::ROG => (0, 24),
//
Key::Esc => (1, 24),
Key::F1 => (1, 30),
Key::F2 => (1, 33),
Key::F3 => (1, 36),
Key::F4 => (1, 39),
Key::F5 => (1, 45),
Key::F6 => (1, 48),
Key::F7 => (1, 51),
Key::F8 => (1, 54),
//
Key::F9 => (2, 12),
Key::F10 => (2, 15),
Key::F11 => (2, 18),
Key::F12 => (2, 21),
Key::Del => (2, 24),
Key::Tilde => (2, 39),
Key::N1 => (2, 42),
Key::N2 => (2, 45),
Key::N3 => (2, 48),
Key::N4 => (2, 51),
Key::N5 => (2, 54),
//
Key::N6 => (3, 9),
Key::N7 => (3, 12),
Key::N8 => (3, 15),
Key::N9 => (3, 18),
Key::N0 => (3, 21),
Key::Hyphen => (3, 24),
Key::Equals => (3, 27),
Key::BkSpc1 => (3, 30),
Key::BkSpc2 => (3, 33),
Key::BkSpc3 => (3, 36),
Key::Home => (3, 39),
Key::Tab => (3, 54),
//
Key::Q => (4, 9),
Key::W => (4, 12),
Key::E => (4, 15),
Key::R => (4, 18),
Key::T => (4, 21),
Key::Y => (4, 24),
Key::U => (4, 27),
Key::I => (4, 30),
Key::O => (4, 33),
Key::P => (4, 36),
Key::LBracket => (4, 39),
Key::RBracket => (4, 42),
Key::BackSlash => (4, 45),
Key::PgUp => (4, 54),
//
Key::Caps => (5, 21),
Key::A => (5, 24),
Key::S => (5, 27),
Key::D => (5, 30),
Key::F => (5, 33),
Key::G => (5, 36),
Key::H => (5, 39),
Key::J => (5, 42),
Key::K => (5, 45),
Key::L => (5, 48),
Key::SemiColon => (5, 51),
Key::Quote => (5, 54),
//
Key::Ret1 => (6, 12),
Key::Ret2 => (6, 15),
Key::Ret3 => (6, 18),
Key::PgDn => (6, 21),
Key::LShift => (6, 36),
Key::Z => (6, 42),
Key::X => (6, 45),
Key::C => (6, 48),
Key::V => (6, 51),
Key::B => (6, 54),
//
Key::N => (7, 9),
Key::M => (7, 12),
Key::Comma => (7, 15),
Key::Period => (7, 18),
Key::FwdSlash => (7, 21),
Key::Rshift1 => (7, 27),
Key::Rshift2 => (7, 30),
Key::Rshift3 => (7, 33),
Key::End => (7, 36),
Key::LCtrl => (7, 51),
Key::LFn => (7, 54),
//
Key::Meta => (8, 9),
Key::LAlt => (8, 12),
Key::Space1 => (8, 15),
Key::Space2 => (8, 18),
Key::Space3 => (8, 21),
Key::Space4 => (8, 24),
Key::RAlt => (8, 30),
Key::PrtSc => (8, 33),
Key::RCtrl => (8, 36),
Key::Up => (8, 42),
Key::RFn => (8, 51),
//
Key::Left => (9, 54),
//
Key::Down => (10, 9),
Key::Right => (10, 12),
Key::None => return None,
};
// LOLOLOLOLOLOLOL! Look it's safe okay
unsafe {
Some((
&mut *(&mut self.0[row][col] as *mut u8),
&mut *(&mut self.0[row][col + 1] as *mut u8),
&mut *(&mut self.0[row][col + 2] as *mut u8),
))
}
}
#[inline]
pub fn get(&self) -> &[[u8; 64]; 11] {
&self.0
}
}
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum Key {
VolUp,
VolDown,
MicMute,
ROG,
Esc,
F1,
F2,
F3,
F4,
F5,
F6,
F7,
F8,
F9,
F10,
F11,
F12,
Del,
Tilde,
N1,
N2,
N3,
N4,
N5,
N6,
N7,
N8,
N9,
N0,
Hyphen,
Equals,
BkSpc1,
BkSpc2,
BkSpc3,
Home,
Tab,
Q,
W,
E,
R,
T,
Y,
U,
I,
O,
P,
LBracket,
RBracket,
BackSlash,
PgUp,
Caps,
A,
S,
D,
F,
G,
H,
J,
K,
L,
SemiColon,
Quote,
Ret1,
Ret2,
Ret3,
PgDn,
LShift,
Z,
X,
C,
V,
B,
N,
M,
Comma,
Period,
FwdSlash,
Rshift1,
Rshift2,
Rshift3,
End,
LCtrl,
LFn,
Meta,
LAlt,
Space1,
Space2,
Space3,
Space4,
RAlt,
PrtSc,
RCtrl,
Up,
Down,
Left,
Right,
RFn,
None,
}
pub trait KeyLayout {
fn get_rows(&self) -> &Vec<[Key; 17]>;
}
pub struct GX502Layout(Vec<[Key; 17]>);
impl KeyLayout for GX502Layout {
fn get_rows(&self) -> &Vec<[Key; 17]> {
&self.0
}
}
impl Default for GX502Layout {
fn default() -> Self {
GX502Layout(vec![
[
Key::None,
Key::None,
Key::VolDown,
Key::VolUp,
Key::MicMute,
Key::ROG,
Key::None,
Key::None,
Key::None,
Key::None,
Key::None,
Key::None,
Key::None,
Key::None,
Key::None,
Key::None,
Key::None,
],
[
Key::Esc,
Key::None,
Key::F1,
Key::F2,
Key::F3,
Key::F4,
Key::None, // not sure which key to put here
Key::F5,
Key::F6,
Key::F7,
Key::F8,
Key::F9,
Key::F9,
Key::F10,
Key::F11,
Key::F12,
Key::Del,
],
[
Key::Tilde,
Key::N1,
Key::N2,
Key::N3,
Key::N4,
Key::N5,
Key::N6,
Key::N7,
Key::N8,
Key::N9,
Key::N0,
Key::Hyphen,
Key::Equals,
Key::BkSpc1,
Key::BkSpc2,
Key::BkSpc3,
Key::Home,
],
[
Key::Tab,
Key::Q,
Key::W,
Key::E,
Key::R,
Key::T,
Key::Y,
Key::U,
Key::I,
Key::O,
Key::P,
Key::LBracket,
Key::RBracket,
Key::BackSlash,
Key::BackSlash,
Key::BackSlash,
Key::PgUp,
],
[
Key::Caps,
Key::A,
Key::S,
Key::D,
Key::F,
Key::G,
Key::H,
Key::J,
Key::K,
Key::L,
Key::SemiColon,
Key::Quote,
Key::Quote,
Key::Ret1,
Key::Ret2,
Key::Ret3,
Key::PgDn,
],
[
Key::LShift,
Key::LShift,
Key::Z,
Key::X,
Key::C,
Key::V,
Key::B,
Key::N,
Key::M,
Key::Comma,
Key::Period,
Key::FwdSlash,
Key::FwdSlash,
Key::Rshift1,
Key::Rshift2,
Key::Rshift3,
Key::End,
],
[
Key::LCtrl,
Key::LFn,
Key::Meta,
Key::LAlt,
Key::Space1,
Key::Space2,
Key::Space3,
Key::Space4,
Key::Space4,
Key::RAlt,
Key::PrtSc,
Key::RCtrl,
Key::RCtrl,
Key::Left,
Key::Up,
Key::Right,
Key::RFn,
],
[
Key::None,
Key::None,
Key::None,
Key::None,
Key::None,
Key::None,
Key::None,
Key::None,
Key::None,
Key::None,
Key::None,
Key::None,
Key::None,
Key::Left,
Key::Down,
Key::Right,
Key::None,
],
])
}
}

View File

@@ -1,259 +0,0 @@
pub static DBUS_NAME: &str = "org.asuslinux.Daemon";
pub static DBUS_PATH: &str = "/org/asuslinux/Daemon";
pub static DBUS_IFACE: &str = "org.asuslinux.Daemon";
pub const LED_MSG_LEN: usize = 17;
pub mod aura_modes;
use aura_modes::AuraModes;
pub mod profile;
/// Contains mostly only what is required for parsing CLI options
pub mod cli_options;
/// Enables you to create fancy RGB effects
pub mod fancy;
/// The main dbus group for system controls, e.g, fan control, keyboard LED's
pub mod core_dbus;
/// Specific dbus for writing to the AniMe Matrix display (if supported)
pub mod anime_dbus;
/// Helper functions for the AniMe display
pub mod anime_matrix;
pub mod dbus_gfx;
pub mod dbus_ledmode;
pub mod dbus_profile;
pub mod dbus_charge;
pub mod error;
// static LED_INIT1: [u8; 2] = [0x5d, 0xb9];
// static LED_INIT2: &str = "]ASUS Tech.Inc."; // ] == 0x5d
// static LED_INIT3: [u8; 6] = [0x5d, 0x05, 0x20, 0x31, 0, 0x08];
// static LED_INIT4: &str = "^ASUS Tech.Inc."; // ^ == 0x5e
// static LED_INIT5: [u8; 6] = [0x5e, 0x05, 0x20, 0x31, 0, 0x08];
/// Writes aout the correct byte string for brightness
///
/// The HID descriptor looks like:
///
/// ```ignore
/// 0x06, 0x31, 0xFF, // Usage Page (Vendor Defined 0xFF31)
/// 0x09, 0x76, // Usage (0x76)
/// 0xA1, 0x01, // Collection (Application)
/// 0x85, 0x5A, // Report ID (90)
/// 0x19, 0x00, // Usage Minimum (0x00)
/// 0x2A, 0xFF, 0x00, // Usage Maximum (0xFF)
/// 0x15, 0x00, // Logical Minimum (0)
/// 0x26, 0xFF, 0x00, // Logical Maximum (255)
/// 0x75, 0x08, // Report Size (8)
/// 0x95, 0x05, // Report Count (5)
/// 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
/// 0x19, 0x00, // Usage Minimum (0x00)
/// 0x2A, 0xFF, 0x00, // Usage Maximum (0xFF)
/// 0x15, 0x00, // Logical Minimum (0)
/// 0x26, 0xFF, 0x00, // Logical Maximum (255)
/// 0x75, 0x08, // Report Size (8)
/// 0x95, 0x3F, // Report Count (63)
/// 0xB1, 0x00, // Feature (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
/// 0xC0, // End Collection
/// ```
pub fn aura_brightness_bytes(brightness: u8) -> [u8; 17] {
// TODO: check brightness range
[
0x5A, 0xBA, 0xC5, 0xC4, brightness, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
]
}
/// Parses `AuraCommands` in to packet data
///
/// Byte structure:
///
/// ```ignore
/// | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10| 11| 12|
/// |---|---|---|---|---|---|---|---|---|---|---|---|---|
/// |5d |b3 |00 |03 |ff |00 |00 |00 |00 |00 |00 |ff |00 |
/// ```
///
/// Bytes 0 and 1 should always be 5d, b3
///
/// On multizone laptops byte 2 is the zone number, RGB in usual
/// place, byte 3 set to zero
///
/// Byte 3 sets the mode type:
/// - 00 = static
/// - 01 = breathe (can set two colours)
/// - 02 = strobe (through all colours)
/// - 03 = rainbow
/// - 04 = star (byte 9 sets rain colour)
/// - 05 = rain keys, red, white, turquoise
/// - 06 = pressed keys light up and fade
/// - 07 = pressed key emits laser
/// - 08 = pressed key emits water ripple
/// - 09 = no effect/not used
/// - 0a fast pulse (no speed setting)
/// - 0b vertical line racing to right (no speed setting)
/// - 0c wider vertical line racing to right (no speed setting)
///
/// Bytes 4, 5, 6 are Red, Green, Blue
///
/// Byte 7 sets speed from
/// - 0x00 = Off
/// - 0xe1 = Slow
/// - 0xeb = Medium
/// - 0xf5 = Fast
///
/// Byte 8 sets rainbow direction:
/// - 0x00 = rightwards
/// - 0x01 = leftwards
/// - 0x02 = upwards
/// - 0x03 = downwards
///
/// Bytes 10, 11, 12 are Red, Green, Blue for second colour if mode supports it
///
/// The HID descriptor looks like:
/// ```ignore
/// 0x06, 0x31, 0xFF, // Usage Page (Vendor Defined 0xFF31)
/// 0x09, 0x79, // Usage (0x79)
/// 0xA1, 0x01, // Collection (Application)
/// 0x85, 0x5D, // Report ID (93)
/// 0x19, 0x00, // Usage Minimum (0x00)
/// 0x2A, 0xFF, 0x00, // Usage Maximum (0xFF)
/// 0x15, 0x00, // Logical Minimum (0)
/// 0x26, 0xFF, 0x00, // Logical Maximum (255)
/// 0x75, 0x08, // Report Size (8)
/// 0x95, 0x1F, // Report Count (31)
/// 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
/// 0x19, 0x00, // Usage Minimum (0x00)
/// 0x2A, 0xFF, 0x00, // Usage Maximum (0xFF)
/// 0x15, 0x00, // Logical Minimum (0)
/// 0x26, 0xFF, 0x00, // Logical Maximum (255)
/// 0x75, 0x08, // Report Size (8)
/// 0x95, 0x3F, // Report Count (63)
/// 0x91, 0x00, // Output (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
/// 0x19, 0x00, // Usage Minimum (0x00)
/// 0x2A, 0xFF, 0x00, // Usage Maximum (0xFF)
/// 0x15, 0x00, // Logical Minimum (0)
/// 0x26, 0xFF, 0x00, // Logical Maximum (255)
/// 0x75, 0x08, // Report Size (8)
/// 0x95, 0x3F, // Report Count (63)
/// 0xB1, 0x00, // Feature (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
/// 0xC0, // End Collection
/// ```
///
/// This descriptor is also used for the per-key LED settings
impl From<&AuraModes> for [u8; LED_MSG_LEN] {
fn from(mode: &AuraModes) -> Self {
let mut msg = [0u8; LED_MSG_LEN];
msg[0] = 0x5d;
msg[1] = 0xb3;
match mode {
AuraModes::LedBrightness(n) => return aura_brightness_bytes(*n),
AuraModes::Static(_) => msg[3] = 0x00,
AuraModes::Breathe(_) => msg[3] = 0x01,
AuraModes::Strobe(_) => msg[3] = 0x02,
AuraModes::Rainbow(_) => msg[3] = 0x03,
AuraModes::Star(_) => msg[3] = 0x04,
AuraModes::Rain(_) => msg[3] = 0x05,
AuraModes::Highlight(_) => msg[3] = 0x06,
AuraModes::Laser(_) => msg[3] = 0x07,
AuraModes::Ripple(_) => msg[3] = 0x08,
AuraModes::Pulse(_) => msg[3] = 0x0a,
AuraModes::Comet(_) => msg[3] = 0x0b,
AuraModes::Flash(_) => msg[3] = 0x0c,
_ => panic!("Mode not convertable to 1D array: {}", <&str>::from(mode)),
}
match mode {
AuraModes::Rainbow(settings) => {
msg[7] = settings.speed as u8;
msg[8] = settings.direction as u8;
}
AuraModes::Star(settings) => {
msg[4] = settings.colour.0;
msg[5] = settings.colour.1;
msg[6] = settings.colour.2;
msg[7] = settings.speed as u8;
msg[9] = settings.colour2.2;
}
AuraModes::Breathe(settings) => {
msg[4] = settings.colour.0;
msg[5] = settings.colour.1;
msg[6] = settings.colour.2;
msg[7] = settings.speed as u8;
msg[10] = settings.colour2.0;
msg[11] = settings.colour2.1;
msg[12] = settings.colour2.2;
}
AuraModes::Strobe(settings) | AuraModes::Rain(settings) => {
msg[7] = settings.speed as u8;
}
AuraModes::Highlight(settings)
| AuraModes::Laser(settings)
| AuraModes::Ripple(settings) => {
msg[4] = settings.colour.0;
msg[5] = settings.colour.1;
msg[6] = settings.colour.2;
msg[7] = settings.speed as u8;
}
AuraModes::Static(settings)
| AuraModes::Pulse(settings)
| AuraModes::Comet(settings)
| AuraModes::Flash(settings) => {
msg[4] = settings.colour.0;
msg[5] = settings.colour.1;
msg[6] = settings.colour.2;
}
_ => panic!("Mode not convertable to 1D array: {}", <&str>::from(mode)),
}
msg
}
}
impl From<AuraModes> for [u8; LED_MSG_LEN] {
#[inline]
fn from(mode: AuraModes) -> Self {
<[u8; LED_MSG_LEN]>::from(&mode)
}
}
impl From<AuraModes> for [[u8; LED_MSG_LEN]; 4] {
#[inline]
fn from(mode: AuraModes) -> Self {
<[[u8; LED_MSG_LEN]; 4]>::from(&mode)
}
}
impl From<&AuraModes> for [[u8; LED_MSG_LEN]; 4] {
#[inline]
fn from(mode: &AuraModes) -> Self {
let mut msg = [[0u8; LED_MSG_LEN]; 4];
for (i, row) in msg.iter_mut().enumerate() {
row[0] = 0x5d;
row[1] = 0xb3;
row[2] = i as u8 + 1;
}
match mode {
AuraModes::MultiStatic(settings) => {
msg[0][4] = settings.colour1.0;
msg[0][5] = settings.colour1.1;
msg[0][6] = settings.colour1.2;
msg[1][4] = settings.colour2.0;
msg[1][5] = settings.colour2.1;
msg[1][6] = settings.colour2.2;
msg[2][4] = settings.colour3.0;
msg[2][5] = settings.colour3.1;
msg[2][6] = settings.colour3.2;
msg[3][4] = settings.colour4.0;
msg[3][5] = settings.colour4.1;
msg[3][6] = settings.colour4.2;
}
_ => panic!("Mode not convertable to 2D array: {}", <&str>::from(mode)),
}
msg
}
}

View File

@@ -1,95 +0,0 @@
use gumdrop::Options;
use rog_fan_curve::{Curve, Fan};
use serde_derive::{Deserialize, Serialize};
use std::str::FromStr;
#[derive(Debug, Serialize, Deserialize)]
pub enum ProfileEvent {
Cli(ProfileCommand),
ChangeMode(u8),
Toggle,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum FanLevel {
Normal,
Boost,
Silent,
}
impl FromStr for FanLevel {
type Err = &'static str;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"normal" => Ok(FanLevel::Normal),
"boost" => Ok(FanLevel::Boost),
"silent" => Ok(FanLevel::Silent),
_ => Err("Invalid fan level"),
}
}
}
impl From<u8> for FanLevel {
fn from(n: u8) -> Self {
match n {
0 => FanLevel::Normal,
1 => FanLevel::Boost,
2 => FanLevel::Silent,
_ => FanLevel::Normal,
}
}
}
impl From<FanLevel> for u8 {
fn from(n: FanLevel) -> Self {
match n {
FanLevel::Normal => 0,
FanLevel::Boost => 1,
FanLevel::Silent => 2,
}
}
}
impl From<&FanLevel> for u8 {
fn from(n: &FanLevel) -> Self {
match n {
FanLevel::Normal => 0,
FanLevel::Boost => 1,
FanLevel::Silent => 2,
}
}
}
fn parse_fan_curve(data: &str) -> Result<Curve, String> {
let curve = Curve::from_config_str(data)?;
if let Err(err) = curve.check_safety(Fan::Cpu) {
return Err(format!("Unsafe curve {:?}", err));
}
if let Err(err) = curve.check_safety(Fan::Gpu) {
return Err(format!("Unsafe curve {:?}", err));
}
Ok(curve)
}
#[derive(Debug, Clone, Options, Serialize, Deserialize)]
pub struct ProfileCommand {
#[options(help = "print help message")]
help: bool,
#[options(help = "create the profile if it doesn't exist")]
pub create: bool,
#[options(help = "enable or disable cpu turbo")]
pub turbo: Option<bool>,
#[options(help = "set min cpu scaling (intel)")]
pub min_percentage: Option<u8>,
#[options(help = "set max cpu scaling (intel)")]
pub max_percentage: Option<u8>,
#[options(meta = "PWR", help = "<silent, normal, boost>")]
pub preset: Option<FanLevel>,
#[options(parse(try_from_str = "parse_fan_curve"), help = "set fan curve")]
pub curve: Option<Curve>,
#[options(free)]
pub profile: Option<String>,
}

View File

@@ -1,17 +0,0 @@
[package]
name = "asus-notify"
version = "1.0.0"
authors = ["Luke D Jones <luke@ljones.dev>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
# serialisation
serde = "^1.0"
serde_derive = "^1.0"
serde_json = "^1.0"
notify-rust = "^4.0.0"
dbus = { version = "^0.8" }
asus-nb = { path = "../asus-nb" }
asus-nb-ctrl = { path = "../asus-nb-ctrl" }

View File

@@ -1,101 +0,0 @@
use asus_nb::core_dbus::CtrlSignals;
use daemon::config::{Config, Profile};
use dbus::blocking::Connection;
use notify_rust::{Hint, Notification, NotificationHandle};
use std::error::Error;
use std::time::Duration;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut cfg = Config::read_new()?;
let mut last_profile = String::new();
let connection = Connection::new_system()?;
let signals = CtrlSignals::new(&connection)?;
let mut last_profile_notif: Option<NotificationHandle> = None;
let mut last_led_notif: Option<NotificationHandle> = None;
let mut last_gfx_notif: Option<NotificationHandle> = None;
let mut last_chrg_notif: Option<NotificationHandle> = None;
loop {
std::thread::sleep(Duration::from_millis(100));
connection.process(std::time::Duration::from_millis(200))?;
if let Ok(mut lock) = signals.gfx_signal.lock() {
if let Some(vendor) = lock.take() {
if let Some(notif) = last_gfx_notif.take() {
notif.close();
}
let x = do_notif(&format!("Graphics mode changed to {}", vendor))?;
last_gfx_notif = Some(x);
}
}
if let Ok(mut lock) = signals.charge_signal.lock() {
if let Some(limit) = lock.take() {
if let Some(notif) = last_chrg_notif.take() {
notif.close();
}
let x = do_notif(&format!("Battery charge limit changed to {}", limit))?;
last_led_notif = Some(x);
}
}
if let Ok(mut lock) = signals.ledmode_signal.lock() {
if let Some(ledmode) = lock.take() {
if let Some(notif) = last_led_notif.take() {
notif.close();
}
let x = do_notif(&format!(
"Keyboard LED mode changed to {}",
<&str>::from(&ledmode)
))?;
last_led_notif = Some(x);
}
}
// We need to do the config read because of a limitation preventing
// easy dbus notification from the profile controller
cfg.read();
if last_profile != cfg.active_profile {
if let Some(notif) = last_profile_notif.take() {
notif.close();
}
if let Some(profile) = cfg.power_profiles.get(&cfg.active_profile) {
let x = do_thermal_notif(&profile, &cfg.active_profile)?;
last_profile_notif = Some(x);
last_profile = cfg.active_profile.clone();
}
}
}
}
fn do_thermal_notif(profile: &Profile, label: &str) -> Result<NotificationHandle, Box<dyn Error>> {
let fan = profile.fan_preset;
let turbo = if profile.turbo { "enabled" } else { "disabled" };
let icon = match fan {
0 => "asus_notif_yellow",
1 => "asus_notif_red",
2 => "asus_notif_green",
_ => "asus_notif_red",
};
let x = Notification::new()
.summary("ASUS ROG")
.body(&format!("Thermal profile changed to {}, turbo {}", label.to_uppercase(), turbo))
.hint(Hint::Resident(true))
.timeout(2000)
.hint(Hint::Category("device".into()))
//.hint(Hint::Transient(true))
.icon(icon)
.show()?;
Ok(x)
}
fn do_notif(body: &str) -> Result<NotificationHandle, Box<dyn Error>> {
let x = Notification::new()
.summary("ASUS ROG")
.body(body)
.timeout(2000)
.show()?;
Ok(x)
}

41
asusctl/Cargo.toml Normal file
View File

@@ -0,0 +1,41 @@
[package]
name = "asusctl"
license.workspace = true
version.workspace = true
readme.workspace = true
authors.workspace = true
repository.workspace = true
homepage.workspace = true
edition.workspace = true
[dependencies]
rog_anime = { path = "../rog-anime" }
rog_scsi = { path = "../rog-scsi" }
rog_slash = { path = "../rog-slash" }
rog_aura = { path = "../rog-aura" }
rog_dbus = { path = "../rog-dbus" }
rog_profiles = { path = "../rog-profiles" }
rog_platform = { path = "../rog-platform" }
dmi_id = { path = "../dmi-id" }
log.workspace = true
env_logger.workspace = true
ron.workspace = true
gumdrop.workspace = true
zbus.workspace = true
[dev-dependencies]
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

@@ -0,0 +1,34 @@
use std::env;
use std::error::Error;
use std::path::Path;
use std::process::exit;
use rog_anime::usb::get_anime_type;
use rog_anime::{AnimeDiagonal, AnimeType};
use rog_dbus::zbus_anime::AnimeProxyBlocking;
use zbus::blocking::Connection;
fn main() -> Result<(), Box<dyn Error>> {
let conn = Connection::system().unwrap();
let proxy = AnimeProxyBlocking::new(&conn).unwrap();
let args: Vec<String> = env::args().collect();
if args.len() != 3 {
println!("Usage: <filepath> <brightness>");
println!("e.g, asusctl/examples/doom_large.png 0.8");
exit(-1);
}
let matrix = AnimeDiagonal::from_png(
Path::new(&args[1]),
None,
args[2].parse::<f32>().unwrap(),
AnimeType::GA401,
)?;
let anime_type = get_anime_type();
proxy.write(matrix.into_data_buffer(anime_type)?).unwrap();
Ok(())
}

View File

@@ -0,0 +1,38 @@
use std::thread::sleep;
use std::time::Duration;
use rog_anime::usb::get_anime_type;
use rog_anime::{AnimeDiagonal, AnimeType};
use rog_dbus::zbus_anime::AnimeProxyBlocking;
use zbus::blocking::Connection;
// In usable data:
// Top row start at 1, ends at 32
// 74w x 36h diagonal used by the windows app
fn main() {
let conn = Connection::system().unwrap();
let proxy = AnimeProxyBlocking::new(&conn).unwrap();
for step in (2..50).rev() {
let mut matrix = AnimeDiagonal::new(AnimeType::GA401, None);
for c in (0..60).step_by(step) {
for i in matrix.get_mut().iter_mut() {
i[c] = 50;
}
}
for c in (0..35).step_by(step) {
for i in &mut matrix.get_mut()[c] {
*i = 50;
}
}
let anime_type = get_anime_type();
proxy
.write(matrix.into_data_buffer(anime_type).unwrap())
.unwrap();
sleep(Duration::from_millis(300));
}
}

View File

@@ -0,0 +1,44 @@
use std::env;
use std::path::Path;
use std::thread::sleep;
use rog_anime::usb::get_anime_type;
use rog_anime::{ActionData, ActionLoader, Sequences};
use rog_dbus::zbus_anime::AnimeProxyBlocking;
use zbus::blocking::Connection;
fn main() {
let conn = Connection::system().unwrap();
let proxy = AnimeProxyBlocking::new(&conn).unwrap();
let args: Vec<String> = env::args().collect();
if args.len() != 3 {
println!("Please supply filepath and brightness");
return;
}
let path = Path::new(&args[1]);
let brightness = args[2].parse::<f32>().unwrap();
let anime_type = get_anime_type();
let mut seq = Sequences::new(anime_type);
seq.insert(
0,
&ActionLoader::AsusAnimation {
file: path.into(),
time: rog_anime::AnimTime::Infinite,
brightness,
},
)
.unwrap();
loop {
for action in seq.iter() {
if let ActionData::Animation(frames) = action {
for frame in frames.frames() {
proxy.write(frame.frame().clone()).unwrap();
sleep(frame.delay());
}
}
}
}
}

View File

@@ -0,0 +1,50 @@
use std::convert::TryFrom;
use rog_anime::usb::get_anime_type;
use rog_anime::{AnimeDataBuffer, AnimeGrid};
use rog_dbus::zbus_anime::AnimeProxyBlocking;
use zbus::blocking::Connection;
// In usable data:
// Top row start at 1, ends at 32
// 74w x 36h diagonal used by the windows app
fn main() {
let conn = Connection::system().unwrap();
let proxy = AnimeProxyBlocking::new(&conn).unwrap();
let anime_type = get_anime_type();
let mut matrix = AnimeGrid::new(anime_type);
let tmp = matrix.get_mut();
let mut i = 0;
for (y, row) in tmp.iter_mut().enumerate() {
if y % 2 == 0 && i + 1 != row.len() - 1 {
i += 1;
}
row[row.len() - i] = 0x22;
if i > 5 {
row[row.len() - i + 5] = 0x22;
}
if i > 10 {
row[row.len() - i + 10] = 0x22;
}
if i > 15 {
row[row.len() - i + 15] = 0x22;
}
if i > 20 {
row[row.len() - i + 20] = 0x22;
}
if i > 25 {
row[row.len() - i + 25] = 0x22;
}
}
let matrix = <AnimeDataBuffer>::try_from(matrix).unwrap();
proxy.write(matrix).unwrap();
}

View File

@@ -0,0 +1,133 @@
use rog_anime::usb::get_anime_type;
use rog_anime::AnimeDataBuffer;
use rog_dbus::zbus_anime::AnimeProxyBlocking;
use zbus::blocking::Connection;
// In usable data:
// Top row start at 1, ends at 32
fn main() {
let conn = Connection::system().unwrap();
let proxy = AnimeProxyBlocking::new(&conn).unwrap();
let anime_type = get_anime_type();
let mut matrix = AnimeDataBuffer::new(anime_type);
matrix.data_mut()[1] = 100; // start = 1
for n in matrix.data_mut()[2..32].iter_mut() {
*n = 250;
}
matrix.data_mut()[32] = 100; // end
matrix.data_mut()[34] = 100; // start x = 0
matrix.data_mut()[66] = 100; // end
matrix.data_mut()[69] = 100; // start x = 1
matrix.data_mut()[101] = 100; // end
matrix.data_mut()[102] = 100; // start
matrix.data_mut()[134] = 100; // end
matrix.data_mut()[137] = 100; // start
matrix.data_mut()[169] = 100; // end
matrix.data_mut()[170] = 100; // start
matrix.data_mut()[202] = 100; // end
matrix.data_mut()[204] = 100; // start
matrix.data_mut()[236] = 100; // end
matrix.data_mut()[237] = 100; // start
matrix.data_mut()[268] = 100; // end
matrix.data_mut()[270] = 100; // start
matrix.data_mut()[301] = 100; // end
matrix.data_mut()[302] = 100; // start
matrix.data_mut()[332] = 100; // end
matrix.data_mut()[334] = 100; // start
matrix.data_mut()[364] = 100; // end
matrix.data_mut()[365] = 100; // start
matrix.data_mut()[394] = 100; // end
matrix.data_mut()[396] = 100; // start
matrix.data_mut()[425] = 100; // end
matrix.data_mut()[426] = 100; // start
matrix.data_mut()[454] = 100; // end
matrix.data_mut()[456] = 100; // start
matrix.data_mut()[484] = 100; // end
matrix.data_mut()[485] = 100; // start
matrix.data_mut()[512] = 100; // end
matrix.data_mut()[514] = 100; // start
matrix.data_mut()[541] = 100; // end
matrix.data_mut()[542] = 100; // start
matrix.data_mut()[568] = 100; // end
matrix.data_mut()[570] = 100; // start
matrix.data_mut()[596] = 100; // end
matrix.data_mut()[597] = 100; // start
matrix.data_mut()[622] = 100; // end
matrix.data_mut()[624] = 100; // start
matrix.data_mut()[649] = 100; // end
matrix.data_mut()[650] = 100; // start
matrix.data_mut()[674] = 100; // end
matrix.data_mut()[676] = 100; // start
matrix.data_mut()[700] = 100; // end
matrix.data_mut()[701] = 100; // start
matrix.data_mut()[724] = 100; // end
matrix.data_mut()[726] = 100; // start
matrix.data_mut()[749] = 100; // end
matrix.data_mut()[750] = 100; // start
matrix.data_mut()[772] = 100; // end
matrix.data_mut()[774] = 100; // start
matrix.data_mut()[796] = 100; // end
matrix.data_mut()[797] = 100; // start
matrix.data_mut()[818] = 100; // end
matrix.data_mut()[820] = 100; // start
matrix.data_mut()[841] = 100; // end
matrix.data_mut()[842] = 100; // start
matrix.data_mut()[862] = 100; // end
matrix.data_mut()[864] = 100; // start
matrix.data_mut()[884] = 100; // end
matrix.data_mut()[885] = 100; // start
matrix.data_mut()[904] = 100; // end
matrix.data_mut()[906] = 100; // start
matrix.data_mut()[925] = 100; // end
matrix.data_mut()[926] = 100; // start
matrix.data_mut()[944] = 100; // end
matrix.data_mut()[946] = 100; // start
matrix.data_mut()[964] = 100; // end
matrix.data_mut()[965] = 100; // start
matrix.data_mut()[982] = 100; // end
matrix.data_mut()[984] = 100; // start
matrix.data_mut()[1001] = 100; // end
matrix.data_mut()[1002] = 100; // start
matrix.data_mut()[1018] = 100; // end
matrix.data_mut()[1020] = 100; // start
matrix.data_mut()[1036] = 100; // end
matrix.data_mut()[1037] = 100; // start
matrix.data_mut()[1052] = 100; // end
matrix.data_mut()[1054] = 100; // start
matrix.data_mut()[1069] = 100; // end
matrix.data_mut()[1070] = 100; // start
matrix.data_mut()[1084] = 100; // end
matrix.data_mut()[1086] = 100; // start
matrix.data_mut()[1100] = 100; // end
matrix.data_mut()[1101] = 100; // start
matrix.data_mut()[1114] = 100; // end
matrix.data_mut()[1116] = 100; // start
matrix.data_mut()[1129] = 100; // end
matrix.data_mut()[1130] = 100; // start
matrix.data_mut()[1142] = 100; // end
matrix.data_mut()[1144] = 100; // start
matrix.data_mut()[1156] = 100; // end
matrix.data_mut()[1157] = 100; // start
matrix.data_mut()[1168] = 100; // end
matrix.data_mut()[1170] = 100; // start
matrix.data_mut()[1181] = 100; // end
matrix.data_mut()[1182] = 100; // start
matrix.data_mut()[1192] = 100; // end
matrix.data_mut()[1194] = 100; // start
matrix.data_mut()[1204] = 100; // end
matrix.data_mut()[1205] = 100; // start
matrix.data_mut()[1214] = 100; // end
matrix.data_mut()[1216] = 100; // start
matrix.data_mut()[1225] = 100; // end
matrix.data_mut()[1226] = 100; // start
matrix.data_mut()[1234] = 100; // end
matrix.data_mut()[1236] = 100; // start
for n in matrix.data_mut()[1237..1244].iter_mut() {
*n = 250;
}
matrix.data_mut()[1244] = 100; // end
println!("{:?}", &matrix);
proxy.write(matrix).unwrap();
}

View File

@@ -0,0 +1,39 @@
use std::convert::TryFrom;
use std::env;
use std::error::Error;
use std::path::Path;
use std::process::exit;
use rog_anime::usb::get_anime_type;
use rog_anime::{AnimeDataBuffer, AnimeImage, Vec2};
use rog_dbus::zbus_anime::AnimeProxyBlocking;
use zbus::blocking::Connection;
fn main() -> Result<(), Box<dyn Error>> {
let conn = Connection::system().unwrap();
let proxy = AnimeProxyBlocking::new(&conn).unwrap();
let args: Vec<String> = env::args().collect();
if args.len() != 7 {
println!("Usage: <filepath> <scale> <angle> <x pos> <y pos> <brightness>");
println!("e.g, asusctl/examples/doom_large.png 0.9 0.4 0.0 0.0 0.8");
exit(-1);
}
let anime_type = get_anime_type();
let matrix = AnimeImage::from_png(
Path::new(&args[1]),
args[2].parse::<f32>().unwrap(),
args[3].parse::<f32>().unwrap(),
Vec2::new(
args[4].parse::<f32>().unwrap(),
args[5].parse::<f32>().unwrap(),
),
args[6].parse::<f32>().unwrap(),
anime_type,
)?;
proxy.write(<AnimeDataBuffer>::try_from(&matrix)?).unwrap();
Ok(())
}

View File

@@ -0,0 +1,49 @@
use std::convert::TryFrom;
use std::env;
use std::error::Error;
use std::f32::consts::PI;
use std::path::Path;
use std::process::exit;
use std::thread::sleep;
use std::time::Duration;
use rog_anime::usb::get_anime_type;
use rog_anime::{AnimeDataBuffer, AnimeImage, Vec2};
use rog_dbus::zbus_anime::AnimeProxyBlocking;
use zbus::blocking::Connection;
fn main() -> Result<(), Box<dyn Error>> {
let conn = Connection::system().unwrap();
let proxy = AnimeProxyBlocking::new(&conn).unwrap();
let args: Vec<String> = env::args().collect();
if args.len() != 7 {
println!("Usage: <filepath> <scale> <angle> <x pos> <y pos> <brightness>");
println!("e.g, asusctl/examples/doom_large.png 0.9 0.4 0.0 0.0 0.8");
exit(-1);
}
let anime_type = get_anime_type();
let mut matrix = AnimeImage::from_png(
Path::new(&args[1]),
args[2].parse::<f32>().unwrap(),
args[3].parse::<f32>().unwrap(),
Vec2::new(
args[4].parse::<f32>().unwrap(),
args[5].parse::<f32>().unwrap(),
),
args[6].parse::<f32>().unwrap(),
anime_type,
)?;
loop {
matrix.angle += 0.05;
if matrix.angle > PI * 2.0 {
matrix.angle = 0.0;
}
matrix.update();
proxy.write(<AnimeDataBuffer>::try_from(&matrix)?).unwrap();
sleep(Duration::from_micros(500));
}
}

View File

@@ -0,0 +1,113 @@
//! Very bad rushed example. The better way to do this would be to have
//! the balles move on their own square grid, then translate that to the
//! key layout via shape by pitch etc.
use rog_aura::{
layouts::{KeyLayout, KeyRow},
KeyColourArray,
};
use rog_dbus::RogDbusClientBlocking;
use std::collections::VecDeque;
#[derive(Debug, Clone)]
struct Ball {
position: (f32, f32),
direction: (f32, f32),
trail: VecDeque<(f32, f32)>,
}
impl Ball {
fn new(x: f32, y: f32, trail_len: u32) -> Self {
let mut trail = VecDeque::new();
for _ in 1..=trail_len {
trail.push_back((x, y));
}
Ball {
position: (x, y),
direction: (1.0, 1.0),
trail,
}
}
#[allow(clippy::if_same_then_else)]
fn update(&mut self, key_map: &[KeyRow]) {
self.position.0 += self.direction.0;
self.position.1 += self.direction.1;
if self.position.1.abs() as usize >= key_map.len() {
self.direction.1 *= -1.0;
self.position.1 += self.direction.1;
self.direction.0 *= -1.0;
self.position.0 += self.direction.0;
}
if self.position.0.abs() as usize >= key_map[self.position.1.abs() as usize].row_ref().len()
{
self.direction.1 *= -1.0;
self.position.1 += self.direction.1;
}
if self.position.0 as usize >= key_map[self.position.1.abs() as usize].row_ref().len() {
self.direction.0 *= -1.0;
self.position.0 += self.direction.0;
}
let pos = self.position;
if pos.1 == key_map[pos.1.abs() as usize].row_ref().len() as f32 - 1.0 || pos.1 <= 0.0 {
self.direction.0 *= -1.0;
} else if key_map[(pos.1) as usize].row_ref()[(pos.0) as usize].is_placeholder() {
self.direction.0 *= -1.0;
}
if pos.0 == key_map.len() as f32 - 1.0 || pos.0 <= 0.0 {
self.direction.1 *= -1.0;
} else if key_map[(pos.1) as usize].row_ref()[(pos.0) as usize].is_placeholder() {
self.direction.1 *= -1.0;
}
self.trail.pop_front();
self.trail.push_back(self.position);
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let (dbus, _) = RogDbusClientBlocking::new()?;
let mut colours = KeyColourArray::new();
let layout = KeyLayout::gx502_layout();
let mut balls = [Ball::new(2.0, 1.0, 12), Ball::new(5.0, 2.0, 12)];
// let mut balls = [Ball::new(2, 1, 12)];
loop {
for (n, ball) in balls.iter_mut().enumerate() {
ball.update(layout.rows_ref());
for (i, pos) in ball.trail.iter().enumerate() {
if let Some(c) = colours
.rgb_for_key(layout.rows_ref()[pos.1.abs() as usize].row_ref()[pos.0 as usize])
{
c[0] = 0;
c[1] = 0;
c[2] = 0;
if n == 0 {
c[0] = i as u8 * (255 / ball.trail.len() as u8);
} else if n == 1 {
c[1] = i as u8 * (255 / ball.trail.len() as u8);
} else if n == 2 {
c[2] = i as u8 * (255 / ball.trail.len() as u8);
}
};
}
if let Some(c) = colours.rgb_for_key(
layout.rows_ref()[ball.position.1.abs() as usize].row_ref()
[ball.position.0 as usize],
) {
c[0] = 255;
c[1] = 255;
c[2] = 255;
};
}
dbus.proxies().led().direct_addressing_raw(colours.get())?;
std::thread::sleep(std::time::Duration::from_millis(150));
}
}

View File

@@ -0,0 +1,69 @@
//! Using a combination of key-colour array plus a key layout to generate
//! outputs.
use rog_aura::effects::{AdvancedEffects, Effect};
use rog_aura::keyboard::{KeyLayout, LedCode};
use rog_aura::Colour;
use rog_dbus::zbus_aura::AuraProxyBlocking;
use zbus::blocking::Connection;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let layout = KeyLayout::default_layout();
let conn = Connection::system().unwrap();
let proxy = AuraProxyBlocking::new(&conn).unwrap();
let mut seq = AdvancedEffects::new(true);
// let zone = Effect::Breathe(rog_aura::effects::Breathe::new(
// RgbAddress::Single,
// Colour(166, 127, 166),
// Colour(127, 155, 20),
// rog_aura::Speed::High,
// ));
// seq.push(zone);
// let zone = Effect::DoomLightFlash(rog_aura::effects::DoomLightFlash::new(
// RgbAddress::Single,
// Colour(200, 0, 0),
// 80,
// 10,
// ));
// seq.push(zone);
let zone = Effect::DoomFlicker(rog_aura::effects::DoomFlicker::new(
LedCode::SingleZone,
Colour {
r: 200,
g: 110,
b: 0,
},
100,
10,
));
seq.push(zone);
// let zone = Effect::Breathe(rog_aura::effects::Breathe::new(
// RgbAddress::KeyboardCenterLeft,
// Colour(16, 127, 255),
// Colour(127, 15, 20),
// rog_aura::Speed::Low,
// ));
// seq.push(zone);
// let zone = Effect::Breathe(rog_aura::effects::Breathe::new(
// RgbAddress::LightbarRightCorner,
// Colour(0, 255, 255),
// Colour(255, 0, 255),
// rog_aura::Speed::Med,
// ));
// seq.push(zone);
loop {
seq.next_state(&layout);
let packets = seq.create_packets();
proxy.direct_addressing_raw(packets)?;
std::thread::sleep(std::time::Duration::from_millis(33));
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

BIN
asusctl/examples/doom.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

BIN
asusctl/examples/ferris.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
asusctl/examples/nudoom.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

BIN
asusctl/examples/rust.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

154
asusctl/src/anime_cli.rs Normal file
View File

@@ -0,0 +1,154 @@
use gumdrop::Options;
use rog_anime::usb::{AnimAwake, AnimBooting, AnimShutdown, AnimSleeping, Brightness};
use rog_anime::AnimeType;
#[derive(Options)]
pub struct AnimeCommand {
#[options(help = "print help message")]
pub help: bool,
#[options(meta = "", help = "override the display type")]
pub override_type: Option<AnimeType>,
#[options(meta = "", help = "enable/disable the display")]
pub enable_display: Option<bool>,
#[options(meta = "", help = "enable/disable the builtin run/powersave animation")]
pub enable_powersave_anim: Option<bool>,
#[options(
meta = "",
help = "set global base brightness value <Off, Low, Med, High>"
)]
pub brightness: Option<Brightness>,
#[options(help = "clear the display")]
pub clear: bool,
#[options(
no_short,
meta = "",
help = "turn the anime off when external power is unplugged"
)]
pub off_when_unplugged: Option<bool>,
#[options(
no_short,
meta = "",
help = "turn the anime off when the laptop suspends"
)]
pub off_when_suspended: Option<bool>,
#[options(
no_short,
meta = "",
help = "turn the anime off when the lid is closed"
)]
pub off_when_lid_closed: Option<bool>,
#[options(no_short, meta = "", help = "Off with his head!!!")]
pub off_with_his_head: Option<bool>,
#[options(command)]
pub command: Option<AnimeActions>,
}
#[derive(Options)]
pub enum AnimeActions {
#[options(help = "display a PNG image")]
Image(AnimeImage),
#[options(help = "display a diagonal/pixel-perfect PNG")]
PixelImage(AnimeImageDiagonal),
#[options(help = "display an animated GIF")]
Gif(AnimeGif),
#[options(help = "display an animated diagonal/pixel-perfect GIF")]
PixelGif(AnimeGifDiagonal),
#[options(help = "change which builtin animations are shown")]
SetBuiltins(Builtins),
}
#[derive(Options)]
pub struct Builtins {
#[options(help = "print help message")]
pub help: bool,
#[options(
meta = "",
help = "Default is used if unspecified, <default:GlitchConstruction, StaticEmergence>"
)]
pub boot: AnimBooting,
#[options(
meta = "",
help = "Default is used if unspecified, <default:BinaryBannerScroll, RogLogoGlitch>"
)]
pub awake: AnimAwake,
#[options(
meta = "",
help = "Default is used if unspecified, <default:BannerSwipe, Starfield>"
)]
pub sleep: AnimSleeping,
#[options(
meta = "",
help = "Default is used if unspecified, <default:GlitchOut, SeeYa>"
)]
pub shutdown: AnimShutdown,
#[options(meta = "", help = "set/apply the animations <true/false>")]
pub set: Option<bool>,
}
#[derive(Options)]
pub struct AnimeImage {
#[options(help = "print help message")]
pub help: bool,
#[options(meta = "", help = "full path to the png to display")]
pub path: String,
#[options(meta = "", default = "1.0", help = "scale 1.0 == normal")]
pub scale: f32,
#[options(meta = "", default = "0.0", help = "x position (float)")]
pub x_pos: f32,
#[options(meta = "", default = "0.0", help = "y position (float)")]
pub y_pos: f32,
#[options(meta = "", default = "0.0", help = "the angle in radians")]
pub angle: f32,
#[options(meta = "", default = "1.0", help = "brightness 0.0-1.0")]
pub bright: f32,
}
#[derive(Options)]
pub struct AnimeImageDiagonal {
#[options(help = "print help message")]
pub help: bool,
#[options(meta = "", help = "full path to the png to display")]
pub path: String,
#[options(meta = "", default = "1.0", help = "brightness 0.0-1.0")]
pub bright: f32,
}
#[derive(Options)]
pub struct AnimeGif {
#[options(help = "print help message")]
pub help: bool,
#[options(meta = "", help = "full path to the png to display")]
pub path: String,
#[options(meta = "", default = "1.0", help = "scale 1.0 == normal")]
pub scale: f32,
#[options(meta = "", default = "0.0", help = "x position (float)")]
pub x_pos: f32,
#[options(meta = "", default = "0.0", help = "y position (float)")]
pub y_pos: f32,
#[options(meta = "", default = "0.0", help = "the angle in radians")]
pub angle: f32,
#[options(meta = "", default = "1.0", help = "brightness 0.0-1.0")]
pub bright: f32,
#[options(
meta = "",
default = "1",
help = "how many loops to play - 0 is infinite"
)]
pub loops: u32,
}
#[derive(Options)]
pub struct AnimeGifDiagonal {
#[options(help = "print help message")]
pub help: bool,
#[options(meta = "", help = "full path to the png to display")]
pub path: String,
#[options(meta = "", default = "1.0", help = "brightness 0.0-1.0")]
pub bright: f32,
#[options(
meta = "",
default = "1",
help = "how many loops to play - 0 is infinite"
)]
pub loops: u32,
}

369
asusctl/src/aura_cli.rs Normal file
View File

@@ -0,0 +1,369 @@
use std::str::FromStr;
use gumdrop::Options;
use rog_aura::error::Error;
use rog_aura::{AuraEffect, AuraModeNum, AuraZone, Colour, Direction, Speed};
#[derive(Options, Debug)]
pub struct LedPowerCommand1 {
#[options(help = "print help message")]
pub help: bool,
#[options(meta = "", help = "Control if LEDs enabled while awake <true/false>")]
pub awake: Option<bool>,
#[options(help = "Use with awake option, if excluded defaults to false")]
pub keyboard: bool,
#[options(help = "Use with awake option, if excluded defaults to false")]
pub lightbar: bool,
#[options(meta = "", help = "Control boot animations <true/false>")]
pub boot: Option<bool>,
#[options(meta = "", help = "Control suspend animations <true/false>")]
pub sleep: Option<bool>,
}
#[derive(Options, Debug)]
pub struct LedPowerCommand2 {
#[options(help = "print help message")]
pub help: bool,
#[options(command)]
pub command: Option<SetAuraZoneEnabled>,
}
#[derive(Options, Debug)]
pub enum SetAuraZoneEnabled {
/// Applies to both old and new models
#[options(help = "")]
Keyboard(AuraPowerStates),
#[options(help = "")]
Logo(AuraPowerStates),
#[options(help = "")]
Lightbar(AuraPowerStates),
#[options(help = "")]
Lid(AuraPowerStates),
#[options(help = "")]
RearGlow(AuraPowerStates),
#[options(help = "")]
Ally(AuraPowerStates),
}
#[derive(Debug, Clone, Options)]
pub struct AuraPowerStates {
#[options(help = "print help message")]
pub help: bool,
#[options(help = "defaults to false if option unused")]
pub boot: bool,
#[options(help = "defaults to false if option unused")]
pub awake: bool,
#[options(help = "defaults to false if option unused")]
pub sleep: bool,
#[options(help = "defaults to false if option unused")]
pub shutdown: bool,
}
#[derive(Options)]
pub struct LedBrightness {
level: Option<u8>,
}
impl LedBrightness {
pub fn new(level: Option<u8>) -> Self {
LedBrightness { level }
}
pub fn level(&self) -> Option<u8> {
self.level
}
}
impl FromStr for LedBrightness {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let s = s.to_lowercase();
match s.as_str() {
"off" => Ok(LedBrightness { level: Some(0x00) }),
"low" => Ok(LedBrightness { level: Some(0x01) }),
"med" => Ok(LedBrightness { level: Some(0x02) }),
"high" => Ok(LedBrightness { level: Some(0x03) }),
_ => {
print!("Invalid argument, must be one of: off, low, med, high");
Err(Error::ParseBrightness)
}
}
}
}
#[allow(clippy::to_string_trait_impl)]
impl ToString for LedBrightness {
fn to_string(&self) -> String {
let s = match self.level {
Some(0x00) => "low",
Some(0x01) => "med",
Some(0x02) => "high",
_ => "unknown",
};
s.to_owned()
}
}
#[derive(Debug, Clone, Options, Default)]
pub struct SingleSpeed {
#[options(help = "print help message")]
help: bool,
#[options(no_long, meta = "WORD", help = "set the speed: low, med, high")]
pub speed: Speed,
#[options(
no_long,
meta = "",
help = "set the zone for this effect e.g, 0, 1, one, logo, lightbar-left"
)]
pub zone: AuraZone,
}
#[derive(Debug, Clone, Options, Default)]
pub struct SingleSpeedDirection {
#[options(help = "print help message")]
help: bool,
#[options(no_long, meta = "", help = "set the direction: up, down, left, right")]
pub direction: Direction,
#[options(no_long, meta = "", help = "set the speed: low, med, high")]
pub speed: Speed,
#[options(
no_long,
meta = "",
help = "set the zone for this effect e.g, 0, 1, one, logo, lightbar-left"
)]
pub zone: AuraZone,
}
#[derive(Debug, Clone, Default, Options)]
pub struct SingleColour {
#[options(help = "print help message")]
help: bool,
#[options(no_long, meta = "", help = "set the RGB value e.g, ff00ff")]
pub colour: Colour,
#[options(
no_long,
meta = "",
help = "set the zone for this effect e.g, 0, 1, one, logo, lightbar-left"
)]
pub zone: AuraZone,
}
#[derive(Debug, Clone, Default, Options)]
pub struct SingleColourSpeed {
#[options(help = "print help message")]
help: bool,
#[options(no_long, meta = "", help = "set the RGB value e.g, ff00ff")]
pub colour: Colour,
#[options(no_long, meta = "", help = "set the speed: low, med, high")]
pub speed: Speed,
#[options(
no_long,
meta = "",
help = "set the zone for this effect e.g, 0, 1, one, logo, lightbar-left"
)]
pub zone: AuraZone,
}
#[derive(Debug, Clone, Options, Default)]
pub struct TwoColourSpeed {
#[options(help = "print help message")]
help: bool,
#[options(no_long, meta = "", help = "set the first RGB value e.g, ff00ff")]
pub colour: Colour,
#[options(no_long, meta = "", help = "set the second RGB value e.g, ff00ff")]
pub colour2: Colour,
#[options(no_long, meta = "", help = "set the speed: low, med, high")]
pub speed: Speed,
#[options(
no_long,
meta = "",
help = "set the zone for this effect e.g, 0, 1, one, logo, lightbar-left"
)]
pub zone: AuraZone,
}
#[derive(Debug, Clone, Default, Options)]
pub struct MultiZone {
#[options(help = "print help message")]
help: bool,
#[options(short = "a", meta = "", help = "set the RGB value e.g, ff00ff")]
pub colour1: Colour,
#[options(short = "b", meta = "", help = "set the RGB value e.g, ff00ff")]
pub colour2: Colour,
#[options(short = "c", meta = "", help = "set the RGB value e.g, ff00ff")]
pub colour3: Colour,
#[options(short = "d", meta = "", help = "set the RGB value e.g, ff00ff")]
pub colour4: Colour,
}
#[derive(Debug, Clone, Default, Options)]
pub struct MultiColourSpeed {
#[options(help = "print help message")]
help: bool,
#[options(short = "a", meta = "", help = "set the RGB value e.g, ff00ff")]
pub colour1: Colour,
#[options(short = "b", meta = "", help = "set the RGB value e.g, ff00ff")]
pub colour2: Colour,
#[options(short = "c", meta = "", help = "set the RGB value e.g, ff00ff")]
pub colour3: Colour,
#[options(short = "d", meta = "", help = "set the RGB value e.g, ff00ff")]
pub colour4: Colour,
#[options(no_long, meta = "", help = "set the speed: low, med, high")]
pub speed: Speed,
}
/// Byte value for setting the built-in mode.
///
/// Enum corresponds to the required integer value
// NOTE: The option names here must match those in rog-aura crate
#[derive(Options)]
pub enum SetAuraBuiltin {
#[options(help = "set a single static colour")]
Static(SingleColour), // 0
#[options(help = "pulse between one or two colours")]
Breathe(TwoColourSpeed), // 1
#[options(help = "strobe through all colours")]
RainbowCycle(SingleSpeed), // 2
#[options(help = "rainbow cycling in one of four directions")]
RainbowWave(SingleSpeedDirection), // 3
#[options(help = "rain pattern mimicking raindrops")]
Stars(TwoColourSpeed), // 4
#[options(help = "rain pattern of three preset colours")]
Rain(SingleSpeed), // 5
#[options(help = "pressed keys are highlighted to fade")]
Highlight(SingleColourSpeed), // 6
#[options(help = "pressed keys generate horizontal laser")]
Laser(SingleColourSpeed), // 7
#[options(help = "pressed keys ripple outwards like a splash")]
Ripple(SingleColourSpeed), // 8
#[options(help = "set a rapid pulse")]
Pulse(SingleColour), // 10
#[options(help = "set a vertical line zooming from left")]
Comet(SingleColour), // 11
#[options(help = "set a wide vertical line zooming from left")]
Flash(SingleColour), // 12
}
impl Default for SetAuraBuiltin {
fn default() -> Self {
SetAuraBuiltin::Static(SingleColour::default())
}
}
impl From<&SingleColour> for AuraEffect {
fn from(aura: &SingleColour) -> Self {
Self {
colour1: aura.colour,
zone: aura.zone,
..Default::default()
}
}
}
impl From<&SingleSpeed> for AuraEffect {
fn from(aura: &SingleSpeed) -> Self {
Self {
speed: aura.speed,
zone: aura.zone,
..Default::default()
}
}
}
impl From<&SingleColourSpeed> for AuraEffect {
fn from(aura: &SingleColourSpeed) -> Self {
Self {
colour1: aura.colour,
speed: aura.speed,
zone: aura.zone,
..Default::default()
}
}
}
impl From<&TwoColourSpeed> for AuraEffect {
fn from(aura: &TwoColourSpeed) -> Self {
Self {
colour1: aura.colour,
colour2: aura.colour2,
zone: aura.zone,
..Default::default()
}
}
}
impl From<&SingleSpeedDirection> for AuraEffect {
fn from(aura: &SingleSpeedDirection) -> Self {
Self {
speed: aura.speed,
direction: aura.direction,
zone: aura.zone,
..Default::default()
}
}
}
impl From<&SetAuraBuiltin> for AuraEffect {
fn from(aura: &SetAuraBuiltin) -> Self {
match aura {
SetAuraBuiltin::Static(x) => {
let mut data: AuraEffect = x.into();
data.mode = AuraModeNum::Static;
data
}
SetAuraBuiltin::Breathe(x) => {
let mut data: AuraEffect = x.into();
data.mode = AuraModeNum::Breathe;
data
}
SetAuraBuiltin::RainbowCycle(x) => {
let mut data: AuraEffect = x.into();
data.mode = AuraModeNum::RainbowCycle;
data
}
SetAuraBuiltin::RainbowWave(x) => {
let mut data: AuraEffect = x.into();
data.mode = AuraModeNum::RainbowWave;
data
}
SetAuraBuiltin::Stars(x) => {
let mut data: AuraEffect = x.into();
data.mode = AuraModeNum::Star;
data
}
SetAuraBuiltin::Rain(x) => {
let mut data: AuraEffect = x.into();
data.mode = AuraModeNum::Rain;
data
}
SetAuraBuiltin::Highlight(x) => {
let mut data: AuraEffect = x.into();
data.mode = AuraModeNum::Highlight;
data
}
SetAuraBuiltin::Laser(x) => {
let mut data: AuraEffect = x.into();
data.mode = AuraModeNum::Laser;
data
}
SetAuraBuiltin::Ripple(x) => {
let mut data: AuraEffect = x.into();
data.mode = AuraModeNum::Ripple;
data
}
SetAuraBuiltin::Pulse(x) => {
let mut data: AuraEffect = x.into();
data.mode = AuraModeNum::Pulse;
data
}
SetAuraBuiltin::Comet(x) => {
let mut data: AuraEffect = x.into();
data.mode = AuraModeNum::Comet;
data
}
SetAuraBuiltin::Flash(x) => {
let mut data: AuraEffect = x.into();
data.mode = AuraModeNum::Flash;
data
}
}
}
}

134
asusctl/src/cli_opts.rs Normal file
View File

@@ -0,0 +1,134 @@
use gumdrop::Options;
use rog_platform::platform::PlatformProfile;
use crate::anime_cli::AnimeCommand;
use crate::aura_cli::{LedBrightness, LedPowerCommand1, LedPowerCommand2, SetAuraBuiltin};
use crate::fan_curve_cli::FanCurveCommand;
use crate::scsi_cli::ScsiCommand;
use crate::slash_cli::SlashCommand;
#[derive(Default, Options)]
pub struct CliStart {
#[options(help_flag, help = "print help message")]
pub help: bool,
#[options(help = "show program version number")]
pub version: bool,
#[options(help = "show supported functions of this laptop")]
pub show_supported: bool,
#[options(meta = "", help = "<off, low, med, high>")]
pub kbd_bright: Option<LedBrightness>,
#[options(help = "Toggle to next keyboard brightness")]
pub next_kbd_bright: bool,
#[options(help = "Toggle to previous keyboard brightness")]
pub prev_kbd_bright: bool,
#[options(meta = "", help = "Set your battery charge limit <20-100>")]
pub chg_limit: Option<u8>,
#[options(help = "Toggle one-shot battery charge to 100%")]
pub one_shot_chg: bool,
#[options(command)]
pub command: Option<CliCommand>,
}
#[derive(Options)]
pub enum CliCommand {
#[options(help = "Set the keyboard lighting from built-in modes")]
Aura(LedModeCommand),
#[options(help = "Set the LED power states")]
AuraPowerOld(LedPowerCommand1),
#[options(help = "Set the LED power states")]
AuraPower(LedPowerCommand2),
#[options(help = "Set or select platform_profile")]
Profile(ProfileCommand),
#[options(help = "Set, select, or modify fan curves if supported")]
FanCurve(FanCurveCommand),
#[options(help = "Set the graphics mode (obsoleted by supergfxctl)")]
Graphics(GraphicsCommand),
#[options(name = "anime", help = "Manage AniMe Matrix")]
Anime(AnimeCommand),
#[options(name = "slash", help = "Manage Slash Ledbar")]
Slash(SlashCommand),
#[options(name = "scsi", help = "Manage SCSI external drive")]
Scsi(ScsiCommand),
#[options(
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"
)]
Armoury(ArmouryCommand),
#[options(name = "backlight", help = "Set screen backlight levels")]
Backlight(BacklightCommand),
}
#[derive(Debug, Clone, Options)]
pub struct ProfileCommand {
#[options(help = "print help message")]
pub help: bool,
#[options(help = "toggle to next profile in list")]
pub next: bool,
#[options(help = "list available profiles")]
pub list: bool,
#[options(help = "get profile")]
pub profile_get: bool,
#[options(meta = "", help = "set the active profile")]
pub profile_set: Option<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)]
pub struct LedModeCommand {
#[options(help = "print help message")]
pub help: bool,
#[options(help = "switch to next aura mode")]
pub next_mode: bool,
#[options(help = "switch to previous aura mode")]
pub prev_mode: bool,
#[options(command)]
pub command: Option<SetAuraBuiltin>,
}
#[derive(Options)]
pub struct GraphicsCommand {
#[options(help = "print help message")]
pub help: bool,
}
#[derive(Options, Debug)]
pub struct ArmouryCommand {
#[options(help = "print help message")]
pub help: bool,
#[options(
free,
help = "append each value name followed by the value to set. `-1` sets to default"
)]
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

@@ -0,0 +1,49 @@
use gumdrop::Options;
use rog_platform::platform::PlatformProfile;
use rog_profiles::fan_curve_set::CurveData;
use rog_profiles::FanCurvePU;
#[derive(Debug, Clone, Options)]
pub struct FanCurveCommand {
#[options(help = "print help message")]
pub help: bool,
#[options(help = "get enabled fan profiles")]
pub get_enabled: bool,
#[options(help = "set the active profile's fan curve to default")]
pub default: bool,
#[options(
meta = "",
help = "profile to modify fan-curve for. Shows data if no options provided"
)]
pub mod_profile: Option<PlatformProfile>,
#[options(
meta = "",
help = "enable or disable <true/false> fan all curves for a profile. `--mod_profile` \
required"
)]
pub enable_fan_curves: Option<bool>,
#[options(
meta = "",
help = "enable or disable <true/false> a single fan curve for a profile. `--mod_profile` \
and `--fan` required"
)]
pub enable_fan_curve: Option<bool>,
#[options(
meta = "",
help = "select fan <cpu/gpu/mid> to modify. `--mod_profile` required"
)]
pub fan: Option<FanCurvePU>,
#[options(
meta = "",
help = "data format = 30c:1%,49c:2%,59c:3%,69c:4%,79c:31%,89c:49%,99c:56%,109c:58%. \
`--mod-profile` required. If '%' is omitted the fan range is 0-255"
)]
pub data: Option<CurveData>,
}

1227
asusctl/src/main.rs Normal file

File diff suppressed because it is too large Load Diff

35
asusctl/src/scsi_cli.rs Normal file
View File

@@ -0,0 +1,35 @@
use gumdrop::Options;
use rog_scsi::{AuraMode, Colour, Direction, Speed};
#[derive(Options)]
pub struct ScsiCommand {
#[options(help = "print help message")]
pub help: bool,
#[options(help = "Enable the SCSI drive LEDs")]
pub enable: Option<bool>,
#[options(meta = "", help = "Set LED mode (so 'list' for all options)")]
pub mode: Option<AuraMode>,
#[options(
meta = "",
help = "Set LED mode speed <slowest, slow, med, fast, fastest> (does not apply to all)"
)]
pub speed: Option<Speed>,
#[options(
meta = "",
help = "Set LED mode direction <forward, reverse> (does not apply to all)"
)]
pub direction: Option<Direction>,
#[options(
meta = "",
help = "Set LED colours <hex>, specify up to 4 with repeated arg"
)]
pub colours: Vec<Colour>,
#[options(help = "list available animations")]
pub list: bool,
}

37
asusctl/src/slash_cli.rs Normal file
View File

@@ -0,0 +1,37 @@
use gumdrop::Options;
use rog_slash::SlashMode;
#[derive(Options)]
pub struct SlashCommand {
#[options(help = "print help message")]
pub help: bool,
#[options(help = "Enable the Slash Ledbar")]
pub enable: bool,
#[options(help = "Disable the Slash Ledbar")]
pub disable: bool,
#[options(short = "l", meta = "", help = "Set brightness value <0-255>")]
pub brightness: Option<u8>,
#[options(meta = "", help = "Set interval value <0-5>")]
pub interval: Option<u8>,
#[options(meta = "", help = "Set SlashMode (so 'list' for all options)")]
pub mode: Option<SlashMode>,
#[options(help = "list available animations")]
pub list: bool,
#[options(short = "B", meta = "", help = "Show the animation on boot")]
pub show_on_boot: Option<bool>,
#[options(short = "S", meta = "", help = "Show the animation on shutdown")]
pub show_on_shutdown: Option<bool>,
#[options(short = "s", meta = "", help = "Show the animation on sleep")]
pub show_on_sleep: Option<bool>,
#[options(short = "b", meta = "", help = "Show the animation on battery")]
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(
short = "w",
meta = "",
help = "Show the low-battery warning animation"
)]
pub show_battery_warning: Option<bool>,
}

47
asusd-user/Cargo.toml Normal file
View File

@@ -0,0 +1,47 @@
[package]
name = "asusd-user"
license.workspace = true
version.workspace = true
readme.workspace = true
authors.workspace = true
repository.workspace = true
homepage.workspace = true
edition.workspace = true
[[bin]]
name = "asusd-user"
path = "src/daemon.rs"
[features]
default = []
local_data = []
[dependencies]
dirs.workspace = true
smol.workspace = true
# serialisation
serde.workspace = true
ron.workspace = true
rog_anime = { path = "../rog-anime" }
rog_aura = { path = "../rog-aura" }
rog_dbus = { path = "../rog-dbus" }
rog_platform = { path = "../rog-platform" }
config-traits = { path = "../config-traits" }
zbus.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"],
]

14
asusd-user/README.md Normal file
View File

@@ -0,0 +1,14 @@
# daemon-user
This crate is for the binary of `asusd-user` and its helper lib.
The purpose of `asusd-user` is to run in userland and provide the user + third-party apps an interface for such things as creating AniMe sequences (and more in future, see todo list).
`asusd-user` should try to be as simple as possible while allowing a decent degree of control.
## TODO
- [ ] CLI for basic settings/interaction
- [ ] RGB keyboard per-key programs
- [ ] User profiles (fan, cpu etc). These would be replacing the system-daemon profiles only when the user is active, otherwise system-daemon defaults to system settings.
- [ ] Audio EQ visualiser - for use with anime + keyboard lighting

232
asusd-user/src/config.rs Normal file
View File

@@ -0,0 +1,232 @@
use std::path::PathBuf;
use std::time::Duration;
use config_traits::{StdConfig, StdConfigLoad};
use rog_anime::{ActionLoader, AnimTime, AnimeType, Fade, Sequences as AnimeSequences, Vec2};
use rog_aura::effects::{AdvancedEffects as AuraSequences, Breathe, DoomFlicker, Effect, Static};
use rog_aura::keyboard::LedCode;
use rog_aura::{Colour, Speed};
use serde::{Deserialize, Serialize};
use crate::error::Error;
const ROOT_CONF_DIR: &str = "rog";
fn root_conf_dir() -> PathBuf {
let mut dir = dirs::config_dir().unwrap_or_else(|| PathBuf::from("/tmp"));
dir.push(ROOT_CONF_DIR);
dir
}
#[derive(Debug, Deserialize, Serialize)]
pub struct ConfigAnime {
pub name: String,
pub anime: Vec<ActionLoader>,
}
impl ConfigAnime {
pub fn create(&self, anime_type: AnimeType) -> Result<AnimeSequences, Error> {
let mut seq = AnimeSequences::new(anime_type);
for (idx, action) in self.anime.iter().enumerate() {
seq.insert(idx, action)?;
}
Ok(seq)
}
pub fn set_name(mut self, name: String) -> Self {
self.name = name;
self
}
}
impl Default for ConfigAnime {
fn default() -> Self {
Self {
name: "anime-default".to_owned(),
anime: vec![
ActionLoader::AsusImage {
file: "/usr/share/asusd/anime/custom/diagonal-template.png".into(),
brightness: 1.0,
time: AnimTime::Fade(Fade::new(
Duration::from_secs(2),
None,
Duration::from_secs(2),
)),
},
ActionLoader::AsusAnimation {
file: "/usr/share/asusd/anime/asus/rog/Sunset.gif".into(),
brightness: 0.5,
time: AnimTime::Fade(Fade::new(
Duration::from_secs(6),
None,
Duration::from_secs(3),
)),
},
ActionLoader::ImageAnimation {
file: "/usr/share/asusd/anime/custom/sonic-run.gif".into(),
scale: 0.9,
angle: 0.65,
translation: Vec2::default(),
brightness: 0.5,
time: AnimTime::Fade(Fade::new(
Duration::from_secs(2),
Some(Duration::from_secs(2)),
Duration::from_secs(2),
)),
},
ActionLoader::Image {
file: "/usr/share/asusd/anime/custom/rust.png".into(),
scale: 1.0,
angle: 0.0,
translation: Vec2::default(),
time: AnimTime::Fade(Fade::new(
Duration::from_secs(2),
Some(Duration::from_secs(1)),
Duration::from_secs(2),
)),
brightness: 0.6,
},
ActionLoader::Pause(Duration::from_secs(1)),
ActionLoader::ImageAnimation {
file: "/usr/share/asusd/anime/custom/sonic-wait.gif".into(),
scale: 0.9,
angle: 0.0,
translation: Vec2::new(3.0, 2.0),
brightness: 0.5,
time: AnimTime::Count(2),
},
],
}
}
}
impl StdConfig for ConfigAnime {
fn new() -> Self {
Self::default()
}
fn file_name(&self) -> String {
format!("{}.ron", self.name)
}
fn config_dir() -> std::path::PathBuf {
root_conf_dir()
}
}
impl StdConfigLoad for ConfigAnime {}
#[derive(Debug, Deserialize, Serialize)]
pub struct ConfigAura {
pub name: String,
pub aura: AuraSequences,
}
impl ConfigAura {
pub fn set_name(mut self, name: String) -> Self {
self.name = name;
self
}
}
impl Default for ConfigAura {
fn default() -> Self {
let mut seq = AuraSequences::new(false);
let mut key = Effect::Breathe(Breathe::new(
LedCode::W,
Colour {
r: 255,
g: 0,
b: 20,
},
Colour {
r: 20,
g: 255,
b: 0,
},
Speed::Low,
));
seq.push(key.clone());
key.set_led(LedCode::A);
seq.push(key.clone());
key.set_led(LedCode::S);
seq.push(key.clone());
key.set_led(LedCode::D);
seq.push(key);
let key = Effect::Breathe(Breathe::new(
LedCode::F,
Colour { r: 255, g: 0, b: 0 },
Colour { r: 255, g: 0, b: 0 },
Speed::High,
));
seq.push(key);
let mut key = Effect::Static(Static::new(LedCode::RCtrl, Colour { r: 0, g: 0, b: 255 }));
seq.push(key.clone());
key.set_led(LedCode::LCtrl);
seq.push(key.clone());
key.set_led(LedCode::Esc);
seq.push(key);
let key = Effect::DoomFlicker(DoomFlicker::new(
LedCode::N9,
Colour { r: 0, g: 0, b: 255 },
80,
40,
));
seq.push(key);
Self {
name: "aura-default".to_owned(),
aura: seq,
}
}
}
impl StdConfig for ConfigAura {
fn new() -> Self {
Self::default()
}
fn file_name(&self) -> String {
format!("{}.ron", self.name)
}
fn config_dir() -> std::path::PathBuf {
root_conf_dir()
}
}
impl StdConfigLoad for ConfigAura {}
#[derive(Debug, Default, Deserialize, Serialize)]
#[serde(default)]
pub struct ConfigBase {
/// Name of active anime config file in the user config directory
pub active_anime: Option<String>,
/// Name of active aura config file in the user config directory
pub active_aura: Option<String>,
}
impl StdConfig for ConfigBase {
fn new() -> Self {
Self {
active_anime: Some("anime-default".to_owned()),
active_aura: Some("aura-default".to_owned()),
}
}
fn file_name(&self) -> String {
"rog-user.ron".to_owned()
}
fn config_dir() -> std::path::PathBuf {
root_conf_dir()
}
}
impl StdConfigLoad for ConfigBase {}

View File

@@ -0,0 +1,358 @@
use std::path::Path;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex};
use std::thread::sleep;
use std::time::{Duration, Instant};
use config_traits::StdConfig;
use rog_anime::error::AnimeError;
use rog_anime::{ActionData, ActionLoader, AnimTime, Fade, Sequences, Vec2};
use rog_dbus::zbus_anime::AnimeProxyBlocking;
use ron::ser::PrettyConfig;
use serde::{Deserialize, Serialize};
use zbus::interface;
use zbus::zvariant::{ObjectPath, Type};
use crate::config::ConfigAnime;
use crate::error::Error;
#[derive(Debug, Clone, Deserialize, Serialize, Type)]
pub struct Timer {
type_of: TimeType,
/// If time type is Timer then this is milliseonds, otherwise it is
/// animation loop count
count: u64,
/// Used only for `TimeType::Timer`, milliseonds to fade the image in for
fade_in: u64,
/// Used only for `TimeType::Timer`, milliseonds to fade the image out for
fade_out: u64,
}
impl From<Timer> for AnimTime {
fn from(time: Timer) -> Self {
match time.type_of {
TimeType::Timer => {
if time.fade_in != 0 && time.fade_out != 0 {
let fade_in = Duration::from_millis(time.fade_in);
let fade_out = Duration::from_millis(time.fade_out);
let show_for = if time.count != 0 {
Some(Duration::from_millis(time.count))
} else {
None
};
AnimTime::Fade(Fade::new(fade_in, show_for, fade_out))
} else {
AnimTime::Time(Duration::from_millis(time.count))
}
}
TimeType::Count => AnimTime::Count(time.count as u32),
TimeType::Infinite => AnimTime::Infinite,
}
}
}
#[derive(Debug, Clone, Deserialize, Serialize, Type)]
pub enum TimeType {
Timer,
Count,
Infinite,
}
/// The inner object exists to allow the zbus proxy to share it with a runner
/// thread and a zbus server behind `Arc<Mutex<T>>`
pub struct CtrlAnimeInner<'a> {
sequences: Sequences,
client: AnimeProxyBlocking<'a>,
do_early_return: Arc<AtomicBool>,
}
impl CtrlAnimeInner<'static> {
pub fn new(
sequences: Sequences,
client: AnimeProxyBlocking<'static>,
do_early_return: Arc<AtomicBool>,
) -> Result<Self, Error> {
Ok(Self {
sequences,
client,
do_early_return,
})
}
/// To be called on each main loop iteration to pump out commands to the
/// anime
pub fn run(&self) -> Result<(), Error> {
if self.do_early_return.load(Ordering::SeqCst) {
return Ok(());
}
for action in self.sequences.iter() {
match action {
ActionData::Animation(frames) => {
rog_anime::run_animation(frames, &|output| {
if self.do_early_return.load(Ordering::Acquire) {
return Ok(true); // Do safe exit
}
self.client
.write(output)
.map_err(|e| AnimeError::Dbus(format!("{}", e)))
.map(|_| false)
});
}
ActionData::Image(image) => {
self.client.write(image.as_ref().clone()).ok();
}
ActionData::Pause(duration) => {
let start = Instant::now();
'pause: loop {
if self.do_early_return.load(Ordering::SeqCst) {
return Ok(());
}
if Instant::now().duration_since(start) > *duration {
break 'pause;
}
sleep(Duration::from_millis(1));
}
}
ActionData::AudioEq
| ActionData::SystemInfo
| ActionData::TimeDate
| ActionData::Matrix => {}
}
}
Ok(())
}
}
pub struct CtrlAnime<'a> {
config: Arc<Mutex<ConfigAnime>>,
client: AnimeProxyBlocking<'a>,
inner: Arc<Mutex<CtrlAnimeInner<'a>>>,
/// Must be the same Atomic as in CtrlAnimeInner
inner_early_return: Arc<AtomicBool>,
}
impl CtrlAnime<'static> {
pub fn new(
config: Arc<Mutex<ConfigAnime>>,
inner: Arc<Mutex<CtrlAnimeInner<'static>>>,
client: AnimeProxyBlocking<'static>,
inner_early_return: Arc<AtomicBool>,
) -> Result<Self, Error> {
Ok(CtrlAnime {
config,
client,
inner,
inner_early_return,
})
}
pub async fn add_to_server(self, server: &mut zbus::Connection) {
server
.object_server()
.at(&ObjectPath::from_str_unchecked("/xyz/ljones/Anime"), self)
.await
.map_err(|err| {
println!("CtrlAnime: add_to_server {}", err);
err
})
.ok();
}
}
// The pattern for a zbus method is:
// - Get config lock if required
// - Set inner_early_return to stop the inner run loop temporarily
// - Do actions
// - Write config if required
// - Unset inner_early_return
#[interface(name = "xyz.ljones.Asusd")]
impl CtrlAnime<'static> {
pub fn insert_asus_gif(
&mut self,
index: u32,
file: &str,
time: Timer,
brightness: f32,
) -> zbus::fdo::Result<String> {
if let Ok(mut config) = self.config.try_lock() {
let time: AnimTime = time.into();
let file = Path::new(&file);
let action = ActionLoader::AsusAnimation {
file: file.into(),
brightness,
time,
};
// Must make the inner run loop return early
self.inner_early_return.store(true, Ordering::SeqCst);
if let Ok(mut controller) = self.inner.lock() {
controller
.sequences
.insert(index as usize, &action)
.map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?;
}
config.anime.push(action);
config.write();
let ron = ron::ser::to_string_pretty(&*config, PrettyConfig::new().depth_limit(4))
.expect("Parse config to RON failed");
// Release the inner run loop again
self.inner_early_return.store(false, Ordering::SeqCst);
return Ok(ron);
}
Err(zbus::fdo::Error::Failed("UserConfig lock fail".into()))
}
#[allow(clippy::too_many_arguments)]
pub fn insert_image_gif(
&mut self,
index: u32,
file: &str,
scale: f32,
angle: f32,
xy: (f32, f32),
time: Timer,
brightness: f32,
) -> zbus::fdo::Result<String> {
if let Ok(mut config) = self.config.try_lock() {
let time: AnimTime = time.into();
let file = Path::new(&file);
let translation = Vec2::new(xy.0, xy.1);
let action = ActionLoader::ImageAnimation {
file: file.into(),
scale,
angle,
translation,
brightness,
time,
};
// Must make the inner run loop return early
self.inner_early_return.store(true, Ordering::SeqCst);
if let Ok(mut controller) = self.inner.lock() {
controller
.sequences
.insert(index as usize, &action)
.map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?;
}
config.anime.push(action);
config.write();
let ron = ron::ser::to_string_pretty(&*config, PrettyConfig::new().depth_limit(4))
.expect("Parse config to RON failed");
// Release the inner run loop again
self.inner_early_return.store(false, Ordering::SeqCst);
return Ok(ron);
}
Err(zbus::fdo::Error::Failed("UserConfig lock fail".into()))
}
#[allow(clippy::too_many_arguments)]
pub fn insert_image(
&mut self,
index: u32,
file: &str,
scale: f32,
angle: f32,
xy: (f32, f32),
time: Timer,
brightness: f32,
) -> zbus::fdo::Result<String> {
if let Ok(mut config) = self.config.try_lock() {
let file = Path::new(&file);
let time = time.into();
let action = ActionLoader::Image {
file: file.into(),
scale,
angle,
translation: Vec2::new(xy.0, xy.1),
brightness,
time,
};
// Must make the inner run loop return early
self.inner_early_return.store(true, Ordering::SeqCst);
if let Ok(mut controller) = self.inner.lock() {
controller
.sequences
.insert(index as usize, &action)
.map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?;
}
config.anime.push(action);
config.write();
let ron = ron::ser::to_string_pretty(&*config, PrettyConfig::new().depth_limit(4))
.expect("Parse config to RON failed");
// Release the inner run loop again
self.inner_early_return.store(false, Ordering::SeqCst);
return Ok(ron);
}
Err(zbus::fdo::Error::Failed("UserConfig lock fail".into()))
}
pub fn insert_pause(&mut self, index: u32, millis: u64) -> zbus::fdo::Result<String> {
if let Ok(mut config) = self.config.try_lock() {
let action = ActionLoader::Pause(Duration::from_millis(millis));
// Must make the inner run loop return early
self.inner_early_return.store(true, Ordering::SeqCst);
if let Ok(mut controller) = self.inner.lock() {
controller
.sequences
.insert(index as usize, &action)
.map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?;
}
config.anime.push(action);
config.write();
let ron = ron::ser::to_string_pretty(&*config, PrettyConfig::new().depth_limit(4))
.expect("Parse config to RON failed");
// Release the inner run loop again
self.inner_early_return.store(false, Ordering::SeqCst);
return Ok(ron);
}
Err(zbus::fdo::Error::Failed("UserConfig lock fail".into()))
}
pub fn remove_item(&mut self, index: u32) -> zbus::fdo::Result<String> {
if let Ok(mut config) = self.config.try_lock() {
// Must make the inner run loop return early
self.inner_early_return.store(true, Ordering::SeqCst);
if let Ok(mut controller) = self.inner.lock() {
controller.sequences.remove_item(index as usize);
}
if (index as usize) < config.anime.len() {
config.anime.remove(index as usize);
}
config.write();
let ron = ron::ser::to_string_pretty(&*config, PrettyConfig::new().depth_limit(4))
.expect("Parse config to RON failed");
// Release the inner run loop again
self.inner_early_return.store(false, Ordering::SeqCst);
return Ok(ron);
}
Err(zbus::fdo::Error::Failed("UserConfig lock fail".into()))
}
pub fn set_state(&mut self, on: bool) -> zbus::fdo::Result<()> {
// Operations here need to be in specific order
if on {
self.client.set_enable_display(on).ok();
// Let the inner loop run
self.inner_early_return.store(false, Ordering::SeqCst);
} else {
// Must make the inner run loop return early
self.inner_early_return.store(true, Ordering::SeqCst);
self.client.set_enable_display(on).ok();
}
Ok(())
}
}

118
asusd-user/src/daemon.rs Normal file
View File

@@ -0,0 +1,118 @@
use std::io::Write;
use std::path::PathBuf;
use std::sync::atomic::AtomicBool;
use std::sync::{Arc, Mutex};
use asusd_user::config::*;
use asusd_user::ctrl_anime::{CtrlAnime, CtrlAnimeInner};
use config_traits::{StdConfig, StdConfigLoad};
use rog_anime::usb::get_anime_type;
use rog_aura::aura_detection::LedSupportData;
use rog_aura::keyboard::KeyLayout;
use rog_dbus::zbus_anime::AnimeProxyBlocking;
use rog_dbus::zbus_aura::AuraProxyBlocking;
use rog_dbus::{list_iface_blocking, DBUS_NAME};
use smol::Executor;
use zbus::Connection;
#[cfg(not(feature = "local_data"))]
const DATA_DIR: &str = "/usr/share/rog-gui/";
#[cfg(feature = "local_data")]
const DATA_DIR: &str = env!("CARGO_MANIFEST_DIR");
const BOARD_NAME: &str = "/sys/class/dmi/id/board_name";
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut logger = env_logger::Builder::new();
logger
.parse_default_env()
.target(env_logger::Target::Stdout)
.format(|buf, record| writeln!(buf, "{}: {}", record.level(), record.args()))
.init();
println!(" user daemon v{}", asusd_user::VERSION);
println!(" rog-anime v{}", rog_anime::VERSION);
println!(" rog-dbus v{}", rog_dbus::VERSION);
println!("rog-platform v{}", rog_platform::VERSION);
let conn = zbus::blocking::Connection::system().unwrap();
let supported = list_iface_blocking()?;
let config = ConfigBase::new().load();
let executor = Executor::new();
let early_return = Arc::new(AtomicBool::new(false));
// Set up the anime data and run loop/thread
if supported.contains(&"xyz.ljones.Anime".to_string()) {
if let Some(cfg) = config.active_anime {
let anime_type = get_anime_type();
let anime_config = ConfigAnime::new().set_name(cfg).load();
let anime = anime_config.create(anime_type)?;
let anime_config = Arc::new(Mutex::new(anime_config));
let anime_proxy_blocking = AnimeProxyBlocking::new(&conn).unwrap();
executor
.spawn(async move {
// Create server
let mut connection = Connection::session().await.unwrap();
connection.request_name(DBUS_NAME).await.unwrap();
// Inner behind mutex required for thread safety
let inner = Arc::new(Mutex::new(
CtrlAnimeInner::new(
anime,
anime_proxy_blocking.clone(),
early_return.clone(),
)
.unwrap(),
));
// Need new client object for dbus control part
let anime_control = CtrlAnime::new(
anime_config,
inner.clone(),
anime_proxy_blocking,
early_return,
)
.unwrap();
anime_control.add_to_server(&mut connection).await;
loop {
if let Ok(inner) = inner.clone().try_lock() {
inner.run().ok();
}
}
})
.detach();
}
}
// if supported.keyboard_led.per_key_led_mode {
if let Some(cfg) = config.active_aura {
let mut aura_config = ConfigAura::new().set_name(cfg).load();
// let baord_name = std::fs::read_to_string(BOARD_NAME)?;
let led_support = LedSupportData::get_data("");
let layout = KeyLayout::find_layout(led_support, PathBuf::from(DATA_DIR))
.map_err(|e| {
println!("{BOARD_NAME}, {e}");
})
.unwrap_or_else(|_| KeyLayout::default_layout());
let aura_proxy_blocking = AuraProxyBlocking::new(&conn).unwrap();
executor
.spawn(async move {
loop {
aura_config.aura.next_state(&layout);
let packets = aura_config.aura.create_packets();
aura_proxy_blocking.direct_addressing_raw(packets).unwrap();
std::thread::sleep(std::time::Duration::from_millis(33));
}
})
.detach();
}
// }
loop {
smol::block_on(executor.tick());
}
}

45
asusd-user/src/error.rs Normal file
View File

@@ -0,0 +1,45 @@
use std::fmt;
use rog_anime::error::AnimeError;
#[derive(Debug)]
pub enum Error {
Io(std::io::Error),
ConfigLoadFail,
ConfigLockFail,
XdgVars,
Anime(AnimeError),
}
impl fmt::Display for Error {
// This trait requires `fmt` with this exact signature.
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::Io(err) => write!(f, "Failed to open: {}", err),
Error::ConfigLoadFail => write!(f, "Failed to load user config"),
Error::ConfigLockFail => write!(f, "Failed to lock user config"),
Error::XdgVars => write!(f, "XDG environment vars appear unset"),
Error::Anime(err) => write!(f, "Anime error: {}", err),
}
}
}
impl std::error::Error for Error {}
impl From<std::io::Error> for Error {
fn from(err: std::io::Error) -> Self {
Error::Io(err)
}
}
impl From<AnimeError> for Error {
fn from(err: AnimeError) -> Self {
Error::Anime(err)
}
}
impl From<Error> for zbus::fdo::Error {
fn from(err: Error) -> Self {
zbus::fdo::Error::Failed(format!("Anime zbus error: {}", err))
}
}

9
asusd-user/src/lib.rs Normal file
View File

@@ -0,0 +1,9 @@
pub mod config;
pub mod error;
pub mod ctrl_anime;
pub mod zbus_anime;
pub static VERSION: &str = env!("CARGO_PKG_VERSION");

View File

@@ -0,0 +1,70 @@
//! # `DBus` interface proxy for: `xyz.ljones.Asusd`
//!
//! This code was generated by `zbus-xmlgen` `1.0.0` from `DBus` introspection
//! data. Source: `Interface '/xyz/ljones/Anime' from service
//! 'xyz.ljones.Asusd' on session bus`.
//!
//! You may prefer to adapt it, instead of using it verbatim.
//!
//! More information can be found in the
//! [Writing a client proxy](https://dbus.pages.freedesktop.org/zbus/client.html)
//! section of the zbus documentation.
//!
//! This `DBus` object implements
//! [standard `DBus` interfaces](https://dbus.freedesktop.org/doc/dbus-specification.html),
//! (`org.freedesktop.DBus.*`) for which the following zbus proxies can be used:
//!
//! * [`zbus::fdo::PeerProxy`]
//! * [`zbus::fdo::IntrospectableProxy`]
//! * [`zbus::fdo::PropertiesProxy`]
//!
//! …consequently `zbus-xmlgen` did not generate code for the above interfaces.
#![allow(clippy::too_many_arguments)]
use zbus::proxy;
#[proxy(interface = "xyz.ljones.Asusd", default_path = "/xyz/ljones/Anime")]
trait Daemon {
/// InsertAsusGif method
fn insert_asus_gif(
&self,
index: u32,
file: &str,
time: u32,
count: u32,
brightness: f64,
) -> zbus::Result<String>;
/// InsertImage method
fn insert_image(
&self,
index: u32,
file: &str,
scale: f64,
angle: f64,
xy: &(f64, f64),
brightness: f64,
) -> zbus::Result<String>;
/// InsertImageGif method
fn insert_image_gif(
&self,
index: u32,
file: &str,
scale: f64,
angle: f64,
xy: &(f64, f64),
time: u32,
count: u32,
brightness: f64,
) -> zbus::Result<String>;
/// InsertPause method
fn insert_pause(&self, index: u32, millis: u64) -> zbus::Result<String>;
/// RemoveItem method
fn remove_item(&self, index: u32) -> zbus::Result<String>;
/// SetState method
fn set_state(&self, on: bool) -> zbus::Result<()>;
}

62
asusd/Cargo.toml Normal file
View File

@@ -0,0 +1,62 @@
[package]
name = "asusd"
license.workspace = true
version.workspace = true
readme.workspace = true
authors.workspace = true
repository.workspace = true
homepage.workspace = true
description.workspace = true
edition.workspace = true
[[bin]]
name = "asusd"
path = "src/daemon.rs"
[dependencies]
config-traits = { path = "../config-traits" }
rog_anime = { path = "../rog-anime", features = ["dbus"] }
rog_slash = { path = "../rog-slash", features = ["dbus"] }
rog_aura = { path = "../rog-aura", features = ["dbus"] }
rog_scsi = { path = "../rog-scsi", features = ["dbus"] }
rog_platform = { path = "../rog-platform" }
rog_profiles = { path = "../rog-profiles" }
dmi_id = { path = "../dmi-id" }
futures-lite = "*"
udev.workspace = true
inotify.workspace = true
mio.workspace = true
tokio.workspace = true
# console-subscriber = "0.2.0"
# cli and logging
log.workspace = true
env_logger.workspace = true
futures-util.workspace = true
zbus.workspace = true
logind-zbus.workspace = true
# serialisation
serde.workspace = true
concat-idents.workspace = true
[dev-dependencies]
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"],
]

626
asusd/src/asus_armoury.rs Normal file
View File

@@ -0,0 +1,626 @@
use std::sync::Arc;
use config_traits::StdConfig;
use log::{debug, error, info};
use rog_platform::asus_armoury::{AttrValue, Attribute, FirmwareAttribute, FirmwareAttributes};
use rog_platform::platform::{PlatformProfile, RogPlatform};
use rog_platform::power::AsusPower;
use serde::{Deserialize, Serialize};
use tokio::sync::Mutex;
use zbus::object_server::SignalEmitter;
use zbus::zvariant::{ObjectPath, OwnedObjectPath, OwnedValue, Type, Value};
use zbus::{fdo, interface, Connection};
use crate::config::Config;
use crate::error::RogError;
use crate::{Reloadable, ASUS_ZBUS_PATH};
const MOD_NAME: &str = "asus_armoury";
#[derive(Debug, Default, Clone, Deserialize, Serialize, Type, Value, OwnedValue)]
pub struct PossibleValues {
strings: Vec<String>,
nums: Vec<i32>,
}
fn dbus_path_for_attr(attr_name: &str) -> OwnedObjectPath {
ObjectPath::from_str_unchecked(&format!("{ASUS_ZBUS_PATH}/{MOD_NAME}/{attr_name}")).into()
}
#[derive(Clone)]
pub struct AsusArmouryAttribute {
attr: Attribute,
config: Arc<Mutex<Config>>,
/// platform control required here for access to PPD or Throttle profile
platform: RogPlatform,
power: AsusPower,
}
impl AsusArmouryAttribute {
pub fn new(
attr: Attribute,
platform: RogPlatform,
power: AsusPower,
config: Arc<Mutex<Config>>,
) -> Self {
Self {
attr,
config,
platform,
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> {
let path = dbus_path_for_attr(self.attr.name());
connection
.object_server()
.at(path.clone(), self)
.await
.map_err(|e| error!("Couldn't add server at path: {path}, {e:?}"))
.ok();
Ok(())
}
async fn watch_and_notify(
&mut self,
signal_ctxt: SignalEmitter<'static>,
) -> Result<(), RogError> {
use futures_util::StreamExt;
let name = self.name();
macro_rules! watch_value_notify {
($attr_str:expr, $fn_prop_changed:ident) => {
match self.attr.get_watcher($attr_str) {
Ok(watch) => {
let name = <&str>::from(name);
let ctrl = self.clone();
let sig = signal_ctxt.clone();
tokio::spawn(async move {
let mut buffer = [0; 32];
if let Ok(stream) = watch.into_event_stream(&mut buffer) {
stream
.for_each(|_| async {
debug!("{} changed", name);
ctrl.$fn_prop_changed(&sig).await.ok();
})
.await;
} else {
info!(
"inotify event stream failed for {} ({}). You can ignore this \
if unsupported",
name, $attr_str
);
}
});
}
Err(e) => info!(
"inotify watch failed: {}. You can ignore this if your device does not \
support the feature",
e
),
}
};
}
// "current_value", "default_value", "min_value", "max_value"
watch_value_notify!("current_value", current_value_changed);
watch_value_notify!("default_value", default_value_changed);
watch_value_notify!("min_value", min_value_changed);
watch_value_notify!("max_value", max_value_changed);
Ok(())
}
}
#[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 {
async fn reload(&mut self) -> Result<(), RogError> {
info!("Reloading {}", self.attr.name());
let name: FirmwareAttribute = self.attr.name().into();
if name.is_ppt() {
let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
let power_plugged = self
.power
.get_online()
.map_err(|e| {
error!("Could not get power status: {e:?}");
e
})
.unwrap_or_default()
== 1;
let apply_value = {
let config = self.config.lock().await;
config
.select_tunings_ref(power_plugged, profile)
.and_then(|tuning| {
if tuning.enabled {
tuning.group.get(&self.name()).copied()
} else {
None
}
})
};
if let Some(tune) = apply_value {
self.attr
.set_current_value(&AttrValue::Integer(tune))
.map_err(|e| {
error!("Could not set {} value: {e:?}", self.attr.name());
self.attr.base_path_exists();
e
})?;
info!("Set {} to {:?}", self.attr.name(), tune);
}
} 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!("Could not set {} value: {e:?}", self.attr.name());
self.attr.base_path_exists();
e
})?;
info!(
"Restored armoury setting {} to {:?}",
self.attr.name(),
saved_value
);
}
}
Ok(())
}
}
/// If return is `-1` on a property then there is avilable value for that
/// property
#[interface(name = "xyz.ljones.AsusArmoury")]
impl AsusArmouryAttribute {
#[zbus(property)]
fn name(&self) -> FirmwareAttribute {
self.attr.name().into()
}
#[zbus(property)]
async fn available_attrs(&self) -> Vec<String> {
let mut attrs = Vec::new();
if !matches!(self.attr.default_value(), AttrValue::None) {
attrs.push("default_value".to_string());
}
if !matches!(self.attr.min_value(), AttrValue::None) {
attrs.push("min_value".to_string());
}
if !matches!(self.attr.max_value(), AttrValue::None) {
attrs.push("max_value".to_string());
}
if !matches!(self.attr.scalar_increment(), AttrValue::None) {
attrs.push("scalar_increment".to_string());
}
if !matches!(self.attr.possible_values(), AttrValue::None) {
attrs.push("possible_values".to_string());
}
// TODO: Don't unwrap, use error
if let Ok(value) = self.attr.current_value().map_err(|e| {
error!("Failed to read: {e:?}");
e
}) {
if !matches!(value, AttrValue::None) {
attrs.push("current_value".to_string());
}
}
attrs
}
/// If return is `-1` then there is no default value
#[zbus(property)]
async fn default_value(&self) -> i32 {
match self.attr.default_value() {
AttrValue::Integer(i) => *i,
_ => -1,
}
}
async fn restore_default(&self) -> fdo::Result<()> {
self.attr.restore_default()?;
if self.name().is_ppt() {
let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
let power_plugged = self
.power
.get_online()
.map_err(|e| {
error!("Could not get power status: {e:?}");
e
})
.unwrap_or_default();
let mut config = self.config.lock().await;
let tuning = config.select_tunings(power_plugged == 1, profile);
if let Some(tune) = tuning.group.get_mut(&self.name()) {
if let AttrValue::Integer(i) = self.attr.default_value() {
*tune = *i;
}
}
if tuning.enabled {
self.attr
.set_current_value(self.attr.default_value())
.map_err(|e| {
error!("Could not set value: {e:?}");
e
})?;
}
config.write();
}
Ok(())
}
#[zbus(property)]
async fn min_value(&self) -> i32 {
Self::resolve_i32_value(self.attr.refresh_min_value(), self.attr.min_value())
}
#[zbus(property)]
async fn max_value(&self) -> i32 {
Self::resolve_i32_value(self.attr.refresh_max_value(), self.attr.max_value())
}
#[zbus(property)]
async fn scalar_increment(&self) -> i32 {
Self::resolve_i32_value(
self.attr.refresh_scalar_increment(),
self.attr.scalar_increment(),
)
}
#[zbus(property)]
async fn possible_values(&self) -> Vec<i32> {
match self.attr.possible_values() {
AttrValue::EnumInt(i) => i.clone(),
_ => Vec::default(),
}
}
#[zbus(property)]
async fn current_value(&self) -> fdo::Result<i32> {
if self.name().is_ppt() {
let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
let power_plugged = self
.power
.get_online()
.map_err(|e| {
error!("Could not get power status: {e:?}");
e
})
.unwrap_or_default()
== 1;
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()) {
return Ok(*tune);
}
}
if let AttrValue::Integer(i) = self.attr.default_value() {
return Ok(*i);
}
return Err(fdo::Error::Failed(
"Could not read current value".to_string(),
));
}
if let Ok(AttrValue::Integer(i)) = self.attr.current_value() {
return Ok(i);
}
Err(fdo::Error::Failed(
"Could not read current value".to_string(),
))
}
async fn stored_value_for_power(&self, on_ac: bool) -> fdo::Result<i32> {
if !self.name().is_ppt() {
return Err(fdo::Error::NotSupported(
"Stored values are only available for PPT attributes".to_string(),
));
}
let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
let config = self.config.lock().await;
if let Some(tuning) = config.select_tunings_ref(on_ac, profile) {
if let Some(tune) = tuning.group.get(&self.name()) {
return Ok(*tune);
}
}
if let AttrValue::Integer(i) = self.attr.default_value() {
return Ok(*i);
}
Err(fdo::Error::Failed(
"Could not read stored value".to_string(),
))
}
async fn set_value_for_power(&mut self, on_ac: bool, value: i32) -> fdo::Result<()> {
if !self.name().is_ppt() {
return Err(fdo::Error::NotSupported(
"Setting stored values is only supported for PPT attributes".to_string(),
));
}
let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
let apply_now;
{
let mut config = self.config.lock().await;
let tuning = config.select_tunings(on_ac, profile);
if let Some(tune) = tuning.group.get_mut(&self.name()) {
*tune = value;
} else {
tuning.group.insert(self.name(), value);
debug!(
"Store {} value for {} power = {}",
self.attr.name(),
if on_ac { "AC" } else { "DC" },
value
);
}
apply_now = tuning.enabled;
config.write();
}
if apply_now {
let power_plugged = self
.power
.get_online()
.map_err(|e| {
error!("Could not get power status: {e:?}");
e
})
.unwrap_or_default()
!= 0;
if power_plugged == on_ac {
self.attr
.set_current_value(&AttrValue::Integer(value))
.map_err(|e| {
error!("Could not set value: {e:?}");
e
})?;
}
}
Ok(())
}
#[zbus(property)]
async fn set_current_value(&mut self, value: i32) -> fdo::Result<()> {
if self.name().is_ppt() {
let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
let power_plugged = self
.power
.get_online()
.map_err(|e| {
error!("Could not get power status: {e:?}");
e
})
.unwrap_or_default();
let mut config = self.config.lock().await;
let tuning = config.select_tunings(power_plugged == 1, profile);
if let Some(tune) = tuning.group.get_mut(&self.name()) {
*tune = value;
} else {
tuning.group.insert(self.name(), value);
debug!("Store tuning config for {} = {:?}", self.attr.name(), value);
}
if tuning.enabled {
self.attr
.set_current_value(&AttrValue::Integer(value))
.map_err(|e| {
error!("Could not set value: {e:?}");
e
})?;
}
} else {
self.attr
.set_current_value(&AttrValue::Integer(value))
.map_err(|e| {
error!("Could not set value: {e:?}");
e
})?;
let has_attr = self
.config
.lock()
.await
.armoury_settings
.contains_key(&self.name());
if has_attr {
if let Some(setting) = self
.config
.lock()
.await
.armoury_settings
.get_mut(&self.name())
{
*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);
}
}
self.config.lock().await.write();
Ok(())
}
}
pub async fn start_attributes_zbus(
conn: &Connection,
platform: RogPlatform,
power: AsusPower,
attributes: FirmwareAttributes,
config: Arc<Mutex<Config>>,
) -> Result<ArmouryAttributeRegistry, RogError> {
let mut registry = ArmouryAttributeRegistry::default();
for attr in attributes.attributes() {
let mut attr = AsusArmouryAttribute::new(
attr.clone(),
platform.clone(),
power.clone(),
config.clone(),
);
let registry_attr = attr.clone();
if let Err(e) = attr.reload().await {
error!(
"Skipping attribute '{}' due to reload error: {e:?}",
attr.attr.name()
);
// continue with others
continue;
}
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(
attrs: &FirmwareAttributes,
config: &mut Config,
power_plugged: bool,
profile: PlatformProfile,
) {
for attr in attrs.attributes().iter() {
let name: FirmwareAttribute = attr.name().into();
if name.is_ppt() {
let tuning = config.select_tunings(power_plugged, profile);
if !tuning.enabled {
debug!("Tuning group is not enabled, skipping");
return;
}
if let Some(tune) = tuning.group.get(&name) {
attr.set_current_value(&AttrValue::Integer(*tune))
.map_err(|e| {
error!("Failed to set {}: {e}", <&str>::from(name));
})
.ok();
} else {
let default = attr.default_value();
attr.set_current_value(default)
.map_err(|e| {
error!("Failed to set {}: {e}", <&str>::from(name));
})
.ok();
if let AttrValue::Integer(i) = default {
tuning.group.insert(name, *i);
info!(
"Set default tuning config for {} = {:?}",
<&str>::from(name),
i
);
// 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

@@ -0,0 +1,182 @@
use std::time::Duration;
use config_traits::{StdConfig, StdConfigLoad};
use rog_anime::error::AnimeError;
use rog_anime::usb::Brightness;
use rog_anime::{
ActionData, ActionLoader, AnimTime, Animations, AnimeType, DeviceState, Fade, Vec2,
};
use serde::{Deserialize, Serialize};
const CONFIG_FILE: &str = "anime.ron";
#[derive(Debug, Clone, Deserialize, Serialize, Default)]
pub struct AniMeConfigCached {
pub system: Vec<ActionData>,
pub boot: Vec<ActionData>,
pub wake: Vec<ActionData>,
pub shutdown: Vec<ActionData>,
}
impl AniMeConfigCached {
pub fn init_from_config(
&mut self,
config: &AniMeConfig,
anime_type: AnimeType,
) -> Result<(), AnimeError> {
let mut sys = Vec::with_capacity(config.system.len());
for ani in &config.system {
sys.push(ActionData::from_anime_action(anime_type, ani)?);
}
self.system = sys;
let mut boot = Vec::with_capacity(config.boot.len());
for ani in &config.boot {
boot.push(ActionData::from_anime_action(anime_type, ani)?);
}
self.boot = boot;
let mut wake = Vec::with_capacity(config.wake.len());
for ani in &config.wake {
wake.push(ActionData::from_anime_action(anime_type, ani)?);
}
self.wake = wake;
let mut shutdown = Vec::with_capacity(config.shutdown.len());
for ani in &config.shutdown {
shutdown.push(ActionData::from_anime_action(anime_type, ani)?);
}
self.shutdown = shutdown;
Ok(())
}
}
/// Config for base system actions for the anime display
#[derive(Deserialize, Serialize, Debug, Clone)]
pub struct AniMeConfig {
#[serde(skip)]
pub anime_type: AnimeType,
pub system: Vec<ActionLoader>,
pub boot: Vec<ActionLoader>,
pub wake: Vec<ActionLoader>,
pub shutdown: Vec<ActionLoader>,
// pub brightness: f32,
pub display_enabled: bool,
pub display_brightness: Brightness,
pub builtin_anims_enabled: bool,
pub off_when_unplugged: bool,
pub off_when_suspended: bool,
pub off_when_lid_closed: bool,
pub brightness_on_battery: Brightness,
pub builtin_anims: Animations,
}
impl Default for AniMeConfig {
fn default() -> Self {
AniMeConfig {
anime_type: AnimeType::GA402,
system: Vec::new(),
boot: Vec::new(),
wake: Vec::new(),
shutdown: Vec::new(),
// brightness: 1.0,
display_enabled: true,
display_brightness: Brightness::Med,
builtin_anims_enabled: true,
off_when_unplugged: true,
off_when_suspended: true,
off_when_lid_closed: true,
brightness_on_battery: Brightness::Low,
builtin_anims: Animations::default(),
}
}
}
impl StdConfig for AniMeConfig {
fn new() -> Self {
Self::create_default()
}
fn file_name(&self) -> String {
CONFIG_FILE.to_owned()
}
fn config_dir() -> std::path::PathBuf {
std::path::PathBuf::from(crate::CONFIG_PATH_BASE)
}
}
impl StdConfigLoad for AniMeConfig {}
impl From<&AniMeConfig> for DeviceState {
fn from(config: &AniMeConfig) -> Self {
DeviceState {
display_enabled: config.display_enabled,
display_brightness: config.display_brightness,
builtin_anims_enabled: config.builtin_anims_enabled,
builtin_anims: config.builtin_anims,
off_when_unplugged: config.off_when_unplugged,
off_when_suspended: config.off_when_suspended,
off_when_lid_closed: config.off_when_lid_closed,
brightness_on_battery: config.brightness_on_battery,
}
}
}
impl AniMeConfig {
// fn clamp_config_brightness(mut config: &mut AnimeConfig) {
// if config.brightness < 0.0 || config.brightness > 1.0 {
// warn!(
// "Clamped brightness to [0.0 ; 1.0], was {}",
// config.brightness
// );
// config.brightness = f32::max(0.0, f32::min(1.0, config.brightness));
// }
// }
fn create_default() -> Self {
// create a default config here
AniMeConfig {
system: vec![],
boot: vec![
ActionLoader::ImageAnimation {
file: "/usr/share/asusd/anime/custom/sonic-run.gif".into(),
scale: 0.9,
angle: 0.65,
translation: Vec2::default(),
brightness: 1.0,
time: AnimTime::Fade(Fade::new(
Duration::from_secs(2),
Some(Duration::from_secs(2)),
Duration::from_secs(2),
)),
},
],
wake: vec![
ActionLoader::ImageAnimation {
file: "/usr/share/asusd/anime/custom/sonic-run.gif".into(),
scale: 0.9,
angle: 0.65,
translation: Vec2::default(),
brightness: 1.0,
time: AnimTime::Fade(Fade::new(
Duration::from_secs(2),
Some(Duration::from_secs(2)),
Duration::from_secs(2),
)),
},
],
shutdown: vec![
ActionLoader::ImageAnimation {
file: "/usr/share/asusd/anime/custom/sonic-wait.gif".into(),
scale: 0.9,
angle: 0.0,
translation: Vec2::new(3.0, 2.0),
brightness: 1.0,
time: AnimTime::Infinite,
},
],
..Default::default()
}
}
}

248
asusd/src/aura_anime/mod.rs Normal file
View File

@@ -0,0 +1,248 @@
pub mod config;
/// Implements `CtrlTask`, Reloadable, `ZbusRun`
pub mod trait_impls;
use std::convert::TryFrom;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::thread::sleep;
use config_traits::StdConfig;
use log::{debug, error, info, warn};
use rog_anime::usb::{
pkt_flush, pkt_set_brightness, pkt_set_enable_display, pkt_set_enable_powersave_anim,
pkts_for_init, Brightness,
};
use rog_anime::{ActionData, AnimeDataBuffer, AnimePacketType};
use rog_platform::hid_raw::HidRaw;
use rog_platform::usb_raw::USBRaw;
use tokio::sync::Mutex;
use self::config::{AniMeConfig, AniMeConfigCached};
use crate::error::RogError;
#[derive(Debug, Clone)]
pub struct AniMe {
hid: Option<Arc<Mutex<HidRaw>>>,
usb: Option<Arc<Mutex<USBRaw>>>,
config: Arc<Mutex<AniMeConfig>>,
cache: AniMeConfigCached,
// set to force thread to exit
thread_exit: Arc<AtomicBool>,
// Set to false when the thread exits
thread_running: Arc<AtomicBool>,
}
impl AniMe {
pub fn new(
hid: Option<Arc<Mutex<HidRaw>>>,
usb: Option<Arc<Mutex<USBRaw>>>,
config: Arc<Mutex<AniMeConfig>>,
) -> Self {
Self {
hid,
usb,
config,
cache: AniMeConfigCached::default(),
thread_exit: Arc::new(AtomicBool::new(false)),
thread_running: Arc::new(AtomicBool::new(false)),
}
}
/// Will fail if something is already holding the config lock
async fn do_init_cache(&mut self) {
if let Ok(mut config) = self.config.try_lock() {
if let Err(e) = self.cache.init_from_config(&config, config.anime_type) {
error!(
"Trying to cache the Anime Config failed, will reset to default config: {e:?}"
);
config.rename_file_old();
*config = AniMeConfig::new();
config.write();
} else {
debug!("Initialised AniMe cache");
}
} else {
error!("AniMe Matrix could not init cache")
}
}
/// Initialise the device if required.
pub async fn do_initialization(&mut self) -> Result<(), RogError> {
self.do_init_cache().await;
let pkts = pkts_for_init();
self.write_bytes(&pkts[0]).await?;
self.write_bytes(&pkts[1]).await?;
debug!("Succesfully initialised AniMe matrix display");
Ok(())
}
pub async fn write_bytes(&self, message: &[u8]) -> Result<(), RogError> {
if let Some(hid) = &self.hid {
hid.lock().await.write_bytes(message)?;
} else if let Some(usb) = &self.usb {
usb.lock().await.write_bytes(message)?;
}
Ok(())
}
/// Write only a data packet. This will modify the leds brightness using the
/// global brightness set in config.
async fn write_data_buffer(&self, mut buffer: AnimeDataBuffer) -> Result<(), RogError> {
for led in buffer.data_mut().iter_mut() {
let mut bright = *led as f32;
if bright > 254.0 {
bright = 254.0;
}
*led = bright as u8;
}
let data = AnimePacketType::try_from(buffer)?;
for row in &data {
self.write_bytes(row).await?;
}
self.write_bytes(&pkt_flush()).await
}
pub async fn set_builtins_enabled(
&self,
enabled: bool,
bright: Brightness,
) -> Result<(), RogError> {
self.write_bytes(&pkt_set_enable_powersave_anim(enabled))
.await?;
self.write_bytes(&pkt_set_enable_display(enabled)).await?;
self.write_bytes(&pkt_set_brightness(bright)).await?;
self.write_bytes(&pkt_set_enable_powersave_anim(enabled))
.await
}
/// Start an action thread. This is classed as a singleton and there should
/// be only one running - so the thread uses atomics to signal run/exit.
///
/// Because this also writes to the usb device, other write tries (display
/// only) *must* get the mutex lock and set the `thread_exit` atomic.
async fn run_thread(&self, actions: Vec<ActionData>, mut once: bool) {
if actions.is_empty() {
warn!("AniMe system actions was empty");
return;
}
self.write_bytes(&pkt_set_enable_powersave_anim(false))
.await
.map_err(|err| {
warn!("rog_anime::run_animation:callback {}", err);
})
.ok();
let thread_exit = self.thread_exit.clone();
let thread_running = self.thread_running.clone();
let anime_type = self.config.lock().await.anime_type;
let inner = self.clone();
// Loop rules:
// - Lock the mutex **only when required**. That is, the lock must be held for
// the shortest duration possible.
// - An AtomicBool used for thread exit should be checked in every loop,
// including nested
// The only reason for this outer thread is to prevent blocking while waiting
// for the next spawned thread to exit
// TODO: turn this in to async task (maybe? COuld still risk blocking main
// thread)
tokio::spawn(async move {
info!("AniMe new system thread started");
// First two loops are to ensure we *do* aquire a lock on the mutex
// The reason the loop is required is because the USB writes can block
// for up to 10ms. We can't fail to get the atomics.
while thread_running.load(Ordering::SeqCst) {
// Make any running loop exit first
thread_exit.store(true, Ordering::SeqCst);
}
info!("AniMe no previous system thread running (now)");
thread_exit.store(false, Ordering::SeqCst);
thread_running.store(true, Ordering::SeqCst);
'main: loop {
for action in &actions {
if thread_exit.load(Ordering::SeqCst) {
break 'main;
}
match action {
ActionData::Animation(frames) => {
// TODO: sort all this out
rog_anime::run_animation(frames, &|frame| {
if thread_exit.load(Ordering::Acquire) {
info!("rog-anime: animation sub-loop was asked to exit");
return Ok(true); // Do safe exit
}
let inner = inner.clone();
tokio::task::spawn(async move {
inner
.write_data_buffer(frame)
.await
.map_err(|err| {
warn!("rog_anime::run_animation:callback {}", err);
})
.ok();
});
Ok(false) // Don't exit yet
});
if thread_exit.load(Ordering::Acquire) {
info!("rog-anime: sub-loop exited and main loop exiting now");
break 'main;
}
}
ActionData::Image(image) => {
once = false;
inner
.write_data_buffer(image.as_ref().clone())
.await
.map_err(|e| error!("{}", e))
.ok();
}
ActionData::Pause(duration) => sleep(*duration),
ActionData::AudioEq
| ActionData::SystemInfo
| ActionData::TimeDate
| ActionData::Matrix => {}
}
}
if thread_exit.load(Ordering::SeqCst) {
break 'main;
}
if once || actions.is_empty() {
break 'main;
}
}
// Clear the display on exit
if let Ok(data) =
AnimeDataBuffer::from_vec(anime_type, vec![0u8; anime_type.data_length()])
.map_err(|e| error!("{}", e))
{
inner
.write_data_buffer(data)
.await
.map_err(|err| {
warn!("rog_anime::run_animation:callback {}", err);
})
.ok();
}
// A write can block for many milliseconds so lets not hold the config lock for
// the same period
let enabled = inner.config.lock().await.builtin_anims_enabled;
inner
.write_bytes(&pkt_set_enable_powersave_anim(enabled))
.await
.map_err(|err| {
warn!("rog_anime::run_animation:callback {}", err);
})
.ok();
// Loop ended, set the atmonics
thread_running.store(false, Ordering::SeqCst);
info!("AniMe system thread exited");
})
.await
.map(|err| info!("AniMe system thread: {:?}", err))
.ok();
}
}

View File

@@ -0,0 +1,507 @@
use std::sync::atomic::Ordering;
use config_traits::StdConfig;
use log::{debug, error, warn};
use logind_zbus::manager::ManagerProxy;
use rog_anime::usb::{
pkt_set_brightness, pkt_set_builtin_animations, pkt_set_enable_display,
pkt_set_enable_powersave_anim, Brightness,
};
use rog_anime::{Animations, AnimeDataBuffer, DeviceState};
use zbus::object_server::SignalEmitter;
use zbus::proxy::CacheProperties;
use zbus::zvariant::OwnedObjectPath;
use zbus::{interface, Connection};
use super::config::AniMeConfig;
use super::AniMe;
use crate::error::RogError;
use crate::Reloadable;
async fn get_logind_manager<'a>() -> ManagerProxy<'a> {
let connection = Connection::system()
.await
.expect("Controller could not create dbus connection");
ManagerProxy::builder(&connection)
.cache_properties(CacheProperties::No)
.build()
.await
.expect("Controller could not create ManagerProxy")
}
#[derive(Clone)]
pub struct AniMeZbus(AniMe);
impl AniMeZbus {
pub fn new(anime: AniMe) -> Self {
Self(anime)
}
pub async fn start_tasks(
mut self,
connection: &Connection,
path: OwnedObjectPath,
) -> Result<(), RogError> {
// let task = zbus.clone();
self.reload()
.await
.unwrap_or_else(|err| warn!("Controller error: {}", err));
connection
.object_server()
.at(path.clone(), self)
.await
.map_err(|e| {
error!("Couldn't add server at path: {path}, {e:?}");
e
})?;
debug!("start_tasks was successful");
Ok(())
}
}
// None of these calls can be guarnateed to succeed unless we loop until okay
// If the try_lock *does* succeed then any other thread trying to lock will not
// grab it until we finish.
#[interface(name = "xyz.ljones.Anime")]
impl AniMeZbus {
/// Writes a data stream of length. Will force system thread to exit until
/// it is restarted
async fn write(&self, input: AnimeDataBuffer) -> zbus::fdo::Result<()> {
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.thread_exit.store(true, Ordering::SeqCst);
self.0.write_data_buffer(input).await.map_err(|err| {
warn!("ctrl_anime::run_animation:callback {}", err);
err
})?;
Ok(())
}
/// Set base brightness level
#[zbus(property)]
async fn brightness(&self) -> Brightness {
if let Ok(config) = self.0.config.try_lock() {
return config.display_brightness;
}
Brightness::Off
}
/// Set base brightness level
#[zbus(property)]
async fn set_brightness(&self, brightness: Brightness) {
self.0
.write_bytes(&pkt_set_brightness(brightness))
.await
.map_err(|err| {
warn!("ctrl_anime::set_brightness {}", err);
})
.ok();
self.0
.write_bytes(&pkt_set_enable_display(brightness != Brightness::Off))
.await
.map_err(|err| {
warn!("ctrl_anime::set_brightness {}", err);
})
.ok();
let mut config = self.0.config.lock().await;
config.display_enabled = brightness != Brightness::Off;
config.display_brightness = brightness;
config.write();
}
#[zbus(property)]
async fn builtins_enabled(&self) -> bool {
if let Ok(config) = self.0.config.try_lock() {
return config.builtin_anims_enabled;
}
false
}
/// Enable the builtin animations or not. This is quivalent to "Powersave
/// animations" in Armory crate
#[zbus(property)]
async fn set_builtins_enabled(&self, enabled: bool) {
let mut config = self.0.config.lock().await;
let brightness = config.display_brightness;
self.0
.set_builtins_enabled(enabled, brightness)
.await
.map_err(|err| {
warn!("ctrl_anime::set_builtins_enabled {}", err);
})
.ok();
if !enabled {
let anime_type = config.anime_type;
let data = vec![255u8; anime_type.data_length()];
if let Ok(tmp) = AnimeDataBuffer::from_vec(anime_type, data).map_err(|err| {
warn!("ctrl_anime::set_builtins_enabled {}", err);
}) {
self.0
.write_bytes(tmp.data())
.await
.map_err(|err| {
warn!("ctrl_anime::set_builtins_enabled {}", err);
})
.ok();
}
}
config.builtin_anims_enabled = enabled;
config.write();
if enabled {
self.0.thread_exit.store(true, Ordering::Release);
}
}
#[zbus(property)]
async fn builtin_animations(&self) -> Animations {
if let Ok(config) = self.0.config.try_lock() {
return config.builtin_anims;
}
Animations::default()
}
/// Set which builtin animation is used for each stage
#[zbus(property)]
async fn set_builtin_animations(&self, settings: Animations) {
self.0
.write_bytes(&pkt_set_builtin_animations(
settings.boot, settings.awake, settings.sleep, settings.shutdown,
))
.await
.map_err(|err| {
warn!("ctrl_anime::run_animation:callback {}", err);
})
.ok();
self.0
.write_bytes(&pkt_set_enable_powersave_anim(true))
.await
.map_err(|err| {
warn!("ctrl_anime::run_animation:callback {}", err);
})
.ok();
let mut config = self.0.config.lock().await;
config.display_enabled = true;
config.builtin_anims = settings;
config.write();
}
#[zbus(property)]
async fn enable_display(&self) -> bool {
if let Ok(config) = self.0.config.try_lock() {
return config.display_enabled;
}
false
}
/// Set whether the AniMe is enabled at all
#[zbus(property)]
async fn set_enable_display(&self, enabled: bool) {
self.0
.write_bytes(&pkt_set_enable_display(enabled))
.await
.map_err(|err| {
warn!("ctrl_anime::run_animation:callback {}", err);
})
.ok();
let mut config = self.0.config.lock().await;
config.display_enabled = enabled;
config.write();
}
#[zbus(property)]
async fn off_when_unplugged(&self) -> bool {
if let Ok(config) = self.0.config.try_lock() {
return config.off_when_unplugged;
}
false
}
/// Set if to turn the AniMe Matrix off when external power is unplugged
#[zbus(property)]
async fn set_off_when_unplugged(&self, enabled: bool) {
let manager = get_logind_manager().await;
let pow = manager.on_external_power().await.unwrap_or_default();
self.0
.write_bytes(&pkt_set_enable_display(!pow && !enabled))
.await
.map_err(|err| {
warn!("create_sys_event_tasks::off_when_lid_closed {}", err);
})
.ok();
let mut config = self.0.config.lock().await;
config.off_when_unplugged = enabled;
config.write();
}
#[zbus(property)]
async fn off_when_suspended(&self) -> bool {
if let Ok(config) = self.0.config.try_lock() {
return config.off_when_suspended;
}
false
}
/// Set if to turn the AniMe Matrix off when the laptop is suspended
#[zbus(property)]
async fn set_off_when_suspended(&self, enabled: bool) {
let mut config = self.0.config.lock().await;
config.off_when_suspended = enabled;
config.write();
}
#[zbus(property)]
async fn off_when_lid_closed(&self) -> bool {
if let Ok(config) = self.0.config.try_lock() {
return config.off_when_lid_closed;
}
false
}
/// Set if to turn the AniMe Matrix off when the lid is closed
#[zbus(property)]
async fn set_off_when_lid_closed(&self, enabled: bool) {
let manager = get_logind_manager().await;
let lid = manager.lid_closed().await.unwrap_or_default();
self.0
.write_bytes(&pkt_set_enable_display(lid && !enabled))
.await
.map_err(|err| {
warn!("create_sys_event_tasks::off_when_lid_closed {}", err);
})
.ok();
let mut config = self.0.config.lock().await;
config.off_when_lid_closed = enabled;
config.write();
}
/// The main loop is the base system set action if the user isn't running
/// the user daemon
async fn run_main_loop(&self, start: bool) {
if start {
self.0.thread_exit.store(true, Ordering::SeqCst);
self.0.run_thread(self.0.cache.system.clone(), false).await;
}
}
/// Get the device state as stored by asusd
// #[zbus(property)]
async fn device_state(&self) -> DeviceState {
DeviceState::from(&*self.0.config.lock().await)
}
}
impl crate::CtrlTask for AniMeZbus {
fn zbus_path() -> &'static str {
"ANIME_ZBUS_PATH"
}
async fn create_tasks(&self, _: SignalEmitter<'static>) -> Result<(), RogError> {
let inner1 = self.0.clone();
let inner2 = self.0.clone();
let inner3 = self.0.clone();
let inner4 = self.0.clone();
self.create_sys_event_tasks(
move |sleeping| {
// on_sleep
let inner = inner1.clone();
async move {
let config = inner.config.lock().await.clone();
if config.display_enabled {
inner.thread_exit.store(true, Ordering::Release); // ensure clean slate
inner
.write_bytes(&pkt_set_enable_display(
!(sleeping && config.off_when_suspended),
))
.await
.map_err(|err| {
warn!("create_sys_event_tasks::off_when_suspended {}", err);
})
.ok();
if config.builtin_anims_enabled {
inner
.write_bytes(&pkt_set_enable_powersave_anim(
!(sleeping && config.off_when_suspended),
))
.await
.map_err(|err| {
warn!("create_sys_event_tasks::off_when_suspended {}", err);
})
.ok();
} else if !sleeping && !config.builtin_anims_enabled {
// Run custom wake animation
inner
.write_bytes(&pkt_set_enable_powersave_anim(false))
.await
.ok(); // ensure builtins are disabled
inner.run_thread(inner.cache.wake.clone(), true).await;
}
}
}
},
move |shutting_down| {
// on_shutdown
let inner = inner2.clone();
async move {
let AniMeConfig {
display_enabled,
builtin_anims_enabled,
..
} = *inner.config.lock().await;
if display_enabled && !builtin_anims_enabled {
if shutting_down {
inner.run_thread(inner.cache.shutdown.clone(), true).await;
} else {
inner.run_thread(inner.cache.boot.clone(), true).await;
}
}
}
},
move |lid_closed| {
let inner = inner3.clone();
// on lid change
async move {
let AniMeConfig {
off_when_lid_closed,
builtin_anims_enabled,
..
} = *inner.config.lock().await;
if off_when_lid_closed {
if builtin_anims_enabled {
inner
.write_bytes(&pkt_set_enable_powersave_anim(!lid_closed))
.await
.map_err(|err| {
warn!("create_sys_event_tasks::off_when_suspended {}", err);
})
.ok();
}
inner
.write_bytes(&pkt_set_enable_display(!lid_closed))
.await
.map_err(|err| {
warn!("create_sys_event_tasks::off_when_lid_closed {}", err);
})
.ok();
}
}
},
move |power_plugged| {
let inner = inner4.clone();
// on power change
async move {
let AniMeConfig {
off_when_unplugged,
builtin_anims_enabled,
brightness_on_battery,
..
} = *inner.config.lock().await;
if off_when_unplugged {
if builtin_anims_enabled {
inner
.write_bytes(&pkt_set_enable_powersave_anim(power_plugged))
.await
.map_err(|err| {
warn!("create_sys_event_tasks::off_when_suspended {}", err);
})
.ok();
}
inner
.write_bytes(&pkt_set_enable_display(power_plugged))
.await
.map_err(|err| {
warn!("create_sys_event_tasks::off_when_unplugged {}", err);
})
.ok();
} else {
inner
.write_bytes(&pkt_set_brightness(brightness_on_battery))
.await
.map_err(|err| {
warn!("create_sys_event_tasks::off_when_unplugged {}", err);
})
.ok();
}
}
},
)
.await;
Ok(())
}
}
impl crate::Reloadable for AniMeZbus {
async fn reload(&mut self) -> Result<(), RogError> {
let AniMeConfig {
builtin_anims_enabled,
builtin_anims,
display_enabled,
display_brightness,
off_when_lid_closed,
off_when_unplugged,
..
} = *self.0.config.lock().await;
// Set builtins
if builtin_anims_enabled {
self.0
.write_bytes(&pkt_set_builtin_animations(
builtin_anims.boot,
builtin_anims.awake,
builtin_anims.sleep,
builtin_anims.shutdown,
))
.await?;
}
// Builtins enabled or na?
self.0
.set_builtins_enabled(builtin_anims_enabled, display_brightness)
.await?;
let manager = get_logind_manager().await;
let lid_closed = manager.lid_closed().await.unwrap_or_default();
let power_plugged = manager.on_external_power().await.unwrap_or_default();
let turn_off =
(lid_closed && off_when_lid_closed) || (!power_plugged && off_when_unplugged);
self.0
.write_bytes(&pkt_set_enable_display(!turn_off))
.await
.map_err(|err| {
warn!("create_sys_event_tasks::reload {}", err);
})
.ok();
if turn_off || !display_enabled {
self.0.write_bytes(&pkt_set_enable_display(false)).await?;
// early return so we don't run animation thread
return Ok(());
}
if !builtin_anims_enabled && !self.0.cache.boot.is_empty() {
self.0
.write_bytes(&pkt_set_enable_powersave_anim(false))
.await
.ok();
let action = self.0.cache.boot.clone();
self.0.run_thread(action, true).await;
}
Ok(())
}
}

View File

@@ -0,0 +1,458 @@
use std::collections::BTreeMap;
use config_traits::{StdConfig, StdConfigLoad};
use log::{debug, info, warn};
use rog_aura::aura_detection::LedSupportData;
use rog_aura::keyboard::LaptopAuraPower;
use rog_aura::{
AuraDeviceType, AuraEffect, AuraModeNum, AuraZone, Direction, LedBrightness, Speed, GRADIENT,
};
use serde::{Deserialize, Serialize};
use crate::error::RogError;
#[derive(Deserialize, Serialize, Default, Debug, Clone)]
// #[serde(default)]
pub struct AuraConfig {
#[serde(skip)]
pub led_type: AuraDeviceType,
#[serde(skip)]
pub support_data: LedSupportData,
pub config_name: String,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub ally_fix: Option<bool>,
pub brightness: LedBrightness,
pub current_mode: AuraModeNum,
pub builtins: BTreeMap<AuraModeNum, AuraEffect>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub multizone: Option<BTreeMap<AuraModeNum, Vec<AuraEffect>>>,
pub multizone_on: bool,
pub enabled: LaptopAuraPower,
#[serde(skip)]
pub per_key_mode_active: bool,
}
impl StdConfig for AuraConfig {
/// Detect the keyboard type and load from default DB if data available
fn new() -> Self {
panic!("This should not be used");
}
fn file_name(&self) -> String {
if self.config_name.is_empty() {
panic!("Config file name should not be empty");
}
self.config_name.to_owned()
}
fn config_dir() -> std::path::PathBuf {
std::path::PathBuf::from(crate::CONFIG_PATH_BASE)
}
}
impl StdConfigLoad for AuraConfig {}
impl AuraConfig {
/// Detect the keyboard type and load from default DB if data available
pub fn new(prod_id: &str) -> Self {
info!("Setting up AuraConfig for {prod_id:?}");
// create a default config here
let device_type = AuraDeviceType::from(prod_id);
if device_type == AuraDeviceType::Unknown {
warn!("idProduct:{prod_id:?} is unknown");
}
let support_data = LedSupportData::get_data(prod_id);
let enabled = LaptopAuraPower::new(device_type, &support_data);
let mut config = AuraConfig {
led_type: device_type,
support_data,
config_name: format!("aura_{prod_id}.ron"),
ally_fix: None,
brightness: LedBrightness::Med,
current_mode: AuraModeNum::Static,
builtins: BTreeMap::new(),
multizone: None,
multizone_on: false,
enabled,
per_key_mode_active: false,
};
for n in &config.support_data.basic_modes {
debug!("creating default for {n}");
config
.builtins
.insert(*n, AuraEffect::default_with_mode(*n));
}
if !config.support_data.basic_zones.is_empty() {
for n in &config.support_data.basic_modes {
let mut default = vec![];
for (i, tmp) in config.support_data.basic_zones.iter().enumerate() {
default.push(AuraEffect {
mode: *n,
zone: *tmp,
colour1: *GRADIENT.get(i).unwrap_or(&GRADIENT[0]),
colour2: *GRADIENT.get(GRADIENT.len() - i).unwrap_or(&GRADIENT[6]),
speed: Speed::Med,
direction: Direction::Left,
});
}
if let Some(m) = config.multizone.as_mut() {
m.insert(*n, default);
} else {
let mut tmp = BTreeMap::new();
tmp.insert(*n, default);
config.multizone = Some(tmp);
}
}
}
config
}
/// Set the mode data, current mode, and if multizone enabled.
///
/// Multipurpose, will accept `AuraEffect` with zones and put in the correct
/// store.
pub fn set_builtin(&mut self, effect: AuraEffect) {
self.current_mode = effect.mode;
if effect.zone() == AuraZone::None {
self.builtins.insert(*effect.mode(), effect);
self.multizone_on = false;
} else {
if let Some(multi) = self.multizone.as_mut() {
if let Some(fx_vec) = multi.get_mut(effect.mode()) {
for fx in fx_vec.iter_mut() {
if fx.zone == effect.zone {
*fx = effect;
return;
}
}
fx_vec.push(effect);
} else {
multi.insert(*effect.mode(), vec![effect]);
}
} else {
let mut tmp = BTreeMap::new();
tmp.insert(*effect.mode(), vec![effect]);
self.multizone = Some(tmp);
}
self.multizone_on = true;
}
}
pub fn get_multizone(&self, aura_type: AuraModeNum) -> Option<&[AuraEffect]> {
if let Some(multi) = &self.multizone {
return multi.get(&aura_type).map(|v| v.as_slice());
}
None
}
/// Create a default for the `current_mode` if multizone and no config
/// exists.
pub fn create_multizone_default(&mut self) -> Result<(), RogError> {
let mut default = vec![];
for (i, tmp) in self.support_data.basic_zones.iter().enumerate() {
default.push(AuraEffect {
mode: self.current_mode,
zone: *tmp,
colour1: *GRADIENT.get(i).unwrap_or(&GRADIENT[0]),
colour2: *GRADIENT.get(GRADIENT.len() - i).unwrap_or(&GRADIENT[6]),
speed: Speed::Med,
direction: Direction::Left,
});
}
if default.is_empty() {
return Err(RogError::AuraEffectNotSupported);
}
if let Some(multizones) = self.multizone.as_mut() {
multizones.insert(self.current_mode, default);
} else {
let mut tmp = BTreeMap::new();
tmp.insert(self.current_mode, default);
self.multizone = Some(tmp);
}
Ok(())
}
/// Reload the config from disk then verify and update it if required.
/// Always rewrites the file to disk.
pub fn load_and_update_config(prod_id: &str) -> AuraConfig {
// New loads data from the DB also
let mut config_init = AuraConfig::new(prod_id);
// config_init.set_filename(prod_id);
let mut config_loaded = config_init.clone().load();
// update the initialised data with what we loaded from disk
for mode_init in &mut config_init.builtins {
// update init values from loaded values if they exist
if let Some(loaded) = config_loaded.builtins.get(mode_init.0) {
*mode_init.1 = loaded.clone();
}
}
// Then replace just incase the initialised data contains new modes added
config_loaded.builtins = config_init.builtins;
config_loaded.support_data = config_init.support_data;
config_loaded.led_type = config_init.led_type;
config_loaded.ally_fix = config_init.ally_fix;
for enabled_init in &mut config_init.enabled.states {
for enabled in &mut config_loaded.enabled.states {
if enabled.zone == enabled_init.zone {
*enabled_init = *enabled;
break;
}
}
}
config_loaded.enabled = config_init.enabled;
if let (Some(mut multizone_init), Some(multizone_loaded)) =
(config_init.multizone, config_loaded.multizone.as_mut())
{
for mode in multizone_init.iter_mut() {
// update init values from loaded values if they exist
if let Some(loaded) = multizone_loaded.get(mode.0) {
let mut new_set = Vec::new();
let data = LedSupportData::get_data(prod_id);
// only reuse a zone mode if the mode is supported
for mode in loaded {
if data.basic_modes.contains(&mode.mode) {
new_set.push(mode.clone());
}
}
*mode.1 = new_set;
}
}
*multizone_loaded = multizone_init;
}
config_loaded.write();
config_loaded
}
}
#[cfg(test)]
mod tests {
use std::sync::{Mutex, MutexGuard, OnceLock};
use rog_aura::keyboard::AuraPowerState;
use rog_aura::{
AuraEffect, AuraModeNum, AuraZone, Colour, Direction, LedBrightness, PowerZones, Speed,
};
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]
fn set_multizone_4key_config() {
let _guard = test_lock();
std::env::set_var("BOARD_NAME", "");
let mut config = AuraConfig::new("19b6");
let effect = AuraEffect {
colour1: Colour {
r: 0xff,
g: 0x00,
b: 0xff,
},
zone: AuraZone::Key1,
..Default::default()
};
config.set_builtin(effect);
assert!(config.multizone.is_some());
let effect = AuraEffect {
colour1: Colour {
r: 0x00,
g: 0xff,
b: 0xff,
},
zone: AuraZone::Key2,
..Default::default()
};
config.set_builtin(effect);
let effect = AuraEffect {
colour1: Colour {
r: 0xff,
g: 0xff,
b: 0x00,
},
zone: AuraZone::Key3,
..Default::default()
};
config.set_builtin(effect);
let effect = AuraEffect {
colour1: Colour {
r: 0x00,
g: 0xff,
b: 0x00,
},
zone: AuraZone::Key4,
..Default::default()
};
let effect_clone = effect.clone();
config.set_builtin(effect);
// This should replace existing
config.set_builtin(effect_clone);
let res = config.multizone.unwrap();
let sta = res.get(&AuraModeNum::Static).unwrap();
assert_eq!(sta.len(), 4);
assert_eq!(
sta[0].colour1,
Colour {
r: 0xff,
g: 0x00,
b: 0xff
}
);
assert_eq!(
sta[1].colour1,
Colour {
r: 0x00,
g: 0xff,
b: 0xff
}
);
assert_eq!(
sta[2].colour1,
Colour {
r: 0xff,
g: 0xff,
b: 0x00
}
);
assert_eq!(
sta[3].colour1,
Colour {
r: 0x00,
g: 0xff,
b: 0x00
}
);
}
#[test]
fn set_multizone_multimode_config() {
let _guard = test_lock();
std::env::set_var("BOARD_NAME", "");
let mut config = AuraConfig::new("19b6");
let effect = AuraEffect {
zone: AuraZone::Key1,
..Default::default()
};
config.set_builtin(effect);
assert!(config.multizone.is_some());
let effect = AuraEffect {
zone: AuraZone::Key2,
mode: AuraModeNum::Breathe,
..Default::default()
};
config.set_builtin(effect);
let effect = AuraEffect {
zone: AuraZone::Key3,
mode: AuraModeNum::Comet,
..Default::default()
};
config.set_builtin(effect);
let effect = AuraEffect {
zone: AuraZone::Key4,
mode: AuraModeNum::Pulse,
..Default::default()
};
config.set_builtin(effect);
let res = config.multizone.unwrap();
let sta = res.get(&AuraModeNum::Static).unwrap();
assert_eq!(sta.len(), 1);
let sta = res.get(&AuraModeNum::Breathe).unwrap();
assert_eq!(sta.len(), 1);
let sta = res.get(&AuraModeNum::Comet).unwrap();
assert_eq!(sta.len(), 1);
let sta = res.get(&AuraModeNum::Pulse).unwrap();
assert_eq!(sta.len(), 1);
}
#[test]
fn verify_0x1866_g531i() {
let _guard = test_lock();
std::env::set_var("BOARD_NAME", "G513I");
let mut config = AuraConfig::new("1866");
assert_eq!(config.brightness, LedBrightness::Med);
assert_eq!(config.builtins.len(), 5);
assert_eq!(
config.builtins.first_entry().unwrap().get(),
&AuraEffect {
mode: AuraModeNum::Static,
zone: AuraZone::None,
colour1: Colour { r: 166, g: 0, b: 0 },
colour2: Colour { r: 0, g: 0, b: 0 },
speed: Speed::Med,
direction: Direction::Right
}
);
assert_eq!(config.enabled.states.len(), 1);
assert_eq!(
config.enabled.states[0],
AuraPowerState {
zone: PowerZones::KeyboardAndLightbar,
boot: true,
awake: true,
sleep: true,
shutdown: true
}
);
}
#[test]
fn verify_0x19b6_g634j() {
let _guard = test_lock();
std::env::set_var("BOARD_NAME", "G634J");
let mut config = AuraConfig::new("19b6");
assert_eq!(config.brightness, LedBrightness::Med);
assert_eq!(config.builtins.len(), 12);
assert_eq!(
config.builtins.first_entry().unwrap().get(),
&AuraEffect {
mode: AuraModeNum::Static,
zone: AuraZone::None,
colour1: Colour { r: 166, g: 0, b: 0 },
colour2: Colour { r: 0, g: 0, b: 0 },
speed: Speed::Med,
direction: Direction::Right
}
);
assert_eq!(config.enabled.states.len(), 4);
assert_eq!(
config.enabled.states[0],
AuraPowerState {
zone: PowerZones::Keyboard,
boot: true,
awake: true,
sleep: true,
shutdown: true
}
);
}
}

View File

@@ -0,0 +1,229 @@
use std::sync::Arc;
use config::AuraConfig;
use config_traits::StdConfig;
use log::info;
use rog_aura::keyboard::{AuraLaptopUsbPackets, LedUsbPackets};
use rog_aura::usb::{AURA_LAPTOP_LED_APPLY, AURA_LAPTOP_LED_SET};
use rog_aura::{AuraDeviceType, AuraEffect, LedBrightness, PowerZones, AURA_LAPTOP_LED_MSG_LEN};
use rog_platform::hid_raw::HidRaw;
use rog_platform::keyboard_led::KeyboardBacklight;
use tokio::sync::{Mutex, MutexGuard};
use crate::error::RogError;
pub mod config;
pub mod trait_impls;
#[derive(Debug, Clone)]
pub struct Aura {
pub hid: Option<Arc<Mutex<HidRaw>>>,
pub backlight: Option<Arc<Mutex<KeyboardBacklight>>>,
pub config: Arc<Mutex<AuraConfig>>,
}
impl Aura {
/// Initialise the device if required.
pub async fn do_initialization(&self) -> Result<(), RogError> {
Ok(())
}
pub async fn lock_config(&self) -> MutexGuard<'_, AuraConfig> {
self.config.lock().await
}
/// Will lock the internal config and update. If anything else has locked
/// this in scope then a deadlock can occur.
pub async fn update_config(&self) -> Result<(), RogError> {
let mut config = self.config.lock().await;
let bright = if let Some(bl) = self.backlight.as_ref() {
bl.lock().await.get_brightness().unwrap_or_default()
} else {
config.brightness.into()
};
config.read();
config.brightness = bright.into();
config.write();
Ok(())
}
pub async fn write_current_config_mode(&self, config: &mut AuraConfig) -> Result<(), RogError> {
if config.multizone_on {
let mode = config.current_mode;
let mut create = false;
// There is no multizone config for this mode so create one here
// using the colours of rainbow if it exists, or first available
// mode, or random
if config.multizone.is_none() {
create = true;
} else if let Some(multizones) = config.multizone.as_ref() {
if !multizones.contains_key(&mode) {
create = true;
}
}
if create {
info!("No user-set config for zone founding, attempting a default");
config.create_multizone_default()?;
}
if let Some(multizones) = config.multizone.as_mut() {
if let Some(set) = multizones.get(&mode) {
for mode in set.clone() {
self.write_effect_and_apply(config.led_type, &mode).await?;
}
}
}
} else {
let mode = config.current_mode;
if let Some(effect) = config.builtins.get(&mode).cloned() {
self.write_effect_and_apply(config.led_type, &effect)
.await?;
}
}
Ok(())
}
/// Write the AuraEffect to the device. Will lock `backlight` or `hid`.
///
/// If per-key or software-mode is active it must be marked as disabled in
/// config.
pub async fn write_effect_and_apply(
&self,
dev_type: AuraDeviceType,
mode: &AuraEffect,
) -> Result<(), RogError> {
if matches!(dev_type, AuraDeviceType::LaptopKeyboardTuf) {
if let Some(platform) = &self.backlight {
let buf = [
1, mode.mode as u8, mode.colour1.r, mode.colour1.g, mode.colour1.b,
mode.speed as u8,
];
platform.lock().await.set_kbd_rgb_mode(&buf)?;
}
} else if let Some(hid_raw) = &self.hid {
let bytes: [u8; AURA_LAPTOP_LED_MSG_LEN] = mode.into();
let hid_raw = hid_raw.lock().await;
hid_raw.write_bytes(&bytes)?;
hid_raw.write_bytes(&AURA_LAPTOP_LED_SET)?;
// Changes won't persist unless apply is set
hid_raw.write_bytes(&AURA_LAPTOP_LED_APPLY)?;
} else {
return Err(RogError::NoAuraKeyboard);
}
Ok(())
}
pub async fn set_brightness(&self, value: u8) -> Result<(), RogError> {
if let Some(backlight) = &self.backlight {
backlight.lock().await.set_brightness(value)?;
return Ok(());
}
Err(RogError::MissingFunction(
"No LED backlight control available".to_string(),
))
}
/// Set combination state for boot animation/sleep animation/all leds/keys
/// leds/side leds LED active
pub async fn set_power_states(&self, config: &AuraConfig) -> Result<(), RogError> {
if matches!(config.led_type, rog_aura::AuraDeviceType::LaptopKeyboardTuf) {
if let Some(backlight) = &self.backlight {
// TODO: tuf bool array
let buf = config.enabled.to_bytes(config.led_type);
backlight.lock().await.set_kbd_rgb_state(&buf)?;
}
} else if let Some(hid_raw) = &self.hid {
let hid_raw = hid_raw.lock().await;
if let Some(p) = config.enabled.states.first() {
if p.zone == PowerZones::Ally {
let msg = [
0x5d,
0xd1,
0x09,
0x01,
p.new_to_byte() as u8,
0x0,
0x0,
];
hid_raw.write_bytes(&msg)?;
return Ok(());
}
}
let bytes = config.enabled.to_bytes(config.led_type);
let msg = [
0x5d, 0xbd, 0x01, bytes[0], bytes[1], bytes[2], bytes[3],
];
hid_raw.write_bytes(&msg)?;
}
Ok(())
}
/// Write an effect block. This is for per-key, but can be repurposed to
/// write the raw factory mode packets - when doing this it is expected that
/// only the first `Vec` (`effect[0]`) is valid.
pub async fn write_effect_block(
&self,
config: &mut AuraConfig,
effect: &AuraLaptopUsbPackets,
) -> Result<(), RogError> {
if config.brightness == LedBrightness::Off {
config.brightness = LedBrightness::Med;
config.write();
}
let pkt_type = effect[0][1];
const PER_KEY_TYPE: u8 = 0xbc;
if let Some(hid_raw) = &self.hid {
let hid_raw = hid_raw.lock().await;
if pkt_type != PER_KEY_TYPE {
config.per_key_mode_active = false;
hid_raw.write_bytes(&effect[0])?;
hid_raw.write_bytes(&AURA_LAPTOP_LED_SET)?;
// hid_raw.write_bytes(&LED_APPLY)?;
} else {
if !config.per_key_mode_active {
let init = LedUsbPackets::get_init_msg();
hid_raw.write_bytes(&init)?;
config.per_key_mode_active = true;
}
for row in effect.iter() {
hid_raw.write_bytes(row)?;
}
}
} else if matches!(config.led_type, rog_aura::AuraDeviceType::LaptopKeyboardTuf) {
if let Some(tuf) = &self.backlight {
for row in effect.iter() {
let r = row[9];
let g = row[10];
let b = row[11];
tuf.lock().await.set_kbd_rgb_mode(&[
0, 0, r, g, b, 0,
])?;
}
}
}
Ok(())
}
pub async fn fix_ally_power(&mut self) -> Result<(), RogError> {
if self.config.lock().await.led_type == AuraDeviceType::Ally {
if let Some(hid_raw) = &self.hid {
let mut config = self.config.lock().await;
if config.ally_fix.is_none() {
let msg = [
0x5d, 0xbd, 0x01, 0xff, 0xff, 0xff, 0xff,
];
hid_raw.lock().await.write_bytes(&msg)?;
info!("Reset Ally power settings to base");
config.ally_fix = Some(true);
}
config.write();
}
}
Ok(())
}
}

View File

@@ -0,0 +1,343 @@
use std::collections::BTreeMap;
use config_traits::StdConfig;
use log::{debug, error, info, warn};
use rog_aura::keyboard::{AuraLaptopUsbPackets, LaptopAuraPower};
use rog_aura::{AuraDeviceType, AuraEffect, AuraModeNum, AuraZone, LedBrightness, PowerZones};
use zbus::fdo::Error as ZbErr;
use zbus::object_server::SignalEmitter;
use zbus::zvariant::OwnedObjectPath;
use zbus::{interface, Connection};
use super::Aura;
use crate::error::RogError;
use crate::{CtrlTask, Reloadable};
pub const AURA_ZBUS_NAME: &str = "Aura";
pub const AURA_ZBUS_PATH: &str = "/xyz/ljones";
#[derive(Clone)]
pub struct AuraZbus(Aura);
impl AuraZbus {
pub fn new(aura: Aura) -> Self {
Self(aura)
}
pub async fn start_tasks(
mut self,
connection: &Connection,
// _signal_ctx: SignalEmitter<'static>,
path: OwnedObjectPath,
) -> Result<(), RogError> {
// let task = zbus.clone();
// let signal_ctx = signal_ctx.clone();
self.reload()
.await
.unwrap_or_else(|err| warn!("Controller error: {}", err));
connection
.object_server()
.at(path.clone(), self)
.await
.map_err(|e| error!("Couldn't add server at path: {path}, {e:?}"))
.ok();
// TODO: skip this until we keep handles to tasks so they can be killed
// task.create_tasks(signal_ctx).await
Ok(())
}
}
/// The main interface for changing, reading, or notfying
///
/// LED commands are split between Brightness, Modes, Per-Key
#[interface(name = "xyz.ljones.Aura")]
impl AuraZbus {
/// Return the device type for this Aura keyboard
#[zbus(property)]
async fn device_type(&self) -> AuraDeviceType {
self.0.config.lock().await.led_type
}
/// Return the current LED brightness
#[zbus(property)]
async fn brightness(&self) -> Result<LedBrightness, ZbErr> {
if let Some(bl) = self.0.backlight.as_ref() {
return Ok(bl.lock().await.get_brightness().map(|n| n.into())?);
}
Err(ZbErr::Failed("No sysfs brightness control".to_string()))
}
/// Set the keyboard brightness level (0-3)
#[zbus(property)]
async fn set_brightness(&mut self, brightness: LedBrightness) -> Result<(), ZbErr> {
if let Some(bl) = self.0.backlight.as_ref() {
return Ok(bl.lock().await.set_brightness(brightness.into())?);
}
Err(ZbErr::Failed("No sysfs brightness control".to_string()))
}
/// Total levels of brightness available
#[zbus(property)]
async fn supported_brightness(&self) -> Vec<LedBrightness> {
vec![
LedBrightness::Off,
LedBrightness::Low,
LedBrightness::Med,
LedBrightness::High,
]
}
/// The total available modes
#[zbus(property)]
async fn supported_basic_modes(&self) -> Result<Vec<AuraModeNum>, ZbErr> {
let config = self.0.config.lock().await;
Ok(config.builtins.keys().cloned().collect())
}
#[zbus(property)]
async fn supported_basic_zones(&self) -> Result<Vec<AuraZone>, ZbErr> {
let config = self.0.config.lock().await;
Ok(config.support_data.basic_zones.clone())
}
#[zbus(property)]
async fn supported_power_zones(&self) -> Result<Vec<PowerZones>, ZbErr> {
let config = self.0.config.lock().await;
Ok(config.support_data.power_zones.clone())
}
/// The current mode data
#[zbus(property)]
async fn led_mode(&self) -> Result<AuraModeNum, ZbErr> {
// entirely possible to deadlock here, so use try instead of lock()
// let ctrl = self.0.lock().await;
// Ok(config.current_mode)
if let Ok(config) = self.0.config.try_lock() {
Ok(config.current_mode)
} else {
Err(ZbErr::Failed("Aura control couldn't lock self".to_string()))
}
}
/// Set an Aura effect if the effect mode or zone is supported.
///
/// On success the aura config file is read to refresh cached values, then
/// the effect is stored and config written to disk.
#[zbus(property)]
async fn set_led_mode(&mut self, num: AuraModeNum) -> Result<(), ZbErr> {
let mut config = self.0.config.lock().await;
config.current_mode = num;
self.0.write_current_config_mode(&mut config).await?;
if config.brightness == LedBrightness::Off {
config.brightness = LedBrightness::Med;
}
self.0.set_brightness(config.brightness.into()).await?;
config.write();
Ok(())
}
/// The current mode data
#[zbus(property)]
async fn led_mode_data(&self) -> Result<AuraEffect, ZbErr> {
// entirely possible to deadlock here, so use try instead of lock()
if let Ok(config) = self.0.config.try_lock() {
let mode = config.current_mode;
match config.builtins.get(&mode) {
Some(effect) => Ok(effect.clone()),
None => Err(ZbErr::Failed("Could not get the current effect".into())),
}
} else {
Err(ZbErr::Failed("Aura control couldn't lock self".to_string()))
}
}
/// Set an Aura effect if the effect mode or zone is supported.
///
/// On success the aura config file is read to refresh cached values, then
/// the effect is stored and config written to disk.
#[zbus(property)]
async fn set_led_mode_data(&mut self, effect: AuraEffect) -> Result<(), ZbErr> {
let mut config = self.0.config.lock().await;
if !config.support_data.basic_modes.contains(&effect.mode)
|| effect.zone != AuraZone::None
&& !config.support_data.basic_zones.contains(&effect.zone)
{
return Err(ZbErr::NotSupported(format!(
"The Aura effect is not supported: {effect:?}"
)));
}
self.0
.write_effect_and_apply(config.led_type, &effect)
.await?;
if config.brightness == LedBrightness::Off {
config.brightness = LedBrightness::Med;
}
self.0.set_brightness(config.brightness.into()).await?;
config.set_builtin(effect);
config.write();
Ok(())
}
/// Get the data set for every mode available
async fn all_mode_data(&self) -> BTreeMap<AuraModeNum, AuraEffect> {
let config = self.0.config.lock().await;
config.builtins.clone()
}
// As property doesn't work for AuraPowerDev (complexity of serialization?)
#[zbus(property)]
async fn led_power(&self) -> LaptopAuraPower {
let config = self.0.config.lock().await;
config.enabled.clone()
}
/// Set a variety of states, input is array of enum.
/// `enabled` sets if the sent array should be disabled or enabled
///
/// For Modern ROG devices the "enabled" flag is ignored.
#[zbus(property)]
async fn set_led_power(&mut self, options: LaptopAuraPower) -> Result<(), ZbErr> {
let mut config = self.0.config.lock().await;
for opt in options.states {
let zone = opt.zone;
for config in config.enabled.states.iter_mut() {
if config.zone == zone {
*config = opt;
}
}
}
config.write();
Ok(self.0.set_power_states(&config).await.map_err(|e| {
warn!("{}", e);
e
})?)
}
/// On machine that have some form of either per-key keyboard or per-zone
/// this can be used to write custom effects over dbus. The input is a
/// nested `Vec<Vec<8>>` where `Vec<u8>` is a raw USB packet
async fn direct_addressing_raw(&self, data: AuraLaptopUsbPackets) -> Result<(), ZbErr> {
let mut config = self.0.config.lock().await;
self.0.write_effect_block(&mut config, &data).await?;
Ok(())
}
}
impl CtrlTask for AuraZbus {
fn zbus_path() -> &'static str {
"/xyz/ljones"
}
async fn create_tasks(&self, _: SignalEmitter<'static>) -> Result<(), RogError> {
let inner1 = self.0.clone();
let inner3 = self.0.clone();
self.create_sys_event_tasks(
move |sleeping| {
let inner1 = inner1.clone();
// unwrap as we want to bomb out of the task
async move {
if !sleeping {
info!("CtrlKbdLedTask reloading brightness and modes");
if let Some(backlight) = &inner1.backlight {
backlight
.lock()
.await
.set_brightness(inner1.config.lock().await.brightness.into())
.map_err(|e| {
error!("CtrlKbdLedTask: {e}");
e
})
.unwrap();
}
let mut config = inner1.config.lock().await;
inner1
.write_current_config_mode(&mut config)
.await
.map_err(|e| {
error!("CtrlKbdLedTask: {e}");
e
})
.unwrap();
} else if sleeping {
inner1
.update_config()
.await
.map_err(|e| {
error!("CtrlKbdLedTask: {e}");
e
})
.unwrap();
}
}
},
move |_shutting_down| {
let inner3 = inner3.clone();
async move {
info!("CtrlKbdLedTask reloading brightness and modes");
if let Some(backlight) = &inner3.backlight {
// unwrap as we want to bomb out of the task
backlight
.lock()
.await
.set_brightness(inner3.config.lock().await.brightness.into())
.map_err(|e| {
error!("CtrlKbdLedTask: {e}");
e
})
.unwrap();
}
}
},
move |_lid_closed| {
// on lid change
async move {}
},
move |_power_plugged| {
// power change
async move {}
},
)
.await;
// let ctrl2 = self.0.clone();
// let ctrl = self.0.lock().await;
// if ctrl.led_node.has_brightness_control() {
// let watch = ctrl.led_node.monitor_brightness()?;
// tokio::spawn(async move {
// let mut buffer = [0; 32];
// watch
// .into_event_stream(&mut buffer)
// .unwrap()
// .for_each(|_| async {
// if let Some(lock) = ctrl2.try_lock() {
// load_save(true, lock).unwrap(); // unwrap as we want
// // to
// // bomb out of the
// // task
// }
// })
// .await;
// });
// }
Ok(())
}
}
impl Reloadable for AuraZbus {
async fn reload(&mut self) -> Result<(), RogError> {
self.0.fix_ally_power().await?;
debug!("reloading keyboard mode");
let mut config = self.0.lock_config().await;
self.0.write_current_config_mode(&mut config).await?;
debug!("reloading power states");
self.0
.set_power_states(&config)
.await
.map_err(|err| warn!("{err}"))
.ok();
Ok(())
}
}

591
asusd/src/aura_manager.rs Normal file
View File

@@ -0,0 +1,591 @@
// Plan:
// - Manager has udev monitor on USB looking for ROG devices
// - If a device is found, add it to watch
// - Add it to Zbus server
// - If udev sees device removed then remove the zbus path
use std::collections::HashMap;
use std::sync::Arc;
use dmi_id::DMIID;
use futures_lite::future::block_on;
use log::{debug, error, info, warn};
use mio::{Events, Interest, Poll, Token};
use rog_platform::error::PlatformError;
use rog_platform::hid_raw::HidRaw;
use tokio::sync::Mutex;
use udev::{Device, MonitorBuilder};
use zbus::zvariant::{ObjectPath, OwnedObjectPath};
use zbus::Connection;
use crate::aura_anime::trait_impls::AniMeZbus;
use crate::aura_laptop::trait_impls::AuraZbus;
use crate::aura_scsi::trait_impls::ScsiZbus;
use crate::aura_slash::trait_impls::SlashZbus;
use crate::aura_types::DeviceHandle;
use crate::error::RogError;
use crate::ASUS_ZBUS_PATH;
const MOD_NAME: &str = "aura";
/// Returns only the Device details concatenated in a form usable for
/// adding/appending to a filename
pub fn filename_partial(parent: &Device) -> Option<OwnedObjectPath> {
if let Some(id_product) = parent.attribute_value("idProduct") {
let id_product = id_product.to_string_lossy();
let mut path = if let Some(devnum) = parent.attribute_value("devnum") {
let devnum = devnum.to_string_lossy();
if let Some(devpath) = parent.attribute_value("devpath") {
let devpath = devpath.to_string_lossy();
format!("{id_product}_{devnum}_{devpath}")
} else {
format!("{id_product}_{devnum}")
}
} else {
format!("{id_product}")
};
if path.contains('.') {
warn!("dbus path for {id_product} contains `.`, removing");
path.replace('.', "").clone_into(&mut path);
}
return Some(ObjectPath::from_str_unchecked(&path).into());
}
None
}
fn dbus_path_for_dev(parent: &Device) -> Option<OwnedObjectPath> {
if let Some(filename) = filename_partial(parent) {
return Some(
ObjectPath::from_str_unchecked(&format!("{ASUS_ZBUS_PATH}/{MOD_NAME}/{filename}"))
.into(),
);
}
None
}
fn dbus_path_for_tuf() -> OwnedObjectPath {
ObjectPath::from_str_unchecked(&format!("{ASUS_ZBUS_PATH}/{MOD_NAME}/tuf")).into()
}
fn dbus_path_for_slash() -> OwnedObjectPath {
ObjectPath::from_str_unchecked(&format!("{ASUS_ZBUS_PATH}/{MOD_NAME}/slash")).into()
}
fn dbus_path_for_anime() -> OwnedObjectPath {
ObjectPath::from_str_unchecked(&format!("{ASUS_ZBUS_PATH}/{MOD_NAME}/anime")).into()
}
fn dbus_path_for_scsi(prod_id: &str) -> OwnedObjectPath {
ObjectPath::from_str_unchecked(&format!("{ASUS_ZBUS_PATH}/{MOD_NAME}/{prod_id}_scsi")).into()
}
fn dev_prop_matches(dev: &Device, prop: &str, value: &str) -> bool {
if let Some(p) = dev.property_value(prop) {
return p == value;
}
false
}
/// A device.
///
/// Each controller within should track its dbus path so it can be removed if
/// required.
pub struct AsusDevice {
device: DeviceHandle,
dbus_path: OwnedObjectPath,
hid_key: Option<String>,
}
pub struct DeviceManager {
_dbus_connection: Connection,
_hid_handles: Arc<Mutex<HashMap<String, Arc<Mutex<HidRaw>>>>>,
}
impl DeviceManager {
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(
connection: &Connection,
device: Device,
handles: Arc<Mutex<HashMap<String, Arc<Mutex<HidRaw>>>>>,
) -> Result<Vec<AsusDevice>, RogError> {
let mut devices = Vec::new();
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(vendor_id) = usb_device.attribute_value("idVendor") {
if vendor_id != "0b05" {
debug!("Not ASUS vendor ID");
return Ok(devices);
}
// Almost all devices are identified by the productId.
// So let's see what we have and:
// 1. Generate an interface path
// 2. Create the device
// Use the top-level endpoint, not the parent
if let Ok((dev, hid_key)) =
Self::get_or_create_hid_handle(&handles, &device).await
{
debug!("Testing device {usb_id:?}");
// SLASH DEVICE
if let Ok(dev_type) = DeviceHandle::new_slash_hid(
dev.clone(),
usb_id.to_str().unwrap_or_default(),
)
.await
{
if let DeviceHandle::Slash(slash) = dev_type.clone() {
let path =
dbus_path_for_dev(&usb_device).unwrap_or(dbus_path_for_slash());
let ctrl = SlashZbus::new(slash);
ctrl.start_tasks(connection, path.clone()).await.unwrap();
devices.push(AsusDevice {
device: dev_type,
dbus_path: path,
hid_key: Some(hid_key.clone()),
});
}
}
// ANIME MATRIX DEVICE
if let Ok(dev_type) = DeviceHandle::maybe_anime_hid(
dev.clone(),
usb_id.to_str().unwrap_or_default(),
)
.await
{
if let DeviceHandle::AniMe(anime) = dev_type.clone() {
let path =
dbus_path_for_dev(&usb_device).unwrap_or(dbus_path_for_anime());
let ctrl = AniMeZbus::new(anime);
ctrl.start_tasks(connection, path.clone()).await.unwrap();
devices.push(AsusDevice {
device: dev_type,
dbus_path: path,
hid_key: Some(hid_key.clone()),
});
}
}
// AURA LAPTOP DEVICE
if let Ok(dev_type) = DeviceHandle::maybe_laptop_aura(
Some(dev),
usb_id.to_str().unwrap_or_default(),
)
.await
{
if let DeviceHandle::Aura(aura) = dev_type.clone() {
let path =
dbus_path_for_dev(&usb_device).unwrap_or(dbus_path_for_tuf());
let ctrl = AuraZbus::new(aura);
ctrl.start_tasks(connection, path.clone()).await.unwrap();
devices.push(AsusDevice {
device: dev_type,
dbus_path: path,
hid_key: Some(hid_key),
});
}
}
} else {
warn!("Failed to initialise shared hid handle for {usb_id:?}");
}
}
}
}
Ok(devices)
}
/// To be called on daemon startup
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
// let mut interfaces = HashSet::new();
let mut devices: Vec<AsusDevice> = Vec::new();
let mut enumerator = udev::Enumerator::new().map_err(|err| {
warn!("{}", err);
PlatformError::Udev("enumerator failed".into(), err)
})?;
enumerator.match_subsystem("hidraw").map_err(|err| {
warn!("{}", err);
PlatformError::Udev("match_subsystem failed".into(), err)
})?;
for device in enumerator
.scan_devices()
.map_err(|e| PlatformError::IoPath("enumerator".to_owned(), e))?
{
devices.append(&mut Self::init_hid_devices(connection, device, handles.clone()).await?);
}
Ok(devices)
}
async fn init_scsi(
connection: &Connection,
device: &Device,
path: OwnedObjectPath,
) -> Option<AsusDevice> {
// "ID_MODEL_ID" "1932"
// "ID_VENDOR_ID" "0b05"
if dev_prop_matches(device, "ID_VENDOR_ID", "0b05") {
if let Some(dev_node) = device.devnode() {
let prod_id = device
.property_value("ID_MODEL_ID")
.unwrap_or_default()
.to_string_lossy();
if let Ok(dev_type) =
DeviceHandle::maybe_scsi(dev_node.as_os_str().to_str().unwrap(), &prod_id).await
{
if let DeviceHandle::Scsi(scsi) = dev_type.clone() {
let ctrl = ScsiZbus::new(scsi);
ctrl.start_tasks(connection, path.clone()).await.unwrap();
return Some(AsusDevice {
device: dev_type,
dbus_path: path,
hid_key: None,
});
}
}
}
}
None
}
async fn init_all_scsi(connection: &Connection) -> Result<Vec<AsusDevice>, RogError> {
// track and ensure we use only one hidraw per prod_id
// let mut interfaces = HashSet::new();
let mut devices: Vec<AsusDevice> = Vec::new();
let mut enumerator = udev::Enumerator::new().map_err(|err| {
warn!("{}", err);
PlatformError::Udev("enumerator failed".into(), err)
})?;
enumerator.match_subsystem("block").map_err(|err| {
warn!("{}", err);
PlatformError::Udev("match_subsystem failed".into(), err)
})?;
let mut found = Vec::new();
for device in enumerator
.scan_devices()
.map_err(|e| PlatformError::IoPath("enumerator".to_owned(), e))?
{
if let Some(serial) = device.property_value("ID_SERIAL_SHORT") {
let serial = serial.to_string_lossy().to_string();
let path = dbus_path_for_scsi(&serial);
if found.contains(&path) {
continue;
}
if let Some(dev) = Self::init_scsi(connection, &device, path.clone()).await {
devices.push(dev);
found.push(path);
}
} else {
debug!("No serial for SCSI device: {:?}", device.devpath());
}
}
Ok(devices)
}
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();
// HID first, always
if let Ok(devs) = &mut Self::init_all_hid(connection, handles.clone()).await {
devices.append(devs);
}
// USB after, need to check if HID picked something up and if so, skip it
let mut do_anime = true;
let mut do_slash = true;
let mut do_kb_backlight = true;
for dev in devices.iter() {
if matches!(dev.device, DeviceHandle::Slash(_)) {
do_slash = false;
}
if matches!(dev.device, DeviceHandle::AniMe(_)) {
do_anime = false;
}
if matches!(dev.device, DeviceHandle::Aura(_) | DeviceHandle::OldAura(_)) {
do_kb_backlight = false;
}
}
if do_slash {
if let Ok(dev_type) = DeviceHandle::new_slash_usb().await {
if let DeviceHandle::Slash(slash) = dev_type.clone() {
let path = dbus_path_for_slash();
let ctrl = SlashZbus::new(slash);
ctrl.start_tasks(connection, path.clone()).await.unwrap();
devices.push(AsusDevice {
device: dev_type,
dbus_path: path,
hid_key: None,
});
}
} else {
info!("Tested device was not Slash");
}
}
if do_anime {
if let Ok(dev_type) = DeviceHandle::maybe_anime_usb().await {
// TODO: this is copy/pasted
if let DeviceHandle::AniMe(anime) = dev_type.clone() {
let path = dbus_path_for_anime();
let ctrl = AniMeZbus::new(anime);
if ctrl
.start_tasks(connection, path.clone())
.await
.map_err(|e| error!("Failed to start tasks: {e:?}, not adding this device"))
.is_ok()
{
devices.push(AsusDevice {
device: dev_type,
dbus_path: path,
hid_key: None,
});
}
}
} else {
info!("Tested device was not AniMe Matrix");
}
}
if do_kb_backlight {
// TUF AURA LAPTOP DEVICE
// product_name = ASUS TUF Gaming F15 FX507ZE_FX507ZE
// product_family = ASUS TUF Gaming F15
let product_name = DMIID::new().unwrap_or_default().product_name;
let product_family = DMIID::new().unwrap_or_default().product_family;
info!(
"No USB keyboard aura, system is {product_name}, try using sysfs backlight control"
);
if product_name.contains("TUF") || product_family.contains("TUF") {
info!("TUF laptop, try using sysfs backlight control");
if let Ok(dev_type) = DeviceHandle::maybe_laptop_aura(None, "tuf").await {
if let DeviceHandle::Aura(aura) = dev_type.clone() {
let path = dbus_path_for_tuf();
let ctrl = AuraZbus::new(aura);
ctrl.start_tasks(connection, path.clone()).await.unwrap();
devices.push(AsusDevice {
device: dev_type,
dbus_path: path,
hid_key: None,
});
}
}
}
}
if let Ok(devs) = &mut Self::init_all_scsi(connection).await {
devices.append(devs);
}
devices
}
pub async fn new(connection: Connection) -> Result<Self, RogError> {
let conn_copy = connection.clone();
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());
let devices = Arc::new(Mutex::new(devices));
let manager = Self {
_dbus_connection: connection,
_hid_handles: hid_handles.clone(),
};
// TODO: The /sysfs/ LEDs don't cause events, so they need to be manually
// checked for and added
let hid_handles_thread = hid_handles.clone();
std::thread::spawn(move || {
let mut monitor = MonitorBuilder::new()?.listen()?;
let mut poll = Poll::new()?;
let mut events = Events::with_capacity(1024);
poll.registry()
.register(&mut monitor, Token(0), Interest::READABLE)?;
let rt = tokio::runtime::Runtime::new().expect("Unable to create Runtime");
let _enter = rt.enter();
loop {
if poll.poll(&mut events, None).is_err() {
continue;
}
for event in monitor.iter() {
let action = event
.action()
.unwrap_or_default()
.to_string_lossy()
.to_string();
let subsys = if let Some(subsys) = event.subsystem() {
subsys.to_string_lossy().to_string()
} else {
continue;
};
let devices = devices.clone();
let conn_copy = conn_copy.clone();
let hid_handles = hid_handles_thread.clone();
block_on(async move {
// SCSCI devs
if subsys == "block" {
if action == "remove" {
if let Some(serial) =
event.device().property_value("ID_SERIAL_SHORT")
{
let serial = serial.to_string_lossy().to_string();
let path = dbus_path_for_scsi(&serial);
let index = if let Some(index) = devices
.lock()
.await
.iter()
.position(|dev| dev.dbus_path == path)
{
index
} else {
if dev_prop_matches(&event.device(), "ID_VENDOR_ID", "0b05")
{
warn!("No device for dbus path: {path:?}");
}
return Ok(());
};
info!("removing: {path:?}");
let dev = devices.lock().await.remove(index);
let path = path.clone();
if let DeviceHandle::Scsi(_) = dev.device {
conn_copy
.object_server()
.remove::<ScsiZbus, _>(&path)
.await?;
}
}
} else if action == "add" {
let evdev = event.device();
if let Some(serial) = evdev.property_value("ID_SERIAL_SHORT") {
let serial = serial.to_string_lossy().to_string();
let path = dbus_path_for_scsi(&serial);
if let Some(new_devs) =
Self::init_scsi(&conn_copy, &evdev, path).await
{
devices.lock().await.append(&mut vec![new_devs]);
}
}
};
}
if subsys == "hidraw" {
if let Some(parent) =
event.parent_with_subsystem_devtype("usb", "usb_device")?
{
if action == "remove" {
if let Some(path) = dbus_path_for_dev(&parent) {
// Find the indexs of devices matching the path
let removals: Vec<usize> = devices
.lock()
.await
.iter()
.enumerate()
.filter_map(|(i, dev)| {
if dev.dbus_path == path {
Some(i)
} else {
None
}
})
.collect();
if removals.is_empty() {
return Ok(());
}
info!("removing: {path:?}");
// Iter in reverse so as to not screw up indexing
for index in removals.iter().rev() {
let dev = devices.lock().await.remove(*index);
let hid_key = dev.hid_key.clone();
let path = path.clone();
let res = match dev.device {
DeviceHandle::Aura(_) => {
conn_copy
.object_server()
.remove::<AuraZbus, _>(&path)
.await?
}
DeviceHandle::Slash(_) => {
conn_copy
.object_server()
.remove::<SlashZbus, _>(&path)
.await?
}
DeviceHandle::AniMe(_) => {
conn_copy
.object_server()
.remove::<AniMeZbus, _>(&path)
.await?
}
DeviceHandle::Scsi(_) => {
conn_copy
.object_server()
.remove::<ScsiZbus, _>(&path)
.await?
}
_ => todo!(),
};
info!("AuraManager removed: {path:?}, {res}");
if let Some(key) = hid_key {
hid_handles.lock().await.remove(&key);
}
}
}
} else if action == "add" {
let evdev = event.device();
if let Ok(mut new_devs) = Self::init_hid_devices(
&conn_copy,
evdev,
hid_handles.clone(),
)
.await
.map_err(|e| error!("Couldn't add new device: {e:?}"))
{
devices.lock().await.append(&mut new_devs);
}
};
}
}
Ok::<(), RogError>(())
})
.map_err(|e| error!("{e:?}"))
.ok();
}
}
// Required for return type on spawn
#[allow(unreachable_code)]
Ok::<(), RogError>(())
});
Ok(manager)
}
}

View File

@@ -0,0 +1,114 @@
use std::collections::BTreeMap;
use config_traits::{StdConfig, StdConfigLoad};
use rog_aura::AuraDeviceType;
use rog_scsi::{AuraEffect, AuraMode};
use serde::{Deserialize, Serialize};
const CONFIG_FILE: &str = "scsi.ron";
/// Config for base system actions for the anime display
#[derive(Deserialize, Serialize, Debug)]
pub struct ScsiConfig {
#[serde(skip)]
pub dev_type: AuraDeviceType,
pub enabled: bool,
pub current_mode: AuraMode,
pub modes: BTreeMap<AuraMode, AuraEffect>,
}
impl ScsiConfig {
pub fn get_effect(&mut self, mode: AuraMode) -> Option<&AuraEffect> {
self.modes.get(&mode)
}
pub fn save_effect(&mut self, effect: AuraEffect) {
self.current_mode = effect.mode;
self.modes.insert(*effect.mode(), effect);
}
}
impl Default for ScsiConfig {
fn default() -> Self {
ScsiConfig {
enabled: true,
current_mode: AuraMode::Static,
dev_type: AuraDeviceType::ScsiExtDisk,
modes: BTreeMap::from([
(AuraMode::Off, AuraEffect::default_with_mode(AuraMode::Off)),
(
AuraMode::Static,
AuraEffect::default_with_mode(AuraMode::Static),
),
(
AuraMode::Breathe,
AuraEffect::default_with_mode(AuraMode::Breathe),
),
(
AuraMode::Flashing,
AuraEffect::default_with_mode(AuraMode::Flashing),
),
(
AuraMode::RainbowCycle,
AuraEffect::default_with_mode(AuraMode::RainbowCycle),
),
(
AuraMode::RainbowWave,
AuraEffect::default_with_mode(AuraMode::RainbowWave),
),
(
AuraMode::RainbowCycleBreathe,
AuraEffect::default_with_mode(AuraMode::RainbowCycleBreathe),
),
(
AuraMode::ChaseFade,
AuraEffect::default_with_mode(AuraMode::ChaseFade),
),
(
AuraMode::RainbowCycleChaseFade,
AuraEffect::default_with_mode(AuraMode::RainbowCycleChaseFade),
),
(
AuraMode::Chase,
AuraEffect::default_with_mode(AuraMode::Chase),
),
(
AuraMode::RainbowCycleChase,
AuraEffect::default_with_mode(AuraMode::RainbowCycleChase),
),
(
AuraMode::RainbowCycleWave,
AuraEffect::default_with_mode(AuraMode::RainbowCycleWave),
),
(
AuraMode::RainbowPulseChase,
AuraEffect::default_with_mode(AuraMode::RainbowPulseChase),
),
(
AuraMode::RandomFlicker,
AuraEffect::default_with_mode(AuraMode::RandomFlicker),
),
(
AuraMode::DoubleFade,
AuraEffect::default_with_mode(AuraMode::DoubleFade),
),
]),
}
}
}
impl StdConfig for ScsiConfig {
fn new() -> Self {
Self::default()
}
fn file_name(&self) -> String {
CONFIG_FILE.to_owned()
}
fn config_dir() -> std::path::PathBuf {
std::path::PathBuf::from(crate::CONFIG_PATH_BASE)
}
}
impl StdConfigLoad for ScsiConfig {}

View File

@@ -0,0 +1,45 @@
use std::sync::Arc;
use config::ScsiConfig;
use rog_scsi::{AuraEffect, Device, Task};
use tokio::sync::{Mutex, MutexGuard};
use crate::error::RogError;
pub mod config;
pub mod trait_impls;
#[derive(Clone)]
pub struct ScsiAura {
device: Arc<Mutex<Device>>,
config: Arc<Mutex<ScsiConfig>>,
}
impl ScsiAura {
pub fn new(device: Arc<Mutex<Device>>, config: Arc<Mutex<ScsiConfig>>) -> Self {
Self { device, config }
}
pub async fn lock_config(&self) -> MutexGuard<'_, ScsiConfig> {
self.config.lock().await
}
pub async fn write_effect(&self, effect: &AuraEffect) -> Result<(), RogError> {
let tasks: Vec<Task> = effect.into();
for task in &tasks {
self.device.lock().await.perform(task).ok();
}
Ok(())
}
/// Initialise the device if required. Locks the internal config so be wary
/// of deadlocks.
pub async fn do_initialization(&self) -> Result<(), RogError> {
let config = self.config.lock().await;
let mode = config.current_mode;
if let Some(effect) = config.modes.get(&mode) {
self.write_effect(effect).await?;
}
Ok(())
}
}

View File

@@ -0,0 +1,116 @@
use std::collections::BTreeMap;
use config_traits::StdConfig;
use log::error;
use rog_aura::AuraDeviceType;
use rog_scsi::{AuraEffect, AuraMode};
use zbus::fdo::Error as ZbErr;
use zbus::zvariant::OwnedObjectPath;
use zbus::{interface, Connection};
use super::ScsiAura;
use crate::error::RogError;
#[derive(Clone)]
pub struct ScsiZbus(ScsiAura);
impl ScsiZbus {
pub fn new(scsi: ScsiAura) -> Self {
Self(scsi)
}
pub async fn start_tasks(
self,
connection: &Connection,
path: OwnedObjectPath,
) -> Result<(), RogError> {
connection
.object_server()
.at(path.clone(), self)
.await
.map_err(|e| error!("Couldn't add server at path: {path}, {e:?}"))
.ok();
Ok(())
}
}
#[interface(name = "xyz.ljones.ScsiAura")]
impl ScsiZbus {
/// Return the device type for this Aura keyboard
#[zbus(property)]
async fn device_type(&self) -> AuraDeviceType {
self.0.config.lock().await.dev_type
}
/// Get enabled or not
#[zbus(property)]
async fn enabled(&self) -> bool {
let lock = self.0.lock_config().await;
lock.enabled
}
/// Set enabled true or false
#[zbus(property)]
async fn set_enabled(&self, enabled: bool) {
let mut config = self.0.lock_config().await;
config.enabled = enabled;
config.write();
}
#[zbus(property)]
async fn led_mode(&self) -> u8 {
let config = self.0.lock_config().await;
config.current_mode as u8
}
#[zbus(property)]
async fn set_led_mode(&self, mode: AuraMode) -> Result<(), zbus::Error> {
let mut config = self.0.lock_config().await;
if let Some(effect) = config.get_effect(mode) {
self.0
.write_effect(effect)
.await
.map_err(|e| zbus::Error::Failure(format!("{e:?}")))?;
} else {
return Err(zbus::Error::Failure("Mode data does not exist".to_string()));
}
config.current_mode = mode;
config.write();
Ok(())
}
/// The current mode data
#[zbus(property)]
async fn led_mode_data(&self) -> Result<AuraEffect, ZbErr> {
// entirely possible to deadlock here, so use try instead of lock()
if let Ok(config) = self.0.config.try_lock() {
let mode = config.current_mode;
match config.modes.get(&mode) {
Some(effect) => Ok(effect.clone()),
None => Err(ZbErr::Failed("Could not get the current effect".into())),
}
} else {
Err(ZbErr::Failed("Aura control couldn't lock self".to_string()))
}
}
/// Set an Aura effect if the effect mode or zone is supported.
///
/// On success the aura config file is read to refresh cached values, then
/// the effect is stored and config written to disk.
#[zbus(property)]
async fn set_led_mode_data(&mut self, effect: AuraEffect) -> Result<(), ZbErr> {
self.0.write_effect(&effect).await?;
let mut config = self.0.config.lock().await;
config.save_effect(effect);
config.write();
Ok(())
}
/// Get the data set for every mode available
async fn all_mode_data(&self) -> BTreeMap<AuraMode, AuraEffect> {
let config = self.0.config.lock().await;
config.modes.clone()
}
}

View File

@@ -0,0 +1,66 @@
use config_traits::{StdConfig, StdConfigLoad};
use rog_slash::{DeviceState, SlashMode, SlashType};
use serde::{Deserialize, Serialize};
const CONFIG_FILE: &str = "slash.ron";
/// Config for base system actions for the anime display
#[derive(Deserialize, Serialize, Debug)]
pub struct SlashConfig {
#[serde(skip)]
pub slash_type: SlashType,
pub enabled: bool,
pub brightness: u8,
pub display_interval: u8,
pub display_mode: SlashMode,
pub show_on_boot: bool,
pub show_on_shutdown: bool,
pub show_on_sleep: bool,
pub show_on_battery: bool,
pub show_battery_warning: bool,
pub show_on_lid_closed: bool,
}
impl Default for SlashConfig {
fn default() -> Self {
SlashConfig {
enabled: true,
brightness: 255,
display_interval: 0,
display_mode: SlashMode::Bounce,
slash_type: SlashType::Unsupported,
show_on_boot: true,
show_on_shutdown: true,
show_on_sleep: true,
show_on_battery: true,
show_battery_warning: true,
show_on_lid_closed: true,
}
}
}
impl StdConfig for SlashConfig {
fn new() -> Self {
Self::default()
}
fn file_name(&self) -> String {
CONFIG_FILE.to_owned()
}
fn config_dir() -> std::path::PathBuf {
std::path::PathBuf::from(crate::CONFIG_PATH_BASE)
}
}
impl StdConfigLoad for SlashConfig {}
impl From<&SlashConfig> for DeviceState {
fn from(config: &SlashConfig) -> Self {
DeviceState {
slash_enabled: config.enabled,
slash_brightness: config.brightness,
slash_interval: config.display_interval,
slash_mode: config.display_mode,
}
}
}

View File

@@ -0,0 +1,69 @@
use std::sync::Arc;
use config::SlashConfig;
use rog_platform::hid_raw::HidRaw;
use rog_platform::usb_raw::USBRaw;
use rog_slash::usb::{slash_pkt_enable, slash_pkt_init, slash_pkt_options, slash_pkt_set_mode};
use tokio::sync::{Mutex, MutexGuard};
use crate::error::RogError;
pub mod config;
pub mod trait_impls;
#[derive(Debug, Clone)]
pub struct Slash {
hid: Option<Arc<Mutex<HidRaw>>>,
usb: Option<Arc<Mutex<USBRaw>>>,
config: Arc<Mutex<SlashConfig>>,
}
impl Slash {
pub fn new(
hid: Option<Arc<Mutex<HidRaw>>>,
usb: Option<Arc<Mutex<USBRaw>>>,
config: Arc<Mutex<SlashConfig>>,
) -> Self {
Self { hid, usb, config }
}
pub async fn lock_config(&self) -> MutexGuard<'_, SlashConfig> {
self.config.lock().await
}
pub async fn write_bytes(&self, message: &[u8]) -> Result<(), RogError> {
if let Some(hid) = &self.hid {
hid.lock().await.write_bytes(message)?;
} else if let Some(usb) = &self.usb {
usb.lock().await.write_bytes(message)?;
}
Ok(())
}
/// Initialise the device if required. Locks the internal config so be wary
/// of deadlocks.
pub async fn do_initialization(&self) -> Result<(), RogError> {
// Don't try to initialise these models as the asus drivers already did
let config = self.config.lock().await;
for pkt in &slash_pkt_init(config.slash_type) {
self.write_bytes(pkt).await?;
}
self.write_bytes(&slash_pkt_enable(config.slash_type, config.enabled))
.await?;
// Apply config upon initialization
let option_packets = slash_pkt_options(
config.slash_type,
config.enabled,
config.brightness,
config.display_interval,
);
self.write_bytes(&option_packets).await?;
let mode_packets = slash_pkt_set_mode(config.slash_type, config.display_mode);
// self.node.write_bytes(&mode_packets[0])?;
self.write_bytes(&mode_packets[1]).await?;
Ok(())
}
}

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