Create rog-platform, refactor rogcc ipc-file handling

- Create new rog-platform crate to manage all i/o in a universal way
  + kbd-led handling
  + platform handling (asus-nb-wmi)
  + hidraw
  + usbraw
- Refactor how ROGCC handles IPC for background open, run-in-bg
This commit is contained in:
Luke D. Jones
2022-08-12 15:22:06 +12:00
parent 45268bfb2b
commit 308fba9413
31 changed files with 860 additions and 635 deletions

View File

@@ -5,6 +5,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased ] ## [Unreleased ]
### Changed
- Create new rog-platform crate to manage all i/o in a universal way
+ kbd-led handling (requires kernel patches, TUF specific)
+ platform handling (asus-nb-wmi)
+ hidraw
+ usbraw
- Refactor how ROGCC handles IPC for background open, run-in-bg
## [4.3.4] - 2022-08-03 ## [4.3.4] - 2022-08-03
### Bugfix ### Bugfix

157
Cargo.lock generated
View File

@@ -119,9 +119,9 @@ dependencies = [
[[package]] [[package]]
name = "async-channel" name = "async-channel"
version = "1.6.1" version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319" checksum = "e14485364214912d3b19cc3435dde4df66065127f05fa0d75c712f36f12c2f28"
dependencies = [ dependencies = [
"concurrent-queue", "concurrent-queue",
"event-listener", "event-listener",
@@ -228,9 +228,9 @@ checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524"
[[package]] [[package]]
name = "async-trait" name = "async-trait"
version = "0.1.56" version = "0.1.57"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96cf8829f67d2eab0b2dfa42c5d0ef737e0724e4a82b01b3e292456202b19716" checksum = "76464446b8bc32758d7e88ee1a804d9914cd9b1cb264c029899680b0be29826f"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -332,9 +332,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]] [[package]]
name = "bytes" name = "bytes"
version = "1.2.0" version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0b3de4a0c5e67e16066a0715723abd91edc2f9001d09c46e1dca929351e130e" checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db"
[[package]] [[package]]
name = "cache-padded" name = "cache-padded"
@@ -435,9 +435,9 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
[[package]] [[package]]
name = "combine" name = "combine"
version = "4.6.4" version = "4.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a604e93b79d1808327a6fca85a6f2d69de66461e7620f5a4cbf5fb4d1d7c948" checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4"
dependencies = [ dependencies = [
"bytes", "bytes",
"memchr", "memchr",
@@ -445,9 +445,9 @@ dependencies = [
[[package]] [[package]]
name = "concurrent-queue" name = "concurrent-queue"
version = "1.2.2" version = "1.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" checksum = "af4780a44ab5696ea9e28294517f1fffb421a83a25af521333c838635509db9c"
dependencies = [ dependencies = [
"cache-padded", "cache-padded",
] ]
@@ -551,16 +551,15 @@ dependencies = [
"rog_anime", "rog_anime",
"rog_aura", "rog_aura",
"rog_dbus", "rog_dbus",
"rog_platform",
"rog_profiles", "rog_profiles",
"rog_supported", "rog_supported",
"rusb",
"serde", "serde",
"serde_derive", "serde_derive",
"serde_json", "serde_json",
"smol", "smol",
"sysfs-class", "sysfs-class",
"toml", "toml",
"udev",
"zbus", "zbus",
"zvariant", "zvariant",
] ]
@@ -740,7 +739,7 @@ checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
[[package]] [[package]]
name = "eframe" name = "eframe"
version = "0.18.0" version = "0.18.0"
source = "git+https://github.com/emilk/egui#a7012cf8a628d125b211fd164ac12fbb898f316e" source = "git+https://github.com/emilk/egui#7c25a9238e8b899b4d5653db98a583e69b790b17"
dependencies = [ dependencies = [
"bytemuck", "bytemuck",
"dark-light", "dark-light",
@@ -761,7 +760,7 @@ dependencies = [
[[package]] [[package]]
name = "egui" name = "egui"
version = "0.18.1" version = "0.18.1"
source = "git+https://github.com/emilk/egui#a7012cf8a628d125b211fd164ac12fbb898f316e" source = "git+https://github.com/emilk/egui#7c25a9238e8b899b4d5653db98a583e69b790b17"
dependencies = [ dependencies = [
"ahash 0.7.6", "ahash 0.7.6",
"epaint", "epaint",
@@ -772,7 +771,7 @@ dependencies = [
[[package]] [[package]]
name = "egui-winit" name = "egui-winit"
version = "0.18.0" version = "0.18.0"
source = "git+https://github.com/emilk/egui#a7012cf8a628d125b211fd164ac12fbb898f316e" source = "git+https://github.com/emilk/egui#7c25a9238e8b899b4d5653db98a583e69b790b17"
dependencies = [ dependencies = [
"arboard", "arboard",
"egui", "egui",
@@ -786,7 +785,7 @@ dependencies = [
[[package]] [[package]]
name = "egui_glow" name = "egui_glow"
version = "0.18.1" version = "0.18.1"
source = "git+https://github.com/emilk/egui#a7012cf8a628d125b211fd164ac12fbb898f316e" source = "git+https://github.com/emilk/egui#7c25a9238e8b899b4d5653db98a583e69b790b17"
dependencies = [ dependencies = [
"bytemuck", "bytemuck",
"egui", "egui",
@@ -800,7 +799,7 @@ dependencies = [
[[package]] [[package]]
name = "emath" name = "emath"
version = "0.18.0" version = "0.18.0"
source = "git+https://github.com/emilk/egui#a7012cf8a628d125b211fd164ac12fbb898f316e" source = "git+https://github.com/emilk/egui#7c25a9238e8b899b4d5653db98a583e69b790b17"
dependencies = [ dependencies = [
"bytemuck", "bytemuck",
] ]
@@ -865,7 +864,7 @@ dependencies = [
[[package]] [[package]]
name = "epaint" name = "epaint"
version = "0.18.1" version = "0.18.1"
source = "git+https://github.com/emilk/egui#a7012cf8a628d125b211fd164ac12fbb898f316e" source = "git+https://github.com/emilk/egui#7c25a9238e8b899b4d5653db98a583e69b790b17"
dependencies = [ dependencies = [
"ab_glyph", "ab_glyph",
"ahash 0.7.6", "ahash 0.7.6",
@@ -888,9 +887,9 @@ dependencies = [
[[package]] [[package]]
name = "event-listener" name = "event-listener"
version = "2.5.2" version = "2.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71" checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
[[package]] [[package]]
name = "fastrand" name = "fastrand"
@@ -1038,9 +1037,9 @@ dependencies = [
[[package]] [[package]]
name = "glam" name = "glam"
version = "0.21.2" version = "0.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "781aa11be58ef14b0cd7326618afcbd9cdb5ba686bdab7193d87cdc322cd7033" checksum = "518faa5064866338b013ff9b2350dc318e14cc4fcd6cb8206d7e7c9886c98815"
dependencies = [ dependencies = [
"serde", "serde",
] ]
@@ -1086,9 +1085,9 @@ dependencies = [
[[package]] [[package]]
name = "glutin_egl_sys" name = "glutin_egl_sys"
version = "0.1.5" version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2abb6aa55523480c4adc5a56bbaa249992e2dddb2fc63dc96e04a3355364c211" checksum = "68900f84b471f31ea1d1355567eb865a2cf446294f06cef8d653ed7bcf5f013d"
dependencies = [ dependencies = [
"gl_generator", "gl_generator",
"winapi", "winapi",
@@ -1112,9 +1111,9 @@ dependencies = [
[[package]] [[package]]
name = "glutin_glx_sys" name = "glutin_glx_sys"
version = "0.1.7" version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e393c8fc02b807459410429150e9c4faffdb312d59b8c038566173c81991351" checksum = "d93d0575865098580c5b3a423188cd959419912ea60b1e48e8b3b526f6d02468"
dependencies = [ dependencies = [
"gl_generator", "gl_generator",
"x11-dl", "x11-dl",
@@ -1219,9 +1218,9 @@ dependencies = [
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "1.0.2" version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754"
[[package]] [[package]]
name = "jni" name = "jni"
@@ -1266,9 +1265,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.126" version = "0.2.131"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" checksum = "04c3b4822ccebfa39c02fc03d1534441b22ead323fa0f48bb7ddd8e6ba076a40"
[[package]] [[package]]
name = "libloading" name = "libloading"
@@ -1292,9 +1291,9 @@ dependencies = [
[[package]] [[package]]
name = "libusb1-sys" name = "libusb1-sys"
version = "0.6.2" version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6dfab089105aa85a3b492b421bd90d55e6257f00f8447cc3873c44f8206809ce" checksum = "f9d0e2afce4245f2c9a418511e5af8718bcaf2fa408aefb259504d1a9cb25f27"
dependencies = [ dependencies = [
"cc", "cc",
"libc", "libc",
@@ -1334,9 +1333,9 @@ dependencies = [
[[package]] [[package]]
name = "mac-notification-sys" name = "mac-notification-sys"
version = "0.5.5" version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fff231a88fe2e9985f9d159a2f02986fe46daa0f6af976a0d934be4870cc9d02" checksum = "3e72d50edb17756489e79d52eb146927bec8eba9dd48faadf9ef08bca3791ad5"
dependencies = [ dependencies = [
"cc", "cc",
"dirs-next", "dirs-next",
@@ -1377,9 +1376,9 @@ dependencies = [
[[package]] [[package]]
name = "memmap2" name = "memmap2"
version = "0.5.5" version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a79b39c93a7a5a27eeaf9a23b5ff43f1b9e0ad6b1cdd441140ae53c35613fc7" checksum = "8e2e4455be2010e8c5e77f0d10234b30f3a636a5305725609b5a71ad00d22577"
dependencies = [ dependencies = [
"libc", "libc",
] ]
@@ -1718,9 +1717,9 @@ dependencies = [
[[package]] [[package]]
name = "owned_ttf_parser" name = "owned_ttf_parser"
version = "0.15.0" version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fb1e509cfe7a12db2a90bfa057dfcdbc55a347f5da677c506b53dd099cfec9d" checksum = "07ef1a404ae479dd6906f4fa2c88b3c94028f1284beb42a47c183a7c27ee9a3e"
dependencies = [ dependencies = [
"ttf-parser", "ttf-parser",
] ]
@@ -1840,28 +1839,29 @@ checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
[[package]] [[package]]
name = "proc-macro-crate" name = "proc-macro-crate"
version = "1.1.3" version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9"
dependencies = [ dependencies = [
"once_cell",
"thiserror", "thiserror",
"toml", "toml",
] ]
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.42" version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c278e965f1d8cf32d6e0e96de3d3e79712178ae67986d9cf9151f51e95aac89b" checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.20" version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@@ -1907,9 +1907,9 @@ dependencies = [
[[package]] [[package]]
name = "redox_syscall" name = "redox_syscall"
version = "0.2.15" version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "534cfe58d6a18cc17120fbf4635d53d14691c1fe4d951064df9bd326178d7d5a" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
dependencies = [ dependencies = [
"bitflags", "bitflags",
] ]
@@ -1985,7 +1985,6 @@ dependencies = [
"serde", "serde",
"serde_derive", "serde_derive",
"sysfs-class", "sysfs-class",
"udev",
"zbus", "zbus",
"zvariant", "zvariant",
] ]
@@ -2013,6 +2012,16 @@ dependencies = [
"zvariant", "zvariant",
] ]
[[package]]
name = "rog_platform"
version = "0.1.0"
dependencies = [
"log",
"rusb",
"sysfs-class",
"udev",
]
[[package]] [[package]]
name = "rog_profiles" name = "rog_profiles"
version = "1.1.3" version = "1.1.3"
@@ -2057,9 +2066,9 @@ dependencies = [
[[package]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.10" version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
[[package]] [[package]]
name = "same-file" name = "same-file"
@@ -2084,18 +2093,18 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.140" version = "1.0.143"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc855a42c7967b7c369eb5860f7164ef1f6f81c20c7cc1141f2a604e18723b03" checksum = "53e8e5d5b70924f74ff5c6d64d9a5acd91422117c60f48c4e07855238a254553"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.140" version = "1.0.143"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f2122636b9fe3b81f1cb25099fcf2d3f542cdb1d45940d56c713158884a05da" checksum = "d3d8e8de557aee63c26b85b947f5e59b690d0454c753f3adeb5cd7835ab88391"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -2104,9 +2113,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.82" version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82c2c1fdcd807d1098552c5b9a36e425e42e9fbd7c6a37a8425f390f781f7fa7" checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7"
dependencies = [ dependencies = [
"itoa", "itoa",
"ryu", "ryu",
@@ -2115,9 +2124,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_repr" name = "serde_repr"
version = "0.1.8" version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2ad84e47328a31223de7fed7a4f5087f2d6ddfe586cf3ca25b7a165bc0a5aed" checksum = "1fe39d9fbb0ebf5eb2c7cb7e2a47e4f462fad1379f1166b8ae49ad9eae89a7ca"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -2221,7 +2230,7 @@ dependencies = [
"dlib", "dlib",
"lazy_static", "lazy_static",
"log", "log",
"memmap2 0.5.5", "memmap2 0.5.6",
"nix 0.24.2", "nix 0.24.2",
"pkg-config", "pkg-config",
"wayland-client", "wayland-client",
@@ -2308,9 +2317,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.98" version = "1.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -2351,18 +2360,18 @@ dependencies = [
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.31" version = "1.0.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" checksum = "f5f6586b7f764adc0231f4c79be7b920e766bb2f3e51b3661cdb263828f19994"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.31" version = "1.0.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" checksum = "12bafc5b54507e0149cdf1b145a5d80ab80a90bcd9275df43d4fff68460f6c21"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -2371,9 +2380,9 @@ dependencies = [
[[package]] [[package]]
name = "time" name = "time"
version = "0.3.11" version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72c91f41dcb2f096c05f0873d667dceec1087ce5bcf984ec8ffb19acddbb3217" checksum = "db76ff9fa4b1458b3c7f077f3ff9887394058460d21e634355b273aaf11eea45"
dependencies = [ dependencies = [
"libc", "libc",
"num_threads", "num_threads",
@@ -2415,9 +2424,9 @@ dependencies = [
[[package]] [[package]]
name = "tracing" name = "tracing"
version = "0.1.35" version = "0.1.36"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160" checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"pin-project-lite", "pin-project-lite",
@@ -2438,9 +2447,9 @@ dependencies = [
[[package]] [[package]]
name = "tracing-core" name = "tracing-core"
version = "0.1.28" version = "0.1.29"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b7358be39f2f274f322d2aaed611acc57f382e8eb1e5b48cb9ae30933495ce7" checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7"
dependencies = [ dependencies = [
"once_cell", "once_cell",
] ]
@@ -2480,9 +2489,9 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.2" version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7" checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf"
[[package]] [[package]]
name = "unicode-normalization" name = "unicode-normalization"
@@ -2914,9 +2923,9 @@ dependencies = [
[[package]] [[package]]
name = "x11-dl" name = "x11-dl"
version = "2.19.1" version = "2.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea26926b4ce81a6f5d9d0f3a0bc401e5a37c6ae14a1bfaa8ff6099ca80038c59" checksum = "0c83627bc137605acc00bb399c7b908ef460b621fc37c953db2b09f88c449ea6"
dependencies = [ dependencies = [
"lazy_static", "lazy_static",
"libc", "libc",

View File

@@ -1,5 +1,5 @@
[workspace] [workspace]
members = ["asusctl", "asus-notify", "daemon", "daemon-user", "rog-supported", "rog-dbus", "rog-anime", "rog-aura", "rog-profiles", "rog-control-center"] members = ["asusctl", "asus-notify", "daemon", "daemon-user", "rog-platform", "rog-supported", "rog-dbus", "rog-anime", "rog-aura", "rog-profiles", "rog-control-center"]
[profile.release] [profile.release]
# thin = 57s, asusd = 9.0M # thin = 57s, asusd = 9.0M

View File

@@ -774,7 +774,7 @@ fn handle_bios_option(
for line in usage.iter().filter(|line| { for line in usage.iter().filter(|line| {
line.contains("sound") && supported.post_sound line.contains("sound") && supported.post_sound
|| line.contains("GPU") && supported.dedicated_gfx || line.contains("GPU") && supported.dgpu_only
|| line.contains("panel") && supported.panel_overdrive || line.contains("panel") && supported.panel_overdrive
}) { }) {
println!("{}", line); println!("{}", line);
@@ -802,7 +802,7 @@ fn handle_bios_option(
} }
} }
if cmd.dedicated_gfx_get { if cmd.dedicated_gfx_get {
let res = dbus.proxies().rog_bios().dedicated_graphic_mode()? == 1; let res = dbus.proxies().rog_bios().dedicated_graphic_mode()?;
println!("Bios dedicated GPU on: {}", res); println!("Bios dedicated GPU on: {}", res);
} }
@@ -810,7 +810,7 @@ fn handle_bios_option(
dbus.proxies().rog_bios().set_panel_overdrive(opt)?; dbus.proxies().rog_bios().set_panel_overdrive(opt)?;
} }
if cmd.panel_overdrive_get { if cmd.panel_overdrive_get {
let res = dbus.proxies().rog_bios().panel_overdrive()? == 1; let res = dbus.proxies().rog_bios().panel_overdrive()?;
println!("Panel overdrive on: {}", res); println!("Panel overdrive on: {}", res);
} }
} }

View File

@@ -21,15 +21,13 @@ path = "src/daemon.rs"
rog_anime = { path = "../rog-anime", features = ["dbus"] } rog_anime = { path = "../rog-anime", features = ["dbus"] }
rog_aura = { path = "../rog-aura", features = ["dbus"] } rog_aura = { path = "../rog-aura", features = ["dbus"] }
rog_supported = { path = "../rog-supported" } rog_supported = { path = "../rog-supported" }
rog_platform = { path = "../rog-platform" }
rog_profiles = { path = "../rog-profiles" } rog_profiles = { path = "../rog-profiles" }
rog_dbus = { path = "../rog-dbus" } rog_dbus = { path = "../rog-dbus" }
async-trait = "^0.1" async-trait = "^0.1"
smol = "^1.2" smol = "^1.2"
rusb = "^0.9"
udev = "^0.6"
# cli and logging # cli and logging
log = "^0.4" log = "^0.4"
env_logger = "^0.9" env_logger = "^0.9"

View File

@@ -8,25 +8,21 @@ use logind_zbus::manager::ManagerProxy;
use rog_anime::{ use rog_anime::{
error::AnimeError, error::AnimeError,
usb::{ usb::{
find_node, get_anime_type, pkt_for_apply, pkt_for_flush, pkt_for_set_boot, pkt_for_set_on, get_anime_type, pkt_for_apply, pkt_for_flush, pkt_for_set_boot, pkt_for_set_on,
pkts_for_init, PROD_ID, VENDOR_ID, pkts_for_init,
}, },
ActionData, AnimeDataBuffer, AnimePacketType, AnimeType, ActionData, AnimeDataBuffer, AnimePacketType, AnimeType,
}; };
use rog_platform::{hid_raw::HidRaw, usb_raw::USBRaw};
use rog_supported::AnimeSupportedFunctions; use rog_supported::AnimeSupportedFunctions;
use rusb::{Device, DeviceHandle};
use smol::{stream::StreamExt, Executor}; use smol::{stream::StreamExt, Executor};
use std::sync::atomic::{AtomicBool, Ordering};
use std::{ use std::{
cell::RefCell,
convert::TryFrom, convert::TryFrom,
error::Error, error::Error,
sync::{Arc, Mutex, MutexGuard}, sync::{Arc, Mutex, MutexGuard},
thread::sleep, thread::sleep,
}; };
use std::{
sync::atomic::{AtomicBool, Ordering},
time::Duration,
};
use crate::{error::RogError, GetSupported}; use crate::{error::RogError, GetSupported};
@@ -36,14 +32,13 @@ impl GetSupported for CtrlAnime {
type A = AnimeSupportedFunctions; type A = AnimeSupportedFunctions;
fn get_supported() -> Self::A { fn get_supported() -> Self::A {
AnimeSupportedFunctions(CtrlAnime::get_device(VENDOR_ID, PROD_ID).is_ok()) AnimeSupportedFunctions(HidRaw::new("193b").is_ok())
} }
} }
pub struct CtrlAnime { pub struct CtrlAnime {
_node: String, node: USBRaw,
anime_type: AnimeType, anime_type: AnimeType,
handle: RefCell<DeviceHandle<rusb::GlobalContext>>,
cache: AnimeConfigCached, cache: AnimeConfigCached,
config: AnimeConfig, config: AnimeConfig,
// set to force thread to exit // set to force thread to exit
@@ -55,57 +50,26 @@ pub struct CtrlAnime {
impl CtrlAnime { impl CtrlAnime {
#[inline] #[inline]
pub fn new(config: AnimeConfig) -> Result<CtrlAnime, Box<dyn Error>> { pub fn new(config: AnimeConfig) -> Result<CtrlAnime, Box<dyn Error>> {
let node = find_node("193b")?; let node = USBRaw::new(0x193b)?;
let anime_type = get_anime_type()?; let anime_type = get_anime_type()?;
let device = Self::get_dev_handle()?;
info!("Device has an AniMe Matrix display"); info!("Device has an AniMe Matrix display");
let mut cache = AnimeConfigCached::default(); let mut cache = AnimeConfigCached::default();
cache.init_from_config(&config, anime_type)?; cache.init_from_config(&config, anime_type)?;
let ctrl = CtrlAnime { let ctrl = CtrlAnime {
_node: node, node,
anime_type, anime_type,
handle: RefCell::new(device),
cache, cache,
config, config,
thread_exit: Arc::new(AtomicBool::new(false)), thread_exit: Arc::new(AtomicBool::new(false)),
thread_running: Arc::new(AtomicBool::new(false)), thread_running: Arc::new(AtomicBool::new(false)),
}; };
ctrl.do_initialization(); ctrl.do_initialization()?;
Ok(ctrl) Ok(ctrl)
} }
// let device = CtrlAnime::get_device(0x0b05, 0x193b)?;
fn get_dev_handle() -> Result<DeviceHandle<rusb::GlobalContext>, Box<dyn Error>> {
// We don't expect this ID to ever change
let device = CtrlAnime::get_device(0x0b05, 0x193b)?;
let mut device = device.open()?;
device.reset()?;
device.set_auto_detach_kernel_driver(true).map_err(|err| {
error!("Auto-detach kernel driver failed: {}", err);
err
})?;
device.claim_interface(0).map_err(|err| {
error!("Could not claim device interface: {}", err);
err
})?;
Ok(device)
}
fn get_device(vendor: u16, product: u16) -> Result<Device<rusb::GlobalContext>, rusb::Error> {
for device in rusb::devices()?.iter() {
let device_desc = device.device_descriptor()?;
if device_desc.vendor_id() == vendor && device_desc.product_id() == product {
return Ok(device);
}
}
Err(rusb::Error::NoDevice)
}
/// Start an action thread. This is classed as a singleton and there should be only /// 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. /// one running - so the thread uses atomics to signal run/exit.
@@ -230,45 +194,6 @@ impl CtrlAnime {
.ok(); .ok();
} }
fn write_bytes(&self, message: &[u8]) {
// if let Ok(mut file) = OpenOptions::new().write(true).open(&self.node) {
// println!("write: {:02x?}", &message);
// return file
// .write_all(message).unwrap();
// }
let mut error = false;
match self.handle.borrow().write_control(
0x21, // request_type
0x09, // request
0x35e, // value
0x00, // index
message,
Duration::from_millis(200),
) {
Ok(_) => {}
Err(err) => match err {
rusb::Error::Timeout => {}
_ => {
error = true;
error!("Failed to write to led interrupt: {}", err);
}
},
}
if error {
warn!("Will attempt to get AniMe device handle again");
match Self::get_dev_handle() {
Ok(dev) => {
self.handle.replace(dev);
}
Err(err) => {
error!("Failed to get AniMe device: {}", err);
}
}
}
}
/// Write only a data packet. This will modify the leds brightness using the /// Write only a data packet. This will modify the leds brightness using the
/// global brightness set in config. /// global brightness set in config.
fn write_data_buffer(&self, mut buffer: AnimeDataBuffer) -> Result<(), RogError> { fn write_data_buffer(&self, mut buffer: AnimeDataBuffer) -> Result<(), RogError> {
@@ -281,16 +206,17 @@ impl CtrlAnime {
} }
let data = AnimePacketType::try_from(buffer)?; let data = AnimePacketType::try_from(buffer)?;
for row in data.iter() { for row in data.iter() {
self.write_bytes(row); self.node.write_bytes(row)?;
} }
self.write_bytes(&pkt_for_flush()); self.node.write_bytes(&pkt_for_flush())?;
Ok(()) Ok(())
} }
fn do_initialization(&self) { fn do_initialization(&self) -> Result<(), RogError> {
let pkts = pkts_for_init(); let pkts = pkts_for_init();
self.write_bytes(&pkts[0]); self.node.write_bytes(&pkts[0])?;
self.write_bytes(&pkts[1]); self.node.write_bytes(&pkts[1])?;
Ok(())
} }
} }
@@ -380,10 +306,12 @@ pub struct CtrlAnimeReloader(pub Arc<Mutex<CtrlAnime>>);
impl crate::Reloadable for CtrlAnimeReloader { impl crate::Reloadable for CtrlAnimeReloader {
fn reload(&mut self) -> Result<(), RogError> { fn reload(&mut self) -> Result<(), RogError> {
if let Ok(lock) = self.0.try_lock() { if let Ok(lock) = self.0.try_lock() {
lock.write_bytes(&pkt_for_set_on(lock.config.awake_enabled)); lock.node
lock.write_bytes(&pkt_for_apply()); .write_bytes(&pkt_for_set_on(lock.config.awake_enabled))?;
lock.write_bytes(&pkt_for_set_boot(lock.config.boot_anim_enabled)); lock.node.write_bytes(&pkt_for_apply())?;
lock.write_bytes(&pkt_for_apply()); lock.node
.write_bytes(&pkt_for_set_boot(lock.config.boot_anim_enabled))?;
lock.node.write_bytes(&pkt_for_apply())?;
let action = lock.cache.boot.clone(); let action = lock.cache.boot.clone();
CtrlAnime::run_thread(self.0.clone(), action, true); CtrlAnime::run_thread(self.0.clone(), action, true);

View File

@@ -64,7 +64,12 @@ impl CtrlAnimeZbus {
let states; let states;
'outer: loop { 'outer: loop {
if let Ok(mut lock) = self.0.try_lock() { if let Ok(mut lock) = self.0.try_lock() {
lock.write_bytes(&pkt_for_set_on(status)); lock.node
.write_bytes(&pkt_for_set_on(status))
.map_err(|err| {
warn!("rog_anime::run_animation:callback {}", err);
})
.ok();
lock.config.awake_enabled = status; lock.config.awake_enabled = status;
lock.config.write(); lock.config.write();
@@ -86,8 +91,18 @@ impl CtrlAnimeZbus {
let states; let states;
'outer: loop { 'outer: loop {
if let Ok(mut lock) = self.0.try_lock() { if let Ok(mut lock) = self.0.try_lock() {
lock.write_bytes(&pkt_for_set_boot(on)); lock.node
lock.write_bytes(&pkt_for_apply()); .write_bytes(&pkt_for_set_boot(on))
.map_err(|err| {
warn!("rog_anime::run_animation:callback {}", err);
})
.ok();
lock.node
.write_bytes(&pkt_for_apply())
.map_err(|err| {
warn!("rog_anime::run_animation:callback {}", err);
})
.ok();
lock.config.boot_anim_enabled = on; lock.config.boot_anim_enabled = on;
lock.config.write(); lock.config.write();

View File

@@ -2,13 +2,13 @@ use crate::laptops::{LaptopLedData, ASUS_KEYBOARD_DEVICES};
use log::{error, warn}; use log::{error, warn};
use rog_aura::usb::{AuraDev1866, AuraDev19b6, AuraDevTuf, AuraDevice, AuraPowerDev}; use rog_aura::usb::{AuraDev1866, AuraDev19b6, AuraDevTuf, AuraDevice, AuraPowerDev};
use rog_aura::{AuraEffect, AuraModeNum, AuraZone, Direction, LedBrightness, Speed, GRADIENT}; 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 serde_derive::{Deserialize, Serialize};
use std::collections::{BTreeMap, HashSet}; use std::collections::{BTreeMap, HashSet};
use std::fs::{File, OpenOptions}; use std::fs::{File, OpenOptions};
use std::io::{Read, Write}; use std::io::{Read, Write};
use super::controller::CtrlKbdLed;
pub static AURA_CONFIG_PATH: &str = "/etc/asusd/aura.conf"; pub static AURA_CONFIG_PATH: &str = "/etc/asusd/aura.conf";
/// Enable/disable LED control in various states such as /// Enable/disable LED control in various states such as
@@ -128,14 +128,16 @@ impl Default for AuraConfig {
fn default() -> Self { fn default() -> Self {
let mut prod_id = AuraDevice::Unknown; let mut prod_id = AuraDevice::Unknown;
for prod in ASUS_KEYBOARD_DEVICES.iter() { for prod in ASUS_KEYBOARD_DEVICES.iter() {
if let Ok(_) = CtrlKbdLed::find_led_node(prod) { if let Ok(_) = HidRaw::new(prod) {
prod_id = AuraDevice::from(*prod); prod_id = AuraDevice::from(*prod);
break; break;
} }
} }
if CtrlKbdLed::get_tuf_mode_path().is_some() { if let Ok(p) = KeyboardLed::new() {
prod_id = AuraDevice::Tuf; if p.has_keyboard_rgb_mode() {
prod_id = AuraDevice::Tuf;
}
} }
let enabled = if prod_id == AuraDevice::X19B6 { let enabled = if prod_id == AuraDevice::X19B6 {

View File

@@ -1,8 +1,3 @@
// Only these two packets must be 17 bytes
static KBD_BRIGHT_PATH: &str = "/sys/class/leds/asus::kbd_backlight/brightness";
static TUF_RGB_MODE_PATH: &str = "/sys/devices/platform/asus-nb-wmi/tuf_krgb_mode";
static TUF_RGB_STATE_PATH: &str = "/sys/devices/platform/asus-nb-wmi/tuf_krgb_state";
use crate::{ use crate::{
error::RogError, error::RogError,
laptops::{LaptopLedData, ASUS_KEYBOARD_DEVICES}, laptops::{LaptopLedData, ASUS_KEYBOARD_DEVICES},
@@ -16,16 +11,13 @@ use rog_aura::{
AuraEffect, LedBrightness, LED_MSG_LEN, AuraEffect, LedBrightness, LED_MSG_LEN,
}; };
use rog_aura::{AuraZone, Direction, Speed, GRADIENT}; use rog_aura::{AuraZone, Direction, Speed, GRADIENT};
use rog_platform::{hid_raw::HidRaw, keyboard_led::KeyboardLed};
use rog_supported::LedSupportedFunctions; use rog_supported::LedSupportedFunctions;
use smol::{stream::StreamExt, Executor}; use smol::{stream::StreamExt, Executor};
use std::path::Path; use std::collections::BTreeMap;
use std::sync::Arc; use std::sync::Arc;
use std::sync::Mutex; use std::sync::Mutex;
use std::{ use std::sync::MutexGuard;
collections::BTreeMap,
io::{Read, Write},
};
use std::{fs::OpenOptions, sync::MutexGuard};
use zbus::Connection; use zbus::Connection;
use crate::GetSupported; use crate::GetSupported;
@@ -44,19 +36,21 @@ impl GetSupported for CtrlKbdLed {
let mut prod_id = AuraDevice::Unknown; let mut prod_id = AuraDevice::Unknown;
for prod in ASUS_KEYBOARD_DEVICES.iter() { for prod in ASUS_KEYBOARD_DEVICES.iter() {
if let Ok(_) = Self::find_led_node(prod) { if let Ok(_) = HidRaw::new(prod) {
prod_id = AuraDevice::from(*prod); prod_id = AuraDevice::from(*prod);
break; break;
} }
} }
if Self::get_tuf_mode_path().is_some() { if let Ok(p) = KeyboardLed::new() {
prod_id = AuraDevice::Tuf; if p.has_keyboard_rgb_mode() {
prod_id = AuraDevice::Tuf;
}
} }
LedSupportedFunctions { LedSupportedFunctions {
prod_id, prod_id,
brightness_set: CtrlKbdLed::get_kbd_bright_path().is_some(), brightness_set: KeyboardLed::new().is_ok(),
stock_led_modes, stock_led_modes,
multizone_led_mode, multizone_led_mode,
per_key_led_mode, per_key_led_mode,
@@ -66,8 +60,8 @@ impl GetSupported for CtrlKbdLed {
#[derive(Debug, PartialEq, PartialOrd)] #[derive(Debug, PartialEq, PartialOrd)]
pub enum LEDNode { pub enum LEDNode {
Tuf, KbdLed(KeyboardLed),
Rog(String), Rog(HidRaw),
None, None,
} }
@@ -75,7 +69,7 @@ pub struct CtrlKbdLed {
// TODO: config stores the keyboard type as an AuraPower, use or update this // TODO: config stores the keyboard type as an AuraPower, use or update this
pub led_prod: Option<String>, pub led_prod: Option<String>,
pub led_node: LEDNode, pub led_node: LEDNode,
pub bright_node: String, pub kd_brightness: KeyboardLed,
pub supported_modes: LaptopLedData, pub supported_modes: LaptopLedData,
pub flip_effect_write: bool, pub flip_effect_write: bool,
pub config: AuraConfig, pub config: AuraConfig,
@@ -91,27 +85,11 @@ impl CtrlKbdLedTask {
} }
fn update_config(lock: &mut CtrlKbdLed) -> Result<(), RogError> { fn update_config(lock: &mut CtrlKbdLed) -> Result<(), RogError> {
let mut file = OpenOptions::new() let bright = lock.kd_brightness.get_brightness()?;
.read(true) lock.config.read();
.open(&lock.bright_node) lock.config.brightness = (bright as u32).into();
.map_err(|err| match err.kind() { lock.config.write();
std::io::ErrorKind::NotFound => { return Ok(());
RogError::MissingLedBrightNode((&lock.bright_node).into(), err)
}
_ => RogError::Path((&lock.bright_node).into(), err),
})?;
let mut buf = [0u8; 1];
file.read_exact(&mut buf)
.map_err(|err| RogError::Read("buffer".into(), err))?;
if let Some(num) = char::from(buf[0]).to_digit(10) {
if lock.config.brightness != num.into() {
lock.config.read();
lock.config.brightness = num.into();
lock.config.write();
}
return Ok(());
}
Err(RogError::ParseLed)
} }
} }
@@ -189,9 +167,7 @@ impl crate::Reloadable for CtrlKbdLedReloader {
fn reload(&mut self) -> Result<(), RogError> { fn reload(&mut self) -> Result<(), RogError> {
if let Ok(mut ctrl) = self.0.try_lock() { if let Ok(mut ctrl) = self.0.try_lock() {
ctrl.write_current_config_mode()?; ctrl.write_current_config_mode()?;
ctrl.set_power_states(&ctrl.config) ctrl.set_power_states().map_err(|err| warn!("{err}")).ok();
.map_err(|err| warn!("{err}"))
.ok();
} }
Ok(()) Ok(())
} }
@@ -210,7 +186,7 @@ impl CtrlKbdLed {
let mut led_prod = None; let mut led_prod = None;
let mut led_node = None; let mut led_node = None;
for prod in ASUS_KEYBOARD_DEVICES.iter() { for prod in ASUS_KEYBOARD_DEVICES.iter() {
match Self::find_led_node(prod) { match HidRaw::new(prod) {
Ok(node) => { Ok(node) => {
led_prod = Some(prod.to_string()); led_prod = Some(prod.to_string());
led_node = Some(node); led_node = Some(node);
@@ -221,10 +197,10 @@ impl CtrlKbdLed {
} }
} }
let bright_node = Self::get_kbd_bright_path(); let bright_node = KeyboardLed::new();
let tuf_node = Self::get_tuf_mode_path().is_some() || Self::get_tuf_state_path().is_some(); let platform = KeyboardLed::new()?;
if led_node.is_none() && tuf_node && bright_node.is_none() { if led_node.is_none() && !platform.has_keyboard_rgb_mode() {
let dmi = sysfs_class::DmiId::default(); let dmi = sysfs_class::DmiId::default();
if let Ok(prod_family) = dmi.product_family() { if let Ok(prod_family) = dmi.product_family() {
if prod_family.contains("TUF") { if prod_family.contains("TUF") {
@@ -237,9 +213,9 @@ impl CtrlKbdLed {
let led_node = if let Some(rog) = led_node { let led_node = if let Some(rog) = led_node {
info!("Found ROG USB keyboard"); info!("Found ROG USB keyboard");
LEDNode::Rog(rog) LEDNode::Rog(rog)
} else if tuf_node { } else if platform.has_keyboard_rgb_mode() {
info!("Found TUF keyboard"); info!("Found TUF keyboard");
LEDNode::Tuf LEDNode::KbdLed(platform)
} else { } else {
LEDNode::None LEDNode::None
}; };
@@ -247,7 +223,7 @@ impl CtrlKbdLed {
let ctrl = CtrlKbdLed { let ctrl = CtrlKbdLed {
led_prod, led_prod,
led_node, led_node,
bright_node: bright_node.unwrap(), // If was none then we already returned above kd_brightness: bright_node?, // If was none then we already returned above
supported_modes, supported_modes,
flip_effect_write: false, flip_effect_write: false,
config, config,
@@ -255,58 +231,16 @@ impl CtrlKbdLed {
Ok(ctrl) Ok(ctrl)
} }
fn get_kbd_bright_path() -> Option<String> {
if Path::new(KBD_BRIGHT_PATH).exists() {
return Some(KBD_BRIGHT_PATH.to_string());
}
None
}
pub fn get_tuf_mode_path() -> Option<String> {
if Path::new(TUF_RGB_MODE_PATH).exists() {
return Some(TUF_RGB_MODE_PATH.to_string());
}
None
}
fn get_tuf_state_path() -> Option<String> {
if Path::new(TUF_RGB_STATE_PATH).exists() {
return Some(TUF_RGB_STATE_PATH.to_string());
}
None
}
pub(super) fn get_brightness(&self) -> Result<u8, RogError> { pub(super) fn get_brightness(&self) -> Result<u8, RogError> {
let mut file = OpenOptions::new() self.kd_brightness
.read(true) .get_brightness()
.open(&self.bright_node) .map_err(|e| RogError::Platform(e))
.map_err(|err| match err.kind() {
std::io::ErrorKind::NotFound => {
RogError::MissingLedBrightNode((&self.bright_node).into(), err)
}
_ => RogError::Path((&self.bright_node).into(), err),
})?;
let mut buf = [0u8; 1];
file.read_exact(&mut buf)
.map_err(|err| RogError::Read("buffer".into(), err))?;
Ok(buf[0])
} }
pub(super) fn set_brightness(&self, brightness: LedBrightness) -> Result<(), RogError> { pub(super) fn set_brightness(&self, brightness: LedBrightness) -> Result<(), RogError> {
let path = Path::new(&self.bright_node); self.kd_brightness
let mut file = .set_brightness(brightness.as_char_code())
OpenOptions::new() .map_err(|e| RogError::Platform(e))
.write(true)
.open(&path)
.map_err(|err| match err.kind() {
std::io::ErrorKind::NotFound => {
RogError::MissingLedBrightNode((&self.bright_node).into(), err)
}
_ => RogError::Path((&self.bright_node).into(), err),
})?;
file.write_all(&[brightness.as_char_code()])
.map_err(|err| RogError::Read("buffer".into(), err))?;
Ok(())
} }
pub fn next_brightness(&mut self) -> Result<(), RogError> { pub fn next_brightness(&mut self) -> Result<(), RogError> {
@@ -332,68 +266,24 @@ impl CtrlKbdLed {
} }
/// 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(&self, config: &AuraConfig) -> Result<(), RogError> { pub(super) fn set_power_states(&mut self) -> Result<(), RogError> {
if LEDNode::Tuf == self.led_node { if let LEDNode::KbdLed(platform) = &mut self.led_node {
if let Some(path) = Self::get_tuf_state_path() { if let Some(pwr) = AuraPowerConfig::to_tuf_bool_array(&self.config.enabled) {
let mut file = OpenOptions::new().write(true).open(path)?; let buf = [1, pwr[1] as u8, pwr[2] as u8, pwr[3] as u8, pwr[4] as u8];
if let Some(pwr) = AuraPowerConfig::to_tuf_bool_array(&config.enabled) { platform.set_keyboard_rgb_state(&buf)?;
let buf = format!(
"1 {} {} {} {}",
pwr[1] as u8, pwr[2] as u8, pwr[3] as u8, pwr[4] as u8,
);
file.write_all(buf.as_bytes())?;
}
} }
} else { } else if let LEDNode::Rog(hid_raw) = &self.led_node {
let bytes = AuraPowerConfig::to_bytes(&config.enabled); let bytes = AuraPowerConfig::to_bytes(&self.config.enabled);
let message = [0x5d, 0xbd, 0x01, bytes[0], bytes[1], bytes[2]]; let message = [0x5d, 0xbd, 0x01, bytes[0], bytes[1], bytes[2]];
self.write_bytes(&message)?; hid_raw.write_bytes(&message)?;
self.write_bytes(&LED_SET)?; hid_raw.write_bytes(&LED_SET)?;
// Changes won't persist unless apply is set // Changes won't persist unless apply is set
self.write_bytes(&LED_APPLY)?; hid_raw.write_bytes(&LED_APPLY)?;
} }
Ok(()) Ok(())
} }
pub(crate) fn find_led_node(id_product: &str) -> Result<String, RogError> {
let mut enumerator = udev::Enumerator::new().map_err(|err| {
warn!("{}", err);
RogError::Udev("enumerator failed".into(), err)
})?;
enumerator.match_subsystem("hidraw").map_err(|err| {
warn!("{}", err);
RogError::Udev("match_subsystem failed".into(), err)
})?;
for device in enumerator.scan_devices().map_err(|err| {
warn!("{}", err);
RogError::Udev("scan_devices failed".into(), err)
})? {
if let Some(parent) = device
.parent_with_subsystem_devtype("usb", "usb_device")
.map_err(|err| {
warn!("{}", err);
RogError::Udev("parent_with_subsystem_devtype failed".into(), err)
})?
{
if parent
.attribute_value("idProduct")
.ok_or_else(|| RogError::NotFound("LED idProduct".into()))?
== id_product
{
if let Some(dev_node) = device.devnode() {
info!("Using device at: {:?} for LED control", dev_node);
return Ok(dev_node.to_string_lossy().to_string());
}
}
}
}
Err(RogError::MissingFunction(
"ASUS LED device node not found".into(),
))
}
/// Set an Aura effect if the effect mode or zone is supported. /// 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 /// On success the aura config file is read to refresh cached values, then the effect is
@@ -414,28 +304,17 @@ impl CtrlKbdLed {
Ok(()) Ok(())
} }
/// Should only be used if the bytes you are writing are verified correct
fn write_bytes(&self, message: &[u8]) -> Result<(), RogError> {
if let LEDNode::Rog(led_node) = &self.led_node {
if let Ok(mut file) = OpenOptions::new().write(true).open(led_node) {
// println!("write: {:02x?}", &message);
return file
.write_all(message)
.map_err(|err| RogError::Write("write_bytes".into(), err));
}
}
Err(RogError::NoAuraNode)
}
/// Write an effect block. This is for per-key /// Write an effect block. This is for per-key
fn _write_effect(&mut self, effect: &[Vec<u8>]) -> Result<(), RogError> { fn _write_effect(&mut self, effect: &[Vec<u8>]) -> Result<(), RogError> {
if self.flip_effect_write { if let LEDNode::Rog(hid_raw) = &self.led_node {
for row in effect.iter().rev() { if self.flip_effect_write {
self.write_bytes(row)?; for row in effect.iter().rev() {
} hid_raw.write_bytes(row)?;
} else { }
for row in effect.iter() { } else {
self.write_bytes(row)?; for row in effect.iter() {
hid_raw.write_bytes(row)?;
}
} }
} }
self.flip_effect_write = !self.flip_effect_write; self.flip_effect_write = !self.flip_effect_write;
@@ -478,19 +357,24 @@ impl CtrlKbdLed {
} }
fn write_mode(&self, mode: &AuraEffect) -> Result<(), RogError> { fn write_mode(&self, mode: &AuraEffect) -> Result<(), RogError> {
if LEDNode::Tuf == self.led_node { if let LEDNode::KbdLed(platform) = &self.led_node {
let mut file = OpenOptions::new().write(true).open(TUF_RGB_MODE_PATH)?; let buf = [
let buf = format!( 1,
"1 {} {} {} {} {}", mode.mode as u8,
mode.mode as u8, mode.colour1.0, mode.colour1.1, mode.colour1.2, mode.speed as u8, mode.colour1.0,
); mode.colour1.1,
file.write_all(buf.as_bytes())?; mode.colour1.2,
} else { mode.speed as u8,
];
platform.set_keyboard_rgb_mode(&buf)?;
} else if let LEDNode::Rog(hid_raw) = &self.led_node {
let bytes: [u8; LED_MSG_LEN] = mode.into(); let bytes: [u8; LED_MSG_LEN] = mode.into();
self.write_bytes(&bytes)?; hid_raw.write_bytes(&bytes)?;
self.write_bytes(&LED_SET)?; hid_raw.write_bytes(&LED_SET)?;
// Changes won't persist unless apply is set // Changes won't persist unless apply is set
self.write_bytes(&LED_APPLY)?; hid_raw.write_bytes(&LED_APPLY)?;
} else {
return Err(RogError::NoAuraKeyboard);
} }
Ok(()) Ok(())
} }
@@ -562,6 +446,7 @@ impl CtrlKbdLed {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use rog_aura::{AuraEffect, AuraModeNum, AuraZone, Colour}; use rog_aura::{AuraEffect, AuraModeNum, AuraZone, Colour};
use rog_platform::keyboard_led::KeyboardLed;
use crate::{ use crate::{
ctrl_aura::{config::AuraConfig, controller::LEDNode}, ctrl_aura::{config::AuraConfig, controller::LEDNode},
@@ -585,7 +470,7 @@ mod tests {
let mut controller = CtrlKbdLed { let mut controller = CtrlKbdLed {
led_prod: None, led_prod: None,
led_node: LEDNode::None, led_node: LEDNode::None,
bright_node: String::new(), kd_brightness: KeyboardLed::default(),
supported_modes, supported_modes,
flip_effect_write: false, flip_effect_write: false,
config, config,
@@ -601,7 +486,7 @@ mod tests {
.set_effect(effect.clone()) .set_effect(effect.clone())
.unwrap_err() .unwrap_err()
.to_string(), .to_string(),
"No Aura keyboard node found" "No supported Aura keyboard"
); );
effect.mode = AuraModeNum::Laser; effect.mode = AuraModeNum::Laser;
@@ -629,7 +514,7 @@ mod tests {
.set_effect(effect.clone()) .set_effect(effect.clone())
.unwrap_err() .unwrap_err()
.to_string(), .to_string(),
"No Aura keyboard node found" "No supported Aura keyboard"
); );
} }
@@ -647,7 +532,7 @@ mod tests {
let mut controller = CtrlKbdLed { let mut controller = CtrlKbdLed {
led_prod: None, led_prod: None,
led_node: LEDNode::None, led_node: LEDNode::None,
bright_node: String::new(), kd_brightness: KeyboardLed::default(),
supported_modes, supported_modes,
flip_effect_write: false, flip_effect_write: false,
config, config,
@@ -684,7 +569,7 @@ mod tests {
let mut controller = CtrlKbdLed { let mut controller = CtrlKbdLed {
led_prod: None, led_prod: None,
led_node: LEDNode::None, led_node: LEDNode::None,
bright_node: String::new(), kd_brightness: KeyboardLed::default(),
supported_modes, supported_modes,
flip_effect_write: false, flip_effect_write: false,
config, config,
@@ -699,7 +584,7 @@ mod tests {
.write_current_config_mode() .write_current_config_mode()
.unwrap_err() .unwrap_err()
.to_string(), .to_string(),
"No Aura keyboard node found" "No supported Aura keyboard"
); );
assert!(controller.config.multizone.is_some()); assert!(controller.config.multizone.is_some());

View File

@@ -78,7 +78,7 @@ impl CtrlKbdLedZbus {
ctrl.config.write(); ctrl.config.write();
ctrl.set_power_states(&ctrl.config).map_err(|e| { ctrl.set_power_states().map_err(|e| {
warn!("{}", e); warn!("{}", e);
e e
})?; })?;

View File

@@ -1,6 +1,7 @@
use crate::{config::Config, error::RogError, GetSupported}; use crate::{config::Config, error::RogError, GetSupported};
use async_trait::async_trait; use async_trait::async_trait;
use log::{error, info, warn}; use log::{error, info, warn};
use rog_platform::platform::AsusPlatform;
use rog_supported::RogBiosSupportedFunctions; use rog_supported::RogBiosSupportedFunctions;
use std::fs::OpenOptions; use std::fs::OpenOptions;
use std::io::BufRead; use std::io::BufRead;
@@ -15,15 +16,13 @@ use zbus::{dbus_interface, SignalContext};
const INITRAMFS_PATH: &str = "/usr/sbin/update-initramfs"; const INITRAMFS_PATH: &str = "/usr/sbin/update-initramfs";
const DRACUT_PATH: &str = "/usr/bin/dracut"; const DRACUT_PATH: &str = "/usr/bin/dracut";
static ASUS_SWITCH_GRAPHIC_MODE: &str = // static ASUS_SWITCH_GRAPHIC_MODE: &str =
"/sys/firmware/efi/efivars/AsusSwitchGraphicMode-607005d5-3f75-4b2e-98f0-85ba66797a3e"; // "/sys/firmware/efi/efivars/AsusSwitchGraphicMode-607005d5-3f75-4b2e-98f0-85ba66797a3e";
static ASUS_POST_LOGO_SOUND: &str = static ASUS_POST_LOGO_SOUND: &str =
"/sys/firmware/efi/efivars/AsusPostLogoSound-607005d5-3f75-4b2e-98f0-85ba66797a3e"; "/sys/firmware/efi/efivars/AsusPostLogoSound-607005d5-3f75-4b2e-98f0-85ba66797a3e";
static ASUS_PANEL_OD_PATH: &str = "/sys/devices/platform/asus-nb-wmi/panel_od";
static ASUS_DGPU_DISABLE_PATH: &str = "/sys/devices/platform/asus-nb-wmi/dgpu_disable";
static ASUS_EGPU_ENABLE_PATH: &str = "/sys/devices/platform/asus-nb-wmi/egpu_enable";
pub struct CtrlRogBios { pub struct CtrlRogBios {
platform: AsusPlatform,
_config: Arc<Mutex<Config>>, _config: Arc<Mutex<Config>>,
} }
@@ -31,12 +30,24 @@ impl GetSupported for CtrlRogBios {
type A = RogBiosSupportedFunctions; type A = RogBiosSupportedFunctions;
fn get_supported() -> Self::A { fn get_supported() -> Self::A {
let mut panel_overdrive = false;
let mut dgpu_disable = false;
let mut egpu_enable = false;
let mut dgpu_only = false;
if let Ok(platform) = AsusPlatform::new() {
panel_overdrive = platform.has_panel_od();
dgpu_disable = platform.has_dgpu_disable();
egpu_enable = platform.has_egpu_enable();
dgpu_only = platform.has_gpu_mux_mode();
}
RogBiosSupportedFunctions { RogBiosSupportedFunctions {
post_sound: Path::new(ASUS_POST_LOGO_SOUND).exists(), post_sound: Path::new(ASUS_POST_LOGO_SOUND).exists(),
dedicated_gfx: Path::new(ASUS_SWITCH_GRAPHIC_MODE).exists(), dgpu_only,
panel_overdrive: Path::new(ASUS_PANEL_OD_PATH).exists(), panel_overdrive,
dgpu_disable: Path::new(ASUS_DGPU_DISABLE_PATH).exists(), dgpu_disable,
egpu_enable: Path::new(ASUS_EGPU_ENABLE_PATH).exists(), egpu_enable,
} }
} }
} }
@@ -59,13 +70,14 @@ impl CtrlRogBios {
.ok(); .ok();
} }
fn dedicated_graphic_mode(&self) -> i8 { fn dedicated_graphic_mode(&self) -> bool {
Self::get_gfx_mode() self.platform
.get_gpu_mux_mode()
.map_err(|err| { .map_err(|err| {
warn!("CtrlRogBios: get_gfx_mode {}", err); warn!("CtrlRogBios: get_gfx_mode {}", err);
err err
}) })
.unwrap_or(-1) .unwrap_or(false)
} }
#[dbus_interface(signal)] #[dbus_interface(signal)]
@@ -118,26 +130,14 @@ impl CtrlRogBios {
} }
} }
fn panel_overdrive(&self) -> i8 { fn panel_overdrive(&self) -> bool {
let path = ASUS_PANEL_OD_PATH; self.platform
if let Ok(mut file) = OpenOptions::new().read(true).open(path).map_err(|err| { .get_panel_od()
warn!("CtrlRogBios: panel_overdrive {}", err); .map_err(|err| {
err warn!("CtrlRogBios: get panel overdrive {}", err);
}) { err
let mut buf = Vec::new(); })
file.read_to_end(&mut buf) .unwrap_or(false)
.map_err(|err| {
warn!("CtrlRogBios: set_panel_overdrive {}", err);
err
})
.ok();
if buf.len() >= 1 {
let tmp = String::from_utf8_lossy(&buf[0..1]);
return tmp.parse::<i8>().unwrap_or(-1);
}
}
-1
} }
#[dbus_interface(signal)] #[dbus_interface(signal)]
@@ -163,9 +163,8 @@ impl crate::Reloadable for CtrlRogBios {
impl CtrlRogBios { impl CtrlRogBios {
pub fn new(config: Arc<Mutex<Config>>) -> Result<Self, RogError> { pub fn new(config: Arc<Mutex<Config>>) -> Result<Self, RogError> {
if Path::new(ASUS_SWITCH_GRAPHIC_MODE).exists() { let platform = AsusPlatform::new()?;
CtrlRogBios::set_path_mutable(ASUS_SWITCH_GRAPHIC_MODE)?; if !platform.has_gpu_mux_mode() {
} else {
info!("G-Sync Switchable Graphics not detected"); info!("G-Sync Switchable Graphics not detected");
info!("If your laptop is not a G-Sync enabled laptop then you can ignore this. Standard graphics switching will still work."); info!("If your laptop is not a G-Sync enabled laptop then you can ignore this. Standard graphics switching will still work.");
} }
@@ -176,7 +175,10 @@ impl CtrlRogBios {
info!("Switch for POST boot sound not detected"); info!("Switch for POST boot sound not detected");
} }
Ok(CtrlRogBios { _config: config }) Ok(CtrlRogBios {
platform,
_config: config,
})
} }
fn set_path_mutable(path: &str) -> Result<(), RogError> { fn set_path_mutable(path: &str) -> Result<(), RogError> {
@@ -189,48 +191,14 @@ impl CtrlRogBios {
Ok(()) Ok(())
} }
pub fn has_dedicated_gfx_toggle() -> bool { pub(super) fn set_gfx_mode(&self, enable: bool) -> Result<(), RogError> {
Path::new(ASUS_SWITCH_GRAPHIC_MODE).exists() self.platform.set_gpu_mux_mode(enable)?;
} self.update_initramfs(enable)?;
if enable {
pub fn get_gfx_mode() -> Result<i8, RogError> {
let path = ASUS_SWITCH_GRAPHIC_MODE;
let mut file = OpenOptions::new()
.read(true)
.open(path)
.map_err(|err| RogError::Path(path.into(), err))?;
let mut data = Vec::new();
file.read_to_end(&mut data)
.map_err(|err| RogError::Read(path.into(), err))?;
let idx = data.len() - 1;
Ok(data[idx] as i8)
}
pub(super) fn set_gfx_mode(&self, dedicated: bool) -> Result<(), RogError> {
let path = ASUS_SWITCH_GRAPHIC_MODE;
let mut file = OpenOptions::new()
.read(true)
.write(true)
.open(path)
.map_err(|err| RogError::Path(path.into(), err))?;
let mut data = Vec::new();
file.read_to_end(&mut data)?;
let idx = data.len() - 1;
if dedicated {
data[idx] = 1;
info!("Set system-level graphics mode: Dedicated Nvidia"); info!("Set system-level graphics mode: Dedicated Nvidia");
} else { } else {
data[idx] = 0;
info!("Set system-level graphics mode: Optimus"); info!("Set system-level graphics mode: Optimus");
} }
file.write_all(&data)
.map_err(|err| RogError::Path(path.into(), err))?;
self.update_initramfs(dedicated)?;
Ok(()) Ok(())
} }
@@ -358,42 +326,11 @@ impl CtrlRogBios {
Ok(()) Ok(())
} }
fn set_panel_od(&mut self, overdrive: bool) -> Result<(), RogError> { fn set_panel_od(&mut self, enable: bool) -> Result<(), RogError> {
let path = ASUS_PANEL_OD_PATH; self.platform.set_panel_od(enable).map_err(|err| {
let mut file = OpenOptions::new().write(true).open(path).map_err(|err| {
warn!("CtrlRogBios: set_panel_overdrive {}", err);
err
})?;
let s = if overdrive { '1' } else { '0' };
file.write(&[s as u8]).map_err(|err| {
warn!("CtrlRogBios: set_panel_overdrive {}", err); warn!("CtrlRogBios: set_panel_overdrive {}", err);
err err
})?; })?;
Ok(()) Ok(())
} }
} }
#[cfg(test)]
mod tests {
use super::CtrlRogBios;
use crate::config::Config;
use std::sync::{Arc, Mutex};
#[test]
#[ignore = "Must be manually tested"]
fn set_multizone_4key_config() {
let config = Config::default();
let controller = CtrlRogBios {
_config: Arc::new(Mutex::new(config)),
};
let res = controller.panel_overdrive();
assert_eq!(res, 1);
// controller.set_panel_od(false).unwrap();
// let res = controller.panel_overdrive();
// assert_eq!(res, 0);
}
}

View File

@@ -1,4 +1,5 @@
use rog_anime::error::AnimeError; use rog_anime::error::AnimeError;
use rog_platform::error::PlatformError;
use rog_profiles::error::ProfileError; use rog_profiles::error::ProfileError;
use std::convert::From; use std::convert::From;
use std::fmt; use std::fmt;
@@ -28,6 +29,7 @@ pub enum RogError {
NoAuraKeyboard, NoAuraKeyboard,
NoAuraNode, NoAuraNode,
Anime(AnimeError), Anime(AnimeError),
Platform(PlatformError),
} }
impl fmt::Display for RogError { impl fmt::Display for RogError {
@@ -57,6 +59,7 @@ impl fmt::Display for RogError {
RogError::NoAuraKeyboard => write!(f, "No supported Aura keyboard"), RogError::NoAuraKeyboard => write!(f, "No supported Aura keyboard"),
RogError::NoAuraNode => write!(f, "No Aura keyboard node found"), RogError::NoAuraNode => write!(f, "No Aura keyboard node found"),
RogError::Anime(deets) => write!(f, "AniMe Matrix error: {}", deets), RogError::Anime(deets) => write!(f, "AniMe Matrix error: {}", deets),
RogError::Platform(deets) => write!(f, "Asus Platform error: {}", deets),
} }
} }
} }
@@ -75,6 +78,12 @@ impl From<AnimeError> for RogError {
} }
} }
impl From<PlatformError> for RogError {
fn from(err: PlatformError) -> Self {
RogError::Platform(err)
}
}
impl From<zbus::Error> for RogError { impl From<zbus::Error> for RogError {
fn from(err: zbus::Error) -> Self { fn from(err: zbus::Error) -> Self {
RogError::Zbus(err) RogError::Zbus(err)

View File

@@ -15,7 +15,7 @@ exclude = ["data"]
[features] [features]
default = ["dbus", "detect"] default = ["dbus", "detect"]
dbus = ["zvariant", "zbus"] dbus = ["zvariant", "zbus"]
detect = ["udev", "sysfs-class"] detect = ["sysfs-class"]
[dependencies] [dependencies]
png_pong = "^0.8.0" png_pong = "^0.8.0"
@@ -31,5 +31,4 @@ glam = { version = "^0.21.2", features = ["serde"] }
zvariant = { version = "^3.0", optional = true } zvariant = { version = "^3.0", optional = true }
zbus = { version = "^2.2", optional = true } zbus = { version = "^2.2", optional = true }
udev = { version = "^0.6", optional = true }
sysfs-class = { version = "^0.1", optional = true } sysfs-class = { version = "^0.1", optional = true }

View File

@@ -36,30 +36,6 @@ pub fn get_anime_type() -> Result<AnimeType, AnimeError> {
Err(AnimeError::UnsupportedDevice) Err(AnimeError::UnsupportedDevice)
} }
/// Find the USB device node - known devices so far: `19b6`
#[inline]
pub fn find_node(id_product: &str) -> Result<String, AnimeError> {
let mut enumerator =
udev::Enumerator::new().map_err(|err| AnimeError::Udev("enumerator failed".into(), err))?;
enumerator
.match_subsystem("usb")
.map_err(|err| AnimeError::Udev("match_subsystem failed".into(), err))?;
for device in enumerator
.scan_devices()
.map_err(|err| AnimeError::Udev("scan_devices failed".into(), err))?
{
if let Some(attr) = device.attribute_value("idProduct") {
if attr == id_product {
if let Some(dev_node) = device.devnode() {
return Ok(dev_node.to_string_lossy().to_string());
}
}
}
}
Err(AnimeError::NoDevice)
}
/// Get the two device initialization packets. These are required for device start /// Get the two device initialization packets. These are required for device start
/// after the laptop boots. /// after the laptop boots.
#[inline] #[inline]

View File

@@ -9,7 +9,7 @@ use crate::{error::Error, keys::Key};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{fs::OpenOptions, io::Read, path::Path, slice::Iter}; use std::{fs::OpenOptions, io::Read, path::Path, slice::Iter};
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize, Clone)]
pub struct KeyLayout { pub struct KeyLayout {
/// A series of board names that this layout can be used for. The board names /// 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 /// stored with the layout can be globbed, e.g, GA401 will match all of the
@@ -48,7 +48,7 @@ impl KeyLayout {
} }
} }
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize, Clone)]
pub struct KeyRow { pub struct KeyRow {
height: f32, height: f32,
row: Vec<Key>, row: Vec<Key>,

View File

@@ -1,6 +1,5 @@
use std::{ use std::{
f64::consts::PI, f64::consts::PI,
io::Write,
sync::{ sync::{
atomic::{AtomicBool, AtomicU8, Ordering}, atomic::{AtomicBool, AtomicU8, Ordering},
Arc, Arc,
@@ -12,18 +11,13 @@ use egui::{Button, RichText};
use rog_supported::SupportedFunctions; use rog_supported::SupportedFunctions;
use crate::{ use crate::{
config::Config, error::Result, get_ipc_file, page_states::PageDataStates, Page, config::Config, error::Result, page_states::PageDataStates, Page, RogDbusClientBlocking,
RogDbusClientBlocking, SHOWING_GUI,
}; };
pub struct RogApp<'a> { pub struct RogApp<'a> {
pub page: Page, pub page: Page,
pub states: PageDataStates, pub states: PageDataStates,
pub supported: SupportedFunctions, pub supported: SupportedFunctions,
/// Should the app begin showing the GUI
pub begin_show_gui: Arc<AtomicBool>,
/// Is the app GUI closed (and running in bg)
pub running_in_bg: bool,
// TODO: can probably just open and read whenever // TODO: can probably just open and read whenever
pub config: Config, pub config: Config,
pub asus_dbus: RogDbusClientBlocking<'a>, pub asus_dbus: RogDbusClientBlocking<'a>,
@@ -40,9 +34,7 @@ pub struct RogApp<'a> {
impl<'a> RogApp<'a> { impl<'a> RogApp<'a> {
/// Called once before the first frame. /// Called once before the first frame.
pub fn new( pub fn new(
start_closed: bool,
config: Config, config: Config,
show_gui: Arc<AtomicBool>,
states: PageDataStates, states: PageDataStates,
_cc: &eframe::CreationContext<'_>, _cc: &eframe::CreationContext<'_>,
) -> Result<Self> { ) -> Result<Self> {
@@ -99,8 +91,6 @@ impl<'a> RogApp<'a> {
supported, supported,
states, states,
page: Page::System, page: Page::System,
begin_show_gui: show_gui,
running_in_bg: start_closed,
config, config,
asus_dbus: dbus, asus_dbus: dbus,
oscillator1, oscillator1,
@@ -113,20 +103,10 @@ impl<'a> RogApp<'a> {
} }
impl<'a> eframe::App for RogApp<'a> { impl<'a> eframe::App for RogApp<'a> {
fn on_exit_event(&mut self) -> bool {
if self.config.run_in_background {
self.running_in_bg = true;
get_ipc_file().unwrap().write_all(&[0]).unwrap();
return false;
}
true
}
/// Called each time the UI needs repainting, which may be many times per second. /// 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`. /// Put your widgets into a `SidePanel`, `TopPanel`, `CentralPanel`, `Window` or `Area`.
fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) { fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
let Self { let Self {
begin_show_gui: should_show_gui,
supported, supported,
asus_dbus: dbus, asus_dbus: dbus,
states, states,
@@ -144,21 +124,6 @@ impl<'a> eframe::App for RogApp<'a> {
let page = self.page; let page = self.page;
if should_show_gui.load(Ordering::SeqCst) {
let mut ipc_file = get_ipc_file().unwrap();
ipc_file.write_all(&[SHOWING_GUI]).unwrap();
should_show_gui.store(false, Ordering::SeqCst);
frame.set_visible(true);
self.running_in_bg = false;
}
if self.running_in_bg {
// Request to draw nothing at all
ctx.request_repaint_after(Duration::from_millis(500));
frame.set_visible(false);
return;
}
// Do all GUI display after this point
self.top_bar(ctx, frame); self.top_bar(ctx, frame);
self.side_panel(ctx); self.side_panel(ctx);

View File

@@ -44,6 +44,14 @@ pub fn on_tmp_dir_exists() -> Result<TempDir, std::io::Error> {
let mut buf = [0u8; 4]; let mut buf = [0u8; 4];
let path = std::env::temp_dir().join("rog-gui"); let path = std::env::temp_dir().join("rog-gui");
if path.read_dir()?.next().is_none() {
std::fs::remove_dir_all(path)?;
return tempfile::Builder::new()
.prefix("rog-gui")
.rand_bytes(0)
.tempdir();
}
let mut ipc_file = OpenOptions::new() let mut ipc_file = OpenOptions::new()
.read(true) .read(true)
.write(true) .write(true)

View File

@@ -2,19 +2,14 @@ use rog_aura::layouts::KeyLayout;
use rog_control_center::{ use rog_control_center::{
config::Config, get_ipc_file, notify::start_notifications, on_tmp_dir_exists, config::Config, get_ipc_file, notify::start_notifications, on_tmp_dir_exists,
page_states::PageDataStates, startup_error::AppErrorShow, RogApp, RogDbusClientBlocking, page_states::PageDataStates, startup_error::AppErrorShow, RogApp, RogDbusClientBlocking,
SHOW_GUI, SHOWING_GUI, SHOW_GUI,
}; };
use std::{ use std::{
fs::{self, OpenOptions}, fs::{self, OpenOptions},
io::Read, io::{Read, Write},
path::PathBuf, path::PathBuf,
sync::{ sync::{atomic::AtomicBool, Arc},
atomic::{AtomicBool, Ordering},
Arc,
},
thread::spawn,
time::Duration,
}; };
#[cfg(not(feature = "mocking"))] #[cfg(not(feature = "mocking"))]
@@ -29,6 +24,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
transparent: false, transparent: false,
min_window_size: Some(egui::vec2(840.0, 600.0)), min_window_size: Some(egui::vec2(840.0, 600.0)),
max_window_size: Some(egui::vec2(840.0, 600.0)), max_window_size: Some(egui::vec2(840.0, 600.0)),
run_and_return: true,
..Default::default() ..Default::default()
}; };
@@ -44,7 +40,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
// Startup // Startup
let mut config = Config::load()?; let mut config = Config::load()?;
let start_closed = config.startup_in_background; let mut start_closed = config.startup_in_background;
if config.startup_in_background { if config.startup_in_background {
config.run_in_background = true; config.run_in_background = true;
@@ -94,44 +90,15 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let fans_notified = Arc::new(AtomicBool::new(false)); let fans_notified = Arc::new(AtomicBool::new(false));
let notifs_enabled = Arc::new(AtomicBool::new(config.enable_notifications)); let notifs_enabled = Arc::new(AtomicBool::new(config.enable_notifications));
let states = { start_notifications(
let supported = dbus charge_notified.clone(),
.proxies() bios_notified.clone(),
.supported() aura_notified.clone(),
.supported_functions() anime_notified.clone(),
.map_err(|e| { profiles_notified.clone(),
eframe::run_native( fans_notified.clone(),
"ROG Control Center", notifs_enabled.clone(),
native_options.clone(), )?;
Box::new(move |_| Box::new(AppErrorShow::new(e.to_string()))),
);
})
.unwrap();
PageDataStates::new(
layout,
notifs_enabled.clone(),
charge_notified.clone(),
bios_notified.clone(),
aura_notified.clone(),
anime_notified.clone(),
profiles_notified.clone(),
fans_notified.clone(),
&supported,
&dbus,
)? // TODO: if error, show alt GUI containing the error message
};
if config.enable_notifications {
start_notifications(
charge_notified,
bios_notified,
aura_notified,
anime_notified,
profiles_notified,
fans_notified,
notifs_enabled,
)?;
}
// tmp-dir must live to the end of program life // tmp-dir must live to the end of program life
let _tmp_dir = match tempfile::Builder::new() let _tmp_dir = match tempfile::Builder::new()
@@ -143,25 +110,59 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
Err(_) => on_tmp_dir_exists().unwrap(), Err(_) => on_tmp_dir_exists().unwrap(),
}; };
let should_show_gui = Arc::new(AtomicBool::new(!start_closed)); loop {
let should = should_show_gui.clone(); let states = {
spawn(move || { let supported = match dbus.proxies().supported().supported_functions() {
// Loop is blocked here until a single byte is read Ok(s) => s,
loop { Err(e) => {
let mut buf = [0u8; 4]; eframe::run_native(
if get_ipc_file().unwrap().read(&mut buf).is_ok() && buf[0] == SHOW_GUI { "ROG Control Center",
should_show_gui.store(true, Ordering::SeqCst); native_options.clone(),
// Give the starting app a change to read or we'll race it Box::new(move |_| Box::new(AppErrorShow::new(e.to_string()))),
std::thread::sleep(Duration::from_millis(10)); );
} return Ok(());
} }
}); };
eframe::run_native( PageDataStates::new(
"ROG Control Center", layout.clone(),
native_options, notifs_enabled.clone(),
Box::new(move |cc| { charge_notified.clone(),
Box::new(RogApp::new(start_closed, config, should, states, cc).unwrap()) bios_notified.clone(),
}), aura_notified.clone(),
); anime_notified.clone(),
profiles_notified.clone(),
fans_notified.clone(),
&supported,
&dbus,
)?
};
if !start_closed {
let mut ipc_file = get_ipc_file().unwrap();
ipc_file.write_all(&[SHOWING_GUI]).unwrap();
eframe::run_native(
"ROG Control Center",
native_options.clone(),
Box::new(move |cc| {
Box::new(RogApp::new(Config::load().unwrap(), states, cc).unwrap())
}),
);
}
let config = Config::load().unwrap();
if !config.run_in_background {
break;
}
let mut buf = [0u8; 4];
// blocks until it is read, typically the read will happen after a second
// process writes to the IPC (so there is data to actually read)
if get_ipc_file().unwrap().read(&mut buf).is_ok() && buf[0] == SHOW_GUI {
start_closed = false;
continue;
}
dbg!("asda");
}
Ok(())
} }

View File

@@ -39,13 +39,13 @@ impl BiosState {
} else { } else {
false false
}, },
dedicated_gfx: if supported.rog_bios_ctrl.dedicated_gfx { dedicated_gfx: if supported.rog_bios_ctrl.dgpu_only {
dbus.proxies().rog_bios().dedicated_graphic_mode()? != 0 dbus.proxies().rog_bios().dedicated_graphic_mode()?
} else { } else {
false false
}, },
panel_overdrive: if supported.rog_bios_ctrl.panel_overdrive { panel_overdrive: if supported.rog_bios_ctrl.panel_overdrive {
dbus.proxies().rog_bios().panel_overdrive()? != 0 dbus.proxies().rog_bios().panel_overdrive()?
} else { } else {
false false
}, },

View File

@@ -1,7 +1,7 @@
use std::{sync::atomic::Ordering, time::Duration}; use std::{sync::atomic::Ordering, time::Duration};
use egui::Color32; use egui::Color32;
use rog_aura::AuraModeNum; use rog_aura::{AuraEffect, AuraModeNum};
use crate::{ use crate::{
widgets::{aura_modes_group, keyboard}, widgets::{aura_modes_group, keyboard},
@@ -31,14 +31,14 @@ impl<'a> RogApp<'a> {
.aura .aura
.modes .modes
.get(&states.aura.current_mode) .get(&states.aura.current_mode)
.unwrap() .unwrap_or(&AuraEffect::default())
.colour1; .colour1;
let c2 = states let c2 = states
.aura .aura
.modes .modes
.get(&states.aura.current_mode) .get(&states.aura.current_mode)
.unwrap() .unwrap_or(&AuraEffect::default())
.colour2; .colour2;
let mut colour = Color32::from_rgb(c1.0, c1.1, c1.2); let mut colour = Color32::from_rgb(c1.0, c1.1, c1.2);

View File

@@ -16,20 +16,21 @@ pub fn fan_graphs(
ui.separator(); ui.separator();
let mut item = |p: Profile, ui: &mut Ui| { let mut item = |p: Profile, ui: &mut Ui| {
ui.group(|ui|{ ui.group(|ui| {
ui.selectable_value(&mut curves.show_curve, p, format!("{p:?}")); ui.selectable_value(&mut curves.show_curve, p, format!("{p:?}"));
ui.add_enabled_ui(curves.show_curve == p ,|ui| { ui.add_enabled_ui(curves.show_curve == p, |ui| {
ui.selectable_value( ui.selectable_value(
&mut curves.show_graph, &mut curves.show_graph,
FanCurvePU::CPU, FanCurvePU::CPU,
format!("{:?}", FanCurvePU::CPU), format!("{:?}", FanCurvePU::CPU),
); );
ui.selectable_value( ui.selectable_value(
&mut curves.show_graph, &mut curves.show_graph,
FanCurvePU::GPU, FanCurvePU::GPU,
format!("{:?}", FanCurvePU::GPU), format!("{:?}", FanCurvePU::GPU),
); );
});}); });
});
}; };
ui.horizontal_wrapped(|ui| { ui.horizontal_wrapped(|ui| {

View File

@@ -90,7 +90,7 @@ pub fn rog_bios_group(
} }
} }
if supported.rog_bios_ctrl.dedicated_gfx { if supported.rog_bios_ctrl.dgpu_only {
if ui if ui
.add(egui::Checkbox::new( .add(egui::Checkbox::new(
&mut states.bios.dedicated_gfx, &mut states.bios.dedicated_gfx,

View File

@@ -27,7 +27,7 @@ use zbus_macros::dbus_proxy;
)] )]
trait RogBios { trait RogBios {
/// DedicatedGraphicMode method /// DedicatedGraphicMode method
fn dedicated_graphic_mode(&self) -> zbus::Result<i16>; fn dedicated_graphic_mode(&self) -> zbus::Result<bool>;
/// PostBootSound method /// PostBootSound method
fn post_boot_sound(&self) -> zbus::Result<i16>; fn post_boot_sound(&self) -> zbus::Result<i16>;
@@ -39,7 +39,7 @@ trait RogBios {
fn set_post_boot_sound(&self, on: bool) -> zbus::Result<()>; fn set_post_boot_sound(&self, on: bool) -> zbus::Result<()>;
/// PanelOverdrive method /// PanelOverdrive method
fn panel_overdrive(&self) -> zbus::Result<i8>; fn panel_overdrive(&self) -> zbus::Result<bool>;
/// SetPanelOverdrive method /// SetPanelOverdrive method
fn set_panel_overdrive(&self, overdrive: bool) -> zbus::Result<()>; fn set_panel_overdrive(&self, overdrive: bool) -> zbus::Result<()>;

12
rog-platform/Cargo.toml Normal file
View File

@@ -0,0 +1,12 @@
[package]
name = "rog_platform"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
log = "*"
udev = "^0.6"
rusb = "^0.9"
sysfs-class = "^0.1"

51
rog-platform/src/error.rs Normal file
View File

@@ -0,0 +1,51 @@
use std::fmt;
pub type Result<T> = std::result::Result<T, PlatformError>;
#[derive(Debug)]
pub enum PlatformError {
ParseVendor,
ParseNum,
Udev(String, std::io::Error),
USB(rusb::Error),
Path(String, std::io::Error),
Read(String, std::io::Error),
Write(String, std::io::Error),
NotSupported,
AttrNotFound(String),
MissingFunction(String),
MissingLedBrightNode(String, std::io::Error),
Io(String, std::io::Error),
NoAuraKeyboard,
NoAuraNode,
}
impl fmt::Display for PlatformError {
// This trait requires `fmt` with this exact signature.
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
PlatformError::ParseVendor => write!(f, "Parse gfx vendor error"),
PlatformError::ParseNum => write!(f, "Parse number error"),
PlatformError::Udev(deets, error) => write!(f, "udev {}: {}", deets, error),
PlatformError::USB(error) => write!(f, "usb {}", error),
PlatformError::Path(path, error) => write!(f, "Path {}: {}", path, error),
PlatformError::Read(path, error) => write!(f, "Read {}: {}", path, error),
PlatformError::Write(path, error) => write!(f, "Write {}: {}", path, error),
PlatformError::NotSupported => write!(f, "Not supported"),
PlatformError::AttrNotFound(deets) => write!(f, "Attribute not found: {}", 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::Io(path, detail) => write!(f, "std::io error: {} {}", path, detail),
PlatformError::NoAuraKeyboard => write!(f, "No supported Aura keyboard"),
PlatformError::NoAuraNode => write!(f, "No Aura keyboard node found"),
}
}
}
impl std::error::Error for PlatformError {}
impl From<rusb::Error> for PlatformError {
fn from(err: rusb::Error) -> Self {
PlatformError::USB(err)
}
}

View File

@@ -0,0 +1,55 @@
use std::{fs::OpenOptions, io::Write, path::PathBuf};
use log::{info, warn};
use crate::error::{PlatformError, Result};
#[derive(Debug, PartialEq, PartialOrd)]
pub struct HidRaw(PathBuf);
impl HidRaw {
pub fn new(id_product: &str) -> Result<Self> {
let mut enumerator = udev::Enumerator::new().map_err(|err| {
warn!("{}", err);
PlatformError::Udev("enumerator failed".into(), err)
})?;
enumerator.match_subsystem("hidraw").map_err(|err| {
warn!("{}", err);
PlatformError::Udev("match_subsystem failed".into(), err)
})?;
for device in enumerator
.scan_devices()
.map_err(|e| PlatformError::Io("enumerator".to_owned(), e))?
{
if let Some(parent) = device
.parent_with_subsystem_devtype("usb", "usb_device")
.map_err(|e| PlatformError::Io(device.devpath().to_string_lossy().to_string(), e))?
{
if let Some(parent) = parent.attribute_value("idProduct") {
if parent == id_product {
if let Some(dev_node) = device.devnode() {
info!("Using device at: {:?} for LED control", dev_node);
return Ok(Self(dev_node.to_owned()));
}
}
}
}
}
Err(PlatformError::MissingFunction(format!(
"hidraw dev {} not found",
id_product
)))
}
pub fn write_bytes(&self, message: &[u8]) -> Result<()> {
let mut file = OpenOptions::new()
.write(true)
.open(&self.0)
.map_err(|e| PlatformError::Io(self.0.to_string_lossy().to_string(), e))?;
// println!("write: {:02x?}", &message);
file.write_all(message)
.map_err(|e| PlatformError::Io(self.0.to_string_lossy().to_string(), e))
}
}

View File

@@ -0,0 +1,59 @@
use std::path::PathBuf;
use log::warn;
use crate::{
attr_u8, attr_u8_array,
error::{PlatformError, Result},
to_device,
};
#[derive(Debug, Default, PartialEq, PartialOrd)]
pub struct KeyboardLed(PathBuf);
impl KeyboardLed {
pub fn new() -> Result<Self> {
let mut enumerator = udev::Enumerator::new().map_err(|err| {
warn!("{}", err);
PlatformError::Udev("enumerator failed".into(), err)
})?;
enumerator.match_subsystem("leds").map_err(|err| {
warn!("{}", err);
PlatformError::Udev("match_subsystem failed".into(), err)
})?;
enumerator
.match_sysname("asus::kbd_backlight")
.map_err(|err| {
warn!("{}", err);
PlatformError::Udev("match_subsystem failed".into(), err)
})?;
for device in enumerator.scan_devices().map_err(|err| {
warn!("{}", err);
PlatformError::Udev("scan_devices failed".into(), err)
})? {
return Ok(Self(device.syspath().to_owned()));
}
Err(PlatformError::MissingFunction(
"asus::kbd_backlight not found".into(),
))
}
attr_u8!(has_brightness, get_brightness, set_brightness, "brightness");
attr_u8_array!(
has_keyboard_rgb_mode,
get_keyboard_rgb_mode,
set_keyboard_rgb_mode,
"kbd_rgb_mode"
);
attr_u8_array!(
has_keyboard_rgb_state,
get_keyboard_rgb_state,
set_keyboard_rgb_state,
"kbd_rgb_state"
);
}

191
rog-platform/src/lib.rs Normal file
View File

@@ -0,0 +1,191 @@
pub mod error;
pub mod hid_raw;
pub mod keyboard_led;
pub mod platform;
pub mod usb_raw;
use std::path::Path;
use error::{PlatformError, Result};
use udev::Device;
#[macro_export]
macro_rules! attr_bool {
($hasser:ident, $getter:ident, $setter:ident, $attr_name:literal) => {
pub fn $hasser(&self) -> bool {
match to_device(&self.0) {
Ok(p) => crate::has_attr(&p, $attr_name),
Err(_) => false,
}
}
pub fn $getter(&self) -> Result<bool> {
crate::read_attr_bool(&to_device(&self.0)?, $attr_name)
}
pub fn $setter(&self, value: bool) -> Result<()> {
crate::write_attr_bool(&mut to_device(&self.0)?, $attr_name, value)
}
};
}
#[macro_export]
macro_rules! attr_u8 {
($hasser:ident, $getter:ident, $setter:ident, $attr_name:literal) => {
pub fn $hasser(&self) -> bool {
match to_device(&self.0) {
Ok(p) => crate::has_attr(&p, $attr_name),
Err(_) => false,
}
}
pub fn $getter(&self) -> Result<u8> {
crate::read_attr_u8(&to_device(&self.0)?, $attr_name)
}
pub fn $setter(&self, value: u8) -> Result<()> {
crate::write_attr_u8(&mut to_device(&self.0)?, $attr_name, value)
}
};
}
#[macro_export]
macro_rules! attr_u8_array {
($hasser:ident, $getter:ident, $setter:ident, $attr_name:literal) => {
pub fn $hasser(&self) -> bool {
match to_device(&self.0) {
Ok(p) => crate::has_attr(&p, $attr_name),
Err(_) => false,
}
}
pub fn $getter(&self) -> Result<Vec<u8>> {
crate::read_attr_u8_array(&to_device(&self.0)?, $attr_name)
}
pub fn $setter(&self, values: &[u8]) -> Result<()> {
crate::write_attr_u8_array(&mut to_device(&self.0)?, $attr_name, values)
}
};
}
pub(crate) fn to_device(sys_path: &Path) -> Result<Device> {
Device::from_syspath(sys_path)
.map_err(|e| PlatformError::Udev("Couldn't transform syspath to device".to_string(), e))
}
pub fn has_attr(device: &Device, attr_name: &str) -> bool {
for attr in device.attributes() {
if attr.name() == attr_name {
return true;
}
}
false
}
pub fn read_attr_bool(device: &Device, attr_name: &str) -> Result<bool> {
if let Some(value) = device.attribute_value(attr_name) {
let tmp = value.to_string_lossy();
if tmp.trim() == "0" {
return Ok(false);
}
return Ok(true);
}
Err(PlatformError::AttrNotFound(attr_name.to_string()))
}
pub fn write_attr_bool(device: &mut Device, attr: &str, value: bool) -> Result<()> {
device
.set_attribute_value(attr, &(value as u8).to_string())
.map_err(|e| PlatformError::Io(attr.into(), e))
}
pub fn read_attr_u8(device: &Device, attr_name: &str) -> Result<u8> {
if let Some(value) = device.attribute_value(attr_name) {
let tmp = value.to_string_lossy();
return Ok(tmp.parse::<u8>().map_err(|_| PlatformError::ParseNum)?);
}
Err(PlatformError::AttrNotFound(attr_name.to_string()))
}
pub fn write_attr_u8(device: &mut Device, attr: &str, value: u8) -> Result<()> {
device
.set_attribute_value(attr, &(value).to_string())
.map_err(|e| PlatformError::Io(attr.into(), e))
}
pub fn read_attr_u8_array(device: &Device, attr_name: &str) -> Result<Vec<u8>> {
if let Some(value) = device.attribute_value(attr_name) {
let tmp = value.to_string_lossy();
let tmp = tmp
.split(' ')
.map(|v| u8::from_str_radix(v, 10).unwrap_or(0))
.collect();
return Ok(tmp);
}
Err(PlatformError::AttrNotFound(attr_name.to_string()))
}
pub fn write_attr_u8_array(device: &mut Device, attr: &str, values: &[u8]) -> Result<()> {
let tmp: String = values.iter().map(|v| format!("{} ", v)).collect();
let tmp = tmp.trim();
device
.set_attribute_value(attr, &tmp)
.map_err(|e| PlatformError::Io(attr.into(), e))
}
#[cfg(test)]
mod tests {
#[test]
fn check() {
let data = [1, 2, 3, 4, 5];
let tmp: String = data.iter().map(|v| format!("{} ", v)).collect();
let tmp = tmp.trim();
assert_eq!(tmp, "1 2 3 4 5");
let tmp: Vec<u8> = tmp
.split(' ')
.map(|v| u8::from_str_radix(v, 10).unwrap_or(0))
.collect();
assert_eq!(tmp, &[1, 2, 3, 4, 5]);
}
}
// pub fn find_led_node(id_product: &str) -> Result<Device, PlatformError> {
// let mut enumerator = udev::Enumerator::new().map_err(|err| {
// warn!("{}", err);
// PlatformError::Udev("enumerator failed".into(), err)
// })?;
// enumerator.match_subsystem("hidraw").map_err(|err| {
// warn!("{}", err);
// PlatformError::Udev("match_subsystem failed".into(), err)
// })?;
// for device in enumerator.scan_devices().map_err(|err| {
// warn!("{}", err);
// PlatformError::Udev("scan_devices failed".into(), err)
// })? {
// if let Some(parent) = device
// .parent_with_subsystem_devtype("usb", "usb_device")
// .map_err(|err| {
// warn!("{}", 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
// {
// if let Some(dev_node) = device.devnode() {
// info!("Using device at: {:?} for LED control", dev_node);
// return Ok(device);
// }
// }
// }
// }
// Err(PlatformError::MissingFunction(
// "ASUS LED device node not found".into(),
// ))
// }

View File

@@ -0,0 +1,69 @@
use std::path::PathBuf;
use log::warn;
use crate::{
attr_bool,
error::{PlatformError, Result},
to_device,
};
/// The "platform" device provides access to things like:
/// - dgpu_disable
/// - egpu_enable
/// - panel_od
/// - dgpu_only
/// - keyboard_mode, set keyboard RGB mode and speed
/// - keyboard_state, set keyboard power states
#[derive(Debug, PartialEq, PartialOrd)]
pub struct AsusPlatform(PathBuf);
impl AsusPlatform {
pub fn new() -> Result<Self> {
let mut enumerator = udev::Enumerator::new().map_err(|err| {
warn!("{}", err);
PlatformError::Udev("enumerator failed".into(), err)
})?;
enumerator.match_subsystem("platform").map_err(|err| {
warn!("{}", err);
PlatformError::Udev("match_subsystem failed".into(), err)
})?;
enumerator.match_sysname("asus-nb-wmi").map_err(|err| {
warn!("{}", err);
PlatformError::Udev("match_subsystem failed".into(), err)
})?;
for device in enumerator.scan_devices().map_err(|err| {
warn!("{}", err);
PlatformError::Udev("scan_devices failed".into(), err)
})? {
return Ok(Self(device.syspath().to_owned()));
}
Err(PlatformError::MissingFunction(
"asus-nb-wmi not found".into(),
))
}
attr_bool!(
has_dgpu_disable,
get_dgpu_disable,
set_dgpu_disable,
"dgpu_disable"
);
attr_bool!(
has_egpu_enable,
get_egpu_enable,
set_egpu_enable,
"egpu_enable"
);
attr_bool!(has_panel_od, get_panel_od, set_panel_od, "panel_od");
attr_bool!(
has_gpu_mux_mode,
get_gpu_mux_mode,
set_gpu_mux_mode,
"gpu_mux_mode"
);
}

View File

@@ -0,0 +1,48 @@
use rusb::{Device, DeviceHandle};
use std::time::Duration;
use crate::error::{PlatformError, Result};
#[derive(Debug, PartialEq)]
pub struct USBRaw(DeviceHandle<rusb::GlobalContext>);
impl USBRaw {
pub fn new(id_product: u16) -> Result<Self> {
for device in rusb::devices()?.iter() {
let device_desc = device.device_descriptor()?;
if device_desc.vendor_id() == 0x0b05 && device_desc.product_id() == id_product {
let handle = Self::get_dev_handle(device)?;
return Ok(Self(handle));
}
}
Err(PlatformError::MissingFunction(format!(
"USBRaw dev {} not found",
id_product
)))
}
fn get_dev_handle(
device: Device<rusb::GlobalContext>,
) -> Result<DeviceHandle<rusb::GlobalContext>> {
// We don't expect this ID to ever change
let mut device = device.open()?;
device.reset()?;
device.set_auto_detach_kernel_driver(true)?;
device.claim_interface(0)?;
Ok(device)
}
pub fn write_bytes(&self, message: &[u8]) -> Result<usize> {
self.0
.write_control(
0x21, // request_type
0x09, // request
0x35e, // value
0x00, // index
message,
Duration::from_millis(200),
)
.map_err(|e| PlatformError::USB(e))
}
}

View File

@@ -40,7 +40,7 @@ pub struct LedSupportedFunctions {
#[derive(Serialize, Deserialize, Type, Debug, Default)] #[derive(Serialize, Deserialize, Type, Debug, Default)]
pub struct RogBiosSupportedFunctions { pub struct RogBiosSupportedFunctions {
pub post_sound: bool, pub post_sound: bool,
pub dedicated_gfx: bool, pub dgpu_only: bool,
pub panel_overdrive: bool, pub panel_overdrive: bool,
pub dgpu_disable: bool, pub dgpu_disable: bool,
pub egpu_enable: bool, pub egpu_enable: bool,
@@ -95,7 +95,7 @@ impl fmt::Display for RogBiosSupportedFunctions {
writeln!(f, "\tPanel Overdrive: {}", self.panel_overdrive)?; writeln!(f, "\tPanel Overdrive: {}", self.panel_overdrive)?;
writeln!(f, "\tdGPU disable switch: {}", self.dgpu_disable)?; writeln!(f, "\tdGPU disable switch: {}", self.dgpu_disable)?;
writeln!(f, "\teGPU enable switch: {}", self.egpu_enable)?; writeln!(f, "\teGPU enable switch: {}", self.egpu_enable)?;
writeln!(f, "\tDedicated GFX switch: {}", self.dedicated_gfx)?; writeln!(f, "\tDedicated GFX switch: {}", self.dgpu_only)?;
Ok(()) Ok(())
} }
} }