mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
Compare commits
40 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a811f20f65 | |||
| 0c9c263be6 | |||
| 6571c04bfe | |||
| e48acbb8a2 | |||
| f33496ef68 | |||
| cd3176b565 | |||
| 7595613d7e | |||
| b8d0245e7a | |||
| 54bd2ec800 | |||
| b6c8566565 | |||
| 052c096014 | |||
| 81cbe3c522 | |||
| 09f7492bec | |||
| 6adfb2cf48 | |||
| a2a56792a8 | |||
| 317daf4ed1 | |||
| eb0d9514b5 | |||
| d324b1bce5 | |||
| d1c7385146 | |||
| 48a4935fc7 | |||
| 7e917b91a5 | |||
| 45f8b8ffb0 | |||
| 031a36242b | |||
| 8ad26ad136 | |||
| 907d4694f3 | |||
| 1dcc4ff502 | |||
| cf232047b0 | |||
| ff99ec9a39 | |||
| 8a19374a41 | |||
| 4cec1f49b4 | |||
| 01aae200f3 | |||
| 4c6db9f0a9 | |||
| 7207d3287a | |||
| 1b2d8d83fc | |||
| 6d8db91583 | |||
| 20c3628476 | |||
| 4edecfce1c | |||
| 34699a7021 | |||
| ef311689ec | |||
| 8ee0281b4f |
+31
-16
@@ -1,22 +1,26 @@
|
|||||||
image: rust:latest
|
image: rust:latest
|
||||||
|
|
||||||
|
# Use shallow clone to reduce checkout size
|
||||||
|
variables:
|
||||||
|
GIT_DEPTH: "1"
|
||||||
|
# Put cargo home and target under project dir so we can clean them easily
|
||||||
|
CARGO_HOME: "$CI_PROJECT_DIR/.cargo"
|
||||||
|
CARGO_TARGET_DIR: "$CI_PROJECT_DIR/ci-target"
|
||||||
|
GIT_SUBMODULE_STRATEGY: normal
|
||||||
|
|
||||||
|
# Cache only cargo registries/git metadata to speed dependency fetches.
|
||||||
|
# Avoid caching compiled `target` artifacts which are large and easily fill disk.
|
||||||
.rust_cache: &rust_cache
|
.rust_cache: &rust_cache
|
||||||
cache:
|
cache:
|
||||||
# key: $CI_COMMIT_REF_SLUG
|
key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
|
||||||
paths:
|
paths:
|
||||||
# Don't include `incremental` to save space
|
- .cargo/registry
|
||||||
# Debug
|
- .cargo/git
|
||||||
- target/debug/build/
|
|
||||||
- target/debug/deps/
|
|
||||||
- target/debug/.fingerprint/
|
|
||||||
- target/debug/.cargo-lock
|
|
||||||
# Release
|
|
||||||
- target/release/build/
|
|
||||||
- target/release/deps/
|
|
||||||
- target/release/.fingerprint/
|
|
||||||
- target/release/.cargo-lock
|
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
|
- df -h
|
||||||
|
- echo "Cleaning stale targets to free space if present"
|
||||||
|
- rm -rf "$CI_PROJECT_DIR/target" "$CI_PROJECT_DIR/ci-target" || true
|
||||||
- apt-get update -qq && apt-get install -y -qq libudev-dev libgtk-3-dev grep llvm clang libclang-dev libsdl2-dev libsdl2-gfx-dev
|
- apt-get update -qq && apt-get install -y -qq libudev-dev libgtk-3-dev grep llvm clang libclang-dev libsdl2-dev libsdl2-gfx-dev
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
@@ -33,6 +37,9 @@ format:
|
|||||||
script:
|
script:
|
||||||
- rustup component add rustfmt || true
|
- rustup component add rustfmt || true
|
||||||
- cargo fmt --check
|
- cargo fmt --check
|
||||||
|
after_script:
|
||||||
|
- du -sh "$CI_PROJECT_DIR/ci-target" || true
|
||||||
|
- rm -rf "$CI_PROJECT_DIR/ci-target" || true
|
||||||
|
|
||||||
check:
|
check:
|
||||||
except:
|
except:
|
||||||
@@ -44,6 +51,8 @@ check:
|
|||||||
# deny currently catches too much
|
# deny currently catches too much
|
||||||
#- cargo install cargo-deny && cargo deny
|
#- cargo install cargo-deny && cargo deny
|
||||||
- cargo install cargo-cranky && cargo cranky
|
- cargo install cargo-cranky && cargo cranky
|
||||||
|
after_script:
|
||||||
|
- rm -rf "$CI_PROJECT_DIR/ci-target" || true
|
||||||
|
|
||||||
test:
|
test:
|
||||||
except:
|
except:
|
||||||
@@ -52,6 +61,8 @@ test:
|
|||||||
script:
|
script:
|
||||||
- mkdir -p .git/hooks > /dev/null
|
- mkdir -p .git/hooks > /dev/null
|
||||||
- cargo test --locked --all
|
- cargo test --locked --all
|
||||||
|
after_script:
|
||||||
|
- rm -rf "$CI_PROJECT_DIR/ci-target" || true
|
||||||
|
|
||||||
release:
|
release:
|
||||||
only:
|
only:
|
||||||
@@ -59,11 +70,15 @@ release:
|
|||||||
<<: *rust_cache
|
<<: *rust_cache
|
||||||
script:
|
script:
|
||||||
- cargo install cargo-vendor-filterer
|
- cargo install cargo-vendor-filterer
|
||||||
|
- cargo fetch
|
||||||
- make FROZEN=1 && make vendor
|
- make FROZEN=1 && make vendor
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
- vendor_asusctl*.tar.xz
|
- vendor_asusctl*.tar.xz
|
||||||
- cargo-config
|
- cargo-config
|
||||||
|
expire_in: 1 week
|
||||||
|
after_script:
|
||||||
|
- rm -rf vendor vendor_asusctl*.tar.xz "$CI_PROJECT_DIR/ci-target" || true
|
||||||
|
|
||||||
pages:
|
pages:
|
||||||
stage: deploy
|
stage: deploy
|
||||||
@@ -74,11 +89,11 @@ pages:
|
|||||||
- cargo doc --locked --document-private-items --no-deps --workspace
|
- cargo doc --locked --document-private-items --no-deps --workspace
|
||||||
- rm -rf public
|
- rm -rf public
|
||||||
- mkdir public
|
- mkdir public
|
||||||
- cp -R target/doc/* public
|
- cp -R ci-target/doc/* public
|
||||||
- cp extra/index.html public
|
- cp extra/index.html public
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
- public
|
- public
|
||||||
|
expire_in: 1 week
|
||||||
variables:
|
after_script:
|
||||||
GIT_SUBMODULE_STRATEGY: normal
|
- rm -rf "$CI_PROJECT_DIR/ci-target" || true
|
||||||
|
|||||||
@@ -2,6 +2,32 @@
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [6.1.22]
|
||||||
|
- Allow configuration of nv_tgp
|
||||||
|
- Treat dGPU attributes as power profiles
|
||||||
|
- Add EXPERTBOOK DMI match to ensure the service is loaded
|
||||||
|
- Support G815L thanks to @solost !
|
||||||
|
|
||||||
|
## [6.1.21]
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Kill Fedora: screw your cursed cargo bullshit
|
||||||
|
- Restore CI building
|
||||||
|
|
||||||
|
## [6.1.20]
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Addded support for G635L: thanks @luca_pisl !
|
||||||
|
- Suppress verbose output in applications too, not just daemon
|
||||||
|
|
||||||
|
## [6.1.18]
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Add aura support for G614FR (ROG Strix G16 2025)
|
||||||
|
- all notifications now respects the timeout
|
||||||
|
- improve udev daemon-starting rule
|
||||||
|
- reduce log noise
|
||||||
|
|
||||||
## [v6.1.17]
|
## [v6.1.17]
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|||||||
Generated
+438
-311
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "6.1.17"
|
version = "6.1.22"
|
||||||
rust-version = "1.82"
|
rust-version = "1.82"
|
||||||
license = "MPL-2.0"
|
license = "MPL-2.0"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|||||||
@@ -59,10 +59,17 @@ clean:
|
|||||||
distclean:
|
distclean:
|
||||||
rm -rf .cargo vendor vendor.tar.xz
|
rm -rf .cargo vendor vendor.tar.xz
|
||||||
|
|
||||||
target/$(TARGET)/$(BIN_D): build
|
target/$(TARGET)/$(BIN_D): $(SRC)
|
||||||
target/$(TARGET)/$(BIN_C): build
|
$(MAKE) build
|
||||||
target/$(TARGET)/$(BIN_U): build
|
|
||||||
target/$(TARGET)/$(BIN_ROG): build
|
target/$(TARGET)/$(BIN_C): $(SRC)
|
||||||
|
$(MAKE) build
|
||||||
|
|
||||||
|
target/$(TARGET)/$(BIN_U): $(SRC)
|
||||||
|
$(MAKE) build
|
||||||
|
|
||||||
|
target/$(TARGET)/$(BIN_ROG): $(SRC)
|
||||||
|
$(MAKE) build
|
||||||
|
|
||||||
install-asusd: target/$(TARGET)/$(BIN_D)
|
install-asusd: target/$(TARGET)/$(BIN_D)
|
||||||
$(INSTALL_PROGRAM) "./target/$(TARGET)/$(BIN_D)" "$(DESTDIR)$(bindir)/$(BIN_D)"
|
$(INSTALL_PROGRAM) "./target/$(TARGET)/$(BIN_D)" "$(DESTDIR)$(bindir)/$(BIN_D)"
|
||||||
@@ -151,6 +158,8 @@ vendor:
|
|||||||
mv .cargo/config ./cargo-config
|
mv .cargo/config ./cargo-config
|
||||||
rm -rf .cargo
|
rm -rf .cargo
|
||||||
rm -rf vendor
|
rm -rf vendor
|
||||||
|
# Ensure cargo-vendor-filterer is installed (CI installs it already)
|
||||||
|
command -v cargo-vendor-filterer >/dev/null 2>&1 || cargo install --locked cargo-vendor-filterer
|
||||||
cargo vendor-filterer --all-features --platform x86_64-unknown-linux-gnu vendor
|
cargo vendor-filterer --all-features --platform x86_64-unknown-linux-gnu vendor
|
||||||
tar pcfJ vendor_asusctl_$(VERSION).tar.xz vendor
|
tar pcfJ vendor_asusctl_$(VERSION).tar.xz vendor
|
||||||
rm -rf vendor
|
rm -rf vendor
|
||||||
|
|||||||
@@ -181,6 +181,7 @@ pub struct TwoColourSpeed {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Options)]
|
#[derive(Debug, Clone, Default, Options)]
|
||||||
|
#[allow(dead_code)]
|
||||||
pub struct MultiZone {
|
pub struct MultiZone {
|
||||||
#[options(help = "print help message")]
|
#[options(help = "print help message")]
|
||||||
help: bool,
|
help: bool,
|
||||||
@@ -195,6 +196,7 @@ pub struct MultiZone {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Options)]
|
#[derive(Debug, Clone, Default, Options)]
|
||||||
|
#[allow(dead_code)]
|
||||||
pub struct MultiColourSpeed {
|
pub struct MultiColourSpeed {
|
||||||
#[options(help = "print help message")]
|
#[options(help = "print help message")]
|
||||||
help: bool,
|
help: bool,
|
||||||
|
|||||||
+10
-5
@@ -9,7 +9,7 @@ use aura_cli::{LedPowerCommand1, LedPowerCommand2};
|
|||||||
use dmi_id::DMIID;
|
use dmi_id::DMIID;
|
||||||
use fan_curve_cli::FanCurveCommand;
|
use fan_curve_cli::FanCurveCommand;
|
||||||
use gumdrop::{Opt, Options};
|
use gumdrop::{Opt, Options};
|
||||||
use log::{error, info};
|
use log::{error, info, LevelFilter};
|
||||||
use rog_anime::usb::get_anime_type;
|
use rog_anime::usb::get_anime_type;
|
||||||
use rog_anime::{AnimTime, AnimeDataBuffer, AnimeDiagonal, AnimeGif, AnimeImage, AnimeType, Vec2};
|
use rog_anime::{AnimTime, AnimeDataBuffer, AnimeDiagonal, AnimeGif, AnimeImage, AnimeType, Vec2};
|
||||||
use rog_aura::keyboard::{AuraPowerState, LaptopAuraPower};
|
use rog_aura::keyboard::{AuraPowerState, LaptopAuraPower};
|
||||||
@@ -44,12 +44,16 @@ mod scsi_cli;
|
|||||||
mod slash_cli;
|
mod slash_cli;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
// Ensure tracing spans are quiet by default unless user overrides
|
||||||
|
if std::env::var_os("RUST_LOG").is_none() {
|
||||||
|
std::env::set_var("RUST_LOG", "warn,tracing=error,zbus=error");
|
||||||
|
}
|
||||||
let mut logger = env_logger::Builder::new();
|
let mut logger = env_logger::Builder::new();
|
||||||
logger
|
logger
|
||||||
.parse_default_env()
|
.parse_default_env()
|
||||||
.target(env_logger::Target::Stdout)
|
.filter_level(LevelFilter::Info)
|
||||||
|
.target(env_logger::Target::Stderr)
|
||||||
.format_timestamp(None)
|
.format_timestamp(None)
|
||||||
.filter_level(log::LevelFilter::Debug)
|
|
||||||
.init();
|
.init();
|
||||||
|
|
||||||
let self_version = env!("CARGO_PKG_VERSION");
|
let self_version = env!("CARGO_PKG_VERSION");
|
||||||
@@ -1184,11 +1188,12 @@ fn print_firmware_attr(attr: &AsusArmouryProxyBlocking) -> Result<(), Box<dyn st
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::manual_is_multiple_of, clippy::nonminimal_bool)]
|
||||||
fn handle_armoury_command(cmd: &ArmouryCommand) -> Result<(), Box<dyn std::error::Error>> {
|
fn handle_armoury_command(cmd: &ArmouryCommand) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
{
|
{
|
||||||
if cmd.free.is_empty() || !cmd.free.len().is_multiple_of(2) || cmd.help {
|
if cmd.free.is_empty() || (cmd.free.len() % 2 != 0) || cmd.help {
|
||||||
const USAGE: &str = "Usage: asusctl platform panel_overdrive 1 nv_dynamic_boost 5";
|
const USAGE: &str = "Usage: asusctl platform panel_overdrive 1 nv_dynamic_boost 5";
|
||||||
if !(cmd.free.len() % 2 == 0) {
|
if cmd.free.len() % 2 != 0 {
|
||||||
println!(
|
println!(
|
||||||
"Incorrect number of args, each attribute label must be paired with a setting:"
|
"Incorrect number of args, each attribute label must be paired with a setting:"
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -170,7 +170,9 @@ impl crate::Reloadable for AsusArmouryAttribute {
|
|||||||
info!("Reloading {}", self.attr.name());
|
info!("Reloading {}", self.attr.name());
|
||||||
let name: FirmwareAttribute = self.attr.name().into();
|
let name: FirmwareAttribute = self.attr.name().into();
|
||||||
|
|
||||||
if name.is_ppt() {
|
// Treat dGPU attributes the same as PPT attributes for power-profile
|
||||||
|
// behaviour so they follow AC/DC tuning groups.
|
||||||
|
if name.is_ppt() || name.is_dgpu() {
|
||||||
let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
|
let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
|
||||||
let power_plugged = self
|
let power_plugged = self
|
||||||
.power
|
.power
|
||||||
@@ -277,7 +279,7 @@ impl AsusArmouryAttribute {
|
|||||||
|
|
||||||
async fn restore_default(&self) -> fdo::Result<()> {
|
async fn restore_default(&self) -> fdo::Result<()> {
|
||||||
self.attr.restore_default()?;
|
self.attr.restore_default()?;
|
||||||
if self.name().is_ppt() {
|
if self.name().is_ppt() || self.name().is_dgpu() {
|
||||||
let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
|
let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
|
||||||
let power_plugged = self
|
let power_plugged = self
|
||||||
.power
|
.power
|
||||||
@@ -336,7 +338,7 @@ impl AsusArmouryAttribute {
|
|||||||
|
|
||||||
#[zbus(property)]
|
#[zbus(property)]
|
||||||
async fn current_value(&self) -> fdo::Result<i32> {
|
async fn current_value(&self) -> fdo::Result<i32> {
|
||||||
if self.name().is_ppt() {
|
if self.name().is_ppt() || self.name().is_dgpu() {
|
||||||
let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
|
let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
|
||||||
let power_plugged = self
|
let power_plugged = self
|
||||||
.power
|
.power
|
||||||
@@ -369,86 +371,9 @@ impl AsusArmouryAttribute {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn stored_value_for_power(&self, on_ac: bool) -> fdo::Result<i32> {
|
|
||||||
if !self.name().is_ppt() {
|
|
||||||
return Err(fdo::Error::NotSupported(
|
|
||||||
"Stored values are only available for PPT attributes".to_string(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
|
|
||||||
let config = self.config.lock().await;
|
|
||||||
if let Some(tuning) = config.select_tunings_ref(on_ac, profile) {
|
|
||||||
if let Some(tune) = tuning.group.get(&self.name()) {
|
|
||||||
return Ok(*tune);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let AttrValue::Integer(i) = self.attr.default_value() {
|
|
||||||
return Ok(*i);
|
|
||||||
}
|
|
||||||
Err(fdo::Error::Failed(
|
|
||||||
"Could not read stored value".to_string(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn set_value_for_power(&mut self, on_ac: bool, value: i32) -> fdo::Result<()> {
|
|
||||||
if !self.name().is_ppt() {
|
|
||||||
return Err(fdo::Error::NotSupported(
|
|
||||||
"Setting stored values is only supported for PPT attributes".to_string(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
|
|
||||||
let apply_now;
|
|
||||||
|
|
||||||
{
|
|
||||||
let mut config = self.config.lock().await;
|
|
||||||
let tuning = config.select_tunings(on_ac, profile);
|
|
||||||
|
|
||||||
if let Some(tune) = tuning.group.get_mut(&self.name()) {
|
|
||||||
*tune = value;
|
|
||||||
} else {
|
|
||||||
tuning.group.insert(self.name(), value);
|
|
||||||
debug!(
|
|
||||||
"Store {} value for {} power = {}",
|
|
||||||
self.attr.name(),
|
|
||||||
if on_ac { "AC" } else { "DC" },
|
|
||||||
value
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
apply_now = tuning.enabled;
|
|
||||||
config.write();
|
|
||||||
}
|
|
||||||
|
|
||||||
if apply_now {
|
|
||||||
let power_plugged = self
|
|
||||||
.power
|
|
||||||
.get_online()
|
|
||||||
.map_err(|e| {
|
|
||||||
error!("Could not get power status: {e:?}");
|
|
||||||
e
|
|
||||||
})
|
|
||||||
.unwrap_or_default()
|
|
||||||
!= 0;
|
|
||||||
|
|
||||||
if power_plugged == on_ac {
|
|
||||||
self.attr
|
|
||||||
.set_current_value(&AttrValue::Integer(value))
|
|
||||||
.map_err(|e| {
|
|
||||||
error!("Could not set value: {e:?}");
|
|
||||||
e
|
|
||||||
})?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[zbus(property)]
|
#[zbus(property)]
|
||||||
async fn set_current_value(&mut self, value: i32) -> fdo::Result<()> {
|
async fn set_current_value(&mut self, value: i32) -> fdo::Result<()> {
|
||||||
if self.name().is_ppt() {
|
if self.name().is_ppt() || self.name().is_dgpu() {
|
||||||
let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
|
let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
|
||||||
let power_plugged = self
|
let power_plugged = self
|
||||||
.power
|
.power
|
||||||
@@ -538,8 +463,7 @@ pub async fn start_attributes_zbus(
|
|||||||
"Skipping attribute '{}' due to reload error: {e:?}",
|
"Skipping attribute '{}' due to reload error: {e:?}",
|
||||||
attr.attr.name()
|
attr.attr.name()
|
||||||
);
|
);
|
||||||
// continue with others
|
break;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let attr_name = attr.attribute_name();
|
let attr_name = attr.attribute_name();
|
||||||
@@ -577,7 +501,7 @@ pub async fn set_config_or_default(
|
|||||||
) {
|
) {
|
||||||
for attr in attrs.attributes().iter() {
|
for attr in attrs.attributes().iter() {
|
||||||
let name: FirmwareAttribute = attr.name().into();
|
let name: FirmwareAttribute = attr.name().into();
|
||||||
if name.is_ppt() {
|
if name.is_ppt() || name.is_dgpu() {
|
||||||
let tuning = config.select_tunings(power_plugged, profile);
|
let tuning = config.select_tunings(power_plugged, profile);
|
||||||
if !tuning.enabled {
|
if !tuning.enabled {
|
||||||
debug!("Tuning group is not enabled, skipping");
|
debug!("Tuning group is not enabled, skipping");
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ pub struct DeviceManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DeviceManager {
|
impl DeviceManager {
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
async fn get_or_create_hid_handle(
|
async fn get_or_create_hid_handle(
|
||||||
handles: &Arc<Mutex<HashMap<String, Arc<Mutex<HidRaw>>>>>,
|
handles: &Arc<Mutex<HashMap<String, Arc<Mutex<HidRaw>>>>>,
|
||||||
endpoint: &Device,
|
endpoint: &Device,
|
||||||
@@ -131,7 +132,7 @@ impl DeviceManager {
|
|||||||
if let Some(usb_id) = usb_device.attribute_value("idProduct") {
|
if let Some(usb_id) = usb_device.attribute_value("idProduct") {
|
||||||
if let Some(vendor_id) = usb_device.attribute_value("idVendor") {
|
if let Some(vendor_id) = usb_device.attribute_value("idVendor") {
|
||||||
if vendor_id != "0b05" {
|
if vendor_id != "0b05" {
|
||||||
debug!("Not ASUS vendor ID");
|
debug!("Not ASUS vendor ID: {}", vendor_id.to_string_lossy());
|
||||||
return Ok(devices);
|
return Ok(devices);
|
||||||
}
|
}
|
||||||
// Almost all devices are identified by the productId.
|
// Almost all devices are identified by the productId.
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ pub struct CtrlPlatform {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CtrlPlatform {
|
impl CtrlPlatform {
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
platform: RogPlatform,
|
platform: RogPlatform,
|
||||||
power: AsusPower,
|
power: AsusPower,
|
||||||
@@ -294,16 +295,39 @@ impl CtrlPlatform {
|
|||||||
|
|
||||||
#[zbus(property)]
|
#[zbus(property)]
|
||||||
fn charge_control_end_threshold(&self) -> Result<u8, FdoErr> {
|
fn charge_control_end_threshold(&self) -> Result<u8, FdoErr> {
|
||||||
let limit = self.power.get_charge_control_end_threshold()?;
|
if !self.power.has_charge_control_end_threshold() {
|
||||||
|
return Err(FdoErr::NotSupported(
|
||||||
|
"RogPlatform: charge_control_end_threshold not supported".to_owned(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let limit = self.power.get_charge_control_end_threshold().map_err(|e| {
|
||||||
|
FdoErr::Failed(format!(
|
||||||
|
"Could not read charge_control_end_threshold: {e:?}"
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
|
||||||
Ok(limit)
|
Ok(limit)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[zbus(property)]
|
#[zbus(property)]
|
||||||
async fn set_charge_control_end_threshold(&mut self, limit: u8) -> Result<(), FdoErr> {
|
async fn set_charge_control_end_threshold(&mut self, limit: u8) -> Result<(), FdoErr> {
|
||||||
|
if !self.power.has_charge_control_end_threshold() {
|
||||||
|
return Err(FdoErr::NotSupported(
|
||||||
|
"RogPlatform: charge_control_end_threshold not supported".to_owned(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
if !(20..=100).contains(&limit) {
|
if !(20..=100).contains(&limit) {
|
||||||
return Err(RogError::ChargeLimit(limit))?;
|
return Err(RogError::ChargeLimit(limit))?;
|
||||||
}
|
}
|
||||||
self.power.set_charge_control_end_threshold(limit)?;
|
|
||||||
|
self.power
|
||||||
|
.set_charge_control_end_threshold(limit)
|
||||||
|
.map_err(|e| {
|
||||||
|
FdoErr::Failed(format!("Could not set charge_control_end_threshold: {e:?}"))
|
||||||
|
})?;
|
||||||
|
|
||||||
self.config.lock().await.charge_control_end_threshold = limit;
|
self.config.lock().await.charge_control_end_threshold = limit;
|
||||||
self.config.lock().await.base_charge_control_end_threshold = limit;
|
self.config.lock().await.base_charge_control_end_threshold = limit;
|
||||||
self.config.lock().await.write();
|
self.config.lock().await.write();
|
||||||
@@ -311,12 +335,22 @@ impl CtrlPlatform {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn one_shot_full_charge(&self) -> Result<(), FdoErr> {
|
async fn one_shot_full_charge(&self) -> Result<(), FdoErr> {
|
||||||
|
if !self.power.has_charge_control_end_threshold() {
|
||||||
|
return Err(FdoErr::NotSupported(
|
||||||
|
"RogPlatform: charge_control_end_threshold not supported".to_owned(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
let base_limit = std::mem::replace(
|
let base_limit = std::mem::replace(
|
||||||
&mut self.config.lock().await.charge_control_end_threshold,
|
&mut self.config.lock().await.charge_control_end_threshold,
|
||||||
100,
|
100,
|
||||||
);
|
);
|
||||||
if base_limit != 100 {
|
if base_limit != 100 {
|
||||||
self.power.set_charge_control_end_threshold(100)?;
|
self.power
|
||||||
|
.set_charge_control_end_threshold(100)
|
||||||
|
.map_err(|e| {
|
||||||
|
FdoErr::Failed(format!("Could not set one_shot_full_charge: {e:?}"))
|
||||||
|
})?;
|
||||||
self.config.lock().await.base_charge_control_end_threshold = base_limit;
|
self.config.lock().await.base_charge_control_end_threshold = base_limit;
|
||||||
self.config.lock().await.write();
|
self.config.lock().await.write();
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -11,11 +11,12 @@ ENV{DMI_FAMILY}=="*Zenbook*", GOTO="asusd_start"
|
|||||||
ENV{DMI_FAMILY}=="*ProArt*", GOTO="asusd_start"
|
ENV{DMI_FAMILY}=="*ProArt*", GOTO="asusd_start"
|
||||||
ENV{DMI_FAMILY}=="*TX Air*", GOTO="asusd_start"
|
ENV{DMI_FAMILY}=="*TX Air*", GOTO="asusd_start"
|
||||||
ENV{DMI_FAMILY}=="*TX Gaming*", GOTO="asusd_start"
|
ENV{DMI_FAMILY}=="*TX Gaming*", GOTO="asusd_start"
|
||||||
|
ENV{DMI_FAMILY}=="*EXPERTBOOK*", GOTO="asusd_start"
|
||||||
# No match so
|
# No match so
|
||||||
GOTO="asusd_end"
|
GOTO="asusd_end"
|
||||||
|
|
||||||
LABEL="asusd_start"
|
LABEL="asusd_start"
|
||||||
ACTION=="add|change", DRIVER=="asus-nb-wmi", TAG+="systemd", ENV{SYSTEMD_WANTS}="asusd.service"
|
ACTION=="add|change", DRIVER=="asus-nb-wmi", TAG+="systemd", ENV{SYSTEMD_WANTS}+="asusd.service"
|
||||||
ACTION=="add|remove", DRIVER=="asus-nb-wmi", TAG+="systemd", RUN+="/usr/bin/systemctl restart asusd.service"
|
ACTION=="add|remove", DRIVER=="asus-nb-wmi", TAG+="systemd", ENV{SYSTEMD_WANTS}+="asusd.service"
|
||||||
|
|
||||||
LABEL="asusd_end"
|
LABEL="asusd_end"
|
||||||
|
|||||||
+4
-1
@@ -6,7 +6,10 @@ After=nvidia-powerd.service systemd-udevd.service
|
|||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Environment=IS_SERVICE=1
|
Environment=IS_SERVICE=1
|
||||||
Environment=RUST_LOG="debug"
|
# Reduce noisy span logs while keeping useful debug info for asusd and related crates.
|
||||||
|
# Keep global level at info but allow debug for our crates; silence tracing::span (very noisy)
|
||||||
|
# RUST_LOG format: <module>=<level>,... (levels: error,warn,info,debug,trace)
|
||||||
|
Environment=RUST_LOG="info,asusd=debug,rog_platform=debug,tracing::span=error"
|
||||||
# required to prevent init issues with hid_asus and MCU
|
# required to prevent init issues with hid_asus and MCU
|
||||||
ExecStartPre=/bin/sleep 1
|
ExecStartPre=/bin/sleep 1
|
||||||
ExecStart=/usr/bin/asusd
|
ExecStart=/usr/bin/asusd
|
||||||
|
|||||||
@@ -1,143 +0,0 @@
|
|||||||
#
|
|
||||||
# spec file for package asus-nb-ctrl
|
|
||||||
#
|
|
||||||
# Copyright (c) 2020-2025 Luke Jones <luke@ljones.dev>
|
|
||||||
#
|
|
||||||
# All modifications and additions to the file contributed by third parties
|
|
||||||
# remain the property of their copyright owners, unless otherwise agreed
|
|
||||||
# upon. The license for this file, and modifications and additions to the
|
|
||||||
# file, is the same license as for the pristine package itself (unless the
|
|
||||||
# license for the pristine package is not an Open Source License, in which
|
|
||||||
# case the license is the MIT License). An "Open Source License" is a
|
|
||||||
# license that conforms to the Open Source Definition (Version 1.9)
|
|
||||||
# published by the Open Source Initiative.
|
|
||||||
|
|
||||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
%if %{defined fedora}
|
|
||||||
%global debug_package %{nil}
|
|
||||||
%endif
|
|
||||||
|
|
||||||
%define version 6.1.17
|
|
||||||
%define specrelease %{?dist}
|
|
||||||
%define pkg_release 9%{specrelease}
|
|
||||||
|
|
||||||
# Use hardening ldflags.
|
|
||||||
%global rustflags -Clink-arg=-Wl,-z,relro,-z,now
|
|
||||||
Name: asusctl
|
|
||||||
Version: %{version}
|
|
||||||
Release: %{pkg_release}
|
|
||||||
Summary: Control fan speeds, LEDs, graphics modes, and charge levels for ASUS notebooks
|
|
||||||
License: MPLv2
|
|
||||||
Requires: power-profiles-daemon
|
|
||||||
|
|
||||||
Group: System Environment/Kernel
|
|
||||||
|
|
||||||
URL: https://gitlab.com/asus-linux/asusctl
|
|
||||||
Source: https://gitlab.com/asus-linux/asusctl/-/archive/%{version}/%{name}-%{version}.tar.gz
|
|
||||||
|
|
||||||
%if %{defined fedora}
|
|
||||||
BuildRequires: rust-packaging
|
|
||||||
BuildRequires: systemd-rpm-macros
|
|
||||||
%else
|
|
||||||
BuildRequires: cargo-packaging
|
|
||||||
%endif
|
|
||||||
BuildRequires: git
|
|
||||||
BuildRequires: clang-devel
|
|
||||||
BuildRequires: cargo
|
|
||||||
BuildRequires: cmake
|
|
||||||
BuildRequires: rust
|
|
||||||
BuildRequires: rust-std-static
|
|
||||||
BuildRequires: pkgconfig(gbm)
|
|
||||||
BuildRequires: pkgconfig(libinput)
|
|
||||||
BuildRequires: pkgconfig(libseat)
|
|
||||||
BuildRequires: pkgconfig(libudev)
|
|
||||||
BuildRequires: pkgconfig(xkbcommon)
|
|
||||||
BuildRequires: pkgconfig(libzstd)
|
|
||||||
BuildRequires: desktop-file-utils
|
|
||||||
|
|
||||||
%description
|
|
||||||
asus-nb-ctrl is a utility for Linux to control many aspects of various
|
|
||||||
ASUS laptops but can also be used with non-Asus laptops with reduced features.
|
|
||||||
|
|
||||||
It provides an interface for rootless control of some system functions such as
|
|
||||||
fan speeds, keyboard LEDs, battery charge level, and graphics modes.
|
|
||||||
asus-nb-ctrl enables third-party apps to use the above with dbus methods.
|
|
||||||
|
|
||||||
%package rog-gui
|
|
||||||
Summary: An experimental GUI for %{name}
|
|
||||||
|
|
||||||
%description rog-gui
|
|
||||||
A one-stop-shop GUI tool for asusd/asusctl. It aims to provide most controls,
|
|
||||||
a notification service, and ability to run in the background.
|
|
||||||
|
|
||||||
%prep
|
|
||||||
%autosetup
|
|
||||||
%if %{defined fedora}
|
|
||||||
%cargo_prep
|
|
||||||
sed -i 's|offline = true|offline = false|' .cargo/config.toml
|
|
||||||
sed -i 's|source.crates-io|source.ignore_this|' .cargo/config.toml
|
|
||||||
%else
|
|
||||||
mkdir -p .cargo
|
|
||||||
cat > .cargo/config.toml << 'EOF'
|
|
||||||
[term]
|
|
||||||
verbose = true
|
|
||||||
[net]
|
|
||||||
offline = false
|
|
||||||
EOF
|
|
||||||
%endif
|
|
||||||
|
|
||||||
%build
|
|
||||||
export RUSTFLAGS="%{rustflags}"
|
|
||||||
%if %{defined fedora}
|
|
||||||
%cargo_build
|
|
||||||
%else
|
|
||||||
/usr/bin/cargo auditable build --release
|
|
||||||
%endif
|
|
||||||
|
|
||||||
%install
|
|
||||||
export RUSTFLAGS="%{rustflags}"
|
|
||||||
mkdir -p "%{buildroot}/%{_bindir}" "%{buildroot}%{_docdir}"
|
|
||||||
%make_install
|
|
||||||
|
|
||||||
install -D -m 0644 README.md %{buildroot}/%{_docdir}/%{name}/README.md
|
|
||||||
install -D -m 0644 rog-anime/README.md %{buildroot}/%{_docdir}/%{name}/README-anime.md
|
|
||||||
install -D -m 0644 rog-anime/data/diagonal-template.png %{buildroot}/%{_docdir}/%{name}/diagonal-template.png
|
|
||||||
|
|
||||||
desktop-file-validate %{buildroot}/%{_datadir}/applications/rog-control-center.desktop
|
|
||||||
|
|
||||||
%files
|
|
||||||
%license LICENSE
|
|
||||||
%{_bindir}/asusd
|
|
||||||
%{_bindir}/asusd-user
|
|
||||||
%{_bindir}/asusctl
|
|
||||||
%{_unitdir}/asusd.service
|
|
||||||
%{_userunitdir}/asusd-user.service
|
|
||||||
%{_udevrulesdir}/99-asusd.rules
|
|
||||||
#%dir %{_sysconfdir}/asusd/
|
|
||||||
%{_datadir}/asusd/aura_support.ron
|
|
||||||
%{_datadir}/dbus-1/system.d/asusd.conf
|
|
||||||
%{_datadir}/icons/hicolor/512x512/apps/asus_notif_yellow.png
|
|
||||||
%{_datadir}/icons/hicolor/512x512/apps/asus_notif_green.png
|
|
||||||
%{_datadir}/icons/hicolor/512x512/apps/asus_notif_red.png
|
|
||||||
%{_datadir}/icons/hicolor/512x512/apps/asus_notif_blue.png
|
|
||||||
%{_datadir}/icons/hicolor/512x512/apps/asus_notif_orange.png
|
|
||||||
%{_datadir}/icons/hicolor/512x512/apps/asus_notif_white.png
|
|
||||||
%{_datadir}/icons/hicolor/scalable/status/gpu-compute.svg
|
|
||||||
%{_datadir}/icons/hicolor/scalable/status/gpu-hybrid.svg
|
|
||||||
%{_datadir}/icons/hicolor/scalable/status/gpu-integrated.svg
|
|
||||||
%{_datadir}/icons/hicolor/scalable/status/gpu-nvidia.svg
|
|
||||||
%{_datadir}/icons/hicolor/scalable/status/gpu-vfio.svg
|
|
||||||
%{_datadir}/icons/hicolor/scalable/status/notification-reboot.svg
|
|
||||||
%{_docdir}/%{name}/
|
|
||||||
%{_datadir}/asusd/
|
|
||||||
|
|
||||||
%files rog-gui
|
|
||||||
%{_bindir}/rog-control-center
|
|
||||||
%{_datadir}/applications/rog-control-center.desktop
|
|
||||||
%{_datadir}/icons/hicolor/512x512/apps/rog-control-center.png
|
|
||||||
%{_datadir}/rog-gui
|
|
||||||
|
|
||||||
%changelog
|
|
||||||
@@ -63,6 +63,7 @@ pub enum AnimeType {
|
|||||||
GA401,
|
GA401,
|
||||||
GA402,
|
GA402,
|
||||||
GU604,
|
GU604,
|
||||||
|
G635L,
|
||||||
#[default]
|
#[default]
|
||||||
Unsupported,
|
Unsupported,
|
||||||
}
|
}
|
||||||
@@ -75,6 +76,7 @@ impl FromStr for AnimeType {
|
|||||||
"ga401" | "GA401" => Self::GA401,
|
"ga401" | "GA401" => Self::GA401,
|
||||||
"ga402" | "GA402" => Self::GA402,
|
"ga402" | "GA402" => Self::GA402,
|
||||||
"gu604" | "GU604" => Self::GU604,
|
"gu604" | "GU604" => Self::GU604,
|
||||||
|
"g635L" | "G635L" => Self::G635L,
|
||||||
_ => Self::Unsupported,
|
_ => Self::Unsupported,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -89,6 +91,8 @@ impl AnimeType {
|
|||||||
AnimeType::GA402
|
AnimeType::GA402
|
||||||
} else if board_name.contains("GU604V") {
|
} else if board_name.contains("GU604V") {
|
||||||
AnimeType::GU604
|
AnimeType::GU604
|
||||||
|
} else if board_name.contains("G635L") || board_name.contains("G635L") {
|
||||||
|
AnimeType::G635L
|
||||||
} else {
|
} else {
|
||||||
AnimeType::Unsupported
|
AnimeType::Unsupported
|
||||||
}
|
}
|
||||||
@@ -180,7 +184,9 @@ impl TryFrom<AnimeDataBuffer> for AnimePacketType {
|
|||||||
|
|
||||||
let mut buffers = match anime.anime {
|
let mut buffers = match anime.anime {
|
||||||
AnimeType::GA401 => vec![[0; 640]; 2],
|
AnimeType::GA401 => vec![[0; 640]; 2],
|
||||||
AnimeType::GA402 | AnimeType::GU604 | AnimeType::Unsupported => vec![[0; 640]; 3],
|
AnimeType::GA402 | AnimeType::GU604 | AnimeType::G635L | AnimeType::Unsupported => {
|
||||||
|
vec![[0; 640]; 3]
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for (idx, chunk) in anime.data.as_slice().chunks(PANE_LEN).enumerate() {
|
for (idx, chunk) in anime.data.as_slice().chunks(PANE_LEN).enumerate() {
|
||||||
|
|||||||
@@ -251,6 +251,8 @@ pub fn get_anime_type() -> AnimeType {
|
|||||||
AnimeType::GA402
|
AnimeType::GA402
|
||||||
} else if board_name.contains("GU604V") {
|
} else if board_name.contains("GU604V") {
|
||||||
AnimeType::GU604
|
AnimeType::GU604
|
||||||
|
} else if board_name.contains("G635L") {
|
||||||
|
AnimeType::G635L
|
||||||
} else {
|
} else {
|
||||||
AnimeType::Unsupported
|
AnimeType::Unsupported
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,6 +44,15 @@
|
|||||||
advanced_type: r#None,
|
advanced_type: r#None,
|
||||||
power_zones: [Keyboard],
|
power_zones: [Keyboard],
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
device_name: "FA617XS",
|
||||||
|
product_id: "",
|
||||||
|
layout_name: "fx505d",
|
||||||
|
basic_modes: [Static, Breathe, Pulse],
|
||||||
|
basic_zones: [],
|
||||||
|
advanced_type: r#None,
|
||||||
|
power_zones: [Keyboard],
|
||||||
|
),
|
||||||
(
|
(
|
||||||
device_name: "FX505",
|
device_name: "FX505",
|
||||||
product_id: "",
|
product_id: "",
|
||||||
@@ -242,6 +251,15 @@
|
|||||||
advanced_type: PerKey,
|
advanced_type: PerKey,
|
||||||
power_zones: [Keyboard],
|
power_zones: [Keyboard],
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
device_name: "G614FR",
|
||||||
|
product_id: "",
|
||||||
|
layout_name: "g634j-per-key",
|
||||||
|
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||||
|
basic_zones: [],
|
||||||
|
advanced_type: PerKey,
|
||||||
|
power_zones: [Keyboard, Lightbar, Logo],
|
||||||
|
),
|
||||||
(
|
(
|
||||||
device_name: "G614J",
|
device_name: "G614J",
|
||||||
product_id: "",
|
product_id: "",
|
||||||
@@ -287,6 +305,15 @@
|
|||||||
advanced_type: PerKey,
|
advanced_type: PerKey,
|
||||||
power_zones: [Keyboard, Lightbar, Logo, RearGlow],
|
power_zones: [Keyboard, Lightbar, Logo, RearGlow],
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
device_name: "G635L",
|
||||||
|
product_id: "",
|
||||||
|
layout_name: "g635l-per-key",
|
||||||
|
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||||
|
basic_zones: [],
|
||||||
|
advanced_type: PerKey,
|
||||||
|
power_zones: [Keyboard, Lightbar, Logo],
|
||||||
|
),
|
||||||
(
|
(
|
||||||
device_name: "G712LI",
|
device_name: "G712LI",
|
||||||
product_id: "",
|
product_id: "",
|
||||||
@@ -485,6 +512,15 @@
|
|||||||
advanced_type: PerKey,
|
advanced_type: PerKey,
|
||||||
power_zones: [Keyboard, Lightbar],
|
power_zones: [Keyboard, Lightbar],
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
device_name: "G815L",
|
||||||
|
product_id: "",
|
||||||
|
layout_name: "g814ji-per-key",
|
||||||
|
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||||
|
basic_zones: [],
|
||||||
|
advanced_type: PerKey,
|
||||||
|
power_zones: [Keyboard, Lightbar],
|
||||||
|
),
|
||||||
(
|
(
|
||||||
device_name: "G834J",
|
device_name: "G834J",
|
||||||
product_id: "",
|
product_id: "",
|
||||||
|
|||||||
@@ -0,0 +1,375 @@
|
|||||||
|
(
|
||||||
|
locale: "US",
|
||||||
|
key_shapes: {
|
||||||
|
"regular": Led(
|
||||||
|
width: 1.0,
|
||||||
|
height: 1.0,
|
||||||
|
pad_left: 0.1,
|
||||||
|
pad_right: 0.1,
|
||||||
|
pad_top: 0.1,
|
||||||
|
pad_bottom: 0.1,
|
||||||
|
),
|
||||||
|
"regular_spacing": Blank(
|
||||||
|
width: 1.2,
|
||||||
|
height: 0.0,
|
||||||
|
),
|
||||||
|
"rog_row": Led(
|
||||||
|
width: 1.0,
|
||||||
|
height: 0.7,
|
||||||
|
pad_left: 0.1,
|
||||||
|
pad_right: 0.1,
|
||||||
|
pad_top: 0.1,
|
||||||
|
pad_bottom: 0.6,
|
||||||
|
),
|
||||||
|
"rog_row_blocking": Blank(
|
||||||
|
width: 1.2,
|
||||||
|
height: 0.0,
|
||||||
|
),
|
||||||
|
"func_space": Blank(
|
||||||
|
width: 0.6,
|
||||||
|
height: 0.0,
|
||||||
|
),
|
||||||
|
"backspace": Led(
|
||||||
|
width: 2.2,
|
||||||
|
height: 1.0,
|
||||||
|
pad_left: 0.1,
|
||||||
|
pad_right: 0.1,
|
||||||
|
pad_top: 0.1,
|
||||||
|
pad_bottom: 0.1,
|
||||||
|
),
|
||||||
|
"tab": Led(
|
||||||
|
width: 1.6,
|
||||||
|
height: 1.0,
|
||||||
|
pad_left: 0.1,
|
||||||
|
pad_right: 0.1,
|
||||||
|
pad_top: 0.1,
|
||||||
|
pad_bottom: 0.1,
|
||||||
|
),
|
||||||
|
"backslash": Led(
|
||||||
|
width: 1.6,
|
||||||
|
height: 1.0,
|
||||||
|
pad_left: 0.1,
|
||||||
|
pad_right: 0.1,
|
||||||
|
pad_top: 0.1,
|
||||||
|
pad_bottom: 0.1,
|
||||||
|
),
|
||||||
|
"capsplonk": Led(
|
||||||
|
width: 2.0,
|
||||||
|
height: 1.0,
|
||||||
|
pad_left: 0.1,
|
||||||
|
pad_right: 0.1,
|
||||||
|
pad_top: 0.1,
|
||||||
|
pad_bottom: 0.1,
|
||||||
|
),
|
||||||
|
"return": Led(
|
||||||
|
width: 2.4,
|
||||||
|
height: 1.0,
|
||||||
|
pad_left: 0.1,
|
||||||
|
pad_right: 0.1,
|
||||||
|
pad_top: 0.1,
|
||||||
|
pad_bottom: 0.1,
|
||||||
|
),
|
||||||
|
"lshift": Led(
|
||||||
|
width: 2.6,
|
||||||
|
height: 1.0,
|
||||||
|
pad_left: 0.1,
|
||||||
|
pad_right: 0.1,
|
||||||
|
pad_top: 0.1,
|
||||||
|
pad_bottom: 0.1,
|
||||||
|
),
|
||||||
|
"rshift": Led(
|
||||||
|
width: 3.0,
|
||||||
|
height: 1.0,
|
||||||
|
pad_left: 0.1,
|
||||||
|
pad_right: 0.1,
|
||||||
|
pad_top: 0.1,
|
||||||
|
pad_bottom: 0.1,
|
||||||
|
),
|
||||||
|
"lctrl": Led(
|
||||||
|
width: 1.4,
|
||||||
|
height: 1.0,
|
||||||
|
pad_left: 0.1,
|
||||||
|
pad_right: 0.1,
|
||||||
|
pad_top: 0.1,
|
||||||
|
pad_bottom: 0.1,
|
||||||
|
),
|
||||||
|
"spacebar": Led(
|
||||||
|
width: 5.8,
|
||||||
|
height: 1.0,
|
||||||
|
pad_left: 0.1,
|
||||||
|
pad_right: 0.1,
|
||||||
|
pad_top: 0.1,
|
||||||
|
pad_bottom: 0.1,
|
||||||
|
),
|
||||||
|
"rctrl": Led(
|
||||||
|
width: 1.2,
|
||||||
|
height: 1.0,
|
||||||
|
pad_left: 0.1,
|
||||||
|
pad_right: 0.1,
|
||||||
|
pad_top: 0.1,
|
||||||
|
pad_bottom: 0.1,
|
||||||
|
),
|
||||||
|
"up_arrow": Led(
|
||||||
|
width: 0.8,
|
||||||
|
height: 0.8,
|
||||||
|
pad_left: 1.1,
|
||||||
|
pad_right: 1.1,
|
||||||
|
pad_top: 0.1,
|
||||||
|
pad_bottom: 0.1,
|
||||||
|
),
|
||||||
|
"arrows_spacer": Blank(
|
||||||
|
width: 15.0,
|
||||||
|
height: 0.0,
|
||||||
|
),
|
||||||
|
"arrows": Led(
|
||||||
|
width: 0.8,
|
||||||
|
height: 0.8,
|
||||||
|
pad_left: 0.1,
|
||||||
|
pad_right: 0.1,
|
||||||
|
pad_top: -0.1,
|
||||||
|
pad_bottom: 0.1,
|
||||||
|
),
|
||||||
|
"row_end_spacing": Blank(
|
||||||
|
width: 0.4,
|
||||||
|
height: 0.0,
|
||||||
|
),
|
||||||
|
"lid_logo": Led(
|
||||||
|
width: 2.6,
|
||||||
|
height: 1.2,
|
||||||
|
pad_left: 0.1,
|
||||||
|
pad_right: 0.1,
|
||||||
|
pad_top: 0.8,
|
||||||
|
pad_bottom: 0.0,
|
||||||
|
),
|
||||||
|
"lightbar_left": Led(
|
||||||
|
width: 0.6,
|
||||||
|
height: 3.6,
|
||||||
|
pad_left: -1.2,
|
||||||
|
pad_right: 0.2,
|
||||||
|
pad_top: -3.0,
|
||||||
|
pad_bottom: 0.3,
|
||||||
|
),
|
||||||
|
"lightbar_corner_left": Led(
|
||||||
|
width: 0.8,
|
||||||
|
height: 0.6,
|
||||||
|
pad_left: -0.6,
|
||||||
|
pad_right: 0.2,
|
||||||
|
pad_top: 0.8,
|
||||||
|
pad_bottom: 0.0,
|
||||||
|
),
|
||||||
|
"lightbar_bottom": Led(
|
||||||
|
width: 12.6,
|
||||||
|
height: 0.5,
|
||||||
|
pad_left: -0.1,
|
||||||
|
pad_right: -0.1,
|
||||||
|
pad_top: 0.8,
|
||||||
|
pad_bottom: 0.0,
|
||||||
|
),
|
||||||
|
"lightbar_corner_right": Led(
|
||||||
|
width: 0.8,
|
||||||
|
height: 0.6,
|
||||||
|
pad_left: 0.0,
|
||||||
|
pad_right: 0.2,
|
||||||
|
pad_top: 0.8,
|
||||||
|
pad_bottom: 0.0,
|
||||||
|
),
|
||||||
|
"lightbar_right": Led(
|
||||||
|
width: 0.6,
|
||||||
|
height: 3.6,
|
||||||
|
pad_left: -0.8,
|
||||||
|
pad_right: 0.2,
|
||||||
|
pad_top: -3.0,
|
||||||
|
pad_bottom: 0.3,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
key_rows: [
|
||||||
|
(
|
||||||
|
pad_left: 0.1,
|
||||||
|
pad_right: 0.1,
|
||||||
|
pad_top: 0.1,
|
||||||
|
pad_bottom: 0.1,
|
||||||
|
row: [
|
||||||
|
(Blocking, "rog_row_blocking"),
|
||||||
|
(Blocking, "rog_row_blocking"),
|
||||||
|
(VolDown, "rog_row"),
|
||||||
|
(VolUp, "rog_row"),
|
||||||
|
(MicMute, "rog_row"),
|
||||||
|
(RogFan, "rog_row"),
|
||||||
|
(RogApp, "rog_row"),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
pad_left: 0.1,
|
||||||
|
pad_right: 0.1,
|
||||||
|
pad_top: 0.1,
|
||||||
|
pad_bottom: 0.1,
|
||||||
|
row: [
|
||||||
|
(Esc, "regular"),
|
||||||
|
(Spacing, "regular_spacing"),
|
||||||
|
(F1, "regular"),
|
||||||
|
(F2, "regular"),
|
||||||
|
(F3, "regular"),
|
||||||
|
(F4, "regular"),
|
||||||
|
(Spacing, "func_space"),
|
||||||
|
(F5, "regular"),
|
||||||
|
(F6, "regular"),
|
||||||
|
(F7, "regular"),
|
||||||
|
(F8, "regular"),
|
||||||
|
(Spacing, "func_space"),
|
||||||
|
(F9, "regular"),
|
||||||
|
(F10, "regular"),
|
||||||
|
(F11, "regular"),
|
||||||
|
(F12, "regular"),
|
||||||
|
(Spacing, "row_end_spacing"),
|
||||||
|
(Del, "regular"), // Should be super/insert
|
||||||
|
],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
pad_left: 0.1,
|
||||||
|
pad_right: 0.1,
|
||||||
|
pad_top: 0.1,
|
||||||
|
pad_bottom: 0.1,
|
||||||
|
row: [
|
||||||
|
(Tilde, "regular"),
|
||||||
|
(N1, "regular"),
|
||||||
|
(N2, "regular"),
|
||||||
|
(N3, "regular"),
|
||||||
|
(N4, "regular"),
|
||||||
|
(N5, "regular"),
|
||||||
|
(N6, "regular"),
|
||||||
|
(N7, "regular"),
|
||||||
|
(N8, "regular"),
|
||||||
|
(N9, "regular"),
|
||||||
|
(N0, "regular"),
|
||||||
|
(Hyphen, "regular"),
|
||||||
|
(Equals, "regular"),
|
||||||
|
(Backspace, "backspace"),
|
||||||
|
(Spacing, "row_end_spacing"),
|
||||||
|
(MediaPlay, "regular"),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
pad_left: 0.1,
|
||||||
|
pad_right: 0.1,
|
||||||
|
pad_top: 0.1,
|
||||||
|
pad_bottom: 0.1,
|
||||||
|
row: [
|
||||||
|
(Tab, "tab"),
|
||||||
|
(Q, "regular"),
|
||||||
|
(W, "regular"),
|
||||||
|
(E, "regular"),
|
||||||
|
(R, "regular"),
|
||||||
|
(T, "regular"),
|
||||||
|
(Y, "regular"),
|
||||||
|
(U, "regular"),
|
||||||
|
(I, "regular"),
|
||||||
|
(O, "regular"),
|
||||||
|
(P, "regular"),
|
||||||
|
(LBracket, "regular"),
|
||||||
|
(RBracket, "regular"),
|
||||||
|
(BackSlash, "backslash"),
|
||||||
|
(Spacing, "row_end_spacing"),
|
||||||
|
(MediaStop, "regular"),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
pad_left: 0.1,
|
||||||
|
pad_right: 0.1,
|
||||||
|
pad_top: 0.1,
|
||||||
|
pad_bottom: 0.1,
|
||||||
|
row: [
|
||||||
|
(Caps, "capsplonk"),
|
||||||
|
(A, "regular"),
|
||||||
|
(S, "regular"),
|
||||||
|
(D, "regular"),
|
||||||
|
(F, "regular"),
|
||||||
|
(G, "regular"),
|
||||||
|
(H, "regular"),
|
||||||
|
(J, "regular"),
|
||||||
|
(K, "regular"),
|
||||||
|
(L, "regular"),
|
||||||
|
(SemiColon, "regular"),
|
||||||
|
(Quote, "regular"),
|
||||||
|
(Return, "return"),
|
||||||
|
(Spacing, "row_end_spacing"),
|
||||||
|
(MediaNext, "regular"),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
pad_left: 0.1,
|
||||||
|
pad_right: 0.1,
|
||||||
|
pad_top: 0.1,
|
||||||
|
pad_bottom: 0.1,
|
||||||
|
row: [
|
||||||
|
(LShift, "lshift"),
|
||||||
|
(Z, "regular"),
|
||||||
|
(X, "regular"),
|
||||||
|
(C, "regular"),
|
||||||
|
(V, "regular"),
|
||||||
|
(B, "regular"),
|
||||||
|
(N, "regular"),
|
||||||
|
(M, "regular"),
|
||||||
|
(Comma, "regular"),
|
||||||
|
(Period, "regular"),
|
||||||
|
(FwdSlash, "regular"),
|
||||||
|
(Rshift, "rshift"),
|
||||||
|
(Spacing, "row_end_spacing"),
|
||||||
|
(MediaPrev, "regular"),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
pad_left: 0.1,
|
||||||
|
pad_right: 0.1,
|
||||||
|
pad_top: 0.1,
|
||||||
|
pad_bottom: 0.1,
|
||||||
|
row: [
|
||||||
|
(LCtrl, "lctrl"),
|
||||||
|
(LFn, "regular"),
|
||||||
|
(Meta, "regular"),
|
||||||
|
(LAlt, "regular"),
|
||||||
|
(Spacebar, "spacebar"),
|
||||||
|
(RAlt, "regular"),
|
||||||
|
(PrtSc, "regular"),
|
||||||
|
(RCtrl, "rctrl"),
|
||||||
|
(Up, "up_arrow"),
|
||||||
|
(Spacing, "row_end_spacing"),
|
||||||
|
(PrtSc, "regular"),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
pad_left: 0.1,
|
||||||
|
pad_right: 0.1,
|
||||||
|
pad_top: 0.1,
|
||||||
|
pad_bottom: 0.1,
|
||||||
|
row: [
|
||||||
|
(Spacing, "arrows_spacer"),
|
||||||
|
(Left, "arrows"),
|
||||||
|
(Down, "arrows"),
|
||||||
|
(Right, "arrows"),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
pad_left: 6.5,
|
||||||
|
pad_right: 6.5,
|
||||||
|
pad_top: 0.2,
|
||||||
|
pad_bottom: 0.1,
|
||||||
|
row: [
|
||||||
|
(LidLogo, "lid_logo"),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
pad_left: 0.1,
|
||||||
|
pad_right: 0.1,
|
||||||
|
pad_top: 0.1,
|
||||||
|
pad_bottom: 0.1,
|
||||||
|
row: [
|
||||||
|
(LightbarLeft, "lightbar_left"),
|
||||||
|
(LightbarLeftCorner, "lightbar_corner_left"),
|
||||||
|
(LightbarLeftBottom, "lightbar_bottom"),
|
||||||
|
(LightbarRightBottom, "lightbar_bottom"),
|
||||||
|
(LightbarRightCorner, "lightbar_corner_right"),
|
||||||
|
(LightbarRight, "lightbar_right"),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
@@ -164,6 +164,25 @@ impl LedSupportFile {
|
|||||||
return Some(data);
|
return Some(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the system-wide files were not found (typical in CI or
|
||||||
|
// development environments), attempt to load the bundled
|
||||||
|
// `data/aura_support.ron` from the crate so tests and local runs
|
||||||
|
// behave the same as when the package is installed.
|
||||||
|
// Attempt to load a bundled `aura_support.ron` included at compile time.
|
||||||
|
// Using `include_str!` ensures the data is available regardless of
|
||||||
|
// runtime `CARGO_MANIFEST_DIR` or CI environment differences.
|
||||||
|
let bundled_buf = include_str!("../data/aura_support.ron");
|
||||||
|
if !bundled_buf.is_empty() {
|
||||||
|
if let Ok(tmp) = ron::from_str::<LedSupportFile>(bundled_buf) {
|
||||||
|
data.0.append(&mut tmp.0.clone());
|
||||||
|
data.0.sort_by(|a, b| a.device_name.cmp(&b.device_name));
|
||||||
|
info!("Loaded bundled LED support data (embedded)");
|
||||||
|
return Some(data);
|
||||||
|
} else {
|
||||||
|
warn!("Could not parse embedded bundled data file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
warn!("Does {} exist?", ASUS_LED_MODE_USER_CONF);
|
warn!("Does {} exist?", ASUS_LED_MODE_USER_CONF);
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,11 +24,16 @@ use tokio::runtime::Runtime;
|
|||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
|
// Ensure tracing spans are quiet by default unless user overrides
|
||||||
|
if std::env::var_os("RUST_LOG").is_none() {
|
||||||
|
std::env::set_var("RUST_LOG", "warn,tracing=error,zbus=error");
|
||||||
|
}
|
||||||
let mut logger = env_logger::Builder::new();
|
let mut logger = env_logger::Builder::new();
|
||||||
logger
|
logger
|
||||||
.filter_level(LevelFilter::Warn)
|
|
||||||
.parse_default_env()
|
.parse_default_env()
|
||||||
.target(env_logger::Target::Stdout)
|
.filter_level(LevelFilter::Info)
|
||||||
|
.parse_default_env()
|
||||||
|
.target(env_logger::Target::Stderr)
|
||||||
.format_timestamp(None)
|
.format_timestamp(None)
|
||||||
.init();
|
.init();
|
||||||
|
|
||||||
|
|||||||
@@ -203,11 +203,19 @@ pub fn start_notifications(
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
let proxy_copy = proxy.clone();
|
let proxy_copy = proxy.clone();
|
||||||
|
let enabled_notifications_copy_action = enabled_notifications_copy.clone();
|
||||||
let mut p = proxy.receive_notify_action().await?;
|
let mut p = proxy.receive_notify_action().await?;
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
info!("Started zbus signal thread: receive_notify_action");
|
info!("Started zbus signal thread: receive_notify_action");
|
||||||
while let Some(e) = p.next().await {
|
while let Some(e) = p.next().await {
|
||||||
if let Ok(out) = e.args() {
|
if let Ok(out) = e.args() {
|
||||||
|
// Respect user notification settings for gpu actions
|
||||||
|
if let Ok(cfg) = enabled_notifications_copy_action.lock() {
|
||||||
|
if !cfg.notifications.enabled || !cfg.notifications.receive_notify_gfx {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let action = out.action();
|
let action = out.action();
|
||||||
let mode = convert_gfx_mode(proxy.mode().await.unwrap_or_default());
|
let mode = convert_gfx_mode(proxy.mode().await.unwrap_or_default());
|
||||||
match action {
|
match action {
|
||||||
@@ -309,7 +317,9 @@ fn do_gfx_action_notif(message: &str, action: GfxUserAction, mode: GpuMode) -> R
|
|||||||
//.hint(Hint::Resident(true))
|
//.hint(Hint::Resident(true))
|
||||||
.hint(Hint::Category("device".into()))
|
.hint(Hint::Category("device".into()))
|
||||||
.urgency(Urgency::Critical)
|
.urgency(Urgency::Critical)
|
||||||
.timeout(Timeout::Never)
|
// For user-action notifications keep them visible if they require interaction
|
||||||
|
// but for non-interactive actions we prefer they auto-hide like other notifs.
|
||||||
|
.timeout(Timeout::Milliseconds(6000))
|
||||||
.icon("dialog-warning")
|
.icon("dialog-warning")
|
||||||
.hint(Hint::Transient(true));
|
.hint(Hint::Transient(true));
|
||||||
|
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if paths.len() > 1 {
|
if paths.len() > 1 {
|
||||||
println!("Multiple asusd interfaces devices found");
|
log::warn!("Multiple asusd interfaces devices found");
|
||||||
}
|
}
|
||||||
if !paths.is_empty() {
|
if !paths.is_empty() {
|
||||||
let mut ctrl = Vec::new();
|
let mut ctrl = Vec::new();
|
||||||
@@ -129,7 +129,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if paths.len() > 1 {
|
if paths.len() > 1 {
|
||||||
println!("Multiple asusd interfaces devices found");
|
log::warn!("Multiple asusd interfaces devices found");
|
||||||
}
|
}
|
||||||
if !paths.is_empty() {
|
if !paths.is_empty() {
|
||||||
let mut ctrl = Vec::new();
|
let mut ctrl = Vec::new();
|
||||||
|
|||||||
@@ -383,7 +383,7 @@ impl From<&str> for FirmwareAttribute {
|
|||||||
"nv_dynamic_boost" => Self::NvDynamicBoost,
|
"nv_dynamic_boost" => Self::NvDynamicBoost,
|
||||||
"nv_temp_target" => Self::NvTempTarget,
|
"nv_temp_target" => Self::NvTempTarget,
|
||||||
"nv_base_tgp" => Self::DgpuBaseTgp,
|
"nv_base_tgp" => Self::DgpuBaseTgp,
|
||||||
"dgpu_tgp" => Self::DgpuTgp,
|
"nv_tgp" => Self::DgpuTgp,
|
||||||
"charge_mode" => Self::ChargeMode,
|
"charge_mode" => Self::ChargeMode,
|
||||||
"boot_sound" => Self::BootSound,
|
"boot_sound" => Self::BootSound,
|
||||||
"mcu_powersave" => Self::McuPowersave,
|
"mcu_powersave" => Self::McuPowersave,
|
||||||
@@ -420,7 +420,7 @@ impl From<FirmwareAttribute> for &str {
|
|||||||
FirmwareAttribute::NvDynamicBoost => "nv_dynamic_boost",
|
FirmwareAttribute::NvDynamicBoost => "nv_dynamic_boost",
|
||||||
FirmwareAttribute::NvTempTarget => "nv_temp_target",
|
FirmwareAttribute::NvTempTarget => "nv_temp_target",
|
||||||
FirmwareAttribute::DgpuBaseTgp => "dgpu_base_tgp",
|
FirmwareAttribute::DgpuBaseTgp => "dgpu_base_tgp",
|
||||||
FirmwareAttribute::DgpuTgp => "dgpu_tgp",
|
FirmwareAttribute::DgpuTgp => "nv_tgp",
|
||||||
FirmwareAttribute::ChargeMode => "charge_mode",
|
FirmwareAttribute::ChargeMode => "charge_mode",
|
||||||
FirmwareAttribute::BootSound => "boot_sound",
|
FirmwareAttribute::BootSound => "boot_sound",
|
||||||
FirmwareAttribute::McuPowersave => "mcu_powersave",
|
FirmwareAttribute::McuPowersave => "mcu_powersave",
|
||||||
|
|||||||
@@ -101,8 +101,15 @@ impl AsusPower {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(PlatformError::MissingFunction(
|
// No battery found. Return an AsusPower with an empty battery path so
|
||||||
"Did not find a battery".to_owned(),
|
// callers can still be constructed and query `has_*` methods which
|
||||||
))
|
// will correctly report absence. This avoids hard-failing on systems
|
||||||
|
// where the asus-nb-wmi driver loads on desktops with no battery.
|
||||||
|
info!("Did not find a battery, continuing without battery support");
|
||||||
|
Ok(Self {
|
||||||
|
mains,
|
||||||
|
battery: PathBuf::new(),
|
||||||
|
usb,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ impl AniMatrix {
|
|||||||
vertical: 2,
|
vertical: 2,
|
||||||
horizontal: 5,
|
horizontal: 5,
|
||||||
},
|
},
|
||||||
AnimeType::GA402 | AnimeType::Unsupported => LedShape {
|
AnimeType::GA402 | AnimeType::G635L | AnimeType::Unsupported => LedShape {
|
||||||
vertical: 2,
|
vertical: 2,
|
||||||
horizontal: 5,
|
horizontal: 5,
|
||||||
},
|
},
|
||||||
@@ -56,7 +56,7 @@ impl AniMatrix {
|
|||||||
// Do a hard mapping of each (derived from wireshardk captures)
|
// Do a hard mapping of each (derived from wireshardk captures)
|
||||||
let rows = match model {
|
let rows = match model {
|
||||||
AnimeType::GA401 => GA401.to_vec(),
|
AnimeType::GA401 => GA401.to_vec(),
|
||||||
AnimeType::GA402 | AnimeType::Unsupported => GA402.to_vec(),
|
AnimeType::GA402 | AnimeType::G635L | AnimeType::Unsupported => GA402.to_vec(),
|
||||||
AnimeType::GU604 => GU604.to_vec(),
|
AnimeType::GU604 => GU604.to_vec(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -157,8 +157,9 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
for (x_count, b) in dev.buffer[start..=end].iter().enumerate() {
|
for (x_count, b) in dev.buffer[start..=end].iter().enumerate() {
|
||||||
canvas.set_draw_color(Color::RGB(*b, *b, *b));
|
canvas.set_draw_color(Color::RGB(*b, *b, *b));
|
||||||
|
|
||||||
|
#[allow(clippy::manual_is_multiple_of)]
|
||||||
let x: i32 = w + x_count as i32 * w
|
let x: i32 = w + x_count as i32 * w
|
||||||
- if !((y_count + y_offset as usize) % 2 == 0) {
|
- if (y_count + y_offset as usize) % 2 != 0 {
|
||||||
0
|
0
|
||||||
} else {
|
} else {
|
||||||
w / 2
|
w / 2
|
||||||
|
|||||||
Reference in New Issue
Block a user