diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..ed6894e5 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,23 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +indent_style = space +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false + +[*.rs] +indent_size = 4 + +[tests/**/*.rs] +charset = utf-8 +end_of_line = unset +indent_size = unset +indent_style = unset +trim_trailing_whitespace = unset +insert_final_newline = unset diff --git a/.gitignore b/.gitignore index 047fdb52..39daca04 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,6 @@ vendor vendor-* vendor_* .vscode-ctags -.vscode \ No newline at end of file +.vscode +.~lock.* +*.ods# \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ad13eef..8d266993 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,11 +8,31 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Added option to set `disable_nvidia_powerd_on_battery` - Add short log entry to throttle_thermal_policy change detection +- ROGCC: Don't notify user if changing to same mux mode +- ROGCC: Add CLI opt for loading a keyboard layout for testing, with live-reload on file change +- 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 +### BREAKING +- Rename aura dbus method from `per_key_raw` to `direct_addressing_raw` and add doc comment +- Changes to aura.conf: +- Changes to asusd-ledmodes.toml: + + Rename `standard` to `basic_modes` + + Rename `multizone` to `basic_zones` + + Raname `per_key` to `advanced` and change type from `bool` to `AdvancedAuraType` + + Removed `prod_family` + + Split all entries to `board_name` (separating `board_names`) (now a huge file) + + removed `asusd-ledmodes.toml` in favour of `aura_support.ron` due to an unsupported type in toml +- Rename and adjust `LedSupportedFunctions` to closely match the above ## [v4.5.8] ### Changed - Fix incorrect stop/start order of nvidia-powerd on AC plug/unplug +## [v4.5.7] +### Changed +- ROGCC: Don't notify user if changing to same mux mode +- + ## [v4.5.7] ### Changed - ROGCC: Don't notify user if changing to same mux mode @@ -576,6 +596,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix small deadlock with awaits -## [1.0.0] - 2020-08-13 - -- Major fork and refactor to use asus-hid patch for ASUS N-Key device +## [1.0.0] \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 16b4cf60..969dc3d2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -292,9 +292,9 @@ checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524" [[package]] name = "async-trait" -version = "0.1.59" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6e93155431f3931513b243d371981bb2770112b370c82745a1d19d2f99364" +checksum = "677d1d8ab452a3936018a687b20e6f7cf5363d713b732b8884001317b0e48aa3" dependencies = [ "proc-macro2", "quote", @@ -349,6 +349,12 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + [[package]] name = "bindgen" version = "0.54.0" @@ -500,9 +506,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.77" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4" +checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" [[package]] name = "cesu8" @@ -1770,15 +1776,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - [[package]] name = "hermit-abi" version = "0.2.6" @@ -1866,7 +1863,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "927609f78c2913a6f6ac3c27a4fe87f43e2a35367c0c4b0f8265e8f49a104330" dependencies = [ - "hermit-abi 0.2.6", + "hermit-abi", "io-lifetimes", "rustix", "windows-sys 0.42.0", @@ -1960,9 +1957,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.138" +version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" [[package]] name = "libloading" @@ -2023,9 +2020,9 @@ dependencies = [ [[package]] name = "logind-zbus" -version = "3.0.3" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "214b1739f5cf1b467329c1a7b42e9b142aee6dce3f38a86cf902b5b6ac1b55b3" +checksum = "3f2cfc54565c8d002ad7344ec08ce512c269b2de56dea59850708691e4b18fe3" dependencies = [ "serde", "zbus", @@ -2275,11 +2272,11 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" dependencies = [ - "hermit-abi 0.1.19", + "hermit-abi", "libc", ] @@ -2520,9 +2517,9 @@ dependencies = [ [[package]] name = "polling" -version = "2.5.1" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "166ca89eb77fd403230b9c156612965a81e094ec6ec3aa13663d4c8b113fa748" +checksum = "22122d5ec4f9fe1b3916419b76be1e80bcb93f618d071d2edf841b137b2a2bd6" dependencies = [ "autocfg", "cfg-if 1.0.0", @@ -2575,9 +2572,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.47" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" dependencies = [ "unicode-ident", ] @@ -2593,9 +2590,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" dependencies = [ "proc-macro2", ] @@ -2704,6 +2701,7 @@ dependencies = [ "egui", "env_logger", "gtk", + "gumdrop", "libappindicator", "log", "nix 0.26.1", @@ -2744,10 +2742,11 @@ dependencies = [ name = "rog_aura" version = "4.5.8" dependencies = [ + "log", + "ron", "serde", "serde_derive", - "serde_json", - "toml", + "sysfs-class", "zbus", ] @@ -2788,6 +2787,17 @@ dependencies = [ "zbus", ] +[[package]] +name = "ron" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300a51053b1cb55c80b7a9fde4120726ddf25ca241a1cbb926626f62fb136bff" +dependencies = [ + "base64", + "bitflags", + "serde", +] + [[package]] name = "rusb" version = "0.9.1" @@ -2895,18 +2905,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.149" +version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "256b9932320c590e707b94576e3cc1f7c9024d0ee6612dfbcf1cb106cbe8e055" +checksum = "97fed41fc1a24994d044e6db6935e69511a1153b52c15eb42493b26fa87feba0" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.149" +version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4eae9b04cbffdfd550eb462ed33bc6a1b68c935127d008b27444d08380f94e4" +checksum = "255abe9a125a985c05190d687b320c12f9b1f0b99445e608c21ba0782c719ad8" dependencies = [ "proc-macro2", "quote", @@ -2926,9 +2936,9 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fe39d9fbb0ebf5eb2c7cb7e2a47e4f462fad1379f1166b8ae49ad9eae89a7ca" +checksum = "9a5ec9fa74a20ebbe5d9ac23dac1fc96ba0ecfe9f50f2843b52e537b10fbcb4e" dependencies = [ "proc-macro2", "quote", @@ -3130,9 +3140,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.105" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" dependencies = [ "proc-macro2", "quote", @@ -3207,18 +3217,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" +checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" +checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" dependencies = [ "proc-macro2", "quote", @@ -3319,9 +3329,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.9" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" +checksum = "1333c76748e868a4d9d1017b5ab53171dfd095f70c712fdb4653a406547f598f" dependencies = [ "serde", ] @@ -3436,9 +3446,9 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] name = "unicode-ident" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" [[package]] name = "unicode-normalization" diff --git a/Cargo.toml b/Cargo.toml index 28b731f4..a50fd449 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,18 +6,18 @@ version = "4.5.8" [workspace.dependencies] async-trait = "^0.1" -tokio = { version = "^1.22.0", features = ["macros", "rt-multi-thread", "time", "sync"]} +tokio = { version = "^1.23.0", features = ["macros", "rt-multi-thread", "time", "sync"]} concat-idents = "^1.1" dirs = "^4.0" smol = "^1.3" -zbus = "^3.5" -logind-zbus = { version = "^3.0.3" } #, default-features = false, features = ["non_blocking"] } +zbus = "^3.6" +logind-zbus = { version = "^3.1.0" } #, default-features = false, features = ["non_blocking"] } serde = "^1.0" serde_derive = "^1.0" serde_json = "^1.0" -toml = "^0.5.9" +toml = "^0.5.10" log = "^0.4" env_logger = "^0.10.0" diff --git a/Makefile b/Makefile index 400c7a7f..316ee132 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ BIN_ROG := rog-control-center BIN_C := asusctl BIN_D := asusd BIN_U := asusd-user -LEDCFG := asusd-ledmodes.toml +LEDCFG := aura_support.ron SRC := Cargo.toml Cargo.lock Makefile $(shell find -type f -wholename '**/src/*.rs') @@ -42,14 +42,14 @@ install: $(INSTALL_PROGRAM) "./target/release/$(BIN_ROG)" "$(DESTDIR)$(bindir)/$(BIN_ROG)" $(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 "*.toml" -exec $(INSTALL_DATA) "{}" "$(DESTDIR)$(datarootdir)/rog-gui/layouts/{}" \; + 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) "./data/$(LEDCFG)" "$(DESTDIR)/etc/asusd/$(LEDCFG)" + $(INSTALL_DATA) "./rog-aura/data/$(LEDCFG)" "$(DESTDIR)$(datarootdir)/asusd/$(LEDCFG)" $(INSTALL_DATA) "./data/$(BIN_D).conf" "$(DESTDIR)$(datarootdir)/dbus-1/system.d/$(BIN_D).conf" $(INSTALL_DATA) "./data/$(BIN_D).service" "$(DESTDIR)$(libdir)/systemd/system/$(BIN_D).service" diff --git a/asusctl/examples/anime-diag-png.rs b/asusctl/examples/anime-diag-png.rs index 889701ec..6c3ca64b 100644 --- a/asusctl/examples/anime-diag-png.rs +++ b/asusctl/examples/anime-diag-png.rs @@ -1,6 +1,10 @@ -use std::{env, error::Error, path::Path, process::exit}; +use std::env; +use std::error::Error; +use std::path::Path; +use std::process::exit; -use rog_anime::{usb::get_anime_type, AnimeDiagonal, AnimeType}; +use rog_anime::usb::get_anime_type; +use rog_anime::{AnimeDiagonal, AnimeType}; use rog_dbus::RogDbusClientBlocking; fn main() -> Result<(), Box> { diff --git a/asusctl/examples/anime-diag.rs b/asusctl/examples/anime-diag.rs index bcbc584c..fa17227f 100644 --- a/asusctl/examples/anime-diag.rs +++ b/asusctl/examples/anime-diag.rs @@ -1,6 +1,8 @@ -use std::{thread::sleep, time::Duration}; +use std::thread::sleep; +use std::time::Duration; -use rog_anime::{usb::get_anime_type, AnimeDiagonal, AnimeType}; +use rog_anime::usb::get_anime_type; +use rog_anime::{AnimeDiagonal, AnimeType}; use rog_dbus::RogDbusClientBlocking; // In usable data: diff --git a/asusctl/examples/anime-gif.rs b/asusctl/examples/anime-gif.rs index 79deecf0..0b73bae6 100644 --- a/asusctl/examples/anime-gif.rs +++ b/asusctl/examples/anime-gif.rs @@ -1,6 +1,9 @@ -use std::{env, path::Path, thread::sleep}; +use std::env; +use std::path::Path; +use std::thread::sleep; -use rog_anime::{usb::get_anime_type, ActionData, ActionLoader, Sequences}; +use rog_anime::usb::get_anime_type; +use rog_anime::{ActionData, ActionLoader, Sequences}; use rog_dbus::RogDbusClientBlocking; fn main() { diff --git a/asusctl/examples/anime-grid.rs b/asusctl/examples/anime-grid.rs index eb115958..b66f8529 100644 --- a/asusctl/examples/anime-grid.rs +++ b/asusctl/examples/anime-grid.rs @@ -1,7 +1,9 @@ -use rog_anime::{usb::get_anime_type, AnimeDataBuffer, AnimeGrid}; -use rog_dbus::RogDbusClientBlocking; use std::convert::TryFrom; +use rog_anime::usb::get_anime_type; +use rog_anime::{AnimeDataBuffer, AnimeGrid}; +use rog_dbus::RogDbusClientBlocking; + // In usable data: // Top row start at 1, ends at 32 diff --git a/asusctl/examples/anime-outline.rs b/asusctl/examples/anime-outline.rs index f7a0fba9..981a736d 100644 --- a/asusctl/examples/anime-outline.rs +++ b/asusctl/examples/anime-outline.rs @@ -1,4 +1,5 @@ -use rog_anime::{usb::get_anime_type, AnimeDataBuffer}; +use rog_anime::usb::get_anime_type; +use rog_anime::AnimeDataBuffer; use rog_dbus::RogDbusClientBlocking; // In usable data: diff --git a/asusctl/examples/anime-png.rs b/asusctl/examples/anime-png.rs index 42cee160..67f30c51 100644 --- a/asusctl/examples/anime-png.rs +++ b/asusctl/examples/anime-png.rs @@ -1,10 +1,11 @@ use std::convert::TryFrom; -use std::{env, error::Error, path::Path, process::exit}; +use std::env; +use std::error::Error; +use std::path::Path; +use std::process::exit; -use rog_anime::{ - usb::get_anime_type, - AnimeDataBuffer, {AnimeImage, Vec2}, -}; +use rog_anime::usb::get_anime_type; +use rog_anime::{AnimeDataBuffer, AnimeImage, Vec2}; use rog_dbus::RogDbusClientBlocking; fn main() -> Result<(), Box> { diff --git a/asusctl/examples/anime-spinning.rs b/asusctl/examples/anime-spinning.rs index f4f9c757..da1ba3b1 100644 --- a/asusctl/examples/anime-spinning.rs +++ b/asusctl/examples/anime-spinning.rs @@ -1,12 +1,14 @@ use std::convert::TryFrom; -use std::{ - env, error::Error, f32::consts::PI, path::Path, process::exit, thread::sleep, time::Duration, -}; +use std::env; +use std::error::Error; +use std::f32::consts::PI; +use std::path::Path; +use std::process::exit; +use std::thread::sleep; +use std::time::Duration; -use rog_anime::{ - usb::get_anime_type, - AnimeDataBuffer, {AnimeImage, Vec2}, -}; +use rog_anime::usb::get_anime_type; +use rog_anime::{AnimeDataBuffer, AnimeImage, Vec2}; use rog_dbus::RogDbusClientBlocking; fn main() -> Result<(), Box> { diff --git a/asusctl/examples/aura-rgb-ball.rs b/asusctl/examples/aura-rgb-ball.rs- similarity index 98% rename from asusctl/examples/aura-rgb-ball.rs rename to asusctl/examples/aura-rgb-ball.rs- index c4081b91..7bc9aaca 100644 --- a/asusctl/examples/aura-rgb-ball.rs +++ b/asusctl/examples/aura-rgb-ball.rs- @@ -106,7 +106,7 @@ fn main() -> Result<(), Box> { c[2] = 255; }; } - dbus.proxies().led().per_key_raw(colours.get())?; + dbus.proxies().led().direct_addressing_raw(colours.get())?; std::thread::sleep(std::time::Duration::from_millis(150)); } diff --git a/asusctl/examples/aura-rgb-breathe.rs b/asusctl/examples/aura-rgb-breathe.rs deleted file mode 100644 index 1f003baf..00000000 --- a/asusctl/examples/aura-rgb-breathe.rs +++ /dev/null @@ -1,59 +0,0 @@ -//! Using a combination of key-colour array plus a key layout to generate outputs. - -use rog_aura::{keys::Key, layouts::KeyLayout, Breathe, Colour, Effect, LedType, Sequences, Speed}; -use rog_dbus::RogDbusClientBlocking; - -fn main() -> Result<(), Box> { - let layout = KeyLayout::gx502_layout(); - - let (client, _) = RogDbusClientBlocking::new().unwrap(); - - let mut seq = Sequences::new(); - let mut key = Effect::Breathe(Breathe::new( - LedType::Key(Key::W), - Colour(255, 127, 0), - Colour(127, 0, 255), - Speed::Med, - )); - - seq.push(key.clone()); - key.set_led_type(LedType::Key(Key::A)); - seq.push(key.clone()); - key.set_led_type(LedType::Key(Key::S)); - seq.push(key.clone()); - key.set_led_type(LedType::Key(Key::D)); - seq.push(key.clone()); - - let mut key = Effect::Breathe(Breathe::new( - LedType::Key(Key::Q), - Colour(127, 127, 127), - Colour(127, 255, 255), - Speed::Low, - )); - seq.push(key.clone()); - key.set_led_type(LedType::Key(Key::E)); - seq.push(key.clone()); - - let mut key = Effect::Breathe(Breathe::new( - LedType::Key(Key::N1), - Colour(166, 127, 166), - Colour(127, 155, 20), - Speed::High, - )); - key.set_led_type(LedType::Key(Key::Tilde)); - seq.push(key.clone()); - key.set_led_type(LedType::Key(Key::N2)); - seq.push(key.clone()); - key.set_led_type(LedType::Key(Key::N3)); - seq.push(key.clone()); - key.set_led_type(LedType::Key(Key::N4)); - seq.push(key.clone()); - - loop { - seq.next_state(&layout); - let packets = seq.create_packets(); - - client.proxies().led().per_key_raw(packets)?; - std::thread::sleep(std::time::Duration::from_millis(60)); - } -} diff --git a/asusctl/examples/aura-rgb-iterate-keys.rs b/asusctl/examples/aura-rgb-iterate-keys.rs deleted file mode 100644 index eaea65b9..00000000 --- a/asusctl/examples/aura-rgb-iterate-keys.rs +++ /dev/null @@ -1,34 +0,0 @@ -//! Using a combination of key-colour array plus a key layout to generate outputs. - -use rog_aura::{layouts::KeyLayout, KeyColourArray}; -use rog_dbus::RogDbusClientBlocking; - -fn main() -> Result<(), Box> { - let (client, _) = RogDbusClientBlocking::new().unwrap(); - let layout = KeyLayout::gx502_layout(); - loop { - let mut key_colours = KeyColourArray::new(); - for row in layout.rows() { - for (k, key) in row.row().enumerate() { - if k != 0 { - if let Some(prev) = row.row().nth(k - 1) { - if let Some(c) = key_colours.rgb_for_key(*prev) { - c[0] = 0; - }; - } - } - - if key.is_placeholder() { - continue; - } - - if let Some(c) = key_colours.rgb_for_key(*key) { - c[0] = 255; - }; - - client.proxies().led().per_key_raw(key_colours.get())?; - std::thread::sleep(std::time::Duration::from_millis(100)); - } - } - } -} diff --git a/asusctl/examples/aura-zoned-breathe.rs b/asusctl/examples/aura-zoned-breathe.rs index 123b429c..bbeb8aef 100644 --- a/asusctl/examples/aura-zoned-breathe.rs +++ b/asusctl/examples/aura-zoned-breathe.rs @@ -1,44 +1,64 @@ -//! Using a combination of key-colour array plus a key layout to generate outputs. +//! Using a combination of key-colour array plus a key layout to generate +//! outputs. -use rog_aura::{layouts::KeyLayout, Breathe, Colour, Effect, LedType, PerZone, Sequences, Speed}; +use rog_aura::advanced::LedCode; +use rog_aura::effects::{AdvancedEffects, Effect}; +use rog_aura::layouts::KeyLayout; +use rog_aura::Colour; use rog_dbus::RogDbusClientBlocking; fn main() -> Result<(), Box> { - let layout = KeyLayout::gx502_layout(); + let layout = KeyLayout::default_layout(); let (client, _) = RogDbusClientBlocking::new().unwrap(); - let mut seq = Sequences::new(); + let mut seq = AdvancedEffects::new(true); - let zone = Effect::Breathe(Breathe::new( - LedType::Zone(PerZone::KeyboardLeft), - Colour(166, 127, 166), - Colour(127, 155, 20), - Speed::High, + // let zone = Effect::Breathe(rog_aura::effects::Breathe::new( + // RgbAddress::Single, + // Colour(166, 127, 166), + // Colour(127, 155, 20), + // rog_aura::Speed::High, + // )); + // seq.push(zone); + + // let zone = Effect::DoomLightFlash(rog_aura::effects::DoomLightFlash::new( + // RgbAddress::Single, + // Colour(200, 0, 0), + // 80, + // 10, + // )); + // seq.push(zone); + + let zone = Effect::DoomFlicker(rog_aura::effects::DoomFlicker::new( + LedCode::SingleZone, + Colour(200, 110, 0), + 100, + 10, )); seq.push(zone); - let zone = Effect::Breathe(Breathe::new( - LedType::Zone(PerZone::KeyboardCenterLeft), - Colour(16, 127, 255), - Colour(127, 15, 20), - Speed::Low, - )); - seq.push(zone); + // let zone = Effect::Breathe(rog_aura::effects::Breathe::new( + // RgbAddress::KeyboardCenterLeft, + // Colour(16, 127, 255), + // Colour(127, 15, 20), + // rog_aura::Speed::Low, + // )); + // seq.push(zone); - let zone = Effect::Breathe(Breathe::new( - LedType::Zone(PerZone::LightbarRightCorner), - Colour(0, 255, 255), - Colour(255, 0, 255), - Speed::Med, - )); - seq.push(zone); + // let zone = Effect::Breathe(rog_aura::effects::Breathe::new( + // RgbAddress::LightbarRightCorner, + // Colour(0, 255, 255), + // Colour(255, 0, 255), + // rog_aura::Speed::Med, + // )); + // seq.push(zone); loop { seq.next_state(&layout); let packets = seq.create_packets(); - client.proxies().led().per_key_raw(packets)?; - std::thread::sleep(std::time::Duration::from_millis(60)); + client.proxies().led().direct_addressing_raw(packets)?; + std::thread::sleep(std::time::Duration::from_millis(33)); } } diff --git a/asusctl/src/aura_cli.rs b/asusctl/src/aura_cli.rs index 98b92c0f..c28c30a2 100644 --- a/asusctl/src/aura_cli.rs +++ b/asusctl/src/aura_cli.rs @@ -1,7 +1,9 @@ -use gumdrop::Options; -use rog_aura::{error::Error, AuraEffect, AuraModeNum, AuraZone, Colour, Direction, Speed}; use std::str::FromStr; +use gumdrop::Options; +use rog_aura::error::Error; +use rog_aura::{AuraEffect, AuraModeNum, AuraZone, Colour, Direction, Speed}; + #[derive(Options)] pub struct LedPowerCommand1 { #[options(help = "print help message")] @@ -220,7 +222,6 @@ pub struct MultiColourSpeed { /// Byte value for setting the built-in mode. /// /// Enum corresponds to the required integer value -/// // NOTE: The option names here must match those in rog-aura crate #[derive(Options)] pub enum SetAuraBuiltin { diff --git a/asusctl/src/cli_opts.rs b/asusctl/src/cli_opts.rs index eada1083..45d8de2b 100644 --- a/asusctl/src/cli_opts.rs +++ b/asusctl/src/cli_opts.rs @@ -1,10 +1,9 @@ -use crate::{ - anime_cli::AnimeCommand, - aura_cli::{LedBrightness, LedPowerCommand1, LedPowerCommand2, SetAuraBuiltin}, - profiles_cli::{FanCurveCommand, ProfileCommand}, -}; use gumdrop::Options; +use crate::anime_cli::AnimeCommand; +use crate::aura_cli::{LedBrightness, LedPowerCommand1, LedPowerCommand2, SetAuraBuiltin}; +use crate::profiles_cli::{FanCurveCommand, ProfileCommand}; + #[derive(Default, Options)] pub struct CliStart { #[options(help_flag, help = "print help message")] diff --git a/asusctl/src/main.rs b/asusctl/src/main.rs index 61bb7846..71249256 100644 --- a/asusctl/src/main.rs +++ b/asusctl/src/main.rs @@ -1,16 +1,15 @@ use std::convert::TryFrom; +use std::env::args; +use std::path::Path; use std::process::Command; use std::thread::sleep; -use std::{env::args, path::Path}; - -use aura_cli::{LedPowerCommand1, LedPowerCommand2}; -use gumdrop::{Opt, Options}; use anime_cli::{AnimeActions, AnimeCommand}; +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_aura::{self, AuraEffect}; use rog_dbus::RogDbusClientBlocking; @@ -150,7 +149,7 @@ fn do_parsed( let commands: Vec = cmdlist.lines().map(|s| s.to_owned()).collect(); for command in commands.iter().filter(|command| { if !matches!( - supported.keyboard_led.prod_id, + supported.keyboard_led.dev_id, AuraDevice::X1854 | AuraDevice::X1869 | AuraDevice::X1866 @@ -159,7 +158,7 @@ fn do_parsed( { return false; } - if supported.keyboard_led.prod_id != AuraDevice::X19B6 + if supported.keyboard_led.dev_id != AuraDevice::X19B6 && command.trim().starts_with("led-pow-2") { return false; @@ -212,7 +211,10 @@ fn do_parsed( } fn do_gfx() { - println!("Please use supergfxctl for graphics switching. supergfxctl is the result of making asusctl graphics switching generic so all laptops can use it"); + println!( + "Please use supergfxctl for graphics switching. supergfxctl is the result of making \ + asusctl graphics switching generic so all laptops can use it" + ); println!("This command will be removed in future"); } @@ -391,7 +393,7 @@ fn handle_led_mode( if let Some(cmdlist) = LedModeCommand::command_list() { let commands: Vec = cmdlist.lines().map(|s| s.to_string()).collect(); for command in commands.iter().filter(|command| { - for mode in &supported.stock_led_modes { + for mode in &supported.basic_modes { if command .trim() .starts_with(&<&str>::from(mode).to_lowercase()) @@ -399,7 +401,7 @@ fn handle_led_mode( return true; } } - if !supported.multizone_led_mode.is_empty() && command.trim().starts_with("multi") { + if !supported.basic_zones.is_empty() && command.trim().starts_with("multi") { return true; } false @@ -452,14 +454,14 @@ fn handle_led_power1( } if matches!( - supported.prod_id, + supported.dev_id, AuraDevice::X1854 | AuraDevice::X1869 | AuraDevice::X1866 ) { handle_led_power_1_do_1866(dbus, power)?; return Ok(()); } - if matches!(supported.prod_id, AuraDevice::Tuf) { + if matches!(supported.dev_id, AuraDevice::Tuf) { handle_led_power_1_do_tuf(dbus, power)?; return Ok(()); } @@ -576,7 +578,7 @@ fn handle_led_power2( return Ok(()); } - if supported.prod_id != AuraDevice::X19B6 { + if supported.dev_id != AuraDevice::X19B6 { println!("This option applies only to keyboards with product ID 0x19b6"); } @@ -786,7 +788,10 @@ fn handle_bios_option( dbus.proxies() .rog_bios() .set_gpu_mux_mode(GpuMode::from_mux(opt))?; - println!("The mode change is not active until you reboot, on boot the bios will make the required change"); + println!( + "The mode change is not active until you reboot, on boot the bios will make the \ + required change" + ); } if cmd.gpu_mux_mode_get { let res = dbus.proxies().rog_bios().gpu_mux_mode()?; diff --git a/asusctl/src/profiles_cli.rs b/asusctl/src/profiles_cli.rs index 1d53c7c8..1a1e2983 100644 --- a/asusctl/src/profiles_cli.rs +++ b/asusctl/src/profiles_cli.rs @@ -1,5 +1,6 @@ use gumdrop::Options; -use rog_profiles::{fan_curve_set::CurveData, FanCurvePU, Profile}; +use rog_profiles::fan_curve_set::CurveData; +use rog_profiles::{FanCurvePU, Profile}; #[derive(Debug, Clone, Options)] pub struct ProfileCommand { diff --git a/daemon-user/src/ctrl_anime.rs b/daemon-user/src/ctrl_anime.rs index 05e9d077..25f66747 100644 --- a/daemon-user/src/ctrl_anime.rs +++ b/daemon-user/src/ctrl_anime.rs @@ -1,28 +1,24 @@ +use std::path::Path; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::{Arc, Mutex}; +use std::thread::sleep; +use std::time::{Duration, Instant}; + use rog_anime::error::AnimeError; use rog_anime::{ActionData, ActionLoader, AnimTime, Fade, Sequences, Vec2}; use rog_dbus::RogDbusClientBlocking; use serde_derive::{Deserialize, Serialize}; -use std::time::Duration; -use std::{ - path::Path, - sync::{ - atomic::{AtomicBool, Ordering}, - Mutex, - }, -}; -use std::{sync::Arc, thread::sleep, time::Instant}; -use zbus::{ - dbus_interface, - zvariant::{ObjectPath, Type}, -}; +use zbus::dbus_interface; +use zbus::zvariant::{ObjectPath, Type}; -use crate::user_config::ConfigLoadSave; -use crate::{error::Error, user_config::UserAnimeConfig}; +use crate::error::Error; +use crate::user_config::{ConfigLoadSave, UserAnimeConfig}; #[derive(Debug, Clone, Deserialize, Serialize, Type)] pub struct Timer { type_of: TimeType, - /// If time type is Timer then this is milliseonds, otherwise it is animation loop count + /// If time type is Timer then this is milliseonds, otherwise it is + /// animation loop count count: u64, /// Used only for `TimeType::Timer`, milliseonds to fade the image in for fade_in: Option, @@ -64,8 +60,8 @@ pub enum TimeType { Infinite, } -/// The inner object exists to allow the zbus proxy to share it with a runner thread -/// and a zbus server behind `Arc>` +/// The inner object exists to allow the zbus proxy to share it with a runner +/// thread and a zbus server behind `Arc>` pub struct CtrlAnimeInner<'a> { sequences: Sequences, client: RogDbusClientBlocking<'a>, @@ -84,7 +80,9 @@ impl<'a> CtrlAnimeInner<'static> { do_early_return, }) } - /// To be called on each main loop iteration to pump out commands to the anime + + /// To be called on each main loop iteration to pump out commands to the + /// anime pub fn run(&'a self) -> Result<(), Error> { if self.do_early_return.load(Ordering::SeqCst) { return Ok(()); diff --git a/daemon-user/src/daemon.rs b/daemon-user/src/daemon.rs index b2e1f36c..c6962d60 100644 --- a/daemon-user/src/daemon.rs +++ b/daemon-user/src/daemon.rs @@ -1,18 +1,19 @@ +use std::fs::OpenOptions; +use std::io::Read; +use std::path::PathBuf; +use std::sync::atomic::AtomicBool; +use std::sync::{Arc, Mutex}; + 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::{ - ctrl_anime::{CtrlAnime, CtrlAnimeInner}, - user_config::*, - DBUS_NAME, -}; +use rog_user::ctrl_anime::{CtrlAnime, CtrlAnimeInner}; +use rog_user::user_config::*; +use rog_user::DBUS_NAME; use smol::Executor; -use std::sync::Mutex; -use std::{fs::OpenOptions, io::Read, path::PathBuf, sync::Arc}; use zbus::Connection; -use std::sync::atomic::AtomicBool; - #[cfg(not(feature = "local_data"))] const DATA_DIR: &str = "/usr/share/rog-gui/"; #[cfg(feature = "local_data")] @@ -82,11 +83,13 @@ fn main() -> Result<(), Box> { let mut board_name = String::new(); file.read_to_string(&mut board_name)?; - let layout = KeyLayout::find_layout(board_name.as_str(), PathBuf::from(DATA_DIR)) + let led_support = LaptopLedData::get_data(); + + let layout = KeyLayout::find_layout(led_support, PathBuf::from(DATA_DIR)) .map_err(|e| { println!("{BOARD_NAME}, {e}"); }) - .unwrap_or_else(|_| KeyLayout::ga401_layout()); + .unwrap_or_else(|_| KeyLayout::default_layout()); executor .spawn(async move { @@ -99,7 +102,11 @@ fn main() -> Result<(), Box> { aura_config.aura.next_state(&layout); let packets = aura_config.aura.create_packets(); - client.proxies().led().per_key_raw(packets).unwrap(); + client + .proxies() + .led() + .direct_addressing_raw(packets) + .unwrap(); std::thread::sleep(std::time::Duration::from_millis(33)); } }) diff --git a/daemon-user/src/user_config.rs b/daemon-user/src/user_config.rs index 00045337..70984ca4 100644 --- a/daemon-user/src/user_config.rs +++ b/daemon-user/src/user_config.rs @@ -1,11 +1,11 @@ -use std::{ - fs::{create_dir, OpenOptions}, - io::{Read, Write}, - time::Duration, -}; +use std::fs::{create_dir, OpenOptions}; +use std::io::{Read, Write}; +use std::time::Duration; -use rog_anime::{ActionLoader, AnimTime, AnimeType, Fade, Sequences, Vec2}; -use rog_aura::{keys::Key, Breathe, Colour, Effect, Flicker, LedType, Speed, Static}; +use rog_anime::{ActionLoader, AnimTime, AnimeType, Fade, Sequences as AnimeSequences, Vec2}; +use rog_aura::advanced::LedCode; +use rog_aura::effects::{AdvancedEffects as AuraSequences, Breathe, DoomFlicker, Effect, Static}; +use rog_aura::{Colour, Speed}; use serde::de::DeserializeOwned; use serde_derive::{Deserialize, Serialize}; @@ -87,8 +87,8 @@ pub struct UserAnimeConfig { } impl UserAnimeConfig { - pub fn create(&self, anime_type: AnimeType) -> Result { - let mut seq = Sequences::new(anime_type); + pub fn create(&self, anime_type: AnimeType) -> Result { + let mut seq = AnimeSequences::new(anime_type); for (idx, action) in self.anime.iter().enumerate() { seq.insert(idx, action)?; @@ -175,7 +175,7 @@ impl Default for UserAnimeConfig { #[derive(Debug, Deserialize, Serialize)] pub struct UserAuraConfig { pub name: String, - pub aura: rog_aura::Sequences, + pub aura: AuraSequences, } impl ConfigLoadSave for UserAuraConfig { @@ -193,43 +193,38 @@ impl ConfigLoadSave for UserAuraConfig { impl Default for UserAuraConfig { fn default() -> Self { - let mut seq = rog_aura::Sequences::new(); + let mut seq = AuraSequences::new(false); let mut key = Effect::Breathe(Breathe::new( - LedType::Key(Key::W), + LedCode::W, Colour(255, 0, 20), Colour(20, 255, 0), Speed::Low, )); seq.push(key.clone()); - key.set_led_type(LedType::Key(Key::A)); + key.set_led(LedCode::A); seq.push(key.clone()); - key.set_led_type(LedType::Key(Key::S)); + key.set_led(LedCode::S); seq.push(key.clone()); - key.set_led_type(LedType::Key(Key::D)); + key.set_led(LedCode::D); seq.push(key); let key = Effect::Breathe(Breathe::new( - LedType::Key(Key::F), + LedCode::F, Colour(255, 0, 0), Colour(255, 0, 0), Speed::High, )); seq.push(key); - let mut key = Effect::Static(Static::new(LedType::Key(Key::RCtrl), Colour(0, 0, 255))); + let mut key = Effect::Static(Static::new(LedCode::RCtrl, Colour(0, 0, 255))); seq.push(key.clone()); - key.set_led_type(LedType::Key(Key::LCtrl)); + key.set_led(LedCode::LCtrl); seq.push(key.clone()); - key.set_led_type(LedType::Key(Key::Esc)); + key.set_led(LedCode::Esc); seq.push(key); - let key = Effect::Flicker(Flicker::new( - LedType::Key(Key::N9), - Colour(0, 0, 255), - 80, - 40, - )); + let key = Effect::DoomFlicker(DoomFlicker::new(LedCode::N9, Colour(0, 0, 255), 80, 40)); seq.push(key); Self { diff --git a/daemon-user/src/zbus_anime.rs b/daemon-user/src/zbus_anime.rs index 6a22aa9c..d08c2185 100644 --- a/daemon-user/src/zbus_anime.rs +++ b/daemon-user/src/zbus_anime.rs @@ -1,7 +1,8 @@ //! # DBus interface proxy for: `org.asuslinux.Daemon` //! -//! This code was generated by `zbus-xmlgen` `1.0.0` from DBus introspection data. -//! Source: `Interface '/org/asuslinux/Anime' from service 'org.asuslinux.Daemon' on session bus`. +//! 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`. //! //! You may prefer to adapt it, instead of using it verbatim. //! diff --git a/daemon/src/config.rs b/daemon/src/config.rs index 8a832d01..7b320107 100644 --- a/daemon/src/config.rs +++ b/daemon/src/config.rs @@ -1,9 +1,10 @@ -use log::{error, warn}; -use serde_derive::{Deserialize, Serialize}; use std::fs::{File, OpenOptions}; use std::io::{Read, Write}; use std::path::PathBuf; +use log::{error, warn}; +use serde_derive::{Deserialize, Serialize}; + pub static CONFIG_PATH: &str = "/etc/asusd/asusd.conf"; #[derive(Deserialize, Serialize, Default)] diff --git a/daemon/src/ctrl_anime/config.rs b/daemon/src/ctrl_anime/config.rs index a63a7eac..76e087d2 100644 --- a/daemon/src/ctrl_anime/config.rs +++ b/daemon/src/ctrl_anime/config.rs @@ -1,12 +1,14 @@ -use crate::VERSION; -use log::{error, info, warn}; -use rog_anime::{error::AnimeError, ActionData, ActionLoader, AnimTime, Vec2}; -use rog_anime::{AnimeType, Fade}; -use serde_derive::{Deserialize, Serialize}; use std::fs::{File, OpenOptions}; use std::io::{Read, Write}; use std::time::Duration; +use log::{error, info, warn}; +use rog_anime::error::AnimeError; +use rog_anime::{ActionData, ActionLoader, AnimTime, AnimeType, Fade, Vec2}; +use serde_derive::{Deserialize, Serialize}; + +use crate::VERSION; + pub static ANIME_CONFIG_PATH: &str = "/etc/asusd/anime.conf"; pub static ANIME_CACHE_PATH: &str = "/etc/asusd/anime-cache.conf"; diff --git a/daemon/src/ctrl_anime/mod.rs b/daemon/src/ctrl_anime/mod.rs index b8d4a27e..bde88d6c 100644 --- a/daemon/src/ctrl_anime/mod.rs +++ b/daemon/src/ctrl_anime/mod.rs @@ -2,18 +2,24 @@ pub mod config; /// Implements `CtrlTask`, Reloadable, `ZbusRun` pub mod trait_impls; -use self::config::{AnimeConfig, AnimeConfigCached}; -use crate::{error::RogError, GetSupported}; +use std::convert::TryFrom; +use std::error::Error; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::Arc; +use std::thread::sleep; + use ::zbus::export::futures_util::lock::Mutex; use log::{error, info, warn}; -use rog_anime::{ - error::AnimeError, - usb::{get_anime_type, pkt_for_flush, pkts_for_init}, - ActionData, AnimeDataBuffer, AnimePacketType, AnimeType, -}; -use rog_platform::{hid_raw::HidRaw, supported::AnimeSupportedFunctions, usb_raw::USBRaw}; -use std::sync::atomic::{AtomicBool, Ordering}; -use std::{convert::TryFrom, error::Error, sync::Arc, thread::sleep}; +use rog_anime::error::AnimeError; +use rog_anime::usb::{get_anime_type, pkt_for_flush, pkts_for_init}; +use rog_anime::{ActionData, AnimeDataBuffer, AnimePacketType, AnimeType}; +use rog_platform::hid_raw::HidRaw; +use rog_platform::supported::AnimeSupportedFunctions; +use rog_platform::usb_raw::USBRaw; + +use self::config::{AnimeConfig, AnimeConfigCached}; +use crate::error::RogError; +use crate::GetSupported; impl GetSupported for CtrlAnime { type A = AnimeSupportedFunctions; @@ -56,13 +62,14 @@ impl CtrlAnime { Ok(ctrl) } + // let device = CtrlAnime::get_device(0x0b05, 0x193b)?; - /// Start an action thread. This is classed as a singleton and there should be only - /// one running - so the thread uses atomics to signal run/exit. + /// Start an action thread. This is classed as a singleton and there should + /// be only one running - so the thread uses atomics to signal run/exit. /// - /// Because this also writes to the usb device, other write tries (display only) *must* - /// get the mutex lock and set the `thread_exit` atomic. + /// 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>, actions: Vec, mut once: bool) { if actions.is_empty() { warn!("AniMe system actions was empty"); @@ -70,12 +77,15 @@ impl CtrlAnime { } // Loop rules: - // - Lock the mutex **only when required**. That is, the lock must be held for the shortest duration possible. - // - An AtomicBool used for thread exit should be checked in every loop, including nested + // - Lock the mutex **only when required**. That is, the lock must be held for + // the shortest duration possible. + // - An AtomicBool used for thread exit should be checked in every loop, + // including nested - // The only reason for this outer thread is to prevent blocking while waiting for the - // next spawned thread to exit - // TODO: turn this in to async task (maybe? COuld still risk blocking main thread) + // The only reason for this outer thread is to prevent blocking while waiting + // for the next spawned thread to exit + // TODO: turn this in to async task (maybe? COuld still risk blocking main + // thread) std::thread::Builder::new() .name("AniMe system thread start".into()) .spawn(move || { diff --git a/daemon/src/ctrl_anime/trait_impls.rs b/daemon/src/ctrl_anime/trait_impls.rs index 64fb7f9c..0da684c8 100644 --- a/daemon/src/ctrl_anime/trait_impls.rs +++ b/daemon/src/ctrl_anime/trait_impls.rs @@ -1,17 +1,15 @@ -use super::CtrlAnime; -use crate::error::RogError; +use std::sync::atomic::Ordering; +use std::sync::Arc; + use async_trait::async_trait; use log::{info, warn}; -use rog_anime::{ - usb::{pkt_for_apply, pkt_for_set_boot, pkt_for_set_on}, - AnimeDataBuffer, AnimePowerStates, -}; -use std::sync::{atomic::Ordering, Arc}; -use zbus::{ - dbus_interface, - export::futures_util::lock::{Mutex, MutexGuard}, - Connection, SignalContext, -}; +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"; @@ -27,11 +25,12 @@ impl crate::ZbusRun for CtrlAnimeZbus { } // 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. +// 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 + /// 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); @@ -133,7 +132,8 @@ impl CtrlAnimeZbus { lock.config.boot_anim_enabled } - /// Notify listeners of the status of AniMe LED power and factory system-status animations + /// Notify listeners of the status of AniMe LED power and factory + /// system-status animations #[dbus_interface(signal)] async fn notify_power_states( ctxt: &SignalContext<'_>, diff --git a/daemon/src/ctrl_aura/config.rs b/daemon/src/ctrl_aura/config.rs index 6e9dc2bb..8e52583d 100644 --- a/daemon/src/ctrl_aura/config.rs +++ b/daemon/src/ctrl_aura/config.rs @@ -1,13 +1,14 @@ -use crate::laptops::{LaptopLedData, ASUS_KEYBOARD_DEVICES}; +use std::collections::{BTreeMap, HashSet}; +use std::fs::{File, OpenOptions}; +use std::io::{Read, Write}; + use log::{error, warn}; +use rog_aura::aura_detection::{LaptopLedData, ASUS_KEYBOARD_DEVICES}; use rog_aura::usb::{AuraDev1866, AuraDev19b6, 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}; -use std::collections::{BTreeMap, HashSet}; -use std::fs::{File, OpenOptions}; -use std::io::{Read, Write}; pub static AURA_CONFIG_PATH: &str = "/etc/asusd/aura.conf"; @@ -70,6 +71,7 @@ impl AuraPowerConfig { } } } + pub fn set_0x1866(&mut self, power: AuraDev1866, on: bool) { if let Self::AuraDev1866(p) = self { if on { @@ -227,14 +229,14 @@ impl AuraConfig { // create a default config here let mut config = AuraConfig::default(); - for n in &support_data.standard { + for n in &support_data.basic_modes { config .builtins .insert(*n, AuraEffect::default_with_mode(*n)); - if !support_data.multizone.is_empty() { + if !support_data.basic_zones.is_empty() { let mut default = vec![]; - for (i, tmp) in support_data.multizone.iter().enumerate() { + for (i, tmp) in support_data.basic_zones.iter().enumerate() { default.push(AuraEffect { mode: *n, zone: *tmp, @@ -287,7 +289,8 @@ impl AuraConfig { /// Set the mode data, current mode, and if multizone enabled. /// - /// Multipurpose, will accept `AuraEffect` with zones and put in the correct store. + /// Multipurpose, will accept `AuraEffect` with zones and put in the correct + /// store. pub fn set_builtin(&mut self, effect: AuraEffect) { self.current_mode = effect.mode; if effect.zone() == AuraZone::None { @@ -325,9 +328,10 @@ impl AuraConfig { #[cfg(test)] mod tests { - use super::AuraConfig; use rog_aura::{AuraEffect, AuraModeNum, AuraZone, Colour}; + use super::AuraConfig; + #[test] fn set_multizone_4key_config() { let mut config = AuraConfig::default(); diff --git a/daemon/src/ctrl_aura/controller.rs b/daemon/src/ctrl_aura/controller.rs index 5d6bfee7..077063a8 100644 --- a/daemon/src/ctrl_aura/controller.rs +++ b/daemon/src/ctrl_aura/controller.rs @@ -1,19 +1,17 @@ -use crate::{ - error::RogError, - laptops::{LaptopLedData, ASUS_KEYBOARD_DEVICES}, -}; -use log::{info, warn}; -use rog_aura::{ - usb::{AuraDevice, LED_APPLY, LED_SET}, - AuraEffect, KeyColourArray, LedBrightness, PerKeyRaw, LED_MSG_LEN, -}; -use rog_aura::{AuraZone, Direction, Speed, GRADIENT}; -use rog_platform::{hid_raw::HidRaw, keyboard_led::KeyboardLed, supported::LedSupportedFunctions}; use std::collections::BTreeMap; -use crate::GetSupported; +use log::{info, warn}; +use rog_aura::advanced::{LedUsbPackets, UsbPackets}; +use rog_aura::aura_detection::{LaptopLedData, ASUS_KEYBOARD_DEVICES}; +use rog_aura::usb::{AuraDevice, LED_APPLY, LED_SET}; +use rog_aura::{AuraEffect, AuraZone, Direction, LedBrightness, Speed, GRADIENT, LED_MSG_LEN}; +use rog_platform::hid_raw::HidRaw; +use rog_platform::keyboard_led::KeyboardLed; +use rog_platform::supported::LedSupportedFunctions; use super::config::{AuraConfig, AuraPowerConfig}; +use crate::error::RogError; +use crate::GetSupported; impl GetSupported for CtrlKbdLed { type A = LedSupportedFunctions; @@ -21,9 +19,9 @@ impl GetSupported for CtrlKbdLed { fn get_supported() -> Self::A { // let mode = <&str>::from(&::from(*mode)); let laptop = LaptopLedData::get_data(); - let stock_led_modes = laptop.standard; - let multizone_led_mode = laptop.multizone; - let per_key_led_mode = laptop.per_key; + let stock_led_modes = laptop.basic_modes; + let multizone_led_mode = laptop.basic_zones; + let advanced_type = laptop.advanced_type; let mut prod_id = AuraDevice::Unknown; for prod in &ASUS_KEYBOARD_DEVICES { @@ -41,11 +39,11 @@ impl GetSupported for CtrlKbdLed { } LedSupportedFunctions { - prod_id, - brightness_set: rgb.is_ok(), - stock_led_modes, - multizone_led_mode, - per_key_led_mode, + dev_id: prod_id, + brightness: rgb.is_ok(), + basic_modes: stock_led_modes, + basic_zones: multizone_led_mode, + advanced_type: advanced_type.into(), } } } @@ -152,7 +150,8 @@ impl CtrlKbdLed { self.set_brightness(self.config.brightness) } - /// Set combination state for boot animation/sleep animation/all leds/keys leds/side leds LED active + /// Set combination state for boot animation/sleep animation/all leds/keys + /// leds/side leds LED active pub(super) fn set_power_states(&mut self) -> Result<(), RogError> { if let LEDNode::KbdLed(platform) = &mut self.led_node { if let Some(pwr) = AuraPowerConfig::to_tuf_bool_array(&self.config.enabled) { @@ -173,12 +172,12 @@ impl CtrlKbdLed { /// Set an Aura effect if the effect mode or zone is supported. /// - /// On success the aura config file is read to refresh cached values, then the effect is - /// stored and config written to disk. + /// On success the aura config file is read to refresh cached values, then + /// the effect is stored and config written to disk. pub(crate) fn set_effect(&mut self, effect: AuraEffect) -> Result<(), RogError> { - if !self.supported_modes.standard.contains(&effect.mode) + if !self.supported_modes.basic_modes.contains(&effect.mode) || effect.zone != AuraZone::None - && !self.supported_modes.multizone.contains(&effect.zone) + && !self.supported_modes.basic_zones.contains(&effect.zone) { return Err(RogError::AuraEffectNotSupported); } @@ -193,7 +192,7 @@ impl CtrlKbdLed { /// Write an effect block. This is for per-key, but can be repurposed to /// write the raw factory mode packets - when doing this it is expected that /// only the first `Vec` (`effect[0]`) is valid. - pub fn write_effect_block(&mut self, effect: &PerKeyRaw) -> Result<(), RogError> { + pub fn write_effect_block(&mut self, effect: &UsbPackets) -> Result<(), RogError> { let pkt_type = effect[0][1]; const PER_KEY_TYPE: u8 = 0xbc; @@ -207,7 +206,7 @@ impl CtrlKbdLed { } else { if !self.per_key_mode_active { if let LEDNode::Rog(hid_raw) = &self.led_node { - let init = KeyColourArray::get_init_msg(); + let init = LedUsbPackets::get_init_msg(); hid_raw.write_bytes(&init)?; } self.per_key_mode_active = true; @@ -233,7 +232,7 @@ impl CtrlKbdLed { let current = self.config.current_mode; if let Some(idx) = self .supported_modes - .standard + .basic_modes .iter() .position(|v| *v == current) { @@ -241,17 +240,17 @@ impl CtrlKbdLed { // goes past end of array if reverse { if idx == 0 { - idx = self.supported_modes.standard.len() - 1; + idx = self.supported_modes.basic_modes.len() - 1; } else { idx -= 1; } } else { idx += 1; - if idx == self.supported_modes.standard.len() { + if idx == self.supported_modes.basic_modes.len() { idx = 0; } } - let next = self.supported_modes.standard[idx]; + let next = self.supported_modes.basic_modes[idx]; self.config.read(); // if self.config.builtins.contains_key(&next) { @@ -324,10 +323,11 @@ impl CtrlKbdLed { Ok(()) } - /// Create a default for the `current_mode` if multizone and no config exists. + /// Create a default for the `current_mode` if multizone and no config + /// exists. fn create_multizone_default(&mut self) -> Result<(), RogError> { let mut default = vec![]; - for (i, tmp) in self.supported_modes.multizone.iter().enumerate() { + for (i, tmp) in self.supported_modes.basic_zones.iter().enumerate() { default.push(AuraEffect { mode: self.config.current_mode, zone: *tmp, @@ -354,15 +354,13 @@ impl CtrlKbdLed { #[cfg(test)] mod tests { + use rog_aura::aura_detection::LaptopLedData; use rog_aura::{AuraEffect, AuraModeNum, AuraZone, Colour}; use rog_platform::keyboard_led::KeyboardLed; - use crate::{ - ctrl_aura::{config::AuraConfig, controller::LEDNode}, - laptops::LaptopLedData, - }; - use super::CtrlKbdLed; + use crate::ctrl_aura::config::AuraConfig; + use crate::ctrl_aura::controller::LEDNode; #[test] // #[ignore = "Must be manually run due to detection stage"] @@ -370,11 +368,11 @@ mod tests { // Checking to ensure set_mode errors when unsupported modes are tried let config = AuraConfig::default(); let supported_modes = LaptopLedData { - prod_family: String::new(), - board_names: vec![], - standard: vec![AuraModeNum::Static], - multizone: vec![], - per_key: false, + board_name: String::new(), + layout_name: "ga401".to_owned(), + basic_modes: vec![AuraModeNum::Static], + basic_zones: vec![], + advanced_type: rog_aura::AdvancedAuraType::None, }; let mut controller = CtrlKbdLed { led_prod: None, @@ -392,7 +390,8 @@ mod tests { ..Default::default() }; - // This error comes from write_bytes because we don't have a keyboard node stored + // This error comes from write_bytes because we don't have a keyboard node + // stored assert_eq!( controller .set_effect(effect.clone()) @@ -420,7 +419,7 @@ mod tests { "Aura effect not supported" ); - controller.supported_modes.multizone.push(AuraZone::Key2); + controller.supported_modes.basic_zones.push(AuraZone::Key2); assert_eq!( controller.set_effect(effect).unwrap_err().to_string(), "No supported Aura keyboard" @@ -432,11 +431,11 @@ mod tests { // Checking to ensure set_mode errors when unsupported modes are tried let config = AuraConfig::default(); let supported_modes = LaptopLedData { - prod_family: String::new(), - board_names: vec![], - standard: vec![AuraModeNum::Static], - multizone: vec![], - per_key: false, + board_name: String::new(), + layout_name: "ga401".to_owned(), + basic_modes: vec![AuraModeNum::Static], + basic_zones: vec![], + advanced_type: rog_aura::AdvancedAuraType::None, }; let mut controller = CtrlKbdLed { led_prod: None, @@ -452,8 +451,8 @@ mod tests { assert!(controller.create_multizone_default().is_err()); assert!(controller.config.multizone.is_none()); - controller.supported_modes.multizone.push(AuraZone::Key1); - controller.supported_modes.multizone.push(AuraZone::Key2); + controller.supported_modes.basic_zones.push(AuraZone::Key1); + controller.supported_modes.basic_zones.push(AuraZone::Key2); assert!(controller.create_multizone_default().is_ok()); assert!(controller.config.multizone.is_some()); @@ -470,11 +469,11 @@ mod tests { // Checking to ensure set_mode errors when unsupported modes are tried let config = AuraConfig::default(); let supported_modes = LaptopLedData { - prod_family: String::new(), - board_names: vec![], - standard: vec![AuraModeNum::Static], - multizone: vec![AuraZone::Key1, AuraZone::Key2], - per_key: false, + board_name: String::new(), + layout_name: "ga401".to_owned(), + basic_modes: vec![AuraModeNum::Static], + basic_zones: vec![AuraZone::Key1, AuraZone::Key2], + advanced_type: rog_aura::AdvancedAuraType::None, }; let mut controller = CtrlKbdLed { led_prod: None, diff --git a/daemon/src/ctrl_aura/trait_impls.rs b/daemon/src/ctrl_aura/trait_impls.rs index 0bc2d4ba..edf0038b 100644 --- a/daemon/src/ctrl_aura/trait_impls.rs +++ b/daemon/src/ctrl_aura/trait_impls.rs @@ -1,19 +1,18 @@ +use std::collections::BTreeMap; +use std::sync::Arc; + use async_trait::async_trait; use log::{error, info, warn}; -use rog_aura::{usb::AuraPowerDev, AuraEffect, AuraModeNum, LedBrightness, PerKeyRaw}; -use std::{collections::BTreeMap, sync::Arc}; -use zbus::{ - dbus_interface, - export::futures_util::{ - lock::{Mutex, MutexGuard}, - StreamExt, - }, - Connection, SignalContext, -}; - -use crate::{error::RogError, CtrlTask}; +use rog_aura::advanced::UsbPackets; +use rog_aura::usb::AuraPowerDev; +use rog_aura::{AuraEffect, AuraModeNum, LedBrightness}; +use zbus::export::futures_util::lock::{Mutex, MutexGuard}; +use zbus::export::futures_util::StreamExt; +use zbus::{dbus_interface, Connection, SignalContext}; use super::controller::CtrlKbdLed; +use crate::error::RogError; +use crate::CtrlTask; pub(super) const ZBUS_PATH: &str = "/org/asuslinux/Aura"; @@ -207,7 +206,10 @@ impl CtrlKbdLedZbus { ctrl.config.builtins.clone() } - async fn per_key_raw(&self, data: PerKeyRaw) -> zbus::fdo::Result<()> { + /// On machine that have some form of either per-key keyboard or per-zone + /// this can be used to write custom effects over dbus. The input is a + /// nested `Vec>` where `Vec` is a raw USB packet + async fn direct_addressing_raw(&self, data: UsbPackets) -> zbus::fdo::Result<()> { let mut ctrl = self.0.lock().await; ctrl.write_effect_block(&data)?; Ok(()) diff --git a/daemon/src/ctrl_platform.rs b/daemon/src/ctrl_platform.rs index c004217d..505ebd46 100644 --- a/daemon/src/ctrl_platform.rs +++ b/daemon/src/ctrl_platform.rs @@ -1,17 +1,19 @@ -use crate::{config::Config, error::RogError, GetSupported}; -use crate::{task_watch_item, CtrlTask}; -use async_trait::async_trait; -use log::{info, warn}; -use rog_platform::platform::{AsusPlatform, GpuMode}; -use rog_platform::supported::RogBiosSupportedFunctions; use std::fs::OpenOptions; use std::io::{Read, Write}; use std::path::Path; use std::process::Command; use std::sync::Arc; + +use async_trait::async_trait; +use log::{info, warn}; +use rog_platform::platform::{AsusPlatform, GpuMode}; +use rog_platform::supported::RogBiosSupportedFunctions; use zbus::export::futures_util::lock::Mutex; -use zbus::Connection; -use zbus::{dbus_interface, SignalContext}; +use zbus::{dbus_interface, Connection, SignalContext}; + +use crate::config::Config; +use crate::error::RogError; +use crate::{task_watch_item, CtrlTask, GetSupported}; const ZBUS_PATH: &str = "/org/asuslinux/Platform"; const ASUS_POST_LOGO_SOUND: &str = @@ -214,7 +216,8 @@ impl CtrlPlatform { }; } - /// Get the `panel_od` value from platform. Updates the stored value in internal config also. + /// Get the `panel_od` value from platform. Updates the stored value in + /// internal config also. fn panel_od(&self) -> bool { let od = self .platform @@ -317,10 +320,12 @@ impl crate::Reloadable for CtrlPlatform { impl CtrlPlatform { task_watch_item!(panel_od platform); + task_watch_item!(dgpu_disable platform); + task_watch_item!(egpu_enable platform); // NOTE: see note further below - //task_watch_item!(gpu_mux_mode platform); + // task_watch_item!(gpu_mux_mode platform); } #[async_trait] @@ -373,9 +378,9 @@ impl CtrlTask for CtrlPlatform { self.watch_panel_od(signal_ctxt.clone()).await?; self.watch_dgpu_disable(signal_ctxt.clone()).await?; self.watch_egpu_enable(signal_ctxt.clone()).await?; - // NOTE: Can't have this as a watch because on a write to it, it reverts back to booted-with value - // as it does not actually change until reboot. - //self.watch_gpu_mux_mode(signal_ctxt.clone()).await?; + // NOTE: Can't have this as a watch because on a write to it, it reverts back to + // booted-with value as it does not actually change until reboot. + // self.watch_gpu_mux_mode(signal_ctxt.clone()).await?; Ok(()) } diff --git a/daemon/src/ctrl_power.rs b/daemon/src/ctrl_power.rs index 20537fd5..66a934b7 100644 --- a/daemon/src/ctrl_power.rs +++ b/daemon/src/ctrl_power.rs @@ -1,18 +1,19 @@ -use crate::{config::Config, error::RogError, GetSupported}; -use crate::{task_watch_item, CtrlTask}; +use std::process::Command; +use std::sync::Arc; +use std::time::Duration; + use async_trait::async_trait; use log::{error, info, warn}; use rog_platform::power::AsusPower; use rog_platform::supported::ChargeSupportedFunctions; -use std::process::Command; -use std::sync::Arc; -use std::time::Duration; use systemd_zbus::{ManagerProxy as SystemdProxy, Mode, UnitFileState}; use tokio::time::sleep; -use zbus::dbus_interface; use zbus::export::futures_util::lock::Mutex; -use zbus::Connection; -use zbus::SignalContext; +use zbus::{dbus_interface, Connection, SignalContext}; + +use crate::config::Config; +use crate::error::RogError; +use crate::{task_watch_item, CtrlTask, GetSupported}; const ZBUS_PATH: &str = "/org/asuslinux/Power"; const NVIDIA_POWERD: &str = "nvidia-powerd.service"; @@ -118,6 +119,8 @@ impl crate::Reloadable for CtrlPower { } impl CtrlPower { + task_watch_item!(charge_control_end_threshold power); + pub fn new(config: Arc>) -> Result { Ok(CtrlPower { power: AsusPower::new()?, @@ -142,8 +145,6 @@ impl CtrlPower { Ok(()) } - - task_watch_item!(charge_control_end_threshold power); } #[async_trait] diff --git a/daemon/src/ctrl_profiles/config.rs b/daemon/src/ctrl_profiles/config.rs index a116f8fd..4addc171 100644 --- a/daemon/src/ctrl_profiles/config.rs +++ b/daemon/src/ctrl_profiles/config.rs @@ -1,8 +1,9 @@ +use std::fs::{File, OpenOptions}; +use std::io::{Read, Write}; + use log::{error, warn}; use rog_profiles::{FanCurveProfiles, Profile}; use serde_derive::{Deserialize, Serialize}; -use std::fs::{File, OpenOptions}; -use std::io::{Read, Write}; #[derive(Deserialize, Serialize, Debug)] pub struct ProfileConfig { diff --git a/daemon/src/ctrl_profiles/controller.rs b/daemon/src/ctrl_profiles/controller.rs index 331a1458..d113c405 100644 --- a/daemon/src/ctrl_profiles/controller.rs +++ b/daemon/src/ctrl_profiles/controller.rs @@ -1,5 +1,3 @@ -use crate::error::RogError; -use crate::GetSupported; use log::{info, warn}; use rog_platform::platform::AsusPlatform; use rog_platform::supported::PlatformProfileFunctions; @@ -7,6 +5,8 @@ use rog_profiles::error::ProfileError; use rog_profiles::{FanCurveProfiles, Profile}; use super::config::ProfileConfig; +use crate::error::RogError; +use crate::GetSupported; pub struct CtrlPlatformProfile { pub config: ProfileConfig, @@ -18,7 +18,10 @@ impl GetSupported for CtrlPlatformProfile { 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."); + warn!( + "platform_profile kernel interface not found, your laptop does not support this, \ + or the interface is missing." + ); } let res = FanCurveProfiles::is_supported(); @@ -28,7 +31,10 @@ impl GetSupported for CtrlPlatformProfile { }; if !fan_curve_supported { - info!("fan curves kernel interface not found, your laptop does not support this, or the interface is missing."); + info!( + "fan curves kernel interface not found, your laptop does not support this, or the \ + interface is missing." + ); } PlatformProfileFunctions { @@ -74,7 +80,8 @@ impl CtrlPlatformProfile { self.config.write(); } - /// Toggle to next profile in list. This will first read the config, switch, then write out + /// 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.config.active_profile { diff --git a/daemon/src/ctrl_profiles/trait_impls.rs b/daemon/src/ctrl_profiles/trait_impls.rs index 50708e3a..8a274c59 100644 --- a/daemon/src/ctrl_profiles/trait_impls.rs +++ b/daemon/src/ctrl_profiles/trait_impls.rs @@ -1,22 +1,18 @@ +use std::sync::Arc; + use async_trait::async_trait; use log::info; use log::warn; -use rog_profiles::fan_curve_set::CurveData; -use rog_profiles::fan_curve_set::FanCurveSet; -use rog_profiles::FanCurveProfiles; -use rog_profiles::Profile; +use rog_profiles::fan_curve_set::{CurveData, FanCurveSet}; +use rog_profiles::{FanCurveProfiles, Profile}; use zbus::export::futures_util::lock::Mutex; use zbus::export::futures_util::StreamExt; -use zbus::Connection; -use zbus::SignalContext; - -use std::sync::Arc; -use zbus::{dbus_interface, fdo::Error}; - -use crate::error::RogError; -use crate::CtrlTask; +use zbus::fdo::Error; +use zbus::{dbus_interface, Connection, SignalContext}; use super::controller::CtrlPlatformProfile; +use crate::error::RogError; +use crate::CtrlTask; const ZBUS_PATH: &str = "/org/asuslinux/Profile"; const UNSUPPORTED_MSG: &str = @@ -91,8 +87,8 @@ impl ProfileZbus { Err(Error::Failed(UNSUPPORTED_MSG.to_owned())) } - /// Set a profile fan curve enabled status. Will also activate a fan curve if in the - /// same profile mode + /// Set a profile fan curve enabled status. Will also activate a fan curve + /// if in the same profile mode async fn set_fan_curve_enabled( &mut self, profile: Profile, @@ -145,10 +141,11 @@ impl ProfileZbus { Ok(()) } - /// Reset the stored (self) and device curve to the defaults of the platform. + /// Reset the stored (self) and device curve to the defaults of the + /// platform. /// - /// Each platform_profile has a different default and the defualt can be read - /// only for the currently active profile. + /// Each platform_profile has a different default and the defualt can be + /// read only for the currently active profile. async fn set_active_curve_to_defaults(&self) -> zbus::fdo::Result<()> { let mut ctrl = self.0.lock().await; ctrl.config.read(); @@ -159,10 +156,11 @@ impl ProfileZbus { Ok(()) } - /// Reset the stored (self) and device curve to the defaults of the platform. + /// Reset the stored (self) and device curve to the defaults of the + /// platform. /// - /// Each platform_profile has a different default and the defualt can be read - /// only for the currently active profile. + /// Each platform_profile has a different default and the defualt can be + /// read only for the currently active profile. async fn reset_profile_curves(&self, profile: Profile) -> zbus::fdo::Result<()> { let mut ctrl = self.0.lock().await; ctrl.config.read(); @@ -244,8 +242,9 @@ impl crate::Reloadable for ProfileZbus { let active = ctrl.config.active_profile; if let Some(curves) = &mut ctrl.config.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 + // 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.write_profile_curve_to_platform(active, &mut device)?; ctrl.config.write(); } diff --git a/daemon/src/ctrl_supported.rs b/daemon/src/ctrl_supported.rs index 5a24b733..3a94db75 100644 --- a/daemon/src/ctrl_supported.rs +++ b/daemon/src/ctrl_supported.rs @@ -1,27 +1,22 @@ use async_trait::async_trait; use serde_derive::{Deserialize, Serialize}; -use zbus::{dbus_interface, zvariant::Type, Connection}; +use zbus::zvariant::Type; +use zbus::{dbus_interface, Connection}; -use crate::{ - ctrl_anime::CtrlAnime, ctrl_aura::controller::CtrlKbdLed, ctrl_platform::CtrlPlatform, - ctrl_power::CtrlPower, ctrl_profiles::controller::CtrlPlatformProfile, GetSupported, -}; +use crate::ctrl_anime::CtrlAnime; +use crate::ctrl_aura::controller::CtrlKbdLed; +use crate::ctrl_platform::CtrlPlatform; +use crate::ctrl_power::CtrlPower; +use crate::ctrl_profiles::controller::CtrlPlatformProfile; +use crate::GetSupported; -use rog_platform::supported::*; - -#[derive(Serialize, Deserialize, Type)] -pub struct SupportedFunctions { - pub anime_ctrl: AnimeSupportedFunctions, - pub charge_ctrl: ChargeSupportedFunctions, - pub platform_profile: PlatformProfileFunctions, - pub keyboard_led: LedSupportedFunctions, - pub rog_bios_ctrl: RogBiosSupportedFunctions, -} +#[derive(Serialize, Deserialize, Debug, Type)] +pub struct SupportedFunctions(rog_platform::supported::SupportedFunctions); #[dbus_interface(name = "org.asuslinux.Daemon")] impl SupportedFunctions { - fn supported_functions(&self) -> &SupportedFunctions { - self + pub fn supported_functions(&self) -> &rog_platform::supported::SupportedFunctions { + &self.0 } } @@ -36,12 +31,12 @@ impl GetSupported for SupportedFunctions { type A = SupportedFunctions; fn get_supported() -> Self::A { - SupportedFunctions { + Self(rog_platform::supported::SupportedFunctions { anime_ctrl: CtrlAnime::get_supported(), keyboard_led: CtrlKbdLed::get_supported(), charge_ctrl: CtrlPower::get_supported(), platform_profile: CtrlPlatformProfile::get_supported(), rog_bios_ctrl: CtrlPlatform::get_supported(), - } + }) } } diff --git a/daemon/src/daemon.rs b/daemon/src/daemon.rs index 268c3294..7f5feead 100644 --- a/daemon/src/daemon.rs +++ b/daemon/src/daemon.rs @@ -6,25 +6,26 @@ use std::time::Duration; use ::zbus::export::futures_util::lock::Mutex; use ::zbus::Connection; +use daemon::config::Config; +use daemon::ctrl_anime::config::AnimeConfig; +use daemon::ctrl_anime::trait_impls::CtrlAnimeZbus; use daemon::ctrl_anime::CtrlAnime; -use log::{error, info, warn}; -use tokio::time::sleep; -use zbus::SignalContext; - -use daemon::ctrl_anime::{config::AnimeConfig, trait_impls::CtrlAnimeZbus}; -use daemon::ctrl_aura::{config::AuraConfig, controller::CtrlKbdLed, trait_impls::CtrlKbdLedZbus}; +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, controller::CtrlPlatformProfile, trait_impls::ProfileZbus, -}; -use daemon::laptops::LaptopLedData; -use daemon::{ - config::Config, ctrl_supported::SupportedFunctions, laptops::print_board_info, GetSupported, -}; -use daemon::{CtrlTask, Reloadable, ZbusRun}; +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; use rog_profiles::Profile; +use tokio::time::sleep; +use zbus::SignalContext; static PROFILE_CONFIG_PATH: &str = "/etc/asusd/profile.conf"; @@ -66,7 +67,7 @@ async fn main() -> Result<(), Box> { async fn start_daemon() -> Result<(), Box> { let supported = SupportedFunctions::get_supported(); print_board_info(); - println!("{}", serde_json::to_string_pretty(&supported)?); + println!("{}", supported.supported_functions()); // Start zbus server let mut connection = Connection::system().await?; diff --git a/daemon/src/error.rs b/daemon/src/error.rs index 70a884b4..a70450e3 100644 --- a/daemon/src/error.rs +++ b/daemon/src/error.rs @@ -1,8 +1,9 @@ +use std::convert::From; +use std::fmt; + use rog_anime::error::AnimeError; use rog_platform::error::PlatformError; use rog_profiles::error::ProfileError; -use std::convert::From; -use std::fmt; #[derive(Debug)] pub enum RogError { @@ -50,14 +51,21 @@ impl fmt::Display for RogError { RogError::NotFound(deets) => write!(f, "Not found: {}", deets), RogError::DoTask(deets) => write!(f, "Task error: {}", deets), RogError::MissingFunction(deets) => write!(f, "Missing functionality: {}", deets), - RogError::MissingLedBrightNode(path, error) => write!(f, "Led node at {} is missing, please check you have the required patch or dkms module installed: {}", path, error), + RogError::MissingLedBrightNode(path, error) => write!( + f, + "Led node at {} is missing, please check you have the required patch or dkms \ + module installed: {}", + path, error + ), RogError::ReloadFail(deets) => write!(f, "Reload error: {}", deets), RogError::Profiles(deets) => write!(f, "Profile error: {}", deets), RogError::Initramfs(detail) => write!(f, "Initiramfs error: {}", detail), RogError::Modprobe(detail) => write!(f, "Modprobe error: {}", detail), RogError::Io(detail) => write!(f, "std::io error: {}", detail), RogError::Zbus(detail) => write!(f, "Zbus error: {}", detail), - RogError::ChargeLimit(value) => write!(f, "Invalid charging limit, not in range 20-100%: {}", value), + RogError::ChargeLimit(value) => { + write!(f, "Invalid charging limit, not in range 20-100%: {}", value) + } RogError::AuraEffectNotSupported => write!(f, "Aura effect not supported"), RogError::NoAuraKeyboard => write!(f, "No supported Aura keyboard"), RogError::NoAuraNode => write!(f, "No Aura keyboard node found"), diff --git a/daemon/src/laptops.rs b/daemon/src/laptops.rs deleted file mode 100644 index 2dbab730..00000000 --- a/daemon/src/laptops.rs +++ /dev/null @@ -1,167 +0,0 @@ -use log::{info, warn}; -use rog_aura::{AuraModeNum, AuraZone}; -use serde_derive::{Deserialize, Serialize}; -use std::fs::OpenOptions; -use std::io::Read; - -pub const ASUS_LED_MODE_CONF: &str = "/etc/asusd/asusd-ledmodes.toml"; -pub const ASUS_LED_MODE_USER_CONF: &str = "/etc/asusd/asusd-user-ledmodes.toml"; -pub const ASUS_KEYBOARD_DEVICES: [&str; 4] = ["1866", "1869", "1854", "19b6"]; - -pub fn print_board_info() { - let dmi = sysfs_class::DmiId::default(); - let board_name = dmi.board_name().expect("Could not get board_name"); - let prod_family = dmi.product_family().expect("Could not get product_family"); - - info!("Product family: {}", prod_family.trim()); - info!("Board name: {}", board_name.trim()); -} - -pub fn print_modes(supported_modes: &[u8]) { - if !supported_modes.is_empty() { - info!("Supported Keyboard LED modes are:"); - for mode in supported_modes { - let mode = <&str>::from(&::from(*mode)); - info!("- {}", mode); - } - info!( - "If these modes are incorrect you can edit {}", - ASUS_LED_MODE_CONF - ); - } else { - info!("No RGB control available"); - } -} - -#[derive(Debug, Default, Deserialize, Serialize)] -struct LedSupportFile { - led_data: Vec, -} - -#[derive(Debug, Clone, Default, Deserialize, Serialize)] -#[serde(default)] -pub struct LaptopLedData { - pub prod_family: String, - pub board_names: Vec, - pub standard: Vec, - pub multizone: Vec, - pub per_key: bool, -} - -impl LaptopLedData { - pub fn get_data() -> Self { - let dmi = sysfs_class::DmiId::default(); - let board_name = dmi.board_name().expect("Could not get board_name"); - let prod_family = dmi.product_family().expect("Could not get product_family"); - - if let Some(modes) = LedSupportFile::load_from_config() { - if let Some(data) = modes.matcher(&prod_family, &board_name) { - return data; - } - } - info!("Using generic LED control for keyboard brightness only"); - LaptopLedData { - prod_family, - board_names: vec![board_name], - standard: vec![], - multizone: vec![], - per_key: false, - } - } -} - -impl LedSupportFile { - /// Consumes the `LEDModes` - fn matcher(self, prod_family: &str, board_name: &str) -> Option { - for config in self.led_data { - if prod_family.contains(&config.prod_family) { - for board in &config.board_names { - if board_name.contains(board) { - info!("Matched to {} {}", config.prod_family, board); - return Some(config); - } - } - } - } - None - } - - fn load_from_config() -> Option { - 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) = toml::from_str::(&buf) { - data.led_data.append(&mut tmp.led_data); - } - 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 = toml::from_str(&buf) - .unwrap_or_else(|_| panic!("Could not deserialise {}", ASUS_LED_MODE_CONF)); - data.led_data.append(&mut tmp.led_data); - loaded = true; - info!( - "Loaded default LED support data from {}", - ASUS_LED_MODE_CONF - ); - } - } - } - - if loaded { - return Some(data); - } - - warn!("Does {} exist?", ASUS_LED_MODE_USER_CONF); - None - } -} - -#[cfg(test)] -mod tests { - use std::{fs::OpenOptions, io::Read, path::PathBuf}; - - use super::LaptopLedData; - use rog_aura::{AuraModeNum, AuraZone}; - - #[test] - fn check_data_parse() { - let led = LaptopLedData { - prod_family: "Test".to_owned(), - board_names: vec!["Test".to_owned()], - standard: vec![AuraModeNum::Static], - multizone: vec![AuraZone::Key1, AuraZone::Logo, AuraZone::BarLeft], - per_key: false, - }; - - let toml = toml::to_string_pretty(&led).unwrap(); - println!("{toml}"); - - let mut data = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - data.push("../data/asusd-ledmodes.toml"); - - let mut file = OpenOptions::new().read(true).open(&data).unwrap(); - let mut buf = String::new(); - file.read_to_string(&mut buf).unwrap(); - - let x = toml::to_string_pretty(&buf).unwrap(); - println!("{x}"); - } -} diff --git a/daemon/src/lib.rs b/daemon/src/lib.rs index 7767543f..d46a0c11 100644 --- a/daemon/src/lib.rs +++ b/daemon/src/lib.rs @@ -11,8 +11,6 @@ pub mod ctrl_platform; pub mod ctrl_power; /// Control platform profiles + fan-curves if available pub mod ctrl_profiles; -/// Laptop matching to determine capabilities -pub mod laptops; /// Fetch all supported functions for the laptop pub mod ctrl_supported; @@ -21,21 +19,27 @@ pub mod error; use std::future::Future; -use crate::error::RogError; use async_trait::async_trait; -use log::{debug, warn}; +use log::{debug, info, warn}; use logind_zbus::manager::ManagerProxy; -use zbus::{export::futures_util::StreamExt, zvariant::ObjectPath, Connection, SignalContext}; +use zbus::export::futures_util::StreamExt; +use zbus::zvariant::ObjectPath; +use zbus::{Connection, SignalContext}; -/// This macro adds a function which spawns an `inotify` task on the passed in `Executor`. +use crate::error::RogError; + +/// This macro adds a function which spawns an `inotify` task on the passed in +/// `Executor`. /// -/// The generated function is `watch_()`. Self requires the following methods to be available: -/// - `() -> SomeValue`, functionally is a getter, but is allowed to have side effects. +/// The generated function is `watch_()`. Self requires the following +/// methods to be available: +/// - `() -> SomeValue`, functionally is a getter, but is allowed to have +/// side effects. /// - `notify_(SignalContext, SomeValue)` /// -/// In most cases if `SomeValue` is stored in a config then `()` getter is expected to update it. -/// The getter should *never* write back to the path or attribute that is being watched or an -/// infinite loop will occur. +/// In most cases if `SomeValue` is stored in a config then `()` getter is +/// expected to update it. The getter should *never* write back to the path or +/// attribute that is being watched or an infinite loop will occur. /// /// # Example /// @@ -80,6 +84,15 @@ macro_rules! task_watch_item { pub const VERSION: &str = env!("CARGO_PKG_VERSION"); +pub fn print_board_info() { + let dmi = sysfs_class::DmiId::default(); + let board_name = dmi.board_name().expect("Could not get board_name"); + let prod_family = dmi.product_family().expect("Could not get product_family"); + + info!("Product family: {}", prod_family.trim()); + info!("Board name: {}", board_name.trim()); +} + #[async_trait] pub trait Reloadable { async fn reload(&mut self) -> Result<(), RogError>; @@ -115,13 +128,14 @@ pub trait CtrlTask { SignalContext::new(connection, Self::zbus_path()) } - /// Implement to set up various tasks that may be required, using the `Executor`. - /// No blocking loops are allowed, or they must be run on a separate thread. + /// Implement to set up various tasks that may be required, using the + /// `Executor`. No blocking loops are allowed, or they must be run on a + /// separate thread. async fn create_tasks(&self, signal: SignalContext<'static>) -> Result<(), RogError>; // /// Create a timed repeating task - // async fn repeating_task(&self, millis: u64, mut task: impl FnMut() + Send + 'static) { - // use std::time::Duration; + // async fn repeating_task(&self, millis: u64, mut task: impl FnMut() + Send + + // 'static) { use std::time::Duration; // use tokio::time; // let mut timer = time::interval(Duration::from_millis(millis)); // tokio::spawn(async move { @@ -130,10 +144,11 @@ pub trait CtrlTask { // }); // } - /// Free helper method to create tasks to run on: sleep, wake, shutdown, boot + /// Free helper method to create tasks to run on: sleep, wake, shutdown, + /// boot /// - /// The closures can potentially block, so execution time should be the minimal possible - /// such as save a variable. + /// The closures can potentially block, so execution time should be the + /// minimal possible such as save a variable. async fn create_sys_event_tasks< Fut1, Fut2, diff --git a/data/asusd-ledmodes.toml b/data/asusd-ledmodes.toml deleted file mode 100644 index 577af09b..00000000 --- a/data/asusd-ledmodes.toml +++ /dev/null @@ -1,204 +0,0 @@ -[[led_data]] -prod_family = "ASUS TUF Gaming F15" -board_names = ["FX506HC"] -standard = ["Static", "Breathe", "Strobe", "Pulse"] -multizone = [] -per_key = false - -[[led_data]] -prod_family = "TUF" -board_names = ["FA507"] -standard = ["Static", "Breathe", "Strobe", "Pulse"] -multizone = [] -per_key = false - -[[led_data]] -prod_family = "TUF Gaming" -board_names = ["FX505D"] -standard = ["Static", "Breathe", "Strobe", "Rainbow", "Pulse"] -multizone = [] -per_key = false - -[[led_data]] -prod_family = "ASUS TUF Gaming A15" -board_names = ["FA506I"] -standard = ["Static", "Breathe", "Strobe", "Pulse"] -multizone = [] -per_key = false - -[[led_data]] -prod_family = "Zephyrus S" -board_names = ["GX502", "GX701", "G531", "GL531", "G532"] -standard = ["Static", "Breathe", "Strobe", "Rainbow", "Star", "Rain", "Highlight", "Laser", "Ripple", "Pulse", "Comet", "Flash"] -multizone = [] -per_key = true - -[[led_data]] -prod_family = "Zephyrus M" -board_names = ["GU502G"] -standard = ["Static", "Breathe", "Strobe", "Rainbow", "Star", "Rain", "Highlight", "Laser", "Ripple", "Pulse", "Comet", "Flash"] -multizone = [] -per_key = true - -[[led_data]] -prod_family = "ROG Zephyrus M15" -board_names = ["GU502LU"] -standard = ["Static", "Breathe", "Strobe", "Pulse"] -multizone = [] -per_key = false - -[[led_data]] -prod_family = "ROG Zephyrus M15" -board_names = ["GU502L"] -standard = ["Static", "Breathe", "Strobe", "Rainbow", "Star", "Rain", "Highlight", "Laser", "Ripple", "Pulse", "Comet", "Flash"] -multizone = [] -per_key = true - -[[led_data]] -prod_family = "ROG Zephyrus M16" -board_names = ["GU603Z", "GU603H"] -standard = ["Static", "Breathe", "Strobe", "Rainbow", "Pulse"] -multizone = [] -per_key = false - -[[led_data]] -prod_family = "ROG Zephyrus S17" -board_names = ["GX703H"] -standard = ["Static", "Breathe", "Strobe", "Rainbow", "Star", "Rain", "Highlight", "Laser", "Ripple", "Pulse", "Comet", "Flash"] -multizone = [] -per_key = false - - -[[led_data]] -prod_family = "Zephyrus" -board_names = ["GM501G", "GX531"] -standard = ["Static", "Breathe", "Strobe", "Rainbow", "Pulse"] -multizone = ["Key1", "Key2", "Key3", "Key4"] -per_key = false - -[[led_data]] -prod_family = "ROG Strix" -board_names = ["G531GW", "G533QR", "G533QS", "G733Q", "G513QR", "G713QR", "G513QM", "G713IC", "G713RS"] -standard = ["Static", "Breathe", "Strobe", "Rainbow", "Star", "Rain", "Highlight", "Laser", "Ripple", "Pulse", "Comet", "Flash"] -multizone = [] -per_key = true - -[[led_data]] -prod_family = "ROG Strix" -board_names = ["G513QE", "GX531", "G512LV", "G712LV", "G712LW", "G513IH", "G513QY", "G713QM", "G512", "G713RM", "G713RW"] -standard = ["Static", "Breathe", "Strobe", "Rainbow", "Pulse"] -multizone = ["Key1", "Key2", "Key3", "Key4"] -per_key = false - -[[led_data]] -prod_family = "ROG Strix" -board_names = ["G512LI", "G712LI", "G531GD"] -standard = ["Static", "Breathe", "Strobe", "Rainbow", "Pulse"] -multizone = [] -per_key = false - -[[led_data]] -prod_family = "ROG Strix" -board_names = ["G513IM"] -standard = ["Flash", "Static", "Breathe", "Strobe", "Rainbow"] -multizone = [] -per_key = true - -[[led_data]] -prod_family = "Strix" -board_names = ["G731GV", "G731GW", "G531GV"] -standard = ["Static", "Breathe", "Strobe", "Rainbow"] -multizone = ["Key1", "Key2", "Key3", "Key4"] -per_key = false - -[[led_data]] -prod_family = "Strix" -board_names = ["GL504G"] -standard = ["Static", "Breathe", "Strobe", "Rainbow", "Pulse"] -multizone = ["Key1", "Key2", "Key3", "Key4", "Logo", "BarLeft", "BarRight"] -per_key = false - -[[led_data]] -prod_family = "Strix" -board_names = ["G731GT", "G731GU", "G531GT", "G531GU"] -standard = ["Static", "Breathe", "Strobe", "Rainbow"] -multizone = [] -per_key = false - -[[led_data]] -prod_family = "Strix Scar" -board_names = ["G531", "G731"] -standard = ["Static", "Breathe", "Strobe", "Rainbow", "Star", "Rain", "Highlight", "Laser", "Ripple", "Pulse", "Comet", "Flash"] -multizone = ["Key1", "Key2", "Key3", "Key4"] -per_key = true - -[[led_data]] -prod_family = "ROG" -board_names = ["GL553VE"] -standard = ["Static", "Breathe", "Strobe"] -multizone = ["Key1", "Key2", "Key3", "Key4"] -per_key = false - -[[led_data]] -prod_family = "ROG Zephyrus G14" -board_names = ["GA401Q"] -standard = ["Static", "Breathe", "Pulse"] -multizone = [] -per_key = false - -[[led_data]] -prod_family = "ROG Zephyrus G14" -board_names = ["GA402R"] -standard = ["Static", "Breathe", "Pulse", "Rainbow"] -multizone = [] -per_key = false - -# GA503QE at higher priority (first match) than GA503Q -[[led_data]] -prod_family = "ROG Zephyrus G15" -board_names = ["GA503QE"] -standard = ["Static", "Breathe", "Pulse"] -multizone = [] -per_key = false - -[[led_data]] -prod_family = "ROG Zephyrus G15" -board_names = ["GA503Q", "GA503R"] -standard = ["Static", "Breathe", "Pulse", "Rainbow", "Strobe"] -multizone = [] -per_key = false - -[[led_data]] -prod_family = "ROG Zephyrus" -board_names = ["GX550L"] -standard = ["Static", "Breathe", "Strobe", "Rainbow", "Star", "Rain", "Highlight", "Laser", "Ripple", "Pulse", "Comet", "Flash"] -multizone = [] -per_key = true - -[[led_data]] -prod_family = "ROG Zephyrus Duo 15 SE" -board_names = ["GX551Q"] -standard = ["Static", "Breathe", "Strobe", "Rainbow", "Pulse"] -multizone = [] -per_key = true - -[[led_data]] -prod_family = "ROG Flow X13" -board_names = ["GV301Q"] -standard = ["Static", "Breathe", "Pulse"] -multizone = [] -per_key = false - -[[led_data]] -prod_family = "ROG Strix" -board_names = ["G513IC", "G513RC", "G513RM"] -standard = ["Static", "Breathe", "Strobe", "Rainbow", "Pulse"] -multizone = [] -per_key = false - -[[led_data]] -prod_family = "ROG Flow X16" -board_names = ["GV601R"] -standard = ["Static", "Breathe", "Strobe", "Pulse"] -multizone = [] -per_key = false diff --git a/rog-anime/src/data.rs b/rog-anime/src/data.rs index e8b410e0..65ead7f4 100644 --- a/rog-anime/src/data.rs +++ b/rog-anime/src/data.rs @@ -1,20 +1,17 @@ -use std::{ - convert::TryFrom, - thread::sleep, - time::{Duration, Instant}, -}; +use std::convert::TryFrom; +use std::thread::sleep; +use std::time::{Duration, Instant}; use log::info; use serde_derive::{Deserialize, Serialize}; #[cfg(feature = "dbus")] use zbus::zvariant::Type; -use crate::{ - error::{AnimeError, Result}, - AnimTime, AnimeGif, -}; +use crate::error::{AnimeError, Result}; +use crate::{AnimTime, AnimeGif}; -/// The first 7 bytes of a USB packet are accounted for by `USB_PREFIX1` and `USB_PREFIX2` +/// The first 7 bytes of a USB packet are accounted for by `USB_PREFIX1` and +/// `USB_PREFIX2` const BLOCK_START: usize = 7; /// *Not* inclusive, the byte before this is the final for each "pane" const BLOCK_END: usize = 634; @@ -143,9 +140,11 @@ impl TryFrom for AnimePacketType { } } -/// This runs the animations as a blocking loop by using the `callback` to write data +/// This runs the animations as a blocking loop by using the `callback` to write +/// data /// -/// If `callback` is `Ok(true)` then `run_animation` will exit the animation loop early. +/// If `callback` is `Ok(true)` then `run_animation` will exit the animation +/// loop early. pub fn run_animation(frames: &AnimeGif, callback: &dyn Fn(AnimeDataBuffer) -> Result) { let mut count = 0; let start = Instant::now(); diff --git a/rog-anime/src/diagonal.rs b/rog-anime/src/diagonal.rs index 30932a5d..1c99556b 100644 --- a/rog-anime/src/diagonal.rs +++ b/rog-anime/src/diagonal.rs @@ -1,12 +1,12 @@ -use std::{path::Path, time::Duration}; +use std::path::Path; +use std::time::Duration; -use crate::{ - data::AnimeDataBuffer, - error::{AnimeError, Result}, - AnimeType, -}; +use crate::data::AnimeDataBuffer; +use crate::error::{AnimeError, Result}; +use crate::AnimeType; -/// Mostly intended to be used with ASUS gifs, but can be used for other purposes (like images) +/// Mostly intended to be used with ASUS gifs, but can be used for other +/// purposes (like images) #[derive(Debug, Clone)] pub struct AnimeDiagonal(AnimeType, Vec>, Option); @@ -25,7 +25,8 @@ impl AnimeDiagonal { &mut self.1 } - /// Get a full diagonal row where `x` `y` is the starting point and `len` is the length of data. + /// Get a full diagonal row where `x` `y` is the starting point and `len` + /// is the length of data. fn get_row(&self, x: usize, y: usize, len: usize) -> Vec { let mut buf = Vec::with_capacity(len); for i in 0..len { @@ -36,8 +37,9 @@ impl AnimeDiagonal { buf } - /// Generate the base image from inputs. The result can be displayed as is or - /// updated via scale, position, or angle then displayed again after `update()`. + /// Generate the base image from inputs. The result can be displayed as is + /// or updated via scale, position, or angle then displayed again after + /// `update()`. #[inline] pub fn from_png( path: &Path, @@ -290,7 +292,8 @@ impl AnimeDiagonal { #[cfg(test)] mod tests { - use std::{convert::TryFrom, path::PathBuf}; + use std::convert::TryFrom; + use std::path::PathBuf; use crate::{AnimeDiagonal, AnimePacketType, AnimeType}; diff --git a/rog-anime/src/error.rs b/rog-anime/src/error.rs index b8c7c585..687862c9 100644 --- a/rog-anime/src/error.rs +++ b/rog-anime/src/error.rs @@ -1,8 +1,9 @@ -use gif::DecodingError; -use png_pong::decode::Error as PngError; use std::error::Error; use std::fmt; +use gif::DecodingError; +use png_pong::decode::Error as PngError; + pub type Result = std::result::Result; #[derive(Debug)] @@ -12,7 +13,8 @@ pub enum AnimeError { Png(PngError), Gif(DecodingError), Format, - /// The input was incorrect size, expected size is `IncorrectSize(width, height)` + /// The input was incorrect size, expected size is `IncorrectSize(width, + /// height)` IncorrectSize(u32, u32), Dbus(String), Udev(String, std::io::Error), diff --git a/rog-anime/src/gif.rs b/rog-anime/src/gif.rs index 28059320..d5d6a4c4 100644 --- a/rog-anime/src/gif.rs +++ b/rog-anime/src/gif.rs @@ -1,15 +1,19 @@ +use std::convert::TryFrom; +use std::fs::File; +use std::path::Path; +use std::time::Duration; + use glam::Vec2; use serde_derive::{Deserialize, Serialize}; -use std::convert::TryFrom; -use std::{fs::File, path::Path, time::Duration}; -use crate::error::AnimeError; -use crate::{error::Result, AnimeDataBuffer, AnimeDiagonal, AnimeImage, AnimeType, Pixel}; +use crate::error::{AnimeError, Result}; +use crate::{AnimeDataBuffer, AnimeDiagonal, AnimeImage, AnimeType, Pixel}; #[derive(Debug, Clone, Deserialize, Serialize)] pub struct AnimeFrame { /// Precomputed data for the frame. This can be transferred directly to the - /// the `asusd` daemon over dbus or converted to USB packet with `AnimePacketType::from(buffer)` + /// the `asusd` daemon over dbus or converted to USB packet with + /// `AnimePacketType::from(buffer)` data: AnimeDataBuffer, delay: Duration, } @@ -33,7 +37,8 @@ impl AnimeFrame { pub enum AnimTime { /// Time in milliseconds for animation to run Time(Duration), - /// How many full animation loops to run or how many seconds if image is static + /// How many full animation loops to run or how many seconds if image is + /// static Count(u32), /// Run for infinite time Infinite, @@ -169,8 +174,8 @@ impl AnimeGif { Ok(Self(frames, duration)) } - /// Create an animation using a gif of any size. This method must precompute the - /// result. + /// Create an animation using a gif of any size. This method must precompute + /// the result. #[inline] pub fn from_gif( file_name: &Path, @@ -243,9 +248,10 @@ impl AnimeGif { Ok(Self(frames, duration)) } - /// Make a static gif out of a greyscale png. If no duration is specified then the default - /// will be 1 second long. If `AnimTime::Cycles` is specified for `duration` then this can - /// be considered how many seconds the image will show for. + /// Make a static gif out of a greyscale png. If no duration is specified + /// then the default will be 1 second long. If `AnimTime::Cycles` is + /// specified for `duration` then this can be considered how many + /// seconds the image will show for. #[inline] pub fn from_png( file_name: &Path, diff --git a/rog-anime/src/image.rs b/rog-anime/src/image.rs index 8d42e5a4..6ee6fa5f 100644 --- a/rog-anime/src/image.rs +++ b/rog-anime/src/image.rs @@ -1,13 +1,12 @@ -use std::{convert::TryFrom, path::Path}; +use std::convert::TryFrom; +use std::path::Path; pub use glam::Vec2; use glam::{Mat3, Vec3}; -use crate::{ - data::AnimeDataBuffer, - error::{AnimeError, Result}, - AnimeType, -}; +use crate::data::AnimeDataBuffer; +use crate::error::{AnimeError, Result}; +use crate::AnimeType; /// A single greyscale + alpha pixel in the image #[derive(Copy, Clone, Debug)] @@ -29,8 +28,8 @@ impl Default for Pixel { /// A single LED position and brightness. The intention of this struct /// is to be used to sample an image and set the LED brightness. /// -/// The position of the Led in `LedPositions` determines the placement in the final -/// data packets when written to the `AniMe`. +/// The position of the Led in `LedPositions` determines the placement in the +/// final data packets when written to the `AniMe`. #[derive(Debug, Clone, Copy, PartialEq)] pub struct Led(f32, f32, u8); @@ -73,8 +72,9 @@ pub struct AnimeImage { img_pixels: Vec, /// width of the image width: u32, - /// The type of the display. The GA401 and GA402 use the same controller and therefore same ID, - /// so the identifier must be by laptop model in `AnimeType`. + /// The type of the display. The GA401 and GA402 use the same controller and + /// therefore same ID, so the identifier must be by laptop model in + /// `AnimeType`. anime_type: AnimeType, } @@ -108,9 +108,9 @@ impl AnimeImage { /// Scale ratio in CM /// - /// This is worked out by measuring the physical width of the display from pixel center to - /// center, then dividing by ` + 0.5`, where the LED count is - /// first/longest row. + /// This is worked out by measuring the physical width of the display from + /// pixel center to center, then dividing by ` + + /// 0.5`, where the LED count is first/longest row. /// /// For GA401 this is `26.8 / (33 + 0.5) = 0.8` /// For GA402 this is `27.4 / (35 + 0.5) = 0.77` @@ -123,9 +123,9 @@ impl AnimeImage { /// 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 ` + 1.0`, where the LED count is - /// first/longest row. + /// This is worked out by measuring the physical height of the display from + /// pixel center to pixel center, then dividing by ` + 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` @@ -136,12 +136,12 @@ impl AnimeImage { } } - /// Get the starting X position for the data we actually require when writing - /// it out to LEDs. + /// Get the starting X position for the data we actually require when + /// writing it out to LEDs. /// - /// 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 + /// 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 /// +------------+ /// | | /// | | @@ -251,8 +251,8 @@ impl AnimeImage { &mut self.img_pixels } - /// Generate a list of LED positions. These are then used to sample the Image data, - /// and will contain their resulting brightness. + /// Generate a list of LED positions. These are then used to sample the + /// Image data, and will contain their resulting brightness. #[inline] pub fn generate_image_positioning(anime_type: AnimeType) -> Vec> { (0..AnimeImage::height(anime_type)) @@ -274,8 +274,8 @@ impl AnimeImage { /// samples, the result can then been transformed to the appropriate data /// for displaying. /// - /// The internal for loop iterates over the LED positions, skipping the blank/dead - /// pixels if any. + /// The internal for loop iterates over the LED positions, skipping the + /// blank/dead pixels if any. #[inline] pub fn update(&mut self) { let width = self.width as i32; @@ -343,7 +343,7 @@ impl AnimeImage { } last_was_led = true; } else if last_was_led { - //ends.push(idx); + // ends.push(idx); last_was_led = false; } } @@ -382,8 +382,9 @@ impl AnimeImage { led_from_px.inverse() } - /// Generate the base image from inputs. The result can be displayed as is or - /// updated via scale, position, or angle then displayed again after `update()`. + /// Generate the base image from inputs. The result can be displayed as is + /// or updated via scale, position, or angle then displayed again after + /// `update()`. #[inline] pub fn from_png( path: &Path, @@ -491,8 +492,8 @@ impl AnimeImage { impl TryFrom<&AnimeImage> for AnimeDataBuffer { type Error = AnimeError; - /// Do conversion from the nested Vec in `AnimeDataBuffer` to the two required - /// packets suitable for sending over USB + /// Do conversion from the nested Vec in `AnimeDataBuffer` to the two + /// required packets suitable for sending over USB fn try_from(leds: &AnimeImage) -> Result { let mut l: Vec = leds .led_pos @@ -511,9 +512,11 @@ impl TryFrom<&AnimeImage> for AnimeDataBuffer { #[cfg(test)] mod tests { - use std::{convert::TryFrom, path::PathBuf}; + use std::convert::TryFrom; + use std::path::PathBuf; - use crate::{image::*, AnimTime, AnimeGif, AnimePacketType}; + use crate::image::*; + use crate::{AnimTime, AnimeGif, AnimePacketType}; #[test] fn led_positions() { diff --git a/rog-anime/src/lib.rs b/rog-anime/src/lib.rs index ed1f76d2..63629291 100644 --- a/rog-anime/src/lib.rs +++ b/rog-anime/src/lib.rs @@ -11,8 +11,8 @@ pub use grid::*; mod image; pub use image::*; -/// A grid of data that is intended to be read out and displayed on the `AniMe` as -/// a diagonal +/// A grid of data that is intended to be read out and displayed on the `AniMe` +/// as a diagonal mod diagonal; pub use diagonal::*; @@ -21,8 +21,8 @@ pub use diagonal::*; mod gif; pub use crate::gif::*; -/// A container of images/grids/gifs/pauses which can be iterated over to generate -/// cool effects +/// A container of images/grids/gifs/pauses which can be iterated over to +/// generate cool effects mod sequencer; pub use sequencer::*; diff --git a/rog-anime/src/sequencer.rs b/rog-anime/src/sequencer.rs index a07ba9e8..3a6e6eec 100644 --- a/rog-anime/src/sequencer.rs +++ b/rog-anime/src/sequencer.rs @@ -1,14 +1,15 @@ +use std::convert::TryFrom; +use std::path::PathBuf; +use std::time::Duration; + use glam::Vec2; use serde_derive::{Deserialize, Serialize}; -use std::convert::TryFrom; -use std::{path::PathBuf, time::Duration}; -use crate::{ - error::Result, AnimTime, AnimeDataBuffer, AnimeDiagonal, AnimeGif, AnimeImage, AnimeType, -}; +use crate::error::Result; +use crate::{AnimTime, AnimeDataBuffer, AnimeDiagonal, AnimeGif, AnimeImage, AnimeType}; -/// All the possible `AniMe` actions that can be used. This enum is intended to be -/// a helper for loading up `ActionData`. +/// All the possible `AniMe` actions that can be used. This enum is intended to +/// be a helper for loading up `ActionData`. #[derive(Debug, Clone, Deserialize, Serialize)] pub enum ActionLoader { /// Full gif sequence. Immutable. @@ -23,7 +24,8 @@ pub enum ActionLoader { time: AnimTime, brightness: f32, }, - /// Animated gif. If the file is a png a static gif is created using the `time` properties + /// Animated gif. If the file is a png a static gif is created using the + /// `time` properties ImageAnimation { file: PathBuf, scale: f32, @@ -44,13 +46,14 @@ pub enum ActionLoader { Pause(Duration), } -/// All the possible `AniMe` actions that can be used. The enum is intended to be -/// used in a array allowing the user to cycle through a series of actions. +/// All the possible `AniMe` actions that can be used. The enum is intended to +/// be used in a array allowing the user to cycle through a series of actions. #[derive(Debug, Clone, Deserialize, Serialize)] pub enum ActionData { /// Full gif sequence. Immutable. Animation(AnimeGif), - /// Basic image, can have properties changed and image updated via those properties + /// Basic image, can have properties changed and image updated via those + /// properties Image(Box), /// A pause to be used between sequences Pause(Duration), @@ -174,8 +177,8 @@ impl Sequences { Self(Vec::new(), anime_type) } - /// Use a base `AnimeAction` to generate the precomputed data and insert in to - /// the run buffer + /// Use a base `AnimeAction` to generate the precomputed data and insert in + /// to the run buffer #[inline] pub fn insert(&mut self, index: usize, action: &ActionLoader) -> Result<()> { self.0 @@ -183,9 +186,9 @@ impl Sequences { Ok(()) } - /// Remove an item at this position from the run buffer. If the `index` supplied - /// is not in range then `None` is returned, otherwise the `ActionData` at that location - /// is yeeted and returned. + /// Remove an item at this position from the run buffer. If the `index` + /// supplied is not in range then `None` is returned, otherwise the + /// `ActionData` at that location is yeeted and returned. #[inline] pub fn remove_item(&mut self, index: usize) -> Option { if index < self.0.len() { diff --git a/rog-anime/src/usb.rs b/rog-anime/src/usb.rs index a3fa2a12..83ef866d 100644 --- a/rog-anime/src/usb.rs +++ b/rog-anime/src/usb.rs @@ -1,13 +1,15 @@ //! Utils for writing to the `AniMe` USB device //! //! Use of the device requires a few steps: -//! 1. Initialise the device by writing the two packets from `get_init_packets()` -//! 2. Write data from `AnimePacketType` -//! 3. Write the packet from `get_flush_packet()`, which tells the device to display the data from step 2 +//! 1. Initialise the device by writing the two packets from +//! `get_init_packets()` 2. Write data from `AnimePacketType` +//! 3. Write the packet from `get_flush_packet()`, which tells the device to +//! display the data from step 2 //! //! Step 1 need to applied only on fresh system boot. -use crate::{error::AnimeError, AnimeType}; +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'.', @@ -17,8 +19,9 @@ const DEV_PAGE: u8 = 0x5e; pub const VENDOR_ID: u16 = 0x0b05; pub const PROD_ID: u16 = 0x193b; -/// `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. +/// `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. /// /// The currently known USB device is `19b6`. #[inline] @@ -34,8 +37,8 @@ pub fn get_anime_type() -> Result { Err(AnimeError::UnsupportedDevice) } -/// Get the two device initialization packets. These are required for device start -/// after the laptop boots. +/// Get the two device initialization packets. These are required for device +/// start after the laptop boots. #[inline] pub const fn pkts_for_init() -> [[u8; PACKET_SIZE]; 2] { let mut packets = [[0; PACKET_SIZE]; 2]; @@ -74,8 +77,8 @@ 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. +/// Get the packet required for setting the device to on. Requires +/// `pkt_for_apply()` to be written after. #[inline] pub const fn pkt_for_set_on(on: bool) -> [u8; PACKET_SIZE] { let mut pkt = [0; PACKET_SIZE]; diff --git a/rog-aura/Cargo.toml b/rog-aura/Cargo.toml index 54e4e9ed..5de63932 100644 --- a/rog-aura/Cargo.toml +++ b/rog-aura/Cargo.toml @@ -13,14 +13,18 @@ edition = "2021" exclude = ["data"] [features] -default = ["dbus", "toml"] +default = ["dbus", "ron"] dbus = ["zbus"] [dependencies] serde.workspace = true serde_derive.workspace = true -toml = { workspace = true, optional = true } zbus = { workspace = true, optional = true } -[dev-dependencies] -serde_json.workspace = true +# cli and logging +log.workspace = true + +# Device control +sysfs-class.workspace = true # used for backlight control and baord ID + +ron = { version = "*", optional = true } \ No newline at end of file diff --git a/rog-aura/README.md b/rog-aura/README.md index e69de29b..3b746bfd 100644 --- a/rog-aura/README.md +++ b/rog-aura/README.md @@ -0,0 +1,246 @@ +# rog-aura + +## What is it? + +rog-aura is a helper crate for interacting with the RGB keyboards found on many ASUS ROG gaming laptops such as the Zephyrus, Strix, TUF, and a few others. + +The crate is primarily used in the asusctl suite of tools. + +The majority of the crate deals with converting from the API to USB packets suitable for sending raw to the USB device. + +## Features + +- Detect USB keyboard type, or if the kayboard is an I2C connected one (typical on TUF) +- Set various basic modes +- Set various basic zones +- Set advanced/direct addressing of: + + Single zone + + Multizone + + Per-key +- Physical layout mapping + +## Config files + +The crate includes config files for helping to determine what laptop models support what feature. This is heavily dependant on folks testing and contributing data. + +It also includes layouts for some laptops. Also heavily dependant on contributions. + +# Support list + +`aura_support.ron` is the support listing file. It functions as a database of which models support which features. + +```ron + ( + board_name: "G513QR", + layout_name: "g513i-per-key", + basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash], + basic_zones: [], + advanced_type: PerKey, + ), +``` + +in the above example the board name is found from `cat /sys/devices/virtual/dmi/id/board_name`. In some model ranges the last letter (which is likely the dGPU/feature variant) can be ommited. `layout_name` is the first part of a related filename for the layout as described in the next section - the filename should be postfixed with a locale such as `g513i_US.ron`. + +`basic_modes` are the default inbuilt modes the keyboard supports. Not all keyboards have the same set of modes. `basic_zones` is a secondary part of `basic_modes` where this lists which zones can be set as part of the basic mode. Each zone reauires a full basic mode setting. The zones supported here are + +- `Key1` +- `Key2` +- `Key3` +- `Key4` +- `Logo` +- `BarLeft` +- `BarRight` + +note that the zone support seems to have changed with new generations of keyboards and is shifted to `advanced_type`. The `advanced_type` field is taken in to account when setting advanced effects. It can be combined with the keyboard layout also to be used in a GUI. + +`advanced_type` can be one of: + +- `None`, no advanced aura at all +- `PerKey`, can use any of `LedCode` except for the `Zoned` items below which work in a different way +- `Zoned`, takes an array such as: + + `Zoned([SingleZone])`, only one zone + + `Zoned([ ... ]),`, array with any combination of: + - `ZonedKbLeft` // keyboard left + - `ZonedKbLeftMid` // keyboard left-middle + - `ZonedKbRightMid` // etc + - `ZonedKbRight` + - `LightbarRight` + - `LightbarRightCorner` + - `LightbarRightBottom` + - `LightbarLeftBottom` + - `LightbarLeftCorner` + - `LightbarLeft` + +# Layouts + +The layout structure is kept in a `.ron`, which is "rusty object notation". The way this works is best demonstrated: + +```ron +( + locale: "US", + key_shapes: { + // This is a regular LED spot, it has a size (width x height), and padding around each edge. + // The final size should be (width + pad_left + pad_right, height + pad_top + pad_bottom) + "regular": Led( + width: 1.0, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + // There is nothing in this space but it takes up room + "func_space": Blank( + width: 0.2, + height: 0.0, + ), + // This backspace button is composed of 3 individual LED + "backspace1": Led( + width: 0.65, + height: 1.0, + pad_left: 0.1, + pad_right: 0.0, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "backspace2": Led( + width: 0.7, + height: 1.0, + pad_left: 0.0, + pad_right: 0.0, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "backspace3": Led( + width: 0.65, + height: 1.0, + pad_left: 0.0, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + }, + key_rows: [ + ( + // Padding generally isn't required but is available just in case + pad_left: 0.1, + pad_top: 0.1, + // Each row is a horizontal row of keys of the keyboard + row: [ + // Declare a tuple of `Key`, and the String name to use from the hashmap above + (Spacing, "rog_spacer"), + (VolDown, "rog_row"), + (VolUp, "rog_row"), + (MicMute, "rog_row"), + (Rog, "rog_row"), + ], + ), + ( + pad_left: 0.1, + pad_top: 0.1, + row: [ + (Esc, "func_key"), + // There are two non-led types, `Blocking` which is intended to block something like a row-laser + (Blocking, "esc_func_spacing"), + (F1, "func_key"), + (F2, "func_key"), + (F3, "func_key"), + (F4, "func_key"), + // and `Spacing` which is intended to act like a non-visible LED + (Spacing, "func_space"), + (F5, "func_key"), + (F6, "func_key"), + (F7, "func_key"), + (F8, "func_key"), + (Spacing, "func_space"), + (F9, "func_key"), + (F10, "func_key"), + (F11, "func_key"), + (F12, "func_key"), + (Spacing, "func_space"), + (Del, "func_key"), + ], + ), + ( + pad_left: 0.1, + pad_top: 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"), + (Backspace3_1, "backspace1"), + (Backspace3_2, "backspace2"), + (Backspace3_3, "backspace3"), + (Spacing, "func_space"), + (Home, "regular"), + ], + ), + ] +) +``` + +**There are two types of layouts to be considered when building one; per-key, and zoned.** + +A zoned keyboard layout includes single zoned + no zones (but not per-key). The layout for this is fairly freeform, and can be built using regular keys from `LedCode` but can not include these per-key specific codes: + +- `LidLogo` +- `LidLeft` +- `LidRight` + +it can include regular keys and: + +- `SingleZone`, if this is used then the `ZonedKb*` should not be used +- `ZonedKbLeft` +- `ZonedKbLeftMid` +- `ZonedKbRightMid` +- `ZonedKbRight` +- `LightbarRight` +- `LightbarRightCorner` +- `LightbarRightBottom` +- `LightbarLeftBottom` +- `LightbarLeftCorner` +- `LightbarLeft` + +#### `Key` + +Every `Key` in the enum maps to a USB packet + RGB index in that packet. The raw mapping is seen in `per_key_raw_bytes.ods` in the data dir, for example there is a single LED backspace, and a 3-LED backspace. + +#### `key_shapes` + +This is a hashmap of `String`:`ShapeType`, as shown by the previous example such as: + +``` + // This is a regular LED spot, it has a size (width x height), and padding around each edge. + // The final size should be (width + pad_left + pad_right, height + pad_top + pad_bottom) + "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" being the key used by the keys in each key row. + +# Testing + +When working with Rog Control Center you can test layouts by starting the app on CLI with options: + +``` + -h, --help print help message + -v, --version show program version number + -b, --board-name set board name for testing, this will make ROGCC show only the keyboard page + -l, --layout-viewing put ROGCC in layout viewing mode - this is helpful for finding existing layouts that might match your laptop +``` \ No newline at end of file diff --git a/rog-aura/data/aura_support.ron b/rog-aura/data/aura_support.ron new file mode 100644 index 00000000..507ecf61 --- /dev/null +++ b/rog-aura/data/aura_support.ron @@ -0,0 +1,450 @@ +([ + ( + board_name: "FA506I", + layout_name: "fa506i", + basic_modes: [Static, Breathe, Strobe, Pulse], + basic_zones: [], + advanced_type: None, + ), + ( + board_name: "FA506Q", + layout_name: "fa506i", + basic_modes: [Static, Breathe, Strobe, Rainbow], + basic_zones: [], + advanced_type: None, + ), + ( + board_name: "FA507", + layout_name: "fa507", + basic_modes: [Static, Breathe, Strobe, Pulse], + basic_zones: [], + advanced_type: None, + ), + ( + board_name: "FX505D", + layout_name: "fx505d", + basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse], + basic_zones: [], + advanced_type: None, + ), + ( + board_name: "FX506HC", + layout_name: "fa506i", + basic_modes: [Static, Breathe, Strobe, Pulse], + basic_zones: [], + advanced_type: None, + ), + ( + board_name: "G512", + layout_name: "g512", + basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse], + 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", + basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse], + basic_zones: [Key1, Key2, Key3, Key4], + 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", + 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, + ), + ( + board_name: "G513QE", + layout_name: "g513i", + basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse], + basic_zones: [Key1, Key2, Key3, Key4], + advanced_type: None, + ), + ( + board_name: "G513QM", + layout_name: "g513i", + basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash], + basic_zones: [], + advanced_type: PerKey, + ), + ( + board_name: "G513QR", + 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: "G513QY", + layout_name: "g513i", + basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse], + basic_zones: [Key1, Key2, Key3, Key4], + advanced_type: None, + ), + ( + board_name: "G513RC", + 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: "G513RM", + 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: "G531", + 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: "G531", + layout_name: "g513i-per-key", + basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash], + basic_zones: [Key1, Key2, Key3, Key4], + advanced_type: PerKey, + ), + ( + board_name: "G531GD", + layout_name: "gx502", + basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse], + basic_zones: [], + advanced_type: None, + ), + ( + board_name: "G531GT", + layout_name: "gx502", + basic_modes: [Static, Breathe, Strobe, Rainbow], + basic_zones: [], + advanced_type: None, + ), + ( + board_name: "G531GU", + layout_name: "gx502", + basic_modes: [Static, Breathe, Strobe, Rainbow], + basic_zones: [Key1, Key2, Key3, Key4], + advanced_type: None, + ), + ( + board_name: "G531GV", + layout_name: "gx502", + basic_modes: [Static, Breathe, Strobe, Rainbow], + basic_zones: [Key1, Key2, Key3, Key4], + advanced_type: None, + ), + ( + board_name: "G531GW", + layout_name: "gx502", + basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash], + basic_zones: [Key1, Key2, Key3, Key4], + advanced_type: None, + ), + ( + board_name: "G532", + layout_name: "gx502", + basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash], + basic_zones: [], + advanced_type: PerKey, + ), + ( + board_name: "G533Q", + 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: "G712LI", + layout_name: "gl503", + basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse], + basic_zones: [], + advanced_type: None, + ), + ( + board_name: "G712LV", + layout_name: "ga401q", + basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse], + basic_zones: [Key1, Key2, Key3, Key4], + advanced_type: None, + ), + ( + board_name: "G712LW", + layout_name: "ga401q", + basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse], + basic_zones: [Key1, Key2, Key3, Key4], + advanced_type: None, + ), + ( + board_name: "G713IC", + layout_name: "gx502", + basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash], + basic_zones: [], + advanced_type: PerKey, + ), + ( + board_name: "G713QM", + layout_name: "ga401q", + basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse], + basic_zones: [Key1, Key2, Key3, Key4], + advanced_type: None, + ), + ( + board_name: "G713QR", + layout_name: "gx502", + basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash], + basic_zones: [], + advanced_type: PerKey, + ), + ( + board_name: "G713RM", + layout_name: "ga401q", + basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse], + basic_zones: [Key1, Key2, Key3, Key4], + advanced_type: None, + ), + ( + board_name: "G713RS", + layout_name: "gx502", + basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash], + basic_zones: [], + advanced_type: PerKey, + ), + ( + board_name: "G713RW", + layout_name: "ga401q", + basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse], + basic_zones: [Key1, Key2, Key3, Key4], + advanced_type: None, + ), + ( + board_name: "G731", + layout_name: "g533q", + basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash], + basic_zones: [Key1, Key2, Key3, Key4], + advanced_type: PerKey, + ), + ( + board_name: "G731GT", + layout_name: "g533q", + basic_modes: [Static, Breathe, Strobe, Rainbow], + basic_zones: [], + advanced_type: None, + ), + ( + board_name: "G731GU", + layout_name: "g533q", + basic_modes: [Static, Breathe, Strobe, Rainbow], + basic_zones: [], + advanced_type: None, + ), + ( + board_name: "G731GV", + layout_name: "g533q", + basic_modes: [Static, Breathe, Strobe, Rainbow], + basic_zones: [Key1, Key2, Key3, Key4], + advanced_type: None, + ), + ( + board_name: "G731GW", + layout_name: "g533q", + basic_modes: [Static, Breathe, Strobe, Rainbow], + basic_zones: [Key1, Key2, Key3, Key4], + advanced_type: None, + ), + ( + board_name: "G733Q", + layout_name: "gx502", + basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash], + basic_zones: [], + advanced_type: PerKey, + ), + ( + board_name: "GA402R", + layout_name: "ga401q", + basic_modes: [Static, Breathe, Pulse, Rainbow], + basic_zones: [], + advanced_type: None, + ), + ( + board_name: "GA503Q", + layout_name: "ga401q", + basic_modes: [Static, Breathe, Pulse, Rainbow, Strobe], + basic_zones: [], + advanced_type: None, + ), + ( + board_name: "GA503QE", + layout_name: "ga401q", + basic_modes: [Static, Breathe, Pulse], + basic_zones: [], + advanced_type: None, + ), + ( + board_name: "GA503R", + layout_name: "ga401q", + basic_modes: [Static, Breathe, Pulse, Rainbow, Strobe], + basic_zones: [], + advanced_type: None, + ), + ( + board_name: "GL504G", + layout_name: "gl503", + basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse], + basic_zones: [Key1, Key2, Key3, Key4, Logo, BarLeft, BarRight], + advanced_type: None, + ), + ( + board_name: "GL531", + layout_name: "g512", + basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash], + basic_zones: [], + advanced_type: PerKey, + ), + ( + board_name: "GL553VE", + layout_name: "g533q", + basic_modes: [Static, Breathe, Strobe], + basic_zones: [Key1, Key2, Key3, Key4], + advanced_type: None, + ), + ( + board_name: "GM501G", + layout_name: "fa507", + basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse], + basic_zones: [Key1, Key2, Key3, Key4], + advanced_type: None, + ), + ( + board_name: "GU502", + layout_name: "gx502", + basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash], + basic_zones: [], + advanced_type: PerKey, + ), + ( + board_name: "GU502G", + layout_name: "gx502", + basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash], + basic_zones: [], + advanced_type: PerKey, + ), + ( + board_name: "GU502L", + layout_name: "gx502", + basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash], + basic_zones: [], + advanced_type: PerKey, + ), + ( + board_name: "GU502LU", + layout_name: "gx502", + basic_modes: [Static, Breathe, Strobe, Pulse], + basic_zones: [], + advanced_type: None, + ), + ( + board_name: "GU603H", + layout_name: "ga401q", + basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse], + basic_zones: [], + advanced_type: Zoned([SingleZone]), + ), + ( + board_name: "GU603Z", + layout_name: "ga401q", + basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse], + basic_zones: [], + advanced_type: Zoned([SingleZone]), + ), + ( + board_name: "GV301Q", + layout_name: "ga401q", + basic_modes: [Static, Breathe, Pulse], + basic_zones: [], + advanced_type: None, + ), + ( + board_name: "GV601R", + layout_name: "ga401q", + basic_modes: [Static, Breathe, Strobe, Pulse], + basic_zones: [], + advanced_type: None, + ), + ( + board_name: "GX502", + layout_name: "gx502", + basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash], + basic_zones: [], + advanced_type: PerKey, + ), + ( + board_name: "GX531", + layout_name: "gx531-per-key", + basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse], + basic_zones: [Key1, Key2, Key3, Key4], + advanced_type: None, + ), + ( + board_name: "GX550L", + 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: "GX551Q", + layout_name: "gx531-per-key", + basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse], + basic_zones: [], + advanced_type: PerKey, + ), + ( + board_name: "GX701", + 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: "GX703H", + layout_name: "gx531-per-key", + basic_modes: [Static, Breathe, Strobe, Rainbow, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash], + basic_zones: [], + advanced_type: None, + ), + ( + board_name: "ga401qQ", + layout_name: "ga401q", + basic_modes: [Static, Breathe, Pulse], + basic_zones: [], + advanced_type: None, + ), +]) \ No newline at end of file diff --git a/rog-aura/data/layouts/fa506i_US.ron b/rog-aura/data/layouts/fa506i_US.ron new file mode 100644 index 00000000..b9163632 --- /dev/null +++ b/rog-aura/data/layouts/fa506i_US.ron @@ -0,0 +1,317 @@ +( + locale: "US", + key_shapes: { + "regular": Led( + width: 1.0, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "regular2": Led( + width: 1.0, + height: 1.3, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "func_key": Led( + width: 1.0, + height: 0.7, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.0, + pad_bottom: 0.1, + ), + "func_space": Blank( + width: 0.5, + height: 0.0, + ), + "esc_func_spacing": Blank( + width: 1.2, + height: 0.0, + ), + "backspace": Led( + width: 2.0, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "bkslash": Led( + width: 1.4, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "tab": Led( + width: 1.6, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "capsplonk": Led( + width: 1.9, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "return": Led( + width: 2.3, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "lshift": Led( + width: 2.5, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "rshift": Led( + width: 2.9, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "lctrl": Led( + width: 1.4, + height: 1.3, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "spacebar": Led( + width: 5.7, + height: 1.3, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "rctrl": Led( + width: 1.2, + height: 1.3, + 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.9, + pad_right: 1.4, + pad_top: 0.1, + pad_bottom: 0.0, + ), + "arrows_spacer": Blank( + width: 14.5, + height: 0.0, + ), + "arrows": Led( + width: 0.8, + height: 0.8, + pad_left: 0.1, + pad_right: 0.1, + pad_top: -0.4, + pad_bottom: 0.1, + ), + "numpad_tall": Led( + width: 1.0, + height: 2.2, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: -1.2, + ), + "numpad_wide": Led( + width: 2.2, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + }, + key_rows: [ + ( + pad_left: 0.1, + pad_top: 0.1, + row: [ + (Esc, "func_key"), + (Spacing, "esc_func_spacing"), + (F1, "func_key"), + (F2, "func_key"), + (F3, "func_key"), + (F4, "func_key"), + (Spacing, "func_space"), + (F5, "func_key"), + (F6, "func_key"), + (F7, "func_key"), + (F8, "func_key"), + (Spacing, "func_space"), + (F9, "func_key"), + (F10, "func_key"), + (F11, "func_key"), + (F12, "func_key"), + (Spacing, "func_space"), + (Del, "func_key"), + (NumPadPause, "func_key"), + (NumPadPrtSc, "func_key"), + (NumPadHome, "func_key"), + ], + ), + ( + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + row: [ + (Tilde, "regular"), + (N1, "regular"), + (N2, "regular"), + (N3, "regular"), + (N4, "regular"), + (N5, "regular"), + (N6, "regular"), + (N7, "regular"), + (N8, "regular"), + (N9, "regular"), + (N0, "regular"), + (Hyphen, "regular"), + (Equals, "regular"), + (Backspace, "backspace"), + (Spacing, "func_space"), + (NumLock, "regular"), + (FwdSlash, "regular"), + (Star, "regular"), + (Hyphen, "regular"), + ], + ), + ( + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + row: [ + (Tab, "tab"), + (Q, "regular"), + (W, "regular"), + (E, "regular"), + (R, "regular"), + (T, "regular"), + (Y, "regular"), + (U, "regular"), + (I, "regular"), + (O, "regular"), + (P, "regular"), + (LBracket, "regular"), + (RBracket, "regular"), + (BackSlash, "bkslash"), + (Spacing, "func_space"), + (N7, "regular"), + (N8, "regular"), + (N9, "regular"), + (NumPadPlus, "numpad_tall"), + ], + ), + ( + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + row: [ + (Caps, "capsplonk"), + (A, "regular"), + (S, "regular"), + (D, "regular"), + (F, "regular"), + (G, "regular"), + (H, "regular"), + (J, "regular"), + (K, "regular"), + (L, "regular"), + (SemiColon, "regular"), + (Quote, "regular"), + (Return, "return"), + (Spacing, "func_space"), + (N4, "regular"), + (N5, "regular"), + (N6, "regular"), + ], + ), + ( + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + row: [ + (LShift, "lshift"), + (Z, "regular"), + (X, "regular"), + (C, "regular"), + (V, "regular"), + (B, "regular"), + (N, "regular"), + (M, "regular"), + (Comma, "regular"), + (Period, "regular"), + (FwdSlash, "regular"), + (Rshift, "rshift"), + (Spacing, "func_space"), + (N1, "regular"), + (N2, "regular"), + (N3, "regular"), + (NumPadEnter, "numpad_tall"), + ], + ), + ( + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + row: [ + (LCtrl, "lctrl"), + (LFn, "regular2"), + (Meta, "regular2"), + (LAlt, "regular2"), + (Spacebar, "spacebar"), + (RAlt, "regular2"), + (RCtrl, "rctrl"), + (Up, "up_arrow"), + (Spacing, "func_space"), + (N0, "numpad_wide"), + (NumPadDel, "regular"), + ], + ), + ( + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + row: [ + (Spacing, "arrows_spacer"), + (Left, "arrows"), + (Down, "arrows"), + (Right, "arrows"), + ], + ), + ], +) \ No newline at end of file diff --git a/rog-aura/data/layouts/fa507_US.ron b/rog-aura/data/layouts/fa507_US.ron new file mode 100644 index 00000000..61d3aad1 --- /dev/null +++ b/rog-aura/data/layouts/fa507_US.ron @@ -0,0 +1,334 @@ +( + locale: "US", + key_shapes: { + "rog_spacer": Blank( + width: 2.5, + height: 0.0, + ), + "rog_row": Led( + width: 1.0, + height: 0.8, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.2, + pad_bottom: 0.5, + ), + "regular": Led( + width: 1.0, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "regular2": Led( + width: 1.0, + height: 1.3, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "func_key": Led( + width: 1.0, + height: 0.7, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.0, + pad_bottom: 0.1, + ), + "func_space": Blank( + width: 0.5, + height: 0.0, + ), + "esc_func_spacing": Blank( + width: 1.2, + height: 0.0, + ), + "backspace": Led( + width: 2.0, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "bkslash": Led( + width: 1.4, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "tab": Led( + width: 1.6, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "capsplonk": Led( + width: 1.9, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "return": Led( + width: 2.3, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "lshift": Led( + width: 2.5, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "rshift": Led( + width: 2.9, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "lctrl": Led( + width: 1.4, + height: 1.3, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "spacebar": Led( + width: 5.7, + height: 1.3, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "rctrl": Led( + width: 1.2, + height: 1.3, + 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.9, + pad_right: 1.4, + pad_top: 0.1, + pad_bottom: 0.0, + ), + "arrows_spacer": Blank( + width: 14.5, + height: 0.0, + ), + "arrows": Led( + width: 0.8, + height: 0.8, + pad_left: 0.1, + pad_right: 0.1, + pad_top: -0.4, + pad_bottom: 0.1, + ), + "numpad_tall": Led( + width: 1.0, + height: 2.2, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: -1.2, + ), + "numpad_wide": Led( + width: 2.2, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + }, + key_rows: [ + ( + pad_left: 0.1, + pad_top: 0.1, + row: [ + (Spacing, "rog_spacer"), + (VolDown, "rog_row"), + (VolUp, "rog_row"), + (MicMute, "rog_row"), + (RogApp, "rog_row"), + ], + ), + ( + pad_left: 0.1, + pad_top: 0.1, + row: [ + (Esc, "func_key"), + (Spacing, "esc_func_spacing"), + (F1, "func_key"), + (F2, "func_key"), + (F3, "func_key"), + (F4, "func_key"), + (Spacing, "func_space"), + (F5, "func_key"), + (F6, "func_key"), + (F7, "func_key"), + (F8, "func_key"), + (Spacing, "func_space"), + (F9, "func_key"), + (F10, "func_key"), + (F11, "func_key"), + (F12, "func_key"), + (Del, "func_key"), + (NumPadPause, "func_key"), + (NumPadPrtSc, "func_key"), + (NumPadHome, "func_key"), + ], + ), + ( + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + row: [ + (Tilde, "regular"), + (N1, "regular"), + (N2, "regular"), + (N3, "regular"), + (N4, "regular"), + (N5, "regular"), + (N6, "regular"), + (N7, "regular"), + (N8, "regular"), + (N9, "regular"), + (N0, "regular"), + (Hyphen, "regular"), + (Equals, "regular"), + (Backspace, "backspace"), + (NumLock, "regular"), + (FwdSlash, "regular"), + (Star, "regular"), + (Hyphen, "regular"), + ], + ), + ( + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + row: [ + (Tab, "tab"), + (Q, "regular"), + (W, "regular"), + (E, "regular"), + (R, "regular"), + (T, "regular"), + (Y, "regular"), + (U, "regular"), + (I, "regular"), + (O, "regular"), + (P, "regular"), + (LBracket, "regular"), + (RBracket, "regular"), + (BackSlash, "bkslash"), + (N7, "regular"), + (N8, "regular"), + (N9, "regular"), + (NumPadPlus, "numpad_tall"), + ], + ), + ( + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + row: [ + (Caps, "capsplonk"), + (A, "regular"), + (S, "regular"), + (D, "regular"), + (F, "regular"), + (G, "regular"), + (H, "regular"), + (J, "regular"), + (K, "regular"), + (L, "regular"), + (SemiColon, "regular"), + (Quote, "regular"), + (Return, "return"), + (N4, "regular"), + (N5, "regular"), + (N6, "regular"), + ], + ), + ( + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + row: [ + (LShift, "lshift"), + (Z, "regular"), + (X, "regular"), + (C, "regular"), + (V, "regular"), + (B, "regular"), + (N, "regular"), + (M, "regular"), + (Comma, "regular"), + (Period, "regular"), + (FwdSlash, "regular"), + (Rshift, "rshift"), + (N1, "regular"), + (N2, "regular"), + (N3, "regular"), + (NumPadEnter, "numpad_tall"), + ], + ), + ( + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + row: [ + (LCtrl, "lctrl"), + (LFn, "regular2"), + (Meta, "regular2"), + (LAlt, "regular2"), + (Spacebar, "spacebar"), + (RAlt, "regular2"), + (RCtrl, "rctrl"), + (Up, "up_arrow"), + (N0, "numpad_wide"), + (NumPadDel, "regular"), + ], + ), + ( + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + row: [ + (Spacing, "arrows_spacer"), + (Left, "arrows"), + (Down, "arrows"), + (Right, "arrows"), + ], + ), + ], +) \ No newline at end of file diff --git a/rog-aura/data/layouts/fx505d_US.ron b/rog-aura/data/layouts/fx505d_US.ron new file mode 100644 index 00000000..e2d7881e --- /dev/null +++ b/rog-aura/data/layouts/fx505d_US.ron @@ -0,0 +1,281 @@ +( + locale: "US", + key_shapes: { + "regular": Led( + width: 1.0, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "regular2": Led( + width: 1.0, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: -0.2, + pad_bottom: 0.1, + ), + "func_key": Led( + width: 1.0, + height: 0.7, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.0, + pad_bottom: 0.1, + ), + "func_space": Blank( + width: 0.5, + height: 0.0, + ), + "esc_func_spacing": Blank( + width: 1.2, + height: 0.0, + ), + "backspace": Led( + width: 2.0, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "bkslash": Led( + width: 1.4, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "tab": Led( + width: 1.6, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "capsplonk": Led( + width: 1.9, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "return": Led( + width: 2.3, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "lshift": Led( + width: 2.5, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "lctrl": Led( + width: 1.4, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "spacebar": Led( + width: 5.7, + height: 1.3, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "arrows_spacer": Blank( + width: 16.6, + height: 0.0, + ), + "numpad_tall": Led( + width: 1.0, + height: 2.2, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: -1.2, + ), + "right_wide": Led( + width: 2.9, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + }, + key_rows: [ + ( + pad_left: 0.1, + pad_top: 0.1, + row: [ + (Esc, "func_key"), + (Spacing, "esc_func_spacing"), + (F1, "func_key"), + (F2, "func_key"), + (F3, "func_key"), + (F4, "func_key"), + (Spacing, "func_space"), + (F5, "func_key"), + (F6, "func_key"), + (F7, "func_key"), + (F8, "func_key"), + (Spacing, "func_space"), + (F9, "func_key"), + (F10, "func_key"), + (F11, "func_key"), + (F12, "func_key"), + (Del, "func_key"), + (NumPadPause, "func_key"), + (NumPadPrtSc, "func_key"), + (NumPadHome, "func_key"), + ], + ), + ( + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + row: [ + (Tilde, "regular"), + (N1, "regular"), + (N2, "regular"), + (N3, "regular"), + (N4, "regular"), + (N5, "regular"), + (N6, "regular"), + (N7, "regular"), + (N8, "regular"), + (N9, "regular"), + (N0, "regular"), + (Hyphen, "regular"), + (Equals, "regular"), + (Backspace, "backspace"), + (NumLock, "regular"), + (FwdSlash, "regular"), + (Star, "regular"), + (Hyphen, "regular"), + ], + ), + ( + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + row: [ + (Tab, "tab"), + (Q, "regular"), + (W, "regular"), + (E, "regular"), + (R, "regular"), + (T, "regular"), + (Y, "regular"), + (U, "regular"), + (I, "regular"), + (O, "regular"), + (P, "regular"), + (LBracket, "regular"), + (RBracket, "regular"), + (BackSlash, "bkslash"), + (N7, "regular"), + (N8, "regular"), + (N9, "regular"), + (NumPadPlus, "numpad_tall"), + ], + ), + ( + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + row: [ + (Caps, "capsplonk"), + (A, "regular"), + (S, "regular"), + (D, "regular"), + (F, "regular"), + (G, "regular"), + (H, "regular"), + (J, "regular"), + (K, "regular"), + (L, "regular"), + (SemiColon, "regular"), + (Quote, "regular"), + (Return, "return"), + (N4, "regular"), + (N5, "regular"), + (N6, "regular"), + ], + ), + ( + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + row: [ + (LShift, "lshift"), + (Z, "regular"), + (X, "regular"), + (C, "regular"), + (V, "regular"), + (B, "regular"), + (N, "regular"), + (M, "regular"), + (Comma, "regular"), + (Period, "regular"), + (FwdSlash, "regular"), + (Rshift, "right_wide"), + (N1, "regular"), + (N2, "regular"), + (N3, "regular"), + (NumPadEnter, "numpad_tall"), + ], + ), + ( + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + row: [ + (LCtrl, "lctrl"), + (LFn, "regular"), + (Meta, "regular"), + (LAlt, "regular"), + (Spacebar, "spacebar"), + (RAlt, "regular"), + (RAlt, "regular"), + (RAlt, "regular"), + (RCtrl, "right_wide"), + (Up, "regular"), + (N0, "regular"), + (NumPadDel, "regular"), + ], + ), + ( + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + row: [ + (Spacing, "arrows_spacer"), + (Left, "regular2"), + (Down, "regular2"), + (Right, "regular2"), + ], + ), + ], +) \ No newline at end of file diff --git a/rog-aura/data/layouts/g512_US.ron b/rog-aura/data/layouts/g512_US.ron new file mode 100644 index 00000000..8965a105 --- /dev/null +++ b/rog-aura/data/layouts/g512_US.ron @@ -0,0 +1,312 @@ +( + 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, + ), + }, + 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"), + ], + ), + ( + 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"), + (Home, "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"), + (PgUp, "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"), + (PgDn, "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"), + (End, "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"), + ], + ), + ], +) \ No newline at end of file diff --git a/rog-aura/data/layouts/g513_US.toml b/rog-aura/data/layouts/g513_US.toml deleted file mode 100644 index dbefeae8..00000000 --- a/rog-aura/data/layouts/g513_US.toml +++ /dev/null @@ -1,161 +0,0 @@ -matches = [ - 'G513', -] - -locale = "US" - -[[rows]] -height = 0.8 -row = [ - 'NormalSpacer', - 'FuncSpacer', - 'VolDown', - 'VolUp', - 'MicMute', - 'Fan', - 'Rog', -] - -[[rows]] -height = 0.8 -row = [ - 'Esc', - 'FuncSpacer', - 'F1', - 'F2', - 'F3', - 'F4', - 'FuncSpacer', - 'F5', - 'F6', - 'F7', - 'F8', - 'FuncSpacer', - 'F9', - 'F10', - 'F11', - 'F12', - 'RowEndSpacer', - 'NumPadDel', -] - -[[rows]] -height = 1.0 -row = [ - 'Tilde', - 'N1', - 'N2', - 'N3', - 'N4', - 'N5', - 'N6', - 'N7', - 'N8', - 'N9', - 'N0', - 'Hyphen', - 'Equals', - 'BkSpc', - 'RowEndSpacer', - 'Home', -] - -[[rows]] -height = 1.0 -row = [ - 'Tab', - 'Q', - 'W', - 'E', - 'R', - 'T', - 'Y', - 'U', - 'I', - 'O', - 'P', - 'LBracket', - 'RBracket', - 'BackSlash', - 'RowEndSpacer', - 'PgUp', -] - -[[rows]] -height = 1.0 -row = [ - 'Caps', - 'A', - 'S', - 'D', - 'F', - 'G', - 'H', - 'J', - 'K', - 'L', - 'SemiColon', - 'Quote', - 'Return', - 'RowEndSpacer', - 'PgDn', -] - -[[rows]] -height = 1.0 -row = [ - 'LShift', - 'Z', - 'X', - 'C', - 'V', - 'B', - 'N', - 'M', - 'Comma', - 'Period', - 'FwdSlash', - 'Rshift', - 'RowEndSpacer', - 'End', -] - -[[rows]] -height = 1.2 -row = [ - 'LCtrl', - 'LFn', - 'Meta', - 'LAlt', - 'Space', - 'RAlt', - 'PrtSc', - 'RCtrl', - 'ArrowSpacer', - 'Up', - 'ArrowSpacer', - 'RowEndSpacer', - 'RFn', -] - -[[rows]] -height = 0.8 -row = [ - 'ArrowSpacer', - 'ArrowSpacer', - 'ArrowSpacer', - 'ArrowSpacer', - 'ArrowSpacer', - 'ArrowSpacer', - 'ArrowSpacer', - 'ArrowSpacer', - 'ArrowSpacer', - 'ArrowSpacer', - 'ArrowSpacer', - 'ArrowSpacer', - 'ArrowSpacer', - 'Left', - 'Down', - 'Right', - 'ArrowSpacer', -] diff --git a/rog-aura/data/layouts/g513i-per-key_US.ron b/rog-aura/data/layouts/g513i-per-key_US.ron new file mode 100644 index 00000000..4ea6b631 --- /dev/null +++ b/rog-aura/data/layouts/g513i-per-key_US.ron @@ -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"), + ], + ), + ], +) \ No newline at end of file diff --git a/rog-aura/data/layouts/g513i_US.ron b/rog-aura/data/layouts/g513i_US.ron new file mode 100644 index 00000000..4ea6b631 --- /dev/null +++ b/rog-aura/data/layouts/g513i_US.ron @@ -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"), + ], + ), + ], +) \ No newline at end of file diff --git a/rog-aura/data/layouts/g533_US.toml b/rog-aura/data/layouts/g533_US.toml deleted file mode 100644 index 2533fa28..00000000 --- a/rog-aura/data/layouts/g533_US.toml +++ /dev/null @@ -1,135 +0,0 @@ -matches = [ - 'G533', -] - -locale = "US" - -[[rows]] -height = 0.8 -row = [ - 'NormalSpacer', - 'FuncSpacer', - 'VolDown', - 'VolUp', - 'MicMute', - 'Fan', - 'Rog', -] - -[[rows]] -height = 0.8 -row = [ - 'Esc', - 'FuncSpacer', - 'F1', - 'F2', - 'F3', - 'F4', - 'FuncSpacer', - 'F5', - 'F6', - 'F7', - 'F8', - 'FuncSpacer', - 'F9', - 'F10', - 'F11', - 'F12', - 'Del', -] - -[[rows]] -height = 1.0 -row = [ - 'Tilde', - 'N1', - 'N2', - 'N3', - 'N4', - 'N5', - 'N6', - 'N7', - 'N8', - 'N9', - 'N0', - 'Hyphen', - 'Equals', - 'BkSpc', - 'MediaPlay', -] - -[[rows]] -height = 1.0 -row = [ - 'Tab', - 'Q', - 'W', - 'E', - 'R', - 'T', - 'Y', - 'U', - 'I', - 'O', - 'P', - 'LBracket', - 'RBracket', - 'BackSlash', - 'MediaStop', -] - -[[rows]] -height = 1.0 -row = [ - 'Caps', - 'A', - 'S', - 'D', - 'F', - 'G', - 'H', - 'J', - 'K', - 'L', - 'SemiColon', - 'Quote', - 'Return', - 'MediaPrev', -] - -[[rows]] -height = 1.0 -row = [ - 'LShift', - 'Z', - 'X', - 'C', - 'V', - 'B', - 'N', - 'M', - 'Comma', - 'Period', - 'FwdSlash', - 'RshiftSmall', - 'UpRegular', - 'MediaNext', -] - -[[rows]] -height = 1.0 -row = [ - 'LCtrlMed', - 'LFn', - 'Meta', - 'LAlt', - 'Space', - 'RAlt', - 'PrtSc', - 'RCtrl', - 'ArrowRegularSpacer', - 'LeftRegular', - 'DownRegular', - 'RightRegular', -] - diff --git a/rog-aura/data/layouts/g533q-per-key_US.ron b/rog-aura/data/layouts/g533q-per-key_US.ron new file mode 100644 index 00000000..5be64903 --- /dev/null +++ b/rog-aura/data/layouts/g533q-per-key_US.ron @@ -0,0 +1,293 @@ +( + 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: 1.8, + 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.0, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "up_arrow": Led( + width: 1.0, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "arrows": Led( + width: 1.0, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "arrow_space": Blank( + width: 0.8, + height: 0.0, + ), + }, + 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"), + (Del, "regular"), + ], + ), + ( + 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"), + (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"), + (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"), + (MediaPrev, "regular"), + ], + ), + ( + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + row: [ + (LShift, "lshift"), + (Z, "regular"), + (X, "regular"), + (C, "regular"), + (V, "regular"), + (B, "regular"), + (N, "regular"), + (M, "regular"), + (Comma, "regular"), + (Period, "regular"), + (FwdSlash, "regular"), + (Rshift, "rshift"), + (Up, "up_arrow"), + (MediaNext, "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"), + (Spacing, "arrow_space"), + (Left, "arrows"), + (Down, "arrows"), + (Right, "arrows"), + ], + ), + ], +) \ No newline at end of file diff --git a/rog-aura/data/layouts/g533q_US.ron b/rog-aura/data/layouts/g533q_US.ron new file mode 100644 index 00000000..b64f9740 --- /dev/null +++ b/rog-aura/data/layouts/g533q_US.ron @@ -0,0 +1,294 @@ +( + 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_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: 1.0, + height: 1.0, + pad_left: 1.0, + pad_right: 1.0, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "arrows_spacer": Blank( + width: 14.7, + height: 0.0, + ), + "arrows": Led( + width: 1.0, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + 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, "regular"), + (VolUp, "regular"), + (MicMute, "regular"), + (RogFan, "regular"), + (RogApp, "regular"), + ], + ), + ( + 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"), + (Del, "regular"), + ], + ), + ( + 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"), + (Home, "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"), + (PgUp, "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"), + (PgDn, "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"), + (End, "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"), + (RFn, "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"), + ], + ), + ], +) diff --git a/rog-aura/data/layouts/ga401_US.toml b/rog-aura/data/layouts/ga401_US.toml deleted file mode 100644 index 2bcb2f2a..00000000 --- a/rog-aura/data/layouts/ga401_US.toml +++ /dev/null @@ -1,154 +0,0 @@ -matches = [ - 'GA401', - 'GA402', - 'GU603', - 'GV301', - 'GA502', - 'GA503', -] - -locale = "US" - -[[rows]] -height = 0.8 -row = [ - 'NormalSpacer', - 'FuncSpacer', - 'VolDown', - 'VolUp', - 'MicMute', - 'Rog', -] - -[[rows]] -height = 0.8 -row = [ - 'Esc', - 'FuncSpacer', - 'F1', - 'F2', - 'F3', - 'F4', - 'FuncSpacer', - 'F5', - 'F6', - 'F7', - 'F8', - 'FuncSpacer', - 'F9', - 'F10', - 'F11', - 'F12', -] - -[[rows]] -height = 1.0 -row = [ - 'Tilde', - 'N1', - 'N2', - 'N3', - 'N4', - 'N5', - 'N6', - 'N7', - 'N8', - 'N9', - 'N0', - 'Hyphen', - 'Equals', - 'BkSpc', -] - -[[rows]] -height = 1.0 -row = [ - 'Tab', - 'Q', - 'W', - 'E', - 'R', - 'T', - 'Y', - 'U', - 'I', - 'O', - 'P', - 'LBracket', - 'RBracket', - 'BackSlash', -] - -[[rows]] -height = 1.0 -row = [ - 'Caps', - 'A', - 'S', - 'D', - 'F', - 'G', - 'H', - 'J', - 'K', - 'L', - 'SemiColon', - 'Quote', - 'Return', -] - -[[rows]] -height = 1.0 -row = [ - 'LShift', - 'Z', - 'X', - 'C', - 'V', - 'B', - 'N', - 'M', - 'Comma', - 'Period', - 'FwdSlash', - 'Rshift', -] - -[[rows]] -height = 1.2 -row = [ - 'LCtrl', - 'LFn', - 'Meta', - 'LAlt', - 'Space', - 'RAlt', - 'PrtSc', - 'RCtrl', - 'ArrowSpacer', - 'Up', - 'ArrowSpacer', -] - -[[rows]] -height = 0.8 -row = [ - 'FuncSpacer', - 'FuncSpacer', - 'NormalSpacer', - 'NormalSpacer', - 'NormalSpacer', - 'NormalSpacer', - 'NormalSpacer', - 'NormalSpacer', - 'NormalSpacer', - 'NormalSpacer', - 'NormalSpacer', - 'NormalSpacer', - 'NormalSpacer', - 'Left', - 'Down', - 'Right', - 'ArrowSpacer', -] - diff --git a/rog-aura/data/layouts/ga401q_US.ron b/rog-aura/data/layouts/ga401q_US.ron new file mode 100644 index 00000000..b67dc4ab --- /dev/null +++ b/rog-aura/data/layouts/ga401q_US.ron @@ -0,0 +1,299 @@ +( + locale: "US", + key_shapes: { + "regular": Led( + width: 1.0, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "regular2": Led( + width: 1.0, + height: 1.3, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "rog_spacer": Blank( + width: 2.5, + height: 0.0, + ), + "rog_row": Led( + width: 1.0, + height: 0.8, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.2, + pad_bottom: 0.5, + ), + "func_key": Led( + width: 1.0, + height: 0.8, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.0, + pad_bottom: 0.1, + ), + "func_space": Blank( + width: 0.2, + height: 0.0, + ), + "esc_func_spacing": 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, + ), + "bkslash": 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, + ), + "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.3, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "spacebar": Led( + width: 5.8, + height: 1.3, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "rctrl": Led( + width: 1.2, + height: 1.3, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "up_arrow": Led( + width: 1.0, + height: 0.6, + pad_left: 1.6, + pad_right: 1.6, + pad_top: 0.1, + pad_bottom: 0.0, + ), + "arrows_spacer": Blank( + width: 14.1, + height: 0.0, + ), + "arrows": Led( + width: 1.0, + height: 0.6, + pad_left: 0.1, + pad_right: 0.1, + pad_top: -0.7, + pad_bottom: 0.1, + ), + }, + key_rows: [ + ( + pad_left: 0.1, + pad_top: 0.1, + row: [ + (Spacing, "rog_spacer"), + (VolDown, "rog_row"), + (VolUp, "rog_row"), + (MicMute, "rog_row"), + (RogApp, "rog_row"), + ], + ), + ( + pad_left: 0.1, + pad_top: 0.1, + row: [ + (Esc, "func_key"), + (Spacing, "esc_func_spacing"), + (F1, "func_key"), + (F2, "func_key"), + (F3, "func_key"), + (F4, "func_key"), + (Spacing, "func_space"), + (F5, "func_key"), + (F6, "func_key"), + (F7, "func_key"), + (F8, "func_key"), + (Spacing, "func_space"), + (F9, "func_key"), + (F10, "func_key"), + (F11, "func_key"), + (F12, "func_key"), + (Spacing, "func_space"), + (Del, "func_key"), + ], + ), + ( + 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"), + ], + ), + ( + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + row: [ + (Tab, "tab"), + (Q, "regular"), + (W, "regular"), + (E, "regular"), + (R, "regular"), + (T, "regular"), + (Y, "regular"), + (U, "regular"), + (I, "regular"), + (O, "regular"), + (P, "regular"), + (LBracket, "regular"), + (RBracket, "regular"), + (BackSlash, "bkslash"), + ], + ), + ( + 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"), + ], + ), + ( + 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"), + ], + ), + ( + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + row: [ + (LCtrl, "lctrl"), + (LFn, "regular2"), + (Meta, "regular2"), + (LAlt, "regular2"), + (Spacebar, "spacebar"), + (RAlt, "regular2"), + (RCtrl, "rctrl"), + (Up, "up_arrow"), + ], + ), + ( + 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"), + ], + ), + ], +) \ No newline at end of file diff --git a/rog-aura/data/layouts/gl503_US.ron b/rog-aura/data/layouts/gl503_US.ron new file mode 100644 index 00000000..8cf17e91 --- /dev/null +++ b/rog-aura/data/layouts/gl503_US.ron @@ -0,0 +1,305 @@ +( + locale: "US", + key_shapes: { + "rog_row_spacing": Blank( + width: 1.2, + height: 0.0, + ), + "rog_row": Led( + width: 1.0, + height: 0.8, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.2, + pad_bottom: 0.6, + ), + "regular": Led( + width: 1.0, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "regular2": Led( + width: 1.0, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: -0.2, + pad_bottom: 0.1, + ), + "func_key": Led( + width: 1.0, + height: 0.7, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.0, + pad_bottom: 0.1, + ), + "func_space": Blank( + width: 0.5, + height: 0.0, + ), + "esc_func_spacing": Blank( + width: 1.2, + height: 0.0, + ), + "backspace": Led( + width: 2.0, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "bkslash": Led( + width: 1.4, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "tab": Led( + width: 1.6, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "capsplonk": Led( + width: 1.9, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "return": Led( + width: 2.3, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "lshift": Led( + width: 2.5, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "lctrl": Led( + width: 1.4, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "spacebar": Led( + width: 5.7, + height: 1.3, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "arrows_spacer": Blank( + width: 16.6, + height: 0.0, + ), + "numpad_tall": Led( + width: 1.0, + height: 2.2, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: -1.2, + ), + "right_wide": Led( + width: 2.9, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + }, + key_rows: [ + ( + pad_left: 0.1, + pad_top: 0.1, + row: [ + (Blocking, "rog_row_spacing"), + (Blocking, "rog_row_spacing"), + (VolDown, "rog_row"), + (VolUp, "rog_row"), + (MicMute, "rog_row"), + (RogApp, "rog_row"), + ], + ), + ( + pad_left: 0.1, + pad_top: 0.1, + row: [ + (Esc, "func_key"), + (Spacing, "esc_func_spacing"), + (F1, "func_key"), + (F2, "func_key"), + (F3, "func_key"), + (F4, "func_key"), + (Spacing, "func_space"), + (F5, "func_key"), + (F6, "func_key"), + (F7, "func_key"), + (F8, "func_key"), + (Spacing, "func_space"), + (F9, "func_key"), + (F10, "func_key"), + (F11, "func_key"), + (F12, "func_key"), + (Del, "func_key"), + (NumPadPause, "func_key"), + (NumPadPrtSc, "func_key"), + (NumPadHome, "func_key"), + ], + ), + ( + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + row: [ + (Tilde, "regular"), + (N1, "regular"), + (N2, "regular"), + (N3, "regular"), + (N4, "regular"), + (N5, "regular"), + (N6, "regular"), + (N7, "regular"), + (N8, "regular"), + (N9, "regular"), + (N0, "regular"), + (Hyphen, "regular"), + (Equals, "regular"), + (Backspace, "backspace"), + (NumLock, "regular"), + (FwdSlash, "regular"), + (Star, "regular"), + (Hyphen, "regular"), + ], + ), + ( + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + row: [ + (Tab, "tab"), + (Q, "regular"), + (W, "regular"), + (E, "regular"), + (R, "regular"), + (T, "regular"), + (Y, "regular"), + (U, "regular"), + (I, "regular"), + (O, "regular"), + (P, "regular"), + (LBracket, "regular"), + (RBracket, "regular"), + (BackSlash, "bkslash"), + (N7, "regular"), + (N8, "regular"), + (N9, "regular"), + (NumPadPlus, "numpad_tall"), + ], + ), + ( + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + row: [ + (Caps, "capsplonk"), + (A, "regular"), + (S, "regular"), + (D, "regular"), + (F, "regular"), + (G, "regular"), + (H, "regular"), + (J, "regular"), + (K, "regular"), + (L, "regular"), + (SemiColon, "regular"), + (Quote, "regular"), + (Return, "return"), + (N4, "regular"), + (N5, "regular"), + (N6, "regular"), + ], + ), + ( + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + row: [ + (LShift, "lshift"), + (Z, "regular"), + (X, "regular"), + (C, "regular"), + (V, "regular"), + (B, "regular"), + (N, "regular"), + (M, "regular"), + (Comma, "regular"), + (Period, "regular"), + (FwdSlash, "regular"), + (Rshift, "right_wide"), + (N1, "regular"), + (N2, "regular"), + (N3, "regular"), + (NumPadEnter, "numpad_tall"), + ], + ), + ( + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + row: [ + (LCtrl, "lctrl"), + (LFn, "regular"), + (Meta, "regular"), + (LAlt, "regular"), + (Spacebar, "spacebar"), + (RAlt, "regular"), + (RAlt, "regular"), + (RAlt, "regular"), + (RCtrl, "right_wide"), + (Up, "regular"), + (N0, "regular"), + (NumPadDel, "regular"), + ], + ), + ( + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + row: [ + (Spacing, "arrows_spacer"), + (Left, "regular2"), + (Down, "regular2"), + (Right, "regular2"), + ], + ), + ], +) \ No newline at end of file diff --git a/rog-aura/data/layouts/gl504_US.toml b/rog-aura/data/layouts/gl504_US.toml deleted file mode 100644 index 0258c086..00000000 --- a/rog-aura/data/layouts/gl504_US.toml +++ /dev/null @@ -1,180 +0,0 @@ -matches = [ - 'GL504', -] - -locale = "US" - -[[rows]] -height = 0.8 -row = [ - 'NormalSpacer', - 'FuncSpacer', - 'VolDown', - 'VolUp', - 'MicMute', - 'Rog', -] - -[[rows]] -height = 0.8 -row = [ - 'Esc', - 'FuncSpacer', - 'F1', - 'F2', - 'F3', - 'F4', - 'FuncSpacer', - 'F5', - 'F6', - 'F7', - 'F8', - 'FuncSpacer', - 'F9', - 'F10', - 'F11', - 'F12', - 'RowEndSpacer', - 'Del', - 'NumPadPause', - 'NumPadPrtSc', - 'NumPadHome', -] - -[[rows]] -height = 1.0 -row = [ - 'Tilde', - 'N1', - 'N2', - 'N3', - 'N4', - 'N5', - 'N6', - 'N7', - 'N8', - 'N9', - 'N0', - 'Hyphen', - 'Equals', - 'BkSpc', - 'RowEndSpacer', - 'NumLock', - 'FwdSlash', - 'Star', - 'Hyphen', -] - -[[rows]] -height = 1.0 -row = [ - 'Tab', - 'Q', - 'W', - 'E', - 'R', - 'T', - 'Y', - 'U', - 'I', - 'O', - 'P', - 'LBracket', - 'RBracket', - 'BackSlash', - 'RowEndSpacer', - 'N7', - 'N8', - 'N9', - 'NumPadPlus', -] - -[[rows]] -height = 1.0 -row = [ - 'Caps', - 'A', - 'S', - 'D', - 'F', - 'G', - 'H', - 'J', - 'K', - 'L', - 'SemiColon', - 'Quote', - 'Return', - 'RowEndSpacer', - 'N4', - 'N5', - 'N6', - 'NumPadPlus', -] - -[[rows]] -height = 1.0 -row = [ - 'LShift', - 'Z', - 'X', - 'C', - 'V', - 'B', - 'N', - 'M', - 'Comma', - 'Period', - 'FwdSlash', - 'Rshift', - 'RowEndSpacer', - 'N1', - 'N2', - 'N3', - 'NumPadEnter', -] - -[[rows]] -height = 1.0 -row = [ - 'LCtrl', - 'LFn', - 'Meta', - 'LAlt', - 'Space', - 'RAlt', - 'RFn', - 'RFn', - 'RCtrlLarge', - 'RowEndSpacer', - 'UpRegular', - 'N0', - 'NumPadDel', - 'NumPadEnter', -] - -[[rows]] -height = 1.0 -row = [ - 'FuncSpacer', - 'FuncSpacer', - 'FuncSpacer', - 'NormalSpacer', - 'NormalSpacer', - 'NormalSpacer', - 'NormalSpacer', - 'NormalSpacer', - 'NormalSpacer', - 'NormalSpacer', - 'NormalSpacer', - 'NormalSpacer', - 'NormalSpacer', - 'NormalSpacer', - 'NormalSpacer', - 'LeftRegular', - 'RowEndSpacer', - 'DownRegular', - 'RightRegular', - 'NormalSpacer', -] - diff --git a/rog-aura/data/layouts/gx502_US.ron b/rog-aura/data/layouts/gx502_US.ron new file mode 100644 index 00000000..ca9779ee --- /dev/null +++ b/rog-aura/data/layouts/gx502_US.ron @@ -0,0 +1,382 @@ +( + 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, + ), + "bottom_row": Led( + width: 1.0, + height: 1.2, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "rog_row_spacing": Blank( + width: 0.9, + height: 0.0, + ), + "rog_row": Led( + width: 1.0, + height: 0.8, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.2, + pad_bottom: 0.4, + ), + "func_key": Led( + width: 1.0, + height: 0.8, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.0, + pad_bottom: 0.4, + ), + "func_space": Blank( + width: 0.7, + height: 0.0, + ), + "esc_func_spacing": Blank( + width: 0.6, + height: 0.0, + ), + "end_space": Blank( + width: 0.4, + height: 0.0, + ), + "ctrl_bkslash": Led( + width: 1.4, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "tilde": Led( + width: 0.7, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "tab": Led( + width: 1.4, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "capsplonk": Led( + width: 1.6, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + // The backspace button is composed of 3 individual LED + "backspace1": Led( + width: 0.7, + height: 1.0, + pad_left: 0.1, + pad_right: 0.0, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "backspace2": Led( + width: 0.7, + height: 1.0, + pad_left: 0.0, + pad_right: 0.0, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "backspace3": Led( + width: 0.7, + height: 1.0, + pad_left: 0.0, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "return1": Led( + width: 0.8, + height: 1.0, + pad_left: 0.1, + pad_right: 0.0, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "return2": Led( + width: 0.8, + height: 1.0, + pad_left: 0.0, + pad_right: 0.0, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "return3": Led( + width: 0.8, + height: 1.0, + pad_left: 0.0, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "lshift": Led( + width: 2.2, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "rshift1": Led( + width: 1.0, + height: 1.0, + pad_left: 0.1, + pad_right: 0.0, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "rshift2": Led( + width: 1.0, + height: 1.0, + pad_left: 0.0, + pad_right: 0.0, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "rshift3": Led( + width: 1.0, + height: 1.0, + pad_left: 0.0, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "spacebar_left": Led( + width: 1.1, + height: 1.4, + pad_left: 0.1, + pad_right: 0.0, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "spacebar_mid": Led( + width: 1.2, + height: 1.4, + pad_left: 0.0, + pad_right: 0.0, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "spacebar_right": Led( + width: 1.1, + height: 1.4, + pad_left: 0.0, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "up_arrow": Led( + width: 0.8, + height: 0.8, + pad_left: 1.2, + pad_right: 1.2, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "arrows": Led( + width: 0.8, + height: 0.8, + pad_left: 0.1, + pad_right: 0.1, + pad_top: -0.5, + pad_bottom: 0.1, + ), + "arrow_row_blocking": Blank( + width: 1.115, + height: 0.0, + ), + }, + key_rows: [ + ( + pad_left: 0.1, + pad_top: 0.1, + row: [ + (Blocking, "rog_row_spacing"), + (Blocking, "rog_row_spacing"), + (VolDown, "rog_row"), + (VolUp, "rog_row"), + (MicMute, "rog_row"), + (RogApp, "rog_row"), + ], + ), + ( + pad_left: 0.1, + pad_top: 0.1, + row: [ + (Esc, "func_key"), + (Spacing, "esc_func_spacing"), + (F1, "func_key"), + (F2, "func_key"), + (F3, "func_key"), + (F4, "func_key"), + (Spacing, "func_space"), + (F5, "func_key"), + (F6, "func_key"), + (F7, "func_key"), + (F8, "func_key"), + (Spacing, "func_space"), + (F9, "func_key"), + (F10, "func_key"), + (F11, "func_key"), + (F12, "func_key"), + (Spacing, "end_space"), + (Del, "func_key"), + ], + ), + ( + pad_left: 0.1, + pad_top: 0.1, + row: [ + (Tilde, "tilde"), + (N1, "regular"), + (N2, "regular"), + (N3, "regular"), + (N4, "regular"), + (N5, "regular"), + (N6, "regular"), + (N7, "regular"), + (N8, "regular"), + (N9, "regular"), + (N0, "regular"), + (Hyphen, "regular"), + (Equals, "regular"), + (Backspace3_1, "backspace1"), + (Backspace3_2, "backspace2"), + (Backspace3_3, "backspace3"), + (Spacing, "end_space"), + (Home, "regular"), + ], + ), + ( + pad_left: 0.1, + pad_top: 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, "ctrl_bkslash"), + (Spacing, "end_space"), + (PgUp, "regular"), + ], + ), + ( + pad_left: 0.1, + pad_top: 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"), + (Return3_1, "return1"), + (Return3_2, "return2"), + (Return3_3, "return3"), + (Spacing, "end_space"), + (PgDn, "regular"), + ], + ), + ( + pad_left: 0.1, + pad_top: 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"), + (Rshift3_1, "rshift1"), + (Rshift3_2, "rshift2"), + (Rshift3_3, "rshift3"), + (Spacing, "end_space"), + (End, "regular"), + ], + ), + ( + pad_left: 0.1, + pad_top: 0.1, + row: [ + (LCtrl, "bottom_row"), + (LFn, "bottom_row"), + (Meta, "bottom_row"), + (LAlt, "bottom_row"), + (Spacebar5_1, "spacebar_left"), + (Spacebar5_2, "spacebar_mid"), + (Spacebar5_3, "spacebar_mid"), + (Spacebar5_4, "spacebar_mid"), + (Spacebar5_5, "spacebar_right"), + (RAlt, "bottom_row"), + (PrtSc, "bottom_row"), + (RCtrl, "bottom_row"), + (Up, "up_arrow"), + (Spacing, "end_space"), + (RFn, "bottom_row"), + ], + ), + ( + pad_left: 0.1, + pad_top: 0.1, + row: [ + (Blocking, "arrow_row_blocking"), + (Blocking, "arrow_row_blocking"), + (Blocking, "arrow_row_blocking"), + (Blocking, "arrow_row_blocking"), + (Blocking, "arrow_row_blocking"), + (Blocking, "arrow_row_blocking"), + (Blocking, "arrow_row_blocking"), + (Blocking, "arrow_row_blocking"), + (Blocking, "arrow_row_blocking"), + (Blocking, "arrow_row_blocking"), + (Blocking, "arrow_row_blocking"), + (Blocking, "arrow_row_blocking"), + (Blocking, "arrow_row_blocking"), + (Left, "arrows"), + (Down, "arrows"), + (Right, "arrows"), + ], + ), + ], +) \ No newline at end of file diff --git a/rog-aura/data/layouts/gx502_US.toml b/rog-aura/data/layouts/gx502_US.toml deleted file mode 100644 index 624de569..00000000 --- a/rog-aura/data/layouts/gx502_US.toml +++ /dev/null @@ -1,172 +0,0 @@ -matches = [ - 'GX502', - 'GU502', -] - -locale = "US" - -[[rows]] -height = 0.8 -row = [ - 'NormalSpacer', - 'FuncSpacer', - 'VolDown', - 'VolUp', - 'MicMute', - 'Rog', -] - -[[rows]] -height = 0.8 -row = [ - 'Esc', - 'FuncSpacer', - 'F1', - 'F2', - 'F3', - 'F4', - 'FuncSpacer', - 'F5', - 'F6', - 'F7', - 'F8', - 'FuncSpacer', - 'F9', - 'F10', - 'F11', - 'F12', - 'RowEndSpacer', - 'Del', -] - -[[rows]] -height = 1.0 -row = [ - 'Tilde', - 'N1', - 'N2', - 'N3', - 'N4', - 'N5', - 'N6', - 'N7', - 'N8', - 'N9', - 'N0', - 'Hyphen', - 'Equals', - 'BkSpc3_1', - 'BkSpc3_2', - 'BkSpc3_3', - 'RowEndSpacer', - 'Home', -] - -[[rows]] -height = 1.0 -row = [ - 'Tab', - 'Q', - 'W', - 'E', - 'R', - 'T', - 'Y', - 'U', - 'I', - 'O', - 'P', - 'LBracket', - 'RBracket', - 'BackSlash', - 'RowEndSpacer', - 'PgUp', -] - -[[rows]] -height = 1.0 -row = [ - 'Caps', - 'A', - 'S', - 'D', - 'F', - 'G', - 'H', - 'J', - 'K', - 'L', - 'SemiColon', - 'Quote', - 'Return3_1', - 'Return3_2', - 'Return3_3', - 'RowEndSpacer', - 'PgDn', -] - -[[rows]] -height = 1.0 -row = [ - 'LShift', - 'Z', - 'X', - 'C', - 'V', - 'B', - 'N', - 'M', - 'Comma', - 'Period', - 'FwdSlash', - 'Rshift3_1', - 'Rshift3_2', - 'Rshift3_3', - 'RowEndSpacer', - 'End', -] - -[[rows]] -height = 1.2 -row = [ - 'LCtrl', - 'LFn', - 'Meta', - 'LAlt', - 'Space5_1', - 'Space5_2', - 'Space5_3', - 'Space5_4', - 'Space5_5', - 'RAlt', - 'PrtSc', - 'RCtrl', - 'ArrowSpacer', - 'Up', - 'ArrowSpacer', - 'RowEndSpacer', - 'RFn', -] - -[[rows]] -height = 0.8 -row = [ - 'FuncSpacer', - 'FuncSpacer', - 'NormalSpacer', - 'NormalSpacer', - 'NormalSpacer', - 'NormalSpacer', - 'NormalSpacer', - 'NormalSpacer', - 'NormalSpacer', - 'NormalSpacer', - 'NormalSpacer', - 'NormalSpacer', - 'NormalSpacer', - 'Left', - 'Down', - 'Right', - 'ArrowSpacer', -] - diff --git a/rog-aura/data/layouts/gx531-per-key_US.ron b/rog-aura/data/layouts/gx531-per-key_US.ron new file mode 100644 index 00000000..f9e71833 --- /dev/null +++ b/rog-aura/data/layouts/gx531-per-key_US.ron @@ -0,0 +1,346 @@ +( + 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, + ), + "bottom_row": Led( + width: 1.0, + height: 1.2, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "func_key": Led( + width: 1.0, + height: 0.8, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.0, + pad_bottom: 0.4, + ), + "func_space": Blank( + width: 0.7, + height: 0.0, + ), + "esc_func_spacing": Blank( + width: 0.6, + height: 0.0, + ), + "ctrl_bkslash": Led( + width: 1.4, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "tilde": Led( + width: 0.7, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "tab": Led( + width: 1.4, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "capsplonk": Led( + width: 1.6, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + // The backspace button is composed of 3 individual LED + "backspace1": Led( + width: 0.7, + height: 1.0, + pad_left: 0.1, + pad_right: 0.0, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "backspace2": Led( + width: 0.7, + height: 1.0, + pad_left: 0.0, + pad_right: 0.0, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "backspace3": Led( + width: 0.7, + height: 1.0, + pad_left: 0.0, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "return1": Led( + width: 0.8, + height: 1.0, + pad_left: 0.1, + pad_right: 0.0, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "return2": Led( + width: 0.8, + height: 1.0, + pad_left: 0.0, + pad_right: 0.0, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "return3": Led( + width: 0.8, + height: 1.0, + pad_left: 0.0, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "lshift": Led( + width: 2.2, + height: 1.0, + pad_left: 0.1, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "rshift1": Led( + width: 1.0, + height: 1.0, + pad_left: 0.1, + pad_right: 0.0, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "rshift2": Led( + width: 1.0, + height: 1.0, + pad_left: 0.0, + pad_right: 0.0, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "rshift3": Led( + width: 1.0, + height: 1.0, + pad_left: 0.0, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "spacebar_left": Led( + width: 1.1, + height: 1.4, + pad_left: 0.1, + pad_right: 0.0, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "spacebar_mid": Led( + width: 1.2, + height: 1.4, + pad_left: 0.0, + pad_right: 0.0, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "spacebar_right": Led( + width: 1.1, + height: 1.4, + pad_left: 0.0, + pad_right: 0.1, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "up_arrow": Led( + width: 0.8, + height: 0.8, + pad_left: 1.2, + pad_right: 1.2, + pad_top: 0.1, + pad_bottom: 0.1, + ), + "arrows": Led( + width: 0.8, + height: 0.8, + pad_left: 0.1, + pad_right: 0.1, + pad_top: -0.5, + pad_bottom: 0.1, + ), + "arrow_row_blocking": Blank( + width: 1.115, + height: 0.0, + ), + }, + key_rows: [ + ( + pad_left: 0.1, + pad_top: 0.1, + row: [ + (Esc, "func_key"), + (Spacing, "esc_func_spacing"), + (F1, "func_key"), + (F2, "func_key"), + (F3, "func_key"), + (F4, "func_key"), + (Spacing, "func_space"), + (F5, "func_key"), + (F6, "func_key"), + (F7, "func_key"), + (F8, "func_key"), + (Spacing, "func_space"), + (F9, "func_key"), + (F10, "func_key"), + (F11, "func_key"), + (F12, "func_key"), + (RogApp, "func_key"), + (RogApp, "func_key"), + (Pause, "func_key"), + (PgDn, "func_key"), + ], + ), + ( + pad_left: 0.1, + pad_top: 0.1, + row: [ + (Tilde, "tilde"), + (N1, "regular"), + (N2, "regular"), + (N3, "regular"), + (N4, "regular"), + (N5, "regular"), + (N6, "regular"), + (N7, "regular"), + (N8, "regular"), + (N9, "regular"), + (N0, "regular"), + (Hyphen, "regular"), + (Equals, "regular"), + (Backspace3_1, "backspace1"), + (Backspace3_2, "backspace2"), + (Backspace3_3, "backspace3"), + ], + ), + ( + pad_left: 0.1, + pad_top: 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, "ctrl_bkslash"), + ], + ), + ( + pad_left: 0.1, + pad_top: 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"), + (Return3_1, "return1"), + (Return3_2, "return2"), + (Return3_3, "return3"), + ], + ), + ( + pad_left: 0.1, + pad_top: 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"), + (Rshift3_1, "rshift1"), + (Rshift3_2, "rshift2"), + (Rshift3_3, "rshift3"), + ], + ), + ( + pad_left: 0.1, + pad_top: 0.1, + row: [ + (LCtrl, "bottom_row"), + (LFn, "bottom_row"), + (Meta, "bottom_row"), + (LAlt, "bottom_row"), + (Spacebar5_1, "spacebar_left"), + (Spacebar5_2, "spacebar_mid"), + (Spacebar5_3, "spacebar_mid"), + (Spacebar5_4, "spacebar_mid"), + (Spacebar5_5, "spacebar_right"), + (RAlt, "bottom_row"), + (PrtSc, "bottom_row"), + (RCtrl, "bottom_row"), + (Up, "up_arrow"), + ], + ), + ( + pad_left: 0.1, + pad_top: 0.1, + row: [ + (Blocking, "arrow_row_blocking"), + (Blocking, "arrow_row_blocking"), + (Blocking, "arrow_row_blocking"), + (Blocking, "arrow_row_blocking"), + (Blocking, "arrow_row_blocking"), + (Blocking, "arrow_row_blocking"), + (Blocking, "arrow_row_blocking"), + (Blocking, "arrow_row_blocking"), + (Blocking, "arrow_row_blocking"), + (Blocking, "arrow_row_blocking"), + (Blocking, "arrow_row_blocking"), + (Blocking, "arrow_row_blocking"), + (Blocking, "arrow_row_blocking"), + (Left, "arrows"), + (Down, "arrows"), + (Right, "arrows"), + ], + ), + ], +) \ No newline at end of file diff --git a/rog-aura/data/per_key_raw_bytes.ods b/rog-aura/data/per_key_raw_bytes.ods new file mode 100644 index 00000000..7543233e Binary files /dev/null and b/rog-aura/data/per_key_raw_bytes.ods differ diff --git a/rog-aura/src/advanced.rs b/rog-aura/src/advanced.rs new file mode 100644 index 00000000..fbaf669e --- /dev/null +++ b/rog-aura/src/advanced.rs @@ -0,0 +1,576 @@ +use log::warn; +use serde::{Deserialize, Serialize}; +#[cfg(feature = "dbus")] +use zbus::zvariant::Type; + +/// The `LedCode` used in setting up keyboard layouts is important because it +/// determines the idexing for an RGB value in the final USB packets (for +/// per-key addressable keyboards). +#[derive(Debug, Default, PartialEq, Eq, Copy, Clone, Serialize, Deserialize)] +pub enum LedCode { + VolUp, + VolDown, + MicMute, + #[default] + RogApp, + RogFan, + Esc, + F1, + F2, + F3, + F4, + F5, + F6, + F7, + F8, + F9, + F10, + F11, + F12, + Del, + Tilde, + N1, + N2, + N3, + N4, + N5, + N6, + N7, + N8, + N9, + N0, + Hyphen, + Equals, + Backspace, + /// For keyboards where the backspace button has 3 LED + Backspace3_1, + Backspace3_2, + Backspace3_3, + Home, + Tab, + Q, + W, + E, + R, + T, + Y, + U, + I, + O, + P, + LBracket, + RBracket, + BackSlash, + PgUp, + Caps, + A, + S, + D, + F, + G, + H, + J, + K, + L, + SemiColon, + Quote, + Return, + /// For keyboards where the return button has 3 LED + Return3_1, + Return3_2, + Return3_3, + PgDn, + LShift, + /// For keyboards where the left shift button has 3 LED + LShift3_1, + LShift3_2, + LShift3_3, + Z, + X, + C, + V, + B, + N, + M, + Comma, + Period, + FwdSlash, + Star, + NumPadDel, + NumPadPlus, + NumPadEnter, + NumPadPause, + NumPadPrtSc, + NumPadHome, + NumLock, + Rshift, + Rshift3_1, + Rshift3_2, + Rshift3_3, + End, + LCtrl, + LFn, + Meta, + LAlt, + Spacebar, + /// For keyboards where the spacebar button has 5 LED + Spacebar5_1, + Spacebar5_2, + Spacebar5_3, + Spacebar5_4, + Spacebar5_5, + Pause, + RAlt, + PrtSc, + RCtrl, + Up, + Down, + Left, + Right, + RFn, + MediaPlay, + MediaStop, + MediaNext, + MediaPrev, + LidLogo, + LidLeft, + LidRight, + /// Used by per-key and multizoned + LightbarRight, + /// Used by per-key and multizoned + LightbarRightCorner, + /// Used by per-key and multizoned + LightbarRightBottom, + /// Used by per-key and multizoned + LightbarLeftBottom, + /// Used by per-key and multizoned + LightbarLeftCorner, + /// Used by per-key and multizoned + LightbarLeft, + /// Use if the keyboard supports only a single zone. This zone uses the same + /// packet data as the `Zoned*` below + SingleZone, + /// Use if the keyboard supports 4 zones, this is the left zone + ZonedKbLeft, + /// Use if the keyboard supports 4 zones, this is the left-center zone + ZonedKbLeftMid, + /// Use if the keyboard supports 4 zones, this is the right-center zone + ZonedKbRightMid, + /// Use if the keyboard supports 4 zones, this is the right zone + ZonedKbRight, + /// To be ignored by effects + Spacing, + /// To be ignored by effects + Blocking, +} + +impl LedCode { + pub fn is_placeholder(&self) -> bool { + matches!(self, Self::Spacing | Self::Blocking) + } + + pub fn is_keyboard_zone(&self) -> bool { + matches!( + self, + Self::ZonedKbLeft | Self::ZonedKbLeftMid | Self::ZonedKbRightMid | Self::ZonedKbRight + ) + } + + pub fn is_lightbar_zone(&self) -> bool { + matches!( + self, + Self::LightbarLeft + | Self::LightbarLeftCorner + | Self::LightbarLeftBottom + | Self::LightbarRightBottom + | Self::LightbarRightCorner + | Self::LightbarRight + ) + } +} + +/// Represents the per-key raw USB packets +pub type UsbPackets = Vec>; + +/// A `UsbPackets` contains all data to change the full set of keyboard +/// key colours individually. +/// +/// Each row of the internal array is a full HID packet that can be sent +/// to the keyboard EC. One row controls one group of keys, these keys are not +/// necessarily all on the same row of the keyboard, with some splitting between +/// two rows. +#[cfg_attr(feature = "dbus", derive(Type))] +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct LedUsbPackets { + /// The packet data used to send data to the USB keyboard + usb_packets: UsbPackets, + /// Wether or not this packet collection is zoned. The determines which + /// starting bytes are used and what the indexing is for lightbar RGB + /// colours + zoned: bool, +} + +impl Default for LedUsbPackets { + fn default() -> Self { + Self::new_per_key() + } +} + +impl LedUsbPackets { + /// Set up a series of per-key packets. This includes setting all the + /// required starting bytes per packet, but does not set any colours. + /// + /// These packets will not work with per-zone keyboards + pub fn new_per_key() -> Self { + let mut set = vec![vec![0u8; 64]; 11]; + // set[0].copy_from_slice(&KeyColourArray::get_init_msg()); + for (count, row) in set.iter_mut().enumerate() { + row[0] = 0x5d; // Report ID + row[1] = 0xbc; // Mode = custom??, 0xb3 is builtin + row[2] = 0x00; + row[3] = 0x01; // ?? + row[4] = 0x01; // ??, 4,5,6 are normally RGB for builtin mode colours + row[5] = 0x01; // ?? + row[6] = (count as u8) << 4; // Key group + if count == 10 { + row[7] = 0x08; // 0b00001000 + } else { + row[7] = 0x10; // 0b00010000 addressing? flips for group a0 + } + row[8] = 0x00; + } + Self { + usb_packets: set, + zoned: false, + } + } + + /// Create new zoned packets. Although the result is a nested `Vec` only the + /// first vector is available. The final packet is slightly different + /// for single-zoned compared to multizoned. + /// + /// This packet will not work with per-key keyboards + /// + /// Wireshark captures show: + /// ```ignore + /// 5d,bc,01,01,00,00,00,00,00,ff,00,00, RED, single zone + /// 5d,bc,01,01,04,00,00,00,00,ff,00,00, RED, multizone + /// ``` + pub fn new_zoned(multizoned: bool) -> Self { + let mut pkt = vec![0u8; 64]; + pkt[0] = 0x5d; // Report ID + pkt[1] = 0xbc; // Mode = custom??, 0xb3 is builtin + pkt[2] = 0x01; + pkt[3] = 0x01; // ?? + if !multizoned { + pkt[4] = 0x00; // This doesn't actually seem to matter on this + // keyboard? + } else { + pkt[4] = 0x04; // ??, 4,5,6 are normally RGB for builtin mode + // colours + } + Self { + usb_packets: vec![pkt], + zoned: true, + } + } + + /// Initialise and clear the keyboard for custom effects, this must be done + /// for every time mode switches from builtin to custom + #[inline] + pub const fn get_init_msg() -> [u8; 64] { + let mut init = [0u8; 64]; + init[0] = 0x5d; // Report ID + init[1] = 0xbc; // Mode = custom??, 0xb3 is builtin + init + } + + /// Set the RGB colour of an `LedCode` + #[inline] + pub fn set(&mut self, key: LedCode, r: u8, g: u8, b: u8) { + if let Some(c) = self.rgb_for_led_code(key) { + c[0] = r; + c[1] = g; + c[2] = b; + } + } + + /// Indexes in to `UsbPackets` at the correct row and column + /// to set a series of three bytes to the chosen R,G,B values + /// + /// Indexing is different for `zoned` and assumes that only one packet is + /// generated for all the zones + fn rgb_for_led_code(&mut self, led_code: LedCode) -> Option<&mut [u8]> { + let zoned = self.zoned; + // Tuples are indexes in to array + let (row, col) = match led_code { + LedCode::VolDown => (0, 15), + LedCode::VolUp => (0, 18), + LedCode::MicMute => (0, 21), + LedCode::RogApp => (0, 24), + // + LedCode::Esc => (1, 24), + LedCode::F1 => (1, 30), + LedCode::F2 => (1, 33), + LedCode::F3 => (1, 36), + LedCode::F4 => (1, 39), + LedCode::F5 => (1, 45), + LedCode::F6 => (1, 48), + LedCode::F7 => (1, 51), + LedCode::F8 => (1, 54), + // + LedCode::F9 => (2, 12), + LedCode::F10 => (2, 15), + LedCode::F11 => (2, 18), + LedCode::F12 => (2, 21), + LedCode::Del => (2, 24), + LedCode::Tilde => (2, 39), + LedCode::N1 => (2, 42), + LedCode::N2 => (2, 45), + LedCode::N3 => (2, 48), + LedCode::N4 => (2, 51), + LedCode::N5 => (2, 54), + // + LedCode::N6 => (3, 9), + LedCode::N7 => (3, 12), + LedCode::N8 => (3, 15), + LedCode::N9 => (3, 18), + LedCode::N0 => (3, 21), + LedCode::Hyphen => (3, 24), + LedCode::Equals => (3, 27), + LedCode::Backspace3_1 => (3, 30), + LedCode::Backspace3_2 => (3, 33), + LedCode::Backspace3_3 => (3, 36), + LedCode::Home => (3, 39), + LedCode::Tab => (3, 54), + // + LedCode::Q => (4, 9), + LedCode::W => (4, 12), + LedCode::E => (4, 15), + LedCode::R => (4, 18), + LedCode::T => (4, 21), + LedCode::Y => (4, 24), + LedCode::U => (4, 27), + LedCode::I => (4, 30), + LedCode::O => (4, 33), + LedCode::P => (4, 36), + LedCode::LBracket => (4, 39), + LedCode::RBracket => (4, 42), + LedCode::BackSlash => (4, 45), + LedCode::PgUp => (4, 54), + // + LedCode::Caps => (5, 21), + LedCode::A => (5, 24), + LedCode::S => (5, 27), + LedCode::D => (5, 30), + LedCode::F => (5, 33), + LedCode::G => (5, 36), + LedCode::H => (5, 39), + LedCode::J => (5, 42), + LedCode::K => (5, 45), + LedCode::L => (5, 48), + LedCode::SemiColon => (5, 51), + LedCode::Quote => (5, 54), + // + LedCode::Return => (6, 9), + LedCode::Return3_1 => (6, 12), + LedCode::Return3_2 => (6, 15), + LedCode::Return3_3 => (6, 18), + LedCode::PgDn => (6, 21), + LedCode::LShift => (6, 36), + // TODO: Find correct locations + LedCode::LShift3_1 => (6, 36), + LedCode::LShift3_2 => (6, 36), + LedCode::LShift3_3 => (6, 36), + LedCode::Z => (6, 42), + LedCode::X => (6, 45), + LedCode::C => (6, 48), + LedCode::V => (6, 51), + LedCode::B => (6, 54), + // + LedCode::N => (7, 9), + LedCode::M => (7, 12), + LedCode::Comma => (7, 15), + LedCode::Period => (7, 18), + LedCode::FwdSlash => (7, 21), + LedCode::Rshift => (7, 24), + LedCode::Rshift3_1 => (7, 27), + LedCode::Rshift3_2 => (7, 30), + LedCode::Rshift3_3 => (7, 33), + LedCode::End => (7, 36), + LedCode::LCtrl => (7, 51), + LedCode::LFn => (7, 54), + // + LedCode::Meta => (8, 9), + LedCode::LAlt => (8, 12), + LedCode::Spacebar5_1 => (8, 15), + LedCode::Spacebar5_2 => (8, 18), + LedCode::Spacebar5_3 => (8, 21), + LedCode::Spacebar5_4 => (8, 24), + LedCode::Spacebar5_5 => (8, 27), + LedCode::RAlt => (8, 30), + LedCode::PrtSc => (8, 33), + LedCode::RCtrl => (8, 36), + LedCode::Up => (8, 42), + LedCode::RFn => (8, 51), + // + LedCode::Left => (9, 54), + // + LedCode::Down => (10, 9), + LedCode::Right => (10, 12), + LedCode::LidLogo => (11, 9), + LedCode::LidLeft => (11, 36), + LedCode::LidRight => (11, 39), + // + LedCode::SingleZone | LedCode::ZonedKbLeft => (0, 9), + LedCode::ZonedKbLeftMid => (0, 12), + LedCode::ZonedKbRightMid => (0, 15), + LedCode::ZonedKbRight => (0, 18), + LedCode::LightbarRight => if zoned {(0, 27)} else { (11, 15)}, + LedCode::LightbarRightCorner => if zoned {(0, 30)} else {(11, 18)}, + LedCode::LightbarRightBottom => if zoned {(0, 33)} else{(11, 21)}, + LedCode::LightbarLeftBottom => if zoned {(0, 36)} else{(11, 24)}, + LedCode::LightbarLeftCorner => if zoned {(0, 39)} else{(11, 27)}, + LedCode::LightbarLeft => if zoned {(0, 42)} else{(11, 30)}, + // + LedCode::Spacing + | LedCode::Blocking + // TODO: the addressing of the following + | LedCode::MediaPlay + | LedCode::MediaStop + | LedCode::MediaPrev + | LedCode::MediaNext + | LedCode::Pause + | LedCode::NumLock + | LedCode::Star + | LedCode::NumPadDel + | LedCode::NumPadPlus + | LedCode::NumPadEnter + | LedCode::NumPadPause + | LedCode::NumPadPrtSc + | LedCode::NumPadHome + | LedCode::RogFan + | LedCode::Spacebar + | LedCode::Backspace => return None, + }; + + if self.zoned && row > 0 { + warn!( + "LedCode {led_code:?} for zoned is not correct or out of Zone range. Setting to 0", + ); + return None; + } + + Some(&mut self.usb_packets[row][col..=col + 2]) + } + + #[inline] + pub fn get(&self) -> UsbPackets { + self.usb_packets.clone() + } + + #[inline] + pub fn get_ref(&self) -> &UsbPackets { + &self.usb_packets + } + + #[inline] + pub fn get_mut(&mut self) -> &mut UsbPackets { + &mut self.usb_packets + } +} + +impl From for UsbPackets { + fn from(k: LedUsbPackets) -> Self { + k.usb_packets + } +} + +#[cfg(test)] +mod tests { + use crate::advanced::{LedCode, LedUsbPackets, UsbPackets}; + + macro_rules! colour_check_zoned { + ($zone:expr, $pkt_idx_start:expr) => { + let mut zone = LedUsbPackets::new_zoned(true); + let c = zone.rgb_for_led_code($zone).unwrap(); + c[0] = 255; + c[1] = 255; + c[2] = 255; + + let pkt: UsbPackets = zone.into(); + assert_eq!(pkt[0][$pkt_idx_start], 0xff); + assert_eq!(pkt[0][$pkt_idx_start + 1], 0xff); + assert_eq!(pkt[0][$pkt_idx_start + 2], 0xff); + }; + } + + #[test] + fn zone_to_packet_check() { + let zone = LedUsbPackets::new_zoned(true); + let pkt: UsbPackets = zone.into(); + assert_eq!(pkt[0][0], 0x5d); + assert_eq!(pkt[0][1], 0xbc); + assert_eq!(pkt[0][2], 0x01); + assert_eq!(pkt[0][3], 0x01); + assert_eq!(pkt[0][4], 0x04); + + colour_check_zoned!(LedCode::ZonedKbLeft, 9); + colour_check_zoned!(LedCode::ZonedKbLeftMid, 12); + colour_check_zoned!(LedCode::ZonedKbRightMid, 15); + colour_check_zoned!(LedCode::ZonedKbRight, 18); + + colour_check_zoned!(LedCode::LightbarRight, 27); + colour_check_zoned!(LedCode::LightbarRightCorner, 30); + colour_check_zoned!(LedCode::LightbarRightBottom, 33); + colour_check_zoned!(LedCode::LightbarLeftBottom, 36); + colour_check_zoned!(LedCode::LightbarLeftCorner, 39); + colour_check_zoned!(LedCode::LightbarLeft, 42); + } + + #[test] + fn perkey_to_packet_check() { + let per_key = LedUsbPackets::new_per_key(); + let pkt: UsbPackets = per_key.into(); + assert_eq!(pkt[0][0], 0x5d); + assert_eq!(pkt[0][1], 0xbc); + assert_eq!(pkt[0][2], 0x00); + assert_eq!(pkt[0][3], 0x01); + assert_eq!(pkt[0][4], 0x01); + assert_eq!(pkt[0][5], 0x01); + + let mut per_key = LedUsbPackets::new_per_key(); + let c = per_key.rgb_for_led_code(LedCode::D).unwrap(); + c[0] = 255; + c[1] = 255; + c[2] = 255; + let c = per_key.rgb_for_led_code(LedCode::O).unwrap(); + c[0] = 255; + c[1] = 255; + c[2] = 255; + let c = per_key.rgb_for_led_code(LedCode::N0).unwrap(); + c[0] = 255; + c[1] = 255; + c[2] = 255; + let c = per_key.rgb_for_led_code(LedCode::M).unwrap(); + c[0] = 255; + c[1] = 255; + c[2] = 255; + + let pkt: UsbPackets = per_key.into(); + assert_eq!(pkt[5][30], 0xff); // D, red + assert_eq!(pkt[5][31], 0xff); // D + assert_eq!(pkt[5][32], 0xff); // D + assert_eq!(pkt[5][33], 0x00); // D + + assert_eq!(pkt[4][33], 0xff); // O, red + assert_eq!(pkt[4][34], 0xff); // O + assert_eq!(pkt[4][35], 0xff); // O + assert_eq!(pkt[4][36], 0x00); // O + + assert_eq!(pkt[7][12], 0xff); // M, red + assert_eq!(pkt[7][13], 0xff); // M + assert_eq!(pkt[7][14], 0xff); // M + assert_eq!(pkt[7][15], 0x00); // M + } +} diff --git a/rog-aura/src/advanced_to_str.rs b/rog-aura/src/advanced_to_str.rs new file mode 100644 index 00000000..95fb1ac2 --- /dev/null +++ b/rog-aura/src/advanced_to_str.rs @@ -0,0 +1,148 @@ +use crate::advanced::LedCode; + +impl From for &str { + fn from(k: LedCode) -> Self { + (&k).into() + } +} + +impl From<&LedCode> for &str { + fn from(k: &LedCode) -> Self { + match k { + LedCode::VolUp => "Volume Up", + LedCode::VolDown => "Volume Down", + LedCode::MicMute => "Mute Mic", + LedCode::RogApp => "ROG", + LedCode::RogFan => "Fan Control", + LedCode::Esc => "Escape", + LedCode::F1 => "F1", + LedCode::F2 => "F2", + LedCode::F3 => "F3", + LedCode::F4 => "F4", + LedCode::F5 => "F5", + LedCode::F6 => "F6", + LedCode::F7 => "F7", + LedCode::F8 => "F8", + LedCode::F9 => "F9", + LedCode::F10 => "F10", + LedCode::F11 => "F11", + LedCode::F12 => "F12", + LedCode::Del => "Delete", + LedCode::Tilde => "Tilde", + LedCode::N1 => "1", + LedCode::N2 => "2", + LedCode::N3 => "3", + LedCode::N4 => "4", + LedCode::N5 => "5", + LedCode::N6 => "6", + LedCode::N7 => "7", + LedCode::N8 => "8", + LedCode::N9 => "9", + LedCode::N0 => "0", + LedCode::Hyphen => "-", + LedCode::Equals => "=", + LedCode::Backspace => "Backspace", + LedCode::Backspace3_1 => "Backspace LED 1", + LedCode::Backspace3_2 => "Backspace LED 2", + LedCode::Backspace3_3 => "Backspace LED 3", + LedCode::Home => "Home", + LedCode::Tab => "Tab", + LedCode::Q => "Q", + LedCode::W => "W", + LedCode::E => "E", + LedCode::R => "R", + LedCode::T => "T", + LedCode::Y => "Y", + LedCode::U => "U", + LedCode::I => "I", + LedCode::O => "O", + LedCode::P => "P", + LedCode::LBracket => "[", + LedCode::RBracket => "]", + LedCode::BackSlash => "\\", + LedCode::PgUp => "Page Up", + LedCode::Caps => "Caps Lock", + LedCode::A => "A", + LedCode::S => "S", + LedCode::D => "D", + LedCode::F => "F", + LedCode::G => "G", + LedCode::H => "H", + LedCode::J => "J", + LedCode::K => "K", + LedCode::L => "L", + LedCode::SemiColon => ";", + LedCode::Quote => "'", + LedCode::Return => "Return", + LedCode::Return3_1 => "Return LED 1", + LedCode::Return3_2 => "Return LED 2", + LedCode::Return3_3 => "Return LED 3", + LedCode::PgDn => "Page Down", + LedCode::LShift => "Left Shift", + LedCode::LShift3_1 => "Left Shift LED 1", + LedCode::LShift3_2 => "Left Shift LED 2", + LedCode::LShift3_3 => "Left Shift LED 3", + LedCode::Z => "Z", + LedCode::X => "X", + LedCode::C => "C", + LedCode::V => "V", + LedCode::B => "B", + LedCode::N => "N", + LedCode::M => "M", + LedCode::Comma => ",", + LedCode::Period => ".", + LedCode::Star => "*", + LedCode::NumPadDel => "Delete", + LedCode::NumPadPlus => "+", + LedCode::NumPadEnter => "Enter", + LedCode::NumPadPause => "Pause", + LedCode::NumPadPrtSc => "Print Screen", + LedCode::NumPadHome => "Home", + LedCode::NumLock => "Num-Lock", + LedCode::FwdSlash => "/", + LedCode::Rshift => "Right Shift", + LedCode::Rshift3_1 => "Right Shift LED 1", + LedCode::Rshift3_2 => "Right Shift LED 2", + LedCode::Rshift3_3 => "Right Shift LED 3", + LedCode::End => "End", + LedCode::LCtrl => "Left Control", + LedCode::LFn => "Left Fn", + LedCode::Meta => "Meta", + LedCode::LAlt => "Left Alt", + LedCode::Spacebar => "Space", + LedCode::Spacebar5_1 => "Space LED 1", + LedCode::Spacebar5_2 => "Space LED 2", + LedCode::Spacebar5_3 => "Space LED 3", + LedCode::Spacebar5_4 => "Space LED 4", + LedCode::Spacebar5_5 => "Space LED 5", + LedCode::RAlt => "Right Alt", + LedCode::PrtSc => "Print Screen", + LedCode::RCtrl => "Right Control", + LedCode::Pause => "Pause", + LedCode::Up => "Up", + LedCode::Down => "Down", + LedCode::Left => "Left", + LedCode::Right => "Right", + LedCode::RFn => "Right Fn", + LedCode::MediaPlay => "Media Play", + LedCode::MediaStop => "Media Stop", + LedCode::MediaNext => "Media Next", + LedCode::MediaPrev => "Media Previous", + LedCode::LidLogo => "Lid Logo", + LedCode::LidLeft => "Lid Left", + LedCode::LidRight => "Lid Right", + LedCode::LightbarRight => "Lightbar Right", + LedCode::LightbarRightCorner => "Lightbar Right Corner", + LedCode::LightbarRightBottom => "Lightbar Right Bottom", + LedCode::LightbarLeftBottom => "Lightbar Left Bottom", + LedCode::LightbarLeftCorner => "Lightbar Left Corner", + LedCode::LightbarLeft => "Lightbar Left", + LedCode::Spacing | LedCode::Blocking => "", + LedCode::SingleZone => "Single Zoned Keyboard", + LedCode::ZonedKbLeft => "Left Zone (zone 1)", + LedCode::ZonedKbLeftMid => "Center-left Zone (zone 2)", + LedCode::ZonedKbRightMid => "Center-right Zone (zone 3)", + LedCode::ZonedKbRight => "Right Zone (zone 4)", + } + } +} diff --git a/rog-aura/src/aura_detection.rs b/rog-aura/src/aura_detection.rs new file mode 100644 index 00000000..ae2451de --- /dev/null +++ b/rog-aura/src/aura_detection.rs @@ -0,0 +1,189 @@ +use std::fs::OpenOptions; +use std::io::Read; + +use log::{error, info, warn}; +use serde_derive::{Deserialize, Serialize}; + +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"]; + +#[derive(Debug, Default, Clone, PartialEq, Eq, Deserialize, Serialize)] +pub struct LedSupportFile(Vec); + +#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, Serialize)] +pub struct LaptopLedData { + /// Found via `cat /sys/class/dmi/id/board_name`, e.g `GU603ZW`. + /// The match doesn't have to be the complete model number as it is + /// typically broken down such: + /// - GU = product + /// - 603 = model/platform + /// - Z = variant/year or perhaps dGPU model (such as RTX 3xxx) + /// - W = possibly dGPU model (such as RTX 3060Ti) + pub board_name: String, + pub layout_name: String, + pub basic_modes: Vec, + pub basic_zones: Vec, + pub advanced_type: AdvancedAuraType, +} + +#[derive(Debug, Clone, Default, Deserialize, Serialize)] +pub struct LaptopLedData456 { + pub prod_family: String, + pub board_names: Vec, + pub standard: Vec, + pub multizone: Vec, + pub per_key: bool, +} + +impl LaptopLedData { + pub fn get_data() -> Self { + let dmi = sysfs_class::DmiId::default(); + let board_name = dmi.board_name().expect("Could not get board_name"); + // let prod_family = dmi.product_family().expect("Could not get + // product_family"); + + if let Some(modes) = LedSupportFile::load_from_config() { + if let Some(data) = modes.matcher(&board_name) { + return data; + } + } + info!("Using generic LED control for keyboard brightness only"); + LaptopLedData::default() + } +} + +impl LedSupportFile { + pub fn get(&self) -> &[LaptopLedData] { + &self.0 + } + + /// The list is stored in ordered format, so the iterator must be reversed + /// to ensure we match to *whole names* first before doing a glob match + pub fn matcher(self, board_name: &str) -> Option { + for config in self.0.iter().rev() { + if board_name.contains(&config.board_name) { + info!("LedSupport: Matched to {}", config.board_name); + return Some(config.clone()); + } + } + None + } + + pub fn load_from_config() -> Option { + 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::(&buf) { + 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 + ); + } + } + } + data.0.sort_by(|a, b| a.board_name.cmp(&b.board_name)); + + if loaded { + return Some(data); + } + + warn!("Does {} exist?", ASUS_LED_MODE_USER_CONF); + None + } +} + +#[cfg(test)] +mod tests { + use std::fs::OpenOptions; + use std::io::{Read, Write}; + use std::path::PathBuf; + + use ron::ser::PrettyConfig; + + use super::LaptopLedData; + use crate::advanced::LedCode; + use crate::aura_detection::LedSupportFile; + // use crate::zoned::Zone; + use crate::{AdvancedAuraType, AuraModeNum, AuraZone}; + + #[test] + fn check_data_parse() { + let led = LaptopLedData { + board_name: "Test".to_owned(), + layout_name: "ga401".to_owned(), + basic_modes: vec![AuraModeNum::Static], + basic_zones: vec![AuraZone::Key1, AuraZone::Logo, AuraZone::BarLeft], + advanced_type: AdvancedAuraType::Zoned(vec![LedCode::LightbarRight]), + }; + + assert!(ron::to_string(&led).is_ok()); + // assert_eq!(json, String::new()); + } + + #[test] + fn check_data_file_parse() { + 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 tmp = ron::from_str::(&buf).unwrap(); + + // Ensure the data is sorted + let mut tmp_sort = tmp.clone(); + tmp_sort.0.sort_by(|a, b| a.board_name.cmp(&b.board_name)); + if tmp != tmp_sort { + let sorted = + ron::ser::to_string_pretty(&tmp_sort, PrettyConfig::new().depth_limit(2)).unwrap(); + let mut file = OpenOptions::new() + .write(true) + .create(true) + .truncate(true) + .open(&data) + .unwrap(); + file.write_all(sorted.as_bytes()).unwrap(); + panic!( + "aura_support.ron not sorted, should be {sorted}. File rewritten with correct \ + order, run test again" + ) + } + + let my_config = PrettyConfig::new().depth_limit(2); + println!( + "RON: {}", + ron::ser::to_string_pretty(&tmp, my_config).unwrap() + ); + } +} diff --git a/rog-aura/src/builtin_modes.rs b/rog-aura/src/builtin_modes.rs index f16f7cc3..ddae1fe0 100644 --- a/rog-aura/src/builtin_modes.rs +++ b/rog-aura/src/builtin_modes.rs @@ -4,12 +4,15 @@ pub const LED_INIT3: [u8; 6] = [0x5d, 0x05, 0x20, 0x31, 0, 0x08]; pub const LED_INIT4: &str = "^ASUS Tech.Inc."; // ^ == 0x5e pub const LED_INIT5: [u8; 6] = [0x5e, 0x05, 0x20, 0x31, 0, 0x08]; +use std::fmt::Display; +use std::str::FromStr; + use serde_derive::{Deserialize, Serialize}; -use std::{fmt::Display, str::FromStr}; #[cfg(feature = "dbus")] use zbus::zvariant::Type; -use crate::{error::Error, LED_MSG_LEN}; +use crate::error::Error; +use crate::LED_MSG_LEN; #[cfg_attr(feature = "dbus", derive(Type))] #[derive(Debug, Copy, Clone, PartialEq, Eq, Deserialize, Serialize)] @@ -280,8 +283,8 @@ impl FromStr for AuraZone { } } -/// Default factory modes structure. This easily converts to an USB HID packet with: -/// ```rust +/// Default factory modes structure. This easily converts to an USB HID packet +/// with: ```rust /// // let bytes: [u8; LED_MSG_LEN] = mode.into(); /// ``` #[cfg_attr(feature = "dbus", derive(Type))] @@ -366,8 +369,8 @@ impl AuraParameters { } impl AuraEffect { - /// A helper to provide detail on what effects have which parameters, e.g the static - /// factory mode accepts only one colour. + /// A helper to provide detail on what effects have which parameters, e.g + /// the static factory mode accepts only one colour. pub const fn allowed_parameters(mode: AuraModeNum) -> AuraParameters { match mode { AuraModeNum::Static diff --git a/rog-aura/src/effects/base.rs b/rog-aura/src/effects/base.rs new file mode 100644 index 00000000..dd57116f --- /dev/null +++ b/rog-aura/src/effects/base.rs @@ -0,0 +1,33 @@ +use super::{EffectState, InputForEffect}; +use crate::advanced::LedCode; +use crate::Colour; + +pub struct InputBased { + address: LedCode, + colour: Colour, + /// - audio + /// - cpu freq + /// - temperature + /// - fan speed + /// - time + input: Box, +} + +impl EffectState for InputBased { + fn next_colour_state(&mut self, _layout: &crate::layouts::KeyLayout) { + self.input.next_colour_state(); + self.colour = self.input.get_colour(); + } + + fn get_colour(&self) -> Colour { + self.colour + } + + fn get_led(&self) -> LedCode { + self.address + } + + fn set_led(&mut self, address: LedCode) { + self.address = address + } +} diff --git a/rog-aura/src/effects/breathe.rs b/rog-aura/src/effects/breathe.rs new file mode 100644 index 00000000..8b74f1c4 --- /dev/null +++ b/rog-aura/src/effects/breathe.rs @@ -0,0 +1,82 @@ +use serde::{Deserialize, Serialize}; + +use super::EffectState; +use crate::advanced::LedCode; +use crate::layouts::KeyLayout; +use crate::{effect_state_impl, Colour, Speed}; + +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct Breathe { + address: LedCode, + /// The starting colour + start_colour1: Colour, + /// The secondary starting colour + start_colour2: Colour, + /// The speed at which to cycle between the colours + speed: Speed, + /// Temporary data to help keep state + #[serde(skip)] + colour: Colour, + #[serde(skip)] + count_flipped: bool, + #[serde(skip)] + use_colour1: bool, +} + +impl Breathe { + pub fn new(address: LedCode, colour1: Colour, colour2: Colour, speed: Speed) -> Self { + Self { + address, + start_colour1: colour1, + start_colour2: colour2, + speed, + colour: colour1, + count_flipped: false, + use_colour1: true, + } + } +} + +impl EffectState for Breathe { + effect_state_impl!(); + + fn next_colour_state(&mut self, _layout: &KeyLayout) { + let Self { + start_colour1: colour1, + start_colour2: colour2, + speed, + colour: colour_actual, + count_flipped: flipped, + use_colour1, + .. + } = self; + + let speed = 4 - ::from(*speed); + + if *colour_actual == Colour(0, 0, 0) { + *use_colour1 = !*use_colour1; + } + + let colour = if !*use_colour1 { colour2 } else { colour1 }; + + let r1_scale = colour.0 / speed / 2; + let g1_scale = colour.1 / speed / 2; + let b1_scale = colour.2 / speed / 2; + + if *colour_actual == Colour(0, 0, 0) { + *flipped = true; + } else if colour_actual >= colour { + *flipped = false; + } + + if !*flipped { + colour_actual.0 = colour_actual.0.saturating_sub(r1_scale); + colour_actual.1 = colour_actual.1.saturating_sub(g1_scale); + colour_actual.2 = colour_actual.2.saturating_sub(b1_scale); + } else { + colour_actual.0 = colour_actual.0.saturating_add(r1_scale); + colour_actual.1 = colour_actual.1.saturating_add(g1_scale); + colour_actual.2 = colour_actual.2.saturating_add(b1_scale); + } + } +} diff --git a/rog-aura/src/effects/doom.rs b/rog-aura/src/effects/doom.rs new file mode 100644 index 00000000..ab23efc3 --- /dev/null +++ b/rog-aura/src/effects/doom.rs @@ -0,0 +1,164 @@ +use serde::{Deserialize, Serialize}; + +use crate::advanced::LedCode; +use crate::effects::{p_random, EffectState}; +use crate::layouts::KeyLayout; +use crate::{effect_state_impl, Colour}; + +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct DoomFlicker { + address: LedCode, + start_colour: Colour, + max_percentage: u8, + min_percentage: u8, + #[serde(skip)] + count: u8, + #[serde(skip)] + colour: Colour, +} + +impl DoomFlicker { + pub fn new(address: LedCode, colour: Colour, max_percentage: u8, min_percentage: u8) -> Self { + Self { + address, + colour, + count: 4, + max_percentage, + min_percentage, + start_colour: colour, + } + } +} + +impl EffectState for DoomFlicker { + effect_state_impl!(); + + fn next_colour_state(&mut self, _layout: &KeyLayout) { + let Self { + max_percentage, + min_percentage, + colour, + start_colour, + .. + } = self; + + if self.count == 0 { + self.count = 4; + } + self.count -= 1; + if self.count != 0 { + return; + } + + // TODO: make a "percentage" method on Colour. + let max_light = Colour( + (start_colour.0 as f32 / 100.0 * *max_percentage as f32) as u8, + (start_colour.1 as f32 / 100.0 * *max_percentage as f32) as u8, + (start_colour.2 as f32 / 100.0 * *max_percentage as f32) as u8, + ); + // min light is a percentage of the set colour + let min_light = Colour( + (start_colour.0 as f32 / 100.0 * *min_percentage as f32) as u8, + (start_colour.1 as f32 / 100.0 * *min_percentage as f32) as u8, + (start_colour.2 as f32 / 100.0 * *min_percentage as f32) as u8, + ); + + // Convert the 255 to percentage + let amount = (p_random() & 7) as f32 * 8.0; + + let set_colour = |colour: &mut u8, max: f32, min: f32| { + let pc = amount / max * 100.0; + let min_amount = pc * min / 100.0; // percentage of min colour + let max_amount = pc * max / 100.0; // percentage of max colour + if *colour as f32 - min_amount < min { + *colour = min as u8; + } else { + *colour = (max - max_amount) as u8; + } + }; + set_colour(&mut colour.0, max_light.0 as f32, min_light.0 as f32); + set_colour(&mut colour.1, max_light.1 as f32, min_light.1 as f32); + set_colour(&mut colour.2, max_light.2 as f32, min_light.2 as f32); + + self.count = 4; + } +} + +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 { + address: LedCode, + start_colour: Colour, + max_percentage: u8, + min_percentage: u8, + #[serde(skip)] + max_time: i32, + #[serde(skip)] + min_time: i32, + #[serde(skip)] + count: u8, + #[serde(skip)] + colour: Colour, +} + +impl DoomLightFlash { + pub fn new(address: LedCode, colour: Colour, max_percentage: u8, min_percentage: u8) -> Self { + Self { + address, + colour, + count: 4, + max_percentage, + min_percentage, + start_colour: colour, + max_time: 32, + min_time: 7, + } + } +} + +impl EffectState for DoomLightFlash { + effect_state_impl!(); + + fn next_colour_state(&mut self, _layout: &KeyLayout) { + let Self { + max_percentage, + min_percentage, + colour, + start_colour, + .. + } = self; + + self.count -= 1; + if self.count != 0 { + return; + } + + // TODO: make a "percentage" method on Colour. + let max_light = Colour( + (start_colour.0 as f32 / 100.0 * *max_percentage as f32) as u8, + (start_colour.1 as f32 / 100.0 * *max_percentage as f32) as u8, + (start_colour.2 as f32 / 100.0 * *max_percentage as f32) as u8, + ); + // min light is a percentage of the set colour + let min_light = Colour( + (start_colour.0 as f32 / 100.0 * *min_percentage as f32) as u8, + (start_colour.1 as f32 / 100.0 * *min_percentage as f32) as u8, + (start_colour.2 as f32 / 100.0 * *min_percentage as f32) as u8, + ); + + if *colour == max_light { + *colour = min_light; + self.count = ((p_random() & self.min_time) + 1) as u8; + } else { + *colour = max_light; + self.count = ((p_random() & self.max_time) + 1) as u8; + } + } +} diff --git a/rog-aura/src/effects/mod.rs b/rog-aura/src/effects/mod.rs new file mode 100644 index 00000000..f479518d --- /dev/null +++ b/rog-aura/src/effects/mod.rs @@ -0,0 +1,291 @@ +use serde_derive::{Deserialize, Serialize}; + +mod doom; +pub use doom::*; + +mod base; +pub use base::*; + +mod breathe; +pub use breathe::*; + +mod static_; +pub use static_::*; + +use crate::advanced::{LedCode, LedUsbPackets, UsbPackets}; +use crate::layouts::KeyLayout; +use crate::Colour; + +// static mut RNDINDEX: usize = 0; +static mut PRNDINDEX: usize = 0; + +/// Pseudo random table ripped straight out of room4doom +pub const RNDTABLE: [i32; 256] = [ + 0, 8, 109, 220, 222, 241, 149, 107, 75, 248, 254, 140, 16, 66, 74, 21, 211, 47, 80, 242, 154, + 27, 205, 128, 161, 89, 77, 36, 95, 110, 85, 48, 212, 140, 211, 249, 22, 79, 200, 50, 28, 188, + 52, 140, 202, 120, 68, 145, 62, 70, 184, 190, 91, 197, 152, 224, 149, 104, 25, 178, 252, 182, + 202, 182, 141, 197, 4, 81, 181, 242, 145, 42, 39, 227, 156, 198, 225, 193, 219, 93, 122, 175, + 249, 0, 175, 143, 70, 239, 46, 246, 163, 53, 163, 109, 168, 135, 2, 235, 25, 92, 20, 145, 138, + 77, 69, 166, 78, 176, 173, 212, 166, 113, 94, 161, 41, 50, 239, 49, 111, 164, 70, 60, 2, 37, + 171, 75, 136, 156, 11, 56, 42, 146, 138, 229, 73, 146, 77, 61, 98, 196, 135, 106, 63, 197, 195, + 86, 96, 203, 113, 101, 170, 247, 181, 113, 80, 250, 108, 7, 255, 237, 129, 226, 79, 107, 112, + 166, 103, 241, 24, 223, 239, 120, 198, 58, 60, 82, 128, 3, 184, 66, 143, 224, 145, 224, 81, + 206, 163, 45, 63, 90, 168, 114, 59, 33, 159, 95, 28, 139, 123, 98, 125, 196, 15, 70, 194, 253, + 54, 14, 109, 226, 71, 17, 161, 93, 186, 87, 244, 138, 20, 52, 123, 251, 26, 36, 17, 46, 52, + 231, 232, 76, 31, 221, 84, 37, 216, 165, 212, 106, 197, 242, 98, 43, 39, 175, 254, 145, 190, + 84, 118, 222, 187, 136, 120, 163, 236, 249, +]; + +pub fn p_random() -> i32 { + unsafe { + PRNDINDEX = (PRNDINDEX + 1) & 0xff; + RNDTABLE[PRNDINDEX] + } +} + +pub trait InputForEffect { + /// Calculate the next colour state + fn next_colour_state(&mut self); + + /// Return the resulting colour. Implementers should store the colour to + /// return it. + fn get_colour(&self) -> Colour; +} + +pub(crate) trait EffectState { + /// Calculate the next colour state + fn next_colour_state(&mut self, _layout: &KeyLayout); + + /// Return the resulting colour. Implementers should store the colour to + /// return it. + fn get_colour(&self) -> Colour; + + fn get_led(&self) -> LedCode; + + fn set_led(&mut self, address: LedCode); +} + +#[derive(Debug, Deserialize, Serialize, Default)] +pub struct AdvancedEffects { + effects: Vec, + zoned: bool, +} + +impl AdvancedEffects { + #[inline] + pub fn new(zoned: bool) -> Self { + Self { + effects: Default::default(), + zoned, + } + } + + #[inline] + pub fn push(&mut self, action: Effect) { + self.effects.push(action); + } + + #[inline] + pub fn insert(&mut self, index: usize, action: Effect) { + self.effects.insert(index, action); + } + + /// Remove an item at this position from the run buffer. If the `index` + /// supplied is not in range then `None` is returned, otherwise the + /// `ActionData` at that location is yeeted and returned. + #[inline] + pub fn remove_item(&mut self, index: usize) -> Option { + if index < self.effects.len() { + return Some(self.effects.remove(index)); + } + None + } + + pub fn next_state(&mut self, layout: &KeyLayout) { + for effect in &mut self.effects { + effect.next_state(layout); + } + } + + pub fn create_packets(&self) -> UsbPackets { + let mut usb_packets = if self.zoned { + // TODO: figure out if that single byte difference for multizone actually + // matters + LedUsbPackets::new_zoned(true) + } else { + LedUsbPackets::new_per_key() + }; + + for effect in &self.effects { + let c = effect.colour(); + usb_packets.set(effect.led(), c.0, c.1, c.2); + } + usb_packets.into() + } +} + +// how to be lazy +#[macro_export] +macro_rules! effect_state_impl { + () => { + fn get_colour(&self) -> $crate::Colour { + self.colour + } + + fn get_led(&self) -> $crate::advanced::LedCode { + self.address.clone() + } + + /// Change the led type + fn set_led(&mut self, address: $crate::advanced::LedCode) { + self.address = address; + } + }; +} + +/// A helper macro to quickly add new effects to the matching on `Effect` +macro_rules! effect_impl { + ($($effect:ident),*) => { + impl Effect { + /// Get the type of LED set + pub fn led(&self) -> $crate::advanced::LedCode { + match self { + $(Effect::$effect(c) => c.get_led(),)* + } + } + + /// Change the led type (can be used to change location of the effect) + pub fn set_led(&mut self, address: $crate::advanced::LedCode) { + match self { + $(Effect::$effect(c) => c.set_led(address),)* + } + } + + /// Calculate the next state of the effect + pub fn next_state(&mut self, layout: &KeyLayout) { + match self { + $(Effect::$effect(c) => c.next_colour_state(layout),)* + } + } + + /// Get the calculated colour + pub fn colour(&self) -> $crate::Colour { + match self { + $(Effect::$effect(c) => c.get_colour(),)* + } + } + } + }; +} + +/// The main effect container, a sequencer will call various methods on this to +/// update states and get colours +/// +/// Every effect is added here to quickly and easily match within `Effect` +#[derive(Debug, Clone, Deserialize, Serialize)] +pub enum Effect { + Static(Static), + Breathe(Breathe), + DoomFlicker(DoomFlicker), + DoomLightFlash(DoomLightFlash), +} + +impl Default for Effect { + fn default() -> Self { + Self::Static(Static::new(LedCode::default(), Colour::default())) + } +} + +effect_impl!(Static, Breathe, DoomFlicker, DoomLightFlash); + +#[cfg(test)] +mod tests { + use crate::advanced::LedCode; + use crate::effects::{AdvancedEffects, Breathe, DoomFlicker, Effect, Static}; + use crate::layouts::KeyLayout; + use crate::{Colour, Speed}; + + #[test] + fn single_key_next_state_then_create() { + let layout = KeyLayout::default_layout(); + let mut seq = AdvancedEffects::new(false); + seq.effects + .push(Effect::Static(Static::new(LedCode::F, Colour(255, 127, 0)))); + + seq.next_state(&layout); + let packets = seq.create_packets(); + + assert_eq!(packets[0][0], 0x5d); + assert_eq!(packets[5][33], 255); + assert_eq!(packets[5][34], 127); + assert_eq!(packets[5][35], 0); + } + + #[test] + fn cycle_breathe() { + let layout = KeyLayout::default_layout(); + let mut seq = AdvancedEffects::new(false); + seq.effects.push(Effect::Breathe(Breathe::new( + LedCode::F, + Colour(255, 127, 0), + Colour(127, 0, 255), + Speed::Med, + ))); + + let s = + ron::ser::to_string_pretty(&seq, ron::ser::PrettyConfig::new().depth_limit(4)).unwrap(); + println!("{s}"); + + seq.next_state(&layout); + let packets = seq.create_packets(); + + assert_eq!(packets[0][0], 0x5d); + assert_eq!(packets[5][33], 213); + assert_eq!(packets[5][34], 106); + assert_eq!(packets[5][35], 0); + + // dbg!(&packets[5][33..=35]); + + seq.next_state(&layout); + let packets = seq.create_packets(); + + assert_eq!(packets[0][0], 0x5d); + assert_eq!(packets[5][33], 171); + assert_eq!(packets[5][34], 85); + assert_eq!(packets[5][35], 0); + } + + #[test] + fn cycle_flicker() { + let layout = KeyLayout::default_layout(); + let mut seq = AdvancedEffects::new(false); + seq.effects.push(Effect::DoomFlicker(DoomFlicker::new( + LedCode::F, + Colour(255, 127, 80), + 100, + 10, + ))); + + seq.next_state(&layout); + let packets = seq.create_packets(); + + assert_eq!(packets[0][0], 0x5d); + assert_eq!(packets[5][33], 255); + assert_eq!(packets[5][34], 127); + assert_eq!(packets[5][35], 80); + + // The random is deterministic + seq.next_state(&layout); + seq.next_state(&layout); + seq.next_state(&layout); + seq.next_state(&layout); + seq.next_state(&layout); + seq.next_state(&layout); + seq.next_state(&layout); + + let packets = seq.create_packets(); + assert_eq!(packets[5][33], 215); + assert_eq!(packets[5][34], 87); + assert_eq!(packets[5][35], 40); + } +} diff --git a/rog-aura/src/effects/static_.rs b/rog-aura/src/effects/static_.rs new file mode 100644 index 00000000..18925a83 --- /dev/null +++ b/rog-aura/src/effects/static_.rs @@ -0,0 +1,25 @@ +use serde::{Deserialize, Serialize}; + +use super::EffectState; +use crate::advanced::LedCode; +use crate::layouts::KeyLayout; +use crate::{effect_state_impl, Colour}; + +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct Static { + address: LedCode, + /// The starting colour + colour: Colour, +} + +impl Static { + pub fn new(address: LedCode, colour: Colour) -> Self { + Self { address, colour } + } +} + +impl EffectState for Static { + effect_state_impl!(); + + fn next_colour_state(&mut self, _layout: &KeyLayout) {} +} diff --git a/rog-aura/src/error.rs b/rog-aura/src/error.rs index 2d6c0b81..2e7c86de 100644 --- a/rog-aura/src/error.rs +++ b/rog-aura/src/error.rs @@ -1,5 +1,4 @@ -use std::error; -use std::fmt; +use std::{error, fmt}; #[derive(Debug)] pub enum Error { @@ -7,8 +6,9 @@ pub enum Error { ParseSpeed, ParseDirection, ParseBrightness, - Io(std::io::Error), - Toml(toml::de::Error), + IoPath(String, std::io::Error), + Ron(ron::Error), + RonParse(ron::error::SpannedError), } impl fmt::Display for Error { @@ -19,22 +19,23 @@ impl fmt::Display for Error { Error::ParseSpeed => write!(f, "Could not parse speed"), Error::ParseDirection => write!(f, "Could not parse direction"), Error::ParseBrightness => write!(f, "Could not parse brightness"), - Error::Io(io) => write!(f, "IO Error: {io}"), - Error::Toml(e) => write!(f, "TOML Parse Error: {e}"), + Error::IoPath(path, io) => write!(f, "IO Error: {path}, {io}"), + Error::Ron(e) => write!(f, "RON Parse Error: {e}"), + Error::RonParse(e) => write!(f, "RON Parse Error: {e}"), } } } impl error::Error for Error {} -impl From for Error { - fn from(e: std::io::Error) -> Self { - Self::Io(e) +impl From for Error { + fn from(e: ron::Error) -> Self { + Self::Ron(e) } } -impl From for Error { - fn from(e: toml::de::Error) -> Self { - Self::Toml(e) +impl From for Error { + fn from(e: ron::error::SpannedError) -> Self { + Self::RonParse(e) } } diff --git a/rog-aura/src/key_to_str.rs b/rog-aura/src/key_to_str.rs deleted file mode 100644 index e215a689..00000000 --- a/rog-aura/src/key_to_str.rs +++ /dev/null @@ -1,155 +0,0 @@ -use crate::keys::Key; - -impl From for &str { - fn from(k: Key) -> Self { - (&k).into() - } -} - -impl From<&Key> for &str { - fn from(k: &Key) -> Self { - match k { - Key::VolUp => "Volume Up", - Key::VolDown => "Volume Down", - Key::MicMute => "Mute Mic", - Key::Rog => "ROG", - Key::Fan => "Fan Control", - Key::Esc => "Escape", - Key::F1 => "F1", - Key::F2 => "F2", - Key::F3 => "F3", - Key::F4 => "F4", - Key::F5 => "F5", - Key::F6 => "F6", - Key::F7 => "F7", - Key::F8 => "F8", - Key::F9 => "F9", - Key::F10 => "F10", - Key::F11 => "F11", - Key::F12 => "F12", - Key::Del => "Delete", - Key::Tilde => "Tilde", - Key::N1 => "1", - Key::N2 => "2", - Key::N3 => "3", - Key::N4 => "4", - Key::N5 => "5", - Key::N6 => "6", - Key::N7 => "7", - Key::N8 => "8", - Key::N9 => "9", - Key::N0 => "0", - Key::Hyphen => "-", - Key::Equals => "=", - Key::BkSpc => "Backspace", - Key::BkSpc3_1 => "Backspace LED 1", - Key::BkSpc3_2 => "Backspace LED 2", - Key::BkSpc3_3 => "Backspace LED 3", - Key::Home => "Home", - Key::Tab => "Tab", - Key::Q => "Q", - Key::W => "W", - Key::E => "E", - Key::R => "R", - Key::T => "T", - Key::Y => "Y", - Key::U => "U", - Key::I => "I", - Key::O => "O", - Key::P => "P", - Key::LBracket => "[", - Key::RBracket => "]", - Key::BackSlash => "\\", - Key::PgUp => "Page Up", - Key::Caps => "Caps Lock", - Key::A => "A", - Key::S => "S", - Key::D => "D", - Key::F => "F", - Key::G => "G", - Key::H => "H", - Key::J => "J", - Key::K => "K", - Key::L => "L", - Key::SemiColon => ";", - Key::Quote => "'", - Key::Return => "Return", - Key::Return3_1 => "Return LED 1", - Key::Return3_2 => "Return LED 2", - Key::Return3_3 => "Return LED 3", - Key::PgDn => "Page Down", - Key::LShift => "Left Shift", - Key::LShift3_1 => "Left Shift LED 1", - Key::LShift3_2 => "Left Shift LED 2", - Key::LShift3_3 => "Left Shift LED 3", - Key::Z => "Z", - Key::X => "X", - Key::C => "C", - Key::V => "V", - Key::B => "B", - Key::N => "N", - Key::M => "M", - Key::Comma => ",", - Key::Period => ".", - Key::Star => "*", - Key::NumPadDel => "Delete", - Key::NumPadPlus => "+", - Key::NumPadEnter => "Enter", - Key::NumPadPause => "Pause", - Key::NumPadPrtSc => "Print Screen", - Key::NumPadHome => "Home", - Key::NumLock => "Num-Lock", - Key::FwdSlash => "/", - Key::Rshift => "Right Shift", - Key::RshiftSmall => "Right Shift", - Key::Rshift3_1 => "Right Shift LED 1", - Key::Rshift3_2 => "Right Shift LED 2", - Key::Rshift3_3 => "Right Shift LED 3", - Key::End => "End", - Key::LCtrl => "Left Control", - Key::LCtrlMed => "Left Control", - Key::LFn => "Left Fn", - Key::Meta => "Meta", - Key::LAlt => "Left Alt", - Key::Space => "Space", - Key::Space5_1 => "Space LED 1", - Key::Space5_2 => "Space LED 2", - Key::Space5_3 => "Space LED 3", - Key::Space5_4 => "Space LED 4", - Key::Space5_5 => "Space LED 5", - Key::RAlt => "Right Alt", - Key::PrtSc => "Print Screen", - Key::RCtrl => "Right Control", - Key::RCtrlLarge => "Right Control", - Key::Pause => "Pause", - Key::Up => "Up", - Key::Down => "Down", - Key::Left => "Left", - Key::Right => "Right", - Key::UpRegular => "Up", - Key::DownRegular => "Down", - Key::LeftRegular => "Left", - Key::RightRegular => "Right", - Key::UpSplit => "Up", - Key::DownSplit => "Down", - Key::LeftSplit => "Left", - Key::RightSplit => "Right", - Key::RFn => "Right Fn", - Key::MediaPlay => "Media Play", - Key::MediaStop => "Media Stop", - Key::MediaNext => "Media Next", - Key::MediaPrev => "Media Previous", - Key::NormalBlank - | Key::NormalSpacer - | Key::FuncBlank - | Key::FuncSpacer - | Key::ArrowBlank - | Key::ArrowSpacer - | Key::ArrowRegularBlank - | Key::ArrowRegularSpacer - | Key::ArrowSplitBlank - | Key::ArrowSplitSpacer - | Key::RowEndSpacer => "", - } - } -} diff --git a/rog-aura/src/keys.rs b/rog-aura/src/keys.rs deleted file mode 100644 index 9e9c97ac..00000000 --- a/rog-aura/src/keys.rs +++ /dev/null @@ -1,358 +0,0 @@ -use serde::{Deserialize, Serialize}; - -#[derive(Debug, Default, PartialEq, Eq, Copy, Clone, Serialize, Deserialize)] -pub enum Key { - VolUp, - VolDown, - MicMute, - #[default] - Rog, - Fan, - Esc, - F1, - F2, - F3, - F4, - F5, - F6, - F7, - F8, - F9, - F10, - F11, - F12, - Del, - Tilde, - N1, - N2, - N3, - N4, - N5, - N6, - N7, - N8, - N9, - N0, - Hyphen, - Equals, - BkSpc, - BkSpc3_1, - BkSpc3_2, - BkSpc3_3, - Home, - Tab, - Q, - W, - E, - R, - T, - Y, - U, - I, - O, - P, - LBracket, - RBracket, - BackSlash, - PgUp, - Caps, - A, - S, - D, - F, - G, - H, - J, - K, - L, - SemiColon, - Quote, - Return, - Return3_1, - Return3_2, - Return3_3, - PgDn, - LShift, - LShift3_1, - LShift3_2, - LShift3_3, - Z, - X, - C, - V, - B, - N, - M, - Comma, - Period, - FwdSlash, - Star, - NumPadDel, - NumPadPlus, - NumPadEnter, - NumPadPause, - NumPadPrtSc, - NumPadHome, - NumLock, - Rshift, - RshiftSmall, - Rshift3_1, - Rshift3_2, - Rshift3_3, - End, - LCtrl, - LCtrlMed, - LFn, - Meta, - LAlt, - Space, - Space5_1, - Space5_2, - Space5_3, - Space5_4, - Space5_5, - Pause, - RAlt, - PrtSc, - RCtrl, - RCtrlLarge, - Up, - Down, - Left, - Right, - UpRegular, - DownRegular, - LeftRegular, - RightRegular, - UpSplit, - DownSplit, - LeftSplit, - RightSplit, - RFn, - MediaPlay, - MediaStop, - MediaNext, - MediaPrev, - NormalBlank, - /// To be ignored by per-key effects - NormalSpacer, - FuncBlank, - /// To be ignored by per-key effects - FuncSpacer, - ArrowBlank, - /// To be ignored by per-key effects - ArrowSpacer, - ArrowRegularBlank, - /// To be ignored by per-key effects - ArrowRegularSpacer, - ArrowSplitBlank, - /// To be ignored by per-key effects - ArrowSplitSpacer, - /// A gap between regular rows and the rightside buttons - RowEndSpacer, -} - -impl Key { - pub fn is_placeholder(&self) -> bool { - let shape = KeyShape::from(self); - shape.is_blank() || shape.is_spacer() - } -} - -/// Types of shapes of LED on keyboards. The shape is used for visual representations -/// -/// A post fix of Spacer *must be ignored by per-key effects -#[derive(Debug, Default, Clone, Copy, Deserialize, Serialize)] -pub enum KeyShape { - Tilde, - #[default] - Normal, - NormalBlank, - NormalSpacer, - Func, - FuncBlank, - FuncSpacer, - Space, - Space5, - LCtrlMed, - LShift, - /// Used in a group of 3 (LED's) - LShift3, - RShift, - RshiftSmall, - /// Used in a group of 3 (LED's) - RShift3, - Return, - Return3, - Tab, - Caps, - Backspace, - /// Used in a group of 3 (LED's) - Backspace3, - Arrow, - ArrowBlank, - ArrowSpacer, - ArrowSplit, - ArrowSplitBlank, - ArrowSplitSpacer, - ArrowRegularBlank, - ArrowRegularSpacer, - RowEndSpacer, -} - -impl KeyShape { - pub const fn width(&self) -> f32 { - match self { - Self::Tilde | Self::Arrow => 0.8, - Self::Normal - | Self::NormalBlank - | Self::NormalSpacer - | Self::Func - | Self::FuncBlank - | Self::Space5 - | Self::ArrowBlank - | Self::ArrowSpacer - | Self::ArrowSplit - | Self::ArrowSplitBlank - | Self::ArrowSplitSpacer => 1.0, - Self::FuncSpacer => 0.6, - Self::Space => 5.0, - Self::LCtrlMed => 1.1, - Self::LShift | Self::Backspace => 2.0, - Self::LShift3 => 0.67, - Self::RShift => 2.8, - Self::RshiftSmall => 1.8, - Self::RShift3 => 0.93, - Self::Return => 2.2, - Self::Return3 => 0.7333, - Self::Tab => 1.4, - Self::Caps => 1.6, - Self::Backspace3 => 0.666, - Self::ArrowRegularBlank | Self::ArrowRegularSpacer => 0.7, - - Self::RowEndSpacer => 0.1, - } - } - - /// A blank is used to space keys out in GUI's and can be used or ignored - /// depednign on the per-key effect - pub const fn is_blank(&self) -> bool { - matches!( - self, - Self::NormalBlank - | Self::FuncBlank - | Self::ArrowBlank - | Self::ArrowSplitBlank - | Self::ArrowRegularBlank - ) - } - - /// A spacer is used to space keys out in GUI's, but ignored in per-key effects - pub const fn is_spacer(&self) -> bool { - matches!( - self, - Self::FuncSpacer - | Self::NormalSpacer - | Self::ArrowSpacer - | Self::ArrowSplitSpacer - | Self::ArrowRegularSpacer - ) - } - - /// All keys with a postfix of some number - pub const fn is_group(&self) -> bool { - matches!( - self, - Self::LShift3 | Self::RShift3 | Self::Return3 | Self::Space5 | Self::Backspace3 - ) - } - - /// Mostly intended as a helper for signalling when to draw a - /// split/compact arrow cluster - pub const fn is_arrow_cluster(&self) -> bool { - matches!(self, Self::Arrow | Self::ArrowBlank | Self::ArrowSpacer) - } - - pub const fn is_arrow_splits(&self) -> bool { - matches!(self, Self::Arrow | Self::ArrowBlank | Self::ArrowSpacer) - } -} - -impl From for KeyShape { - fn from(k: Key) -> Self { - match k { - Key::VolUp - | Key::VolDown - | Key::MicMute - | Key::Rog - | Key::Fan - | Key::Esc - | Key::F1 - | Key::F2 - | Key::F3 - | Key::F4 - | Key::F5 - | Key::F6 - | Key::F7 - | Key::F8 - | Key::F9 - | Key::F10 - | Key::F11 - | Key::F12 - | Key::Del => KeyShape::Func, - Key::Tilde => KeyShape::Tilde, - - Key::BkSpc => KeyShape::Backspace, - Key::BkSpc3_1 | Key::BkSpc3_2 | Key::BkSpc3_3 => KeyShape::Backspace3, - Key::Tab | Key::BackSlash => KeyShape::Tab, - Key::Caps => KeyShape::Caps, - - Key::Return => KeyShape::Return, - Key::Return3_1 | Key::Return3_2 | Key::Return3_3 => KeyShape::Return3, - Key::LCtrlMed => KeyShape::LCtrlMed, - Key::LShift => KeyShape::LShift, - - Key::Rshift | Key::RCtrlLarge => KeyShape::RShift, - Key::RshiftSmall => KeyShape::RshiftSmall, - Key::Rshift3_1 | Key::Rshift3_2 | Key::Rshift3_3 => KeyShape::RShift3, - - Key::Space => KeyShape::Space, - Key::Space5_1 | Key::Space5_2 | Key::Space5_3 | Key::Space5_4 | Key::Space5_5 => { - KeyShape::Space5 - } - - Key::NumPadPause | Key::NumPadPrtSc | Key::NumPadHome | Key::NumPadDel => { - KeyShape::Func - } - - Key::NormalBlank => KeyShape::NormalBlank, - Key::NormalSpacer => KeyShape::NormalSpacer, - - Key::FuncBlank => KeyShape::FuncBlank, - Key::FuncSpacer => KeyShape::FuncSpacer, - - Key::Up | Key::Down | Key::Left | Key::Right => KeyShape::Arrow, - Key::ArrowBlank => KeyShape::ArrowBlank, - Key::ArrowSpacer => KeyShape::ArrowSpacer, - - Key::ArrowRegularBlank => KeyShape::ArrowRegularBlank, - Key::ArrowRegularSpacer => KeyShape::ArrowRegularSpacer, - - Key::UpSplit | Key::LeftSplit | Key::DownSplit | Key::RightSplit => { - KeyShape::ArrowSplit - } - Key::ArrowSplitBlank => KeyShape::ArrowSplitBlank, - Key::ArrowSplitSpacer => KeyShape::ArrowSplitSpacer, - - Key::RowEndSpacer => KeyShape::RowEndSpacer, - - _ => KeyShape::Normal, - } - } -} - -impl From<&Key> for KeyShape { - fn from(k: &Key) -> Self { - (*k).into() - } -} diff --git a/rog-aura/src/layouts.rs b/rog-aura/src/layouts.rs new file mode 100644 index 00000000..dfd0ed14 --- /dev/null +++ b/rog-aura/src/layouts.rs @@ -0,0 +1,554 @@ +//! A series of pre-defined layouts. These were mostly used to generate an +//! 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; + +use log::warn; +use serde::{Deserialize, Serialize}; + +use crate::advanced::LedCode; +use crate::aura_detection::LaptopLedData; +use crate::error::Error; +use crate::{AdvancedAuraType, AuraModeNum, AuraZone}; + +/// The `key_type` plays a role in effects (eventually). You could for example +/// add a `ShapeType::Spacing` to pad out an effect, such as a laserbeam across +/// a row so that it doesn't appear to *jump* across a gap +/// +/// w=1.0, h=1.0 should be considered the size of a typical key like 'A' +#[derive(Debug, Deserialize, Serialize, Clone)] +pub enum KeyShape { + Led { + width: f32, + height: f32, + pad_left: f32, + pad_right: f32, + pad_top: f32, + pad_bottom: f32, + }, + Blank { + width: f32, + height: f32, + }, +} + +impl KeyShape { + pub fn new_led( + width: f32, + height: f32, + pad_left: f32, + pad_right: f32, + pad_top: f32, + pad_bottom: f32, + ) -> Self { + Self::Led { + width, + height, + pad_left, + pad_right, + pad_top, + pad_bottom, + } + } + + pub fn new_blank(width: f32, height: f32) -> Self { + Self::Blank { width, height } + } + + /// Scale the shape up/down. Intended for use in UI on a clone + pub fn scale(&mut self, scale: f32) { + match self { + KeyShape::Led { + width, + height, + pad_left, + pad_right, + pad_top, + pad_bottom, + } => { + *width *= scale; + *height *= scale; + *pad_left *= scale; + *pad_right *= scale; + *pad_top *= scale; + *pad_bottom *= scale; + } + KeyShape::Blank { width, height } => { + *width *= scale; + *height *= scale; + } + } + } +} + +/// 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 +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct KeyRow { + pad_left: f32, + pad_top: f32, + /// The `Key` is what provides an RGB index location in the final USB + /// packets + row: Vec<(LedCode, String)>, + /// The final data structure merged key_shapes and rows + #[serde(skip)] + built_row: Vec<(LedCode, KeyShape)>, +} + +impl KeyRow { + pub fn new(pad_left: f32, pad_top: f32, row: Vec<(LedCode, String)>) -> Self { + Self { + pad_left, + pad_top, + row, + built_row: Default::default(), + } + } + + pub fn row(&self) -> Iter<'_, (LedCode, KeyShape)> { + self.built_row.iter() + } + + pub fn row_ref(&self) -> &[(LedCode, KeyShape)] { + &self.built_row + } + + /// Find and return the heightest height of this row + pub fn height(&self) -> f32 { + if self.built_row.is_empty() { + return 0.0; + } + let mut h = 0.0; + for k in &self.built_row { + let height = match &k.1 { + KeyShape::Led { + height, + pad_top, + pad_bottom, + .. + } => height + pad_top + pad_bottom, + KeyShape::Blank { height, .. } => *height, + }; + + if h < height { + h = height + } + } + h + } + + /// Return the total row width + pub fn width(&self) -> f32 { + if self.built_row.is_empty() { + return 0.0; + } + let mut w = 0.0; + for k in &self.built_row { + match &k.1 { + KeyShape::Led { + width, + pad_left, + pad_right, + .. + } => w += width + pad_left + pad_right, + KeyShape::Blank { width, .. } => w += width, + } + } + w + } +} + +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct KeyLayout { + /// Localization of this keyboard layout + locale: String, + /// The shapes of keys used + key_shapes: HashMap, + /// The rows of keys of this layout + key_rows: Vec, + /// Should be copied from the `LaptopLedData` as laptops may have the same + /// layout, but different EC features + #[serde(skip)] + basic_modes: Vec, + /// Should be copied from the `LaptopLedData` as laptops may have the same + /// layout, but different EC features + #[serde(skip)] + basic_zones: Vec, + /// Paired with the key selection in UI. Determines if individual keys are + /// selectable, zones, or single zone. + /// + /// Should be copied from the `LaptopLedData` as laptops may have the same + /// layout, but different EC features. + #[serde(skip)] + advanced_type: AdvancedAuraType, +} + +impl KeyLayout { + pub fn from_file(path: &Path) -> Result { + let mut file = OpenOptions::new() + .read(true) + .open(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 { + Err(Error::IoPath( + path.to_string_lossy().to_string(), + std::io::ErrorKind::InvalidData.into(), + )) + } else { + let mut data = ron::from_str::(&buf)?; + + let mut unused = HashSet::new(); + for k in data.key_shapes.keys() { + unused.insert(k); + } + + let rows = &mut data.key_rows; + for row in rows { + for k in &mut row.row { + if let Some(shape) = data.key_shapes.get(&k.1) { + row.built_row.push((k.0, shape.clone())); + unused.remove(&k.1); + } else { + warn!("Key {:?} was missing matching shape {}", k.0, k.1); + } + } + } + + if !unused.is_empty() { + warn!("The layout {path:?} had unused shapes {unused:?}",); + } + + Ok(data) + } + } + + pub fn rows(&self) -> Iter { + self.key_rows.iter() + } + + pub fn rows_ref(&self) -> &[KeyRow] { + &self.key_rows + } + + pub fn basic_modes(&self) -> &[AuraModeNum] { + &self.basic_modes + } + + pub fn basic_zones(&self) -> &[AuraZone] { + &self.basic_zones + } + + pub fn advanced_type(&self) -> &AdvancedAuraType { + &self.advanced_type + } + + pub fn max_height(&self) -> f32 { + let mut height = 0.0; + for r in &self.key_rows { + height += r.height(); + } + height + } + + pub fn max_width(&self) -> f32 { + let mut width = 0.0; + for r in &self.key_rows { + let tmp = r.width(); + if width < tmp { + width = tmp + } + } + width + } + + /// Find a layout matching the name in `LaptopLedData` in the provided dir + pub fn find_layout(led_data: LaptopLedData, mut data_path: PathBuf) -> Result { + // TODO: locales + let layout_file = format!("{}_US.ron", led_data.layout_name); + data_path.push("layouts"); + data_path.push(layout_file); + let path = data_path.as_path(); + + let mut tmp = KeyLayout::from_file(path)?; + tmp.basic_modes = led_data.basic_modes; + tmp.basic_zones = led_data.basic_zones; + tmp.advanced_type = led_data.advanced_type; + + Ok(tmp) + } + + pub fn layout_files(mut data_path: PathBuf) -> Result, Error> { + data_path.push("layouts"); + let path = data_path.as_path(); + let mut files = Vec::new(); + fs::read_dir(path) + .map_err(|e| { + println!("{:?}, {e}", path); + e + }) + .unwrap() + .for_each(|p| { + if let Ok(p) = p { + files.push(p.path()); + } + }); + + Ok(files) + } +} + +impl KeyLayout { + pub fn default_layout() -> Self { + Self { + locale: "US".to_owned(), + basic_modes: vec![ + AuraModeNum::Static, + AuraModeNum::Breathe, + AuraModeNum::Pulse, + ], + basic_zones: vec![AuraZone::None], + advanced_type: AdvancedAuraType::None, + key_shapes: HashMap::from([( + "regular".to_owned(), + KeyShape::new_led(1.0, 1.0, 0.1, 0.1, 0.1, 0.1), + )]), + key_rows: vec![ + KeyRow::new( + 0.1, + 0.1, + vec![ + (LedCode::Esc, "regular".to_owned()), + (LedCode::F1, "regular".to_owned()), + (LedCode::F2, "regular".to_owned()), + (LedCode::F3, "regular".to_owned()), + (LedCode::F4, "regular".to_owned()), + // not sure which key to put here + (LedCode::F5, "regular".to_owned()), + (LedCode::F6, "regular".to_owned()), + (LedCode::F7, "regular".to_owned()), + (LedCode::F8, "regular".to_owned()), + (LedCode::F9, "regular".to_owned()), + (LedCode::F10, "regular".to_owned()), + (LedCode::F11, "regular".to_owned()), + (LedCode::F12, "regular".to_owned()), + ], + ), + KeyRow::new( + 0.1, + 0.1, + vec![ + (LedCode::Tilde, "regular".to_owned()), + (LedCode::N1, "regular".to_owned()), + (LedCode::N2, "regular".to_owned()), + (LedCode::N3, "regular".to_owned()), + (LedCode::N4, "regular".to_owned()), + (LedCode::N5, "regular".to_owned()), + (LedCode::N6, "regular".to_owned()), + (LedCode::N7, "regular".to_owned()), + (LedCode::N8, "regular".to_owned()), + (LedCode::N9, "regular".to_owned()), + (LedCode::N0, "regular".to_owned()), + (LedCode::Hyphen, "regular".to_owned()), + (LedCode::Equals, "regular".to_owned()), + (LedCode::Backspace, "regular".to_owned()), + ], + ), + KeyRow::new( + 0.1, + 0.1, + vec![ + (LedCode::Tab, "regular".to_owned()), + (LedCode::Q, "regular".to_owned()), + (LedCode::W, "regular".to_owned()), + (LedCode::E, "regular".to_owned()), + (LedCode::R, "regular".to_owned()), + (LedCode::T, "regular".to_owned()), + (LedCode::Y, "regular".to_owned()), + (LedCode::U, "regular".to_owned()), + (LedCode::I, "regular".to_owned()), + (LedCode::O, "regular".to_owned()), + (LedCode::P, "regular".to_owned()), + (LedCode::LBracket, "regular".to_owned()), + (LedCode::RBracket, "regular".to_owned()), + (LedCode::BackSlash, "regular".to_owned()), + ], + ), + KeyRow::new( + 0.1, + 0.1, + vec![ + (LedCode::Caps, "regular".to_owned()), + (LedCode::A, "regular".to_owned()), + (LedCode::S, "regular".to_owned()), + (LedCode::D, "regular".to_owned()), + (LedCode::F, "regular".to_owned()), + (LedCode::G, "regular".to_owned()), + (LedCode::H, "regular".to_owned()), + (LedCode::J, "regular".to_owned()), + (LedCode::K, "regular".to_owned()), + (LedCode::L, "regular".to_owned()), + (LedCode::SemiColon, "regular".to_owned()), + (LedCode::Quote, "regular".to_owned()), + (LedCode::Return, "regular".to_owned()), + ], + ), + KeyRow::new( + 0.1, + 0.1, + vec![ + (LedCode::LShift, "regular".to_owned()), + (LedCode::Z, "regular".to_owned()), + (LedCode::X, "regular".to_owned()), + (LedCode::C, "regular".to_owned()), + (LedCode::V, "regular".to_owned()), + (LedCode::B, "regular".to_owned()), + (LedCode::N, "regular".to_owned()), + (LedCode::M, "regular".to_owned()), + (LedCode::Comma, "regular".to_owned()), + (LedCode::Period, "regular".to_owned()), + (LedCode::FwdSlash, "regular".to_owned()), + (LedCode::Rshift, "regular".to_owned()), + ], + ), + KeyRow::new( + 0.1, + 0.1, + vec![ + (LedCode::LCtrl, "regular".to_owned()), + (LedCode::LFn, "regular".to_owned()), + (LedCode::Meta, "regular".to_owned()), + (LedCode::LAlt, "regular".to_owned()), + (LedCode::Spacebar, "regular".to_owned()), + (LedCode::RAlt, "regular".to_owned()), + (LedCode::PrtSc, "regular".to_owned()), + (LedCode::RCtrl, "regular".to_owned()), + ], + ), + ], + } + } +} + +#[cfg(test)] +mod tests { + use std::collections::HashSet; + use std::fs::{self, OpenOptions}; + use std::io::Read; + use std::path::PathBuf; + + use crate::aura_detection::LedSupportFile; + use crate::layouts::KeyLayout; + + #[test] + fn check_parse_all() { + const DATA_DIR: &str = env!("CARGO_MANIFEST_DIR"); + let mut data_path = PathBuf::from(DATA_DIR); + + 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); + e + }) + .unwrap() + { + let path = p.unwrap().path(); + let mut file = OpenOptions::new().read(true).open(&path).unwrap(); + file.read_to_string(&mut buf).unwrap(); + + let data: KeyLayout = ron::from_str(&buf).unwrap(); + + let mut unused = HashSet::new(); + for k in data.key_shapes.keys() { + unused.insert(k); + } + + let rows = &data.key_rows; + for row in rows { + for k in &row.row { + if data.key_shapes.get(&k.1).is_some() { + unused.remove(&k.1); + } else { + panic!("Key {:?} was missing matching shape {}", k.0, k.1); + } + } + } + + if !unused.is_empty() { + panic!("The layout {path:?} had unused shapes {unused:?}",); + } + buf.clear(); + } + + // println!( + // "RON: {}", + // ron::ser::to_string_pretty(&tmp, + // PrettyConfig::new().depth_limit(4)).unwrap() ); + + // let mut data = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + // data.push("data/aura-support2.json"); + + // let mut file = + // OpenOptions::new().write(true).create(true).truncate(true).open(& + // data).unwrap(); file.write_all(json.as_bytes()).unwrap(); + } + + #[test] + fn check_layout_file_links() { + const DATA_DIR: &str = env!("CARGO_MANIFEST_DIR"); + let mut data_path = PathBuf::from(DATA_DIR); + 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 data: LedSupportFile = ron::from_str(&buf).unwrap(); + + data_path.pop(); + data_path.push("layouts"); + data_path.push("loop_prep"); + + for config in data.get().iter().rev() { + buf.clear(); + + let layout_file = format!("{}_US.ron", config.layout_name); + data_path.pop(); + data_path.push(&layout_file); + + let mut file = OpenOptions::new() + .read(true) + .open(&data_path) + .map_err(|e| { + panic!( + "Error checking {data_path:?} for {} : {e:?}", + config.board_name + ) + }) + .unwrap(); + if let Err(e) = file.read_to_string(&mut buf) { + panic!( + "Error checking {data_path:?} for {} : {e:?}", + config.board_name + ) + } + if let Err(e) = ron::from_str::(&buf) { + panic!("Error checking {data_path:?} : {e:?}") + } + } + } +} diff --git a/rog-aura/src/layouts/g513.rs b/rog-aura/src/layouts/g513.rs deleted file mode 100644 index bb347b08..00000000 --- a/rog-aura/src/layouts/g513.rs +++ /dev/null @@ -1,170 +0,0 @@ -use super::{KeyLayout, KeyRow}; -use crate::keys::Key; - -impl KeyLayout { - /// Similar to GX502, but not per-key enabled - pub fn g513_layout() -> Self { - Self { - matches: vec!["G513".into()], - locale: "US".to_owned(), - rows: vec![ - KeyRow::new( - 0.8, - vec![ - Key::NormalSpacer, - Key::FuncSpacer, - Key::VolDown, - Key::VolUp, - Key::MicMute, - Key::Fan, - Key::Rog, - ], - ), - KeyRow::new( - 0.8, - vec![ - Key::Esc, - Key::FuncSpacer, - Key::F1, - Key::F2, - Key::F3, - Key::F4, - Key::FuncSpacer, // not sure which key to put here - Key::F5, - Key::F6, - Key::F7, - Key::F8, - Key::FuncSpacer, - Key::F9, - Key::F10, - Key::F11, - Key::F12, - Key::RowEndSpacer, - Key::Del, - ], - ), - KeyRow::new( - 1.0, - vec![ - Key::Tilde, - Key::N1, - Key::N2, - Key::N3, - Key::N4, - Key::N5, - Key::N6, - Key::N7, - Key::N8, - Key::N9, - Key::N0, - Key::Hyphen, - Key::Equals, - Key::BkSpc, - Key::RowEndSpacer, - Key::Home, - ], - ), - KeyRow::new( - 1.0, - vec![ - Key::Tab, - Key::Q, - Key::W, - Key::E, - Key::R, - Key::T, - Key::Y, - Key::U, - Key::I, - Key::O, - Key::P, - Key::LBracket, - Key::RBracket, - Key::BackSlash, - Key::RowEndSpacer, - Key::PgUp, - ], - ), - KeyRow::new( - 1.0, - vec![ - Key::Caps, - Key::A, - Key::S, - Key::D, - Key::F, - Key::G, - Key::H, - Key::J, - Key::K, - Key::L, - Key::SemiColon, - Key::Quote, - Key::Return, - Key::RowEndSpacer, - Key::PgDn, - ], - ), - KeyRow::new( - 1.0, - vec![ - Key::LShift, - Key::Z, - Key::X, - Key::C, - Key::V, - Key::B, - Key::N, - Key::M, - Key::Comma, - Key::Period, - Key::FwdSlash, - Key::Rshift, - Key::RowEndSpacer, - Key::End, - ], - ), - KeyRow::new( - 1.0, - vec![ - Key::LCtrl, - Key::LFn, - Key::Meta, - Key::LAlt, - Key::Space, - Key::RAlt, - Key::PrtSc, - Key::RCtrl, - Key::ArrowSpacer, - Key::Up, - Key::ArrowSpacer, - Key::RowEndSpacer, - Key::RFn, - ], - ), - KeyRow::new( - 1.0, - vec![ - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::Left, - Key::Down, - Key::Right, - Key::ArrowSpacer, - ], - ), - ], - } - } -} diff --git a/rog-aura/src/layouts/ga401.rs b/rog-aura/src/layouts/ga401.rs deleted file mode 100644 index f44556aa..00000000 --- a/rog-aura/src/layouts/ga401.rs +++ /dev/null @@ -1,156 +0,0 @@ -use super::{KeyLayout, KeyRow}; -use crate::keys::Key; - -impl KeyLayout { - pub fn ga401_layout() -> Self { - Self { - matches: vec!["GA401".into(), "GA402".into()], - locale: "US".to_owned(), - rows: vec![ - KeyRow::new( - 0.8, - vec![ - Key::NormalSpacer, - Key::FuncSpacer, - Key::VolDown, - Key::VolUp, - Key::MicMute, - Key::Rog, - ], - ), - KeyRow::new( - 0.8, - vec![ - Key::Esc, - Key::FuncSpacer, - Key::F1, - Key::F2, - Key::F3, - Key::F4, - Key::FuncSpacer, // not sure which key to put here - Key::F5, - Key::F6, - Key::F7, - Key::F8, - Key::FuncSpacer, - Key::F9, - Key::F10, - Key::F11, - Key::F12, - ], - ), - KeyRow::new( - 1.0, - vec![ - Key::Tilde, - Key::N1, - Key::N2, - Key::N3, - Key::N4, - Key::N5, - Key::N6, - Key::N7, - Key::N8, - Key::N9, - Key::N0, - Key::Hyphen, - Key::Equals, - Key::BkSpc, - ], - ), - KeyRow::new( - 1.0, - vec![ - Key::Tab, - Key::Q, - Key::W, - Key::E, - Key::R, - Key::T, - Key::Y, - Key::U, - Key::I, - Key::O, - Key::P, - Key::LBracket, - Key::RBracket, - Key::BackSlash, - ], - ), - KeyRow::new( - 1.0, - vec![ - Key::Caps, - Key::A, - Key::S, - Key::D, - Key::F, - Key::G, - Key::H, - Key::J, - Key::K, - Key::L, - Key::SemiColon, - Key::Quote, - Key::Return, - ], - ), - KeyRow::new( - 1.0, - vec![ - Key::LShift, - Key::Z, - Key::X, - Key::C, - Key::V, - Key::B, - Key::N, - Key::M, - Key::Comma, - Key::Period, - Key::FwdSlash, - Key::Rshift, - ], - ), - KeyRow::new( - 1.0, - vec![ - Key::LCtrl, - Key::LFn, - Key::Meta, - Key::LAlt, - Key::Space, - Key::RAlt, - Key::PrtSc, - Key::RCtrl, - Key::ArrowSpacer, - Key::Up, - Key::ArrowSpacer, - ], - ), - KeyRow::new( - 1.2, - vec![ - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::Left, - Key::Down, - Key::Right, - Key::ArrowSpacer, - ], - ), - ], - } - } -} diff --git a/rog-aura/src/layouts/gx502.rs b/rog-aura/src/layouts/gx502.rs deleted file mode 100644 index 5b7fce6b..00000000 --- a/rog-aura/src/layouts/gx502.rs +++ /dev/null @@ -1,178 +0,0 @@ -use super::{KeyLayout, KeyRow}; -use crate::keys::Key; - -impl KeyLayout { - pub fn gx502_layout() -> Self { - Self { - matches: vec!["GX502".into(), "GU502".into()], - locale: "US".to_owned(), - rows: vec![ - KeyRow::new( - 0.8, - vec![ - Key::NormalSpacer, - Key::FuncSpacer, - Key::VolDown, - Key::VolUp, - Key::MicMute, - Key::Rog, - ], - ), - KeyRow::new( - 0.8, - vec![ - Key::Esc, - Key::FuncSpacer, - Key::F1, - Key::F2, - Key::F3, - Key::F4, - Key::FuncSpacer, // not sure which key to put here - Key::F5, - Key::F6, - Key::F7, - Key::F8, - Key::FuncSpacer, - Key::F9, - Key::F10, - Key::F11, - Key::F12, - Key::RowEndSpacer, - Key::Del, - ], - ), - KeyRow::new( - 1.0, - vec![ - Key::Tilde, - Key::N1, - Key::N2, - Key::N3, - Key::N4, - Key::N5, - Key::N6, - Key::N7, - Key::N8, - Key::N9, - Key::N0, - Key::Hyphen, - Key::Equals, - Key::BkSpc3_1, - Key::BkSpc3_2, - Key::BkSpc3_3, - Key::RowEndSpacer, - Key::Home, - ], - ), - KeyRow::new( - 1.0, - vec![ - Key::Tab, - Key::Q, - Key::W, - Key::E, - Key::R, - Key::T, - Key::Y, - Key::U, - Key::I, - Key::O, - Key::P, - Key::LBracket, - Key::RBracket, - Key::BackSlash, - Key::RowEndSpacer, - Key::PgUp, - ], - ), - KeyRow::new( - 1.0, - vec![ - Key::Caps, - Key::A, - Key::S, - Key::D, - Key::F, - Key::G, - Key::H, - Key::J, - Key::K, - Key::L, - Key::SemiColon, - Key::Quote, - Key::Return3_1, - Key::Return3_2, - Key::Return3_3, - Key::RowEndSpacer, - Key::PgDn, - ], - ), - KeyRow::new( - 1.0, - vec![ - Key::LShift, - Key::Z, - Key::X, - Key::C, - Key::V, - Key::B, - Key::N, - Key::M, - Key::Comma, - Key::Period, - Key::FwdSlash, - Key::Rshift3_1, - Key::Rshift3_2, - Key::Rshift3_3, - Key::RowEndSpacer, - Key::End, - ], - ), - KeyRow::new( - 1.0, - vec![ - Key::LCtrl, - Key::LFn, - Key::Meta, - Key::LAlt, - Key::Space5_1, - Key::Space5_2, - Key::Space5_3, - Key::Space5_4, - Key::Space5_5, - Key::RAlt, - Key::PrtSc, - Key::RCtrl, - Key::ArrowSpacer, - Key::Up, - Key::ArrowSpacer, - Key::RowEndSpacer, - Key::RFn, - ], - ), - KeyRow::new( - 1.0, - vec![ - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::ArrowSpacer, - Key::Left, - Key::Down, - Key::Right, - Key::ArrowSpacer, - ], - ), - ], - } - } -} diff --git a/rog-aura/src/layouts/mod.rs b/rog-aura/src/layouts/mod.rs deleted file mode 100644 index f25656da..00000000 --- a/rog-aura/src/layouts/mod.rs +++ /dev/null @@ -1,105 +0,0 @@ -//! A series of pre-defined layouts. These were mostly used to generate an editable -//! config. - -/// Hardcoded layout. Was used to generate a toml default -pub mod g513; -/// Hardcoded layout. Was used to generate a toml default -pub mod ga401; -/// Hardcoded layout. Was used to generate a toml default -pub mod gx502; - -use crate::{error::Error, keys::Key}; -use serde::{Deserialize, Serialize}; -use std::{ - fs::{self, OpenOptions}, - io::Read, - path::{Path, PathBuf}, - slice::Iter, -}; - -#[derive(Debug, Deserialize, Serialize, Clone)] -pub struct KeyLayout { - /// A series of board names that this layout can be used for. The board names - /// stored with the layout can be globbed, e.g, GA401 will match all of the - /// GA401I and GA401Q range variants. - /// - /// `/sys/class/dmi/id/board_name` - matches: Vec, - locale: String, - rows: Vec, -} - -impl KeyLayout { - pub fn from_file(path: &Path) -> Result { - let mut file = OpenOptions::new().read(true).open(path)?; - let mut buf = String::new(); - let read_len = file.read_to_string(&mut buf)?; - if read_len == 0 { - Err(Error::Io(std::io::ErrorKind::InvalidData.into())) - } else { - Ok(toml::from_str::(&buf)?) - } - } - - pub fn matches(&self, board_name: &str) -> bool { - let board = board_name.to_ascii_uppercase(); - for tmp in &self.matches { - if board.contains(tmp.as_str()) { - return true; - } - } - false - } - - pub fn rows(&self) -> Iter { - self.rows.iter() - } - - pub fn rows_ref(&self) -> &[KeyRow] { - &self.rows - } - - /// Find a layout matching the provided board name in the provided dir - pub fn find_layout(board_name: &str, mut data_path: PathBuf) -> Result { - let mut layout = KeyLayout::ga401_layout(); // default - - data_path.push("layouts"); - let path = data_path.as_path(); - for p in fs::read_dir(path).map_err(|e| { - println!("{:?}, {e}", path); - e - })? { - let tmp = KeyLayout::from_file(&p?.path()).unwrap(); - if tmp.matches(board_name) { - layout = tmp; - break; - } - } - - Ok(layout) - } -} - -#[derive(Debug, Deserialize, Serialize, Clone)] -pub struct KeyRow { - height: f32, - row: Vec, -} - -impl KeyRow { - pub fn new(height: f32, row: Vec) -> Self { - Self { height, row } - } - - pub fn row(&self) -> Iter<'_, Key> { - self.row.iter() - } - - pub fn row_ref(&self) -> &[Key] { - &self.row - } - - pub fn height(&self) -> f32 { - self.height - } -} diff --git a/rog-aura/src/layouts/old_gx502.rs b/rog-aura/src/layouts/old_gx502.rs deleted file mode 100644 index c142a1b1..00000000 --- a/rog-aura/src/layouts/old_gx502.rs +++ /dev/null @@ -1,168 +0,0 @@ - -#[allow(clippy::upper_case_acronyms)] -pub struct GX502Layout(Vec<[Key; 17]>); - -impl KeyLayout for GX502Layout { - fn get_rows(&self) -> &Vec<[Key; 17]> { - &self.0 - } -} - -impl Default for GX502Layout { - fn default() -> Self { - GX502Layout(vec![ - [ - Key::NormalSpacer, - Key::FuncSpacer, - Key::VolDown, - Key::VolUp, - Key::MicMute, - Key::Rog, - Key::NormalBlank, - Key::NormalBlank, - Key::NormalBlank, - Key::NormalBlank, - Key::NormalBlank, - Key::NormalBlank, - Key::NormalBlank, - Key::NormalBlank, - Key::NormalBlank, - Key::NormalBlank, - Key::NormalBlank, - ], - [ - Key::Esc, - Key::NormalBlank, - Key::F1, - Key::F2, - Key::F3, - Key::F4, - Key::NormalBlank, // not sure which key to put here - Key::F5, - Key::F6, - Key::F7, - Key::F8, - Key::NormalBlank, - Key::F9, - Key::F10, - Key::F11, - Key::F12, - Key::Del, - ], - [ - Key::Tilde, - Key::N1, - Key::N2, - Key::N3, - Key::N4, - Key::N5, - Key::N6, - Key::N7, - Key::N8, - Key::N9, - Key::N0, - Key::Hyphen, - Key::Equals, - Key::BkSpc3_1, - Key::BkSpc3_2, - Key::BkSpc3_3, - Key::Home, - ], - [ - Key::Tab, - Key::Q, - Key::W, - Key::E, - Key::R, - Key::T, - Key::Y, - Key::U, - Key::I, - Key::O, - Key::P, - Key::LBracket, - Key::RBracket, - Key::BackSlash, - Key::BackSlash, - Key::BackSlash, - Key::PgUp, - ], - [ - Key::Caps, - Key::A, - Key::S, - Key::D, - Key::F, - Key::G, - Key::H, - Key::J, - Key::K, - Key::L, - Key::SemiColon, - Key::Quote, - Key::Quote, - Key::Return3_1, - Key::Return3_2, - Key::Return3_3, - Key::PgDn, - ], - [ - Key::LShift, - Key::LShift, - Key::Z, - Key::X, - Key::C, - Key::V, - Key::B, - Key::N, - Key::M, - Key::Comma, - Key::Period, - Key::FwdSlash, - Key::FwdSlash, - Key::Rshift3_1, - Key::Rshift3_2, - Key::Rshift3_3, - Key::End, - ], - [ - Key::LCtrl, - Key::LFn, - Key::Meta, - Key::LAlt, - Key::Space5_1, - Key::Space5_2, - Key::Space5_3, - Key::Space5_4, - Key::Space5_5, - Key::RAlt, - Key::PrtSc, - Key::RCtrl, - Key::RCtrl, - Key::Left, - Key::Up, - Key::Right, - Key::RFn, - ], - [ - Key::NormalBlank, - Key::NormalBlank, - Key::NormalBlank, - Key::NormalBlank, - Key::NormalBlank, - Key::NormalBlank, - Key::NormalBlank, - Key::NormalBlank, - Key::NormalBlank, - Key::NormalBlank, - Key::NormalBlank, - Key::NormalBlank, - Key::NormalBlank, - Key::Left, - Key::Down, - Key::Right, - Key::NormalBlank, - ], - ]) - } -} \ No newline at end of file diff --git a/rog-aura/src/lib.rs b/rog-aura/src/lib.rs index bc9e530c..232662cd 100644 --- a/rog-aura/src/lib.rs +++ b/rog-aura/src/lib.rs @@ -1,21 +1,20 @@ -/// A container of images/grids/gifs/pauses which can be iterated over to generate -/// cool effects -mod sequencer; -pub use sequencer::*; - mod builtin_modes; +use advanced::LedCode; pub use builtin_modes::*; -mod per_key_rgb; -pub use per_key_rgb::*; - -mod per_zone; -pub use per_zone::*; +/// A container of images/grids/gifs/pauses which can be iterated over to +/// generate cool effects +pub mod effects; +/// All handling for `RgbAddress`ing. +pub mod advanced; +/// Convert the `RgbAddress` to `&str` labels +pub mod advanced_to_str; pub mod error; -pub mod key_to_str; -pub mod keys; -pub use key_to_str::*; +pub use advanced_to_str::*; +/// Helper for detecting what is available +pub mod aura_detection; +/// Helpers for consructing keyboard layouts for UI use and effects pub mod layouts; pub mod usb; @@ -25,8 +24,18 @@ pub const VERSION: &str = env!("CARGO_PKG_VERSION"); pub const RED: Colour = Colour(0xff, 0x00, 0x00); pub const GREEN: Colour = Colour(0x00, 0xff, 0x00); pub const BLUE: Colour = Colour(0x00, 0x00, 0xff); -pub const VIOLET: Colour = Colour(0x9B, 0x26, 0xB6); -pub const TEAL: Colour = Colour(0x00, 0x7C, 0x80); +pub const VIOLET: Colour = Colour(0x9b, 0x26, 0xb6); +pub const TEAL: Colour = Colour(0x00, 0x7c, 0x80); pub const YELLOW: Colour = Colour(0xff, 0xef, 0x00); pub const ORANGE: Colour = Colour(0xff, 0xa4, 0x00); pub const GRADIENT: [Colour; 7] = [RED, VIOLET, BLUE, TEAL, GREEN, YELLOW, ORANGE]; + +#[derive(Debug, Clone, PartialEq, Eq, Default, serde::Deserialize, serde::Serialize)] +pub enum AdvancedAuraType { + /// A `None` will apply the effect to the whole keyboard via basic-static + /// mode + #[default] + None, + Zoned(Vec), + PerKey, +} diff --git a/rog-aura/src/per_key_rgb.rs b/rog-aura/src/per_key_rgb.rs deleted file mode 100644 index 7ea76678..00000000 --- a/rog-aura/src/per_key_rgb.rs +++ /dev/null @@ -1,247 +0,0 @@ -use crate::keys::Key; -use serde_derive::{Deserialize, Serialize}; -#[cfg(feature = "dbus")] -use zbus::zvariant::Type; - -/// Represents the per-key raw USB packets -pub type PerKeyRaw = Vec>; - -/// A `KeyColourArray` contains all data to change the full set of keyboard -/// key colours individually. -/// -/// Each row of the internal array is a full HID packet that can be sent -/// to the keyboard EC. One row controls one group of keys, these keys are not -/// necessarily all on the same row of the keyboard, with some splitting between -/// two rows. -#[cfg_attr(feature = "dbus", derive(Type))] -#[derive(Debug, Clone, Deserialize, Serialize)] -pub struct KeyColourArray(PerKeyRaw); - -impl Default for KeyColourArray { - fn default() -> Self { - Self::new() - } -} - -impl KeyColourArray { - pub fn new() -> Self { - let mut set = vec![vec![0u8; 64]; 11]; - // set[0].copy_from_slice(&KeyColourArray::get_init_msg()); - for (count, row) in set.iter_mut().enumerate() { - row[0] = 0x5d; // Report ID - row[1] = 0xbc; // Mode = custom??, 0xb3 is builtin - row[2] = 0x00; - row[3] = 0x01; // ?? - row[4] = 0x01; // ??, 4,5,6 are normally RGB for builtin mode colours - row[5] = 0x01; // ?? - row[6] = (count as u8) << 4; // Key group - if count == 10 { - row[7] = 0x08; // 0b00001000 - } else { - row[7] = 0x10; // 0b00010000 addressing? flips for group a0 - } - row[8] = 0x00; - } - KeyColourArray(set) - } - - /// Initialise and clear the keyboard for custom effects, this must be done for - /// every time mode switches from builtin to custom - #[inline] - pub const fn get_init_msg() -> [u8; 64] { - let mut init = [0u8; 64]; - init[0] = 0x5d; // Report ID - init[1] = 0xbc; // Mode = custom??, 0xb3 is builtin - init - } - - #[inline] - pub fn set(&mut self, key: Key, r: u8, g: u8, b: u8) { - if let Some(c) = self.rgb_for_key(key) { - c[0] = r; - c[1] = g; - c[2] = b; - } - } - - /// Indexes in to `KeyColourArray` at the correct row and column - /// to set a series of three bytes to the chosen R,G,B values - pub fn rgb_for_key(&mut self, key: Key) -> Option<&mut [u8]> { - // Tuples are indexes in to array - let (row, col) = match key { - Key::VolDown => (0, 15), - Key::VolUp => (0, 18), - Key::MicMute => (0, 21), - Key::Rog => (0, 24), - // - Key::Esc => (1, 24), - Key::F1 => (1, 30), - Key::F2 => (1, 33), - Key::F3 => (1, 36), - Key::F4 => (1, 39), - Key::F5 => (1, 45), - Key::F6 => (1, 48), - Key::F7 => (1, 51), - Key::F8 => (1, 54), - // - Key::F9 => (2, 12), - Key::F10 => (2, 15), - Key::F11 => (2, 18), - Key::F12 => (2, 21), - Key::Del => (2, 24), - Key::Tilde => (2, 39), - Key::N1 => (2, 42), - Key::N2 => (2, 45), - Key::N3 => (2, 48), - Key::N4 => (2, 51), - Key::N5 => (2, 54), - // - Key::N6 => (3, 9), - Key::N7 => (3, 12), - Key::N8 => (3, 15), - Key::N9 => (3, 18), - Key::N0 => (3, 21), - Key::Hyphen => (3, 24), - Key::Equals => (3, 27), - Key::BkSpc3_1 => (3, 30), - Key::BkSpc3_2 => (3, 33), - Key::BkSpc3_3 => (3, 36), - Key::Home => (3, 39), - Key::Tab => (3, 54), - // - Key::Q => (4, 9), - Key::W => (4, 12), - Key::E => (4, 15), - Key::R => (4, 18), - Key::T => (4, 21), - Key::Y => (4, 24), - Key::U => (4, 27), - Key::I => (4, 30), - Key::O => (4, 33), - Key::P => (4, 36), - Key::LBracket => (4, 39), - Key::RBracket => (4, 42), - Key::BackSlash => (4, 45), - Key::PgUp => (4, 54), - // - Key::Caps => (5, 21), - Key::A => (5, 24), - Key::S => (5, 27), - Key::D => (5, 30), - Key::F => (5, 33), - Key::G => (5, 36), - Key::H => (5, 39), - Key::J => (5, 42), - Key::K => (5, 45), - Key::L => (5, 48), - Key::SemiColon => (5, 51), - Key::Quote => (5, 54), - // - Key::Return => (6, 9), - Key::Return3_1 => (6, 12), - Key::Return3_2 => (6, 15), - Key::Return3_3 => (6, 18), - Key::PgDn => (6, 21), - Key::LShift => (6, 36), - // TODO: Find correct locations - Key::LShift3_1 => (6, 36), - Key::LShift3_2 => (6, 36), - Key::LShift3_3 => (6, 36), - Key::Z => (6, 42), - Key::X => (6, 45), - Key::C => (6, 48), - Key::V => (6, 51), - Key::B => (6, 54), - // - Key::N => (7, 9), - Key::M => (7, 12), - Key::Comma => (7, 15), - Key::Period => (7, 18), - Key::FwdSlash => (7, 21), - Key::Rshift => (7, 24), - Key::Rshift3_1 => (7, 27), - Key::Rshift3_2 => (7, 30), - Key::Rshift3_3 => (7, 33), - Key::End => (7, 36), - Key::LCtrl => (7, 51), - Key::LFn => (7, 54), - // - Key::Meta => (8, 9), - Key::LAlt => (8, 12), - Key::Space5_1 => (8, 15), - Key::Space5_2 => (8, 18), - Key::Space5_3 => (8, 21), - Key::Space5_4 => (8, 24), - Key::Space5_5 => (8, 27), - Key::RAlt => (8, 30), - Key::PrtSc => (8, 33), - Key::RCtrl => (8, 36), - Key::Up => (8, 42), - Key::RFn => (8, 51), - // - Key::Left => (9, 54), - // - Key::Down => (10, 9), - Key::Right => (10, 12), - Key::NormalBlank - | Key::FuncBlank - | Key::NormalSpacer - | Key::FuncSpacer - | Key::ArrowBlank - | Key::ArrowSpacer - | Key::UpRegular - | Key::DownRegular - | Key::LeftRegular - | Key::RightRegular - | Key::UpSplit - | Key::DownSplit - | Key::LeftSplit - | Key::RightSplit - | Key::ArrowRegularBlank - | Key::ArrowRegularSpacer - | Key::ArrowSplitBlank - | Key::ArrowSplitSpacer - | Key::RshiftSmall - | Key::LCtrlMed - | Key::MediaPlay - | Key::MediaStop - | Key::MediaPrev - | Key::MediaNext - | Key::Pause - | Key::NumLock - | Key::Star - | Key::NumPadDel - | Key::NumPadPlus - | Key::NumPadEnter - | Key::NumPadPause - | Key::NumPadPrtSc - | Key::NumPadHome - | Key::RCtrlLarge - | Key::RowEndSpacer => return None, - Key::Fan | Key::Space | Key::BkSpc => return None, - }; - - Some(&mut self.0[row][col..=col + 2]) - } - - #[inline] - pub fn get(&self) -> PerKeyRaw { - self.0.clone() - } - - #[inline] - pub fn get_ref(&self) -> &PerKeyRaw { - &self.0 - } - - #[inline] - pub fn get_mut(&mut self) -> &mut PerKeyRaw { - &mut self.0 - } -} - -impl From for PerKeyRaw { - fn from(k: KeyColourArray) -> Self { - k.0 - } -} diff --git a/rog-aura/src/per_zone.rs b/rog-aura/src/per_zone.rs deleted file mode 100644 index b743c995..00000000 --- a/rog-aura/src/per_zone.rs +++ /dev/null @@ -1,123 +0,0 @@ -use serde_derive::{Deserialize, Serialize}; -#[cfg(feature = "dbus")] -use zbus::zvariant::Type; - -/// Represents the zoned raw USB packets -pub type ZonedRaw = Vec; - -#[derive(Debug, Clone, Copy, Deserialize, Serialize)] -pub enum PerZone { - None, - KeyboardLeft, - KeyboardCenterLeft, - KeyboardCenterRight, - KeyboardRight, - LightbarRight, - LightbarRightCorner, - LightbarRightBottom, - LightbarLeftBottom, - LightbarLeftCorner, - LightbarLeft, -} - -#[cfg_attr(feature = "dbus", derive(Type))] -#[derive(Debug, Clone, Deserialize, Serialize)] -pub struct ZonedColourArray(ZonedRaw); - -impl Default for ZonedColourArray { - fn default() -> Self { - Self::new() - } -} - -impl ZonedColourArray { - pub fn new() -> Self { - let mut pkt = vec![0u8; 64]; - pkt[0] = 0x5d; // Report ID - pkt[1] = 0xbc; // Mode = custom??, 0xb3 is builtin - pkt[2] = 0x01; - pkt[3] = 0x01; // ?? - pkt[4] = 0x04; // ??, 4,5,6 are normally RGB for builtin mode colours - ZonedColourArray(pkt) - } - - pub fn rgb_for_zone(&mut self, zone: PerZone) -> &mut [u8] { - match zone { - PerZone::None | PerZone::KeyboardLeft => &mut self.0[9..=11], - PerZone::KeyboardCenterLeft => &mut self.0[12..=14], - PerZone::KeyboardCenterRight => &mut self.0[15..=17], - PerZone::KeyboardRight => &mut self.0[18..=20], - // Two sections missing here? - PerZone::LightbarRight => &mut self.0[27..=29], - PerZone::LightbarRightCorner => &mut self.0[30..=32], - PerZone::LightbarRightBottom => &mut self.0[33..=35], - PerZone::LightbarLeftBottom => &mut self.0[36..=38], - PerZone::LightbarLeftCorner => &mut self.0[39..=41], - PerZone::LightbarLeft => &mut self.0[42..=44], - } - } - - #[inline] - pub fn get(&self) -> ZonedRaw { - self.0.clone() - } - - #[inline] - pub fn get_ref(&self) -> &ZonedRaw { - &self.0 - } - - #[inline] - pub fn get_mut(&mut self) -> &mut ZonedRaw { - &mut self.0 - } -} - -impl From for ZonedRaw { - fn from(k: ZonedColourArray) -> Self { - k.0 - } -} - -#[cfg(test)] -mod tests { - use crate::{PerZone, ZonedColourArray, ZonedRaw}; - - macro_rules! colour_check { - ($zone:expr, $pkt_idx_start:expr) => { - let mut zone = ZonedColourArray::new(); - let c = zone.rgb_for_zone($zone); - c[0] = 255; - c[1] = 255; - c[2] = 255; - - let pkt: ZonedRaw = zone.get(); - assert_eq!(pkt[$pkt_idx_start], 0xff); - assert_eq!(pkt[$pkt_idx_start + 1], 0xff); - assert_eq!(pkt[$pkt_idx_start + 2], 0xff); - }; - } - - #[test] - fn zone_to_packet_check() { - let zone = ZonedColourArray::new(); - let pkt: ZonedRaw = zone.into(); - assert_eq!(pkt[0], 0x5d); - assert_eq!(pkt[1], 0xbc); - assert_eq!(pkt[2], 0x01); - assert_eq!(pkt[3], 0x01); - assert_eq!(pkt[4], 0x04); - - colour_check!(PerZone::KeyboardLeft, 9); - colour_check!(PerZone::KeyboardCenterLeft, 12); - colour_check!(PerZone::KeyboardCenterRight, 15); - colour_check!(PerZone::KeyboardRight, 18); - - colour_check!(PerZone::LightbarRight, 27); - colour_check!(PerZone::LightbarRightCorner, 30); - colour_check!(PerZone::LightbarRightBottom, 33); - colour_check!(PerZone::LightbarLeftBottom, 36); - colour_check!(PerZone::LightbarLeftCorner, 39); - colour_check!(PerZone::LightbarLeft, 42); - } -} diff --git a/rog-aura/src/sequencer/effects.rs b/rog-aura/src/sequencer/effects.rs deleted file mode 100644 index 74bfde2a..00000000 --- a/rog-aura/src/sequencer/effects.rs +++ /dev/null @@ -1,250 +0,0 @@ -use crate::{layouts::KeyLayout, p_random, Colour, EffectState, LedType, Speed}; -use serde_derive::{Deserialize, Serialize}; - -macro_rules! effect_state_impl { - () => { - fn get_colour(&self) -> Colour { - self.colour - } - - fn get_led_type(&self) -> LedType { - self.led_type.clone() - } - - /// Change the led type - fn set_led_type(&mut self, led_type: LedType) { - self.led_type = led_type; - } - }; -} - -macro_rules! effect_impl { - ($($effect:ident),*) => { - impl Effect { - /// Get the type of LED set - pub fn get_led_type(&self) -> LedType { - match self { - $(Effect::$effect(c) => c.get_led_type(),)* - } - } - - /// Change the led type - pub fn set_led_type(&mut self, led_type: LedType) { - match self { - $(Effect::$effect(c) => c.set_led_type(led_type),)* - } - } - - /// Calculate the next state of the effect - pub fn next_state(&mut self, layout: &KeyLayout) { - match self { - $(Effect::$effect(c) => c.next_colour_state(layout),)* - } - } - - /// Get the calculated colour - pub fn get_colour(&self) -> Colour { - match self { - $(Effect::$effect(c) => c.get_colour(),)* - } - } - } - }; -} - -/**************************************************************************************************/ - -#[derive(Debug, Clone, Deserialize, Serialize)] -pub enum Effect { - Static(Static), - Breathe(Breathe), - Flicker(Flicker), -} - -impl Default for Effect { - fn default() -> Self { - Self::Static(Static::new(LedType::default(), Colour::default())) - } -} - -effect_impl!(Static, Breathe, Flicker); - -/**************************************************************************************************/ - -#[derive(Debug, Clone, Deserialize, Serialize)] -pub struct Static { - led_type: LedType, - /// The starting colour - colour: Colour, -} - -impl Static { - pub fn new(led_type: LedType, colour: Colour) -> Self { - Self { led_type, colour } - } -} - -impl EffectState for Static { - fn next_colour_state(&mut self, _layout: &KeyLayout) {} - - effect_state_impl!(); -} - -/**************************************************************************************************/ - -#[derive(Debug, Clone, Deserialize, Serialize)] -pub struct Breathe { - led_type: LedType, - /// The starting colour - start_colour1: Colour, - /// The secondary starting colour - start_colour2: Colour, - /// The speed at which to cycle between the colours - speed: Speed, - /// Temporary data to help keep state - #[serde(skip)] - colour: Colour, - #[serde(skip)] - count_flipped: bool, - #[serde(skip)] - use_colour1: bool, -} - -impl Breathe { - pub fn new(led_type: LedType, colour1: Colour, colour2: Colour, speed: Speed) -> Self { - Self { - led_type, - start_colour1: colour1, - start_colour2: colour2, - speed, - colour: colour1, - count_flipped: false, - use_colour1: true, - } - } -} - -impl EffectState for Breathe { - fn next_colour_state(&mut self, _layout: &KeyLayout) { - let Self { - start_colour1: colour1, - start_colour2: colour2, - speed, - colour: colour_actual, - count_flipped: flipped, - use_colour1, - .. - } = self; - - let speed = 4 - ::from(*speed); - - if *colour_actual == Colour(0, 0, 0) { - *use_colour1 = !*use_colour1; - } - - let colour = if !*use_colour1 { colour2 } else { colour1 }; - - let r1_scale = colour.0 / speed / 2; - let g1_scale = colour.1 / speed / 2; - let b1_scale = colour.2 / speed / 2; - - if *colour_actual == Colour(0, 0, 0) { - *flipped = true; - } else if colour_actual >= colour { - *flipped = false; - } - - if !*flipped { - colour_actual.0 = colour_actual.0.saturating_sub(r1_scale); - colour_actual.1 = colour_actual.1.saturating_sub(g1_scale); - colour_actual.2 = colour_actual.2.saturating_sub(b1_scale); - } else { - colour_actual.0 = colour_actual.0.saturating_add(r1_scale); - colour_actual.1 = colour_actual.1.saturating_add(g1_scale); - colour_actual.2 = colour_actual.2.saturating_add(b1_scale); - } - } - - effect_state_impl!(); -} - -/**************************************************************************************************/ - -#[derive(Debug, Clone, Deserialize, Serialize)] -pub struct Flicker { - led_type: LedType, - start_colour: Colour, - max_percentage: u8, - min_percentage: u8, - #[serde(skip)] - count: u8, - #[serde(skip)] - colour: Colour, -} - -impl Flicker { - pub fn new(led_type: LedType, colour: Colour, max_percentage: u8, min_percentage: u8) -> Self { - Self { - led_type, - colour, - count: 4, - max_percentage, - min_percentage, - start_colour: colour, - } - } -} - -impl EffectState for Flicker { - fn next_colour_state(&mut self, _layout: &KeyLayout) { - let Self { - max_percentage, - min_percentage, - colour, - start_colour, - .. - } = self; - - if self.count == 0 { - self.count = 4; - } - self.count -= 1; - if self.count != 0 { - return; - } - - // TODO: make a "percentage" method on Colour. - let max_light = Colour( - (start_colour.0 as f32 / 100.0 * *max_percentage as f32) as u8, - (start_colour.1 as f32 / 100.0 * *max_percentage as f32) as u8, - (start_colour.2 as f32 / 100.0 * *max_percentage as f32) as u8, - ); - // min light is a percentage of the set colour - let min_light = Colour( - (start_colour.0 as f32 / 100.0 * *min_percentage as f32) as u8, - (start_colour.1 as f32 / 100.0 * *min_percentage as f32) as u8, - (start_colour.2 as f32 / 100.0 * *min_percentage as f32) as u8, - ); - - // Convert the 255 to percentage - let amount = (p_random() & 7) as f32 * 8.0; - - let set_colour = |colour: &mut u8, max: f32, min: f32| { - let pc = amount / max * 100.0; - let min_amount = pc * min / 100.0; // percentage of min colour - let max_amount = pc * max / 100.0; // percentage of max colour - if *colour as f32 - min_amount < min { - *colour = min as u8; - } else { - *colour = (max - max_amount) as u8; - } - }; - set_colour(&mut colour.0, max_light.0 as f32, min_light.0 as f32); - set_colour(&mut colour.1, max_light.1 as f32, min_light.1 as f32); - set_colour(&mut colour.2, max_light.2 as f32, min_light.2 as f32); - - self.count = 4; - } - - effect_state_impl!(); -} diff --git a/rog-aura/src/sequencer/mod.rs b/rog-aura/src/sequencer/mod.rs deleted file mode 100644 index 9882dc4a..00000000 --- a/rog-aura/src/sequencer/mod.rs +++ /dev/null @@ -1,219 +0,0 @@ -mod effects; -pub use effects::*; - -use crate::{ - keys::Key, layouts::KeyLayout, Colour, KeyColourArray, PerKeyRaw, PerZone, ZonedColourArray, -}; -use serde_derive::{Deserialize, Serialize}; - -// static mut RNDINDEX: usize = 0; -static mut PRNDINDEX: usize = 0; - -/// Pseudo random table ripped straight out of room4doom -pub const RNDTABLE: [i32; 256] = [ - 0, 8, 109, 220, 222, 241, 149, 107, 75, 248, 254, 140, 16, 66, 74, 21, 211, 47, 80, 242, 154, - 27, 205, 128, 161, 89, 77, 36, 95, 110, 85, 48, 212, 140, 211, 249, 22, 79, 200, 50, 28, 188, - 52, 140, 202, 120, 68, 145, 62, 70, 184, 190, 91, 197, 152, 224, 149, 104, 25, 178, 252, 182, - 202, 182, 141, 197, 4, 81, 181, 242, 145, 42, 39, 227, 156, 198, 225, 193, 219, 93, 122, 175, - 249, 0, 175, 143, 70, 239, 46, 246, 163, 53, 163, 109, 168, 135, 2, 235, 25, 92, 20, 145, 138, - 77, 69, 166, 78, 176, 173, 212, 166, 113, 94, 161, 41, 50, 239, 49, 111, 164, 70, 60, 2, 37, - 171, 75, 136, 156, 11, 56, 42, 146, 138, 229, 73, 146, 77, 61, 98, 196, 135, 106, 63, 197, 195, - 86, 96, 203, 113, 101, 170, 247, 181, 113, 80, 250, 108, 7, 255, 237, 129, 226, 79, 107, 112, - 166, 103, 241, 24, 223, 239, 120, 198, 58, 60, 82, 128, 3, 184, 66, 143, 224, 145, 224, 81, - 206, 163, 45, 63, 90, 168, 114, 59, 33, 159, 95, 28, 139, 123, 98, 125, 196, 15, 70, 194, 253, - 54, 14, 109, 226, 71, 17, 161, 93, 186, 87, 244, 138, 20, 52, 123, 251, 26, 36, 17, 46, 52, - 231, 232, 76, 31, 221, 84, 37, 216, 165, 212, 106, 197, 242, 98, 43, 39, 175, 254, 145, 190, - 84, 118, 222, 187, 136, 120, 163, 236, 249, -]; - -pub fn p_random() -> i32 { - unsafe { - PRNDINDEX = (PRNDINDEX + 1) & 0xFF; - RNDTABLE[PRNDINDEX] - } -} - -pub(crate) trait EffectState { - /// Calculate the next colour state - fn next_colour_state(&mut self, _layout: &KeyLayout); - - /// Return the resulting colour. Implementers should store the colour to return it. - fn get_colour(&self) -> Colour; - - fn get_led_type(&self) -> LedType; - - fn set_led_type(&mut self, led_type: LedType); -} - -#[derive(Debug, Clone, Deserialize, Serialize)] -pub enum LedType { - Key(Key), - Zone(PerZone), -} - -impl Default for LedType { - fn default() -> Self { - Self::Zone(PerZone::None) - } -} - -#[derive(Debug, Deserialize, Serialize, Default)] -pub struct Sequences(Vec); - -impl Sequences { - #[inline] - pub fn new() -> Self { - Self(Vec::new()) - } - - #[inline] - pub fn push(&mut self, action: Effect) { - self.0.push(action); - } - - #[inline] - pub fn insert(&mut self, index: usize, action: Effect) { - self.0.insert(index, action); - } - - /// Remove an item at this position from the run buffer. If the `index` supplied - /// is not in range then `None` is returned, otherwise the `ActionData` at that location - /// is yeeted and returned. - #[inline] - pub fn remove_item(&mut self, index: usize) -> Option { - if index < self.0.len() { - return Some(self.0.remove(index)); - } - None - } - - pub fn next_state(&mut self, layout: &KeyLayout) { - for effect in &mut self.0 { - effect.next_state(layout); - } - } - - pub fn create_packets(&self) -> PerKeyRaw { - let mut keys = KeyColourArray::new(); - let mut zones = ZonedColourArray::new(); - let mut is_per_key = false; - for effect in &self.0 { - match effect.get_led_type() { - LedType::Key(key) => { - is_per_key = true; - if let Some(rgb) = keys.rgb_for_key(key) { - let c = effect.get_colour(); - rgb[0] = c.0; - rgb[1] = c.1; - rgb[2] = c.2; - } - } - LedType::Zone(z) => { - let rgb = zones.rgb_for_zone(z); - let c = effect.get_colour(); - rgb[0] = c.0; - rgb[1] = c.1; - rgb[2] = c.2; - } - } - } - if is_per_key { - keys.into() - } else { - vec![zones.into()] - } - } -} - -#[cfg(test)] -mod tests { - use crate::{ - keys::Key, layouts::KeyLayout, Breathe, Colour, Effect, Flicker, LedType, Sequences, Speed, - Static, - }; - - #[test] - fn single_key_next_state_then_create() { - let layout = KeyLayout::gx502_layout(); - let mut seq = Sequences::new(); - seq.0.push(Effect::Static(Static::new( - LedType::Key(Key::F), - Colour(255, 127, 0), - ))); - - seq.next_state(&layout); - let packets = seq.create_packets(); - - assert_eq!(packets[0][0], 0x5d); - assert_eq!(packets[5][33], 255); - assert_eq!(packets[5][34], 127); - assert_eq!(packets[5][35], 0); - } - - #[test] - fn cycle_breathe() { - let layout = KeyLayout::gx502_layout(); - let mut seq = Sequences::new(); - seq.0.push(Effect::Breathe(Breathe::new( - LedType::Key(Key::F), - Colour(255, 127, 0), - Colour(127, 0, 255), - Speed::Med, - ))); - - let s = serde_json::to_string_pretty(&seq).unwrap(); - println!("{s}"); - - seq.next_state(&layout); - let packets = seq.create_packets(); - - assert_eq!(packets[0][0], 0x5d); - assert_eq!(packets[5][33], 213); - assert_eq!(packets[5][34], 106); - assert_eq!(packets[5][35], 0); - - // dbg!(&packets[5][33..=35]); - - seq.next_state(&layout); - let packets = seq.create_packets(); - - assert_eq!(packets[0][0], 0x5d); - assert_eq!(packets[5][33], 171); - assert_eq!(packets[5][34], 85); - assert_eq!(packets[5][35], 0); - } - - #[test] - fn cycle_flicker() { - let layout = KeyLayout::gx502_layout(); - let mut seq = Sequences::new(); - seq.0.push(Effect::Flicker(Flicker::new( - LedType::Key(Key::F), - Colour(255, 127, 80), - 100, - 10, - ))); - - seq.next_state(&layout); - let packets = seq.create_packets(); - - assert_eq!(packets[0][0], 0x5d); - assert_eq!(packets[5][33], 255); - assert_eq!(packets[5][34], 127); - assert_eq!(packets[5][35], 80); - - // The random is deterministic - seq.next_state(&layout); - seq.next_state(&layout); - seq.next_state(&layout); - seq.next_state(&layout); - seq.next_state(&layout); - seq.next_state(&layout); - seq.next_state(&layout); - - let packets = seq.create_packets(); - assert_eq!(packets[5][33], 215); - assert_eq!(packets[5][34], 87); - assert_eq!(packets[5][35], 40); - } -} diff --git a/rog-aura/src/usb.rs b/rog-aura/src/usb.rs index ee074389..dcdc72fd 100644 --- a/rog-aura/src/usb.rs +++ b/rog-aura/src/usb.rs @@ -1,5 +1,7 @@ -use serde::{Deserialize, Serialize}; +use std::fmt::Debug; use std::ops::{BitAnd, BitOr}; + +use serde::{Deserialize, Serialize}; #[cfg(feature = "dbus")] use zbus::zvariant::Type; @@ -16,12 +18,12 @@ pub const LED_SET: [u8; 17] = [0x5d, 0xb5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /// Writes out the correct byte string for brightness pub const fn aura_brightness_bytes(brightness: u8) -> [u8; 17] { [ - 0x5A, 0xBA, 0xC5, 0xC4, brightness, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0x5a, 0xba, 0xc5, 0xc4, brightness, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ] } #[cfg_attr(feature = "dbus", derive(Type))] -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Serialize, Deserialize, Default)] +#[derive(Clone, PartialEq, Eq, PartialOrd, Serialize, Deserialize, Default)] pub enum AuraDevice { Tuf, X1854, @@ -45,6 +47,19 @@ impl From<&str> for AuraDevice { } } +impl Debug for AuraDevice { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Tuf => write!(f, "Tuf"), + Self::X1854 => write!(f, "0x1854"), + Self::X1869 => write!(f, "0x1869"), + Self::X1866 => write!(f, "0x1866"), + Self::X19B6 => write!(f, "0x19B6"), + Self::Unknown => write!(f, "Unknown"), + } + } +} + /// This struct is intended as a helper to pass args to generic dbus interface #[cfg_attr(feature = "dbus", derive(Type))] #[derive(Clone, Default, Debug, Serialize, Deserialize)] @@ -73,7 +88,8 @@ impl AuraDevTuf { /// # Bits for older 0x1866 keyboard model /// /// Keybord and Lightbar require Awake, Boot and Sleep apply to both -/// Keybord and Lightbar regardless of if either are enabled (or Awake is enabled) +/// Keybord and Lightbar regardless of if either are enabled (or Awake is +/// enabled) /// /// | Byte 1 | Byte 2 | Byte 3 | function | hex | /// |------------|------------|------------|----------|----------| @@ -83,7 +99,6 @@ impl AuraDevTuf { /// | 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 | | -/// #[cfg_attr(feature = "dbus", derive(Type))] #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)] #[repr(u32)] @@ -161,7 +176,6 @@ impl BitAnd for AuraDev1866 { /// | 0000 | 0100 | 04 | lightbar on | bit 3 | /// | 0000 | 1000 | 08 | lightbar off sleep | bit 4 | /// | 0001 | 0000 | 10 | lightbar shtdn off | bit 5 | -/// #[cfg_attr(feature = "dbus", derive(Type))] #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)] #[repr(u32)] @@ -226,9 +240,8 @@ impl BitAnd for AuraDev19b6 { #[cfg(test)] mod tests { - use crate::usb::AuraDev19b6; - use super::AuraDev1866; + use crate::usb::AuraDev19b6; #[test] fn check_0x1866_control_bytes() { @@ -370,7 +383,7 @@ mod tests { assert_eq!(bytes[2], 0x0f); let byte3 = [ - //AuraDev19b6::AwakeLid, + // AuraDev19b6::AwakeLid, AuraDev19b6::BootLid, AuraDev19b6::SleepLid, AuraDev19b6::ShutdownLid, @@ -393,7 +406,7 @@ mod tests { AuraDev19b6::AwakeLid, AuraDev19b6::BootLid, AuraDev19b6::SleepLid, - //AuraDev19b6::ShutdownLid, + // AuraDev19b6::ShutdownLid, ]; let bytes = AuraDev19b6::to_bytes(&byte3); println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]); @@ -401,9 +414,9 @@ mod tests { let byte3 = [ AuraDev19b6::AwakeLid, - //AuraDev19b6::BootLid, + // AuraDev19b6::BootLid, AuraDev19b6::SleepLid, - //AuraDev19b6::ShutdownLid, + // AuraDev19b6::ShutdownLid, ]; let bytes = AuraDev19b6::to_bytes(&byte3); println!("{:08b}, {:08b}, {:08b}", bytes[0], bytes[1], bytes[2]); diff --git a/rog-control-center/Cargo.toml b/rog-control-center/Cargo.toml index c9fff538..5f4fcd7a 100644 --- a/rog-control-center/Cargo.toml +++ b/rog-control-center/Cargo.toml @@ -6,6 +6,7 @@ authors = ["Luke D. Jones "] edition = "2021" [features] +#default = ["mocking"] mocking = [] [dependencies] @@ -23,6 +24,7 @@ rog_profiles = { path = "../rog-profiles" } rog_platform = { path = "../rog-platform" } supergfxctl = { git = "https://gitlab.com/asus-linux/supergfxctl.git", default-features = false } +gumdrop.workspace = true log.workspace = true env_logger.workspace = true diff --git a/rog-control-center/src/app.rs b/rog-control-center/src/app.rs index 537c0fec..d37e51e3 100644 --- a/rog-control-center/src/app.rs +++ b/rog-control-center/src/app.rs @@ -1,18 +1,16 @@ -use std::{ - f64::consts::PI, - sync::{ - atomic::{AtomicBool, AtomicU8, Ordering}, - Arc, Mutex, - }, - time::{Duration, Instant}, -}; +use std::f64::consts::PI; +use std::sync::atomic::{AtomicBool, AtomicU8, Ordering}; +use std::sync::{Arc, Mutex}; +use std::time::{Duration, Instant}; use egui::{Button, RichText}; +use rog_aura::layouts::KeyLayout; use rog_platform::supported::SupportedFunctions; -use crate::{ - config::Config, error::Result, system_state::SystemState, Page, RogDbusClientBlocking, -}; +use crate::config::Config; +use crate::error::Result; +use crate::system_state::SystemState; +use crate::{Page, RogDbusClientBlocking}; pub struct RogApp { pub page: Page, @@ -103,8 +101,9 @@ impl RogApp { } impl eframe::App for RogApp { - /// Called each time the UI needs repainting, which may be many times per second. - /// Put your widgets into a `SidePanel`, `TopPanel`, `CentralPanel`, `Window` or `Area`. + /// Called each time the UI needs repainting, which may be many times per + /// second. Put your widgets into a `SidePanel`, `TopPanel`, + /// `CentralPanel`, `Window` or `Area`. fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) { let states = self.states.clone(); @@ -115,6 +114,21 @@ impl eframe::App for RogApp { } } + // Shortcut typical display stuff + if let Ok(mut states) = states.try_lock() { + let layout_testing = states.aura_creation.layout_testing.clone(); + if let Some(path) = &layout_testing { + let modified = path.metadata().unwrap().modified().unwrap(); + if states.aura_creation.layout_last_modified < modified { + states.aura_creation.layout_last_modified = modified; + // time to reload the config + states.aura_creation.keyboard_layout = KeyLayout::from_file(path).unwrap(); + } + self.aura_page(&mut states, ctx); + return; + } + } + let page = self.page; self.top_bar(ctx, frame); @@ -146,6 +160,7 @@ impl eframe::App for RogApp { }); } } + if !was_error { if let Ok(mut states) = states.try_lock() { if page == Page::System { diff --git a/rog-control-center/src/cli_options.rs b/rog-control-center/src/cli_options.rs new file mode 100644 index 00000000..d6040eba --- /dev/null +++ b/rog-control-center/src/cli_options.rs @@ -0,0 +1,19 @@ +use gumdrop::Options; + +#[derive(Default, Options)] +pub struct CliStart { + #[options(help_flag, help = "print help message")] + pub help: bool, + #[options(help = "show program version number")] + pub version: bool, + #[options( + meta = "", + help = "set board name for testing, this will make ROGCC show only the keyboard page" + )] + pub board_name: Option, + #[options( + help = "put ROGCC in layout viewing mode - this is helpful for finding existing layouts \ + that might match your laptop" + )] + pub layout_viewing: bool, +} diff --git a/rog-control-center/src/config.rs b/rog-control-center/src/config.rs index c74c6ced..bad72070 100644 --- a/rog-control-center/src/config.rs +++ b/rog-control-center/src/config.rs @@ -1,11 +1,11 @@ +use std::fs::{create_dir, OpenOptions}; +use std::io::{Read, Write}; + use log::{error, info, warn}; use serde_derive::{Deserialize, Serialize}; -use std::{ - fs::{create_dir, OpenOptions}, - io::{Read, Write}, -}; -use crate::{error::Error, update_and_notify::EnabledNotifications}; +use crate::error::Error; +use crate::update_and_notify::EnabledNotifications; const CFG_DIR: &str = "rog"; const CFG_FILE_NAME: &str = "rog-control-center.cfg"; diff --git a/rog-control-center/src/lib.rs b/rog-control-center/src/lib.rs index 799a9d26..f03a7ca2 100644 --- a/rog-control-center/src/lib.rs +++ b/rog-control-center/src/lib.rs @@ -1,14 +1,13 @@ pub mod app; -use std::{ - fs::{remove_dir_all, File, OpenOptions}, - io::{Read, Write}, - process::exit, - thread::sleep, - time::Duration, -}; +use std::fs::{remove_dir_all, File, OpenOptions}; +use std::io::{Read, Write}; +use std::process::exit; +use std::thread::sleep; +use std::time::Duration; pub use app::RogApp; +pub mod cli_options; pub mod config; pub mod error; #[cfg(feature = "mocking")] @@ -22,12 +21,12 @@ pub mod widgets; #[cfg(feature = "mocking")] pub use mocking::RogDbusClientBlocking; +use nix::sys::stat; +use nix::unistd; #[cfg(not(feature = "mocking"))] pub use rog_dbus::RogDbusClientBlocking; - -use nix::{sys::stat, unistd}; use tempfile::TempDir; -//use log::{error, info, warn}; +// use log::{error, info, warn}; pub const VERSION: &str = env!("CARGO_PKG_VERSION"); diff --git a/rog-control-center/src/main.rs b/rog-control-center/src/main.rs index edbe81b2..9adf0f66 100644 --- a/rog-control-center/src/main.rs +++ b/rog-control-center/src/main.rs @@ -1,21 +1,26 @@ +use std::env::args; +use std::fs::OpenOptions; +use std::io::{Read, Write}; +use std::path::{Path, PathBuf}; +use std::sync::{Arc, Mutex}; + use eframe::{IconData, NativeOptions}; -use log::{error, info}; +use gumdrop::Options; +use log::{error, info, warn}; +use rog_aura::aura_detection::{LaptopLedData, LedSupportFile}; use rog_aura::layouts::KeyLayout; +use rog_control_center::cli_options::CliStart; +use rog_control_center::config::Config; +use rog_control_center::error::Result; +use rog_control_center::startup_error::AppErrorShow; +use rog_control_center::system_state::SystemState; use rog_control_center::tray::init_tray; -use rog_control_center::update_and_notify::EnabledNotifications; +use rog_control_center::update_and_notify::{start_notifications, EnabledNotifications}; use rog_control_center::{ - config::Config, error::Result, get_ipc_file, on_tmp_dir_exists, print_versions, - startup_error::AppErrorShow, system_state::SystemState, update_and_notify::start_notifications, - RogApp, RogDbusClientBlocking, SHOWING_GUI, SHOW_GUI, + get_ipc_file, on_tmp_dir_exists, print_versions, RogApp, RogDbusClientBlocking, SHOWING_GUI, + SHOW_GUI, }; use rog_platform::supported::SupportedFunctions; -use std::sync::Mutex; -use std::{ - fs::OpenOptions, - io::{Read, Write}, - path::PathBuf, - sync::Arc, -}; use tokio::runtime::Runtime; #[cfg(not(feature = "mocking"))] @@ -26,7 +31,19 @@ const BOARD_NAME: &str = "/sys/class/dmi/id/board_name"; const APP_ICON_PATH: &str = "/usr/share/icons/hicolor/512x512/apps/rog-control-center.png"; fn main() -> Result<()> { - print_versions(); + let args: Vec = args().skip(1).collect(); + + let parsed = match CliStart::parse_args_default(&args) { + Ok(p) => p, + Err(err) => { + panic!("source {}", err); + } + }; + + if do_cli_help(&parsed) { + return Ok(()); + } + let mut logger = env_logger::Builder::new(); logger .parse_default_env() @@ -43,8 +60,8 @@ fn main() -> Result<()> { vsync: true, decorated: true, transparent: false, - min_window_size: Some(egui::vec2(840.0, 600.0)), - max_window_size: Some(egui::vec2(840.0, 600.0)), + min_window_size: Some(egui::vec2(900.0, 600.0)), + max_window_size: Some(egui::vec2(900.0, 600.0)), run_and_return: true, icon_data: Some(load_icon()), ..Default::default() @@ -88,25 +105,66 @@ fn main() -> Result<()> { .read(true) .open(PathBuf::from(BOARD_NAME)) .map_err(|e| { - println!("{BOARD_NAME}, {e}"); + println!("DOH! {BOARD_NAME}, {e}"); e })?; let mut board_name = String::new(); file.read_to_string(&mut board_name)?; - #[cfg(feature = "mocking")] - { - board_name = "gl504".to_string(); + let mut led_support = LaptopLedData::get_data(); + + let mut path = PathBuf::from(DATA_DIR); + let mut layout_name = None; + let mut layouts = Vec::new(); + if parsed.board_name.is_some() || parsed.layout_viewing { path.pop(); path.push("rog-aura"); path.push("data"); + layouts = KeyLayout::layout_files(path.to_owned()).unwrap(); + + if let Some(name) = &parsed.board_name { + if let Some(modes) = LedSupportFile::load_from_config() { + if let Some(data) = modes.matcher(name) { + led_support = data; + } + } + board_name = name.to_owned(); + for layout in &layouts { + if layout + .file_name() + .unwrap() + .to_string_lossy() + .contains(&led_support.layout_name.to_lowercase()) + { + layout_name = Some(layout.to_owned()); + } + } + } else { + board_name = "GQ401QM".to_string() + }; + + if parsed.layout_viewing { + layout_name = Some(layouts[0].clone()); + board_name = layouts[0] + .file_name() + .unwrap() + .to_string_lossy() + .split_once('_') + .unwrap() + .0 + .to_owned(); + led_support.layout_name = board_name.clone(); + } } - let layout = KeyLayout::find_layout(board_name.as_str(), PathBuf::from(DATA_DIR)) + let layout = KeyLayout::find_layout(led_support, path) .map_err(|e| { - println!("{BOARD_NAME}, {e}"); + println!("DERP! , {e}"); }) - .unwrap_or_else(|_| KeyLayout::ga401_layout()); + .unwrap_or_else(|_| { + warn!("Did not find a keyboard layout matching {board_name}"); + KeyLayout::default_layout() + }); // tmp-dir must live to the end of program life let _tmp_dir = match tempfile::Builder::new() @@ -118,7 +176,14 @@ fn main() -> Result<()> { Err(_) => on_tmp_dir_exists().unwrap(), }; - let states = setup_page_state_and_notifs(layout, enabled_notifications, &config, &supported)?; + let states = setup_page_state_and_notifs( + layout_name, + layout, + layouts, + enabled_notifications, + &config, + &supported, + )?; init_tray(supported, states.clone()); @@ -128,7 +193,7 @@ fn main() -> Result<()> { } let config = Config::load()?; - if !config.run_in_background { + if !config.run_in_background || parsed.board_name.is_some() || parsed.layout_viewing { break; } @@ -151,13 +216,17 @@ fn main() -> Result<()> { } fn setup_page_state_and_notifs( + layout_testing: Option, keyboard_layout: KeyLayout, + keyboard_layouts: Vec, enabled_notifications: Arc>, config: &Config, supported: &SupportedFunctions, ) -> Result>> { let page_states = Arc::new(Mutex::new(SystemState::new( + layout_testing, keyboard_layout, + keyboard_layouts, enabled_notifications.clone(), supported, )?)); @@ -216,3 +285,31 @@ fn load_icon() -> IconData { rgba, } } + +fn do_cli_help(parsed: &CliStart) -> bool { + if parsed.help { + println!("{}", CliStart::usage()); + println!(); + if let Some(cmdlist) = CliStart::command_list() { + let commands: Vec = cmdlist.lines().map(|s| s.to_owned()).collect(); + for command in commands.iter() { + println!("{}", command); + } + } + } + + if parsed.version { + print_versions(); + println!(); + } + + parsed.help +} + +pub fn get_layout_path(path: &Path, layout_name: &str) -> PathBuf { + let mut data_path = PathBuf::from(path); + let layout_file = format!("{}_US.ron", layout_name); + data_path.push("layouts"); + data_path.push(layout_file); + data_path +} diff --git a/rog-control-center/src/mocking.rs b/rog-control-center/src/mocking.rs index 7291c44c..d99cfe16 100644 --- a/rog-control-center/src/mocking.rs +++ b/rog-control-center/src/mocking.rs @@ -1,35 +1,48 @@ use std::collections::BTreeMap; -use rog_aura::{ - usb::{AuraDev19b6, AuraDevice, AuraPowerDev}, - AuraEffect, AuraModeNum, AuraZone, -}; -use rog_profiles::fan_curve_set::{CurveData, FanCurveSet}; -use rog_supported::{ - AnimeSupportedFunctions, ChargeSupportedFunctions, LedSupportedFunctions, +use rog_aura::usb::{AuraDev19b6, AuraDevice, AuraPowerDev}; +use rog_aura::{AuraEffect, AuraModeNum, AuraZone}; +use rog_platform::platform::GpuMode; +use rog_platform::supported::{ + AdvancedAura, AnimeSupportedFunctions, ChargeSupportedFunctions, LedSupportedFunctions, PlatformProfileFunctions, RogBiosSupportedFunctions, SupportedFunctions, }; +use rog_profiles::fan_curve_set::{CurveData, FanCurveSet}; +use supergfxctl::pci_device::{GfxMode, GfxPower}; use crate::error::Result; -const NOPE: &'static str = ""; +const NOPE: &str = ""; -pub struct RogDbusClientBlocking<'a> { +#[derive(Default)] +pub struct DaemonProxyBlocking<'a> { _phantom: &'a str, } -impl<'a> Default for RogDbusClientBlocking<'a> { - fn default() -> Self { - Self { - _phantom: Default::default(), - } +impl<'a> DaemonProxyBlocking<'a> { + pub fn new(_c: &bool) -> Result { + Ok(Self { _phantom: NOPE }) } + + pub fn mode(&self) -> Result { + Ok(GfxMode::None) + } + + pub fn power(&self) -> Result { + Ok(GfxPower::Suspended) + } +} + +#[derive(Default)] +pub struct RogDbusClientBlocking<'a> { + _phantom: &'a str, } impl<'a> RogDbusClientBlocking<'a> { pub fn new() -> Result<(Self, bool)> { Ok((Self { _phantom: NOPE }, true)) } + pub fn proxies(&self) -> Proxies { Proxies } @@ -40,18 +53,23 @@ impl Proxies { pub fn rog_bios(&self) -> Bios { Bios } + pub fn profile(&self) -> Profile { Profile } + pub fn led(&self) -> Led { Led } + pub fn anime(&self) -> Anime { Anime } + pub fn charge(&self) -> Profile { Profile } + pub fn supported(&self) -> Supported { Supported } @@ -62,18 +80,23 @@ impl Bios { pub fn post_boot_sound(&self) -> Result { Ok(1) } - pub fn gpu_mux_mode(&self) -> Result { - Ok(1) + + pub fn gpu_mux_mode(&self) -> Result { + Ok(GpuMode::Optimus) } - pub fn panel_od(&self) -> Result { - Ok(1) + + pub fn panel_od(&self) -> Result { + Ok(true) } + pub fn set_post_boot_sound(&self, _b: bool) -> Result<()> { Ok(()) } - pub fn set_gpu_mux_mode(&self, _b: bool) -> Result<()> { + + pub fn set_gpu_mux_mode(&self, _b: GpuMode) -> Result<()> { Ok(()) } + pub fn set_panel_od(&self, _b: bool) -> Result<()> { Ok(()) } @@ -88,15 +111,18 @@ impl Profile { rog_profiles::Profile::Quiet, ]) } + pub fn active_profile(&self) -> Result { Ok(rog_profiles::Profile::Performance) } + pub fn enabled_fan_profiles(&self) -> Result> { Ok(vec![ rog_profiles::Profile::Performance, rog_profiles::Profile::Balanced, ]) } + pub fn fan_curve_data(&self, _p: rog_profiles::Profile) -> Result { let mut curve = FanCurveSet::default(); curve.cpu.pwm = [30, 40, 60, 100, 140, 180, 200, 250]; @@ -105,21 +131,34 @@ impl Profile { curve.gpu.temp = [20, 30, 40, 50, 70, 80, 90, 100]; Ok(curve) } + pub fn set_fan_curve(&self, _p: rog_profiles::Profile, _c: CurveData) -> Result<()> { Ok(()) } + pub fn set_fan_curve_enabled(&self, _p: rog_profiles::Profile, _b: bool) -> Result<()> { Ok(()) } - pub fn limit(&self) -> Result { + + pub fn charge_control_end_threshold(&self) -> Result { Ok(66) } - pub fn set_limit(&self, _l: u8) -> Result<()> { + + pub fn set_charge_control_end_threshold(&self, _l: u8) -> Result<()> { Ok(()) } + pub fn set_active_profile(&self, _p: rog_profiles::Profile) -> Result<()> { Ok(()) } + + pub fn mains_online(&self) -> Result { + Ok(true) + } + + pub fn reset_profile_curves(&self, _p: rog_profiles::Profile) -> Result { + Ok(true) + } } pub struct Led; @@ -139,12 +178,15 @@ impl Led { data.insert(AuraModeNum::Pulse, AuraEffect::default()); Ok(data) } + pub fn led_mode(&self) -> Result { Ok(AuraModeNum::Rainbow) } + pub fn led_brightness(&self) -> Result { Ok(1) } + pub fn leds_enabled(&self) -> Result { Ok(AuraPowerDev { tuf: vec![], @@ -157,9 +199,11 @@ impl Led { ], }) } + pub fn set_leds_power(&self, _a: AuraPowerDev, _b: bool) -> Result<()> { Ok(()) } + pub fn set_led_mode(&self, _a: &AuraEffect) -> Result<()> { Ok(()) } @@ -170,12 +214,15 @@ impl Anime { pub fn boot_enabled(&self) -> Result { Ok(true) } + pub fn awake_enabled(&self) -> Result { Ok(true) } + pub fn set_on_off(&self, _b: bool) -> Result<()> { Ok(()) } + pub fn set_boot_on_off(&self, _b: bool) -> Result<()> { Ok(()) } @@ -194,16 +241,16 @@ impl Supported { fan_curves: true, }, keyboard_led: LedSupportedFunctions { - prod_id: AuraDevice::X19B6, - brightness_set: true, - stock_led_modes: vec![ + dev_id: AuraDevice::X19B6, + brightness: true, + basic_modes: vec![ AuraModeNum::Rain, AuraModeNum::Rainbow, AuraModeNum::Star, AuraModeNum::Static, AuraModeNum::Strobe, ], - multizone_led_mode: vec![ + basic_zones: vec![ AuraZone::Key1, AuraZone::Key2, AuraZone::Key3, @@ -212,12 +259,12 @@ impl Supported { AuraZone::BarRight, AuraZone::Logo, ], - per_key_led_mode: true, + advanced_type: AdvancedAura::PerKey, }, rog_bios_ctrl: RogBiosSupportedFunctions { post_sound: true, - dedicated_gfx: true, - panel_od: true, + gpu_mux: true, + panel_overdrive: true, dgpu_disable: true, egpu_enable: true, }, diff --git a/rog-control-center/src/pages/aura_page.rs b/rog-control-center/src/pages/aura_page.rs index 3c07c54b..b99dc0c6 100644 --- a/rog-control-center/src/pages/aura_page.rs +++ b/rog-control-center/src/pages/aura_page.rs @@ -1,18 +1,16 @@ -use std::{sync::atomic::Ordering, time::Duration}; +use std::sync::atomic::Ordering; +use std::time::Duration; use egui::Color32; use rog_aura::{AuraEffect, AuraModeNum}; -use crate::{ - system_state::SystemState, - widgets::{aura_modes_group, keyboard}, - RogApp, -}; +use crate::system_state::SystemState; +use crate::widgets::{aura_modes_group, keyboard}; +use crate::RogApp; impl RogApp { pub fn aura_page(&mut self, states: &mut SystemState, ctx: &egui::Context) { let Self { - supported, oscillator1, oscillator2, oscillator3, @@ -70,9 +68,13 @@ impl RogApp { // TODO: animation of colour changes/periods/blending egui::CentralPanel::default().show(ctx, |ui| { - aura_modes_group(supported, states, oscillator_freq, ui); - - keyboard(ui, &states.keyboard_layout, &mut states.aura, colour); + aura_modes_group(states, oscillator_freq, ui); + keyboard( + ui, + &states.aura_creation.keyboard_layout, + &mut states.aura, + colour, + ); }); // Only do repaint request if on this page diff --git a/rog-control-center/src/pages/fan_curve_page.rs b/rog-control-center/src/pages/fan_curve_page.rs index e2cb324b..e9725575 100644 --- a/rog-control-center/src/pages/fan_curve_page.rs +++ b/rog-control-center/src/pages/fan_curve_page.rs @@ -1,28 +1,37 @@ -use crate::{ - system_state::{FanCurvesState, ProfilesState, SystemState}, - widgets::fan_graphs, - RogApp, RogDbusClientBlocking, -}; use egui::Ui; use rog_platform::supported::SupportedFunctions; use rog_profiles::Profile; +use crate::system_state::{FanCurvesState, ProfilesState, SystemState}; +use crate::widgets::fan_graphs; +use crate::{RogApp, RogDbusClientBlocking}; + impl RogApp { pub fn fan_curve_page(&mut self, states: &mut SystemState, ctx: &egui::Context) { let Self { supported, .. } = self; egui::CentralPanel::default().show(ctx, |ui| { ui.heading("Custom fan curves"); - ui.label("A fan curve is only active when the related profile is active and the curve is enabled"); + ui.label( + "A fan curve is only active when the related profile is active and the curve is \ + enabled", + ); Self::fan_curve( supported, &mut states.profiles, &mut states.fan_curves, - &states.asus_dbus, &mut states.error, + &states.asus_dbus, + &mut states.error, ui, ); - fan_graphs(supported, &mut states.fan_curves, &states.asus_dbus, &mut states.error, ui); + fan_graphs( + supported, + &mut states.fan_curves, + &states.asus_dbus, + &mut states.error, + ui, + ); }); } diff --git a/rog-control-center/src/pages/system_page.rs b/rog-control-center/src/pages/system_page.rs index 17a4cb56..ae1b9212 100644 --- a/rog-control-center/src/pages/system_page.rs +++ b/rog-control-center/src/pages/system_page.rs @@ -1,10 +1,8 @@ -use crate::{ - system_state::SystemState, - widgets::{ - anime_power_group, app_settings, aura_power_group, platform_profile, rog_bios_group, - }, - RogApp, +use crate::system_state::SystemState; +use crate::widgets::{ + anime_power_group, app_settings, aura_power_group, platform_profile, rog_bios_group, }; +use crate::RogApp; impl RogApp { pub fn system_page(&mut self, states: &mut SystemState, ctx: &egui::Context) { @@ -21,7 +19,6 @@ impl RogApp { egui::Grid::new("grid_of_bits") .min_col_width(rect.width() / 2.0) .show(ui, |ui| { - /******************************************************/ ui.vertical(|ui| { ui.separator(); if supported.platform_profile.platform_profile { @@ -34,7 +31,6 @@ impl RogApp { }); ui.end_row(); - /******************************************************/ ui.vertical(|ui| { ui.separator(); app_settings(config, states, ui); @@ -45,7 +41,6 @@ impl RogApp { }); ui.end_row(); - /******************************************************/ ui.vertical(|ui| { ui.separator(); if supported.anime_ctrl.0 { diff --git a/rog-control-center/src/system_state.rs b/rog-control-center/src/system_state.rs index 100921b4..3f7e465f 100644 --- a/rog-control-center/src/system_state.rs +++ b/rog-control-center/src/system_state.rs @@ -1,19 +1,26 @@ -use std::{ - collections::{BTreeMap, HashSet}, - sync::{Arc, Mutex}, -}; +use std::collections::{BTreeMap, HashSet}; +use std::path::PathBuf; +use std::sync::{Arc, Mutex}; +use std::time::SystemTime; use egui::Vec2; -use rog_aura::{layouts::KeyLayout, usb::AuraPowerDev, AuraEffect, AuraModeNum}; -use rog_platform::{platform::GpuMode, supported::SupportedFunctions}; -use rog_profiles::{fan_curve_set::FanCurveSet, FanCurvePU, Profile}; -use supergfxctl::{ - pci_device::{GfxMode, GfxPower}, - zbus_proxy::DaemonProxyBlocking as GfxProxyBlocking, -}; - -use crate::{error::Result, update_and_notify::EnabledNotifications, RogDbusClientBlocking}; use log::error; +use rog_aura::layouts::KeyLayout; +use rog_aura::usb::AuraPowerDev; +use rog_aura::{AuraEffect, AuraModeNum}; +use rog_platform::platform::GpuMode; +use rog_platform::supported::SupportedFunctions; +use rog_profiles::fan_curve_set::FanCurveSet; +use rog_profiles::{FanCurvePU, Profile}; +use supergfxctl::pci_device::{GfxMode, GfxPower}; +#[cfg(not(feature = "mocking"))] +use supergfxctl::zbus_proxy::DaemonProxyBlocking as GfxProxyBlocking; + +use crate::error::Result; +#[cfg(feature = "mocking")] +use crate::mocking::DaemonProxyBlocking as GfxProxyBlocking; +use crate::update_and_notify::EnabledNotifications; +use crate::RogDbusClientBlocking; #[derive(Clone, Debug, Default)] pub struct BiosState { @@ -149,25 +156,21 @@ pub struct AuraState { } impl AuraState { - pub fn new(supported: &SupportedFunctions, dbus: &RogDbusClientBlocking<'_>) -> Result { + pub fn new(layout: &KeyLayout, dbus: &RogDbusClientBlocking<'_>) -> Result { Ok(Self { - current_mode: if !supported.keyboard_led.stock_led_modes.is_empty() { + current_mode: if !layout.basic_modes().is_empty() { dbus.proxies().led().led_mode().unwrap_or_default() } else { AuraModeNum::Static }, - modes: if !supported.keyboard_led.stock_led_modes.is_empty() { + modes: if !layout.basic_modes().is_empty() { dbus.proxies().led().led_modes().unwrap_or_default() } else { BTreeMap::new() }, enabled: dbus.proxies().led().leds_enabled().unwrap_or_default(), - bright: if !supported.keyboard_led.brightness_set { - dbus.proxies().led().led_brightness().unwrap_or_default() - } else { - 2 - }, + bright: dbus.proxies().led().led_brightness().unwrap_or_default(), wave_red: [0u8; 22], wave_green: [0u8; 22], wave_blue: [0u8; 22], @@ -259,13 +262,42 @@ impl PowerState { } } -/// State stored from system daemons. This is shared with: tray, zbus notifications thread -/// and the GUI app thread. -pub struct SystemState { +#[derive(Clone, Debug)] +pub struct AuraCreation { + /// Specifically for testing the development of keyboard layouts (combined + /// with `--layout-name` CLI option) + pub layout_testing: Option, + pub layout_last_modified: SystemTime, pub keyboard_layout: KeyLayout, + pub keyboard_layouts: Vec, + /// current index in to `self.keyboard_layouts` + pub keyboard_layout_index: usize, +} + +impl AuraCreation { + pub fn new( + layout_testing: Option, + keyboard_layout: KeyLayout, + keyboard_layouts: Vec, + ) -> Self { + Self { + layout_testing, + layout_last_modified: SystemTime::now(), + keyboard_layout, + keyboard_layouts, + keyboard_layout_index: 0, + } + } +} + +/// State stored from system daemons. This is shared with: tray, zbus +/// notifications thread and the GUI app thread. +pub struct SystemState { + pub aura_creation: AuraCreation, + //-- pub enabled_notifications: Arc>, - /// Because much of the app state here is the same as `RogBiosSupportedFunctions` - /// we can re-use that structure. + /// Because much of the app state here is the same as + /// `RogBiosSupportedFunctions` we can re-use that structure. pub bios: BiosState, pub aura: AuraState, pub anime: AnimeState, @@ -274,8 +306,8 @@ pub struct SystemState { pub gfx_state: GfxState, pub power_state: PowerState, pub error: Option, - /// Specific field for the tray only so that we can know when it does need update. - /// The tray should set this to false when done. + /// Specific field for the tray only so that we can know when it does need + /// update. The tray should set this to false when done. pub tray_should_update: bool, pub app_should_update: bool, pub asus_dbus: RogDbusClientBlocking<'static>, @@ -283,17 +315,28 @@ pub struct SystemState { } impl SystemState { - /// Creates self, including the relevant dbus connections and proixies for internal use + /// Creates self, including the relevant dbus connections and proixies for + /// internal use pub fn new( + layout_testing: Option, keyboard_layout: KeyLayout, + keyboard_layouts: Vec, enabled_notifications: Arc>, supported: &SupportedFunctions, ) -> Result { let (asus_dbus, conn) = RogDbusClientBlocking::new()?; let mut error = None; let gfx_dbus = GfxProxyBlocking::new(&conn).expect("Couldn't connect to supergfxd"); + let aura = AuraState::new(&keyboard_layout, &asus_dbus) + .map_err(|e| { + let e = format!("Could not get AuraState state: {e}"); + error!("{e}"); + error = Some(e); + }) + .unwrap_or_default(); + Ok(Self { - keyboard_layout, + aura_creation: AuraCreation::new(layout_testing, keyboard_layout, keyboard_layouts), enabled_notifications, power_state: PowerState::new(supported, &asus_dbus) .map_err(|e| { @@ -309,13 +352,7 @@ impl SystemState { error = Some(e); }) .unwrap_or_default(), - aura: AuraState::new(supported, &asus_dbus) - .map_err(|e| { - let e = format!("Could not get AuraState state: {e}"); - error!("{e}"); - error = Some(e); - }) - .unwrap_or_default(), + aura, anime: AnimeState::new(supported, &asus_dbus) .map_err(|e| { let e = format!("Could not get AanimeState state: {e}"); @@ -364,7 +401,13 @@ impl Default for SystemState { let gfx_dbus = GfxProxyBlocking::new(&conn).expect("Couldn't connect to supergfxd"); Self { - keyboard_layout: KeyLayout::ga401_layout(), + aura_creation: AuraCreation { + layout_testing: None, + layout_last_modified: SystemTime::now(), + keyboard_layout: KeyLayout::default_layout(), + keyboard_layouts: Default::default(), + keyboard_layout_index: 0, + }, enabled_notifications: Default::default(), bios: BiosState { post_sound: Default::default(), diff --git a/rog-control-center/src/tray.rs b/rog-control-center/src/tray.rs index d2399f9e..6b3261e3 100644 --- a/rog-control-center/src/tray.rs +++ b/rog-control-center/src/tray.rs @@ -1,28 +1,25 @@ //! A seld-contained tray icon with menus. The control of app<->tray is done via //! commands over an MPSC channel. -use std::{ - io::Write, - sync::{ - atomic::{AtomicBool, Ordering}, - mpsc::{channel, Receiver}, - Arc, Mutex, - }, - time::Duration, -}; +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; -use gtk::{gio::Icon, prelude::*}; -use rog_dbus::zbus_platform::RogBiosProxyBlocking; -use rog_platform::{platform::GpuMode, supported::SupportedFunctions}; - -use crate::{error::Result, get_ipc_file, system_state::SystemState, SHOW_GUI}; +use gtk::gio::Icon; +use gtk::prelude::*; use libappindicator::{AppIndicator, AppIndicatorStatus}; -use supergfxctl::{ - pci_device::{GfxMode, GfxPower}, - zbus_proxy::DaemonProxyBlocking as GfxProxyBlocking, -}; - 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::pci_device::{GfxMode, GfxPower}; +use supergfxctl::zbus_proxy::DaemonProxyBlocking as GfxProxyBlocking; + +use crate::error::Result; +use crate::system_state::SystemState; +use crate::{get_ipc_file, SHOW_GUI}; const TRAY_APP_ICON: &str = "rog-control-center"; const TRAY_LABEL: &str = "ROG Control Center"; @@ -433,7 +430,8 @@ impl ROGTray { debug!("ROGTray: cleared self"); } - /// Reset GTK menu to internal state, this can be called after clearing and rebuilding the menu too. + /// Reset GTK menu to internal state, this can be called after clearing and + /// rebuilding the menu too. fn menu_update(&mut self) { self.tray.set_menu(&mut self.menu); self.set_icon(self.icon); diff --git a/rog-control-center/src/update_and_notify.rs b/rog-control-center/src/update_and_notify.rs index 8846a7da..7a9bf25b 100644 --- a/rog-control-center/src/update_and_notify.rs +++ b/rog-control-center/src/update_and_notify.rs @@ -1,27 +1,31 @@ -//! `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. +//! `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. + +use std::fmt::Display; +use std::process::Command; +use std::sync::{Arc, Mutex}; +use std::time::Duration; -use crate::{config::Config, error::Result, system_state::SystemState}; use log::{error, info, trace, warn}; use notify_rust::{Hint, Notification, NotificationHandle, Urgency}; -use rog_dbus::{ - zbus_anime::AnimeProxy, zbus_led::LedProxy, zbus_platform::RogBiosProxy, - zbus_power::PowerProxy, zbus_profile::ProfileProxy, -}; +use rog_dbus::zbus_anime::AnimeProxy; +use rog_dbus::zbus_led::LedProxy; +use rog_dbus::zbus_platform::RogBiosProxy; +use rog_dbus::zbus_power::PowerProxy; +use rog_dbus::zbus_profile::ProfileProxy; use rog_platform::platform::GpuMode; use rog_profiles::Profile; use serde::{Deserialize, Serialize}; -use std::{ - fmt::Display, - process::Command, - sync::{Arc, Mutex}, - time::Duration, -}; -use supergfxctl::{pci_device::GfxPower, zbus_proxy::DaemonProxy as SuperProxy}; +use supergfxctl::pci_device::GfxPower; +use supergfxctl::zbus_proxy::DaemonProxy as SuperProxy; use tokio::time::sleep; use zbus::export::futures_util::{future, StreamExt}; +use crate::config::Config; +use crate::error::Result; +use crate::system_state::SystemState; + const NOTIF_HEADER: &str = "ROG Control"; static mut POWER_AC_CMD: Option = None; @@ -356,7 +360,8 @@ pub fn start_notifications( if status != GfxPower::Unknown && status != last_status { if let Ok(config) = notifs_enabled1.lock() { if config.all_enabled && config.receive_notify_gfx_status { - // Required check because status cycles through active/unknown/suspended + // Required check because status cycles through + // active/unknown/suspended if let Ok(ref mut lock) = last_notif.lock() { notify!( do_gpu_status_notif( diff --git a/rog-control-center/src/widgets/app_settings.rs b/rog-control-center/src/widgets/app_settings.rs index bf1f3809..d822014d 100644 --- a/rog-control-center/src/widgets/app_settings.rs +++ b/rog-control-center/src/widgets/app_settings.rs @@ -1,6 +1,7 @@ use egui::Ui; -use crate::{config::Config, system_state::SystemState}; +use crate::config::Config; +use crate::system_state::SystemState; pub fn app_settings(config: &mut Config, states: &mut SystemState, ui: &mut Ui) { ui.heading("ROG GUI Settings"); diff --git a/rog-control-center/src/widgets/aura_modes.rs b/rog-control-center/src/widgets/aura_modes.rs index d172b6dd..70be2c7c 100644 --- a/rog-control-center/src/widgets/aura_modes.rs +++ b/rog-control-center/src/widgets/aura_modes.rs @@ -1,42 +1,41 @@ -use std::sync::{ - atomic::{AtomicU8, Ordering}, - Arc, -}; +use std::sync::atomic::{AtomicU8, Ordering}; +use std::sync::Arc; use egui::{RichText, Ui}; +use rog_aura::layouts::KeyLayout; use rog_aura::{AuraEffect, AuraModeNum, AuraZone, Colour, Speed}; -use rog_platform::supported::SupportedFunctions; use crate::system_state::{AuraState, SystemState}; -pub fn aura_modes_group( - supported: &SupportedFunctions, - states: &mut SystemState, - freq: &mut Arc, - ui: &mut Ui, -) { +pub fn aura_modes_group(states: &mut SystemState, freq: &mut Arc, ui: &mut Ui) { let mut changed = false; let mut selected = states.aura.current_mode; let allowed = AuraEffect::allowed_parameters(selected); - let has_keyzones = supported - .keyboard_led - .multizone_led_mode + let SystemState { aura_creation, .. } = states; + + let has_keyzones = aura_creation + .keyboard_layout + .basic_zones() .contains(&AuraZone::Key2); - let has_logo = supported - .keyboard_led - .multizone_led_mode + let has_logo = aura_creation + .keyboard_layout + .basic_zones() .contains(&AuraZone::Logo); - let has_lightbar = supported - .keyboard_led - .multizone_led_mode + let has_lightbar = aura_creation + .keyboard_layout + .basic_zones() .contains(&AuraZone::BarLeft) - || supported - .keyboard_led - .multizone_led_mode + || aura_creation + .keyboard_layout + .basic_zones() .contains(&AuraZone::BarRight); - ui.heading("Aura modes"); + if let Some(p) = aura_creation.layout_testing.as_ref() { + ui.heading(format!("{p:?}")); + } else { + ui.heading("Aura modes"); + } let mut item = |a: AuraModeNum, ui: &mut Ui| { if ui .selectable_value(&mut selected, a, format!("{:?}", a)) @@ -168,7 +167,7 @@ pub fn aura_modes_group( 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(supported, &states.asus_dbus) { + 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()), } @@ -177,6 +176,32 @@ pub fn aura_modes_group( 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() { + if aura_creation.keyboard_layout_index < aura_creation.keyboard_layouts.len() - 1 { + aura_creation.keyboard_layout_index += 1; + } + aura_creation.layout_testing = Some( + aura_creation.keyboard_layouts[aura_creation.keyboard_layout_index].clone(), + ); + aura_creation.keyboard_layout = + KeyLayout::from_file(aura_creation.layout_testing.as_ref().unwrap().as_path()) + .unwrap(); + } + + if ui.add(egui::Button::new("Prev layout")).clicked() { + if aura_creation.keyboard_layout_index > 0 { + aura_creation.keyboard_layout_index -= 1; + } + aura_creation.layout_testing = Some( + aura_creation.keyboard_layouts[aura_creation.keyboard_layout_index].clone(), + ); + aura_creation.keyboard_layout = + KeyLayout::from_file(aura_creation.layout_testing.as_ref().unwrap().as_path()) + .unwrap(); + } + } }); // egui::TopBottomPanel::bottom("error_bar") @@ -185,8 +210,8 @@ pub fn aura_modes_group( // 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; - // } + // states.aura.modes = AuraState::new(notif, supported, + // dbus).modes; } // if ui.add(egui::Button::new("Apply")).clicked() { // changed = true; diff --git a/rog-control-center/src/widgets/aura_power.rs b/rog-control-center/src/widgets/aura_power.rs index 54eb162c..d5afe702 100644 --- a/rog-control-center/src/widgets/aura_power.rs +++ b/rog-control-center/src/widgets/aura_power.rs @@ -1,8 +1,6 @@ use egui::{RichText, Ui}; -use rog_aura::{ - usb::{AuraDev1866, AuraDev19b6, AuraDevTuf, AuraDevice, AuraPowerDev}, - AuraZone, -}; +use rog_aura::usb::{AuraDev1866, AuraDev19b6, AuraDevTuf, AuraDevice, AuraPowerDev}; +use rog_aura::AuraZone; use rog_platform::supported::SupportedFunctions; use crate::system_state::SystemState; @@ -10,7 +8,7 @@ use crate::system_state::SystemState; pub fn aura_power_group(supported: &SupportedFunctions, states: &mut SystemState, ui: &mut Ui) { ui.heading("LED settings"); - match supported.keyboard_led.prod_id { + match supported.keyboard_led.dev_id { AuraDevice::X1854 | AuraDevice::X1869 | AuraDevice::X1866 => { aura_power1(supported, states, ui); } @@ -26,7 +24,7 @@ fn aura_power1(supported: &SupportedFunctions, states: &mut SystemState, ui: &mu 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); - if supported.keyboard_led.prod_id == AuraDevice::Tuf { + if supported.keyboard_led.dev_id == AuraDevice::Tuf { boot = enabled_states.tuf.contains(&AuraDevTuf::Boot); sleep = enabled_states.tuf.contains(&AuraDevTuf::Sleep); keyboard = enabled_states.tuf.contains(&AuraDevTuf::Awake); @@ -63,7 +61,7 @@ fn aura_power1(supported: &SupportedFunctions, states: &mut SystemState, ui: &mu if ui.toggle_value(&mut keyboard, "Keyboard").changed() { changed = true; } - if !supported.keyboard_led.multizone_led_mode.is_empty() + if !supported.keyboard_led.basic_zones.is_empty() && ui.toggle_value(&mut lightbar, "Lightbar").changed() { changed = true; @@ -84,8 +82,8 @@ fn aura_power1(supported: &SupportedFunctions, states: &mut SystemState, ui: &mu // )) // .changed() // { - // let bright = LedBrightness::from(states.aura.bright as u32); - // dbus.proxies() + // let bright = LedBrightness::from(states.aura.bright as + // u32); dbus.proxies() // .led() // .set_brightness(bright) // .map_err(|err| { @@ -98,7 +96,7 @@ fn aura_power1(supported: &SupportedFunctions, states: &mut SystemState, ui: &mu }); if changed { - if supported.keyboard_led.prod_id == AuraDevice::Tuf { + if supported.keyboard_led.dev_id == AuraDevice::Tuf { let mut enabled = Vec::new(); let mut disabled = Vec::new(); @@ -174,7 +172,7 @@ 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); - if !supported.keyboard_led.multizone_led_mode.is_empty() { + if !supported.keyboard_led.basic_zones.is_empty() { modify_x1866(lightbar, AuraDev1866::Lightbar); } @@ -203,17 +201,14 @@ fn aura_power1(supported: &SupportedFunctions, states: &mut SystemState, ui: &mu fn aura_power2(supported: &SupportedFunctions, states: &mut SystemState, ui: &mut Ui) { let enabled_states = &mut states.aura.enabled; - let has_logo = supported - .keyboard_led - .multizone_led_mode - .contains(&AuraZone::Logo); + let has_logo = supported.keyboard_led.basic_zones.contains(&AuraZone::Logo); let has_lightbar = supported .keyboard_led - .multizone_led_mode + .basic_zones .contains(&AuraZone::BarLeft) || supported .keyboard_led - .multizone_led_mode + .basic_zones .contains(&AuraZone::BarRight); let boot_bar = &mut enabled_states.x19b6.contains(&AuraDev19b6::AwakeBar); @@ -294,18 +289,14 @@ 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); - if supported - .keyboard_led - .multizone_led_mode - .contains(&AuraZone::Logo) - { + if supported.keyboard_led.basic_zones.contains(&AuraZone::Logo) { modify(*boot_logo, AuraDev19b6::BootLogo); modify(*sleep_logo, AuraDev19b6::SleepLogo); modify(*awake_logo, AuraDev19b6::AwakeLogo); } if supported .keyboard_led - .multizone_led_mode + .basic_zones .contains(&AuraZone::BarLeft) { modify(*boot_bar, AuraDev19b6::AwakeBar); diff --git a/rog-control-center/src/widgets/fan_graph.rs b/rog-control-center/src/widgets/fan_graph.rs index 584ad397..a51711cc 100644 --- a/rog-control-center/src/widgets/fan_graph.rs +++ b/rog-control-center/src/widgets/fan_graph.rs @@ -1,8 +1,10 @@ -use egui::{plot::Points, Ui}; +use egui::plot::Points; +use egui::Ui; use rog_platform::supported::SupportedFunctions; use rog_profiles::{FanCurvePU, Profile}; -use crate::{system_state::FanCurvesState, RogDbusClientBlocking}; +use crate::system_state::FanCurvesState; +use crate::RogDbusClientBlocking; pub fn fan_graphs( supported: &SupportedFunctions, diff --git a/rog-control-center/src/widgets/keyboard_layout.rs b/rog-control-center/src/widgets/keyboard_layout.rs index e5dcc7a6..3597cbc9 100644 --- a/rog-control-center/src/widgets/keyboard_layout.rs +++ b/rog-control-center/src/widgets/keyboard_layout.rs @@ -1,59 +1,152 @@ -use egui::{Align, Color32, Vec2}; -use rog_aura::{keys::KeyShape, layouts::KeyLayout, AuraModeNum}; +use egui::{Color32, Pos2}; +use rog_aura::advanced::LedCode; +use rog_aura::layouts::{KeyLayout, KeyShape}; +use rog_aura::{AdvancedAuraType, AuraModeNum}; use crate::system_state::AuraState; +const SCALE: f32 = 2.0; + +// TODO: +// - Multizone: draw regions? While iterating keys check if located in one of +// the 4 regions and mark +// - Tab for advanced effects +// - Keys need to select colour themselves + pub fn keyboard( ui: &mut egui::Ui, keyboard_layout: &KeyLayout, states: &mut AuraState, - mut colour: Color32, + colour: Color32, ) { + let mut key_colour = colour; + let mut input_colour = colour; + let (keyboard_is_multizoned, keyboard_width, keyboard_is_per_key) = + match keyboard_layout.advanced_type() { + AdvancedAuraType::PerKey => (false, 0.0, true), + 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 + } else { + 0.0 + }; + (!zones.contains(&LedCode::SingleZone), width, false) + } + }; + let mut start_pos = None; + + let y = ui.spacing().interact_size.y; + let this_size = ui.available_size(); + let keys_width = keyboard_layout.max_width() * SCALE * y; + let keys_height = keyboard_layout.max_height() * SCALE * y; + let x_start = (this_size.x - keys_width) / SCALE; + let y_start = (this_size.y - keys_height) / SCALE; + ui.spacing_mut().item_spacing = egui::vec2(0.0, 0.0); - let mut arrows_done = false; - let mut rog_done = false; + blank(ui, 0.0, y_start / y); + // Need to exclude the lightbar row if there is one + let mut keyboard_height = 0.0; for row in keyboard_layout.rows() { ui.horizontal_top(|ui| { + blank(ui, x_start / y, 0.0); for (i, key) in row.row().enumerate() { + if !key.0.is_lightbar_zone() && i == 0 { + keyboard_height += row.height() as f32 * SCALE; + } if states.current_mode == AuraModeNum::Rainbow { - colour = Color32::from_rgb( + key_colour = Color32::from_rgb( (states.wave_red[i] as u32 * 255 / 100) as u8, (states.wave_green[i] as u32 * 255 / 100) as u8, (states.wave_blue[i] as u32 * 255 / 100) as u8, ); } - // your boat - let height = if rog_done { - row.height() - } else { - // Use the first item (always a blank) to stand off the row - rog_done = true; - 1.2 - }; - let shape = KeyShape::from(key); + if (keyboard_is_multizoned && !key.0.is_lightbar_zone()) + && states.current_mode == AuraModeNum::Rainbow + { + input_colour = key_colour; + key_colour = Color32::TRANSPARENT; + } - let label = <&str>::from(key); - if shape.is_arrow_cluster() { - if !arrows_done { - arrow_cluster(ui, colour); - arrows_done = true; + let label = <&str>::from(key.0); + let mut shape = key.1.clone(); + shape.scale(SCALE); + + match shape { + KeyShape::Led { + width, + height, + pad_left, + pad_right, + pad_top, + pad_bottom, + } => { + let (pos, response) = key_shape( + ui, key_colour, width, height, pad_left, pad_right, pad_top, pad_bottom, + ); + if start_pos.is_none() { + start_pos = Some(pos); + } else if let Some(old_pos) = start_pos.as_mut() { + if !key.0.is_lightbar_zone() { + if pos.x < old_pos.x { + old_pos.x = pos.x; + } + if pos.y < old_pos.y { + old_pos.y = pos.y; + } + } + } + if response.on_hover_text(label).clicked() && keyboard_is_per_key { + // TODO: set an effect on the LedCode + } + } + KeyShape::Blank { width, height } => { + blank(ui, width, height); } - } else if shape.is_blank() || shape.is_spacer() { - blank(ui, shape.width(), height); - } else if shape.is_group() { - key_group(ui, colour, shape.width(), height).on_hover_text(label); - } else { - key_shape(ui, colour, shape.width(), height).on_hover_text(label); } } }); } + + if keyboard_is_multizoned { + let zone_width = keyboard_width * SCALE / 4.0 - 0.1; + for n in 0..4 { + if states.current_mode == AuraModeNum::Rainbow { + input_colour = Color32::from_rgba_unmultiplied( + (states.wave_red[n] as u32 * 255 / 100) as u8, + (states.wave_green[n] as u32 * 255 / 100) as u8, + (states.wave_blue[n] as u32 * 255 / 100) as u8, + 70, + ); + } + if let Some(mut pos) = start_pos { + pos.x += n as f32 * zone_width * y; + let response = zone_shape(ui, input_colour, pos, zone_width, keyboard_height); + let label = format!("Zone {}", 1 + n); + if response.on_hover_text(label).clicked() { + // TODO: set an effect on the zone + } + } + } + } } -fn key_shape(ui: &mut egui::Ui, colour: Color32, ux: f32, uy: f32) -> egui::Response { - let desired_size = ui.spacing().interact_size.y * egui::vec2(2.0 * ux, 2.0 * uy); +#[allow(clippy::too_many_arguments)] +fn key_shape( + ui: &mut egui::Ui, + colour: Color32, + width: f32, + height: f32, + pad_left: f32, + pad_right: f32, + pad_top: f32, + pad_bottom: f32, +) -> (egui::Pos2, egui::Response) { + // First, get some space + let y = ui.spacing().interact_size.y; + let desired_size = y * egui::vec2(width + pad_left + pad_right, height + pad_top + pad_bottom); let (mut rect, mut response) = ui.allocate_exact_size(desired_size, egui::Sense::click()); - rect = rect.shrink(3.0); + // rect = rect.shrink(3.0); if response.clicked() { response.mark_changed(); } @@ -62,62 +155,56 @@ fn key_shape(ui: &mut egui::Ui, colour: Color32, ux: f32, uy: f32) -> egui::Resp }); if ui.is_rect_visible(rect) { + // Now set the actual visible rect let visuals = ui.style().interact_selectable(&response, true); - let rect = rect.expand(visuals.expansion); + let size = y * egui::vec2(width, height); + rect.set_width(size.x); + rect.set_height(size.y); + let center = Pos2::new( + rect.center().x + pad_left * y, + rect.center().y + pad_top * y, + ); + rect.set_center(center); + // let rect = rect.expand(visuals.expansion); + ui.painter().rect(rect, 0.1, colour, visuals.fg_stroke); + } + + (rect.left_top(), response) +} + +#[allow(clippy::too_many_arguments)] +fn zone_shape( + ui: &mut egui::Ui, + mut colour: Color32, + pos: Pos2, + width: f32, + height: f32, +) -> egui::Response { + // First, get some space + let y = ui.spacing().interact_size.y; + let desired_size = y * egui::vec2(width, height); + let rect = egui::Rect::from_min_size(pos, desired_size); + let mut response = ui.allocate_rect(rect, egui::Sense::click()); + // rect = rect.shrink(3.0); + if response.clicked() { + response.mark_changed(); + } + response.widget_info(|| { + egui::WidgetInfo::selected(egui::WidgetType::Checkbox, response.clicked(), "") + }); + + if ui.is_rect_visible(rect) { + // Now set the actual visible rect + let visuals = ui.style().interact_selectable(&response, true); + // let rect = rect.expand(visuals.expansion); + colour[3] = 20; ui.painter().rect(rect, 0.1, colour, visuals.fg_stroke); } response } -fn key_group(ui: &mut egui::Ui, colour: Color32, ux: f32, uy: f32) -> egui::Response { - let desired_size = ui.spacing().interact_size.y * egui::vec2(2.0 * ux, 2.0 * uy); - let (mut rect, mut response) = ui.allocate_exact_size(desired_size, egui::Sense::click()); - rect = rect.shrink2(Vec2::new(3.0, 3.0)); - if response.clicked() { - response.mark_changed(); - } - response.widget_info(|| { - egui::WidgetInfo::selected(egui::WidgetType::Checkbox, response.clicked(), "") - }); - - if ui.is_rect_visible(rect) { - let visuals = ui.style().interact_selectable(&response, true); - let rect = rect.expand(visuals.expansion); - let mut stroke = visuals.fg_stroke; - stroke.color = visuals.bg_fill; - ui.painter().rect(rect, 0.1, colour, stroke); - } - - response -} - fn blank(ui: &mut egui::Ui, ux: f32, uy: f32) { - let desired_size = ui.spacing().interact_size.y * egui::vec2(2.0 * ux, 2.0 * uy); + let desired_size = ui.spacing().interact_size.y * egui::vec2(ux, uy); ui.allocate_exact_size(desired_size, egui::Sense::click()); } - -/// Draws entire arrow cluster block. This is visibly different to the split-arrows. -fn arrow_cluster(ui: &mut egui::Ui, colour: Color32) { - let height = 0.7; - let space = KeyShape::ArrowSpacer; - let shape = KeyShape::Arrow; - ui.horizontal_top(|ui| { - ui.with_layout(egui::Layout::top_down(Align::LEFT), |ui| { - blank(ui, space.width(), height); - ui.horizontal(|ui| { - blank(ui, KeyShape::RowEndSpacer.width(), height); - blank(ui, KeyShape::RowEndSpacer.width(), height); - key_shape(ui, colour, shape.width(), height).on_hover_text("Left"); - }); - }); - ui.with_layout(egui::Layout::top_down(Align::LEFT), |ui| { - key_shape(ui, colour, shape.width(), height).on_hover_text("Up"); - key_shape(ui, colour, shape.width(), height).on_hover_text("Down"); - }); - ui.with_layout(egui::Layout::top_down(Align::LEFT), |ui| { - blank(ui, space.width(), height); - key_shape(ui, colour, shape.width(), height).on_hover_text("Right"); - }); - }); -} diff --git a/rog-control-center/src/widgets/rog_bios.rs b/rog-control-center/src/widgets/rog_bios.rs index 8bdeb100..7a22039d 100644 --- a/rog-control-center/src/widgets/rog_bios.rs +++ b/rog-control-center/src/widgets/rog_bios.rs @@ -1,8 +1,10 @@ -use crate::system_state::SystemState; use egui::Ui; -use rog_platform::{platform::GpuMode, supported::SupportedFunctions}; +use rog_platform::platform::GpuMode; +use rog_platform::supported::SupportedFunctions; use rog_profiles::Profile; +use crate::system_state::SystemState; + pub fn platform_profile(states: &mut SystemState, ui: &mut Ui) { ui.heading("Platform profile"); diff --git a/rog-control-center/src/widgets/side_panel.rs b/rog-control-center/src/widgets/side_panel.rs index 40c14a23..b90792f5 100644 --- a/rog-control-center/src/widgets/side_panel.rs +++ b/rog-control-center/src/widgets/side_panel.rs @@ -28,7 +28,7 @@ impl RogApp { } } - if !self.supported.keyboard_led.stock_led_modes.is_empty() { + if !self.supported.keyboard_led.basic_modes.is_empty() { ui.separator(); if ui .selectable_value(page, Page::AuraEffects, "Keyboard Aura") diff --git a/rog-control-center/src/widgets/top_bar.rs b/rog-control-center/src/widgets/top_bar.rs index cc062bca..fd727034 100644 --- a/rog-control-center/src/widgets/top_bar.rs +++ b/rog-control-center/src/widgets/top_bar.rs @@ -12,7 +12,6 @@ impl RogApp { egui::warn_if_debug_build(ui); }); - /***********************************************************/ // Drag area let text_color = ctx.style().visuals.text_color(); let mut titlebar_rect = ui.available_rect_before_wrap(); @@ -23,8 +22,9 @@ impl RogApp { { frame.drag_window(); } - /***********************************************************/ + let height = titlebar_rect.height(); + // Paint the title: ui.painter().text( titlebar_rect.right_top() + vec2(0.0, height / 2.0), @@ -35,9 +35,10 @@ impl RogApp { ); // // Add the close button: // let close_response = ui.put( - // Rect::from_min_size(titlebar_rect.right_top(), Vec2::splat(height)), - // Button::new(RichText::new("❌").size(height - 4.0)).frame(false), - // ); + // Rect::from_min_size(titlebar_rect.right_top(), + // Vec2::splat(height)), + // Button::new(RichText::new("❌").size(height - + // 4.0)).frame(false), ); // if close_response.clicked() { // frame.close(); // } diff --git a/rog-dbus/src/zbus_anime.rs b/rog-dbus/src/zbus_anime.rs index fa129faa..228a0830 100644 --- a/rog-dbus/src/zbus_anime.rs +++ b/rog-dbus/src/zbus_anime.rs @@ -15,7 +15,8 @@ trait Anime { /// Set whether the AniMe is displaying images/data fn set_on_off(&self, status: bool) -> zbus::Result<()>; - /// Writes a data stream of length. Will force system thread to exit until it is restarted + /// 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 @@ -26,7 +27,8 @@ trait Anime { #[dbus_proxy(property)] fn boot_enabled(&self) -> zbus::Result; - /// Notify listeners of the status of AniMe LED power and factory system-status animations + /// 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<()>; } diff --git a/rog-dbus/src/zbus_led.rs b/rog-dbus/src/zbus_led.rs index 0f7b4cf5..17f2bdd2 100644 --- a/rog-dbus/src/zbus_led.rs +++ b/rog-dbus/src/zbus_led.rs @@ -1,7 +1,8 @@ //! # DBus interface proxy for: `org.asuslinux.Daemon` //! -//! This code was generated by `zbus-xmlgen` `1.0.0` from DBus introspection data. -//! Source: `Interface '/org/asuslinux/Aura' from service 'org.asuslinux.Daemon' on system bus`. +//! 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`. //! //! You may prefer to adapt it, instead of using it verbatim. //! @@ -21,12 +22,13 @@ use std::collections::BTreeMap; -use zbus::dbus_proxy; -use zbus::{blocking::Connection, Result}; +use rog_aura::advanced::UsbPackets; +use rog_aura::usb::AuraPowerDev; +use rog_aura::{AuraEffect, AuraModeNum, LedBrightness}; +use zbus::blocking::Connection; +use zbus::{dbus_proxy, Result}; -use rog_aura::{usb::AuraPowerDev, AuraEffect, AuraModeNum, LedBrightness, PerKeyRaw}; - -const BLOCKING_TIME: u64 = 40; // 100ms = 10 FPS, max 50ms = 20 FPS, 40ms = 25 FPS +const BLOCKING_TIME: u64 = 33; // 100ms = 10 FPS, max 50ms = 20 FPS, 40ms = 25 FPS #[dbus_proxy( interface = "org.asuslinux.Daemon", @@ -53,7 +55,10 @@ trait Led { fn set_leds_power(&self, options: AuraPowerDev, enabled: bool) -> zbus::Result<()>; - fn per_key_raw(&self, data: PerKeyRaw) -> zbus::fdo::Result<()>; + /// On machine that have some form of either per-key keyboard or per-zone + /// this can be used to write custom effects over dbus. The input is a + /// nested `Vec>` where `Vec` is a raw USB packet + fn direct_addressing_raw(&self, data: UsbPackets) -> zbus::fdo::Result<()>; /// NotifyLed signal #[dbus_proxy(signal)] @@ -95,8 +100,8 @@ impl<'a> LedProxyPerkey<'a> { /// Intentionally blocks for 10ms after sending to allow the block to /// be written to the keyboard EC. This should not be async. #[inline] - pub fn set_per_key(&self, per_key_raw: PerKeyRaw) -> Result<()> { - self.0.per_key_raw(per_key_raw)?; + pub fn direct_addressing_raw(&self, direct_raw: UsbPackets) -> Result<()> { + self.0.direct_addressing_raw(direct_raw)?; std::thread::sleep(std::time::Duration::from_millis(BLOCKING_TIME)); Ok(()) } diff --git a/rog-dbus/src/zbus_platform.rs b/rog-dbus/src/zbus_platform.rs index 498a724d..b59e8f5f 100644 --- a/rog-dbus/src/zbus_platform.rs +++ b/rog-dbus/src/zbus_platform.rs @@ -1,7 +1,8 @@ //! # DBus interface proxy for: `org.asuslinux.Daemon` //! -//! This code was generated by `zbus-xmlgen` `1.0.0` from DBus introspection data. -//! Source: `Interface '/org/asuslinux/Platform' from service 'org.asuslinux.Daemon' on system bus`. +//! This code was generated by `zbus-xmlgen` `1.0.0` from DBus introspection +//! data. Source: `Interface '/org/asuslinux/Platform' from service +//! 'org.asuslinux.Daemon' on system bus`. //! //! You may prefer to adapt it, instead of using it verbatim. //! diff --git a/rog-dbus/src/zbus_power.rs b/rog-dbus/src/zbus_power.rs index 55160737..3a16e34e 100644 --- a/rog-dbus/src/zbus_power.rs +++ b/rog-dbus/src/zbus_power.rs @@ -1,7 +1,8 @@ //! # DBus interface proxy for: `org.asuslinux.Daemon` //! -//! This code was generated by `zbus-xmlgen` `1.0.0` from DBus introspection data. -//! Source: `Interface '/org/asuslinux/Charge' from service 'org.asuslinux.Daemon' on system bus`. +//! This code was generated by `zbus-xmlgen` `1.0.0` from DBus introspection +//! data. Source: `Interface '/org/asuslinux/Charge' from service +//! 'org.asuslinux.Daemon' on system bus`. //! //! You may prefer to adapt it, instead of using it verbatim. //! diff --git a/rog-dbus/src/zbus_profile.rs b/rog-dbus/src/zbus_profile.rs index 2f340c08..24a58b5d 100644 --- a/rog-dbus/src/zbus_profile.rs +++ b/rog-dbus/src/zbus_profile.rs @@ -1,7 +1,8 @@ //! # DBus interface proxy for: `org.asuslinux.Daemon` //! -//! This code was generated by `zbus-xmlgen` `1.0.0` from DBus introspection data. -//! Source: `Interface '/org/asuslinux/Profile' from service 'org.asuslinux.Daemon' on system bus`. +//! This code was generated by `zbus-xmlgen` `1.0.0` from DBus introspection +//! data. Source: `Interface '/org/asuslinux/Profile' from service +//! 'org.asuslinux.Daemon' on system bus`. //! //! You may prefer to adapt it, instead of using it verbatim. //! @@ -19,10 +20,8 @@ //! //! …consequently `zbus-xmlgen` did not generate code for the above interfaces. -use rog_profiles::{ - fan_curve_set::{CurveData, FanCurveSet}, - Profile, -}; +use rog_profiles::fan_curve_set::{CurveData, FanCurveSet}; +use rog_profiles::Profile; use zbus::dbus_proxy; #[dbus_proxy( @@ -56,16 +55,18 @@ trait Profile { /// currently in if profile == None. Will also activate the fan curve. fn set_fan_curve(&self, profile: Profile, curve: CurveData) -> zbus::Result<()>; - /// Reset the stored (self) and device curve to the defaults of the platform. + /// Reset the stored (self) and device curve to the defaults of the + /// platform. /// - /// Each platform_profile has a different default and the defualt can be read - /// only for the currently active profile. + /// Each platform_profile has a different default and the defualt can be + /// read only for the currently active profile. fn set_active_curve_to_defaults(&self) -> zbus::Result<()>; - /// Reset the stored (self) and device curve to the defaults of the platform. + /// Reset the stored (self) and device curve to the defaults of the + /// platform. /// - /// Each platform_profile has a different default and the defualt can be read - /// only for the currently active profile. + /// Each platform_profile has a different default and the defualt can be + /// read only for the currently active profile. fn reset_profile_curves(&self, profile: Profile) -> zbus::fdo::Result<()>; /// NotifyProfile signal diff --git a/rog-dbus/src/zbus_supported.rs b/rog-dbus/src/zbus_supported.rs index 649e5f5d..4862ca2c 100644 --- a/rog-dbus/src/zbus_supported.rs +++ b/rog-dbus/src/zbus_supported.rs @@ -1,7 +1,8 @@ //! # DBus interface proxy for: `org.asuslinux.Daemon` //! -//! This code was generated by `zbus-xmlgen` `1.0.0` from DBus introspection data. -//! Source: `Interface '/org/asuslinux/Supported' from service 'org.asuslinux.Daemon' on system bus`. +//! This code was generated by `zbus-xmlgen` `1.0.0` from DBus introspection +//! data. Source: `Interface '/org/asuslinux/Supported' from service +//! 'org.asuslinux.Daemon' on system bus`. //! //! You may prefer to adapt it, instead of using it verbatim. //! diff --git a/rog-platform/src/error.rs b/rog-platform/src/error.rs index 992e8a5b..e8c14ab8 100644 --- a/rog-platform/src/error.rs +++ b/rog-platform/src/error.rs @@ -36,7 +36,12 @@ impl fmt::Display for PlatformError { PlatformError::AttrNotFound(deets) => write!(f, "Attribute not found: {}", deets), PlatformError::Io(deets) => write!(f, "std::io error: {}", deets), PlatformError::MissingFunction(deets) => write!(f, "Missing functionality: {}", deets), - PlatformError::MissingLedBrightNode(path, error) => write!(f, "Led node at {} is missing, please check you have the required patch or dkms module installed: {}", path, error), + PlatformError::MissingLedBrightNode(path, error) => write!( + f, + "Led node at {} is missing, please check you have the required patch or dkms \ + module installed: {}", + path, error + ), PlatformError::IoPath(path, detail) => write!(f, "{} {}", path, detail), PlatformError::NoAuraKeyboard => write!(f, "No supported Aura keyboard"), PlatformError::NoAuraNode => write!(f, "No Aura keyboard node found"), diff --git a/rog-platform/src/hid_raw.rs b/rog-platform/src/hid_raw.rs index 3d7d9f7f..46fbe994 100644 --- a/rog-platform/src/hid_raw.rs +++ b/rog-platform/src/hid_raw.rs @@ -1,4 +1,6 @@ -use std::{fs::OpenOptions, io::Write, path::PathBuf}; +use std::fs::OpenOptions; +use std::io::Write; +use std::path::PathBuf; use log::{info, warn}; diff --git a/rog-platform/src/keyboard_led.rs b/rog-platform/src/keyboard_led.rs index d5bba6a0..056091d1 100644 --- a/rog-platform/src/keyboard_led.rs +++ b/rog-platform/src/keyboard_led.rs @@ -2,11 +2,8 @@ use std::path::PathBuf; use log::{info, warn}; -use crate::{ - attr_u8, - error::{PlatformError, Result}, - has_attr, set_attr_u8_array, to_device, -}; +use crate::error::{PlatformError, Result}; +use crate::{attr_u8, has_attr, set_attr_u8_array, to_device}; #[derive(Debug, Default, PartialEq, Eq, PartialOrd, Clone)] pub struct KeyboardLed { @@ -14,6 +11,24 @@ pub struct KeyboardLed { } impl KeyboardLed { + attr_u8!("brightness", path); + + has_attr!("kbd_rgb_mode" path); + + set_attr_u8_array!( + /// kbd_rgb_mode can only be set, not read back + "kbd_rgb_mode" + path + ); + + has_attr!("kbd_rgb_state" path); + + set_attr_u8_array!( + /// kbd_rgb_state can only be set, not read back + "kbd_rgb_state" + path + ); + pub fn new() -> Result { let mut enumerator = udev::Enumerator::new().map_err(|err| { warn!("{}", err); @@ -47,20 +62,4 @@ impl KeyboardLed { "asus::kbd_backlight not found".into(), )) } - - attr_u8!("brightness", path); - - has_attr!("kbd_rgb_mode" path); - set_attr_u8_array!( - /// kbd_rgb_mode can only be set, not read back - "kbd_rgb_mode" - path - ); - - has_attr!("kbd_rgb_state" path); - set_attr_u8_array!( - /// kbd_rgb_state can only be set, not read back - "kbd_rgb_state" - path - ); } diff --git a/rog-platform/src/lib.rs b/rog-platform/src/lib.rs index c4c030d6..ffc3a89a 100644 --- a/rog-platform/src/lib.rs +++ b/rog-platform/src/lib.rs @@ -118,13 +118,13 @@ mod tests { // .parent_with_subsystem_devtype("usb", "usb_device") // .map_err(|err| { // warn!("{}", err); -// PlatformError::Udev("parent_with_subsystem_devtype failed".into(), err) -// })? +// PlatformError::Udev("parent_with_subsystem_devtype +// failed".into(), err) })? // { // if parent // .attribute_value("idProduct") -// .ok_or_else(|| PlatformError::NotFound("LED idProduct".into()))? -// == id_product +// .ok_or_else(|| PlatformError::NotFound("LED +// idProduct".into()))? == id_product // { // if let Some(dev_node) = device.devnode() { // info!("Using device at: {:?} for LED control", dev_node); diff --git a/rog-platform/src/platform.rs b/rog-platform/src/platform.rs index ef84db77..c208d653 100644 --- a/rog-platform/src/platform.rs +++ b/rog-platform/src/platform.rs @@ -1,14 +1,13 @@ -use std::{fmt::Display, path::PathBuf, str::FromStr}; +use std::fmt::Display; +use std::path::PathBuf; +use std::str::FromStr; use log::{info, warn}; use serde::{Deserialize, Serialize}; use zbus::zvariant::Type; -use crate::{ - attr_bool, attr_u8, - error::{PlatformError, Result}, - to_device, -}; +use crate::error::{PlatformError, Result}; +use crate::{attr_bool, attr_u8, to_device}; /// The "platform" device provides access to things like: /// - `dgpu_disable` @@ -24,6 +23,21 @@ pub struct AsusPlatform { } impl AsusPlatform { + attr_bool!("dgpu_disable", path); + + attr_bool!("egpu_enable", path); + + attr_bool!("panel_od", path); + + attr_bool!("gpu_mux_mode", path); + + // This is technically the same as `platform_profile` since both are tied + // in-kernel + attr_u8!("throttle_thermal_policy", path); + + // The acpi platform_profile support + attr_u8!("platform_profile", pp_path); + pub fn new() -> Result { let mut enumerator = udev::Enumerator::new().map_err(|err| { warn!("{}", err); @@ -54,15 +68,6 @@ impl AsusPlatform { "asus-nb-wmi not found".into(), )) } - - attr_bool!("dgpu_disable", path); - attr_bool!("egpu_enable", path); - attr_bool!("panel_od", path); - attr_bool!("gpu_mux_mode", path); - // This is technically the same as `platform_profile` since both are tied in-kernel - attr_u8!("throttle_thermal_policy", path); - // The acpi platform_profile support - attr_u8!("platform_profile", pp_path); } #[derive(Serialize, Deserialize, Default, Type, Debug, PartialEq, Eq, Clone, Copy)] diff --git a/rog-platform/src/power.rs b/rog-platform/src/power.rs index a4b80c4d..9c5ef43f 100644 --- a/rog-platform/src/power.rs +++ b/rog-platform/src/power.rs @@ -2,11 +2,8 @@ use std::path::PathBuf; use log::{info, warn}; -use crate::{ - attr_u8, - error::{PlatformError, Result}, - to_device, -}; +use crate::error::{PlatformError, Result}; +use crate::{attr_u8, to_device}; /// The "platform" device provides access to things like: /// - `dgpu_disable` @@ -23,9 +20,14 @@ pub struct AsusPower { } impl AsusPower { + attr_u8!("charge_control_end_threshold", battery); + + attr_u8!("online", mains); + /// When checking for battery this will look in order: /// - if attr `manufacturer` contains `asus` - /// - if attr `charge_control_end_threshold` exists and `energy_full_design` >= 50 watt + /// - if attr `charge_control_end_threshold` exists and `energy_full_design` + /// >= 50 watt /// - if syspath end conatins `BAT` /// - if attr `type` is `battery` (last resort) pub fn new() -> Result { @@ -62,7 +64,11 @@ impl AsusPower { .attribute_value("charge_control_end_threshold") .is_some() { - info!("Found battery power at {:?}, matched charge_control_end_threshold", device.sysname()); + info!( + "Found battery power at {:?}, matched \ + charge_control_end_threshold", + device.sysname() + ); battery = Some(device.syspath().to_path_buf()); } else if device.sysname().to_string_lossy().starts_with("BAT") { info!( @@ -100,7 +106,4 @@ impl AsusPower { "Did not find a battery".to_owned(), )) } - - attr_u8!("charge_control_end_threshold", battery); - attr_u8!("online", mains); } diff --git a/rog-platform/src/supported.rs b/rog-platform/src/supported.rs index 4c46e9ad..084977bb 100644 --- a/rog-platform/src/supported.rs +++ b/rog-platform/src/supported.rs @@ -1,6 +1,8 @@ -use rog_aura::{usb::AuraDevice, AuraModeNum, AuraZone}; -use serde_derive::{Deserialize, Serialize}; use std::fmt; + +use rog_aura::usb::AuraDevice; +use rog_aura::{AdvancedAuraType, AuraModeNum, AuraZone}; +use serde_derive::{Deserialize, Serialize}; use zbus::zvariant::Type; #[derive(Serialize, Deserialize, Type, Debug, Default, Clone)] @@ -26,13 +28,31 @@ pub struct PlatformProfileFunctions { pub fan_curves: bool, } +#[derive(Serialize, Deserialize, Default, Type, Debug, Clone)] +pub enum AdvancedAura { + #[default] + None, + Zoned, + PerKey, +} + +impl From for AdvancedAura { + fn from(a: AdvancedAuraType) -> Self { + match a { + AdvancedAuraType::None => Self::None, + AdvancedAuraType::Zoned(_) => Self::Zoned, + AdvancedAuraType::PerKey => Self::PerKey, + } + } +} + #[derive(Serialize, Deserialize, Type, Debug, Default, Clone)] pub struct LedSupportedFunctions { - pub prod_id: AuraDevice, - pub brightness_set: bool, - pub stock_led_modes: Vec, - pub multizone_led_mode: Vec, - pub per_key_led_mode: bool, + pub dev_id: AuraDevice, + pub brightness: bool, + pub basic_modes: Vec, + pub basic_zones: Vec, + pub advanced_type: AdvancedAura, } #[derive(Serialize, Deserialize, Type, Debug, Default, Clone)] @@ -46,7 +66,7 @@ pub struct RogBiosSupportedFunctions { impl fmt::Display for SupportedFunctions { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - writeln!(f, "{}", self.anime_ctrl)?; + writeln!(f, "\n{}", self.anime_ctrl)?; writeln!(f, "{}", self.charge_ctrl)?; writeln!(f, "{}", self.platform_profile)?; writeln!(f, "{}", self.keyboard_led)?; @@ -80,10 +100,11 @@ impl fmt::Display for PlatformProfileFunctions { impl fmt::Display for LedSupportedFunctions { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { writeln!(f, "LED:")?; - writeln!(f, "\tBrightness control: {}", self.brightness_set)?; - writeln!(f, "\tStock LED modes: {:?}", self.stock_led_modes)?; - writeln!(f, "\tMultizone LED mode: {:?}", self.multizone_led_mode)?; - writeln!(f, "\tPer key LED mode: {}", self.per_key_led_mode) + writeln!(f, "\tDevice ID: {:?}", self.dev_id)?; + writeln!(f, "\tBrightness control: {}", self.brightness)?; + writeln!(f, "\tBasic modes: {:?}", self.basic_modes)?; + writeln!(f, "\tBasic zones: {:?}", self.basic_zones)?; + writeln!(f, "\tAdvanced modes: {:?}", self.advanced_type) } } impl fmt::Display for RogBiosSupportedFunctions { diff --git a/rog-platform/src/usb_raw.rs b/rog-platform/src/usb_raw.rs index b28db657..9670959d 100644 --- a/rog-platform/src/usb_raw.rs +++ b/rog-platform/src/usb_raw.rs @@ -1,6 +1,7 @@ -use rusb::{Device, DeviceHandle}; use std::time::Duration; +use rusb::{Device, DeviceHandle}; + use crate::error::{PlatformError, Result}; #[derive(Debug, PartialEq, Eq)] diff --git a/rog-profiles/src/fan_curve_set.rs b/rog-profiles/src/fan_curve_set.rs index eea11a02..fb47881a 100644 --- a/rog-profiles/src/fan_curve_set.rs +++ b/rog-profiles/src/fan_curve_set.rs @@ -1,10 +1,10 @@ use serde_derive::{Deserialize, Serialize}; - use udev::Device; #[cfg(feature = "dbus")] use zbus::zvariant::Type; -use crate::{error::ProfileError, FanCurvePU}; +use crate::error::ProfileError; +use crate::FanCurvePU; pub(crate) fn pwm_str(fan: char, index: usize) -> String { let mut buf = "pwm1_auto_point1_pwm".to_string(); @@ -62,12 +62,15 @@ impl From<&CurveData> for String { impl std::str::FromStr for CurveData { type Err = ProfileError; - /// Parse a string to the correct values that the fan curve kernel driver expects + /// Parse a string to the correct values that the fan curve kernel driver + /// expects /// - /// If the fan curve is given with percentage char '%' then the fan power values are converted - /// otherwise the expected fan power range is 0-255. + /// If the fan curve is given with percentage char '%' then the fan power + /// values are converted otherwise the expected fan power range is + /// 0-255. /// - /// Temperature range is 0-255 in degrees C. You don't want to be setting over 100. + /// Temperature range is 0-255 in degrees C. You don't want to be setting + /// over 100. fn from_str(input: &str) -> Result { let mut temp = [0u8; 8]; let mut pwm = [0u8; 8]; @@ -313,6 +316,10 @@ mod tests { fn set_to_string() { let set = FanCurveSet::default(); let string = String::from(&set); - assert_eq!(string.as_str(), "Enabled: false, CPU: 0c:0%,0c:0%,0c:0%,0c:0%,0c:0%,0c:0%,0c:0%,0c:0%, GPU: 0c:0%,0c:0%,0c:0%,0c:0%,0c:0%,0c:0%,0c:0%,0c:0%"); + assert_eq!( + string.as_str(), + "Enabled: false, CPU: 0c:0%,0c:0%,0c:0%,0c:0%,0c:0%,0c:0%,0c:0%,0c:0%, GPU: \ + 0c:0%,0c:0%,0c:0%,0c:0%,0c:0%,0c:0%,0c:0%,0c:0%" + ); } } diff --git a/rog-profiles/src/lib.rs b/rog-profiles/src/lib.rs index 00667c74..aaf8f030 100644 --- a/rog-profiles/src/lib.rs +++ b/rog-profiles/src/lib.rs @@ -1,17 +1,14 @@ pub mod error; pub mod fan_curve_set; -use std::{ - fmt::Display, - fs::OpenOptions, - io::{Read, Write}, - path::Path, -}; +use std::fmt::Display; +use std::fs::OpenOptions; +use std::io::{Read, Write}; +use std::path::Path; use error::ProfileError; use fan_curve_set::{CurveData, FanCurveSet}; use serde_derive::{Deserialize, Serialize}; - use udev::Device; #[cfg(feature = "dbus")] use zbus::zvariant::Type; @@ -207,10 +204,11 @@ impl FanCurveProfiles { } } - /// Reset the stored (self) and device curve to the defaults of the platform. + /// Reset the stored (self) and device curve to the defaults of the + /// platform. /// - /// Each `platform_profile` has a different default and the defualt can be read - /// only for the currently active profile. + /// Each `platform_profile` has a different default and the defualt can be + /// read only for the currently active profile. pub fn set_active_curve_to_defaults( &mut self, profile: Profile, @@ -232,8 +230,8 @@ impl FanCurveProfiles { } /// Write the curves for the selected profile to the device. If the curve is - /// in the enabled list it will become active. If the curve is zeroed it will be initialised - /// to a default read from the system. + /// in the enabled list it will become active. If the curve is zeroed it + /// will be initialised to a default read from the system. // TODO: Make this return an error if curve is zeroed pub fn write_profile_curve_to_platform( &mut self, diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 00000000..b22a925c --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,15 @@ +condense_wildcard_suffixes = true +edition = "2021" +format_strings = true +group_imports = "StdExternalCrate" +hex_literal_case = "Lower" +imports_granularity = "Module" +max_width = 100 +normalize_comments = true +normalize_doc_attributes = true +reorder_impl_items = true +reorder_imports = true +reorder_modules = true +unstable_features = true +use_field_init_shorthand = true +wrap_comments = true