Compare commits

...

90 Commits

Author SHA1 Message Date
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
121 changed files with 6036 additions and 3240 deletions
+12
View File
@@ -0,0 +1,12 @@
#!/bin/sh
set -e
echo '+cargo +nightly fmt --all -- --check'
cargo +nightly fmt --all -- --check
echo '+cargo clippy --all -- -D warnings'
cargo clippy --all -- -D warnings
echo '+cargo test --all'
cargo test --all
echo '+cargo cranky'
cargo cranky
+10
View File
@@ -0,0 +1,10 @@
#!/bin/sh
set -e
echo '+cargo +nightly fmt --all -- --check'
cargo +nightly fmt --all -- --check
echo '+cargo clippy --all -- -D warnings'
cargo clippy --all -- -D warnings
echo '+cargo cranky'
cargo cranky
+32 -11
View File
@@ -1,15 +1,15 @@
image: rust:latest
cache:
key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
paths:
.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
- target/debug/df_storyteller
# Release
- target/release/build/
- target/release/deps/
@@ -17,17 +17,19 @@ cache:
- target/release/.cargo-lock
before_script:
- apt-get update -qq && apt-get install -y -qq libudev-dev libgtk-3-dev grep llvm clang libclang-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:
- format
- check
- test
- release
- format
- check
- test
- release
- deploy
format:
except:
- tags
<<: *rust_cache
script:
- echo "nightly" > rust-toolchain
- rustup component add rustfmt
@@ -36,6 +38,7 @@ format:
check:
except:
- tags
<<: *rust_cache
script:
- rustup component add clippy
- cargo check
@@ -46,18 +49,36 @@ check:
test:
except:
- tags
<<: *rust_cache
script:
- cargo test
- mkdir -p .git/hooks > /dev/null
- cargo test --all
release:
only:
- tags
<<: *rust_cache
script:
- make && make vendor
artifacts:
paths:
- vendor_asusctl_*.tar.xz
- vendor_asusctl*.tar.xz
- cargo-config
pages:
stage: deploy
only:
- tags
<<: *rust_cache
script:
- cargo doc --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
+60 -2
View File
@@ -5,8 +5,64 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [v4.7.0-RC1]
### Added
- Support for FX507Z LED modes
- Support for GL503V LED modes
- Support for G733C LED modes
- Support for GV601VI LED modes
- Support for G634J LED modes (layout is in progress)
- Support the Rear Glow on some laptops
- Support M16 matrix display
- Custom images
- Pixel gifs
- Power options
- Builtin animations
- In-progress simulators for GA402, GU604 animatrix, optional build and takes a single arg
- Add `model_override` option to anime config, this is handy for forcing a model for "Unknown" anime, and for simulators
- Add `mini_led_mode` support to asusd and zbus crates (requires kernel patch https://lkml.org/lkml/2023/6/19/1264)
- Add `mini_led_mode` toggle to rog-control-center GUI, tray, notifications
### Changed
- Move FX506HC to FX506H in arua DB to catch full series of this range
- Move FX506LH to FX506L in arua DB to catch full series of this range
- Move G513I* to G513I in arua DB to catch full series of this range
- Remove notification handle tracking limit, fixes KDE issue with profile notif
- Rename daemon and daemon-user crates to asusd and asusd-user to not be confusing in workspace naming
- Prevent the multiple notifications from a profile change from occuring (too many functions with side effects!)
- Apply keyboard brightness when setting a mode
- Update GL503 led config
### BREAKING
- All Anime related DBUS methods/notifs are changed
## [v4.6.2]
- Fix rog-control-center not reopening if `startup_in_background` is set
## [v4.6.1]
### Added
- Support for G733Z LED modes
- Support for GU604V LED modes
- Support for GX650P LED modes
- Support for GV604I LED modes
- Support for FX516P LED modes (this laptop still has further issues, will require a patched kernel when patch is ready)
- Add device code for the Z13 ACRNM keyboard (requires kernel patch, in progress)
- Support for GV301VIC LED modes
- Add device code for the plain Z13 keyboard (requires kernel patch, in progress)
- Support for GV301V LED modes
### Changed
- Adjustments to Anime system events thread
- Add "sleep" animetion config options to anime config
- rog-control-center dark/light mode persistency
- Adjustments to keyboard detection
- Better support of using supergfxctl when available (tray icon and menu)
- Check supergfx version before enabling use in tray (require 5.1.0+)
- Update allowed Aura modes on asusd restart if changed
- Set tray icon for dgpu to "On" if in Vfio mode to prevent confusion
- Add support for Logout/Reboot in notification for KDE
## [v4.6.0]
### Added
- Support for GL703GE keyboard layout
- Support for G533Z modes and keyboard layout
### Changed
- Better handling of `/etc/asusd` not existing
- Better handling of non-existant config files
@@ -20,6 +76,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- ROGCC: Add CLI opt for viewing all layout files + filenames to help find a layout matching your laptop
+ Both of these options would hopefully be temporary and replaced with a "wizard" GUI helper
- Fix profile controller not detecting if platform_profile is changed
- Fix remove the leftover initial config writes on `new()` for some controllers to prevent resetting settings on startup
+ refactor the loading of systemd curve defaults and config file
### BREAKING
- Rename aura dbus method from `per_key_raw` to `direct_addressing_raw` and add doc comment
- Changes to aura.conf:
@@ -39,7 +97,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [v4.5.7]
### Changed
- ROGCC: Don't notify user if changing to same mux mode
-
-
## [v4.5.7]
### Changed
@@ -604,4 +662,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fix small deadlock with awaits
## [1.0.0]
## [1.0.0]
Generated
+1008 -1047
View File
File diff suppressed because it is too large Load Diff
+11 -3
View File
@@ -1,8 +1,9 @@
[workspace]
members = ["asusctl", "config-traits", "daemon", "daemon-user", "rog-platform", "rog-dbus", "rog-anime", "rog-aura", "rog-profiles", "rog-control-center"]
members = ["asusctl", "asusd", "asusd-user", "config-traits", "rog-platform", "rog-dbus", "rog-anime", "rog-aura", "rog-profiles", "rog-control-center", "simulators"]
default-members = ["asusctl", "asusd", "asusd-user", "rog-control-center"]
[workspace.package]
version = "4.6.0-rc1"
version = "4.7.0-RC1"
[workspace.dependencies]
async-trait = "^0.1"
@@ -11,7 +12,7 @@ concat-idents = "^1.1"
dirs = "^4.0"
smol = "^1.3"
zbus = "^3.6"
zbus = "~3.13.1"
logind-zbus = { version = "^3.1.0" } #, default-features = false, features = ["non_blocking"] }
serde = "^1.0"
@@ -35,6 +36,8 @@ pix = "^0.13"
tinybmp = "^0.4.0"
gif = "^0.12.0"
versions = "4.1"
notify-rust = { git = "https://github.com/flukejones/notify-rust.git", default-features = false, features = ["z"] }
[profile.release]
@@ -52,3 +55,8 @@ opt-level = 1
[profile.bench]
debug = false
opt-level = 3
[workspace.dependencies.cargo-husky]
version = "1"
default-features = false
features = ["user-hooks"]
+1 -1
View File
@@ -1,7 +1,7 @@
# https://github.com/ericseppanen/cargo-cranky
# cargo install cargo-cranky && cargo cranky
warn = [
error = [
"clippy::all",
"clippy::await_holding_lock",
"clippy::bool_to_int_with_if",
+22 -10
View File
@@ -19,10 +19,15 @@ LEDCFG := aura_support.ron
SRC := Cargo.toml Cargo.lock Makefile $(shell find -type f -wholename '**/src/*.rs')
STRIP_BINARIES ?= 0
DEBUG ?= 0
ifeq ($(DEBUG),0)
ARGS += --release
TARGET = release
else
ARGS += --profile dev
TARGET = debug
endif
VENDORED ?= 0
@@ -38,16 +43,18 @@ clean:
distclean:
rm -rf .cargo vendor vendor.tar.xz
install:
$(INSTALL_PROGRAM) "./target/release/$(BIN_ROG)" "$(DESTDIR)$(bindir)/$(BIN_ROG)"
install-program:
$(INSTALL_PROGRAM) "./target/$(TARGET)/$(BIN_ROG)" "$(DESTDIR)$(bindir)/$(BIN_ROG)"
$(INSTALL_PROGRAM) "./target/$(TARGET)/$(BIN_C)" "$(DESTDIR)$(bindir)/$(BIN_C)"
$(INSTALL_PROGRAM) "./target/$(TARGET)/$(BIN_D)" "$(DESTDIR)$(bindir)/$(BIN_D)"
$(INSTALL_PROGRAM) "./target/$(TARGET)/$(BIN_U)" "$(DESTDIR)$(bindir)/$(BIN_U)"
install-data:
$(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)$(datarootdir)/rog-gui/layouts/{}" \;
$(INSTALL_PROGRAM) "./target/release/$(BIN_C)" "$(DESTDIR)$(bindir)/$(BIN_C)"
$(INSTALL_PROGRAM) "./target/release/$(BIN_D)" "$(DESTDIR)$(bindir)/$(BIN_D)"
$(INSTALL_PROGRAM) "./target/release/$(BIN_U)" "$(DESTDIR)$(bindir)/$(BIN_U)"
$(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"
@@ -71,6 +78,8 @@ install:
cd rog-anime/data && find "./anime" -type f -exec $(INSTALL_DATA) "{}" "$(DESTDIR)$(datarootdir)/asusd/{}" \;
install: install-program install-data
uninstall:
rm -f "$(DESTDIR)$(bindir)/$(BIN_ROG)"
rm -r "$(DESTDIR)$(datarootdir)/applications/$(BIN_ROG).desktop"
@@ -112,9 +121,12 @@ ifeq ($(VENDORED),1)
tar pxf vendor_asusctl_$(VERSION).tar.xz
endif
cargo build $(ARGS)
strip -s ./target/release/$(BIN_C)
strip -s ./target/release/$(BIN_D)
strip -s ./target/release/$(BIN_U)
strip -s ./target/release/$(BIN_ROG)
ifneq ($(STRIP_BINARIES),0)
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
+10 -6
View File
@@ -31,7 +31,7 @@ a system-level daemon should.
## Discord
[Discord server link](https://discord.gg/4ZKGd7Un5t)
[Discord server link](https://discord.gg/WTHnqabm)
## SUPPORTED LAPTOPS
@@ -81,17 +81,17 @@ Requirements are rust >= 1.57 installed from rustup.io if the distro provided ve
sudo make install
**popos (unsuported):**
sudo apt install cmake libclang-dev libudev-dev libgtk-3-dev ibclang-dev libglib2.0-dev libatkmm-1.6-dev libpangomm-1.4-dev librust-gdk-pixbuf-dev
sudo apt install cmake libclang-dev libudev-dev libgtk-3-dev libclang-dev libglib2.0-dev libatkmm-1.6-dev libpangomm-1.4-dev librust-gdk-pixbuf-dev
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env"
make
sudo make install
**fedora:**
dnf install cmake clang-devel systemd-devel glib2-devel cairo-devel atkmm-devel pangomm-devel gdk-pixbuf-devel gtk3-devel libappindicator-gtk3
dnf install cmake clang-devel systemd-devel glib2-devel cairo-devel atkmm-devel pangomm-devel gdk-pixbuf2-devel gtk3-devel libappindicator-gtk3
make
sudo make install
@@ -100,7 +100,7 @@ Requirements are rust >= 1.57 installed from rustup.io if the distro provided ve
Works with KDE Plasma (without GTK packages)
zypper in -t pattern devel_basis
zypper in rustup cmake clang-devel systemd-devel glib2-devel cairo-devel atkmm-devel pangomm-devel gdk-pixbuf-devel gtk3-devel
zypper in rustup make cmake systemd-devel clang-devel llvm-devel gdk-pixbuf-devel cairo-devel pango-devel freetype-devel gtk3-devel libexpat-devel libayatana-indicator3-7
make
sudo make install
@@ -126,6 +126,10 @@ You may also need to activate the service for debian install. If running Pop!_OS
Run `sudo make uninstall` in the source repo, and remove `/etc/asusd/`.
# Contributing
See `CONTRIBUTING.md`. Additionally, also do `cargo clean` and `cargo test` on first checkout to ensure the commit hooks are used (via `cargo-husky`).
# OTHER
## Supporting more laptops
+3 -1
View File
@@ -11,7 +11,7 @@ rog_aura = { path = "../rog-aura" }
rog_dbus = { path = "../rog-dbus" }
rog_profiles = { path = "../rog-profiles" }
rog_platform = { path = "../rog-platform" }
daemon = { path = "../daemon" }
asusd = { path = "../asusd" }
gumdrop.workspace = true
toml.workspace = true
@@ -22,3 +22,5 @@ gif.workspace = true
tinybmp.workspace = true
glam.workspace = true
rog_dbus = { path = "../rog-dbus" }
cargo-husky.workspace = true
+30 -9
View File
@@ -1,21 +1,24 @@
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 = "enable/disable the panel LEDs (does not erase last image)"
help = "set global base brightness value <Off, Low, Med, High>"
)]
pub enable: Option<bool>,
#[options(
meta = "",
help = "enable/disable system animations (boot/sleep/shutdown)"
)]
pub boot_enable: Option<bool>,
#[options(meta = "", help = "set global AniMe brightness value")]
pub brightness: Option<f32>,
pub brightness: Option<Brightness>,
#[options(meta = "", help = "set global (image) brightness value")]
pub image_brightness: Option<f32>,
#[options(help = "clear the display")]
pub clear: bool,
#[options(command)]
@@ -32,6 +35,24 @@ pub enum AnimeActions {
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 = " <GlitchConstruction, StaticEmergence>")]
pub boot: AnimBooting,
#[options(meta = "", help = "<BinaryBannerScroll, RogLogoGlitch>")]
pub awake: AnimAwake,
#[options(meta = "", help = "<BannerSwipe, Starfield>")]
pub sleep: AnimSleeping,
#[options(meta = "", help = "<GlitchOut, SeeYa>")]
pub shutdown: AnimShutdown,
#[options(meta = "", help = "set/apply the animations")]
pub set: Option<bool>,
}
#[derive(Options)]
+13 -5
View File
@@ -31,13 +31,19 @@ pub struct LedPowerCommand2 {
#[derive(Options)]
pub enum SetAuraEnabled {
/// Applies to both old and new models
#[options(help = "set <keyboard, logo, lightbar> to enabled while device is awake")]
#[options(help = "set <keyboard, logo, lightbar, rearglow> to enabled while device is awake")]
Awake(AuraEnabled),
#[options(help = "set <keyboard, logo, lightbar> to enabled while the device is booting")]
#[options(
help = "set <keyboard, logo, lightbar, rearglow> to enabled while the device is booting"
)]
Boot(AuraEnabled),
#[options(help = "set <keyboard, logo, lightbar> to animate while the device is suspended")]
#[options(
help = "set <keyboard, logo, lightbar, rearglow> to animate while the device is suspended"
)]
Sleep(AuraEnabled),
#[options(help = "set <keyboard, logo, lightbar> to animate while the device is shutdown")]
#[options(
help = "set <keyboard, logo, lightbar, rearglow> to animate while the device is shutdown"
)]
Shutdown(AuraEnabled),
}
@@ -50,7 +56,9 @@ pub struct AuraEnabled {
#[options(meta = "", help = "<true/false>")]
pub logo: Option<bool>,
#[options(meta = "", help = "<true/false>")]
pub lightbar: Option<bool>,
pub frontglow: Option<bool>,
#[options(meta = "", help = "<true/false>")]
pub rearglow: Option<bool>,
#[options(meta = "", help = "<true/false>")]
pub lid: Option<bool>,
}
+109 -96
View File
@@ -9,8 +9,8 @@ use aura_cli::{LedPowerCommand1, LedPowerCommand2};
use gumdrop::{Opt, Options};
use profiles_cli::{FanCurveCommand, ProfileCommand};
use rog_anime::usb::get_anime_type;
use rog_anime::{AnimTime, AnimeDataBuffer, AnimeDiagonal, AnimeGif, AnimeImage, Vec2};
use rog_aura::usb::{AuraDev1866, AuraDev19b6, AuraDevTuf, AuraDevice, AuraPowerDev};
use rog_anime::{AnimTime, AnimeDataBuffer, AnimeDiagonal, AnimeGif, AnimeImage, AnimeType, Vec2};
use rog_aura::usb::{AuraDevRog1, AuraDevRog2, AuraDevTuf, AuraDevice, AuraPowerDev};
use rog_aura::{self, AuraEffect};
use rog_dbus::RogDbusClientBlocking;
use rog_platform::platform::GpuMode;
@@ -36,70 +36,52 @@ fn main() {
..Default::default()
},
Err(err) => {
eprintln!("source {}", err);
std::process::exit(2);
println!("Error: {}", err);
return;
}
};
let (dbus, _) = RogDbusClientBlocking::new()
.map_err(|e| {
print_error_help(&e, None);
std::process::exit(3);
})
.unwrap();
if let Ok((dbus, _)) = RogDbusClientBlocking::new().map_err(|e| {
print_error_help(&e, None);
}) {
if let Ok(supported) = dbus
.proxies()
.supported()
.supported_functions()
.map_err(|e| {
print_error_help(&e, None);
})
{
if parsed.version {
println!("asusctl v{}", env!("CARGO_PKG_VERSION"));
println!();
print_info();
}
let supported = dbus
.proxies()
.supported()
.supported_functions()
.map_err(|e| {
print_error_help(&e, None);
std::process::exit(4);
})
.unwrap();
if parsed.version {
print_versions();
println!();
print_laptop_info();
}
if let Err(err) = do_parsed(&parsed, &supported, &dbus) {
print_error_help(&*err, Some(&supported));
if let Err(err) = do_parsed(&parsed, &supported, &dbus) {
print_error_help(&*err, Some(&supported));
}
}
}
}
fn print_error_help(err: &dyn std::error::Error, supported: Option<&SupportedFunctions>) {
check_service("asusd");
println!("\nError: {}\n", err);
print_versions();
println!();
print_laptop_info();
print_info();
if let Some(supported) = supported {
println!();
println!("Supported laptop functions:\n\n{}", supported);
}
}
fn print_versions() {
println!("App and daemon versions:");
println!(" asusctl v{}", env!("CARGO_PKG_VERSION"));
println!(" asusd v{}", daemon::VERSION);
println!("\nComponent crate versions:");
println!(" rog-anime v{}", rog_anime::VERSION);
println!(" rog-aura v{}", rog_aura::VERSION);
println!(" rog-dbus v{}", rog_dbus::VERSION);
println!(" rog-profiles v{}", rog_profiles::VERSION);
println!("rog-platform v{}", rog_platform::VERSION);
}
fn print_laptop_info() {
fn print_info() {
let dmi = sysfs_class::DmiId::default();
let board_name = dmi.board_name().expect("Could not get board_name");
let prod_family = dmi.product_family().expect("Could not get product_family");
println!("Product family: {}", prod_family.trim());
println!("Board name: {}", board_name.trim());
println!("asusctl version: {}", env!("CARGO_PKG_VERSION"));
println!(" Product family: {}", prod_family.trim());
println!(" Board name: {}", board_name.trim());
}
fn check_service(name: &str) -> bool {
@@ -158,7 +140,7 @@ fn do_parsed(
{
return false;
}
if supported.keyboard_led.dev_id != AuraDevice::X19B6
if supported.keyboard_led.dev_id != AuraDevice::X19b6
&& command.trim().starts_with("led-pow-2")
{
return false;
@@ -224,9 +206,11 @@ fn handle_anime(
cmd: &AnimeCommand,
) -> Result<(), Box<dyn std::error::Error>> {
if (cmd.command.is_none()
&& cmd.enable.is_none()
&& cmd.boot_enable.is_none()
&& cmd.brightness.is_none())
&& cmd.enable_display.is_none()
&& cmd.enable_powersave_anim.is_none()
&& cmd.brightness.is_none()
&& cmd.image_brightness.is_none()
&& !cmd.clear)
|| cmd.help
{
println!("Missing arg or command\n\n{}", cmd.self_usage());
@@ -234,25 +218,34 @@ fn handle_anime(
println!("\n{}", lst);
}
}
if let Some(anime_turn) = cmd.enable {
dbus.proxies().anime().set_on_off(anime_turn)?;
if let Some(enable) = cmd.enable_display {
dbus.proxies().anime().set_enable_display(enable)?;
}
if let Some(anime_boot) = cmd.boot_enable {
dbus.proxies().anime().set_boot_on_off(anime_boot)?;
if let Some(enable) = cmd.enable_powersave_anim {
dbus.proxies().anime().set_builtins_enabled(enable)?;
}
if let Some(bright) = cmd.brightness {
verify_brightness(bright);
dbus.proxies().anime().set_brightness(bright)?;
}
if let Some(bright) = cmd.image_brightness {
verify_brightness(bright);
dbus.proxies().anime().set_image_brightness(bright)?;
}
let mut anime_type = get_anime_type()?;
if let AnimeType::Unknown = anime_type {
if let Some(model) = cmd.override_type {
anime_type = model;
}
}
if cmd.clear {
let anime_type = get_anime_type()?;
let data = vec![0u8; anime_type.data_length()];
let data = vec![255u8; anime_type.data_length()];
let tmp = AnimeDataBuffer::from_vec(anime_type, data)?;
dbus.proxies().anime().write(tmp)?;
}
if let Some(action) = cmd.command.as_ref() {
let anime_type = get_anime_type()?;
match action {
AnimeActions::Image(image) => {
if image.help_requested() || image.path.is_empty() {
@@ -260,7 +253,7 @@ fn handle_anime(
if let Some(lst) = image.self_command_list() {
println!("\n{}", lst);
}
std::process::exit(1);
return Ok(());
}
verify_brightness(image.bright);
@@ -283,7 +276,7 @@ fn handle_anime(
if let Some(lst) = image.self_command_list() {
println!("\n{}", lst);
}
std::process::exit(1);
return Ok(());
}
verify_brightness(image.bright);
@@ -304,7 +297,7 @@ fn handle_anime(
if let Some(lst) = gif.self_command_list() {
println!("\n{}", lst);
}
std::process::exit(1);
return Ok(());
}
verify_brightness(gif.bright);
@@ -338,7 +331,7 @@ fn handle_anime(
if let Some(lst) = gif.self_command_list() {
println!("\n{}", lst);
}
std::process::exit(1);
return Ok(());
}
verify_brightness(gif.bright);
@@ -363,6 +356,23 @@ fn handle_anime(
}
}
}
AnimeActions::SetBuiltins(builtins) => {
if builtins.help_requested() || builtins.set.is_none() {
println!("\nAny unspecified args will be set to default (first shown var)\n");
println!("\n{}", builtins.self_usage());
if let Some(lst) = builtins.self_command_list() {
println!("\n{}", lst);
}
return Ok(());
}
dbus.proxies().anime().set_builtin_animations(
builtins.boot,
builtins.awake,
builtins.sleep,
builtins.shutdown,
)?;
}
}
}
Ok(())
@@ -374,7 +384,6 @@ fn verify_brightness(brightness: f32) {
"Image and global brightness must be between 0.0 and 1.0 (inclusive), was {}",
brightness
);
std::process::exit(1);
}
}
@@ -391,7 +400,7 @@ fn handle_led_mode(
println!("Commands available");
if let Some(cmdlist) = LedModeCommand::command_list() {
let commands: Vec<String> = cmdlist.lines().map(|s| s.to_string()).collect();
let commands: Vec<String> = cmdlist.lines().map(|s| s.to_owned()).collect();
for command in commands.iter().filter(|command| {
for mode in &supported.basic_modes {
if command
@@ -474,10 +483,10 @@ fn handle_led_power_1_do_1866(
dbus: &RogDbusClientBlocking<'_>,
power: &LedPowerCommand1,
) -> Result<(), Box<dyn std::error::Error>> {
let mut enabled: Vec<AuraDev1866> = Vec::new();
let mut disabled: Vec<AuraDev1866> = Vec::new();
let mut enabled: Vec<AuraDevRog1> = Vec::new();
let mut disabled: Vec<AuraDevRog1> = Vec::new();
let mut check = |e: Option<bool>, a: AuraDev1866| {
let mut check = |e: Option<bool>, a: AuraDevRog1| {
if let Some(arg) = e {
if arg {
enabled.push(a);
@@ -487,11 +496,11 @@ fn handle_led_power_1_do_1866(
}
};
check(power.awake, AuraDev1866::Awake);
check(power.boot, AuraDev1866::Boot);
check(power.sleep, AuraDev1866::Sleep);
check(power.keyboard, AuraDev1866::Keyboard);
check(power.lightbar, AuraDev1866::Lightbar);
check(power.awake, AuraDevRog1::Awake);
check(power.boot, AuraDevRog1::Boot);
check(power.sleep, AuraDevRog1::Sleep);
check(power.keyboard, AuraDevRog1::Keyboard);
check(power.lightbar, AuraDevRog1::Lightbar);
let data = AuraPowerDev {
x1866: enabled,
@@ -578,13 +587,13 @@ fn handle_led_power2(
return Ok(());
}
if supported.dev_id != AuraDevice::X19B6 {
if supported.dev_id != AuraDevice::X19b6 {
println!("This option applies only to keyboards with product ID 0x19b6");
}
let mut enabled: Vec<AuraDev19b6> = Vec::new();
let mut disabled: Vec<AuraDev19b6> = Vec::new();
let mut check = |e: Option<bool>, a: AuraDev19b6| {
let mut enabled: Vec<AuraDevRog2> = Vec::new();
let mut disabled: Vec<AuraDevRog2> = Vec::new();
let mut check = |e: Option<bool>, a: AuraDevRog2| {
if let Some(arg) = e {
if arg {
enabled.push(a);
@@ -596,28 +605,32 @@ fn handle_led_power2(
match pow {
aura_cli::SetAuraEnabled::Boot(arg) => {
check(arg.keyboard, AuraDev19b6::BootKeyb);
check(arg.logo, AuraDev19b6::BootLogo);
check(arg.lightbar, AuraDev19b6::BootBar);
check(arg.lid, AuraDev19b6::AwakeLid);
check(arg.keyboard, AuraDevRog2::BootKeyb);
check(arg.logo, AuraDevRog2::BootLogo);
check(arg.frontglow, AuraDevRog2::BootBar);
check(arg.rearglow, AuraDevRog2::BootRearGlow);
check(arg.lid, AuraDevRog2::AwakeLid);
}
aura_cli::SetAuraEnabled::Sleep(arg) => {
check(arg.keyboard, AuraDev19b6::SleepKeyb);
check(arg.logo, AuraDev19b6::SleepLogo);
check(arg.lightbar, AuraDev19b6::SleepBar);
check(arg.lid, AuraDev19b6::SleepLid);
check(arg.keyboard, AuraDevRog2::SleepKeyb);
check(arg.logo, AuraDevRog2::SleepLogo);
check(arg.frontglow, AuraDevRog2::SleepBar);
check(arg.rearglow, AuraDevRog2::SleepRearGlow);
check(arg.lid, AuraDevRog2::SleepLid);
}
aura_cli::SetAuraEnabled::Awake(arg) => {
check(arg.keyboard, AuraDev19b6::AwakeKeyb);
check(arg.logo, AuraDev19b6::AwakeLogo);
check(arg.lightbar, AuraDev19b6::AwakeBar);
check(arg.lid, AuraDev19b6::AwakeLid);
check(arg.keyboard, AuraDevRog2::AwakeKeyb);
check(arg.logo, AuraDevRog2::AwakeLogo);
check(arg.frontglow, AuraDevRog2::AwakeBar);
check(arg.rearglow, AuraDevRog2::AwakeRearGlow);
check(arg.lid, AuraDevRog2::AwakeLid);
}
aura_cli::SetAuraEnabled::Shutdown(arg) => {
check(arg.keyboard, AuraDev19b6::ShutdownKeyb);
check(arg.logo, AuraDev19b6::ShutdownLogo);
check(arg.lightbar, AuraDev19b6::ShutdownBar);
check(arg.lid, AuraDev19b6::ShutdownBar);
check(arg.keyboard, AuraDevRog2::ShutdownKeyb);
check(arg.logo, AuraDevRog2::ShutdownLogo);
check(arg.frontglow, AuraDevRog2::ShutdownBar);
check(arg.rearglow, AuraDevRog2::ShutdownRearGlow);
check(arg.lid, AuraDevRog2::ShutdownLid);
}
}
@@ -662,7 +675,7 @@ fn handle_profile(
if let Some(lst) = cmd.self_command_list() {
println!("\n{}", lst);
}
std::process::exit(1);
return Ok(());
}
if cmd.next {
@@ -706,14 +719,14 @@ fn handle_fan_curve(
if let Some(lst) = cmd.self_command_list() {
println!("\n{}", lst);
}
std::process::exit(1);
return Ok(());
}
if (cmd.enabled.is_some() || cmd.fan.is_some() || cmd.data.is_some())
&& cmd.mod_profile.is_none()
{
println!("--enabled, --fan, and --data options require --mod-profile");
std::process::exit(666);
return Ok(());
}
if cmd.get_enabled {
@@ -1,15 +1,11 @@
[package]
name = "daemon-user"
name = "asusd-user"
license = "MPL-2.0"
version.workspace = true
authors = ["Luke D Jones <luke@ljones.dev>"]
edition = "2021"
description = "Usermode daemon for user settings, anime, per-key lighting"
[lib]
name = "rog_user"
path = "src/lib.rs"
[[bin]]
name = "asusd-user"
path = "src/daemon.rs"
@@ -33,4 +29,7 @@ zbus.workspace = true
# cli and logging
log.workspace = true
env_logger.workspace = true
env_logger.workspace = true
[dev-dependencies]
cargo-husky.workspace = true
@@ -360,13 +360,13 @@ impl CtrlAnime<'static> {
pub fn set_state(&mut self, on: bool) -> zbus::fdo::Result<()> {
// Operations here need to be in specific order
if on {
self.client.proxies().anime().set_on_off(on).ok();
self.client.proxies().anime().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.proxies().anime().set_on_off(on).ok();
self.client.proxies().anime().set_enable_display(on).ok();
}
Ok(())
}
@@ -1,17 +1,16 @@
use std::fs::OpenOptions;
use std::io::{Read, Write};
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 asusd_user::DBUS_NAME;
use config_traits::{StdConfig, StdConfigLoad};
use rog_anime::usb::get_anime_type;
use rog_aura::aura_detection::LaptopLedData;
use rog_aura::layouts::KeyLayout;
use rog_dbus::RogDbusClientBlocking;
use rog_user::config::*;
use rog_user::ctrl_anime::{CtrlAnime, CtrlAnimeInner};
use rog_user::DBUS_NAME;
use smol::Executor;
use zbus::Connection;
@@ -29,7 +28,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
.format(|buf, record| writeln!(buf, "{}: {}", record.level(), record.args()))
.init();
println!(" user daemon v{}", rog_user::VERSION);
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);
@@ -78,17 +77,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
// 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();
// Find and load a matching layout for laptop
let mut file = OpenOptions::new()
.read(true)
.open(PathBuf::from(BOARD_NAME))
.map_err(|e| {
println!("{BOARD_NAME}, {e}");
e
})?;
let mut board_name = String::new();
file.read_to_string(&mut board_name)?;
// let baord_name = std::fs::read_to_string(BOARD_NAME)?;
let led_support = LaptopLedData::get_data();
@@ -1,6 +1,6 @@
//! # DBus interface proxy for: `org.asuslinux.Daemon`
//! # `DBus` interface proxy for: `org.asuslinux.Daemon`
//!
//! This code was generated by `zbus-xmlgen` `1.0.0` from DBus introspection
//! This code was generated by `zbus-xmlgen` `1.0.0` from `DBus` introspection
//! data. Source: `Interface '/org/asuslinux/Anime' from service
//! 'org.asuslinux.Daemon' on session bus`.
//!
@@ -10,8 +10,8 @@
//! [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),
//! 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`]
+5 -6
View File
@@ -1,5 +1,5 @@
[package]
name = "daemon"
name = "asusd"
license = "MPL-2.0"
version.workspace = true
readme = "README.md"
@@ -9,10 +9,6 @@ homepage = "https://gitlab.com/asus-linux/asus-nb-ctrl"
description = "A daemon app for ASUS GX502 and similar laptops to control missing features"
edition = "2021"
[lib]
name = "daemon"
path = "src/lib.rs"
[[bin]]
name = "asusd"
path = "src/daemon.rs"
@@ -44,4 +40,7 @@ sysfs-class.workspace = true # used for backlight control and baord ID
concat-idents.workspace = true
systemd-zbus = "*"
systemd-zbus = "*"
[dev-dependencies]
cargo-husky.workspace = true
+15 -9
View File
@@ -3,11 +3,12 @@ use serde_derive::{Deserialize, Serialize};
const CONFIG_FILE: &str = "asusd.ron";
#[derive(Deserialize, Serialize, Default)]
#[derive(Deserialize, Serialize, Default, Debug)]
pub struct Config {
/// Save charge limit for restoring on boot
pub bat_charge_limit: u8,
pub panel_od: bool,
pub mini_led_mode: bool,
pub disable_nvidia_powerd_on_battery: bool,
pub ac_command: String,
pub bat_command: String,
@@ -18,6 +19,7 @@ impl StdConfig for Config {
Config {
bat_charge_limit: 100,
panel_od: false,
mini_led_mode: false,
disable_nvidia_powerd_on_battery: true,
ac_command: String::new(),
bat_command: String::new(),
@@ -29,25 +31,28 @@ impl StdConfig for Config {
}
fn file_name(&self) -> String {
CONFIG_FILE.to_string()
CONFIG_FILE.to_owned()
}
}
impl StdConfigLoad2<Config455, Config458> for Config {}
impl StdConfigLoad2<Config458, Config462> for Config {}
#[derive(Deserialize, Serialize, Default)]
#[serde(default)]
pub struct Config455 {
#[derive(Deserialize, Serialize)]
pub struct Config462 {
/// Save charge limit for restoring on boot
pub bat_charge_limit: u8,
pub panel_od: bool,
pub disable_nvidia_powerd_on_battery: bool,
pub ac_command: String,
pub bat_command: String,
}
impl From<Config455> for Config {
fn from(c: Config455) -> Self {
impl From<Config462> for Config {
fn from(c: Config462) -> Self {
Self {
bat_charge_limit: c.bat_charge_limit,
panel_od: c.panel_od,
mini_led_mode: false,
disable_nvidia_powerd_on_battery: true,
ac_command: String::new(),
bat_command: String::new(),
@@ -55,7 +60,7 @@ impl From<Config455> for Config {
}
}
#[derive(Deserialize, Serialize, Default)]
#[derive(Deserialize, Serialize)]
pub struct Config458 {
/// Save charge limit for restoring on boot
pub bat_charge_limit: u8,
@@ -69,6 +74,7 @@ impl From<Config458> for Config {
Self {
bat_charge_limit: c.bat_charge_limit,
panel_od: c.panel_od,
mini_led_mode: false,
disable_nvidia_powerd_on_battery: true,
ac_command: c.ac_command,
bat_command: c.bat_command,
@@ -2,68 +2,56 @@ use std::time::Duration;
use config_traits::{StdConfig, StdConfigLoad2};
use rog_anime::error::AnimeError;
use rog_anime::{ActionData, ActionLoader, AnimTime, AnimeType, Fade, Vec2};
use rog_anime::usb::Brightness;
use rog_anime::{ActionData, ActionLoader, AnimTime, Animations, AnimeType, Fade, Vec2};
use serde_derive::{Deserialize, Serialize};
const CONFIG_FILE: &str = "anime.ron";
#[derive(Deserialize, Serialize)]
pub struct AnimeConfigV341 {
pub system: Option<ActionLoader>,
pub boot: Option<ActionLoader>,
pub suspend: Option<ActionLoader>,
pub shutdown: Option<ActionLoader>,
}
impl From<AnimeConfigV341> for AnimeConfig {
fn from(c: AnimeConfigV341) -> AnimeConfig {
AnimeConfig {
system: if let Some(ani) = c.system {
vec![ani]
} else {
vec![]
},
boot: if let Some(ani) = c.boot {
vec![ani]
} else {
vec![]
},
wake: if let Some(ani) = c.suspend {
vec![ani]
} else {
vec![]
},
shutdown: if let Some(ani) = c.shutdown {
vec![ani]
} else {
vec![]
},
brightness: 1.0,
awake_enabled: true,
boot_anim_enabled: true,
}
}
}
#[derive(Deserialize, Serialize)]
pub struct AnimeConfigV352 {
pub struct AnimeConfigV460 {
pub system: Vec<ActionLoader>,
pub boot: Vec<ActionLoader>,
pub wake: Vec<ActionLoader>,
pub sleep: Vec<ActionLoader>,
pub shutdown: Vec<ActionLoader>,
pub brightness: f32,
}
impl From<AnimeConfigV352> for AnimeConfig {
fn from(c: AnimeConfigV352) -> AnimeConfig {
impl From<AnimeConfigV460> for AnimeConfig {
fn from(c: AnimeConfigV460) -> AnimeConfig {
AnimeConfig {
system: c.system,
boot: c.boot,
wake: c.wake,
sleep: c.sleep,
shutdown: c.shutdown,
brightness: 1.0,
awake_enabled: true,
boot_anim_enabled: true,
..Default::default()
}
}
}
#[derive(Deserialize, Serialize, Debug)]
pub struct AnimeConfigV5 {
pub system: Vec<ActionLoader>,
pub boot: Vec<ActionLoader>,
pub wake: Vec<ActionLoader>,
pub sleep: Vec<ActionLoader>,
pub shutdown: Vec<ActionLoader>,
pub brightness: f32,
pub awake_enabled: bool,
pub boot_anim_enabled: bool,
}
impl From<AnimeConfigV5> for AnimeConfig {
fn from(c: AnimeConfigV5) -> AnimeConfig {
AnimeConfig {
system: c.system,
boot: c.boot,
wake: c.wake,
sleep: c.sleep,
shutdown: c.shutdown,
..Default::default()
}
}
}
@@ -73,6 +61,7 @@ pub struct AnimeConfigCached {
pub system: Vec<ActionData>,
pub boot: Vec<ActionData>,
pub wake: Vec<ActionData>,
pub sleep: Vec<ActionData>,
pub shutdown: Vec<ActionData>,
}
@@ -100,6 +89,12 @@ impl AnimeConfigCached {
}
self.wake = wake;
let mut sleep = Vec::with_capacity(config.sleep.len());
for ani in &config.sleep {
sleep.push(ActionData::from_anime_action(anime_type, ani)?);
}
self.sleep = sleep;
let mut shutdown = Vec::with_capacity(config.shutdown.len());
for ani in &config.shutdown {
shutdown.push(ActionData::from_anime_action(anime_type, ani)?);
@@ -110,27 +105,35 @@ impl AnimeConfigCached {
}
/// Config for base system actions for the anime display
#[derive(Deserialize, Serialize)]
#[derive(Deserialize, Serialize, Debug)]
pub struct AnimeConfig {
pub model_override: Option<AnimeType>,
pub system: Vec<ActionLoader>,
pub boot: Vec<ActionLoader>,
pub wake: Vec<ActionLoader>,
pub sleep: Vec<ActionLoader>,
pub shutdown: Vec<ActionLoader>,
pub brightness: f32,
pub awake_enabled: bool,
pub boot_anim_enabled: bool,
pub display_enabled: bool,
pub display_brightness: Brightness,
pub builtin_anims_enabled: bool,
pub builtin_anims: Animations,
}
impl Default for AnimeConfig {
fn default() -> Self {
AnimeConfig {
model_override: None,
system: Vec::new(),
boot: Vec::new(),
wake: Vec::new(),
sleep: Vec::new(),
shutdown: Vec::new(),
brightness: 1.0,
awake_enabled: true,
boot_anim_enabled: true,
display_enabled: true,
display_brightness: Brightness::Med,
builtin_anims_enabled: true,
builtin_anims: Animations::default(),
}
}
}
@@ -145,11 +148,11 @@ impl StdConfig for AnimeConfig {
}
fn file_name(&self) -> String {
CONFIG_FILE.to_string()
CONFIG_FILE.to_owned()
}
}
impl StdConfigLoad2<AnimeConfigV341, AnimeConfigV352> for AnimeConfig {}
impl StdConfigLoad2<AnimeConfigV460, AnimeConfigV5> for AnimeConfig {}
impl AnimeConfig {
// fn clamp_config_brightness(mut config: &mut AnimeConfig) {
@@ -164,7 +167,7 @@ impl AnimeConfig {
fn create_default() -> Self {
// create a default config here
let config = AnimeConfig {
AnimeConfig {
system: vec![],
boot: vec![ActionLoader::ImageAnimation {
file: "/usr/share/asusd/anime/custom/sonic-run.gif".into(),
@@ -190,6 +193,14 @@ impl AnimeConfig {
Duration::from_secs(2),
)),
}],
sleep: vec![ActionLoader::ImageAnimation {
file: "/usr/share/asusd/anime/custom/sonic-wait.gif".into(),
scale: 0.9,
angle: 0.0,
translation: Vec2::new(3.0, 2.0),
brightness: 1.0,
time: AnimTime::Infinite,
}],
shutdown: vec![ActionLoader::ImageAnimation {
file: "/usr/share/asusd/anime/custom/sonic-wait.gif".into(),
scale: 0.9,
@@ -199,10 +210,7 @@ impl AnimeConfig {
time: AnimTime::Infinite,
}],
brightness: 1.0,
awake_enabled: true,
boot_anim_enabled: true,
};
config.write();
config
..Default::default()
}
}
}
@@ -3,7 +3,6 @@ pub mod config;
pub mod trait_impls;
use std::convert::TryFrom;
use std::error::Error;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::thread::sleep;
@@ -11,7 +10,7 @@ use std::thread::sleep;
use ::zbus::export::futures_util::lock::Mutex;
use log::{error, info, warn};
use rog_anime::error::AnimeError;
use rog_anime::usb::{get_anime_type, pkt_for_flush, pkts_for_init};
use rog_anime::usb::{get_anime_type, pkt_flush, pkt_set_enable_powersave_anim, pkts_for_init};
use rog_anime::{ActionData, AnimeDataBuffer, AnimePacketType, AnimeType};
use rog_platform::hid_raw::HidRaw;
use rog_platform::supported::AnimeSupportedFunctions;
@@ -29,8 +28,29 @@ impl GetSupported for CtrlAnime {
}
}
enum Node {
Usb(USBRaw),
Hid(HidRaw),
}
impl Node {
pub fn write_bytes(&self, message: &[u8]) -> Result<(), RogError> {
// TODO: map and pass on errors
match self {
Node::Usb(u) => {
u.write_bytes(message).ok();
}
Node::Hid(h) => {
h.write_bytes(message).ok();
}
}
Ok(())
}
}
pub struct CtrlAnime {
node: USBRaw,
// node: HidRaw,
node: Node,
anime_type: AnimeType,
cache: AnimeConfigCached,
config: AnimeConfig,
@@ -42,11 +62,27 @@ pub struct CtrlAnime {
impl CtrlAnime {
#[inline]
pub fn new(config: AnimeConfig) -> Result<CtrlAnime, Box<dyn Error>> {
let node = USBRaw::new(0x193b)?;
let anime_type = get_anime_type()?;
pub fn new(config: AnimeConfig) -> Result<CtrlAnime, RogError> {
// let node = HidRaw::new("193b")?;
let usb = USBRaw::new(0x193b).ok();
let hid = HidRaw::new("193b").ok();
let node = if usb.is_some() {
unsafe { Node::Usb(usb.unwrap_unchecked()) }
} else if hid.is_some() {
unsafe { Node::Hid(hid.unwrap_unchecked()) }
} else {
return Err(RogError::Anime(AnimeError::NoDevice));
};
info!("Device has an AniMe Matrix display");
let mut anime_type = get_anime_type()?;
if let AnimeType::Unknown = anime_type {
if let Some(model) = config.model_override {
warn!("Overriding the Animatrix type as {model:?}");
anime_type = model;
}
}
info!("Device has an AniMe Matrix display: {anime_type:?}");
let mut cache = AnimeConfigCached::default();
cache.init_from_config(&config, anime_type)?;
@@ -70,12 +106,21 @@ impl CtrlAnime {
///
/// Because this also writes to the usb device, other write tries (display
/// only) *must* get the mutex lock and set the `thread_exit` atomic.
fn run_thread(inner: Arc<Mutex<CtrlAnime>>, actions: Vec<ActionData>, mut once: bool) {
async fn run_thread(inner: Arc<Mutex<CtrlAnime>>, actions: Vec<ActionData>, mut once: bool) {
if actions.is_empty() {
warn!("AniMe system actions was empty");
return;
}
if let Some(lock) = inner.try_lock() {
lock.node
.write_bytes(&pkt_set_enable_powersave_anim(false))
.map_err(|err| {
warn!("rog_anime::run_animation:callback {}", err);
})
.ok();
}
// Loop rules:
// - Lock the mutex **only when required**. That is, the lock must be held for
// the shortest duration possible.
@@ -113,9 +158,8 @@ impl CtrlAnime {
info!("AniMe no previous system thread running (now)");
thread_exit.store(false, Ordering::SeqCst);
thread_running.store(true, Ordering::SeqCst);
'main: loop {
thread_running.store(true, Ordering::SeqCst);
for action in &actions {
if thread_exit.load(Ordering::SeqCst) {
break 'main;
@@ -124,7 +168,7 @@ impl CtrlAnime {
ActionData::Animation(frames) => {
rog_anime::run_animation(frames, &|frame| {
if thread_exit.load(Ordering::Acquire) {
info!("rog-anime: frame-loop was asked to exit");
info!("rog-anime: animation sub-loop was asked to exit");
return Ok(true); // Do safe exit
}
inner
@@ -148,6 +192,10 @@ impl CtrlAnime {
Ok,
)
});
if thread_exit.load(Ordering::Acquire) {
info!("rog-anime: sub-loop exited and main loop exiting now");
break 'main;
}
}
ActionData::Image(image) => {
once = false;
@@ -206,7 +254,7 @@ impl CtrlAnime {
for row in &data {
self.node.write_bytes(row)?;
}
self.node.write_bytes(&pkt_for_flush())?;
self.node.write_bytes(&pkt_flush())?;
Ok(())
}
+299
View File
@@ -0,0 +1,299 @@
use std::sync::atomic::Ordering;
use std::sync::Arc;
use async_trait::async_trait;
use config_traits::StdConfig;
use log::warn;
use rog_anime::usb::{
pkt_set_brightness, pkt_set_builtin_animations, pkt_set_enable_display,
pkt_set_enable_powersave_anim, AnimAwake, AnimBooting, AnimShutdown, AnimSleeping, Brightness,
};
use rog_anime::{AnimeDataBuffer, DeviceState};
use zbus::export::futures_util::lock::Mutex;
use zbus::{dbus_interface, Connection, SignalContext};
use super::CtrlAnime;
use crate::error::RogError;
pub(super) const ZBUS_PATH: &str = "/org/asuslinux/Anime";
#[derive(Clone)]
pub struct CtrlAnimeZbus(pub Arc<Mutex<CtrlAnime>>);
/// The struct with the main dbus methods requires this trait
#[async_trait]
impl crate::ZbusRun for CtrlAnimeZbus {
async fn add_to_server(self, server: &mut Connection) {
Self::add_to_server_helper(self, ZBUS_PATH, server).await;
}
}
// None of these calls can be guarnateed to succeed unless we loop until okay
// If the try_lock *does* succeed then any other thread trying to lock will not
// grab it until we finish.
#[dbus_interface(name = "org.asuslinux.Daemon")]
impl CtrlAnimeZbus {
/// Writes a data stream of length. Will force system thread to exit until
/// it is restarted
async fn write(&self, input: AnimeDataBuffer) -> zbus::fdo::Result<()> {
let lock = self.0.lock().await;
lock.thread_exit.store(true, Ordering::SeqCst);
lock.write_data_buffer(input).map_err(|err| {
warn!("rog_anime::run_animation:callback {}", err);
err
})?;
Ok(())
}
/// Set the global AniMe brightness
async fn set_image_brightness(&self, bright: f32) {
let mut lock = self.0.lock().await;
let mut bright = bright;
if bright < 0.0 {
bright = 0.0;
} else if bright > 1.0 {
bright = 1.0;
}
lock.config.brightness = bright;
lock.config.write();
}
/// Set base brightness level
// TODO: enum for brightness
async fn set_brightness(
&self,
#[zbus(signal_context)] ctxt: SignalContext<'_>,
brightness: Brightness,
) {
let mut lock = self.0.lock().await;
lock.node
.write_bytes(&pkt_set_brightness(brightness))
.map_err(|err| {
warn!("rog_anime::run_animation:callback {}", err);
})
.ok();
lock.config.display_brightness = brightness;
lock.config.write();
Self::notify_device_state(
&ctxt,
DeviceState {
display_enabled: lock.config.display_enabled,
display_brightness: lock.config.display_brightness,
builtin_anims_enabled: lock.config.builtin_anims_enabled,
builtin_anims: lock.config.builtin_anims,
},
)
.await
.ok();
}
/// Enable the builtin animations or not
async fn set_builtins_enabled(
&self,
#[zbus(signal_context)] ctxt: SignalContext<'_>,
enabled: bool,
) {
let mut lock = self.0.lock().await;
lock.node
.write_bytes(&pkt_set_enable_powersave_anim(enabled))
.map_err(|err| {
warn!("rog_anime::run_animation:callback {}", err);
})
.ok();
lock.config.builtin_anims_enabled = enabled;
lock.config.write();
if enabled {
lock.thread_exit.store(true, Ordering::Release);
}
Self::notify_device_state(
&ctxt,
DeviceState {
display_enabled: lock.config.display_enabled,
display_brightness: lock.config.display_brightness,
builtin_anims_enabled: lock.config.builtin_anims_enabled,
builtin_anims: lock.config.builtin_anims,
},
)
.await
.ok();
}
/// Set which builtin animation is used for each stage
async fn set_builtin_animations(
&self,
#[zbus(signal_context)] ctxt: SignalContext<'_>,
boot: AnimBooting,
awake: AnimAwake,
sleep: AnimSleeping,
shutdown: AnimShutdown,
) {
let mut lock = self.0.lock().await;
lock.node
.write_bytes(&pkt_set_enable_powersave_anim(true))
.map_err(|err| {
warn!("rog_anime::run_animation:callback {}", err);
})
.ok();
lock.node
.write_bytes(&pkt_set_builtin_animations(boot, awake, sleep, shutdown))
.map_err(|err| {
warn!("rog_anime::run_animation:callback {}", err);
})
.ok();
lock.config.builtin_anims.boot = boot;
lock.config.builtin_anims.sleep = sleep;
lock.config.builtin_anims.awake = awake;
lock.config.builtin_anims.shutdown = shutdown;
lock.config.write();
Self::notify_device_state(
&ctxt,
DeviceState {
display_enabled: lock.config.display_enabled,
display_brightness: lock.config.display_brightness,
builtin_anims_enabled: lock.config.builtin_anims_enabled,
builtin_anims: lock.config.builtin_anims,
},
)
.await
.ok();
}
/// Set whether the AniMe is enabled at all
async fn set_enable_display(
&self,
#[zbus(signal_context)] ctxt: SignalContext<'_>,
enabled: bool,
) {
let mut lock = self.0.lock().await;
lock.node
.write_bytes(&pkt_set_enable_display(enabled))
.map_err(|err| {
warn!("rog_anime::run_animation:callback {}", err);
})
.ok();
lock.config.display_enabled = enabled;
lock.config.write();
Self::notify_device_state(
&ctxt,
DeviceState {
display_enabled: lock.config.display_enabled,
display_brightness: lock.config.display_brightness,
builtin_anims_enabled: lock.config.builtin_anims_enabled,
builtin_anims: lock.config.builtin_anims,
},
)
.await
.ok();
}
/// 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 {
let lock = self.0.lock().await;
lock.thread_exit.store(true, Ordering::SeqCst);
CtrlAnime::run_thread(self.0.clone(), lock.cache.system.clone(), false).await;
}
}
/// Get the device state as stored by asusd
// #[dbus_interface(property)]
async fn device_state(&self) -> DeviceState {
let lock = self.0.lock().await;
DeviceState {
display_enabled: lock.config.display_enabled,
display_brightness: lock.config.display_brightness,
builtin_anims_enabled: lock.config.builtin_anims_enabled,
builtin_anims: lock.config.builtin_anims,
}
}
/// Notify listeners of the status of AniMe LED power and factory
/// system-status animations
#[dbus_interface(signal)]
async fn notify_device_state(ctxt: &SignalContext<'_>, data: DeviceState) -> zbus::Result<()>;
}
#[async_trait]
impl crate::CtrlTask for CtrlAnimeZbus {
fn zbus_path() -> &'static str {
ZBUS_PATH
}
async fn create_tasks(&self, _: SignalContext<'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 || {
// on_sleep
let inner1 = inner1.clone();
async move {
let lock = inner1.lock().await;
CtrlAnime::run_thread(inner1.clone(), lock.cache.sleep.clone(), true).await;
}
},
move || {
// on_wake
let inner2 = inner2.clone();
async move {
let lock = inner2.lock().await;
CtrlAnime::run_thread(inner2.clone(), lock.cache.wake.clone(), true).await;
}
},
move || {
// on_shutdown
let inner3 = inner3.clone();
async move {
let lock = inner3.lock().await;
CtrlAnime::run_thread(inner3.clone(), lock.cache.shutdown.clone(), true).await;
}
},
move || {
// on_boot
let inner4 = inner4.clone();
async move {
let lock = inner4.lock().await;
CtrlAnime::run_thread(inner4.clone(), lock.cache.boot.clone(), true).await;
}
},
)
.await;
Ok(())
}
}
#[async_trait]
impl crate::Reloadable for CtrlAnimeZbus {
async fn reload(&mut self) -> Result<(), RogError> {
if let Some(lock) = self.0.try_lock() {
let anim = &lock.config.builtin_anims;
lock.node
.write_bytes(&pkt_set_enable_display(lock.config.display_enabled))?;
lock.node.write_bytes(&pkt_set_enable_powersave_anim(
lock.config.builtin_anims_enabled,
))?;
lock.node.write_bytes(&pkt_set_builtin_animations(
anim.boot,
anim.awake,
anim.sleep,
anim.shutdown,
))?;
if lock.config.builtin_anims_enabled && !lock.cache.boot.is_empty() {
lock.node
.write_bytes(&pkt_set_enable_powersave_anim(false))
.ok();
}
let action = lock.cache.boot.clone();
CtrlAnime::run_thread(self.0.clone(), action, true).await;
}
Ok(())
}
}
@@ -1,11 +1,9 @@
use std::collections::{BTreeMap, HashSet};
use config_traits::{StdConfig, StdConfigLoad};
use rog_aura::aura_detection::{LaptopLedData, ASUS_KEYBOARD_DEVICES};
use rog_aura::usb::{AuraDev1866, AuraDev19b6, AuraDevTuf, AuraDevice, AuraPowerDev};
use rog_aura::aura_detection::LaptopLedData;
use rog_aura::usb::{AuraDevRog1, AuraDevRog2, AuraDevTuf, AuraDevice, AuraPowerDev};
use rog_aura::{AuraEffect, AuraModeNum, AuraZone, Direction, LedBrightness, Speed, GRADIENT};
use rog_platform::hid_raw::HidRaw;
use rog_platform::keyboard_led::KeyboardLed;
use serde_derive::{Deserialize, Serialize};
const CONFIG_FILE: &str = "aura.ron";
@@ -16,22 +14,22 @@ const CONFIG_FILE: &str = "aura.ron";
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum AuraPowerConfig {
AuraDevTuf(HashSet<AuraDevTuf>),
AuraDev1866(HashSet<AuraDev1866>),
AuraDev19b6(HashSet<AuraDev19b6>),
AuraDevRog1(HashSet<AuraDevRog1>),
AuraDevRog2(HashSet<AuraDevRog2>),
}
impl AuraPowerConfig {
/// Invalid for TUF laptops
pub fn to_bytes(control: &Self) -> [u8; 3] {
pub fn to_bytes(control: &Self) -> [u8; 4] {
match control {
AuraPowerConfig::AuraDevTuf(_) => [0, 0, 0],
AuraPowerConfig::AuraDev1866(c) => {
let c: Vec<AuraDev1866> = c.iter().copied().collect();
AuraDev1866::to_bytes(&c)
AuraPowerConfig::AuraDevTuf(_) => [0, 0, 0, 0],
AuraPowerConfig::AuraDevRog1(c) => {
let c: Vec<AuraDevRog1> = c.iter().copied().collect();
AuraDevRog1::to_bytes(&c)
}
AuraPowerConfig::AuraDev19b6(c) => {
let c: Vec<AuraDev19b6> = c.iter().copied().collect();
AuraDev19b6::to_bytes(&c)
AuraPowerConfig::AuraDevRog2(c) => {
let c: Vec<AuraDevRog2> = c.iter().copied().collect();
AuraDevRog2::to_bytes(&c)
}
}
}
@@ -47,13 +45,13 @@ impl AuraPowerConfig {
]);
}
if let Self::AuraDev1866(c) = control {
if let Self::AuraDevRog1(c) = control {
return Some([
true,
c.contains(&AuraDev1866::Boot),
c.contains(&AuraDev1866::Awake),
c.contains(&AuraDev1866::Sleep),
c.contains(&AuraDev1866::Keyboard),
c.contains(&AuraDevRog1::Boot),
c.contains(&AuraDevRog1::Awake),
c.contains(&AuraDevRog1::Sleep),
c.contains(&AuraDevRog1::Keyboard),
]);
}
@@ -70,8 +68,8 @@ impl AuraPowerConfig {
}
}
pub fn set_0x1866(&mut self, power: AuraDev1866, on: bool) {
if let Self::AuraDev1866(p) = self {
pub fn set_0x1866(&mut self, power: AuraDevRog1, on: bool) {
if let Self::AuraDevRog1(p) = self {
if on {
p.insert(power);
} else {
@@ -80,8 +78,8 @@ impl AuraPowerConfig {
}
}
pub fn set_0x19b6(&mut self, power: AuraDev19b6, on: bool) {
if let Self::AuraDev19b6(p) = self {
pub fn set_0x19b6(&mut self, power: AuraDevRog2, on: bool) {
if let Self::AuraDevRog2(p) = self {
if on {
p.insert(power);
} else {
@@ -99,12 +97,12 @@ impl From<&AuraPowerConfig> for AuraPowerDev {
x1866: vec![],
x19b6: vec![],
},
AuraPowerConfig::AuraDev1866(d) => AuraPowerDev {
AuraPowerConfig::AuraDevRog1(d) => AuraPowerDev {
tuf: vec![],
x1866: d.iter().copied().collect(),
x19b6: vec![],
},
AuraPowerConfig::AuraDev19b6(d) => AuraPowerDev {
AuraPowerConfig::AuraDevRog2(d) => AuraPowerDev {
tuf: vec![],
x1866: vec![],
x19b6: d.iter().copied().collect(),
@@ -113,7 +111,7 @@ impl From<&AuraPowerConfig> for AuraPowerDev {
}
}
#[derive(Deserialize, Serialize)]
#[derive(Deserialize, Serialize, Debug, Clone)]
// #[serde(default)]
pub struct AuraConfig {
pub brightness: LedBrightness,
@@ -124,38 +122,44 @@ pub struct AuraConfig {
pub enabled: AuraPowerConfig,
}
impl Default for AuraConfig {
fn default() -> Self {
let mut prod_id = AuraDevice::Unknown;
for prod in &ASUS_KEYBOARD_DEVICES {
if HidRaw::new(prod).is_ok() {
prod_id = AuraDevice::from(*prod);
break;
}
}
impl StdConfig for AuraConfig {
fn new() -> Self {
// Self::create_default(AuraDevice::X19b6, &LaptopLedData::get_data())
panic!("AuraConfig::new() should not be used, use AuraConfig::create_default() instead");
}
if prod_id == AuraDevice::Unknown {
if let Ok(p) = KeyboardLed::new() {
if p.has_kbd_rgb_mode() {
prod_id = AuraDevice::Tuf;
}
}
}
fn config_dir() -> std::path::PathBuf {
std::path::PathBuf::from(crate::CONFIG_PATH_BASE)
}
let enabled = if prod_id == AuraDevice::X19B6 {
AuraPowerConfig::AuraDev19b6(HashSet::from([
AuraDev19b6::BootLogo,
AuraDev19b6::BootKeyb,
AuraDev19b6::SleepLogo,
AuraDev19b6::SleepKeyb,
AuraDev19b6::AwakeLogo,
AuraDev19b6::AwakeKeyb,
AuraDev19b6::ShutdownLogo,
AuraDev19b6::ShutdownKeyb,
AuraDev19b6::BootBar,
AuraDev19b6::AwakeBar,
AuraDev19b6::SleepBar,
AuraDev19b6::ShutdownBar,
fn file_name(&self) -> String {
CONFIG_FILE.to_owned()
}
}
impl StdConfigLoad for AuraConfig {}
impl AuraConfig {
pub fn create_default(prod_id: AuraDevice, support_data: &LaptopLedData) -> Self {
// create a default config here
let enabled = if prod_id == AuraDevice::X19b6 {
AuraPowerConfig::AuraDevRog2(HashSet::from([
AuraDevRog2::BootLogo,
AuraDevRog2::BootKeyb,
AuraDevRog2::SleepLogo,
AuraDevRog2::SleepKeyb,
AuraDevRog2::AwakeLogo,
AuraDevRog2::AwakeKeyb,
AuraDevRog2::ShutdownLogo,
AuraDevRog2::ShutdownKeyb,
AuraDevRog2::BootBar,
AuraDevRog2::AwakeBar,
AuraDevRog2::SleepBar,
AuraDevRog2::ShutdownBar,
AuraDevRog2::BootRearGlow,
AuraDevRog2::AwakeRearGlow,
AuraDevRog2::SleepRearGlow,
AuraDevRog2::ShutdownRearGlow,
]))
} else if prod_id == AuraDevice::Tuf {
AuraPowerConfig::AuraDevTuf(HashSet::from([
@@ -165,46 +169,22 @@ impl Default for AuraConfig {
AuraDevTuf::Keyboard,
]))
} else {
AuraPowerConfig::AuraDev1866(HashSet::from([
AuraDev1866::Awake,
AuraDev1866::Boot,
AuraDev1866::Sleep,
AuraDev1866::Keyboard,
AuraDev1866::Lightbar,
AuraPowerConfig::AuraDevRog1(HashSet::from([
AuraDevRog1::Awake,
AuraDevRog1::Boot,
AuraDevRog1::Sleep,
AuraDevRog1::Keyboard,
AuraDevRog1::Lightbar,
]))
};
AuraConfig {
let mut config = AuraConfig {
brightness: LedBrightness::Med,
current_mode: AuraModeNum::Static,
builtins: BTreeMap::new(),
multizone: None,
multizone_on: false,
enabled,
}
}
}
impl StdConfig for AuraConfig {
fn new() -> Self {
Self::create_default(&LaptopLedData::get_data())
}
fn config_dir() -> std::path::PathBuf {
std::path::PathBuf::from(crate::CONFIG_PATH_BASE)
}
fn file_name(&self) -> String {
CONFIG_FILE.to_string()
}
}
impl StdConfigLoad for AuraConfig {}
impl AuraConfig {
fn create_default(support_data: &LaptopLedData) -> Self {
// create a default config here
let mut config = AuraConfig::default();
};
for n in &support_data.basic_modes {
config
@@ -232,7 +212,6 @@ impl AuraConfig {
}
}
}
config.write();
config
}
@@ -277,13 +256,15 @@ impl AuraConfig {
#[cfg(test)]
mod tests {
use rog_aura::aura_detection::LaptopLedData;
use rog_aura::usb::AuraDevice;
use rog_aura::{AuraEffect, AuraModeNum, AuraZone, Colour};
use super::AuraConfig;
#[test]
fn set_multizone_4key_config() {
let mut config = AuraConfig::default();
let mut config = AuraConfig::create_default(AuraDevice::X19b6, &LaptopLedData::default());
let effect = AuraEffect {
colour1: Colour(0xff, 0x00, 0xff),
@@ -329,7 +310,7 @@ mod tests {
#[test]
fn set_multizone_multimode_config() {
let mut config = AuraConfig::default();
let mut config = AuraConfig::create_default(AuraDevice::X19b6, &LaptopLedData::default());
let effect = AuraEffect {
zone: AuraZone::Key1,
@@ -1,6 +1,6 @@
use std::collections::BTreeMap;
use config_traits::StdConfig;
use config_traits::{StdConfig, StdConfigLoad};
use log::{info, warn};
use rog_aura::advanced::{LedUsbPackets, UsbPackets};
use rog_aura::aura_detection::{LaptopLedData, ASUS_KEYBOARD_DEVICES};
@@ -25,9 +25,9 @@ impl GetSupported for CtrlKbdLed {
let advanced_type = laptop.advanced_type;
let mut prod_id = AuraDevice::Unknown;
for prod in &ASUS_KEYBOARD_DEVICES {
if HidRaw::new(prod).is_ok() {
prod_id = AuraDevice::from(*prod);
for prod in ASUS_KEYBOARD_DEVICES {
if HidRaw::new(prod.into()).is_ok() {
prod_id = prod;
break;
}
}
@@ -58,7 +58,7 @@ pub enum LEDNode {
pub struct CtrlKbdLed {
// TODO: config stores the keyboard type as an AuraPower, use or update this
pub led_prod: Option<String>,
pub led_prod: AuraDevice,
pub led_node: LEDNode,
pub kd_brightness: KeyboardLed,
pub supported_modes: LaptopLedData,
@@ -68,34 +68,43 @@ pub struct CtrlKbdLed {
}
impl CtrlKbdLed {
pub fn new(supported_modes: LaptopLedData, config: AuraConfig) -> Result<Self, RogError> {
let mut led_prod = None;
let mut led_node = None;
for prod in &ASUS_KEYBOARD_DEVICES {
match HidRaw::new(prod) {
pub fn new(supported_modes: LaptopLedData) -> Result<Self, RogError> {
let mut led_prod = AuraDevice::Unknown;
let mut usb_node = None;
for prod in ASUS_KEYBOARD_DEVICES {
match HidRaw::new(prod.into()) {
Ok(node) => {
led_prod = Some((*prod).to_owned());
led_node = Some(node);
info!("Looked for keyboard controller 0x{prod}: Found");
led_prod = prod;
usb_node = Some(node);
info!(
"Looked for keyboard controller 0x{}: Found",
<&str>::from(prod)
);
break;
}
Err(err) => info!("Looked for keyboard controller 0x{prod}: {err}"),
Err(err) => info!(
"Looked for keyboard controller 0x{}: {err}",
<&str>::from(prod)
),
}
}
let rgb_led = KeyboardLed::new()?;
if led_node.is_none() && !rgb_led.has_kbd_rgb_mode() {
if usb_node.is_none() && !rgb_led.has_kbd_rgb_mode() {
let dmi = sysfs_class::DmiId::default();
if let Ok(prod_family) = dmi.product_family() {
if prod_family.contains("TUF") {
warn!("A kernel patch is in progress for TUF RGB support");
warn!(
"kbd_rgb_mode was not found in the /sys/. You require a minimum 6.1 \
kernel and a supported TUF laptop"
);
}
}
return Err(RogError::NoAuraKeyboard);
}
let led_node = if let Some(rog) = led_node {
let led_node = if let Some(rog) = usb_node {
info!("Found ROG USB keyboard");
LEDNode::Rog(rog)
} else if rgb_led.has_kbd_rgb_mode() {
@@ -105,14 +114,44 @@ impl CtrlKbdLed {
LEDNode::None
};
let mut config_init = AuraConfig::create_default(led_prod, &supported_modes);
let mut config_loaded = config_init.clone().load();
for mode in &mut config_init.builtins {
// update init values from loaded values if they exist
if let Some(loaded) = config_loaded.builtins.get(mode.0) {
*mode.1 = loaded.clone();
}
}
config_loaded.builtins = config_init.builtins;
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();
// only reuse a zone mode if the mode is supported
for mode in loaded {
if supported_modes.basic_modes.contains(&mode.mode) {
new_set.push(mode.clone());
}
}
*mode.1 = new_set;
}
}
*multizone_loaded = multizone_init;
}
let ctrl = CtrlKbdLed {
led_prod,
led_node,
led_node, // on TUF this is the same as rgb_led / kd_brightness
kd_brightness: rgb_led, // If was none then we already returned above
supported_modes,
flip_effect_write: false,
per_key_mode_active: false,
config,
config: config_loaded,
};
Ok(ctrl)
}
@@ -161,7 +200,7 @@ impl CtrlKbdLed {
}
} else if let LEDNode::Rog(hid_raw) = &self.led_node {
let bytes = AuraPowerConfig::to_bytes(&self.config.enabled);
let message = [0x5d, 0xbd, 0x01, bytes[0], bytes[1], bytes[2]];
let message = [0x5d, 0xbd, 0x01, bytes[0], bytes[1], bytes[2], bytes[3]];
hid_raw.write_bytes(&message)?;
hid_raw.write_bytes(&LED_SET)?;
@@ -186,7 +225,11 @@ impl CtrlKbdLed {
self.write_mode(&effect)?;
self.config.read(); // refresh config if successful
self.config.set_builtin(effect);
if self.config.brightness == LedBrightness::Off {
self.config.brightness = LedBrightness::Med;
}
self.config.write();
self.set_brightness(self.config.brightness)?;
Ok(())
}
@@ -194,6 +237,11 @@ impl CtrlKbdLed {
/// write the raw factory mode packets - when doing this it is expected that
/// only the first `Vec` (`effect[0]`) is valid.
pub fn write_effect_block(&mut self, effect: &UsbPackets) -> Result<(), RogError> {
if self.config.brightness == LedBrightness::Off {
self.config.brightness = LedBrightness::Med;
self.config.write();
}
let pkt_type = effect[0][1];
const PER_KEY_TYPE: u8 = 0xbc;
@@ -356,6 +404,7 @@ impl CtrlKbdLed {
#[cfg(test)]
mod tests {
use rog_aura::aura_detection::LaptopLedData;
use rog_aura::usb::AuraDevice;
use rog_aura::{AuraEffect, AuraModeNum, AuraZone, Colour};
use rog_platform::keyboard_led::KeyboardLed;
@@ -367,7 +416,7 @@ mod tests {
// #[ignore = "Must be manually run due to detection stage"]
fn check_set_mode_errors() {
// Checking to ensure set_mode errors when unsupported modes are tried
let config = AuraConfig::default();
let config = AuraConfig::create_default(AuraDevice::X19b6, &LaptopLedData::default());
let supported_modes = LaptopLedData {
board_name: String::new(),
layout_name: "ga401".to_owned(),
@@ -376,7 +425,7 @@ mod tests {
advanced_type: rog_aura::AdvancedAuraType::None,
};
let mut controller = CtrlKbdLed {
led_prod: None,
led_prod: AuraDevice::X19b6,
led_node: LEDNode::None,
kd_brightness: KeyboardLed::default(),
supported_modes,
@@ -430,7 +479,7 @@ mod tests {
#[test]
fn create_multizone_if_no_config() {
// Checking to ensure set_mode errors when unsupported modes are tried
let config = AuraConfig::default();
let config = AuraConfig::create_default(AuraDevice::X19b6, &LaptopLedData::default());
let supported_modes = LaptopLedData {
board_name: String::new(),
layout_name: "ga401".to_owned(),
@@ -439,7 +488,7 @@ mod tests {
advanced_type: rog_aura::AdvancedAuraType::None,
};
let mut controller = CtrlKbdLed {
led_prod: None,
led_prod: AuraDevice::X19b6,
led_node: LEDNode::None,
kd_brightness: KeyboardLed::default(),
supported_modes,
@@ -468,7 +517,7 @@ mod tests {
#[test]
fn next_mode_create_multizone_if_no_config() {
// Checking to ensure set_mode errors when unsupported modes are tried
let config = AuraConfig::default();
let config = AuraConfig::create_default(AuraDevice::X19b6, &LaptopLedData::default());
let supported_modes = LaptopLedData {
board_name: String::new(),
layout_name: "ga401".to_owned(),
@@ -477,7 +526,7 @@ mod tests {
advanced_type: rog_aura::AdvancedAuraType::None,
};
let mut controller = CtrlKbdLed {
led_prod: None,
led_prod: AuraDevice::X19b6,
led_node: LEDNode::None,
kd_brightness: KeyboardLed::default(),
supported_modes,
@@ -1,4 +1,4 @@
pub mod config;
pub mod controller;
/// Implements CtrlTask, Reloadable, ZbusRun
/// Implements `CtrlTask`, `Reloadable`, `ZbusRun`
pub mod trait_impls;
@@ -78,6 +78,10 @@ impl CtrlKbdLedZbus {
/// BootBar,
/// SleepBar,
/// ShutdownBar,
/// BootRearBar,
/// AwakeRearBar,
/// SleepRearBar,
/// ShutdownRearBar,
/// }
/// ```
async fn set_leds_power(
@@ -122,6 +126,11 @@ impl CtrlKbdLedZbus {
e
})?;
ctrl.set_brightness(ctrl.config.brightness).map_err(|e| {
warn!("{}", e);
e
})?;
if let Some(mode) = ctrl.config.builtins.get(&ctrl.config.current_mode) {
Self::notify_led(&ctxt, mode.clone())
.await
@@ -298,11 +307,11 @@ impl CtrlTask for CtrlKbdLedZbus {
let ctrl2 = self.0.clone();
let ctrl = self.0.lock().await;
let mut watch = ctrl.kd_brightness.monitor_brightness()?;
let watch = ctrl.kd_brightness.monitor_brightness()?;
tokio::spawn(async move {
let mut buffer = [0; 32];
watch
.event_stream(&mut buffer)
.into_event_stream(&mut buffer)
.unwrap()
.for_each(|_| async {
if let Some(lock) = ctrl2.try_lock() {
@@ -31,12 +31,14 @@ impl GetSupported for CtrlPlatform {
fn get_supported() -> Self::A {
let mut panel_overdrive = false;
let mut mini_led_mode = false;
let mut dgpu_disable = false;
let mut egpu_enable = false;
let mut gpu_mux = false;
if let Ok(platform) = AsusPlatform::new() {
panel_overdrive = platform.has_panel_od();
mini_led_mode = platform.has_mini_led_mode();
dgpu_disable = platform.has_dgpu_disable();
egpu_enable = platform.has_egpu_enable();
gpu_mux = platform.has_gpu_mux_mode();
@@ -46,6 +48,7 @@ impl GetSupported for CtrlPlatform {
post_sound: Path::new(ASUS_POST_LOGO_SOUND).exists(),
gpu_mux,
panel_overdrive,
mini_led_mode,
dgpu_disable,
egpu_enable,
}
@@ -92,15 +95,8 @@ impl CtrlPlatform {
}
pub fn get_boot_sound() -> Result<i8, RogError> {
let path = ASUS_POST_LOGO_SOUND;
let mut file = OpenOptions::new()
.read(true)
.open(path)
.map_err(|err| RogError::Path(path.into(), err))?;
let mut data = Vec::new();
file.read_to_end(&mut data)
.map_err(|err| RogError::Read(path.into(), err))?;
let data = std::fs::read(ASUS_POST_LOGO_SOUND)
.map_err(|err| RogError::Read(ASUS_POST_LOGO_SOUND.into(), err))?;
let idx = data.len() - 1;
Ok(data[idx] as i8)
@@ -115,6 +111,7 @@ impl CtrlPlatform {
.map_err(|err| RogError::Path(path.into(), err))?;
let mut data = Vec::new();
#[allow(clippy::verbose_file_reads)]
file.read_to_end(&mut data)
.map_err(|err| RogError::Read(path.into(), err))?;
@@ -220,25 +217,51 @@ impl CtrlPlatform {
/// Get the `panel_od` value from platform. Updates the stored value in
/// internal config also.
fn panel_od(&self) -> bool {
let od = self
.platform
self.platform
.get_panel_od()
.map_err(|err| {
warn!("CtrlRogBios: get_panel_od {}", err);
err
})
.unwrap_or(false);
if let Some(mut lock) = self.config.try_lock() {
lock.panel_od = od;
lock.write();
}
od
.unwrap_or(false)
}
#[dbus_interface(signal)]
async fn notify_panel_od(signal_ctxt: &SignalContext<'_>, overdrive: bool) -> zbus::Result<()> {
}
async fn set_mini_led_mode(
&mut self,
#[zbus(signal_context)] ctxt: SignalContext<'_>,
on: bool,
) {
match self.platform.set_mini_led_mode(on) {
Ok(_) => {
if let Some(mut lock) = self.config.try_lock() {
lock.mini_led_mode = on;
lock.write();
}
Self::notify_mini_led_mode(&ctxt, on).await.ok();
}
Err(err) => warn!("CtrlRogBios: set_mini_led_mode {}", err),
};
}
/// Get the `panel_od` value from platform. Updates the stored value in
/// internal config also.
fn mini_led_mode(&self) -> bool {
self.platform
.get_mini_led_mode()
.map_err(|err| {
warn!("CtrlRogBios: get_mini_led_mode {}", err);
err
})
.unwrap_or(false)
}
#[dbus_interface(signal)]
async fn notify_mini_led_mode(signal_ctxt: &SignalContext<'_>, on: bool) -> zbus::Result<()> {}
async fn set_dgpu_disable(
&mut self,
#[zbus(signal_context)] ctxt: SignalContext<'_>,
@@ -349,7 +372,7 @@ impl CtrlTask for CtrlPlatform {
platform1
.set_panel_overdrive(lock.panel_od)
.map_err(|err| {
warn!("CtrlCharge: set_limit {}", err);
warn!("CtrlCharge: panel_od {}", err);
err
})
.ok();
@@ -366,7 +389,7 @@ impl CtrlTask for CtrlPlatform {
platform2
.set_panel_overdrive(lock.panel_od)
.map_err(|err| {
warn!("CtrlCharge: set_limit {}", err);
warn!("CtrlCharge: panel_od {}", err);
err
})
.ok();
@@ -14,7 +14,7 @@ use zbus::{dbus_interface, Connection, SignalContext};
use crate::config::Config;
use crate::error::RogError;
use crate::{task_watch_item, CtrlTask, GetSupported};
use crate::{CtrlTask, GetSupported};
const ZBUS_PATH: &str = "/org/asuslinux/Power";
const NVIDIA_POWERD: &str = "nvidia-powerd.service";
@@ -120,7 +120,7 @@ impl crate::Reloadable for CtrlPower {
}
impl CtrlPower {
task_watch_item!(charge_control_end_threshold power);
// task_watch_item!(charge_control_end_threshold power);
pub fn new(config: Arc<Mutex<Config>>) -> Result<Self, RogError> {
Ok(CtrlPower {
@@ -211,8 +211,8 @@ impl CtrlTask for CtrlPower {
.await;
let config = self.config.clone();
self.watch_charge_control_end_threshold(signal_ctxt.clone())
.await?;
// self.watch_charge_control_end_threshold(signal_ctxt.clone())
// .await?;
let ctrl = self.clone();
tokio::spawn(async move {
@@ -2,7 +2,7 @@ use std::path::PathBuf;
use config_traits::{StdConfig, StdConfigLoad};
use rog_profiles::fan_curve_set::FanCurveSet;
use rog_profiles::{FanCurveProfiles, Profile};
use rog_profiles::Profile;
use serde_derive::{Deserialize, Serialize};
use crate::CONFIG_PATH_BASE;
@@ -28,7 +28,7 @@ impl StdConfig for ProfileConfig {
}
fn file_name(&self) -> String {
CONFIG_FILE.to_string()
CONFIG_FILE.to_owned()
}
}
@@ -36,40 +36,16 @@ impl StdConfigLoad for ProfileConfig {}
#[derive(Deserialize, Serialize, Debug, Default)]
pub struct FanCurveConfig {
balanced: FanCurveSet,
performance: FanCurveSet,
quiet: FanCurveSet,
#[serde(skip)]
device: FanCurveProfiles,
}
impl FanCurveConfig {
pub fn update_device_config(&mut self) {
self.balanced = self.device.balanced.clone();
self.performance = self.device.performance.clone();
self.quiet = self.device.quiet.clone();
}
pub fn update_config(&mut self) {
self.balanced = self.device.balanced.clone();
self.performance = self.device.performance.clone();
self.quiet = self.device.quiet.clone();
}
pub fn device(&self) -> &FanCurveProfiles {
&self.device
}
pub fn device_mut(&mut self) -> &mut FanCurveProfiles {
&mut self.device
}
pub balanced: FanCurveSet,
pub performance: FanCurveSet,
pub quiet: FanCurveSet,
}
impl StdConfig for FanCurveConfig {
/// Create a new config. The defaults are zeroed so the device must be read
/// to get the actual device defaults.
fn new() -> Self {
let mut tmp = Self::default();
tmp.update_device_config();
tmp
Self::default()
}
fn config_dir() -> std::path::PathBuf {
@@ -77,7 +53,7 @@ impl StdConfig for FanCurveConfig {
}
fn file_name(&self) -> String {
CONFIG_FAN_FILE.to_string()
CONFIG_FAN_FILE.to_owned()
}
}
+175
View File
@@ -0,0 +1,175 @@
use config_traits::{StdConfig, StdConfigLoad};
use log::{info, warn};
use rog_platform::platform::AsusPlatform;
use rog_platform::supported::PlatformProfileFunctions;
use rog_profiles::error::ProfileError;
use rog_profiles::{FanCurveProfiles, Profile};
use super::config::{FanCurveConfig, ProfileConfig};
use crate::error::RogError;
use crate::GetSupported;
// TODO: macro wrapper for warn/info/error log macros to add module name
const MOD_NAME: &str = "CtrlPlatformProfile";
pub struct FanCurves {
config_file: FanCurveConfig,
profiles: FanCurveProfiles,
}
impl FanCurves {
pub fn update_profiles_from_config(&mut self) {
self.profiles.balanced = self.config_file.balanced.clone();
self.profiles.performance = self.config_file.performance.clone();
self.profiles.quiet = self.config_file.quiet.clone();
}
pub fn update_config_from_profiles(&mut self) {
self.config_file.balanced = self.profiles.balanced.clone();
self.config_file.performance = self.profiles.performance.clone();
self.config_file.quiet = self.profiles.quiet.clone();
}
pub fn profiles(&self) -> &FanCurveProfiles {
&self.profiles
}
pub fn profiles_mut(&mut self) -> &mut FanCurveProfiles {
&mut self.profiles
}
}
pub struct CtrlPlatformProfile {
pub profile_config: ProfileConfig,
pub fan_curves: Option<FanCurves>,
pub platform: AsusPlatform,
}
impl GetSupported for CtrlPlatformProfile {
type A = PlatformProfileFunctions;
fn get_supported() -> Self::A {
if !Profile::is_platform_profile_supported() {
warn!(
"platform_profile kernel interface not found, your laptop does not support this, \
or the interface is missing."
);
}
let res = FanCurveProfiles::is_supported();
let mut fan_curve_supported = res.is_err();
if let Ok(r) = res {
fan_curve_supported = r;
};
if !fan_curve_supported {
info!(
"fan curves kernel interface not found, your laptop does not support this, or the \
interface is missing."
);
}
PlatformProfileFunctions {
platform_profile: Profile::is_platform_profile_supported(),
fan_curves: fan_curve_supported,
}
}
}
impl CtrlPlatformProfile {
pub fn new(config: ProfileConfig) -> Result<Self, RogError> {
let platform = AsusPlatform::new()?;
if platform.has_platform_profile() || platform.has_throttle_thermal_policy() {
info!("{MOD_NAME}: Device has profile control available");
let mut controller = CtrlPlatformProfile {
profile_config: config,
fan_curves: None,
platform,
};
if FanCurveProfiles::get_device().is_ok() {
info!("{MOD_NAME}: Device has fan curves available");
let fan_config = FanCurveConfig::new();
// Only do defaults if the config doesn't already exist
if !fan_config.file_path().exists() {
info!("{MOD_NAME}: Fetching default fan curves");
controller.fan_curves = Some(FanCurves {
config_file: fan_config,
profiles: FanCurveProfiles::default(),
});
for _ in [Profile::Balanced, Profile::Performance, Profile::Quiet] {
// For each profile we need to switch to it before we
// can read the existing values from hardware. The ACPI method used
// for this is what limits us.
let next =
Profile::get_next_profile(controller.profile_config.active_profile);
Profile::set_profile(next)
.map_err(|e| warn!("{MOD_NAME}: set_profile, {}", e))
.ok();
controller.profile_config.active_profile = next;
// Make sure to set the baseline to default
controller.set_active_curve_to_defaults()?;
let active = Profile::get_active_profile().unwrap_or(Profile::Balanced);
if let Some(curves) = controller.fan_curves.as_ref() {
info!(
"{MOD_NAME}: {active:?}: {}",
String::from(curves.profiles().get_fan_curves_for(active))
);
}
}
if let Some(curves) = controller.fan_curves.as_ref() {
curves.config_file.write();
}
} else {
info!("{MOD_NAME}: Fan curves previously stored, loading...");
let mut fan_curves = FanCurves {
config_file: fan_config.load(),
profiles: FanCurveProfiles::default(),
};
fan_curves.update_profiles_from_config();
controller.fan_curves = Some(fan_curves);
}
}
return Ok(controller);
}
Err(ProfileError::NotSupported.into())
}
pub fn save_config(&mut self) {
self.profile_config.write();
if let Some(fans) = self.fan_curves.as_mut() {
fans.update_config_from_profiles();
fans.config_file.write(); // config write
}
}
/// Set the curve for the active profile active
pub(super) fn write_profile_curve_to_platform(&mut self) -> Result<(), RogError> {
if let Some(curves) = &mut self.fan_curves {
if let Ok(mut device) = FanCurveProfiles::get_device() {
curves.profiles_mut().write_profile_curve_to_platform(
self.profile_config.active_profile,
&mut device,
)?;
}
}
Ok(())
}
pub(super) fn set_active_curve_to_defaults(&mut self) -> Result<(), RogError> {
if let Some(curves) = self.fan_curves.as_mut() {
if let Ok(mut device) = FanCurveProfiles::get_device() {
curves.profiles_mut().set_active_curve_to_defaults(
self.profile_config.active_profile,
&mut device,
)?;
curves.update_config_from_profiles();
}
}
Ok(())
}
}
@@ -15,6 +15,8 @@ use super::controller::CtrlPlatformProfile;
use crate::error::RogError;
use crate::CtrlTask;
const MOD_NAME: &str = "ProfileZbus";
const ZBUS_PATH: &str = "/org/asuslinux/Profile";
const UNSUPPORTED_MSG: &str =
"Fan curves are not supported on this laptop or you require a patched kernel";
@@ -38,8 +40,11 @@ impl ProfileZbus {
/// If fan-curves are supported will also activate a fan curve for profile.
async fn next_profile(&mut self, #[zbus(signal_context)] ctxt: SignalContext<'_>) {
let mut ctrl = self.0.lock().await;
ctrl.set_next_profile()
.unwrap_or_else(|err| warn!("{}", err));
let next = Profile::get_next_profile(ctrl.profile_config.active_profile);
Profile::set_profile(next)
.map_err(|e| warn!("{MOD_NAME}: set_profile, {}", e))
.ok();
ctrl.profile_config.active_profile = next;
ctrl.save_config();
Self::notify_profile(&ctxt, ctrl.profile_config.active_profile)
@@ -64,11 +69,11 @@ impl ProfileZbus {
// Read first just incase the user has modified the config before calling this
ctrl.profile_config.read();
Profile::set_profile(profile)
.map_err(|e| warn!("set_profile, {}", e))
.map_err(|e| warn!("{MOD_NAME}: set_profile, {}", e))
.ok();
ctrl.profile_config.active_profile = profile;
ctrl.write_profile_curve_to_platform()
.map_err(|e| warn!("write_profile_curve_to_platform, {}", e))
.map_err(|e| warn!("{MOD_NAME}: write_profile_curve_to_platform, {}", e))
.ok();
ctrl.save_config();
@@ -82,8 +87,8 @@ impl ProfileZbus {
async fn enabled_fan_profiles(&mut self) -> zbus::fdo::Result<Vec<Profile>> {
let mut ctrl = self.0.lock().await;
ctrl.profile_config.read();
if let Some(curves) = &mut ctrl.fan_config {
return Ok(curves.device().get_enabled_curve_profiles());
if let Some(curves) = &mut ctrl.fan_curves {
return Ok(curves.profiles().get_enabled_curve_profiles());
}
Err(Error::Failed(UNSUPPORTED_MSG.to_owned()))
}
@@ -97,14 +102,13 @@ impl ProfileZbus {
) -> zbus::fdo::Result<()> {
let mut ctrl = self.0.lock().await;
ctrl.profile_config.read();
if let Some(curves) = &mut ctrl.fan_config {
if let Some(curves) = &mut ctrl.fan_curves {
curves
.device_mut()
.profiles_mut()
.set_profile_curve_enabled(profile, enabled);
curves.update_config();
ctrl.write_profile_curve_to_platform()
.map_err(|e| warn!("write_profile_curve_to_platform, {}", e))
.map_err(|e| warn!("{MOD_NAME}: write_profile_curve_to_platform, {}", e))
.ok();
ctrl.save_config();
@@ -118,8 +122,8 @@ impl ProfileZbus {
async fn fan_curve_data(&mut self, profile: Profile) -> zbus::fdo::Result<FanCurveSet> {
let mut ctrl = self.0.lock().await;
ctrl.profile_config.read();
if let Some(curves) = &mut ctrl.fan_config {
let curve = curves.device().get_fan_curves_for(profile);
if let Some(curves) = &mut ctrl.fan_curves {
let curve = curves.profiles().get_fan_curves_for(profile);
return Ok(curve.clone());
}
Err(Error::Failed(UNSUPPORTED_MSG.to_owned()))
@@ -130,17 +134,16 @@ impl ProfileZbus {
async fn set_fan_curve(&self, profile: Profile, curve: CurveData) -> zbus::fdo::Result<()> {
let mut ctrl = self.0.lock().await;
ctrl.profile_config.read();
if let Some(curves) = &mut ctrl.fan_config {
if let Some(curves) = &mut ctrl.fan_curves {
curves
.device_mut()
.profiles_mut()
.save_fan_curve(curve, profile)
.map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?;
curves.update_config();
} else {
return Err(Error::Failed(UNSUPPORTED_MSG.to_owned()));
}
ctrl.write_profile_curve_to_platform()
.map_err(|e| warn!("Profile::set_profile, {}", e))
.map_err(|e| warn!("{MOD_NAME}: Profile::set_profile, {}", e))
.ok();
ctrl.save_config();
@@ -156,7 +159,7 @@ impl ProfileZbus {
let mut ctrl = self.0.lock().await;
ctrl.profile_config.read();
ctrl.set_active_curve_to_defaults()
.map_err(|e| warn!("Profile::set_active_curve_to_defaults, {}", e))
.map_err(|e| warn!("{MOD_NAME}: Profile::set_active_curve_to_defaults, {}", e))
.ok();
ctrl.save_config();
Ok(())
@@ -173,14 +176,14 @@ impl ProfileZbus {
let active = Profile::get_active_profile().unwrap_or(Profile::Balanced);
Profile::set_profile(profile)
.map_err(|e| warn!("set_profile, {}", e))
.map_err(|e| warn!("{MOD_NAME}: set_profile, {}", e))
.ok();
ctrl.set_active_curve_to_defaults()
.map_err(|e| warn!("Profile::set_active_curve_to_defaults, {}", e))
.map_err(|e| warn!("{MOD_NAME}: Profile::set_active_curve_to_defaults, {}", e))
.ok();
Profile::set_profile(active)
.map_err(|e| warn!("set_profile, {}", e))
.map_err(|e| warn!("{MOD_NAME}: set_profile, {}", e))
.ok();
ctrl.save_config();
Ok(())
@@ -207,7 +210,7 @@ impl CtrlTask for ProfileZbus {
async fn create_tasks(&self, signal_ctxt: SignalContext<'static>) -> Result<(), RogError> {
let ctrl = self.0.clone();
let sig_ctx = signal_ctxt.clone();
let mut watch = self
let watch = self
.0
.lock()
.await
@@ -216,18 +219,18 @@ impl CtrlTask for ProfileZbus {
tokio::spawn(async move {
let mut buffer = [0; 32];
if let Ok(stream) = watch.event_stream(&mut buffer) {
if let Ok(stream) = watch.into_event_stream(&mut buffer) {
stream
.for_each(|_| async {
let mut lock = ctrl.lock().await;
if let Ok(profile) =
lock.platform.get_throttle_thermal_policy().map_err(|e| {
error!("get_throttle_thermal_policy error: {e}");
error!("{MOD_NAME}: get_throttle_thermal_policy error: {e}");
})
{
let new_profile = Profile::from_throttle_thermal_policy(profile);
if new_profile != lock.profile_config.active_profile {
info!("platform_profile changed to {new_profile}");
info!("{MOD_NAME}: platform_profile changed to {new_profile}");
lock.profile_config.active_profile = new_profile;
lock.write_profile_curve_to_platform().unwrap();
lock.save_config();
@@ -236,10 +239,11 @@ impl CtrlTask for ProfileZbus {
error!("Profile::set_profile() error: {e}");
})
.ok();
Self::notify_profile(&sig_ctx, lock.profile_config.active_profile)
.await
.ok();
}
Self::notify_profile(&sig_ctx, lock.profile_config.active_profile)
.await
.ok();
}
})
.await;
@@ -247,11 +251,11 @@ impl CtrlTask for ProfileZbus {
});
let ctrl = self.0.clone();
let mut watch = self.0.lock().await.platform.monitor_platform_profile()?;
let watch = self.0.lock().await.platform.monitor_platform_profile()?;
tokio::spawn(async move {
let mut buffer = [0; 32];
if let Ok(stream) = watch.event_stream(&mut buffer) {
if let Ok(stream) = watch.into_event_stream(&mut buffer) {
stream
.for_each(|_| async {
let mut lock = ctrl.lock().await;
@@ -262,7 +266,7 @@ impl CtrlTask for ProfileZbus {
error!("Profile::from_str(&profile) error: {e}");
}) {
if new_profile != lock.profile_config.active_profile {
info!("platform_profile changed to {new_profile}");
info!("{MOD_NAME}: platform_profile changed to {new_profile}");
lock.profile_config.active_profile = new_profile;
lock.write_profile_curve_to_platform().unwrap();
lock.save_config();
@@ -271,13 +275,14 @@ impl CtrlTask for ProfileZbus {
error!("Profile::set_profile() error: {e}");
})
.ok();
Self::notify_profile(
&signal_ctxt,
lock.profile_config.active_profile,
)
.await
.ok();
}
Self::notify_profile(
&signal_ctxt,
lock.profile_config.active_profile,
)
.await
.ok();
}
}
})
@@ -295,15 +300,14 @@ impl crate::Reloadable for ProfileZbus {
async fn reload(&mut self) -> Result<(), RogError> {
let mut ctrl = self.0.lock().await;
let active = ctrl.profile_config.active_profile;
if let Some(curves) = &mut ctrl.fan_config {
if let Some(curves) = &mut ctrl.fan_curves {
if let Ok(mut device) = FanCurveProfiles::get_device() {
// There is a possibility that the curve was default zeroed, so this call
// initialises the data from system read and we need to save it
// after
curves
.device_mut()
.profiles_mut()
.write_profile_curve_to_platform(active, &mut device)?;
curves.update_config();
ctrl.profile_config.write();
}
}
+17 -17
View File
@@ -6,21 +6,20 @@ use std::time::Duration;
use ::zbus::export::futures_util::lock::Mutex;
use ::zbus::Connection;
use asusd::config::Config;
use asusd::ctrl_anime::config::AnimeConfig;
use asusd::ctrl_anime::trait_impls::CtrlAnimeZbus;
use asusd::ctrl_anime::CtrlAnime;
use asusd::ctrl_aura::controller::CtrlKbdLed;
use asusd::ctrl_aura::trait_impls::CtrlKbdLedZbus;
use asusd::ctrl_platform::CtrlPlatform;
use asusd::ctrl_power::CtrlPower;
use asusd::ctrl_profiles::config::ProfileConfig;
use asusd::ctrl_profiles::controller::CtrlPlatformProfile;
use asusd::ctrl_profiles::trait_impls::ProfileZbus;
use asusd::ctrl_supported::SupportedFunctions;
use asusd::{print_board_info, CtrlTask, GetSupported, Reloadable, ZbusRun};
use config_traits::{StdConfig, StdConfigLoad, StdConfigLoad2};
use daemon::config::Config;
use daemon::ctrl_anime::config::AnimeConfig;
use daemon::ctrl_anime::trait_impls::CtrlAnimeZbus;
use daemon::ctrl_anime::CtrlAnime;
use daemon::ctrl_aura::config::AuraConfig;
use daemon::ctrl_aura::controller::CtrlKbdLed;
use daemon::ctrl_aura::trait_impls::CtrlKbdLedZbus;
use daemon::ctrl_platform::CtrlPlatform;
use daemon::ctrl_power::CtrlPower;
use daemon::ctrl_profiles::config::ProfileConfig;
use daemon::ctrl_profiles::controller::CtrlPlatformProfile;
use daemon::ctrl_profiles::trait_impls::ProfileZbus;
use daemon::ctrl_supported::SupportedFunctions;
use daemon::{print_board_info, CtrlTask, GetSupported, Reloadable, ZbusRun};
use log::{error, info, warn};
use rog_aura::aura_detection::LaptopLedData;
use rog_dbus::DBUS_NAME;
@@ -51,7 +50,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
return Ok(());
}
info!(" daemon v{}", daemon::VERSION);
info!(" daemon v{}", asusd::VERSION);
info!(" rog-anime v{}", rog_anime::VERSION);
info!(" rog-aura v{}", rog_aura::VERSION);
info!(" rog-dbus v{}", rog_dbus::VERSION);
@@ -124,8 +123,9 @@ async fn start_daemon() -> Result<(), Box<dyn Error>> {
}
let laptop = LaptopLedData::get_data();
let aura_config = AuraConfig::new().load();
match CtrlKbdLed::new(laptop, aura_config) {
// CtrlKbdLed deviates from the config pattern above due to requiring a keyboard
// detection first
match CtrlKbdLed::new(laptop) {
Ok(ctrl) => {
let zbus = CtrlKbdLedZbus(Arc::new(Mutex::new(ctrl)));
let sig_ctx = CtrlKbdLedZbus::signal_context(&connection)?;
+3 -2
View File
@@ -51,6 +51,7 @@ const CONFIG_PATH_BASE: &str = "/etc/asusd/";
/// task_watch_item!(gpu_mux_mode platform);
/// }
/// ```
/// // TODO: this is kind of useless if it can't trigger some action
#[macro_export]
macro_rules! task_watch_item {
($name:ident $self_inner:ident) => {
@@ -64,10 +65,10 @@ macro_rules! task_watch_item {
let ctrl = self.clone();
concat_idents::concat_idents!(watch_fn = monitor_, $name {
match self.$self_inner.watch_fn() {
Ok(mut watch) => {
Ok(watch) => {
tokio::spawn(async move {
let mut buffer = [0; 32];
watch.event_stream(&mut buffer).unwrap().for_each(|_| async {
watch.into_event_stream(&mut buffer).unwrap().for_each(|_| async {
let value = ctrl.$name();
concat_idents::concat_idents!(notif_fn = notify_, $name {
Self::notif_fn(&signal_ctxt, value).await.ok();
+7 -4
View File
@@ -1,9 +1,9 @@
[package]
name = "config-traits"
version = "0.1.0"
license = "MPL-2.0"
authors = ["Luke D Jones <luke@ljones.dev>"]
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
version.workspace = true
[dependencies]
serde.workspace = true
@@ -12,4 +12,7 @@ serde_json.workspace = true
toml.workspace = true
ron.workspace = true
log.workspace = true
log.workspace = true
[dev-dependencies]
cargo-husky.workspace = true
+10
View File
@@ -0,0 +1,10 @@
# config-traits
`config_traits` is a crate that broke out from the requirement to manage various
different config files, including parsing from different formats and updating
them from previous versions where fields or names are changed in some way.
The end canonical file format is `.ron` as this supports rust types well, and includes
the ability to add commenting, and is less verbose than `json`. Currently the crate will
also try to parse from `json` and `toml` if the `ron` parsing fails, then update to `ron`
format.
+38 -27
View File
@@ -1,4 +1,14 @@
use std::fs::{create_dir, File, OpenOptions};
//! `config_traits` is a crate that broke out from the requirement to manage
//! various different config files, including parsing from different formats and
//! updating them from previous versions where fields or names are changed in
//! some way.
//!
//! The end canonical file format is `.ron` as this supports rust types well,
//! and includes the ability to add commenting, and is less verbose than `json`.
//! Currently the crate will also try to parse from `json` and `toml` if the
//! `ron` parsing fails, then update to `ron` format.
use std::fs::{self, create_dir, File, OpenOptions};
use std::io::{Read, Write};
use std::path::PathBuf;
@@ -49,7 +59,7 @@ where
"Could not rename. Please remove {} then restart service: Error {}",
self.file_name(),
err
)
);
});
do_rename = false;
}
@@ -68,7 +78,7 @@ where
"Could not rename. Please remove {} then restart service: Error {}",
self.file_name(),
err
)
);
});
}
config
@@ -88,18 +98,10 @@ where
/// Open and parse the config file to self from ron format
fn read(&mut self) {
let mut file = match OpenOptions::new().read(true).open(self.file_path()) {
Ok(data) => data,
Err(err) => {
error!("Error reading {:?}: {}", self.file_path(), err);
return;
}
};
let mut buf = String::new();
if let Ok(l) = file.read_to_string(&mut buf) {
if l == 0 {
if let Ok(data) = fs::read_to_string(self.file_path()) {
if data.is_empty() {
warn!("File is empty {:?}", self.file_path());
} else if let Ok(data) = ron::from_str(&buf) {
} else if let Ok(data) = ron::from_str(&data) {
*self = data;
} else {
warn!("Could not deserialise {:?}", self.file_path());
@@ -137,13 +139,14 @@ where
self.file_name(),
self.file_name()
);
let cfg_old = self.file_path().to_string_lossy().to_string() + "-old";
let mut cfg_old = self.file_path().to_string_lossy().to_string();
cfg_old.push_str("-old");
std::fs::rename(self.file_path(), cfg_old).unwrap_or_else(|err| {
error!(
"Could not rename. Please remove {} then restart service: Error {}",
self.file_name(),
err
)
);
});
}
}
@@ -160,13 +163,13 @@ macro_rules! std_config_load {
/// use serde::{Deserialize, Serialize};
/// use config_traits::{StdConfig, StdConfigLoad2};
///
/// #[derive(Deserialize, Serialize)]
/// #[derive(Deserialize, Serialize, Debug)]
/// struct FanCurveConfigOld {}
///
/// #[derive(Deserialize, Serialize)]
/// #[derive(Deserialize, Serialize, Debug)]
/// struct FanCurveConfigOlder {}
///
/// #[derive(Deserialize, Serialize)]
/// #[derive(Deserialize, Serialize, Debug)]
/// struct FanCurveConfig {}
///
/// impl From<FanCurveConfigOld> for FanCurveConfig {
@@ -192,7 +195,7 @@ macro_rules! std_config_load {
/// new one created
pub trait $trait_name<$($generic),*>
where
Self: $crate::StdConfig + DeserializeOwned + Serialize,
Self: $crate::StdConfig +std::fmt::Debug + DeserializeOwned + Serialize,
$($generic: DeserializeOwned + Into<Self>),*
{
fn load(mut self) -> Self {
@@ -202,14 +205,22 @@ macro_rules! std_config_load {
if read_len != 0 {
if let Ok(data) = ron::from_str(&buf) {
self = data;
log::info!("Parsed RON for {:?}", std::any::type_name::<Self>());
} else if let Ok(data) = serde_json::from_str(&buf) {
self = data;
log::info!("Parsed JSON for {:?}", std::any::type_name::<Self>());
} else if let Ok(data) = toml::from_str(&buf) {
self = data;
} $(else if let Ok(data) = serde_json::from_str::<$generic>(&buf) {
log::info!("Parsed TOML for {:?}", std::any::type_name::<Self>());
} $(else if let Ok(data) = ron::from_str::<$generic>(&buf) {
self = data.into();
log::info!("New version failed, trying previous: Parsed RON for {:?}", std::any::type_name::<$generic>());
} else if let Ok(data) = serde_json::from_str::<$generic>(&buf) {
self = data.into();
log::info!("New version failed, trying previous: Parsed JSON for {:?}", std::any::type_name::<$generic>());
} else if let Ok(data) = toml::from_str::<$generic>(&buf) {
self = data.into();
log::info!("Newvious version failed, trying previous: Parsed TOML for {:?}", std::any::type_name::<$generic>());
})* else {
self.rename_file_old();
self = Self::new();
@@ -237,10 +248,10 @@ mod tests {
#[test]
fn check_macro_from_1() {
#[derive(serde::Deserialize, serde::Serialize)]
#[derive(serde::Deserialize, serde::Serialize, Debug)]
struct Test {}
#[derive(serde::Deserialize, serde::Serialize)]
#[derive(serde::Deserialize, serde::Serialize, Debug)]
struct Old1 {}
impl crate::StdConfig for Test {
@@ -268,16 +279,16 @@ mod tests {
#[test]
fn check_macro_from_3() {
#[derive(serde::Deserialize, serde::Serialize)]
#[derive(serde::Deserialize, serde::Serialize, Debug)]
struct Test {}
#[derive(serde::Deserialize, serde::Serialize)]
#[derive(serde::Deserialize, serde::Serialize, Debug)]
struct Old1 {}
#[derive(serde::Deserialize, serde::Serialize)]
#[derive(serde::Deserialize, serde::Serialize, Debug)]
struct Old2 {}
#[derive(serde::Deserialize, serde::Serialize)]
#[derive(serde::Deserialize, serde::Serialize, Debug)]
struct Old3 {}
impl crate::StdConfig for Test {
-221
View File
@@ -1,221 +0,0 @@
use std::sync::atomic::Ordering;
use std::sync::Arc;
use async_trait::async_trait;
use config_traits::StdConfig;
use log::{info, warn};
use rog_anime::usb::{pkt_for_apply, pkt_for_set_boot, pkt_for_set_on};
use rog_anime::{AnimeDataBuffer, AnimePowerStates};
use zbus::export::futures_util::lock::{Mutex, MutexGuard};
use zbus::{dbus_interface, Connection, SignalContext};
use super::CtrlAnime;
use crate::error::RogError;
pub(super) const ZBUS_PATH: &str = "/org/asuslinux/Anime";
#[derive(Clone)]
pub struct CtrlAnimeZbus(pub Arc<Mutex<CtrlAnime>>);
/// The struct with the main dbus methods requires this trait
#[async_trait]
impl crate::ZbusRun for CtrlAnimeZbus {
async fn add_to_server(self, server: &mut Connection) {
Self::add_to_server_helper(self, ZBUS_PATH, server).await;
}
}
// None of these calls can be guarnateed to succeed unless we loop until okay
// If the try_lock *does* succeed then any other thread trying to lock will not
// grab it until we finish.
#[dbus_interface(name = "org.asuslinux.Daemon")]
impl CtrlAnimeZbus {
/// Writes a data stream of length. Will force system thread to exit until
/// it is restarted
async fn write(&self, input: AnimeDataBuffer) -> zbus::fdo::Result<()> {
let lock = self.0.lock().await;
lock.thread_exit.store(true, Ordering::SeqCst);
lock.write_data_buffer(input).map_err(|err| {
warn!("rog_anime::run_animation:callback {}", err);
err
})?;
Ok(())
}
/// Set the global AniMe brightness
async fn set_brightness(&self, bright: f32) {
let mut lock = self.0.lock().await;
let mut bright = bright;
if bright < 0.0 {
bright = 0.0;
} else if bright > 1.0 {
bright = 1.0;
}
lock.config.brightness = bright;
lock.config.write();
}
/// Set whether the AniMe is displaying images/data
async fn set_on_off(&self, #[zbus(signal_context)] ctxt: SignalContext<'_>, status: bool) {
let mut lock = self.0.lock().await;
lock.node
.write_bytes(&pkt_for_set_on(status))
.map_err(|err| {
warn!("rog_anime::run_animation:callback {}", err);
})
.ok();
lock.config.awake_enabled = status;
lock.config.write();
Self::notify_power_states(
&ctxt,
AnimePowerStates {
brightness: lock.config.brightness.floor() as u8,
enabled: lock.config.awake_enabled,
boot_anim_enabled: lock.config.boot_anim_enabled,
},
)
.await
.ok();
}
/// Set whether the AniMe will show boot, suspend, or off animations
async fn set_boot_on_off(&self, #[zbus(signal_context)] ctxt: SignalContext<'_>, on: bool) {
let mut lock = self.0.lock().await;
lock.node
.write_bytes(&pkt_for_set_boot(on))
.map_err(|err| {
warn!("rog_anime::run_animation:callback {}", err);
})
.ok();
lock.node
.write_bytes(&pkt_for_apply())
.map_err(|err| {
warn!("rog_anime::run_animation:callback {}", err);
})
.ok();
lock.config.boot_anim_enabled = on;
lock.config.write();
Self::notify_power_states(
&ctxt,
AnimePowerStates {
brightness: lock.config.brightness.floor() as u8,
enabled: lock.config.awake_enabled,
boot_anim_enabled: lock.config.boot_anim_enabled,
},
)
.await
.ok();
}
/// 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 {
let lock = self.0.lock().await;
lock.thread_exit.store(true, Ordering::SeqCst);
CtrlAnime::run_thread(self.0.clone(), lock.cache.system.clone(), false);
}
}
/// Get status of if the AniMe LEDs are on/displaying while system is awake
#[dbus_interface(property)]
async fn awake_enabled(&self) -> bool {
let lock = self.0.lock().await;
lock.config.awake_enabled
}
/// Get the status of if factory system-status animations are enabled
#[dbus_interface(property)]
async fn boot_enabled(&self) -> bool {
let lock = self.0.lock().await;
lock.config.boot_anim_enabled
}
/// Notify listeners of the status of AniMe LED power and factory
/// system-status animations
#[dbus_interface(signal)]
async fn notify_power_states(
ctxt: &SignalContext<'_>,
data: AnimePowerStates,
) -> zbus::Result<()>;
}
#[async_trait]
impl crate::CtrlTask for CtrlAnimeZbus {
fn zbus_path() -> &'static str {
ZBUS_PATH
}
async fn create_tasks(&self, _: SignalContext<'static>) -> Result<(), RogError> {
let run_action =
|start: bool, lock: MutexGuard<'_, CtrlAnime>, inner: Arc<Mutex<CtrlAnime>>| {
if start {
info!("CtrlAnimeTask running sleep animation");
CtrlAnime::run_thread(inner, lock.cache.shutdown.clone(), true);
} else {
info!("CtrlAnimeTask running wake animation");
CtrlAnime::run_thread(inner, lock.cache.wake.clone(), true);
}
};
let inner1 = self.0.clone();
let inner2 = self.0.clone();
let inner3 = self.0.clone();
let inner4 = self.0.clone();
self.create_sys_event_tasks(
// Loop is required to try an attempt to get the mutex *without* blocking
// other threads - it is possible to end up with deadlocks otherwise.
move || {
let inner1 = inner1.clone();
async move {
let lock = inner1.lock().await;
run_action(true, lock, inner1.clone());
}
},
move || {
let inner2 = inner2.clone();
async move {
let lock = inner2.lock().await;
run_action(true, lock, inner2.clone());
}
},
move || {
let inner3 = inner3.clone();
async move {
let lock = inner3.lock().await;
run_action(true, lock, inner3.clone());
}
},
move || {
let inner4 = inner4.clone();
async move {
let lock = inner4.lock().await;
run_action(true, lock, inner4.clone());
}
},
)
.await;
Ok(())
}
}
#[async_trait]
impl crate::Reloadable for CtrlAnimeZbus {
async fn reload(&mut self) -> Result<(), RogError> {
if let Some(lock) = self.0.try_lock() {
lock.node
.write_bytes(&pkt_for_set_on(lock.config.awake_enabled))?;
lock.node.write_bytes(&pkt_for_apply())?;
lock.node
.write_bytes(&pkt_for_set_boot(lock.config.boot_anim_enabled))?;
lock.node.write_bytes(&pkt_for_apply())?;
let action = lock.cache.boot.clone();
CtrlAnime::run_thread(self.0.clone(), action, true);
}
Ok(())
}
}
-141
View File
@@ -1,141 +0,0 @@
use config_traits::StdConfig;
use log::{info, warn};
use rog_platform::platform::AsusPlatform;
use rog_platform::supported::PlatformProfileFunctions;
use rog_profiles::error::ProfileError;
use rog_profiles::{FanCurveProfiles, Profile};
use super::config::{FanCurveConfig, ProfileConfig};
use crate::error::RogError;
use crate::GetSupported;
pub struct CtrlPlatformProfile {
pub profile_config: ProfileConfig,
pub fan_config: Option<FanCurveConfig>,
pub platform: AsusPlatform,
}
impl GetSupported for CtrlPlatformProfile {
type A = PlatformProfileFunctions;
fn get_supported() -> Self::A {
if !Profile::is_platform_profile_supported() {
warn!(
"platform_profile kernel interface not found, your laptop does not support this, \
or the interface is missing."
);
}
let res = FanCurveProfiles::is_supported();
let mut fan_curve_supported = res.is_err();
if let Ok(r) = res {
fan_curve_supported = r;
};
if !fan_curve_supported {
info!(
"fan curves kernel interface not found, your laptop does not support this, or the \
interface is missing."
);
}
PlatformProfileFunctions {
platform_profile: Profile::is_platform_profile_supported(),
fan_curves: fan_curve_supported,
}
}
}
impl CtrlPlatformProfile {
pub fn new(config: ProfileConfig) -> Result<Self, RogError> {
let platform = AsusPlatform::new()?;
if platform.has_platform_profile() || platform.has_throttle_thermal_policy() {
info!("Device has profile control available");
let mut controller = CtrlPlatformProfile {
profile_config: config,
fan_config: None,
platform,
};
if FanCurveProfiles::get_device().is_ok() {
info!("Device has fan curves available");
if controller.fan_config.is_none() {
controller.fan_config = Some(Default::default());
for _ in [Profile::Balanced, Profile::Performance, Profile::Quiet] {
controller.set_next_profile()?;
controller.set_active_curve_to_defaults()?;
let active = Profile::get_active_profile().unwrap_or(Profile::Balanced);
if let Some(curves) = controller.fan_config.as_ref() {
info!(
"{active:?}: {}",
String::from(curves.device().get_fan_curves_for(active))
);
curves.write();
}
}
}
}
return Ok(controller);
}
Err(ProfileError::NotSupported.into())
}
pub fn save_config(&mut self) {
self.profile_config.write();
if let Some(fans) = self.fan_config.as_mut() {
fans.update_config();
fans.write();
}
}
/// Toggle to next profile in list. This will first read the config, switch,
/// then write out
pub(super) fn set_next_profile(&mut self) -> Result<(), RogError> {
// Read first just incase the user has modified the config before calling this
match self.profile_config.active_profile {
Profile::Balanced => {
Profile::set_profile(Profile::Performance)?;
self.profile_config.active_profile = Profile::Performance;
}
Profile::Performance => {
Profile::set_profile(Profile::Quiet)?;
self.profile_config.active_profile = Profile::Quiet;
}
Profile::Quiet => {
Profile::set_profile(Profile::Balanced)?;
self.profile_config.active_profile = Profile::Balanced;
}
}
self.write_profile_curve_to_platform()?;
Ok(())
}
/// Set the curve for the active profile active
pub(super) fn write_profile_curve_to_platform(&mut self) -> Result<(), RogError> {
if let Some(curves) = &mut self.fan_config {
if let Ok(mut device) = FanCurveProfiles::get_device() {
curves.device_mut().write_profile_curve_to_platform(
self.profile_config.active_profile,
&mut device,
)?;
}
}
Ok(())
}
pub(super) fn set_active_curve_to_defaults(&mut self) -> Result<(), RogError> {
if let Some(curves) = self.fan_config.as_mut() {
if let Ok(mut device) = FanCurveProfiles::get_device() {
curves.device_mut().set_active_curve_to_defaults(
self.profile_config.active_profile,
&mut device,
)?;
curves.update_config();
}
}
Ok(())
}
}
+12
View File
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<body>
<script language="javascript" type="text/javascript">
<!--
window.setTimeout('window.location="room4doom/index.html"; ', 0);
// -->
</script>
</body>
</html>
+6 -1
View File
@@ -17,6 +17,10 @@ default = ["dbus", "detect"]
dbus = ["zbus"]
detect = ["sysfs-class"]
[lib]
name = "rog_anime"
path = "src/lib.rs"
[dependencies]
png_pong.workspace = true
pix.workspace = true
@@ -32,4 +36,5 @@ zbus = { workspace = true, optional = true }
sysfs-class = { workspace = true, optional = true }
uhid-virt = "^0.0.5"
[dev-dependencies]
cargo-husky.workspace = true
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

+47 -14
View File
@@ -1,4 +1,5 @@
use std::convert::TryFrom;
use std::str::FromStr;
use std::thread::sleep;
use std::time::{Duration, Instant};
@@ -8,6 +9,7 @@ use serde_derive::{Deserialize, Serialize};
use zbus::zvariant::Type;
use crate::error::{AnimeError, Result};
use crate::usb::{AnimAwake, AnimBooting, AnimShutdown, AnimSleeping, Brightness};
use crate::{AnimTime, AnimeGif};
/// The first 7 bytes of a USB packet are accounted for by `USB_PREFIX1` and
@@ -19,18 +21,28 @@ const BLOCK_END: usize = 634;
const PANE_LEN: usize = BLOCK_END - BLOCK_START;
/// First packet is for GA401 + GA402
const USB_PREFIX1: [u8; 7] = [0x5e, 0xc0, 0x02, 0x01, 0x00, 0x73, 0x02];
pub const USB_PREFIX1: [u8; 7] = [0x5e, 0xc0, 0x02, 0x01, 0x00, 0x73, 0x02];
/// Second packet is for GA401 + GA402
const USB_PREFIX2: [u8; 7] = [0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02];
pub const USB_PREFIX2: [u8; 7] = [0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02];
/// Third packet is for GA402 matrix
const USB_PREFIX3: [u8; 7] = [0x5e, 0xc0, 0x02, 0xe7, 0x04, 0x73, 0x02];
pub const USB_PREFIX3: [u8; 7] = [0x5e, 0xc0, 0x02, 0xe7, 0x04, 0x73, 0x02];
#[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Default, Deserialize, PartialEq, Eq, Clone, Copy, Serialize, Debug)]
pub struct Animations {
pub boot: AnimBooting,
pub awake: AnimAwake,
pub sleep: AnimSleeping,
pub shutdown: AnimShutdown,
}
#[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Debug, PartialEq, Eq, Copy, Clone, Deserialize, Serialize)]
pub struct AnimePowerStates {
pub brightness: u8,
pub enabled: bool,
pub boot_anim_enabled: bool,
pub struct DeviceState {
pub display_enabled: bool,
pub display_brightness: Brightness,
pub builtin_anims_enabled: bool,
pub builtin_anims: Animations,
}
#[cfg_attr(feature = "dbus", derive(Type))]
@@ -38,13 +50,29 @@ pub struct AnimePowerStates {
pub enum AnimeType {
GA401,
GA402,
GU604,
Unknown,
}
impl FromStr for AnimeType {
type Err = AnimeError;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
Ok(match s {
"ga401" | "GA401" => Self::GA401,
"ga402" | "GA402" => Self::GA402,
"gu604" | "GU604" => Self::GU604,
_ => Self::Unknown,
})
}
}
impl AnimeType {
/// The width of diagonal images
pub fn width(&self) -> usize {
match self {
AnimeType::GA401 | AnimeType::GA402 => 74,
AnimeType::GU604 => 70,
_ => 74,
}
}
@@ -52,7 +80,8 @@ impl AnimeType {
pub fn height(&self) -> usize {
match self {
AnimeType::GA401 => 36,
AnimeType::GA402 => 39,
AnimeType::GU604 => 43,
_ => 39,
}
}
@@ -60,7 +89,8 @@ impl AnimeType {
pub fn data_length(&self) -> usize {
match self {
AnimeType::GA401 => PANE_LEN * 2,
AnimeType::GA402 => PANE_LEN * 3,
AnimeType::GU604 => PANE_LEN * 3,
_ => PANE_LEN * 3,
}
}
}
@@ -111,7 +141,7 @@ impl AnimeDataBuffer {
}
}
/// The two packets to be written to USB
/// The packets to be written to USB
pub type AnimePacketType = Vec<[u8; 640]>;
impl TryFrom<AnimeDataBuffer> for AnimePacketType {
@@ -124,7 +154,7 @@ impl TryFrom<AnimeDataBuffer> for AnimePacketType {
let mut buffers = match anime.anime {
AnimeType::GA401 => vec![[0; 640]; 2],
AnimeType::GA402 => vec![[0; 640]; 3],
AnimeType::GA402 | AnimeType::GU604 | AnimeType::Unknown => vec![[0; 640]; 3],
};
for (idx, chunk) in anime.data.as_slice().chunks(PANE_LEN).enumerate() {
@@ -133,7 +163,10 @@ impl TryFrom<AnimeDataBuffer> for AnimePacketType {
buffers[0][..7].copy_from_slice(&USB_PREFIX1);
buffers[1][..7].copy_from_slice(&USB_PREFIX2);
if matches!(anime.anime, AnimeType::GA402) {
if matches!(
anime.anime,
AnimeType::GA402 | AnimeType::GU604 | AnimeType::Unknown
) {
buffers[2][..7].copy_from_slice(&USB_PREFIX3);
}
Ok(buffers)
@@ -212,7 +245,7 @@ pub fn run_animation(frames: &AnimeGif, callback: &dyn Fn(AnimeDataBuffer) -> Re
// TODO: Log this error
if matches!(callback(output), Ok(true)) {
info!("rog-anime: frame-loop callback asked to exit early");
info!("rog-anime: animation frame-loop callback asked to exit early");
return;
}
+84 -380
View File
@@ -1,3 +1,5 @@
//! This is full of crap code which is basically bruteforced
use std::path::Path;
use std::time::Duration;
@@ -138,7 +140,8 @@ impl AnimeDiagonal {
pub fn into_data_buffer(&self, anime_type: AnimeType) -> Result<AnimeDataBuffer> {
match anime_type {
AnimeType::GA401 => self.to_ga401_packets(),
AnimeType::GA402 => self.to_ga402_packets(),
AnimeType::GU604 => self.to_gu604_packets(),
_ => self.to_ga402_packets(),
}
}
@@ -288,388 +291,89 @@ impl AnimeDiagonal {
AnimeDataBuffer::from_vec(crate::AnimeType::GA402, buf)
}
}
#[cfg(test)]
mod tests {
use std::convert::TryFrom;
use std::path::PathBuf;
fn to_gu604_packets(&self) -> Result<AnimeDataBuffer> {
let mut buf = vec![0u8; AnimeType::GU604.data_length()];
let mut start_index: usize = 0;
use crate::{AnimeDiagonal, AnimePacketType, AnimeType};
fn copy_slice(
buf: &mut [u8],
anime: &AnimeDiagonal,
x: usize,
y: usize,
start_index: &mut usize,
len: usize,
) {
buf[*start_index..*start_index + len].copy_from_slice(&anime.get_row(x, y, len));
*start_index += len;
}
#[test]
fn ga401_diagonal_packet_check() {
let pkt0_check = [
0x5e, 0xc0, 0x2, 0x1, 0x0, 0x73, 0x2, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0xff, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0xff, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff,
0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0,
];
let pkt1_check = [
0x5e, 0xc0, 0x2, 0x74, 0x2, 0x73, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
];
let b = &mut buf;
let a = &self;
copy_slice(b, a, 0, 4, &mut start_index, 38);
copy_slice(b, a, 0, 3, &mut start_index, 39);
copy_slice(b, a, 1, 3, &mut start_index, 38);
copy_slice(b, a, 1, 2, &mut start_index, 39);
copy_slice(b, a, 2, 2, &mut start_index, 38);
copy_slice(b, a, 2, 1, &mut start_index, 39);
copy_slice(b, a, 3, 1, &mut start_index, 38);
copy_slice(b, a, 3, 0, &mut start_index, 39);
copy_slice(b, a, 4, 0, &mut start_index, 39);
copy_slice(b, a, 5, 0, &mut start_index, 39);
copy_slice(b, a, 6, 0, &mut start_index, 38);
copy_slice(b, a, 7, 0, &mut start_index, 38);
copy_slice(b, a, 8, 0, &mut start_index, 37);
copy_slice(b, a, 9, 0, &mut start_index, 37);
copy_slice(b, a, 10, 0, &mut start_index, 36);
copy_slice(b, a, 11, 0, &mut start_index, 36);
copy_slice(b, a, 12, 0, &mut start_index, 35);
copy_slice(b, a, 13, 0, &mut start_index, 35);
copy_slice(b, a, 14, 0, &mut start_index, 34);
copy_slice(b, a, 15, 0, &mut start_index, 34);
copy_slice(b, a, 16, 0, &mut start_index, 33);
copy_slice(b, a, 17, 0, &mut start_index, 33);
copy_slice(b, a, 18, 0, &mut start_index, 32);
copy_slice(b, a, 19, 0, &mut start_index, 32);
copy_slice(b, a, 20, 0, &mut start_index, 31);
copy_slice(b, a, 21, 0, &mut start_index, 31);
copy_slice(b, a, 22, 0, &mut start_index, 30);
copy_slice(b, a, 23, 0, &mut start_index, 30);
copy_slice(b, a, 24, 0, &mut start_index, 29);
copy_slice(b, a, 25, 0, &mut start_index, 29);
copy_slice(b, a, 26, 0, &mut start_index, 28);
copy_slice(b, a, 27, 0, &mut start_index, 28);
copy_slice(b, a, 28, 0, &mut start_index, 27);
copy_slice(b, a, 29, 0, &mut start_index, 27);
copy_slice(b, a, 30, 0, &mut start_index, 26);
copy_slice(b, a, 31, 0, &mut start_index, 26);
copy_slice(b, a, 32, 0, &mut start_index, 25);
copy_slice(b, a, 33, 0, &mut start_index, 25);
copy_slice(b, a, 34, 0, &mut start_index, 24);
copy_slice(b, a, 35, 0, &mut start_index, 24);
copy_slice(b, a, 36, 0, &mut start_index, 23);
copy_slice(b, a, 37, 0, &mut start_index, 23);
copy_slice(b, a, 38, 0, &mut start_index, 22);
copy_slice(b, a, 39, 0, &mut start_index, 22);
copy_slice(b, a, 40, 0, &mut start_index, 21);
copy_slice(b, a, 41, 0, &mut start_index, 21);
copy_slice(b, a, 42, 0, &mut start_index, 20);
copy_slice(b, a, 43, 0, &mut start_index, 20);
copy_slice(b, a, 44, 0, &mut start_index, 19);
copy_slice(b, a, 45, 0, &mut start_index, 19);
copy_slice(b, a, 46, 0, &mut start_index, 18);
copy_slice(b, a, 47, 0, &mut start_index, 18);
copy_slice(b, a, 48, 0, &mut start_index, 17);
copy_slice(b, a, 49, 0, &mut start_index, 17);
copy_slice(b, a, 50, 0, &mut start_index, 16);
copy_slice(b, a, 51, 0, &mut start_index, 16);
copy_slice(b, a, 52, 0, &mut start_index, 15);
copy_slice(b, a, 53, 0, &mut start_index, 15);
copy_slice(b, a, 54, 0, &mut start_index, 14);
copy_slice(b, a, 55, 0, &mut start_index, 14);
copy_slice(b, a, 56, 0, &mut start_index, 13);
copy_slice(b, a, 57, 0, &mut start_index, 13);
copy_slice(b, a, 58, 0, &mut start_index, 12);
let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
path.push("test/ga401-diagonal.png");
let matrix = AnimeDiagonal::from_png(&path, None, 255.0, AnimeType::GA401).unwrap();
let data = matrix.into_data_buffer(crate::AnimeType::GA401).unwrap();
let pkt = AnimePacketType::try_from(data).unwrap();
assert_eq!(pkt[0], pkt0_check);
assert_eq!(pkt[1], pkt1_check);
}
#[test]
fn ga402_diagonal_packet_check() {
let pkt0_check = [
0x5e, 0xc0, 0x2, 0x1, 0x0, 0x73, 0x2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0,
];
let pkt1_check = [
0x5e, 0xc0, 0x2, 0x74, 0x2, 0x73, 0x2, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
];
let pkt2_check = [
0x5e, 0xc0, 0x2, 0xe7, 0x4, 0x73, 0x2, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff,
0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff,
0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
];
let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
path.push("test/ga402-diagonal.png");
let matrix = AnimeDiagonal::from_png(&path, None, 255.0, AnimeType::GA402).unwrap();
let data = matrix.into_data_buffer(crate::AnimeType::GA402).unwrap();
let pkt = AnimePacketType::try_from(data).unwrap();
assert_eq!(pkt[0], pkt0_check);
assert_eq!(pkt[1], pkt1_check);
assert_eq!(pkt[2], pkt2_check);
}
#[test]
#[ignore = "Needs the packets verified with capture"]
fn ga402_diagonal_fullbright_packet_check() {
let pkt0_check = [
0x5e, 0xc0, 0x2, 0x1, 0x0, 0x73, 0x2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x68, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x67, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
];
let pkt1_check = [
0x5e, 0xc0, 0x2, 0x74, 0x2, 0x73, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
];
let pkt2_check = [
0x5e, 0xc0, 0x2, 0xe7, 0x4, 0x73, 0x2, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
];
let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
path.push("test/ga402-diagonal-fullbright.png");
let matrix = AnimeDiagonal::from_png(&path, None, 255.0, AnimeType::GA402).unwrap();
let data = matrix.into_data_buffer(crate::AnimeType::GA402).unwrap();
let pkt = AnimePacketType::try_from(data).unwrap();
assert_eq!(pkt[0], pkt0_check);
assert_eq!(pkt[1], pkt1_check);
assert_eq!(pkt[2], pkt2_check);
AnimeDataBuffer::from_vec(crate::AnimeType::GA402, buf)
}
}
+2
View File
@@ -24,12 +24,14 @@ pub enum AnimeError {
DataBufferLength,
PixelGifWidth(usize),
PixelGifHeight(usize),
ParseError(String),
}
impl fmt::Display for AnimeError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AnimeError::ParseError(e) => write!(f, "Could not parse {e}"),
AnimeError::NoFrames => write!(f, "No frames in PNG"),
AnimeError::Io(e) => write!(f, "Could not open: {}", e),
AnimeError::Png(e) => write!(f, "PNG error: {}", e),
+4 -5
View File
@@ -110,13 +110,12 @@ impl AnimeGif {
let file = File::open(file_name)?;
let mut decoder = decoder.read_info(file)?;
let mut frames = Vec::with_capacity(decoder.buffer_size());
let mut frames = Vec::default();
while let Some(frame) = decoder.read_next_frame()? {
let wait = frame.delay * 10;
if matches!(frame.dispose, gif::DisposalMethod::Background) {
frames = Vec::new();
}
// if matches!(frame.dispose, gif::DisposalMethod::Background) {
// frames = Vec::new();
// }
for (y, row) in frame.buffer.chunks(frame.width as usize * 4).enumerate() {
for (x, px) in row.chunks(4).enumerate() {
if px[3] != 255 {
+41 -157
View File
@@ -10,7 +10,7 @@ use crate::AnimeType;
/// A single greyscale + alpha pixel in the image
#[derive(Copy, Clone, Debug)]
pub(crate) struct Pixel {
pub struct Pixel {
pub color: u32,
pub alpha: f32,
}
@@ -79,7 +79,8 @@ pub struct AnimeImage {
}
impl AnimeImage {
pub(crate) fn new(
/// Exposed only for tests. Please use `from_png()` instead.
pub fn new(
scale: Vec2,
angle: f32,
translation: Vec2,
@@ -114,25 +115,29 @@ impl AnimeImage {
///
/// For GA401 this is `26.8 / (33 + 0.5) = 0.8`
/// For GA402 this is `27.4 / (35 + 0.5) = 0.77`
/// For GA402 this is `30.9 / (39 + 0.5) = 0.77`
fn scale_x(anime_type: AnimeType) -> f32 {
match anime_type {
AnimeType::GA401 => 0.8,
AnimeType::GA402 => 0.77,
AnimeType::GU604 => 0.78,
_ => 0.77,
}
}
/// Scale ratio in CM
///
/// This is worked out by measuring the physical height of the display from
/// pixel center to pixel center, then dividing by `<vertical LED
/// count> + 1.0`, where the LED count is first/longest row.
/// pixel center to pixel center, then dividing by 10 divided `<vertical
/// LED count> + 1.0`, where the LED count is first/longest row.
///
/// For GA401 this is `16.5 / (54.0 + 1.0) = 0.3`
/// For GA402 this is `17.3 / (61.0) = 0.283`
/// For GU604 this is `17.7 / (62.0 + 1) = 0.28`
fn scale_y(anime_type: AnimeType) -> f32 {
match anime_type {
AnimeType::GA401 => 0.3,
AnimeType::GA402 => 0.283,
AnimeType::GU604 => 0.28,
_ => 0.283,
}
}
@@ -141,7 +146,9 @@ impl AnimeImage {
///
/// In relation to the display itself you should think of it as a full
/// square grid, so `first_x` is the x position on that grid where the
/// LED is actually positioned in relation to the Y. ```text
/// LED is actually positioned in relation to the Y.
///
/// ```text
/// +------------+
/// | |
/// | |
@@ -163,7 +170,15 @@ impl AnimeImage {
}
(y + 1) / 2 - 3
}
AnimeType::GA402 => {
AnimeType::GU604 => {
// first 9 rows start at zero
if y <= 9 {
return 0;
}
// and then their offset grows by one every two rows
(y - 9) / 2
}
_ => {
// first 11 rows start at zero
if y <= 11 {
return 0;
@@ -189,6 +204,7 @@ impl AnimeImage {
/// \ |
/// ------+
/// ```
// TODO: make this return only width, and move calcs to pitch
fn width(anime_type: AnimeType, y: u32) -> u32 {
match anime_type {
AnimeType::GA401 => {
@@ -198,7 +214,13 @@ impl AnimeImage {
}
36 - (y + 1) / 2
}
AnimeType::GA402 => {
AnimeType::GU604 => {
if y <= 9 {
return 38 + y % 2;
}
38 - Self::first_x(anime_type, y) + y % 2
}
_ => {
if y <= 11 {
return 34;
}
@@ -212,7 +234,9 @@ impl AnimeImage {
match anime_type {
// 33.0 = Longest row LED count (physical) plus half-pixel offset
AnimeType::GA401 => (33.0 + 0.5) * Self::scale_x(anime_type),
AnimeType::GA402 => (35.0 + 0.5) * Self::scale_x(anime_type),
AnimeType::GU604 => (38.0 + 0.5) * Self::scale_x(anime_type),
_ => (35.0 + 0.5) * Self::scale_x(anime_type),
}
}
@@ -220,7 +244,8 @@ impl AnimeImage {
fn height(anime_type: AnimeType) -> u32 {
match anime_type {
AnimeType::GA401 => 55,
AnimeType::GA402 => 61,
AnimeType::GU604 => 62,
_ => 61,
}
}
@@ -229,8 +254,9 @@ impl AnimeImage {
match anime_type {
// 54.0 = End column LED count (physical) plus one dead pixel
AnimeType::GA401 => (54.0 + 1.0) * Self::scale_y(anime_type),
AnimeType::GU604 => 62.0 * Self::scale_y(anime_type),
// GA402 may not have dead pixels and require only the physical LED count
AnimeType::GA402 => 61.0 * Self::scale_y(anime_type),
_ => 61.0 * Self::scale_y(anime_type),
}
}
@@ -242,8 +268,9 @@ impl AnimeImage {
1 | 3 => 35, // Some rows are padded
_ => 36 - y / 2,
},
AnimeType::GU604 => AnimeImage::width(anime_type, y),
// GA402 does not have padding, equivalent to width
AnimeType::GA402 => AnimeImage::width(anime_type, y),
_ => AnimeImage::width(anime_type, y),
}
}
@@ -317,7 +344,7 @@ impl AnimeImage {
}
/// A helper for determining physical position alignment
fn _edge_outline(&mut self) {
pub fn edge_outline(&mut self) {
// Janky shit here just to try help align images
let mut last_x = 0.0;
let mut last_y = 0.0;
@@ -607,149 +634,6 @@ mod tests {
assert_eq!(AnimeImage::pitch(a, 14), 29);
}
#[test]
fn ga402_image_edge_packet_check() {
let pkt0_check = [
0x5e, 0xc0, 0x2, 0x1, 0x0, 0x73, 0x2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0,
];
let pkt1_check = [
0x5e, 0xc0, 0x2, 0x74, 0x2, 0x73, 0x2, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
];
let pkt2_check = [
0x5e, 0xc0, 0x2, 0xe7, 0x4, 0x73, 0x2, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff,
0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff,
0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
];
let mut matrix = AnimeImage::new(
Vec2::new(1.0, 1.0),
0.0,
Vec2::default(),
0.0,
vec![Pixel::default(); 1000],
100,
AnimeType::GA402,
)
.unwrap();
matrix._edge_outline();
let data = AnimeDataBuffer::try_from(&matrix).unwrap();
let pkt = AnimePacketType::try_from(data).unwrap();
assert_eq!(pkt[0], pkt0_check);
assert_eq!(pkt[1], pkt1_check);
assert_eq!(pkt[2], pkt2_check);
}
#[test]
#[ignore = "Just to inspect image packet"]
fn ga402_image_packet_check() {
+166 -25
View File
@@ -8,17 +8,136 @@
//!
//! Step 1 need to applied only on fresh system boot.
use std::str::FromStr;
use serde_derive::{Deserialize, Serialize};
#[cfg(feature = "dbus")]
use zbus::zvariant::Type;
use crate::error::AnimeError;
use crate::AnimeType;
const INIT_STR: [u8; 15] = [
0x5e, b'A', b'S', b'U', b'S', b' ', b'T', b'e', b'c', b'h', b'.', b'I', b'n', b'c', b'.',
];
const PACKET_SIZE: usize = 640;
const DEV_PAGE: u8 = 0x5e;
pub const VENDOR_ID: u16 = 0x0b05;
pub const PROD_ID: u16 = 0x193b;
#[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Debug, Default, PartialEq, Eq, Copy, Clone, Deserialize, Serialize)]
/// Base LED brightness of the display
pub enum Brightness {
Off,
Low,
#[default]
Med,
High,
}
impl FromStr for Brightness {
type Err = AnimeError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
"Off" | "off" => Brightness::Off,
"Low" | "low" => Brightness::Low,
"Med" | "med" => Brightness::Med,
"High" | "high" => Brightness::High,
_ => Brightness::Med,
})
}
}
impl From<u8> for Brightness {
fn from(v: u8) -> Brightness {
match v {
0 => Brightness::Off,
2 => Brightness::Low,
3 => Brightness::High,
_ => Brightness::Med,
}
}
}
#[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Debug, Default, PartialEq, Eq, Copy, Clone, Deserialize, Serialize)]
pub enum AnimBooting {
#[default]
GlitchConstruction,
StaticEmergence,
}
impl FromStr for AnimBooting {
type Err = AnimeError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"GlitchConstruction" => Ok(Self::GlitchConstruction),
"StaticEmergence" => Ok(Self::StaticEmergence),
_ => Err(AnimeError::ParseError(s.to_owned())),
}
}
}
#[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Debug, Default, PartialEq, Eq, Copy, Clone, Deserialize, Serialize)]
pub enum AnimAwake {
#[default]
BinaryBannerScroll,
RogLogoGlitch,
}
impl FromStr for AnimAwake {
type Err = AnimeError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"BinaryBannerScroll" => Ok(Self::BinaryBannerScroll),
"RogLogoGlitch" => Ok(Self::RogLogoGlitch),
_ => Err(AnimeError::ParseError(s.to_owned())),
}
}
}
#[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Debug, Default, PartialEq, Eq, Copy, Clone, Deserialize, Serialize)]
pub enum AnimSleeping {
#[default]
BannerSwipe,
Starfield,
}
impl FromStr for AnimSleeping {
type Err = AnimeError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"BannerSwipe" => Ok(Self::BannerSwipe),
"Starfield" => Ok(Self::Starfield),
_ => Err(AnimeError::ParseError(s.to_owned())),
}
}
}
#[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Debug, Default, PartialEq, Eq, Copy, Clone, Deserialize, Serialize)]
pub enum AnimShutdown {
#[default]
GlitchOut,
SeeYa,
}
impl FromStr for AnimShutdown {
type Err = AnimeError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"GlitchOut" => Ok(Self::GlitchOut),
"SeeYa" => Ok(Self::SeeYa),
_ => Err(AnimeError::ParseError(s.to_owned())),
}
}
}
/// `get_anime_type` is very broad, matching on part of the laptop board name
/// only. For this reason `find_node()` must be used also to verify if the USB
/// device is available.
@@ -33,8 +152,11 @@ pub fn get_anime_type() -> Result<AnimeType, AnimeError> {
return Ok(AnimeType::GA401);
} else if board_name.contains("GA402R") {
return Ok(AnimeType::GA402);
} else if board_name.contains("GU604V") {
return Ok(AnimeType::GU604);
}
Err(AnimeError::UnsupportedDevice)
log::warn!("AniMe Matrix device found but not yet supported, will default to a GA402 layout");
Ok(AnimeType::Unknown)
}
/// Get the two device initialization packets. These are required for device
@@ -44,12 +166,14 @@ pub const fn pkts_for_init() -> [[u8; PACKET_SIZE]; 2] {
let mut packets = [[0; PACKET_SIZE]; 2];
packets[0][0] = DEV_PAGE; // This is the USB page we're using throughout
let mut count = 0;
while count < INIT_STR.len() {
packets[0][count] = INIT_STR[count];
// TODO: memcpy or slice copy
let bytes = "ASUS Tech.Inc.".as_bytes();
while count < bytes.len() {
packets[0][count + 1] = bytes[count];
count += 1;
}
//
packets[1][0] = DEV_PAGE; // write it to be sure?
packets[1][0] = DEV_PAGE;
packets[1][1] = 0xc2;
packets
}
@@ -57,7 +181,7 @@ pub const fn pkts_for_init() -> [[u8; PACKET_SIZE]; 2] {
/// Should be written to the device after writing the two main data packets that
/// make up the display data packet
#[inline]
pub const fn pkt_for_flush() -> [u8; PACKET_SIZE] {
pub const fn pkt_flush() -> [u8; PACKET_SIZE] {
let mut pkt = [0; PACKET_SIZE];
pkt[0] = DEV_PAGE;
pkt[1] = 0xc0;
@@ -65,10 +189,21 @@ pub const fn pkt_for_flush() -> [u8; PACKET_SIZE] {
pkt
}
/// Get the packet required for setting the device to on, on boot. Requires
/// Packet for setting the brightness (0-3). Requires
/// `pkt_for_apply()` to be written after.
#[inline]
pub const fn pkt_for_set_boot(status: bool) -> [u8; PACKET_SIZE] {
pub const fn pkt_set_brightness(brightness: Brightness) -> [u8; PACKET_SIZE] {
let mut pkt = [0; PACKET_SIZE];
pkt[0] = DEV_PAGE;
pkt[1] = 0xc0;
pkt[2] = 0x04;
pkt[3] = brightness as u8;
pkt
}
/// Enable the display?
#[inline]
pub const fn pkt_set_enable_display(status: bool) -> [u8; PACKET_SIZE] {
let mut pkt = [0; PACKET_SIZE];
pkt[0] = DEV_PAGE;
pkt[1] = 0xc3;
@@ -77,25 +212,31 @@ pub const fn pkt_for_set_boot(status: bool) -> [u8; PACKET_SIZE] {
pkt
}
/// Get the packet required for setting the device to on. Requires
/// `pkt_for_apply()` to be written after.
/// Enable builtin animations?
#[inline]
pub const fn pkt_for_set_on(on: bool) -> [u8; PACKET_SIZE] {
let mut pkt = [0; PACKET_SIZE];
pkt[0] = DEV_PAGE;
pkt[1] = 0xc0;
pkt[2] = 0x04;
pkt[3] = if on { 0x03 } else { 0x00 };
pkt
}
/// Packet required to apply a device setting
#[inline]
pub const fn pkt_for_apply() -> [u8; PACKET_SIZE] {
pub const fn pkt_set_enable_powersave_anim(status: bool) -> [u8; PACKET_SIZE] {
let mut pkt = [0; PACKET_SIZE];
pkt[0] = DEV_PAGE;
pkt[1] = 0xc4;
pkt[2] = 0x01;
pkt[3] = 0x80;
pkt[3] = if status { 0x00 } else { 0x80 };
pkt
}
/// Set which animations are shown for each stage
#[inline]
pub const fn pkt_set_builtin_animations(
boot: AnimBooting,
awake: AnimAwake,
sleep: AnimSleeping,
shutdown: AnimShutdown,
) -> [u8; PACKET_SIZE] {
let mut pkt = [0; PACKET_SIZE];
pkt[0] = DEV_PAGE;
pkt[1] = 0xc5;
pkt[2] = (awake as u8)
| ((sleep as u8) << 0x01)
| ((shutdown as u8) << 0x02)
| ((boot as u8) << 0x03);
pkt
}

Before

Width:  |  Height:  |  Size: 981 B

After

Width:  |  Height:  |  Size: 981 B

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

Before

Width:  |  Height:  |  Size: 189 B

After

Width:  |  Height:  |  Size: 189 B

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 761 B

+239
View File
@@ -0,0 +1,239 @@
#[cfg(test)]
mod tests {
use std::path::PathBuf;
use rog_anime::*;
#[test]
fn ga401_image_edge_packet_check() {
let pkt0_check = [
0x5e, 0xc0, 0x02, 0x01, 0x00, 0x73, 0x02, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let pkt1_check = [
0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let mut matrix = AnimeImage::new(
Vec2::new(1.0, 1.0),
0.0,
Vec2::default(),
0.0,
vec![Pixel::default(); 1000],
100,
AnimeType::GA401,
)
.unwrap();
matrix.edge_outline();
let data = AnimeDataBuffer::try_from(&matrix).unwrap();
let pkt = AnimePacketType::try_from(data).unwrap();
// print!("left: '[");
// for b in pkt[1] {
// print!("{b:#02x},");
// }
// print!("]'");
assert_eq!(pkt[0], pkt0_check);
assert_eq!(pkt[1], pkt1_check);
}
#[test]
fn ga401_diagonal_packet_check() {
let pkt0_check = [
0x5e, 0xc0, 0x02, 0x1, 0x00, 0x73, 0x02, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let pkt1_check = [
0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
path.push("tests/data/ga401-diagonal.png");
let matrix = AnimeDiagonal::from_png(&path, None, 255.0, AnimeType::GA401).unwrap();
let data = matrix.into_data_buffer(AnimeType::GA401).unwrap();
let pkt = AnimePacketType::try_from(data).unwrap();
assert_eq!(pkt[0], pkt0_check);
assert_eq!(pkt[1], pkt1_check);
}
}
+491
View File
@@ -0,0 +1,491 @@
#[cfg(test)]
mod tests {
use std::path::PathBuf;
use rog_anime::*;
#[test]
fn ga402_image_edge_packet_check() {
let pkt0_check = [
0x5e, 0xc0, 0x2, 0x1, 0x00, 0x73, 0x2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let pkt1_check = [
0x5e, 0xc0, 0x2, 0x74, 0x2, 0x73, 0x2, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let pkt2_check = [
0x5e, 0xc0, 0x2, 0xe7, 0x4, 0x73, 0x2, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let mut matrix = AnimeImage::new(
Vec2::new(1.0, 1.0),
0.0,
Vec2::default(),
0.0,
vec![Pixel::default(); 1000],
100,
AnimeType::GA402,
)
.unwrap();
matrix.edge_outline();
let data = AnimeDataBuffer::try_from(&matrix).unwrap();
let pkt = AnimePacketType::try_from(data).unwrap();
assert_eq!(pkt[0], pkt0_check);
assert_eq!(pkt[1], pkt1_check);
assert_eq!(pkt[2], pkt2_check);
}
#[test]
fn ga402_diagonal_packet_check() {
let pkt0_check = [
0x5e, 0xc0, 0x02, 0x1, 0x00, 0x73, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let pkt1_check = [
0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let pkt2_check = [
0x5e, 0xc0, 0x02, 0xe7, 0x04, 0x73, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
path.push("tests/data/ga402-diagonal.png");
let matrix = AnimeDiagonal::from_png(&path, None, 255.0, AnimeType::GA402).unwrap();
let data = matrix.into_data_buffer(AnimeType::GA402).unwrap();
let pkt = AnimePacketType::try_from(data).unwrap();
assert_eq!(pkt[0], pkt0_check);
assert_eq!(pkt[1], pkt1_check);
assert_eq!(pkt[2], pkt2_check);
}
#[test]
#[ignore = "Needs the packets verified with capture"]
fn ga402_diagonal_fullbright_packet_check() {
let pkt0_check = [
0x5e, 0xc0, 0x02, 0x1, 0x00, 0x73, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x67, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let pkt1_check = [
0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let pkt2_check = [
0x5e, 0xc0, 0x02, 0xe7, 0x04, 0x73, 0x02, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
path.push("tests/data/ga402-diagonal-fullbright.png");
let matrix = AnimeDiagonal::from_png(&path, None, 255.0, AnimeType::GA402).unwrap();
let data = matrix.into_data_buffer(AnimeType::GA402).unwrap();
let pkt = AnimePacketType::try_from(data).unwrap();
assert_eq!(pkt[0], pkt0_check);
assert_eq!(pkt[1], pkt1_check);
assert_eq!(pkt[2], pkt2_check);
}
}
+331
View File
@@ -0,0 +1,331 @@
#[cfg(test)]
mod tests {
use std::path::PathBuf;
use rog_anime::*;
#[test]
fn gu604_image_edge_packet_check() {
let pkt0_check = [
0x5e, 0xc0, 0x02, 0x01, 0x00, 0x73, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let pkt1_check = [
0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let pkt2_check = [
0x5e, 0xc0, 0x02, 0xe7, 0x04, 0x73, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let mut matrix = AnimeImage::new(
Vec2::new(1.0, 1.0),
0.0,
Vec2::default(),
0.0,
vec![Pixel::default(); 1000],
100,
AnimeType::GU604,
)
.unwrap();
matrix.edge_outline();
let data = AnimeDataBuffer::try_from(&matrix).unwrap();
let pkt = AnimePacketType::try_from(data).unwrap();
assert_eq!(pkt[0], pkt0_check);
assert_eq!(pkt[1], pkt1_check);
assert_eq!(pkt[2], pkt2_check);
}
#[test]
fn gu604_diagonal_edge_packet_check() {
let pkt0_check = [
0x5e, 0xc0, 0x02, 0x01, 0x00, 0x73, 0x02, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let pkt1_check = [
0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let pkt2_check = [
0x5e, 0xc0, 0x02, 0xe7, 0x04, 0x73, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
path.push("tests/data/gu604-diagonal.png");
let matrix = AnimeDiagonal::from_png(&path, None, 255.0, AnimeType::GU604).unwrap();
let data = matrix.into_data_buffer(AnimeType::GU604).unwrap();
let pkt = AnimePacketType::try_from(data).unwrap();
assert_eq!(pkt[0], pkt0_check);
assert_eq!(pkt[1], pkt1_check);
assert_eq!(pkt[2], pkt2_check);
}
}
+4 -1
View File
@@ -27,4 +27,7 @@ log.workspace = true
# Device control
sysfs-class.workspace = true # used for backlight control and baord ID
ron = { version = "*", optional = true }
ron = { version = "*", optional = true }
[dev-dependencies]
cargo-husky.workspace = true
+125 -27
View File
@@ -28,12 +28,33 @@
advanced_type: None,
),
(
board_name: "FX506HC",
board_name: "FX506H",
layout_name: "fa506i",
basic_modes: [Static, Breathe, Strobe, Pulse],
basic_zones: [],
advanced_type: None,
),
(
board_name: "FX506L",
layout_name: "fa506i",
basic_modes: [Static, Breathe, Strobe, Pulse],
basic_zones: [],
advanced_type: None,
),
(
board_name: "FX507Z",
layout_name: "fa506i",
basic_modes: [Static, Breathe, Strobe, Pulse],
basic_zones: [],
advanced_type: None,
),
(
board_name: "FX516P",
layout_name: "fa506i",
basic_modes: [Static, Breathe, Strobe],
basic_zones: [],
advanced_type: None,
),
(
board_name: "G512",
layout_name: "g512",
@@ -41,13 +62,6 @@
basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None,
),
(
board_name: "G512LI",
layout_name: "gl503",
basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse],
basic_zones: [],
advanced_type: None,
),
(
board_name: "G512LV",
layout_name: "ga401q",
@@ -56,25 +70,11 @@
advanced_type: None,
),
(
board_name: "G513IC",
layout_name: "g513i",
basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse],
basic_zones: [],
advanced_type: Zoned([ZonedKbLeft, ZonedKbLeftMid, ZonedKbRightMid, ZonedKbRight, LightbarRight, LightbarRightCorner, LightbarRightBottom, LightbarLeftBottom, LightbarLeftCorner, LightbarLeft]),
),
(
board_name: "G513IH",
board_name: "G513I",
layout_name: "g513i",
basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse],
basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None,
),
(
board_name: "G513IM",
layout_name: "g513i-per-key",
basic_modes: [Flash, Static, Breathe, Strobe, Rainbow],
basic_zones: [],
advanced_type: PerKey,
advanced_type: Zoned([ZonedKbLeft, ZonedKbLeftMid, ZonedKbRightMid, ZonedKbRight, LightbarRight, LightbarRightCorner, LightbarRightBottom, LightbarLeftBottom, LightbarLeftCorner, LightbarLeft]),
),
(
board_name: "G513QE",
@@ -99,10 +99,10 @@
),
(
board_name: "G513QY",
layout_name: "g513i",
layout_name: "g513i-per-key",
basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse],
basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None,
advanced_type: PerKey,
),
(
board_name: "G513RC",
@@ -181,6 +181,20 @@
basic_zones: [],
advanced_type: PerKey,
),
(
board_name: "G533Z",
layout_name: "g533q-per-key",
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
basic_zones: [],
advanced_type: PerKey,
),
(
board_name: "G634J",
layout_name: "g634j-per-key",
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
basic_zones: [],
advanced_type: PerKey,
),
(
board_name: "G712LI",
layout_name: "gl503",
@@ -279,6 +293,13 @@
basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None,
),
(
board_name: "G733C",
layout_name: "g513i-per-key",
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
basic_zones: [Logo, BarLeft, BarRight],
advanced_type: PerKey,
),
(
board_name: "G733Q",
layout_name: "gx502",
@@ -286,6 +307,20 @@
basic_zones: [],
advanced_type: PerKey,
),
(
board_name: "G733Z",
layout_name: "g513i-per-key",
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
basic_zones: [],
advanced_type: PerKey,
),
(
board_name: "GA401Q",
layout_name: "ga401q",
basic_modes: [Static, Breathe, Pulse],
basic_zones: [],
advanced_type: None,
),
(
board_name: "GA402R",
layout_name: "ga401q",
@@ -314,6 +349,20 @@
basic_zones: [],
advanced_type: None,
),
(
board_name: "GL503",
layout_name: "gl503",
basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse],
basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None,
),
(
board_name: "GL503V",
layout_name: "gl503",
basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse],
basic_zones: [Key1, Key2, Key3, Key4],
advanced_type: None,
),
(
board_name: "GL504G",
layout_name: "gl503",
@@ -391,6 +440,13 @@
basic_zones: [],
advanced_type: Zoned([SingleZone]),
),
(
board_name: "GU604V",
layout_name: "ga401q",
basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse],
basic_zones: [],
advanced_type: Zoned([SingleZone]),
),
(
board_name: "GV301Q",
layout_name: "ga401q",
@@ -398,6 +454,20 @@
basic_zones: [],
advanced_type: None,
),
(
board_name: "GV301V",
layout_name: "ga401q",
basic_modes: [Static, Breathe, Pulse],
basic_zones: [],
advanced_type: None,
),
(
board_name: "GV301VIC",
layout_name: "ga401q",
basic_modes: [Static, Breathe, Pulse],
basic_zones: [],
advanced_type: None,
),
(
board_name: "GV601R",
layout_name: "ga401q",
@@ -405,6 +475,20 @@
basic_zones: [],
advanced_type: None,
),
(
board_name: "GV601VI",
layout_name: "ga401q",
basic_modes: [Static, Breathe, Pulse, Strobe],
basic_zones: [],
advanced_type: None,
),
(
board_name: "GV604V",
layout_name: "ga401q",
basic_modes: [Static, Breathe, Strobe, Pulse],
basic_zones: [],
advanced_type: None,
),
(
board_name: "GX502",
layout_name: "gx502",
@@ -433,6 +517,13 @@
basic_zones: [],
advanced_type: PerKey,
),
(
board_name: "GX650P",
layout_name: "gx531-per-key",
basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
basic_zones: [],
advanced_type: PerKey,
),
(
board_name: "GX701",
layout_name: "gx531-per-key",
@@ -448,7 +539,14 @@
advanced_type: None,
),
(
board_name: "ga401qQ",
board_name: "GZ301V",
layout_name: "ga401q",
basic_modes: [Static, Breathe, Pulse],
basic_zones: [],
advanced_type: None,
),
(
board_name: "GZ301VIC",
layout_name: "ga401q",
basic_modes: [Static, Breathe, Pulse],
basic_zones: [],
+366
View File
@@ -0,0 +1,366 @@
(
locale: "US",
key_shapes: {
"regular": Led(
width: 1.0,
height: 1.0,
pad_left: 0.1,
pad_right: 0.1,
pad_top: 0.1,
pad_bottom: 0.1,
),
"regular_spacing": Blank(
width: 1.2,
height: 0.0,
),
"rog_row": Led(
width: 1.0,
height: 0.7,
pad_left: 0.1,
pad_right: 0.1,
pad_top: 0.1,
pad_bottom: 0.6,
),
"rog_row_blocking": Blank(
width: 1.2,
height: 0.0,
),
"func_space": Blank(
width: 0.6,
height: 0.0,
),
"backspace": Led(
width: 2.2,
height: 1.0,
pad_left: 0.1,
pad_right: 0.1,
pad_top: 0.1,
pad_bottom: 0.1,
),
"tab": Led(
width: 1.6,
height: 1.0,
pad_left: 0.1,
pad_right: 0.1,
pad_top: 0.1,
pad_bottom: 0.1,
),
"tab": Led(
width: 1.6,
height: 1.0,
pad_left: 0.1,
pad_right: 0.1,
pad_top: 0.1,
pad_bottom: 0.1,
),
"backslash": Led(
width: 1.6,
height: 1.0,
pad_left: 0.1,
pad_right: 0.1,
pad_top: 0.1,
pad_bottom: 0.1,
),
"capsplonk": Led(
width: 2.0,
height: 1.0,
pad_left: 0.1,
pad_right: 0.1,
pad_top: 0.1,
pad_bottom: 0.1,
),
"return": Led(
width: 2.4,
height: 1.0,
pad_left: 0.1,
pad_right: 0.1,
pad_top: 0.1,
pad_bottom: 0.1,
),
"lshift": Led(
width: 2.6,
height: 1.0,
pad_left: 0.1,
pad_right: 0.1,
pad_top: 0.1,
pad_bottom: 0.1,
),
"rshift": Led(
width: 3.0,
height: 1.0,
pad_left: 0.1,
pad_right: 0.1,
pad_top: 0.1,
pad_bottom: 0.1,
),
"lctrl": Led(
width: 1.4,
height: 1.0,
pad_left: 0.1,
pad_right: 0.1,
pad_top: 0.1,
pad_bottom: 0.1,
),
"spacebar": Led(
width: 5.8,
height: 1.0,
pad_left: 0.1,
pad_right: 0.1,
pad_top: 0.1,
pad_bottom: 0.1,
),
"rctrl": Led(
width: 1.2,
height: 1.0,
pad_left: 0.1,
pad_right: 0.1,
pad_top: 0.1,
pad_bottom: 0.1,
),
"up_arrow": Led(
width: 0.8,
height: 0.8,
pad_left: 1.1,
pad_right: 1.1,
pad_top: 0.1,
pad_bottom: 0.1,
),
"arrows_spacer": Blank(
width: 15.0,
height: 0.0,
),
"arrows": Led(
width: 0.8,
height: 0.8,
pad_left: 0.1,
pad_right: 0.1,
pad_top: -0.1,
pad_bottom: 0.1,
),
"row_end_spacing": Blank(
width: 0.4,
height: 0.0,
),
"lightbar_left": Led(
width: 0.4,
height: 3.0,
pad_left: -1.0,
pad_right: 0.1,
pad_top: -2.7,
pad_bottom: 0.1,
),
"lightbar_corner_left": Led(
width: 0.4,
height: 0.4,
pad_left: -0.5,
pad_right: 0.1,
pad_top: 0.5,
pad_bottom: 0.1,
),
"lightbar_bottom": Led(
width: 10.1,
height: 0.4,
pad_left: 0.1,
pad_right: 0.1,
pad_top: 0.5,
pad_bottom: 0.1,
),
"lightbar_corner_right": Led(
width: 0.4,
height: 0.4,
pad_left: 0.1,
pad_right: 0.1,
pad_top: 0.5,
pad_bottom: 0.1,
),
"lightbar_right": Led(
width: 0.4,
height: 3.0,
pad_left: -0.5,
pad_right: 0.1,
pad_top: -2.7,
pad_bottom: 0.1,
),
},
key_rows: [
(
pad_left: 0.1,
pad_right: 0.1,
pad_top: 0.1,
pad_bottom: 0.1,
row: [
(Blocking, "rog_row_blocking"),
(Blocking, "rog_row_blocking"),
(VolDown, "rog_row"),
(VolUp, "rog_row"),
(MicMute, "rog_row"),
(RogFan, "rog_row"),
(RogApp, "rog_row"),
],
),
(
pad_left: 0.1,
pad_right: 0.1,
pad_top: 0.1,
pad_bottom: 0.1,
row: [
(Esc, "regular"),
(Spacing, "regular_spacing"),
(F1, "regular"),
(F2, "regular"),
(F3, "regular"),
(F4, "regular"),
(Spacing, "func_space"),
(F5, "regular"),
(F6, "regular"),
(F7, "regular"),
(F8, "regular"),
(Spacing, "func_space"),
(F9, "regular"),
(F10, "regular"),
(F11, "regular"),
(F12, "regular"),
(Spacing, "row_end_spacing"),
(Del, "regular"), // Should be super/insert
],
),
(
pad_left: 0.1,
pad_right: 0.1,
pad_top: 0.1,
pad_bottom: 0.1,
row: [
(Tilde, "regular"),
(N1, "regular"),
(N2, "regular"),
(N3, "regular"),
(N4, "regular"),
(N5, "regular"),
(N6, "regular"),
(N7, "regular"),
(N8, "regular"),
(N9, "regular"),
(N0, "regular"),
(Hyphen, "regular"),
(Equals, "regular"),
(Backspace, "backspace"),
(Spacing, "row_end_spacing"),
(MediaPlay, "regular"),
],
),
(
pad_left: 0.1,
pad_right: 0.1,
pad_top: 0.1,
pad_bottom: 0.1,
row: [
(Tab, "tab"),
(Q, "regular"),
(W, "regular"),
(E, "regular"),
(R, "regular"),
(T, "regular"),
(Y, "regular"),
(U, "regular"),
(I, "regular"),
(O, "regular"),
(P, "regular"),
(LBracket, "regular"),
(RBracket, "regular"),
(BackSlash, "backslash"),
(Spacing, "row_end_spacing"),
(MediaStop, "regular"),
],
),
(
pad_left: 0.1,
pad_right: 0.1,
pad_top: 0.1,
pad_bottom: 0.1,
row: [
(Caps, "capsplonk"),
(A, "regular"),
(S, "regular"),
(D, "regular"),
(F, "regular"),
(G, "regular"),
(H, "regular"),
(J, "regular"),
(K, "regular"),
(L, "regular"),
(SemiColon, "regular"),
(Quote, "regular"),
(Return, "return"),
(Spacing, "row_end_spacing"),
(MediaNext, "regular"),
],
),
(
pad_left: 0.1,
pad_right: 0.1,
pad_top: 0.1,
pad_bottom: 0.1,
row: [
(LShift, "lshift"),
(Z, "regular"),
(X, "regular"),
(C, "regular"),
(V, "regular"),
(B, "regular"),
(N, "regular"),
(M, "regular"),
(Comma, "regular"),
(Period, "regular"),
(FwdSlash, "regular"),
(Rshift, "rshift"),
(Spacing, "row_end_spacing"),
(MediaPrev, "regular"),
],
),
(
pad_left: 0.1,
pad_right: 0.1,
pad_top: 0.1,
pad_bottom: 0.1,
row: [
(LCtrl, "lctrl"),
(LFn, "regular"),
(Meta, "regular"),
(LAlt, "regular"),
(Spacebar, "spacebar"),
(RAlt, "regular"),
(PrtSc, "regular"),
(RCtrl, "rctrl"),
(Up, "up_arrow"),
(Spacing, "row_end_spacing"),
(PrtSc, "regular"),
],
),
(
pad_left: 0.1,
pad_right: 0.1,
pad_top: 0.1,
pad_bottom: 0.1,
row: [
(Spacing, "arrows_spacer"),
(Left, "arrows"),
(Down, "arrows"),
(Right, "arrows"),
],
),
(
pad_left: 0.1,
pad_right: 0.1,
pad_top: 0.1,
pad_bottom: 0.1,
row: [
(LightbarLeft, "lightbar_left"),
(LightbarLeftCorner, "lightbar_corner_left"),
(LightbarLeftBottom, "lightbar_bottom"),
(LightbarRightBottom, "lightbar_bottom"),
(LightbarRightCorner, "lightbar_corner_right"),
(LightbarRight, "lightbar_right"),
],
),
],
)
+1
View File
@@ -303,6 +303,7 @@ impl LedUsbPackets {
fn rgb_for_led_code(&mut self, led_code: LedCode) -> Option<&mut [u8]> {
let zoned = self.zoned;
// Tuples are indexes in to array
#[allow(clippy::match_same_arms)]
let (row, col) = match led_code {
LedCode::VolDown => (0, 15),
LedCode::VolUp => (0, 18),
+1
View File
@@ -8,6 +8,7 @@ impl From<LedCode> for &str {
impl From<&LedCode> for &str {
fn from(k: &LedCode) -> Self {
#[allow(clippy::match_same_arms)]
match k {
LedCode::VolUp => "Volume Up",
LedCode::VolDown => "Volume Down",
+35 -37
View File
@@ -1,14 +1,20 @@
use std::fs::OpenOptions;
use std::io::Read;
use log::{error, info, warn};
use serde_derive::{Deserialize, Serialize};
use crate::usb::AuraDevice;
use crate::{AdvancedAuraType, AuraModeNum, AuraZone};
pub const ASUS_LED_MODE_CONF: &str = "/usr/share/asusd/aura_support.ron";
pub const ASUS_LED_MODE_USER_CONF: &str = "/etc/asusd/asusd_user_ledmodes.ron";
pub const ASUS_KEYBOARD_DEVICES: [&str; 4] = ["1866", "1869", "1854", "19b6"];
pub const ASUS_KEYBOARD_DEVICES: [AuraDevice; 7] = [
AuraDevice::Tuf,
AuraDevice::X1854,
AuraDevice::X1869,
AuraDevice::X1866,
AuraDevice::X18c6,
AuraDevice::X19b6,
AuraDevice::X1a30,
];
#[derive(Debug, Default, Clone, PartialEq, Eq, Deserialize, Serialize)]
pub struct LedSupportFile(Vec<LaptopLedData>);
@@ -76,39 +82,33 @@ impl LedSupportFile {
let mut loaded = false;
let mut data = LedSupportFile::default();
// Load user configs first so they are first to be checked
if let Ok(mut file) = OpenOptions::new().read(true).open(ASUS_LED_MODE_USER_CONF) {
let mut buf = String::new();
if let Ok(l) = file.read_to_string(&mut buf) {
if l == 0 {
warn!("{} is empty", ASUS_LED_MODE_USER_CONF);
} else {
if let Ok(mut tmp) = ron::from_str::<LedSupportFile>(&buf) {
data.0.append(&mut tmp.0);
}
info!(
"Loaded user-defined LED support data from {}",
ASUS_LED_MODE_USER_CONF
);
if let Ok(file) = std::fs::read_to_string(ASUS_LED_MODE_USER_CONF) {
if file.is_empty() {
warn!("{} is empty", ASUS_LED_MODE_USER_CONF);
} else {
if let Ok(mut tmp) = ron::from_str::<LedSupportFile>(&file) {
data.0.append(&mut tmp.0);
}
info!(
"Loaded user-defined LED support data from {}",
ASUS_LED_MODE_USER_CONF
);
}
}
// Load and append the default LED support data
if let Ok(mut file) = OpenOptions::new().read(true).open(ASUS_LED_MODE_CONF) {
let mut buf = String::new();
if let Ok(l) = file.read_to_string(&mut buf) {
if l == 0 {
warn!("{} is empty", ASUS_LED_MODE_CONF);
} else {
let mut tmp: LedSupportFile = ron::from_str(&buf)
.map_err(|e| error!("{e}"))
.unwrap_or_else(|_| panic!("Could not deserialise {}", ASUS_LED_MODE_CONF));
data.0.append(&mut tmp.0);
loaded = true;
info!(
"Loaded default LED support data from {}",
ASUS_LED_MODE_CONF
);
}
if let Ok(file) = std::fs::read_to_string(ASUS_LED_MODE_CONF) {
if file.is_empty() {
warn!("{} is empty", ASUS_LED_MODE_CONF);
} else {
let mut tmp: LedSupportFile = ron::from_str(&file)
.map_err(|e| error!("{e}"))
.unwrap_or_else(|_| panic!("Could not deserialise {}", ASUS_LED_MODE_CONF));
data.0.append(&mut tmp.0);
loaded = true;
info!(
"Loaded default LED support data from {}",
ASUS_LED_MODE_CONF
);
}
}
data.0.sort_by(|a, b| a.board_name.cmp(&b.board_name));
@@ -125,7 +125,7 @@ impl LedSupportFile {
#[cfg(test)]
mod tests {
use std::fs::OpenOptions;
use std::io::{Read, Write};
use std::io::Write;
use std::path::PathBuf;
use ron::ser::PrettyConfig;
@@ -155,9 +155,7 @@ mod tests {
let mut data = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
data.push("data/aura_support.ron");
let mut file = OpenOptions::new().read(true).open(&data).unwrap();
let mut buf = String::new();
file.read_to_string(&mut buf).unwrap();
let buf = std::fs::read_to_string(&data).unwrap();
let tmp = ron::from_str::<LedSupportFile>(&buf).unwrap();
+3 -1
View File
@@ -284,7 +284,8 @@ impl FromStr for AuraZone {
}
/// Default factory modes structure. This easily converts to an USB HID packet
/// with: ```rust
/// with:
/// ```rust
/// // let bytes: [u8; LED_MSG_LEN] = mode.into();
/// ```
#[cfg_attr(feature = "dbus", derive(Type))]
@@ -350,6 +351,7 @@ pub struct AuraParameters {
pub direction: bool,
}
#[allow(clippy::fn_params_excessive_bools)]
impl AuraParameters {
pub const fn new(
zone: bool,
+1 -1
View File
@@ -28,6 +28,6 @@ impl EffectState for InputBased {
}
fn set_led(&mut self, address: LedCode) {
self.led = address
self.led = address;
}
}
-8
View File
@@ -84,14 +84,6 @@ impl EffectState for DoomFlicker {
}
}
pub struct LightFlash {
pub count: i32,
pub max_light: i32,
pub min_light: i32,
pub max_time: i32,
pub min_time: i32,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct DoomLightFlash {
led: LedCode,
+22 -27
View File
@@ -2,8 +2,6 @@
//! editable config.
use std::collections::{HashMap, HashSet};
use std::fs::{self, OpenOptions};
use std::io::Read;
use std::path::{Path, PathBuf};
use std::slice::Iter;
@@ -88,8 +86,8 @@ impl KeyShape {
/// The first `Key` will determine the row height.
///
/// Every row is considered to start a x=0, with the first row being y=0,
/// and following rows starting after the previous row_y+pad_top and
/// row_x+pad_left
/// and following rows starting after the previous `row_y + pad_top` and
/// `row_x + pad_left`
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct KeyRow {
pad_left: f32,
@@ -138,7 +136,7 @@ impl KeyRow {
};
if h < height {
h = height
h = height;
}
}
h
@@ -192,15 +190,9 @@ pub struct KeyLayout {
impl KeyLayout {
pub fn from_file(path: &Path) -> Result<Self, Error> {
let mut file = OpenOptions::new()
.read(true)
.open(path)
let buf: String = std::fs::read_to_string(path)
.map_err(|e| Error::IoPath(path.to_string_lossy().to_string(), e))?;
let mut buf = String::new();
let read_len = file
.read_to_string(&mut buf)
.map_err(|e| Error::IoPath(path.to_string_lossy().to_string(), e))?;
if read_len == 0 {
if buf.is_empty() {
Err(Error::IoPath(
path.to_string_lossy().to_string(),
std::io::ErrorKind::InvalidData.into(),
@@ -233,7 +225,7 @@ impl KeyLayout {
}
}
pub fn rows(&self) -> Iter<KeyRow> {
pub fn rows(&self) -> Iter<'_, KeyRow> {
self.key_rows.iter()
}
@@ -279,7 +271,7 @@ impl KeyLayout {
for r in &self.key_rows {
let tmp = r.width();
if width < tmp {
width = tmp
width = tmp;
}
}
width
@@ -288,7 +280,13 @@ impl KeyLayout {
/// Find a layout matching the name in `LaptopLedData` in the provided dir
pub fn find_layout(led_data: LaptopLedData, mut data_path: PathBuf) -> Result<Self, Error> {
// TODO: locales
let layout_file = format!("{}_US.ron", led_data.layout_name);
let layout_name = if led_data.layout_name.is_empty() {
"ga401q".to_owned() // Need some sort of default here due to ROGCC
// expecting it
} else {
led_data.layout_name
};
let layout_file = format!("{layout_name}_US.ron");
data_path.push("layouts");
data_path.push(layout_file);
let path = data_path.as_path();
@@ -305,7 +303,7 @@ impl KeyLayout {
data_path.push("layouts");
let path = data_path.as_path();
let mut files = Vec::new();
fs::read_dir(path)
std::fs::read_dir(path)
.map_err(|e| {
println!("{:?}, {e}", path);
e
@@ -471,7 +469,6 @@ mod tests {
data_path.push("data");
data_path.push("layouts");
let path = data_path.as_path();
let mut buf = String::new();
for p in fs::read_dir(path)
.map_err(|e| {
println!("{:?}, {e}", path);
@@ -479,9 +476,7 @@ mod tests {
})
.unwrap()
{
let path = p.unwrap().path();
let mut file = OpenOptions::new().read(true).open(&path).unwrap();
file.read_to_string(&mut buf).unwrap();
let mut buf = std::fs::read_to_string(p.unwrap().path()).unwrap();
let data: KeyLayout = ron::from_str(&buf).unwrap();
@@ -501,9 +496,10 @@ mod tests {
}
}
if !unused.is_empty() {
panic!("The layout {path:?} had unused shapes {unused:?}",);
}
assert!(
unused.is_empty(),
"The layout {path:?} had unused shapes {unused:?}",
);
buf.clear();
}
@@ -527,9 +523,7 @@ mod tests {
data_path.push("data");
data_path.push("aura_support.ron");
let mut buf = String::new();
let mut file = OpenOptions::new().read(true).open(&data_path).unwrap();
file.read_to_string(&mut buf).unwrap();
let mut buf = std::fs::read_to_string(&data_path).unwrap();
let data: LedSupportFile = ron::from_str(&buf).unwrap();
data_path.pop();
@@ -553,6 +547,7 @@ mod tests {
)
})
.unwrap();
#[allow(clippy::verbose_file_reads)]
if let Err(e) = file.read_to_string(&mut buf) {
panic!(
"Error checking {data_path:?} for {} : {e:?}",
+220 -125
View File
@@ -23,25 +23,44 @@ pub const fn aura_brightness_bytes(brightness: u8) -> [u8; 17] {
}
#[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Clone, PartialEq, Eq, PartialOrd, Serialize, Deserialize, Default)]
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Serialize, Deserialize, Default)]
pub enum AuraDevice {
Tuf,
X1854,
X1869,
X1866,
X18c6,
#[default]
X19B6,
X19b6,
X1a30,
Unknown,
}
impl From<AuraDevice> for &str {
fn from(a: AuraDevice) -> Self {
match a {
AuraDevice::Tuf => "tuf",
AuraDevice::X1854 => "1854",
AuraDevice::X1869 => "1869",
AuraDevice::X1866 => "1866",
AuraDevice::X18c6 => "18c6",
AuraDevice::X19b6 => "19b6",
AuraDevice::X1a30 => "1a30",
AuraDevice::Unknown => "unknown",
}
}
}
impl From<&str> for AuraDevice {
fn from(s: &str) -> Self {
match s.to_lowercase().as_str() {
"tuf" => AuraDevice::Tuf,
"1866" | "0x1866" => AuraDevice::X1866,
"18c6" | "0x18c6" => AuraDevice::X18c6,
"1869" | "0x1869" => AuraDevice::X1869,
"1854" | "0x1854" => AuraDevice::X1854,
"19b6" | "0x19b6" => AuraDevice::X19B6,
"19b6" | "0x19b6" => AuraDevice::X19b6,
"1a30" | "0x1a30" => AuraDevice::X1a30,
_ => AuraDevice::Unknown,
}
}
@@ -54,7 +73,9 @@ impl Debug for AuraDevice {
Self::X1854 => write!(f, "0x1854"),
Self::X1869 => write!(f, "0x1869"),
Self::X1866 => write!(f, "0x1866"),
Self::X19B6 => write!(f, "0x19B6"),
Self::X18c6 => write!(f, "0x18c6"),
Self::X19b6 => write!(f, "0x19B6"),
Self::X1a30 => write!(f, "0x1A30"),
Self::Unknown => write!(f, "Unknown"),
}
}
@@ -65,8 +86,8 @@ impl Debug for AuraDevice {
#[derive(Clone, Default, Debug, Serialize, Deserialize)]
pub struct AuraPowerDev {
pub tuf: Vec<AuraDevTuf>,
pub x1866: Vec<AuraDev1866>,
pub x19b6: Vec<AuraDev19b6>,
pub x1866: Vec<AuraDevRog1>,
pub x19b6: Vec<AuraDevRog2>,
}
#[cfg_attr(feature = "dbus", derive(Type))]
@@ -85,24 +106,27 @@ impl AuraDevTuf {
}
}
/// # Bits for older 0x1866 keyboard model
/// # Bits for older 0x1866, 0x1869, 0x1854 keyboard models
///
/// Keybord and Lightbar require Awake, Boot and Sleep apply to both
/// Keybord and Lightbar regardless of if either are enabled (or Awake is
/// enabled)
///
/// | Byte 1 | Byte 2 | Byte 3 | function | hex |
/// |------------|------------|------------|----------|----------|
/// | 0000, 0000 | 0000, 0000 | 0000, 0010 | Awake | 00,00,02 |
/// | 0000, 1000 | 0000, 0000 | 0000, 0000 | Keyboard | 08,00,00 |
/// | 0000, 0100 | 0000, 0101 | 0000, 0000 | Lightbar | 04,05,00 |
/// | 1100, 0011 | 0001, 0010 | 0000, 1001 | Boot/Sht | c3,12,09 |
/// | 0011, 0000 | 0000, 1000 | 0000, 0100 | Sleep | 30,08,04 |
/// | 1111, 1111 | 0001, 1111 | 0000, 1111 | all on | |
/// | Byte 1 | Byte 2 | Byte 3 | Byte 4 | function | hex
/// |
/// |------------|------------|------------|------------|-----------|-------------|
/// | 0000, 0000 | 0000, 0000 | 0000, 0010 | 0000, 0000 | Awake |
/// 00,00,02,00 | | 0000, 1000 | 0000, 0000 | 0000, 0000 | 0000, 0000 | Keyboard
/// | 08,00,00,00 | | 0000, 0100 | 0000, 0101 | 0000, 0000 | 0000, 0000 |
/// Lightbar | 04,05,00,00 | | 1100, 0011 | 0001, 0010 | 0000, 1001 | 0000,
/// 0000 | Boot/Sht | c3,12,09,00 | | 0011, 0000 | 0000, 1000 | 0000, 0100 |
/// 0000, 0000 | Sleep | 30,08,04,00 | | 1111, 1111 | 0001, 1111 | 0000,
/// 1111 | 0000, 0000 | all on | | | 0000, 0000 | 0000, 0000 |
/// 0000, 0000 | 0000, 0010 | Rear Glow | 00,00,00,02 |
#[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[repr(u32)]
pub enum AuraDev1866 {
pub enum AuraDevRog1 {
Awake = 0x000002,
Keyboard = 0x080000,
Lightbar = 0x040500,
@@ -110,14 +134,14 @@ pub enum AuraDev1866 {
Sleep = 0x300804,
}
impl From<AuraDev1866> for u32 {
fn from(a: AuraDev1866) -> Self {
impl From<AuraDevRog1> for u32 {
fn from(a: AuraDevRog1) -> Self {
a as u32
}
}
impl AuraDev1866 {
pub fn to_bytes(control: &[Self]) -> [u8; 3] {
impl AuraDevRog1 {
pub fn to_bytes(control: &[Self]) -> [u8; 4] {
let mut a: u32 = 0;
for n in control {
a |= *n as u32;
@@ -126,6 +150,7 @@ impl AuraDev1866 {
((a & 0xff0000) >> 16) as u8,
((a & 0xff00) >> 8) as u8,
(a & 0xff) as u8,
0x00,
]
}
@@ -134,23 +159,23 @@ impl AuraDev1866 {
}
}
impl BitOr<AuraDev1866> for AuraDev1866 {
impl BitOr<AuraDevRog1> for AuraDevRog1 {
type Output = u32;
fn bitor(self, rhs: AuraDev1866) -> Self::Output {
fn bitor(self, rhs: AuraDevRog1) -> Self::Output {
self as u32 | rhs as u32
}
}
impl BitAnd<AuraDev1866> for AuraDev1866 {
impl BitAnd<AuraDevRog1> for AuraDevRog1 {
type Output = u32;
fn bitand(self, rhs: AuraDev1866) -> Self::Output {
fn bitand(self, rhs: AuraDevRog1) -> Self::Output {
self as u32 & rhs as u32
}
}
/// # Bits for 0x19b6 keyboard model
/// # Bits for newer 0x18c6, 0x19B6, 0x1a30, keyboard models
///
/// byte 4 in the USB packet is for keyboard + logo power states
/// default is on, `ff`
@@ -179,7 +204,7 @@ impl BitAnd<AuraDev1866> for AuraDev1866 {
#[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[repr(u32)]
pub enum AuraDev19b6 {
pub enum AuraDevRog2 {
BootLogo = 1,
BootKeyb = 1 << 1,
AwakeLogo = 1 << 2,
@@ -196,16 +221,20 @@ pub enum AuraDev19b6 {
AwakeLid = 1 << (15 + 2),
SleepLid = 1 << (15 + 3),
ShutdownLid = 1 << (15 + 4),
BootRearGlow = 1 << (23 + 1),
AwakeRearGlow = 1 << (23 + 2),
SleepRearGlow = 1 << (23 + 3),
ShutdownRearGlow = 1 << (23 + 4),
}
impl From<AuraDev19b6> for u32 {
fn from(a: AuraDev19b6) -> Self {
impl From<AuraDevRog2> for u32 {
fn from(a: AuraDevRog2) -> Self {
a as u32
}
}
impl AuraDev19b6 {
pub fn to_bytes(control: &[Self]) -> [u8; 3] {
impl AuraDevRog2 {
pub fn to_bytes(control: &[Self]) -> [u8; 4] {
let mut a: u32 = 0;
for n in control {
a |= *n as u32;
@@ -214,6 +243,7 @@ impl AuraDev19b6 {
(a & 0xff) as u8,
((a & 0xff00) >> 8) as u8,
((a & 0xff0000) >> 16) as u8,
((a & 0xff000000) >> 24) as u8,
]
}
@@ -222,204 +252,269 @@ impl AuraDev19b6 {
}
}
impl BitOr<AuraDev19b6> for AuraDev19b6 {
impl BitOr<AuraDevRog2> for AuraDevRog2 {
type Output = u16;
fn bitor(self, rhs: AuraDev19b6) -> Self::Output {
fn bitor(self, rhs: AuraDevRog2) -> Self::Output {
self as u16 | rhs as u16
}
}
impl BitAnd<AuraDev19b6> for AuraDev19b6 {
impl BitAnd<AuraDevRog2> for AuraDevRog2 {
type Output = u16;
fn bitand(self, rhs: AuraDev19b6) -> Self::Output {
fn bitand(self, rhs: AuraDevRog2) -> Self::Output {
self as u16 & rhs as u16
}
}
#[cfg(test)]
mod tests {
use super::AuraDev1866;
use crate::usb::AuraDev19b6;
use super::AuraDevRog1;
use crate::usb::AuraDevRog2;
#[test]
fn check_0x1866_control_bytes() {
let bytes = [AuraDev1866::Keyboard, AuraDev1866::Awake];
let bytes = AuraDev1866::to_bytes(&bytes);
let bytes = [AuraDevRog1::Keyboard, AuraDevRog1::Awake];
let bytes = AuraDevRog1::to_bytes(&bytes);
println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]);
assert_eq!(bytes, [0x08, 0x00, 0x02]);
assert_eq!(bytes, [0x08, 0x00, 0x02, 0x00]);
let bytes = [AuraDev1866::Lightbar, AuraDev1866::Awake];
let bytes = AuraDev1866::to_bytes(&bytes);
let bytes = [AuraDevRog1::Lightbar, AuraDevRog1::Awake];
let bytes = AuraDevRog1::to_bytes(&bytes);
println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]);
assert_eq!(bytes, [0x04, 0x05, 0x02]);
assert_eq!(bytes, [0x04, 0x05, 0x02, 0x00]);
let bytes = [AuraDev1866::Sleep];
let bytes = AuraDev1866::to_bytes(&bytes);
let bytes = [AuraDevRog1::Sleep];
let bytes = AuraDevRog1::to_bytes(&bytes);
println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]);
assert_eq!(bytes, [0x30, 0x08, 0x04]);
assert_eq!(bytes, [0x30, 0x08, 0x04, 0x00]);
let bytes = [AuraDev1866::Boot];
let bytes = AuraDev1866::to_bytes(&bytes);
let bytes = [AuraDevRog1::Boot];
let bytes = AuraDevRog1::to_bytes(&bytes);
println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]);
assert_eq!(bytes, [0xc3, 0x12, 0x09]);
assert_eq!(bytes, [0xc3, 0x12, 0x09, 0x00]);
let bytes = [
AuraDev1866::Keyboard,
AuraDev1866::Lightbar,
AuraDev1866::Awake,
AuraDev1866::Sleep,
AuraDev1866::Boot,
AuraDevRog1::Keyboard,
AuraDevRog1::Lightbar,
AuraDevRog1::Awake,
AuraDevRog1::Sleep,
AuraDevRog1::Boot,
];
let bytes = AuraDev1866::to_bytes(&bytes);
let bytes = AuraDevRog1::to_bytes(&bytes);
println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]);
assert_eq!(bytes, [0xff, 0x1f, 0x000f]);
assert_eq!(bytes, [0xff, 0x1f, 0x000f, 0x00]);
}
#[test]
fn check_0x19b6_control_bytes() {
// All on
let byte1 = [
AuraDev19b6::BootLogo,
AuraDev19b6::BootKeyb,
AuraDev19b6::SleepLogo,
AuraDev19b6::SleepKeyb,
AuraDev19b6::AwakeLogo,
AuraDev19b6::AwakeKeyb,
AuraDev19b6::ShutdownLogo,
AuraDev19b6::ShutdownKeyb,
AuraDevRog2::BootLogo,
AuraDevRog2::BootKeyb,
AuraDevRog2::SleepLogo,
AuraDevRog2::SleepKeyb,
AuraDevRog2::AwakeLogo,
AuraDevRog2::AwakeKeyb,
AuraDevRog2::ShutdownLogo,
AuraDevRog2::ShutdownKeyb,
];
let bytes = AuraDev19b6::to_bytes(&byte1);
let bytes = AuraDevRog2::to_bytes(&byte1);
println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]);
assert_eq!(bytes[0], 0xff);
//
let byte1 = [
// AuraControl::BootLogo,
AuraDev19b6::BootKeyb,
AuraDev19b6::SleepLogo,
AuraDev19b6::SleepKeyb,
AuraDev19b6::AwakeLogo,
AuraDev19b6::AwakeKeyb,
AuraDev19b6::ShutdownLogo,
AuraDev19b6::ShutdownKeyb,
AuraDevRog2::BootKeyb,
AuraDevRog2::SleepLogo,
AuraDevRog2::SleepKeyb,
AuraDevRog2::AwakeLogo,
AuraDevRog2::AwakeKeyb,
AuraDevRog2::ShutdownLogo,
AuraDevRog2::ShutdownKeyb,
];
let bytes = AuraDev19b6::to_bytes(&byte1);
let bytes = AuraDevRog2::to_bytes(&byte1);
println!("{:08b}", bytes[0]);
assert_eq!(bytes[0], 0xfe);
let byte1 = [
AuraDev19b6::BootLogo,
AuraDevRog2::BootLogo,
// AuraControl::BootKeyb,
AuraDev19b6::SleepLogo,
AuraDev19b6::SleepKeyb,
AuraDev19b6::AwakeLogo,
AuraDev19b6::AwakeKeyb,
AuraDev19b6::ShutdownLogo,
AuraDev19b6::ShutdownKeyb,
AuraDevRog2::SleepLogo,
AuraDevRog2::SleepKeyb,
AuraDevRog2::AwakeLogo,
AuraDevRog2::AwakeKeyb,
AuraDevRog2::ShutdownLogo,
AuraDevRog2::ShutdownKeyb,
];
let bytes = AuraDev19b6::to_bytes(&byte1);
let bytes = AuraDevRog2::to_bytes(&byte1);
println!("{:08b}", bytes[0]);
assert_eq!(bytes[0], 0xfd);
let byte1 = [
AuraDev19b6::BootLogo,
AuraDev19b6::BootKeyb,
AuraDevRog2::BootLogo,
AuraDevRog2::BootKeyb,
// AuraControl::SleepLogo,
AuraDev19b6::SleepKeyb,
AuraDev19b6::AwakeLogo,
AuraDev19b6::AwakeKeyb,
AuraDev19b6::ShutdownLogo,
AuraDev19b6::ShutdownKeyb,
AuraDevRog2::SleepKeyb,
AuraDevRog2::AwakeLogo,
AuraDevRog2::AwakeKeyb,
AuraDevRog2::ShutdownLogo,
AuraDevRog2::ShutdownKeyb,
];
let bytes = AuraDev19b6::to_bytes(&byte1);
let bytes = AuraDevRog2::to_bytes(&byte1);
println!("{:08b}", bytes[0]);
assert_eq!(bytes[0], 0xef);
let byte1 = [
AuraDev19b6::BootLogo,
AuraDev19b6::BootKeyb,
AuraDev19b6::SleepLogo,
AuraDevRog2::BootLogo,
AuraDevRog2::BootKeyb,
AuraDevRog2::SleepLogo,
// AuraControl::SleepKeyb,
AuraDev19b6::AwakeLogo,
AuraDev19b6::AwakeKeyb,
AuraDev19b6::ShutdownLogo,
AuraDev19b6::ShutdownKeyb,
AuraDevRog2::AwakeLogo,
AuraDevRog2::AwakeKeyb,
AuraDevRog2::ShutdownLogo,
AuraDevRog2::ShutdownKeyb,
];
let bytes = AuraDev19b6::to_bytes(&byte1);
let bytes = AuraDevRog2::to_bytes(&byte1);
println!("{:08b}", bytes[0]);
assert_eq!(bytes[0], 0xdf);
let byte2 = [
AuraDev19b6::BootBar,
AuraDev19b6::AwakeBar,
AuraDev19b6::SleepBar,
AuraDev19b6::ShutdownBar,
AuraDevRog2::BootBar,
AuraDevRog2::AwakeBar,
AuraDevRog2::SleepBar,
AuraDevRog2::ShutdownBar,
];
let bytes = AuraDev19b6::to_bytes(&byte2);
let bytes = AuraDevRog2::to_bytes(&byte2);
println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]);
assert_eq!(bytes[1], 0x1e);
let byte2 = [
AuraDev19b6::BootBar,
AuraDev19b6::AwakeBar,
AuraDevRog2::BootBar,
AuraDevRog2::AwakeBar,
// AuraControl::SleepBar,
AuraDev19b6::ShutdownBar,
AuraDevRog2::ShutdownBar,
];
let bytes = AuraDev19b6::to_bytes(&byte2);
let bytes = AuraDevRog2::to_bytes(&byte2);
println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]);
assert_eq!(bytes[1], 0x16);
let byte3 = [
AuraDev19b6::AwakeLid,
AuraDev19b6::BootLid,
AuraDev19b6::SleepLid,
AuraDev19b6::ShutdownLid,
AuraDevRog2::AwakeLid,
AuraDevRog2::BootLid,
AuraDevRog2::SleepLid,
AuraDevRog2::ShutdownLid,
];
let bytes = AuraDev19b6::to_bytes(&byte3);
let bytes = AuraDevRog2::to_bytes(&byte3);
println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]);
assert_eq!(bytes[2], 0x0f);
let byte3 = [
// AuraDev19b6::AwakeLid,
AuraDev19b6::BootLid,
AuraDev19b6::SleepLid,
AuraDev19b6::ShutdownLid,
AuraDevRog2::BootLid,
AuraDevRog2::SleepLid,
AuraDevRog2::ShutdownLid,
];
let bytes = AuraDev19b6::to_bytes(&byte3);
let bytes = AuraDevRog2::to_bytes(&byte3);
println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]);
assert_eq!(bytes[2], 0x0d);
let byte3 = [
AuraDev19b6::AwakeLid,
AuraDev19b6::BootLid,
AuraDevRog2::AwakeLid,
AuraDevRog2::BootLid,
// AuraControl::SleepLid,
AuraDev19b6::ShutdownLid,
AuraDevRog2::ShutdownLid,
];
let bytes = AuraDev19b6::to_bytes(&byte3);
let bytes = AuraDevRog2::to_bytes(&byte3);
println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]);
assert_eq!(bytes[2], 0x0b);
let byte3 = [
AuraDev19b6::AwakeLid,
AuraDev19b6::BootLid,
AuraDev19b6::SleepLid,
AuraDevRog2::AwakeLid,
AuraDevRog2::BootLid,
AuraDevRog2::SleepLid,
// AuraDev19b6::ShutdownLid,
];
let bytes = AuraDev19b6::to_bytes(&byte3);
let bytes = AuraDevRog2::to_bytes(&byte3);
println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]);
assert_eq!(bytes[2], 0x07);
let byte3 = [
AuraDev19b6::AwakeLid,
AuraDevRog2::AwakeLid,
// AuraDev19b6::BootLid,
AuraDev19b6::SleepLid,
AuraDevRog2::SleepLid,
// AuraDev19b6::ShutdownLid,
];
let bytes = AuraDev19b6::to_bytes(&byte3);
let bytes = AuraDevRog2::to_bytes(&byte3);
println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]);
assert_eq!(bytes[2], 0x06);
let byte4 = [
// AuraDev19b6::AwakeRearBar,
AuraDevRog2::BootRearGlow,
AuraDevRog2::SleepRearGlow,
AuraDevRog2::ShutdownRearGlow,
];
let bytes = AuraDevRog2::to_bytes(&byte4);
println!(
"{:08b}, {:08b}, {:08b}, {:08b}",
bytes[0], bytes[1], bytes[2], bytes[3]
);
assert_eq!(bytes[3], 0x0d);
let byte4 = [
AuraDevRog2::AwakeRearGlow,
AuraDevRog2::BootRearGlow,
// AuraDevRog2::SleepRearBar,
AuraDevRog2::ShutdownRearGlow,
];
let bytes = AuraDevRog2::to_bytes(&byte4);
println!(
"{:08b}, {:08b}, {:08b}, {:08b}",
bytes[0], bytes[1], bytes[2], bytes[3]
);
assert_eq!(bytes[3], 0x0b);
let byte4 = [
AuraDevRog2::AwakeRearGlow,
AuraDevRog2::BootRearGlow,
AuraDevRog2::SleepRearGlow,
// AuraDevRog2::ShutdownRearBar,
];
let bytes = AuraDevRog2::to_bytes(&byte4);
println!(
"{:08b}, {:08b}, {:08b}, {:08b}",
bytes[0], bytes[1], bytes[2], bytes[3]
);
assert_eq!(bytes[3], 0x07);
let byte4 = [
AuraDevRog2::AwakeRearGlow,
// AuraDevRog2::BootRearBar,
AuraDevRog2::SleepRearGlow,
// AuraDevRog2::ShutdownRearBar,
];
let bytes = AuraDevRog2::to_bytes(&byte4);
println!(
"{:08b}, {:08b}, {:08b}, {:08b}",
bytes[0], bytes[1], bytes[2], bytes[3]
);
assert_eq!(bytes[3], 0x06);
let byte4 = [
AuraDevRog2::AwakeRearGlow,
// AuraDevRog2::BootRearBar,
// AuraDevRog2::SleepRearBar,
// AuraDevRog2::ShutdownRearBar,
];
let bytes = AuraDevRog2::to_bytes(&byte4);
println!(
"{:08b}, {:08b}, {:08b}, {:08b}",
bytes[0], bytes[1], bytes[2], bytes[3]
);
assert_eq!(bytes[3], 0x02);
}
}
+16 -5
View File
@@ -10,13 +10,15 @@ edition = "2021"
mocking = []
[dependencies]
egui = { git = "https://github.com/flukejones/egui", branch = "wayland_dark_theme" }
eframe = { git = "https://github.com/flukejones/egui", branch = "wayland_dark_theme" }
egui = { git = "https://github.com/emilk/egui", rev = "b8e798777de519de3a1878798097ab2ab0bd4def"}
eframe = { git = "https://github.com/emilk/egui", rev = "b8e798777de519de3a1878798097ab2ab0bd4def"}
# egui = { path = "../../egui/crates/egui" }
# eframe = { path = "../../egui/crates/eframe" }
libappindicator = "0.7" # Tray icon
gtk = "0.15.5"
libappindicator = "0.8" # Tray icon
gtk = "0.16"
daemon = { path = "../daemon" }
asusd = { path = "../asusd" }
rog_anime = { path = "../rog-anime" }
rog_dbus = { path = "../rog-dbus" }
rog_aura = { path = "../rog-aura" }
@@ -39,5 +41,14 @@ notify-rust.workspace = true
png_pong.workspace = true
versions.workspace = true
nix = "^0.26.1"
tempfile = "3.3.0"
# [patch.crates-io]
# egui = { git = "https://github.com/flukejones/egui" }
# eframe = { git = "https://github.com/flukejones/egui" }
[dev-dependencies]
cargo-husky.workspace = true
+32
View File
@@ -17,6 +17,7 @@ pub struct Config {
pub ac_command: String,
pub bat_command: String,
pub enable_notifications: bool,
pub dark_mode: bool,
// This field must be last
pub enabled_notifications: EnabledNotifications,
}
@@ -27,6 +28,7 @@ impl Default for Config {
run_in_background: true,
startup_in_background: false,
enable_notifications: true,
dark_mode: true,
enabled_notifications: EnabledNotifications::default(),
ac_command: String::new(),
bat_command: String::new(),
@@ -60,6 +62,8 @@ impl Config {
let mut buf = String::new();
// Lint to allow, because we want the above file behaviour
#[allow(clippy::verbose_file_reads)]
if let Ok(read_len) = file.read_to_string(&mut buf) {
if read_len == 0 {
warn!("Zero len read of Config file");
@@ -70,6 +74,9 @@ impl Config {
} else if let Ok(data) = toml::from_str::<Config>(&buf) {
info!("Loaded config file {path:?}");
return Ok(data);
} else if let Ok(data) = toml::from_str::<Config460>(&buf) {
info!("Loaded old v4.6.0 config file {path:?}");
return Ok(data.into());
} else if let Ok(data) = toml::from_str::<Config455>(&buf) {
info!("Loaded old v4.5.5 config file {path:?}");
return Ok(data.into());
@@ -122,8 +129,33 @@ impl From<Config455> for Config {
startup_in_background: c.startup_in_background,
enable_notifications: c.enable_notifications,
enabled_notifications: c.enabled_notifications,
dark_mode: true,
ac_command: String::new(),
bat_command: String::new(),
}
}
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Config460 {
pub run_in_background: bool,
pub startup_in_background: bool,
pub ac_command: String,
pub bat_command: String,
pub enable_notifications: bool,
pub enabled_notifications: EnabledNotifications,
}
impl From<Config460> for Config {
fn from(c: Config460) -> Self {
Self {
run_in_background: c.run_in_background,
startup_in_background: c.startup_in_background,
ac_command: c.ac_command,
bat_command: c.bat_command,
dark_mode: true,
enable_notifications: c.enable_notifications,
enabled_notifications: c.enabled_notifications,
}
}
}
+8
View File
@@ -11,6 +11,7 @@ pub enum Error {
XdgVars,
Zbus(zbus::Error),
Notification(notify_rust::error::Error),
Eframe(eframe::Error),
}
impl fmt::Display for Error {
@@ -24,6 +25,7 @@ impl fmt::Display for Error {
Error::XdgVars => write!(f, "XDG environment vars appear unset"),
Error::Zbus(err) => write!(f, "Error: {}", err),
Error::Notification(err) => write!(f, "Notification Error: {}", err),
Error::Eframe(err) => write!(f, "Eframe Error: {}", err),
}
}
}
@@ -53,3 +55,9 @@ impl From<notify_rust::error::Error> for Error {
Error::Notification(err)
}
}
impl From<eframe::Error> for Error {
fn from(err: eframe::Error) -> Self {
Error::Eframe(err)
}
}
+5 -3
View File
@@ -33,7 +33,7 @@ pub const VERSION: &str = env!("CARGO_PKG_VERSION");
pub fn print_versions() {
println!("App and daemon versions:");
println!(" rog-gui v{}", VERSION);
println!(" asusd v{}", daemon::VERSION);
println!(" asusd v{}", asusd::VERSION);
println!("\nComponent crate versions:");
println!(" rog-anime v{}", rog_anime::VERSION);
println!(" rog-aura v{}", rog_aura::VERSION);
@@ -81,6 +81,8 @@ pub fn on_tmp_dir_exists() -> Result<TempDir, std::io::Error> {
// First entry is the actual state
if buf[0] == SHOWING_GUI {
ipc_file.write_all(&[SHOWING_GUI])?; // Store state again as we drained the fifo
// Early exit is not an error and we don't want to pass back a dir
#[allow(clippy::exit)]
exit(0);
} else if buf[0] == SHOW_GUI {
remove_dir_all(&path)?;
@@ -89,7 +91,7 @@ pub fn on_tmp_dir_exists() -> Result<TempDir, std::io::Error> {
.rand_bytes(0)
.tempdir();
}
exit(-1);
panic!("Invalid exit or app state");
}
pub fn get_ipc_file() -> Result<File, crate::error::Error> {
@@ -103,6 +105,6 @@ pub fn get_ipc_file() -> Result<File, crate::error::Error> {
Ok(OpenOptions::new()
.read(true)
.write(true)
.truncate(true)
// .truncate(true)
.open(&fifo_path)?)
}
+61 -54
View File
@@ -1,12 +1,14 @@
use std::env::args;
use std::fs::OpenOptions;
use std::io::{Read, Write};
use std::path::{Path, PathBuf};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
use eframe::{IconData, NativeOptions};
use eframe::IconData;
use gumdrop::Options;
use log::{error, info, warn};
use log::{debug, error, info, warn, LevelFilter};
use rog_aura::aura_detection::{LaptopLedData, LedSupportFile};
use rog_aura::layouts::KeyLayout;
use rog_control_center::cli_options::CliStart;
@@ -46,6 +48,7 @@ fn main() -> Result<()> {
let mut logger = env_logger::Builder::new();
logger
.filter_level(LevelFilter::Warn)
.parse_default_env()
.target(env_logger::Target::Stdout)
.format(|buf, record| writeln!(buf, "{}: {}", record.level(), record.args()))
@@ -73,7 +76,9 @@ fn main() -> Result<()> {
"ROG Control Center",
native_options.clone(),
Box::new(move |_| Box::new(AppErrorShow::new(e.to_string()))),
);
)
.map_err(|e| error!("{e}"))
.ok();
})
.unwrap();
@@ -84,14 +89,16 @@ fn main() -> Result<()> {
"ROG Control Center",
native_options.clone(),
Box::new(move |_| Box::new(AppErrorShow::new(e.to_string()))),
);
)
.map_err(|e| error!("{e}"))
.ok();
SupportedFunctions::default()
}
};
// Startup
let mut config = Config::load()?;
let mut start_closed = config.startup_in_background;
let running_in_bg = Arc::new(AtomicBool::new(config.startup_in_background));
if config.startup_in_background {
config.run_in_background = true;
@@ -101,15 +108,10 @@ fn main() -> Result<()> {
let enabled_notifications = EnabledNotifications::tokio_mutex(&config);
// Find and load a matching layout for laptop
let mut file = OpenOptions::new()
.read(true)
.open(PathBuf::from(BOARD_NAME))
.map_err(|e| {
println!("DOH! {BOARD_NAME}, {e}");
e
})?;
let mut board_name = String::new();
file.read_to_string(&mut board_name)?;
let mut board_name = std::fs::read_to_string(BOARD_NAME).map_err(|e| {
println!("DOH! {BOARD_NAME}, {e}");
e
})?;
let mut led_support = LaptopLedData::get_data();
@@ -122,7 +124,7 @@ fn main() -> Result<()> {
path.push("rog-aura");
path.push("data");
}
layouts = KeyLayout::layout_files(path.to_owned()).unwrap();
layouts = KeyLayout::layout_files(path.clone()).unwrap();
if let Some(name) = &cli_parsed.board_name {
if let Some(modes) = LedSupportFile::load_from_config() {
@@ -130,7 +132,7 @@ fn main() -> Result<()> {
led_support = data;
}
}
board_name = name.to_owned();
board_name = name.clone();
for layout in &layouts {
if layout
.file_name()
@@ -138,11 +140,11 @@ fn main() -> Result<()> {
.to_string_lossy()
.contains(&led_support.layout_name.to_lowercase())
{
layout_name = Some(layout.to_owned());
layout_name = Some(layout.clone());
}
}
} else {
board_name = "GQ401QM".to_string()
board_name = "GQ401QM".to_owned();
};
if cli_parsed.layout_viewing {
@@ -182,33 +184,55 @@ fn main() -> Result<()> {
layout_name,
layout,
layouts,
enabled_notifications,
&enabled_notifications,
&config,
&supported,
)?;
init_tray(supported, states.clone());
let mut bg_check_spawned = false;
loop {
if !start_closed {
start_app(states.clone(), native_options.clone())?;
if !running_in_bg.load(Ordering::Relaxed) {
// blocks until window is closed
let states = states.clone();
let mut ipc_file = get_ipc_file()?;
ipc_file.write_all(&[SHOWING_GUI])?;
eframe::run_native(
"ROG Control Center",
native_options.clone(),
Box::new(move |cc| {
Box::new(RogApp::new(Config::load().unwrap(), states, cc).unwrap())
}),
)?;
running_in_bg.store(true, Ordering::SeqCst);
bg_check_spawned = false;
}
let config = Config::load()?;
if !config.run_in_background || cli_parsed.board_name.is_some() || cli_parsed.layout_viewing
{
break;
}
if config.run_in_background {
let mut buf = [0u8; 4];
// blocks until it is read, typically the read will happen after a second
// process writes to the IPC (so there is data to actually read)
if get_ipc_file()?.read(&mut buf).is_ok() && buf[0] == SHOW_GUI {
start_closed = false;
continue;
}
if config.run_in_background && running_in_bg.load(Ordering::Acquire) && !bg_check_spawned {
let running_in_bg = running_in_bg.clone();
thread::spawn(move || {
let mut buf = [0u8; 4];
// blocks until it is read, typically the read will happen after a second
// process writes to the IPC (so there is data to actually read)
loop {
if get_ipc_file().unwrap().read(&mut buf).is_ok() && buf[0] == SHOW_GUI {
running_in_bg.store(false, Ordering::Release);
debug!("Wait thread got from tray {buf:#?}");
break;
}
}
});
bg_check_spawned = true;
}
// Prevent hogging CPU
thread::sleep(Duration::from_millis(500));
}
// loop {
@@ -222,7 +246,7 @@ fn setup_page_state_and_notifs(
layout_testing: Option<PathBuf>,
keyboard_layout: KeyLayout,
keyboard_layouts: Vec<PathBuf>,
enabled_notifications: Arc<Mutex<EnabledNotifications>>,
enabled_notifications: &Arc<Mutex<EnabledNotifications>>,
config: &Config,
supported: &SupportedFunctions,
) -> Result<Arc<Mutex<SystemState>>> {
@@ -234,40 +258,23 @@ fn setup_page_state_and_notifs(
supported,
)?));
start_notifications(config, page_states.clone(), enabled_notifications)?;
start_notifications(config, &page_states, enabled_notifications)?;
Ok(page_states)
}
fn start_app(states: Arc<Mutex<SystemState>>, native_options: NativeOptions) -> Result<()> {
let mut ipc_file = get_ipc_file()?;
ipc_file.write_all(&[SHOWING_GUI])?;
eframe::run_native(
"ROG Control Center",
native_options,
Box::new(move |cc| Box::new(RogApp::new(Config::load().unwrap(), states, cc).unwrap())),
);
Ok(())
}
/// Bah.. the icon dosn't work on wayland anyway, but we'll leave it in for now.
fn load_icon() -> IconData {
let path = PathBuf::from(APP_ICON_PATH);
let mut buf = Vec::new();
let mut rgba = Vec::new();
let mut height = 512;
let mut width = 512;
if path.exists() {
if let Ok(mut file) = OpenOptions::new()
.read(true)
.open(path)
if let Ok(data) = std::fs::read(path)
.map_err(|e| error!("Error reading app icon: {e:?}"))
.map_err(|e| error!("Error opening app icon: {e:?}"))
{
file.read_to_end(&mut buf)
.map_err(|e| error!("Error reading app icon: {e:?}"))
.ok();
let data = std::io::Cursor::new(buf);
let data = std::io::Cursor::new(data);
let decoder = png_pong::Decoder::new(data).unwrap().into_steps();
let png_pong::Step { raster, delay: _ } = decoder.last().unwrap().unwrap();
@@ -295,7 +302,7 @@ fn do_cli_help(parsed: &CliStart) -> bool {
println!();
if let Some(cmdlist) = CliStart::command_list() {
let commands: Vec<String> = cmdlist.lines().map(|s| s.to_owned()).collect();
for command in commands.iter() {
for command in &commands {
println!("{}", command);
}
}
+28 -39
View File
@@ -5,6 +5,8 @@ use std::time::SystemTime;
use egui::Vec2;
use log::error;
use rog_anime::usb::Brightness;
use rog_anime::Animations;
use rog_aura::layouts::KeyLayout;
use rog_aura::usb::AuraPowerDev;
use rog_aura::{AuraEffect, AuraModeNum};
@@ -30,6 +32,7 @@ pub struct BiosState {
pub post_sound: bool,
pub dedicated_gfx: GpuMode,
pub panel_overdrive: bool,
pub mini_led_mode: bool,
pub dgpu_disable: bool,
pub egpu_enable: bool,
}
@@ -52,6 +55,11 @@ impl BiosState {
} else {
false
},
mini_led_mode: if supported.rog_bios_ctrl.mini_led_mode {
dbus.proxies().rog_bios().mini_led_mode()?
} else {
false
},
// TODO: needs supergfx
dgpu_disable: supported.rog_bios_ctrl.dgpu_disable,
egpu_enable: supported.rog_bios_ctrl.egpu_enable,
@@ -194,29 +202,25 @@ impl AuraState {
#[derive(Clone, Debug, Default)]
pub struct AnimeState {
pub bright: u8,
pub boot: bool,
pub awake: bool,
pub sleep: bool,
pub display_enabled: bool,
pub display_brightness: Brightness,
pub builtin_anims_enabled: bool,
pub builtin_anims: Animations,
}
impl AnimeState {
pub fn new(supported: &SupportedFunctions, dbus: &RogDbusClientBlocking<'_>) -> Result<Self> {
Ok(Self {
boot: if supported.anime_ctrl.0 {
dbus.proxies().anime().boot_enabled()?
} else {
false
},
awake: if supported.anime_ctrl.0 {
dbus.proxies().anime().awake_enabled()?
} else {
false
},
// TODO:
sleep: false,
bright: 200,
})
if supported.anime_ctrl.0 {
let device_state = dbus.proxies().anime().device_state()?;
Ok(Self {
display_enabled: device_state.display_enabled,
display_brightness: device_state.display_brightness,
builtin_anims_enabled: device_state.builtin_anims_enabled,
builtin_anims: device_state.builtin_anims,
})
} else {
Ok(Default::default())
}
}
}
@@ -412,9 +416,7 @@ impl Default for SystemState {
bios: BiosState {
post_sound: Default::default(),
dedicated_gfx: GpuMode::NotSupported,
panel_overdrive: Default::default(),
dgpu_disable: Default::default(),
egpu_enable: Default::default(),
..Default::default()
},
aura: AuraState {
current_mode: AuraModeNum::Static,
@@ -424,27 +426,14 @@ impl Default for SystemState {
x1866: vec![],
x19b6: vec![],
},
bright: Default::default(),
wave_red: Default::default(),
wave_green: Default::default(),
wave_blue: Default::default(),
},
anime: AnimeState {
bright: Default::default(),
boot: Default::default(),
awake: Default::default(),
sleep: Default::default(),
..Default::default()
},
anime: AnimeState::default(),
profiles: ProfilesState {
list: Default::default(),
current: Default::default(),
..Default::default()
},
fan_curves: FanCurvesState {
show_curve: Default::default(),
show_graph: Default::default(),
enabled: Default::default(),
curves: Default::default(),
drag_delta: Default::default(),
..Default::default()
},
gfx_state: GfxState {
has_supergfx: false,
+124 -137
View File
@@ -2,7 +2,6 @@
//! commands over an MPSC channel.
use std::io::Write;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::{channel, Receiver};
use std::sync::{Arc, Mutex};
use std::time::Duration;
@@ -14,8 +13,10 @@ use log::{debug, error, info, trace, warn};
use rog_dbus::zbus_platform::RogBiosProxyBlocking;
use rog_platform::platform::GpuMode;
use rog_platform::supported::SupportedFunctions;
use supergfxctl::actions::UserActionRequired as GfxUserActionRequired;
use supergfxctl::pci_device::{GfxMode, GfxPower};
use supergfxctl::zbus_proxy::DaemonProxyBlocking as GfxProxyBlocking;
use versions::Versioning;
use crate::error::Result;
use crate::system_state::SystemState;
@@ -79,6 +80,8 @@ pub struct ROGTray {
menu: gtk::Menu,
icon: &'static str,
bios_proxy: RogBiosProxyBlocking<'static>,
gfx_proxy_is_active: bool,
gfx_action: Arc<Mutex<GfxUserActionRequired>>,
gfx_proxy: GfxProxyBlocking<'static>,
}
@@ -88,6 +91,12 @@ impl ROGTray {
error!("ROGTray: {e}");
e
})?;
let gfx_proxy = GfxProxyBlocking::new(&conn).map_err(|e| {
error!("ROGTray: {e}");
e
})?;
let rog_tray = Self {
tray: AppIndicator::new(TRAY_LABEL, TRAY_APP_ICON),
menu: gtk::Menu::new(),
@@ -96,10 +105,9 @@ impl ROGTray {
error!("ROGTray: {e}");
e
})?,
gfx_proxy: GfxProxyBlocking::new(&conn).map_err(|e| {
error!("ROGTray: {e}");
e
})?,
gfx_proxy_is_active: gfx_proxy.mode().is_ok(),
gfx_action: Arc::new(Mutex::new(GfxUserActionRequired::Nothing)),
gfx_proxy,
};
Ok(rog_tray)
}
@@ -208,6 +216,7 @@ impl ROGTray {
if let Ok(mut ipc) = get_ipc_file().map_err(|e| {
error!("ROGTray: get_ipc_file: {}", e);
}) {
debug!("Tray told app to show self");
ipc.write_all(&[SHOW_GUI]).ok();
}
});
@@ -238,132 +247,79 @@ impl ROGTray {
}
}
fn menu_add_gpu(&mut self, supported: &SupportedFunctions, current_mode: GfxMode) {
let set_mux_off = Arc::new(AtomicBool::new(false));
fn menu_add_mini_led_mode(&mut self, supported: &SupportedFunctions, on: bool) {
if supported.rog_bios_ctrl.mini_led_mode {
let bios = self.bios_proxy.clone();
self.add_check_menu_item("MiniLED mode", on, move |this| {
bios.set_mini_led_mode(this.is_active())
.map_err(|e| {
error!("ROGTray: set_mini_led_mode: {e}");
e
})
.ok();
});
debug!("ROGTray: appended miniLED mode menu");
}
}
fn menu_add_supergfx(&mut self, supported_gfx: &[GfxMode], current_mode: GfxMode) {
if !self.gfx_proxy_is_active {
trace!("menu_add_supergfx: gfx_proxy_is_active is false");
return;
}
let gfx_dbus = self.gfx_proxy.clone();
let set_mux_off1 = set_mux_off.clone();
let gfx_action = self.gfx_action.clone();
let mut gpu_menu = RadioGroup::new("Integrated", move |_| {
let mode = gfx_dbus
.mode()
.map_err(|e| {
error!("ROGTray: mode: {e}");
if current_mode != GfxMode::Integrated {
if let Ok(res) = gfx_dbus.set_mode(&GfxMode::Integrated).map_err(|e| {
error!("ROGTray: srt_mode: {e}");
e
})
.unwrap_or(GfxMode::None);
if mode != GfxMode::Integrated {
gfx_dbus
.set_mode(&GfxMode::Integrated)
.map_err(|e| {
error!("ROGTray: srt_mode: {e}");
e
})
.ok();
}) {
if let Ok(mut lock) = gfx_action.lock() {
*lock = res;
}
}
}
set_mux_off1.store(true, Ordering::Relaxed);
});
let gfx_dbus = self.gfx_proxy.clone();
let set_mux_off1 = set_mux_off.clone();
gpu_menu.add("Hybrid", move |_| {
let mode = gfx_dbus
.mode()
.map_err(|e| {
error!("ROGTray: mode: {e}");
e
})
.unwrap_or(GfxMode::None);
if mode != GfxMode::Hybrid {
gfx_dbus
.set_mode(&GfxMode::Hybrid)
.map_err(|e| {
error!("ROGTray: set_mode: {e}");
e
})
.ok();
}
set_mux_off1.store(true, Ordering::Relaxed);
});
if supported.rog_bios_ctrl.egpu_enable {
let set_mux_off1 = set_mux_off.clone();
let mut func = |menu_mode: GfxMode| {
let gfx_dbus = self.gfx_proxy.clone();
gpu_menu.add("eGPU", move |_| {
let mode = gfx_dbus
.mode()
.map_err(|e| {
error!("ROGTray: mode: {e}");
e
})
.unwrap_or(GfxMode::None);
if mode != GfxMode::Egpu {
gfx_dbus
.set_mode(&GfxMode::Egpu)
.map_err(|e| {
error!("ROGTray: set_mode: {e}");
e
})
.ok();
}
set_mux_off1.store(true, Ordering::Relaxed);
});
}
let mut reboot_required = false;
if supported.rog_bios_ctrl.gpu_mux {
let gfx_dbus = self.bios_proxy.clone();
gpu_menu.add("Ultimate (Reboot required)", move |_| {
let mode = gfx_dbus
.gpu_mux_mode()
.map_err(|e| {
error!("ROGTray: mode: {e}");
e
})
.unwrap_or(GpuMode::Error);
if mode != GpuMode::Discrete {
gfx_dbus
.set_gpu_mux_mode(GpuMode::Discrete)
.map_err(|e| {
error!("ROGTray: set_mode: {e}");
e
})
.ok();
}
});
if set_mux_off.load(Ordering::Relaxed) {
warn!("Selected non-dgpu mode, must set MUX to optimus");
self.bios_proxy
.set_gpu_mux_mode(GpuMode::Optimus)
.map_err(|e| {
let gfx_action = self.gfx_action.clone();
gpu_menu.add(&format!("{menu_mode}"), move |_| {
if current_mode != menu_mode {
if let Ok(res) = gfx_dbus.set_mode(&menu_mode).map_err(|e| {
error!("ROGTray: set_mode: {e}");
e
})
.ok();
}
if let Ok(mode) = self.bios_proxy.gpu_mux_mode() {
let mode = match mode {
GpuMode::Discrete => GfxMode::AsusMuxDiscreet,
_ => GfxMode::Hybrid,
};
reboot_required = mode != current_mode;
}
}
let active = match current_mode {
GfxMode::AsusMuxDiscreet => "Discreet".to_owned(),
_ => current_mode.to_string(),
}) {
if let Ok(mut lock) = gfx_action.lock() {
*lock = res;
}
}
}
});
};
let reboot_required = if reboot_required {
"(Reboot required)"
for item in supported_gfx {
if *item == GfxMode::Integrated {
continue;
}
func(*item);
}
let action_required = if let Ok(lock) = self.gfx_action.lock() {
if matches!(*lock, GfxUserActionRequired::Nothing) {
""
} else {
<&str>::from(*lock)
}
} else {
""
};
self.add_radio_sub_menu(
&format!("GPU Mode: {active} {reboot_required}"),
active.as_str(),
&format!("GPU Mode: {current_mode} {action_required}"),
&current_mode.to_string(),
&gpu_menu,
);
@@ -376,7 +332,7 @@ impl ROGTray {
let mut reboot_required = false;
if let Ok(mode) = gfx_dbus.gpu_mux_mode() {
let mode = match mode {
GpuMode::Discrete => GfxMode::AsusMuxDiscreet,
GpuMode::Discrete => GfxMode::AsusMuxDgpu,
_ => GfxMode::Hybrid,
};
reboot_required = mode != current_mode;
@@ -406,7 +362,7 @@ impl ROGTray {
});
let active = match current_mode {
GfxMode::AsusMuxDiscreet => "Ultimate".to_owned(),
GfxMode::AsusMuxDgpu => "Ultimate".to_owned(),
GfxMode::Hybrid => "Optimus".to_owned(),
_ => current_mode.to_string(),
};
@@ -441,17 +397,20 @@ impl ROGTray {
fn rebuild_and_update(
&mut self,
supported: &SupportedFunctions,
has_supergfx: bool,
supported_gfx: &[GfxMode],
current_gfx_mode: GfxMode,
charge_limit: u8,
panel_od: bool,
mini_led: bool,
) {
self.menu_clear();
self.menu_add_base();
self.menu_add_charge_limit(supported, charge_limit);
self.menu_add_panel_od(supported, panel_od);
if has_supergfx {
self.menu_add_gpu(supported, current_gfx_mode);
self.menu_add_mini_led_mode(supported, mini_led);
if self.gfx_proxy_is_active {
// Add a supergfxctl specific menu
self.menu_add_supergfx(supported_gfx, current_gfx_mode);
} else if supported.rog_bios_ctrl.gpu_mux {
self.menu_add_mux(current_gfx_mode);
}
@@ -466,20 +425,12 @@ pub fn init_tray(
let (send, recv) = channel();
let _send = Arc::new(Mutex::new(send));
let has_supergfx = if let Ok(lock) = states.try_lock() {
lock.gfx_state.has_supergfx
} else {
false
};
std::thread::spawn(move || {
if gtk::init()
.map_err(|e| {
error!("ROGTray: gtk init {e}");
e
})
.is_err()
{
let gtk_init = gtk::init().map_err(|e| {
error!("ROGTray: gtk init {e}");
e
});
if gtk_init.is_err() {
return;
} // Make this the main thread for gtk
debug!("init_tray gtk");
@@ -497,7 +448,36 @@ pub fn init_tray(
return;
}
};
tray.rebuild_and_update(&supported, has_supergfx, GfxMode::Hybrid, 100, false);
let supported_gfx = if tray.gfx_proxy_is_active {
if let Ok(version) = tray.gfx_proxy.version() {
if let Some(version) = Versioning::new(&version) {
let curr_gfx = Versioning::new("5.0.3-RC4").unwrap();
warn!("supergfxd version = {version}");
if version < curr_gfx {
// Don't allow mode changing if too old a version
warn!("supergfxd found but is too old to use");
tray.gfx_proxy_is_active = false;
}
}
}
if tray.gfx_proxy_is_active {
tray.gfx_proxy.supported().unwrap()
} else {
Default::default()
}
} else {
Default::default()
};
tray.rebuild_and_update(
&supported,
&supported_gfx,
GfxMode::Hybrid,
100,
false,
false,
);
tray.set_icon(TRAY_APP_ICON);
info!("Started ROGTray");
@@ -509,29 +489,36 @@ pub fn init_tray(
lock.gfx_state.mode
} else {
match lock.bios.dedicated_gfx {
GpuMode::Discrete => GfxMode::AsusMuxDiscreet,
GpuMode::Discrete => GfxMode::AsusMuxDgpu,
_ => GfxMode::Hybrid,
}
};
tray.rebuild_and_update(
&supported,
has_supergfx,
&supported_gfx,
current_gpu_mode,
lock.power_state.charge_limit,
lock.bios.panel_overdrive,
lock.bios.mini_led_mode,
);
lock.tray_should_update = false;
debug!("ROGTray: rebuilt menus due to state change");
match lock.gfx_state.power_status {
GfxPower::Suspended => tray.set_icon("asus_notif_blue"),
GfxPower::Off => tray.set_icon("asus_notif_green"),
GfxPower::Off => {
if lock.gfx_state.mode == GfxMode::Vfio {
tray.set_icon("asus_notif_red")
} else {
tray.set_icon("asus_notif_green")
}
}
GfxPower::AsusDisabled => tray.set_icon("asus_notif_white"),
GfxPower::AsusMuxDiscreet | GfxPower::Active => {
tray.set_icon("asus_notif_red");
}
GfxPower::Unknown => {
if has_supergfx {
if tray.gfx_proxy_is_active {
tray.set_icon("gpu-integrated");
} else {
tray.set_icon("asus_notif_red");
+128 -76
View File
@@ -1,6 +1,8 @@
//! `update_and_notify` is responsible for both notifications *and* updating
//! stored statuses about the system state. This is done through either direct,
//! intoify, zbus notifications or similar methods.
//!
//! This module very much functions like a stand-alone app on its own thread.
use std::fmt::Display;
use std::process::Command;
@@ -17,7 +19,8 @@ use rog_dbus::zbus_profile::ProfileProxy;
use rog_platform::platform::GpuMode;
use rog_profiles::Profile;
use serde::{Deserialize, Serialize};
use supergfxctl::pci_device::GfxPower;
use supergfxctl::actions::UserActionRequired as GfxUserAction;
use supergfxctl::pci_device::{GfxMode, GfxPower};
use supergfxctl::zbus_proxy::DaemonProxy as SuperProxy;
use tokio::time::sleep;
use zbus::export::futures_util::{future, StreamExt};
@@ -36,6 +39,7 @@ static mut POWER_BAT_CMD: Option<Command> = None;
pub struct EnabledNotifications {
pub receive_notify_post_boot_sound: bool,
pub receive_notify_panel_od: bool,
pub receive_notify_mini_led_mode: bool,
pub receive_notify_dgpu_disable: bool,
pub receive_notify_egpu_enable: bool,
pub receive_notify_gpu_mux_mode: bool,
@@ -55,6 +59,7 @@ impl Default for EnabledNotifications {
Self {
receive_notify_post_boot_sound: false,
receive_notify_panel_od: true,
receive_notify_mini_led_mode: true,
receive_notify_dgpu_disable: true,
receive_notify_egpu_enable: true,
receive_notify_gpu_mux_mode: true,
@@ -76,17 +81,6 @@ impl EnabledNotifications {
}
}
macro_rules! notify {
($notifier:expr, $last_notif:ident) => {
if let Some(notif) = $last_notif.take() {
notif.close();
}
if let Ok(x) = $notifier {
$last_notif.replace(x);
}
};
}
// TODO: drop the macro and use generics plus closure
macro_rules! recv_notif {
($proxy:ident,
@@ -99,7 +93,6 @@ macro_rules! recv_notif {
$msg:literal,
$notifier:ident) => {
let last_notif = $last_notif.clone();
let notifs_enabled1 = $notif_enabled.clone();
let page_states1 = $page_states.clone();
@@ -118,10 +111,8 @@ macro_rules! recv_notif {
if let Ok(out) = e.args() {
if let Ok(config) = notifs_enabled1.lock() {
if config.all_enabled && config.$signal {
if let Ok(ref mut lock) = last_notif.lock() {
trace!("zbus signal {} locked last_notif", stringify!($signal));
notify!($notifier($msg, &out.$($out_arg)+()), lock);
}
trace!("zbus signal {}", stringify!($signal));
$notifier($msg, &out.$($out_arg)+()).ok();
}
}
if let Ok(mut lock) = page_states1.lock() {
@@ -129,21 +120,18 @@ macro_rules! recv_notif {
lock.set_notified();
}
}
sleep(Duration::from_millis(500)).await;
}
};
});
};
}
type SharedHandle = Arc<Mutex<Option<NotificationHandle>>>;
pub fn start_notifications(
config: &Config,
page_states: Arc<Mutex<SystemState>>,
enabled_notifications: Arc<Mutex<EnabledNotifications>>,
page_states: &Arc<Mutex<SystemState>>,
enabled_notifications: &Arc<Mutex<EnabledNotifications>>,
) -> Result<()> {
let last_notification: SharedHandle = Arc::new(Mutex::new(None));
// Setup the AC/BAT commands that will run on poweer status change
unsafe {
let prog: Vec<&str> = config.ac_command.split_whitespace().collect();
@@ -193,6 +181,18 @@ pub fn start_notifications(
do_notification
);
recv_notif!(
RogBiosProxy,
receive_notify_mini_led_mode,
last_notification,
enabled_notifications,
page_states,
(bios.mini_led_mode),
(on),
"MiniLED mode enabled:",
do_notification
);
recv_notif!(
RogBiosProxy,
receive_notify_dgpu_disable,
@@ -285,7 +285,7 @@ pub fn start_notifications(
e
})
.unwrap();
if let Ok(p) = proxy.receive_power_states().await {
if let Ok(p) = proxy.receive_device_state().await {
info!("Started zbus signal thread: receive_power_states");
p.for_each(|_| {
if let Ok(_lock) = page_states1.lock() {
@@ -298,7 +298,6 @@ pub fn start_notifications(
});
let page_states1 = page_states.clone();
let last_notification1 = last_notification.clone();
tokio::spawn(async move {
let conn = zbus::Connection::system()
.await
@@ -331,11 +330,6 @@ pub fn start_notifications(
lock.bios.dedicated_gfx = out.mode;
lock.set_notified();
}
if let Ok(ref mut lock) = last_notification1.lock() {
if let Some(notif) = lock.take() {
notif.close();
}
}
do_mux_notification("Reboot required. BIOS GPU MUX mode set to", &out.mode)
.ok();
}
@@ -350,7 +344,6 @@ pub fn start_notifications(
for dev in dev {
if dev.is_dgpu() {
let notifs_enabled1 = enabled_notifications.clone();
let last_notif = last_notification.clone();
let page_states1 = page_states.clone();
// Plain old thread is perfectly fine since most of this is potentially blocking
tokio::spawn(async move {
@@ -362,15 +355,7 @@ pub fn start_notifications(
if config.all_enabled && config.receive_notify_gfx_status {
// Required check because status cycles through
// active/unknown/suspended
if let Ok(ref mut lock) = last_notif.lock() {
notify!(
do_gpu_status_notif(
"dGPU status changed:",
&status
),
lock
);
}
do_gpu_status_notif("dGPU status changed:", &status).ok();
}
}
if let Ok(mut lock) = page_states1.lock() {
@@ -406,6 +391,7 @@ pub fn start_notifications(
do_notification
);
let page_states1 = page_states.clone();
tokio::spawn(async move {
let conn = zbus::Connection::system()
.await
@@ -426,15 +412,25 @@ pub fn start_notifications(
while let Some(e) = p.next().await {
if let Ok(out) = e.args() {
let action = out.action();
do_gfx_action_notif(
"Gfx mode change requires",
&format!("{action:?}",),
)
let mode = if let Ok(lock) = page_states1.lock() {
convert_gfx_mode(lock.gfx_state.mode)
} else {
GpuMode::Error
};
match action {
supergfxctl::actions::UserActionRequired::Reboot => {
do_mux_notification(
"Graphics mode change requires reboot",
&mode,
)
}
_ => do_gfx_action_notif(<&str>::from(action), *action, mode),
}
.map_err(|e| {
error!("zbus signal: do_gfx_action_notif: {e}");
e
})
.unwrap();
.ok();
}
}
};
@@ -445,6 +441,18 @@ pub fn start_notifications(
Ok(())
}
fn convert_gfx_mode(gfx: GfxMode) -> GpuMode {
match gfx {
GfxMode::Hybrid => GpuMode::Optimus,
GfxMode::Integrated => GpuMode::Integrated,
GfxMode::NvidiaNoModeset => GpuMode::Discrete,
GfxMode::Vfio => GpuMode::Vfio,
GfxMode::AsusEgpu => GpuMode::Egpu,
GfxMode::AsusMuxDgpu => GpuMode::Ultimate,
GfxMode::None => GpuMode::Error,
}
}
fn base_notification<T>(message: &str, data: &T) -> Notification
where
T: Display,
@@ -454,7 +462,7 @@ where
notif
.summary(NOTIF_HEADER)
.body(&format!("{message} {data}"))
.timeout(2000)
.timeout(-1)
//.hint(Hint::Resident(true))
.hint(Hint::Category("device".into()));
@@ -516,47 +524,91 @@ fn do_gpu_status_notif(message: &str, data: &GfxPower) -> Result<NotificationHan
Ok(Notification::show(&notif)?)
}
fn do_gfx_action_notif<T>(message: &str, data: &T) -> Result<()>
where
T: Display,
{
let mut notif = base_notification(message, data);
notif.action("gnome-session-quit", "Logout");
notif.urgency(Urgency::Critical);
notif.timeout(3000);
notif.icon("dialog-warning");
notif.hint(Hint::Transient(true));
let handle = notif.show()?;
handle.wait_for_action(|id| {
if id == "gnome-session-quit" {
let mut cmd = Command::new("gnome-session-quit");
cmd.spawn().ok();
} else if id == "__closed" {
// TODO: cancel the switching
fn do_gfx_action_notif(message: &str, action: GfxUserAction, mode: GpuMode) -> Result<()> {
if matches!(action, GfxUserAction::Reboot) {
do_mux_notification("Graphics mode change requires reboot", &mode).ok();
return Ok(());
}
let mut notif = Notification::new();
notif
.summary(NOTIF_HEADER)
.body(&format!("Changing to {mode}. {message}"))
.timeout(2000)
//.hint(Hint::Resident(true))
.hint(Hint::Category("device".into()))
.urgency(Urgency::Critical)
.timeout(-1)
.icon("dialog-warning")
.hint(Hint::Transient(true));
if matches!(action, GfxUserAction::Logout) {
notif.action("gfx-mode-session-action", "Logout");
let handle = notif.show()?;
if let Ok(desktop) = std::env::var("XDG_CURRENT_DESKTOP") {
if desktop.to_lowercase() == "gnome" {
handle.wait_for_action(|id| {
if id == "gfx-mode-session-action" {
let mut cmd = Command::new("gnome-session-quit");
cmd.spawn().ok();
} else if id == "__closed" {
// TODO: cancel the switching
}
});
} else if desktop.to_lowercase() == "kde" {
handle.wait_for_action(|id| {
if id == "gfx-mode-session-action" {
let mut cmd = Command::new("qdbus");
cmd.args(["org.kde.ksmserver", "/KSMServer", "logout", "1", "0", "0"]);
cmd.spawn().ok();
} else if id == "__closed" {
// TODO: cancel the switching
}
});
} else {
// todo: handle alternatives
}
}
});
} else {
notif.show()?;
}
Ok(())
}
/// Actual `GpuMode` unused as data is never correct until switched by reboot
fn do_mux_notification(message: &str, m: &GpuMode) -> Result<()> {
let mut notif = base_notification(message, &m.to_string());
notif.action("gnome-session-quit", "Reboot");
notif.urgency(Urgency::Critical);
notif.icon("system-reboot-symbolic");
notif.hint(Hint::Transient(true));
notif
.action("gfx-mode-session-action", "Reboot")
.urgency(Urgency::Critical)
.icon("system-reboot-symbolic")
.hint(Hint::Transient(true));
let handle = notif.show()?;
std::thread::spawn(|| {
handle.wait_for_action(|id| {
if id == "gnome-session-quit" {
let mut cmd = Command::new("gnome-session-quit");
cmd.arg("--reboot");
cmd.spawn().ok();
} else if id == "__closed" {
// TODO: cancel the switching
if let Ok(desktop) = std::env::var("XDG_CURRENT_DESKTOP") {
if desktop.to_lowercase() == "gnome" {
handle.wait_for_action(|id| {
if id == "gfx-mode-session-action" {
let mut cmd = Command::new("gnome-session-quit");
cmd.arg("--reboot");
cmd.spawn().ok();
} else if id == "__closed" {
// TODO: cancel the switching
}
});
} else if desktop.to_lowercase() == "kde" {
handle.wait_for_action(|id| {
if id == "gfx-mode-session-action" {
let mut cmd = Command::new("qdbus");
cmd.args(["org.kde.ksmserver", "/KSMServer", "logout", "1", "1", "0"]);
cmd.spawn().ok();
} else if id == "__closed" {
// TODO: cancel the switching
}
});
}
})
}
});
Ok(())
}
+33 -21
View File
@@ -1,4 +1,5 @@
use egui::{RichText, Ui};
use rog_anime::usb::Brightness;
use rog_platform::supported::SupportedFunctions;
use crate::system_state::SystemState;
@@ -7,42 +8,50 @@ pub fn anime_power_group(_supported: &SupportedFunctions, states: &mut SystemSta
ui.heading("AniMe Matrix Settings");
ui.label("Options are incomplete. Awake + Boot should work");
let mut changed = false;
let mut brightness = states.anime.display_brightness as u8;
ui.horizontal_wrapped(|ui| {
ui.vertical(|ui| {
let h = 16.0;
ui.set_row_height(22.0);
ui.horizontal_wrapped(|ui| {
ui.label(RichText::new("Brightness").size(h));
ui.label(RichText::new("Display brightness").size(h));
});
ui.horizontal_wrapped(|ui| {
ui.label(RichText::new("Boot").size(h));
ui.label(RichText::new("Display enabled").size(h));
});
ui.horizontal_wrapped(|ui| {
ui.label(RichText::new("Awake").size(h));
});
ui.horizontal_wrapped(|ui| {
ui.label(RichText::new("Sleep").size(h));
ui.label(RichText::new("Animations enabled").size(h));
});
// ui.horizontal_wrapped(|ui| {
// ui.label(RichText::new("Sleep").size(h));
// });
});
ui.vertical(|ui| {
ui.set_row_height(22.0);
ui.horizontal_wrapped(|ui| {
if ui.add(egui::Slider::new(&mut brightness, 0..=3)).changed() {
states
.asus_dbus
.proxies()
.anime()
.set_brightness(Brightness::from(brightness))
.map_err(|err| {
states.error = Some(err.to_string());
})
.ok();
}
});
ui.horizontal_wrapped(|ui| {
if ui
.add(egui::Slider::new(&mut states.anime.bright, 0..=254))
.checkbox(&mut states.anime.display_enabled, "Enable")
.changed()
{
changed = true;
}
});
ui.horizontal_wrapped(|ui| {
if ui.checkbox(&mut states.anime.boot, "Enable").changed() {
states
.asus_dbus
.proxies()
.anime()
.set_boot_on_off(states.anime.boot)
.set_enable_display(states.anime.display_enabled)
.map_err(|err| {
states.error = Some(err.to_string());
})
@@ -50,23 +59,26 @@ pub fn anime_power_group(_supported: &SupportedFunctions, states: &mut SystemSta
}
});
ui.horizontal_wrapped(|ui| {
if ui.checkbox(&mut states.anime.awake, "Enable").changed() {
if ui
.checkbox(&mut states.anime.builtin_anims_enabled, "Enable")
.changed()
{
states
.asus_dbus
.proxies()
.anime()
.set_on_off(states.anime.awake)
.set_builtins_enabled(states.anime.builtin_anims_enabled)
.map_err(|err| {
states.error = Some(err.to_string());
})
.ok();
}
});
ui.horizontal_wrapped(|ui| {
if ui.checkbox(&mut states.anime.sleep, "Enable").changed() {
changed = true;
}
});
// ui.horizontal_wrapped(|ui| {
// if ui.checkbox(&mut states.anime.sleep, "Enable").changed() {
// changed = true;
// }
// });
});
});
}
@@ -76,6 +76,12 @@ pub fn app_settings(config: &mut Config, states: &mut SystemState, ui: &mut Ui)
"Enable panel overdrive notification",
)
.clicked()
|| ui
.checkbox(
&mut enabled_notifications.receive_notify_mini_led_mode,
"Enable MiniLED mode notification",
)
.clicked()
|| ui
.checkbox(
&mut enabled_notifications.receive_notify_post_boot_sound,
+36 -37
View File
@@ -5,7 +5,7 @@ use egui::{RichText, Ui};
use rog_aura::layouts::KeyLayout;
use rog_aura::{AuraEffect, AuraModeNum, AuraZone, Colour, Speed};
use crate::system_state::{AuraState, SystemState};
use crate::system_state::SystemState;
pub fn aura_modes_group(states: &mut SystemState, freq: &mut Arc<AtomicU8>, ui: &mut Ui) {
let mut changed = false;
@@ -59,7 +59,7 @@ pub fn aura_modes_group(states: &mut SystemState, freq: &mut Arc<AtomicU8>, ui:
let mut zone_button = |a: AuraZone, ui: &mut Ui| {
ui.selectable_value(&mut effect.zone, a, format!("{:?}", a));
};
let mut speed_button = |a: Speed, ui: &mut Ui| {
let mut speed_button = |a: Speed, ui: &mut Ui| -> bool {
if ui
.selectable_value(&mut effect.speed, a, format!("{:?}", a))
.clicked()
@@ -70,10 +70,13 @@ pub fn aura_modes_group(states: &mut SystemState, freq: &mut Arc<AtomicU8>, ui:
Speed::High => 10,
};
freq.store(val, Ordering::SeqCst);
return true;
}
false
};
let mut dir_button = |a: rog_aura::Direction, ui: &mut Ui| {
ui.selectable_value(&mut effect.direction, a, format!("{:?}", a));
let mut dir_button = |a: rog_aura::Direction, ui: &mut Ui| -> bool {
ui.selectable_value(&mut effect.direction, a, format!("{:?}", a))
.clicked()
};
let mut c1: [u8; 3] = effect.colour1.into();
@@ -139,26 +142,37 @@ pub fn aura_modes_group(states: &mut SystemState, freq: &mut Arc<AtomicU8>, ui:
});
ui.add_enabled_ui(allowed.colour1, |ui| {
egui::color_picker::color_edit_button_srgb(ui, &mut c1)
if egui::color_picker::color_edit_button_srgb(ui, &mut c1).changed() {
changed = true;
}
});
ui.add_enabled_ui(allowed.colour2, |ui| {
egui::color_picker::color_edit_button_srgb(ui, &mut c2)
if egui::color_picker::color_edit_button_srgb(ui, &mut c2).changed() {
changed = true;
}
});
ui.add_enabled_ui(allowed.speed, |ui| {
ui.horizontal_wrapped(|ui| {
speed_button(Speed::Low, ui);
speed_button(Speed::Med, ui);
speed_button(Speed::High, ui);
if speed_button(Speed::Low, ui)
|| speed_button(Speed::Med, ui)
|| speed_button(Speed::High, ui)
{
changed = true;
}
});
});
ui.add_enabled_ui(allowed.direction, |ui| {
ui.horizontal_wrapped(|ui| {
dir_button(rog_aura::Direction::Left, ui);
dir_button(rog_aura::Direction::Down, ui);
dir_button(rog_aura::Direction::Right, ui);
dir_button(rog_aura::Direction::Up, ui);
if dir_button(rog_aura::Direction::Left, ui)
|| dir_button(rog_aura::Direction::Down, ui)
|| dir_button(rog_aura::Direction::Right, ui)
|| dir_button(rog_aura::Direction::Up, ui)
{
changed = true;
}
});
});
});
@@ -170,16 +184,16 @@ pub fn aura_modes_group(states: &mut SystemState, freq: &mut Arc<AtomicU8>, ui:
ui.separator();
ui.with_layout(egui::Layout::right_to_left(egui::Align::TOP), |ui| {
if ui.add(egui::Button::new("Cancel")).clicked() {
match AuraState::new(&aura_creation.keyboard_layout, &states.asus_dbus) {
Ok(a) => states.aura.modes = a.modes,
Err(e) => states.error = Some(e.to_string()),
}
}
// if ui.add(egui::Button::new("Cancel")).clicked() {
// match AuraState::new(&aura_creation.keyboard_layout, &states.asus_dbus) {
// Ok(a) => states.aura.modes = a.modes,
// Err(e) => states.error = Some(e.to_string()),
// }
// }
if ui.add(egui::Button::new("Apply")).clicked() {
changed = true;
}
// if ui.add(egui::Button::new("Apply")).clicked() {
// changed = true;
// }
if aura_creation.layout_testing.is_some() {
if ui.add(egui::Button::new("Next layout")).clicked() {
@@ -208,21 +222,6 @@ pub fn aura_modes_group(states: &mut SystemState, freq: &mut Arc<AtomicU8>, ui:
}
});
// egui::TopBottomPanel::bottom("error_bar")
// .default_height(26.0)
// .show(ctx, |ui| {
// ui.with_layout(egui::Layout::right_to_left(egui::Align::TOP), |ui| {
// if ui.add(egui::Button::new("Cancel")).clicked() {
// let notif = states.aura.was_notified.clone();
// states.aura.modes = AuraState::new(notif, supported,
// dbus).modes; }
// if ui.add(egui::Button::new("Apply")).clicked() {
// changed = true;
// }
// });
// });
if changed {
states.aura.current_mode = selected;
+34 -32
View File
@@ -1,5 +1,5 @@
use egui::{RichText, Ui};
use rog_aura::usb::{AuraDev1866, AuraDev19b6, AuraDevTuf, AuraDevice, AuraPowerDev};
use rog_aura::usb::{AuraDevRog1, AuraDevRog2, AuraDevTuf, AuraDevice, AuraPowerDev};
use rog_aura::AuraZone;
use rog_platform::supported::SupportedFunctions;
@@ -12,7 +12,9 @@ pub fn aura_power_group(supported: &SupportedFunctions, states: &mut SystemState
AuraDevice::X1854 | AuraDevice::X1869 | AuraDevice::X1866 => {
aura_power1(supported, states, ui);
}
AuraDevice::X19B6 => aura_power2(supported, states, ui),
AuraDevice::X19b6 | AuraDevice::X18c6 | AuraDevice::X1a30 => {
aura_power2(supported, states, ui)
}
AuraDevice::Tuf => aura_power1(supported, states, ui),
AuraDevice::Unknown => {}
}
@@ -20,10 +22,10 @@ pub fn aura_power_group(supported: &SupportedFunctions, states: &mut SystemState
fn aura_power1(supported: &SupportedFunctions, states: &mut SystemState, ui: &mut Ui) {
let enabled_states = &mut states.aura.enabled;
let mut boot = enabled_states.x1866.contains(&AuraDev1866::Boot);
let mut sleep = enabled_states.x1866.contains(&AuraDev1866::Sleep);
let mut keyboard = enabled_states.x1866.contains(&AuraDev1866::Keyboard);
let mut lightbar = enabled_states.x1866.contains(&AuraDev1866::Lightbar);
let mut boot = enabled_states.x1866.contains(&AuraDevRog1::Boot);
let mut sleep = enabled_states.x1866.contains(&AuraDevRog1::Sleep);
let mut keyboard = enabled_states.x1866.contains(&AuraDevRog1::Keyboard);
let mut lightbar = enabled_states.x1866.contains(&AuraDevRog1::Lightbar);
if supported.keyboard_led.dev_id == AuraDevice::Tuf {
boot = enabled_states.tuf.contains(&AuraDevTuf::Boot);
sleep = enabled_states.tuf.contains(&AuraDevTuf::Sleep);
@@ -148,7 +150,7 @@ fn aura_power1(supported: &SupportedFunctions, states: &mut SystemState, ui: &mu
let mut enabled = Vec::new();
let mut disabled = Vec::new();
let mut modify_x1866 = |b: bool, a: AuraDev1866| {
let mut modify_x1866 = |b: bool, a: AuraDevRog1| {
if b {
enabled.push(a);
if !enabled_states.x1866.contains(&a) {
@@ -169,14 +171,14 @@ fn aura_power1(supported: &SupportedFunctions, states: &mut SystemState, ui: &mu
}
}
};
modify_x1866(boot, AuraDev1866::Boot);
modify_x1866(sleep, AuraDev1866::Sleep);
modify_x1866(keyboard, AuraDev1866::Keyboard);
modify_x1866(boot, AuraDevRog1::Boot);
modify_x1866(sleep, AuraDevRog1::Sleep);
modify_x1866(keyboard, AuraDevRog1::Keyboard);
if !supported.keyboard_led.basic_zones.is_empty() {
modify_x1866(lightbar, AuraDev1866::Lightbar);
modify_x1866(lightbar, AuraDevRog1::Lightbar);
}
let mut send = |enable: bool, data: Vec<AuraDev1866>| {
let mut send = |enable: bool, data: Vec<AuraDevRog1>| {
let options = AuraPowerDev {
tuf: vec![],
x1866: data,
@@ -211,17 +213,17 @@ fn aura_power2(supported: &SupportedFunctions, states: &mut SystemState, ui: &mu
.basic_zones
.contains(&AuraZone::BarRight);
let boot_bar = &mut enabled_states.x19b6.contains(&AuraDev19b6::AwakeBar);
let boot_logo = &mut enabled_states.x19b6.contains(&AuraDev19b6::BootLogo);
let boot_keyb = &mut enabled_states.x19b6.contains(&AuraDev19b6::BootKeyb);
let boot_bar = &mut enabled_states.x19b6.contains(&AuraDevRog2::AwakeBar);
let boot_logo = &mut enabled_states.x19b6.contains(&AuraDevRog2::BootLogo);
let boot_keyb = &mut enabled_states.x19b6.contains(&AuraDevRog2::BootKeyb);
let awake_bar = &mut enabled_states.x19b6.contains(&AuraDev19b6::BootBar);
let awake_logo = &mut enabled_states.x19b6.contains(&AuraDev19b6::AwakeLogo);
let awake_keyb = &mut enabled_states.x19b6.contains(&AuraDev19b6::AwakeKeyb);
let awake_bar = &mut enabled_states.x19b6.contains(&AuraDevRog2::BootBar);
let awake_logo = &mut enabled_states.x19b6.contains(&AuraDevRog2::AwakeLogo);
let awake_keyb = &mut enabled_states.x19b6.contains(&AuraDevRog2::AwakeKeyb);
let sleep_bar = &mut enabled_states.x19b6.contains(&AuraDev19b6::SleepBar);
let sleep_logo = &mut enabled_states.x19b6.contains(&AuraDev19b6::SleepLogo);
let sleep_keyb = &mut enabled_states.x19b6.contains(&AuraDev19b6::SleepKeyb);
let sleep_bar = &mut enabled_states.x19b6.contains(&AuraDevRog2::SleepBar);
let sleep_logo = &mut enabled_states.x19b6.contains(&AuraDevRog2::SleepLogo);
let sleep_keyb = &mut enabled_states.x19b6.contains(&AuraDevRog2::SleepKeyb);
let mut changed = false;
@@ -265,7 +267,7 @@ fn aura_power2(supported: &SupportedFunctions, states: &mut SystemState, ui: &mu
let mut enabled = Vec::new();
let mut disabled = Vec::new();
let mut modify = |b: bool, a: AuraDev19b6| {
let mut modify = |b: bool, a: AuraDevRog2| {
if b {
enabled.push(a);
if !enabled_states.x19b6.contains(&a) {
@@ -286,25 +288,25 @@ fn aura_power2(supported: &SupportedFunctions, states: &mut SystemState, ui: &mu
}
}
};
modify(*boot_keyb, AuraDev19b6::BootKeyb);
modify(*sleep_keyb, AuraDev19b6::SleepKeyb);
modify(*awake_keyb, AuraDev19b6::AwakeKeyb);
modify(*boot_keyb, AuraDevRog2::BootKeyb);
modify(*sleep_keyb, AuraDevRog2::SleepKeyb);
modify(*awake_keyb, AuraDevRog2::AwakeKeyb);
if supported.keyboard_led.basic_zones.contains(&AuraZone::Logo) {
modify(*boot_logo, AuraDev19b6::BootLogo);
modify(*sleep_logo, AuraDev19b6::SleepLogo);
modify(*awake_logo, AuraDev19b6::AwakeLogo);
modify(*boot_logo, AuraDevRog2::BootLogo);
modify(*sleep_logo, AuraDevRog2::SleepLogo);
modify(*awake_logo, AuraDevRog2::AwakeLogo);
}
if supported
.keyboard_led
.basic_zones
.contains(&AuraZone::BarLeft)
{
modify(*boot_bar, AuraDev19b6::AwakeBar);
modify(*sleep_bar, AuraDev19b6::SleepBar);
modify(*awake_bar, AuraDev19b6::BootBar);
modify(*boot_bar, AuraDevRog2::AwakeBar);
modify(*sleep_bar, AuraDevRog2::SleepBar);
modify(*awake_bar, AuraDevRog2::BootBar);
}
let mut send = |enable: bool, data: Vec<AuraDev19b6>| {
let mut send = |enable: bool, data: Vec<AuraDevRog2>| {
let options = AuraPowerDev {
tuf: vec![],
x1866: vec![],
@@ -25,7 +25,7 @@ pub fn keyboard(
AdvancedAuraType::None => (false, keyboard_layout.max_width(), false),
AdvancedAuraType::Zoned(zones) => {
let width = if let Some(row) = keyboard_layout.rows_ref().get(2) {
row.width() as f32
row.width()
} else {
0.0
};
+20 -1
View File
@@ -74,7 +74,7 @@ pub fn rog_bios_group(supported: &SupportedFunctions, states: &mut SystemState,
.ok();
}
if supported.rog_bios_ctrl.post_sound
if supported.rog_bios_ctrl.panel_overdrive
&& ui
.add(egui::Checkbox::new(
&mut states.bios.panel_overdrive,
@@ -93,6 +93,25 @@ pub fn rog_bios_group(supported: &SupportedFunctions, states: &mut SystemState,
.ok();
}
if supported.rog_bios_ctrl.mini_led_mode
&& ui
.add(egui::Checkbox::new(
&mut states.bios.mini_led_mode,
"MiniLED backlight",
))
.changed()
{
states
.asus_dbus
.proxies()
.rog_bios()
.set_mini_led_mode(states.bios.mini_led_mode)
.map_err(|err| {
states.error = Some(err.to_string());
})
.ok();
}
if supported.rog_bios_ctrl.gpu_mux {
let mut changed = false;
let mut dedicated_gfx = states.bios.dedicated_gfx;
+31 -1
View File
@@ -8,7 +8,7 @@ impl RogApp {
// The top panel is often a good place for a menu bar:
egui::menu::bar(ui, |ui| {
ui.horizontal(|ui| {
egui::global_dark_light_mode_buttons(ui);
self.dark_light_mode_buttons(ui);
egui::warn_if_debug_build(ui);
});
@@ -45,4 +45,34 @@ impl RogApp {
});
});
}
fn dark_light_mode_buttons(&mut self, ui: &mut egui::Ui) {
let load_from_cfg = self.config.dark_mode != ui.ctx().style().visuals.dark_mode;
if ui
.add(egui::SelectableLabel::new(
!self.config.dark_mode,
"☀ Light",
))
.clicked()
|| (load_from_cfg && !self.config.dark_mode)
{
ui.ctx().set_visuals(egui::Visuals::light());
}
if ui
.add(egui::SelectableLabel::new(self.config.dark_mode, "🌙 Dark"))
.clicked()
|| (load_from_cfg && self.config.dark_mode)
{
ui.ctx().set_visuals(egui::Visuals::dark());
}
let applied_dark_mode = ui.ctx().style().visuals.dark_mode;
if self.config.dark_mode != applied_dark_mode {
self.config.dark_mode = applied_dark_mode;
let tmp = self.config.enabled_notifications.clone();
self.config.save(&tmp).ok();
}
}
}
+4 -1
View File
@@ -10,8 +10,11 @@ description = "dbus interface methods for asusctl"
edition = "2021"
[dependencies]
rog_anime = { path = "../rog-anime" }
rog_anime = { path = "../rog-anime", features = ["dbus"] }
rog_aura = { path = "../rog-aura" }
rog_profiles = { path = "../rog-profiles" }
rog_platform = { path = "../rog-platform" }
zbus.workspace = true
[dev-dependencies]
cargo-husky.workspace = true
+22 -14
View File
@@ -1,4 +1,5 @@
use rog_anime::{AnimeDataBuffer, AnimePowerStates};
use rog_anime::usb::{AnimAwake, AnimBooting, AnimShutdown, AnimSleeping, Brightness};
use rog_anime::{AnimeDataBuffer, DeviceState as AnimeDeviceState};
use zbus::dbus_proxy;
#[dbus_proxy(
@@ -6,29 +7,36 @@ use zbus::dbus_proxy;
default_path = "/org/asuslinux/Anime"
)]
trait Anime {
/// Set whether the AniMe will show boot, suspend, or off animations
fn set_boot_on_off(&self, status: bool) -> zbus::Result<()>;
/// Set the global (image) brightness
fn set_image_brightness(&self, bright: f32) -> zbus::Result<()>;
/// Set the global AniMe brightness
fn set_brightness(&self, bright: f32) -> zbus::Result<()>;
/// Set the global base brightness
fn set_brightness(&self, bright: Brightness) -> zbus::Result<()>;
/// Set whether the AniMe will show boot, suspend, or off animations
fn set_builtins_enabled(&self, enabled: bool) -> zbus::Result<()>;
/// Set which builtin animation is used for each stage
fn set_builtin_animations(
&self,
boot: AnimBooting,
awake: AnimAwake,
sleep: AnimSleeping,
shutdown: AnimShutdown,
) -> zbus::Result<()>;
/// Set whether the AniMe is displaying images/data
fn set_on_off(&self, status: bool) -> zbus::Result<()>;
fn set_enable_display(&self, status: bool) -> zbus::Result<()>;
/// Writes a data stream of length. Will force system thread to exit until
/// it is restarted
fn write(&self, input: AnimeDataBuffer) -> zbus::Result<()>;
/// Get status of if the AniMe LEDs are on
#[dbus_proxy(property)]
fn awake_enabled(&self) -> zbus::Result<bool>;
/// Get the status of if factory system-status animations are enabled
#[dbus_proxy(property)]
fn boot_enabled(&self) -> zbus::Result<bool>;
// #[dbus_proxy(property)]
fn device_state(&self) -> zbus::Result<AnimeDeviceState>;
/// Notify listeners of the status of AniMe LED power and factory
/// system-status animations
#[dbus_proxy(signal)]
fn power_states(&self, data: AnimePowerStates) -> zbus::Result<()>;
fn device_state(&self, data: AnimeDeviceState) -> zbus::Result<()>;
}
+4 -4
View File
@@ -1,6 +1,6 @@
//! # DBus interface proxy for: `org.asuslinux.Daemon`
//! # `DBus` interface proxy for: `org.asuslinux.Daemon`
//!
//! This code was generated by `zbus-xmlgen` `1.0.0` from DBus introspection
//! This code was generated by `zbus-xmlgen` `1.0.0` from `DBus` introspection
//! data. Source: `Interface '/org/asuslinux/Aura' from service
//! 'org.asuslinux.Daemon' on system bus`.
//!
@@ -10,8 +10,8 @@
//! [Writing a client proxy](https://zeenix.pages.freedesktop.org/zbus/client.html)
//! section of the zbus documentation.
//!
//! This DBus object implements
//! [standard DBus interfaces](https://dbus.freedesktop.org/doc/dbus-specification.html),
//! 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`]

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