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).
## [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
### Bugfix

157
Cargo.lock generated
View File

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

View File

@@ -1,5 +1,5 @@
[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]
# thin = 57s, asusd = 9.0M

View File

@@ -774,7 +774,7 @@ fn handle_bios_option(
for line in usage.iter().filter(|line| {
line.contains("sound") && supported.post_sound
|| line.contains("GPU") && supported.dedicated_gfx
|| line.contains("GPU") && supported.dgpu_only
|| line.contains("panel") && supported.panel_overdrive
}) {
println!("{}", line);
@@ -802,7 +802,7 @@ fn handle_bios_option(
}
}
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);
}
@@ -810,7 +810,7 @@ fn handle_bios_option(
dbus.proxies().rog_bios().set_panel_overdrive(opt)?;
}
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);
}
}

View File

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

View File

@@ -8,25 +8,21 @@ use logind_zbus::manager::ManagerProxy;
use rog_anime::{
error::AnimeError,
usb::{
find_node, get_anime_type, pkt_for_apply, pkt_for_flush, pkt_for_set_boot, pkt_for_set_on,
pkts_for_init, PROD_ID, VENDOR_ID,
get_anime_type, pkt_for_apply, pkt_for_flush, pkt_for_set_boot, pkt_for_set_on,
pkts_for_init,
},
ActionData, AnimeDataBuffer, AnimePacketType, AnimeType,
};
use rog_platform::{hid_raw::HidRaw, usb_raw::USBRaw};
use rog_supported::AnimeSupportedFunctions;
use rusb::{Device, DeviceHandle};
use smol::{stream::StreamExt, Executor};
use std::sync::atomic::{AtomicBool, Ordering};
use std::{
cell::RefCell,
convert::TryFrom,
error::Error,
sync::{Arc, Mutex, MutexGuard},
thread::sleep,
};
use std::{
sync::atomic::{AtomicBool, Ordering},
time::Duration,
};
use crate::{error::RogError, GetSupported};
@@ -36,14 +32,13 @@ impl GetSupported for CtrlAnime {
type A = AnimeSupportedFunctions;
fn get_supported() -> Self::A {
AnimeSupportedFunctions(CtrlAnime::get_device(VENDOR_ID, PROD_ID).is_ok())
AnimeSupportedFunctions(HidRaw::new("193b").is_ok())
}
}
pub struct CtrlAnime {
_node: String,
node: USBRaw,
anime_type: AnimeType,
handle: RefCell<DeviceHandle<rusb::GlobalContext>>,
cache: AnimeConfigCached,
config: AnimeConfig,
// set to force thread to exit
@@ -55,57 +50,26 @@ pub struct CtrlAnime {
impl CtrlAnime {
#[inline]
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 device = Self::get_dev_handle()?;
info!("Device has an AniMe Matrix display");
let mut cache = AnimeConfigCached::default();
cache.init_from_config(&config, anime_type)?;
let ctrl = CtrlAnime {
_node: node,
node,
anime_type,
handle: RefCell::new(device),
cache,
config,
thread_exit: Arc::new(AtomicBool::new(false)),
thread_running: Arc::new(AtomicBool::new(false)),
};
ctrl.do_initialization();
ctrl.do_initialization()?;
Ok(ctrl)
}
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)
}
// 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.
@@ -230,45 +194,6 @@ impl CtrlAnime {
.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
/// global brightness set in config.
fn write_data_buffer(&self, mut buffer: AnimeDataBuffer) -> Result<(), RogError> {
@@ -281,16 +206,17 @@ impl CtrlAnime {
}
let data = AnimePacketType::try_from(buffer)?;
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(())
}
fn do_initialization(&self) {
fn do_initialization(&self) -> Result<(), RogError> {
let pkts = pkts_for_init();
self.write_bytes(&pkts[0]);
self.write_bytes(&pkts[1]);
self.node.write_bytes(&pkts[0])?;
self.node.write_bytes(&pkts[1])?;
Ok(())
}
}
@@ -380,10 +306,12 @@ pub struct CtrlAnimeReloader(pub Arc<Mutex<CtrlAnime>>);
impl crate::Reloadable for CtrlAnimeReloader {
fn reload(&mut self) -> Result<(), RogError> {
if let Ok(lock) = self.0.try_lock() {
lock.write_bytes(&pkt_for_set_on(lock.config.awake_enabled));
lock.write_bytes(&pkt_for_apply());
lock.write_bytes(&pkt_for_set_boot(lock.config.boot_anim_enabled));
lock.write_bytes(&pkt_for_apply());
lock.node
.write_bytes(&pkt_for_set_on(lock.config.awake_enabled))?;
lock.node.write_bytes(&pkt_for_apply())?;
lock.node
.write_bytes(&pkt_for_set_boot(lock.config.boot_anim_enabled))?;
lock.node.write_bytes(&pkt_for_apply())?;
let action = lock.cache.boot.clone();
CtrlAnime::run_thread(self.0.clone(), action, true);

View File

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

View File

@@ -2,13 +2,13 @@ use crate::laptops::{LaptopLedData, ASUS_KEYBOARD_DEVICES};
use log::{error, warn};
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};
use super::controller::CtrlKbdLed;
pub static AURA_CONFIG_PATH: &str = "/etc/asusd/aura.conf";
/// Enable/disable LED control in various states such as
@@ -128,14 +128,16 @@ impl Default for AuraConfig {
fn default() -> Self {
let mut prod_id = AuraDevice::Unknown;
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);
break;
}
}
if CtrlKbdLed::get_tuf_mode_path().is_some() {
prod_id = AuraDevice::Tuf;
if let Ok(p) = KeyboardLed::new() {
if p.has_keyboard_rgb_mode() {
prod_id = AuraDevice::Tuf;
}
}
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::{
error::RogError,
laptops::{LaptopLedData, ASUS_KEYBOARD_DEVICES},
@@ -16,16 +11,13 @@ use rog_aura::{
AuraEffect, LedBrightness, LED_MSG_LEN,
};
use rog_aura::{AuraZone, Direction, Speed, GRADIENT};
use rog_platform::{hid_raw::HidRaw, keyboard_led::KeyboardLed};
use rog_supported::LedSupportedFunctions;
use smol::{stream::StreamExt, Executor};
use std::path::Path;
use std::collections::BTreeMap;
use std::sync::Arc;
use std::sync::Mutex;
use std::{
collections::BTreeMap,
io::{Read, Write},
};
use std::{fs::OpenOptions, sync::MutexGuard};
use std::sync::MutexGuard;
use zbus::Connection;
use crate::GetSupported;
@@ -44,19 +36,21 @@ impl GetSupported for CtrlKbdLed {
let mut prod_id = AuraDevice::Unknown;
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);
break;
}
}
if Self::get_tuf_mode_path().is_some() {
prod_id = AuraDevice::Tuf;
if let Ok(p) = KeyboardLed::new() {
if p.has_keyboard_rgb_mode() {
prod_id = AuraDevice::Tuf;
}
}
LedSupportedFunctions {
prod_id,
brightness_set: CtrlKbdLed::get_kbd_bright_path().is_some(),
brightness_set: KeyboardLed::new().is_ok(),
stock_led_modes,
multizone_led_mode,
per_key_led_mode,
@@ -66,8 +60,8 @@ impl GetSupported for CtrlKbdLed {
#[derive(Debug, PartialEq, PartialOrd)]
pub enum LEDNode {
Tuf,
Rog(String),
KbdLed(KeyboardLed),
Rog(HidRaw),
None,
}
@@ -75,7 +69,7 @@ pub struct CtrlKbdLed {
// TODO: config stores the keyboard type as an AuraPower, use or update this
pub led_prod: Option<String>,
pub led_node: LEDNode,
pub bright_node: String,
pub kd_brightness: KeyboardLed,
pub supported_modes: LaptopLedData,
pub flip_effect_write: bool,
pub config: AuraConfig,
@@ -91,27 +85,11 @@ impl CtrlKbdLedTask {
}
fn update_config(lock: &mut CtrlKbdLed) -> Result<(), RogError> {
let mut file = OpenOptions::new()
.read(true)
.open(&lock.bright_node)
.map_err(|err| match err.kind() {
std::io::ErrorKind::NotFound => {
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)
let bright = lock.kd_brightness.get_brightness()?;
lock.config.read();
lock.config.brightness = (bright as u32).into();
lock.config.write();
return Ok(());
}
}
@@ -189,9 +167,7 @@ impl crate::Reloadable for CtrlKbdLedReloader {
fn reload(&mut self) -> Result<(), RogError> {
if let Ok(mut ctrl) = self.0.try_lock() {
ctrl.write_current_config_mode()?;
ctrl.set_power_states(&ctrl.config)
.map_err(|err| warn!("{err}"))
.ok();
ctrl.set_power_states().map_err(|err| warn!("{err}")).ok();
}
Ok(())
}
@@ -210,7 +186,7 @@ impl CtrlKbdLed {
let mut led_prod = None;
let mut led_node = None;
for prod in ASUS_KEYBOARD_DEVICES.iter() {
match Self::find_led_node(prod) {
match HidRaw::new(prod) {
Ok(node) => {
led_prod = Some(prod.to_string());
led_node = Some(node);
@@ -221,10 +197,10 @@ impl CtrlKbdLed {
}
}
let bright_node = Self::get_kbd_bright_path();
let tuf_node = Self::get_tuf_mode_path().is_some() || Self::get_tuf_state_path().is_some();
let bright_node = KeyboardLed::new();
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();
if let Ok(prod_family) = dmi.product_family() {
if prod_family.contains("TUF") {
@@ -237,9 +213,9 @@ impl CtrlKbdLed {
let led_node = if let Some(rog) = led_node {
info!("Found ROG USB keyboard");
LEDNode::Rog(rog)
} else if tuf_node {
} else if platform.has_keyboard_rgb_mode() {
info!("Found TUF keyboard");
LEDNode::Tuf
LEDNode::KbdLed(platform)
} else {
LEDNode::None
};
@@ -247,7 +223,7 @@ impl CtrlKbdLed {
let ctrl = CtrlKbdLed {
led_prod,
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,
flip_effect_write: false,
config,
@@ -255,58 +231,16 @@ impl CtrlKbdLed {
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> {
let mut file = OpenOptions::new()
.read(true)
.open(&self.bright_node)
.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])
self.kd_brightness
.get_brightness()
.map_err(|e| RogError::Platform(e))
}
pub(super) fn set_brightness(&self, brightness: LedBrightness) -> Result<(), RogError> {
let path = Path::new(&self.bright_node);
let mut file =
OpenOptions::new()
.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(())
self.kd_brightness
.set_brightness(brightness.as_char_code())
.map_err(|e| RogError::Platform(e))
}
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
pub(super) fn set_power_states(&self, config: &AuraConfig) -> Result<(), RogError> {
if LEDNode::Tuf == self.led_node {
if let Some(path) = Self::get_tuf_state_path() {
let mut file = OpenOptions::new().write(true).open(path)?;
if let Some(pwr) = AuraPowerConfig::to_tuf_bool_array(&config.enabled) {
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())?;
}
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) {
let buf = [1, pwr[1] as u8, pwr[2] as u8, pwr[3] as u8, pwr[4] as u8];
platform.set_keyboard_rgb_state(&buf)?;
}
} else {
let bytes = AuraPowerConfig::to_bytes(&config.enabled);
} else if let LEDNode::Rog(hid_raw) = &self.led_node {
let bytes = AuraPowerConfig::to_bytes(&self.config.enabled);
let message = [0x5d, 0xbd, 0x01, bytes[0], bytes[1], bytes[2]];
self.write_bytes(&message)?;
self.write_bytes(&LED_SET)?;
hid_raw.write_bytes(&message)?;
hid_raw.write_bytes(&LED_SET)?;
// Changes won't persist unless apply is set
self.write_bytes(&LED_APPLY)?;
hid_raw.write_bytes(&LED_APPLY)?;
}
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.
///
/// On success the aura config file is read to refresh cached values, then the effect is
@@ -414,28 +304,17 @@ impl CtrlKbdLed {
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
fn _write_effect(&mut self, effect: &[Vec<u8>]) -> Result<(), RogError> {
if self.flip_effect_write {
for row in effect.iter().rev() {
self.write_bytes(row)?;
}
} else {
for row in effect.iter() {
self.write_bytes(row)?;
if let LEDNode::Rog(hid_raw) = &self.led_node {
if self.flip_effect_write {
for row in effect.iter().rev() {
hid_raw.write_bytes(row)?;
}
} else {
for row in effect.iter() {
hid_raw.write_bytes(row)?;
}
}
}
self.flip_effect_write = !self.flip_effect_write;
@@ -478,19 +357,24 @@ impl CtrlKbdLed {
}
fn write_mode(&self, mode: &AuraEffect) -> Result<(), RogError> {
if LEDNode::Tuf == self.led_node {
let mut file = OpenOptions::new().write(true).open(TUF_RGB_MODE_PATH)?;
let buf = format!(
"1 {} {} {} {} {}",
mode.mode as u8, mode.colour1.0, mode.colour1.1, mode.colour1.2, mode.speed as u8,
);
file.write_all(buf.as_bytes())?;
} else {
if let LEDNode::KbdLed(platform) = &self.led_node {
let buf = [
1,
mode.mode as u8,
mode.colour1.0,
mode.colour1.1,
mode.colour1.2,
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();
self.write_bytes(&bytes)?;
self.write_bytes(&LED_SET)?;
hid_raw.write_bytes(&bytes)?;
hid_raw.write_bytes(&LED_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(())
}
@@ -562,6 +446,7 @@ impl CtrlKbdLed {
#[cfg(test)]
mod tests {
use rog_aura::{AuraEffect, AuraModeNum, AuraZone, Colour};
use rog_platform::keyboard_led::KeyboardLed;
use crate::{
ctrl_aura::{config::AuraConfig, controller::LEDNode},
@@ -585,7 +470,7 @@ mod tests {
let mut controller = CtrlKbdLed {
led_prod: None,
led_node: LEDNode::None,
bright_node: String::new(),
kd_brightness: KeyboardLed::default(),
supported_modes,
flip_effect_write: false,
config,
@@ -601,7 +486,7 @@ mod tests {
.set_effect(effect.clone())
.unwrap_err()
.to_string(),
"No Aura keyboard node found"
"No supported Aura keyboard"
);
effect.mode = AuraModeNum::Laser;
@@ -629,7 +514,7 @@ mod tests {
.set_effect(effect.clone())
.unwrap_err()
.to_string(),
"No Aura keyboard node found"
"No supported Aura keyboard"
);
}
@@ -647,7 +532,7 @@ mod tests {
let mut controller = CtrlKbdLed {
led_prod: None,
led_node: LEDNode::None,
bright_node: String::new(),
kd_brightness: KeyboardLed::default(),
supported_modes,
flip_effect_write: false,
config,
@@ -684,7 +569,7 @@ mod tests {
let mut controller = CtrlKbdLed {
led_prod: None,
led_node: LEDNode::None,
bright_node: String::new(),
kd_brightness: KeyboardLed::default(),
supported_modes,
flip_effect_write: false,
config,
@@ -699,7 +584,7 @@ mod tests {
.write_current_config_mode()
.unwrap_err()
.to_string(),
"No Aura keyboard node found"
"No supported Aura keyboard"
);
assert!(controller.config.multizone.is_some());

View File

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

View File

@@ -1,6 +1,7 @@
use crate::{config::Config, error::RogError, GetSupported};
use async_trait::async_trait;
use log::{error, info, warn};
use rog_platform::platform::AsusPlatform;
use rog_supported::RogBiosSupportedFunctions;
use std::fs::OpenOptions;
use std::io::BufRead;
@@ -15,15 +16,13 @@ use zbus::{dbus_interface, SignalContext};
const INITRAMFS_PATH: &str = "/usr/sbin/update-initramfs";
const DRACUT_PATH: &str = "/usr/bin/dracut";
static ASUS_SWITCH_GRAPHIC_MODE: &str =
"/sys/firmware/efi/efivars/AsusSwitchGraphicMode-607005d5-3f75-4b2e-98f0-85ba66797a3e";
// static ASUS_SWITCH_GRAPHIC_MODE: &str =
// "/sys/firmware/efi/efivars/AsusSwitchGraphicMode-607005d5-3f75-4b2e-98f0-85ba66797a3e";
static ASUS_POST_LOGO_SOUND: &str =
"/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 {
platform: AsusPlatform,
_config: Arc<Mutex<Config>>,
}
@@ -31,12 +30,24 @@ impl GetSupported for CtrlRogBios {
type A = RogBiosSupportedFunctions;
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 {
post_sound: Path::new(ASUS_POST_LOGO_SOUND).exists(),
dedicated_gfx: Path::new(ASUS_SWITCH_GRAPHIC_MODE).exists(),
panel_overdrive: Path::new(ASUS_PANEL_OD_PATH).exists(),
dgpu_disable: Path::new(ASUS_DGPU_DISABLE_PATH).exists(),
egpu_enable: Path::new(ASUS_EGPU_ENABLE_PATH).exists(),
dgpu_only,
panel_overdrive,
dgpu_disable,
egpu_enable,
}
}
}
@@ -59,13 +70,14 @@ impl CtrlRogBios {
.ok();
}
fn dedicated_graphic_mode(&self) -> i8 {
Self::get_gfx_mode()
fn dedicated_graphic_mode(&self) -> bool {
self.platform
.get_gpu_mux_mode()
.map_err(|err| {
warn!("CtrlRogBios: get_gfx_mode {}", err);
err
})
.unwrap_or(-1)
.unwrap_or(false)
}
#[dbus_interface(signal)]
@@ -118,26 +130,14 @@ impl CtrlRogBios {
}
}
fn panel_overdrive(&self) -> i8 {
let path = ASUS_PANEL_OD_PATH;
if let Ok(mut file) = OpenOptions::new().read(true).open(path).map_err(|err| {
warn!("CtrlRogBios: panel_overdrive {}", err);
err
}) {
let mut buf = Vec::new();
file.read_to_end(&mut buf)
.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
fn panel_overdrive(&self) -> bool {
self.platform
.get_panel_od()
.map_err(|err| {
warn!("CtrlRogBios: get panel overdrive {}", err);
err
})
.unwrap_or(false)
}
#[dbus_interface(signal)]
@@ -163,9 +163,8 @@ impl crate::Reloadable for CtrlRogBios {
impl CtrlRogBios {
pub fn new(config: Arc<Mutex<Config>>) -> Result<Self, RogError> {
if Path::new(ASUS_SWITCH_GRAPHIC_MODE).exists() {
CtrlRogBios::set_path_mutable(ASUS_SWITCH_GRAPHIC_MODE)?;
} else {
let platform = AsusPlatform::new()?;
if !platform.has_gpu_mux_mode() {
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.");
}
@@ -176,7 +175,10 @@ impl CtrlRogBios {
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> {
@@ -189,48 +191,14 @@ impl CtrlRogBios {
Ok(())
}
pub fn has_dedicated_gfx_toggle() -> bool {
Path::new(ASUS_SWITCH_GRAPHIC_MODE).exists()
}
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;
pub(super) fn set_gfx_mode(&self, enable: bool) -> Result<(), RogError> {
self.platform.set_gpu_mux_mode(enable)?;
self.update_initramfs(enable)?;
if enable {
info!("Set system-level graphics mode: Dedicated Nvidia");
} else {
data[idx] = 0;
info!("Set system-level graphics mode: Optimus");
}
file.write_all(&data)
.map_err(|err| RogError::Path(path.into(), err))?;
self.update_initramfs(dedicated)?;
Ok(())
}
@@ -358,42 +326,11 @@ impl CtrlRogBios {
Ok(())
}
fn set_panel_od(&mut self, overdrive: bool) -> Result<(), RogError> {
let path = ASUS_PANEL_OD_PATH;
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| {
fn set_panel_od(&mut self, enable: bool) -> Result<(), RogError> {
self.platform.set_panel_od(enable).map_err(|err| {
warn!("CtrlRogBios: set_panel_overdrive {}", err);
err
})?;
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_platform::error::PlatformError;
use rog_profiles::error::ProfileError;
use std::convert::From;
use std::fmt;
@@ -28,6 +29,7 @@ pub enum RogError {
NoAuraKeyboard,
NoAuraNode,
Anime(AnimeError),
Platform(PlatformError),
}
impl fmt::Display for RogError {
@@ -57,6 +59,7 @@ impl fmt::Display for RogError {
RogError::NoAuraKeyboard => write!(f, "No supported Aura keyboard"),
RogError::NoAuraNode => write!(f, "No Aura keyboard node found"),
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 {
fn from(err: zbus::Error) -> Self {
RogError::Zbus(err)

View File

@@ -15,7 +15,7 @@ exclude = ["data"]
[features]
default = ["dbus", "detect"]
dbus = ["zvariant", "zbus"]
detect = ["udev", "sysfs-class"]
detect = ["sysfs-class"]
[dependencies]
png_pong = "^0.8.0"
@@ -31,5 +31,4 @@ glam = { version = "^0.21.2", features = ["serde"] }
zvariant = { version = "^3.0", optional = true }
zbus = { version = "^2.2", optional = true }
udev = { version = "^0.6", 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)
}
/// 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
/// after the laptop boots.
#[inline]

View File

@@ -9,7 +9,7 @@ use crate::{error::Error, keys::Key};
use serde::{Deserialize, Serialize};
use std::{fs::OpenOptions, io::Read, path::Path, slice::Iter};
#[derive(Debug, Deserialize, Serialize)]
#[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
@@ -48,7 +48,7 @@ impl KeyLayout {
}
}
#[derive(Debug, Deserialize, Serialize)]
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct KeyRow {
height: f32,
row: Vec<Key>,

View File

@@ -1,6 +1,5 @@
use std::{
f64::consts::PI,
io::Write,
sync::{
atomic::{AtomicBool, AtomicU8, Ordering},
Arc,
@@ -12,18 +11,13 @@ use egui::{Button, RichText};
use rog_supported::SupportedFunctions;
use crate::{
config::Config, error::Result, get_ipc_file, page_states::PageDataStates, Page,
RogDbusClientBlocking, SHOWING_GUI,
config::Config, error::Result, page_states::PageDataStates, Page, RogDbusClientBlocking,
};
pub struct RogApp<'a> {
pub page: Page,
pub states: PageDataStates,
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
pub config: Config,
pub asus_dbus: RogDbusClientBlocking<'a>,
@@ -40,9 +34,7 @@ pub struct RogApp<'a> {
impl<'a> RogApp<'a> {
/// Called once before the first frame.
pub fn new(
start_closed: bool,
config: Config,
show_gui: Arc<AtomicBool>,
states: PageDataStates,
_cc: &eframe::CreationContext<'_>,
) -> Result<Self> {
@@ -99,8 +91,6 @@ impl<'a> RogApp<'a> {
supported,
states,
page: Page::System,
begin_show_gui: show_gui,
running_in_bg: start_closed,
config,
asus_dbus: dbus,
oscillator1,
@@ -113,20 +103,10 @@ impl<'a> 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.
/// Put your widgets into a `SidePanel`, `TopPanel`, `CentralPanel`, `Window` or `Area`.
fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
let Self {
begin_show_gui: should_show_gui,
supported,
asus_dbus: dbus,
states,
@@ -144,21 +124,6 @@ impl<'a> eframe::App for RogApp<'a> {
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.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 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()
.read(true)
.write(true)

View File

@@ -2,19 +2,14 @@ use rog_aura::layouts::KeyLayout;
use rog_control_center::{
config::Config, get_ipc_file, notify::start_notifications, on_tmp_dir_exists,
page_states::PageDataStates, startup_error::AppErrorShow, RogApp, RogDbusClientBlocking,
SHOW_GUI,
SHOWING_GUI, SHOW_GUI,
};
use std::{
fs::{self, OpenOptions},
io::Read,
io::{Read, Write},
path::PathBuf,
sync::{
atomic::{AtomicBool, Ordering},
Arc,
},
thread::spawn,
time::Duration,
sync::{atomic::AtomicBool, Arc},
};
#[cfg(not(feature = "mocking"))]
@@ -29,6 +24,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
transparent: false,
min_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()
};
@@ -44,7 +40,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
// Startup
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 {
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 notifs_enabled = Arc::new(AtomicBool::new(config.enable_notifications));
let states = {
let supported = dbus
.proxies()
.supported()
.supported_functions()
.map_err(|e| {
eframe::run_native(
"ROG Control Center",
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,
)?;
}
start_notifications(
charge_notified.clone(),
bios_notified.clone(),
aura_notified.clone(),
anime_notified.clone(),
profiles_notified.clone(),
fans_notified.clone(),
notifs_enabled.clone(),
)?;
// tmp-dir must live to the end of program life
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(),
};
let should_show_gui = Arc::new(AtomicBool::new(!start_closed));
let should = should_show_gui.clone();
spawn(move || {
// Loop is blocked here until a single byte is read
loop {
let mut buf = [0u8; 4];
if get_ipc_file().unwrap().read(&mut buf).is_ok() && buf[0] == SHOW_GUI {
should_show_gui.store(true, Ordering::SeqCst);
// Give the starting app a change to read or we'll race it
std::thread::sleep(Duration::from_millis(10));
}
}
});
loop {
let states = {
let supported = match dbus.proxies().supported().supported_functions() {
Ok(s) => s,
Err(e) => {
eframe::run_native(
"ROG Control Center",
native_options.clone(),
Box::new(move |_| Box::new(AppErrorShow::new(e.to_string()))),
);
return Ok(());
}
};
eframe::run_native(
"ROG Control Center",
native_options,
Box::new(move |cc| {
Box::new(RogApp::new(start_closed, config, should, states, cc).unwrap())
}),
);
PageDataStates::new(
layout.clone(),
notifs_enabled.clone(),
charge_notified.clone(),
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 {
false
},
dedicated_gfx: if supported.rog_bios_ctrl.dedicated_gfx {
dbus.proxies().rog_bios().dedicated_graphic_mode()? != 0
dedicated_gfx: if supported.rog_bios_ctrl.dgpu_only {
dbus.proxies().rog_bios().dedicated_graphic_mode()?
} else {
false
},
panel_overdrive: if supported.rog_bios_ctrl.panel_overdrive {
dbus.proxies().rog_bios().panel_overdrive()? != 0
dbus.proxies().rog_bios().panel_overdrive()?
} else {
false
},

View File

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

View File

@@ -16,20 +16,21 @@ pub fn fan_graphs(
ui.separator();
let mut item = |p: Profile, ui: &mut Ui| {
ui.group(|ui|{
ui.selectable_value(&mut curves.show_curve, p, format!("{p:?}"));
ui.add_enabled_ui(curves.show_curve == p ,|ui| {
ui.selectable_value(
&mut curves.show_graph,
FanCurvePU::CPU,
format!("{:?}", FanCurvePU::CPU),
);
ui.selectable_value(
&mut curves.show_graph,
FanCurvePU::GPU,
format!("{:?}", FanCurvePU::GPU),
);
});});
ui.group(|ui| {
ui.selectable_value(&mut curves.show_curve, p, format!("{p:?}"));
ui.add_enabled_ui(curves.show_curve == p, |ui| {
ui.selectable_value(
&mut curves.show_graph,
FanCurvePU::CPU,
format!("{:?}", FanCurvePU::CPU),
);
ui.selectable_value(
&mut curves.show_graph,
FanCurvePU::GPU,
format!("{:?}", FanCurvePU::GPU),
);
});
});
};
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
.add(egui::Checkbox::new(
&mut states.bios.dedicated_gfx,

View File

@@ -27,7 +27,7 @@ use zbus_macros::dbus_proxy;
)]
trait RogBios {
/// DedicatedGraphicMode method
fn dedicated_graphic_mode(&self) -> zbus::Result<i16>;
fn dedicated_graphic_mode(&self) -> zbus::Result<bool>;
/// PostBootSound method
fn post_boot_sound(&self) -> zbus::Result<i16>;
@@ -39,7 +39,7 @@ trait RogBios {
fn set_post_boot_sound(&self, on: bool) -> zbus::Result<()>;
/// PanelOverdrive method
fn panel_overdrive(&self) -> zbus::Result<i8>;
fn panel_overdrive(&self) -> zbus::Result<bool>;
/// SetPanelOverdrive method
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)]
pub struct RogBiosSupportedFunctions {
pub post_sound: bool,
pub dedicated_gfx: bool,
pub dgpu_only: bool,
pub panel_overdrive: bool,
pub dgpu_disable: bool,
pub egpu_enable: bool,
@@ -95,7 +95,7 @@ impl fmt::Display for RogBiosSupportedFunctions {
writeln!(f, "\tPanel Overdrive: {}", self.panel_overdrive)?;
writeln!(f, "\tdGPU disable switch: {}", self.dgpu_disable)?;
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(())
}
}