From 1da68ea69db274fba5f6ea1c6d717bb9bd9c60d1 Mon Sep 17 00:00:00 2001 From: "Luke D. Jones" Date: Fri, 10 May 2024 12:21:15 +1200 Subject: [PATCH] Try to mitigate the lack of kbd_brightness on some laptops --- CHANGELOG.md | 1 + README.md | 2 + asusd/src/ctrl_aura/controller.rs | 72 +++++++++++++++++++++++++----- asusd/src/ctrl_aura/trait_impls.rs | 58 +++++++++++++----------- rog-aura/data/aura_support.ron | 4 +- rog-platform/src/keyboard_led.rs | 9 ++-- 6 files changed, 105 insertions(+), 41 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a3dba62..bd17e882 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Better more robust error handling in ROGCC - Try to better handle pre-2021 laptops with lightbar - Add more logging to try and trace the charge_control_end_threshold issue +- Make `kbd_brightness` optional to work around issues on some laptops that seem to lack it. Likely this will all need a refactor *again* if work proceeds in kernel for better RGB support. ## [v6.0.4] diff --git a/README.md b/README.md index 150a60f5..8fa3eb27 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,8 @@ The list is a bit outdated as many features have been enabled in the Linux kerne A gui is now in the repo - ROG Control Center. At this time it is still a WIP, but it has almost all features in place already. +**NOTE**: Xorg is not supported. + # BUILDING Rust and cargo are required, they can be installed from [rustup.rs](https://rustup.rs/) or from the distro repos if newer than 1.75. diff --git a/asusd/src/ctrl_aura/controller.rs b/asusd/src/ctrl_aura/controller.rs index 16ec28b0..de187d14 100644 --- a/asusd/src/ctrl_aura/controller.rs +++ b/asusd/src/ctrl_aura/controller.rs @@ -11,7 +11,7 @@ use rog_aura::{ AuraDeviceType, AuraEffect, Direction, LedBrightness, Speed, GRADIENT, LED_MSG_LEN, }; use rog_platform::hid_raw::HidRaw; -use rog_platform::keyboard_led::KeyboardLed; +use rog_platform::keyboard_led::KeyboardBacklight; use zbus::zvariant::OwnedObjectPath; use super::config::AuraConfig; @@ -21,9 +21,9 @@ use crate::error::RogError; #[derive(Debug)] pub enum LEDNode { /// Brightness and/or TUF RGB controls - KbdLed(KeyboardLed), + KbdLed(KeyboardBacklight), /// Raw HID handle - Rog(KeyboardLed, HidRaw), + Rog(Option, HidRaw), } impl LEDNode { @@ -31,7 +31,13 @@ impl LEDNode { pub fn set_brightness(&self, value: u8) -> Result<(), RogError> { match self { LEDNode::KbdLed(k) => k.set_brightness(value)?, - LEDNode::Rog(k, _) => k.set_brightness(value)?, + LEDNode::Rog(k, _) => { + if let Some(k) = k { + k.set_brightness(value)? + } else { + debug!("No brightness control found"); + } + } } Ok(()) } @@ -39,16 +45,47 @@ impl LEDNode { pub fn get_brightness(&self) -> Result { Ok(match self { LEDNode::KbdLed(k) => k.get_brightness()?, - LEDNode::Rog(k, _) => k.get_brightness()?, + LEDNode::Rog(k, _) => { + if let Some(k) = k { + k.get_brightness()? + } else { + debug!("No brightness control found"); + return Err(RogError::MissingFunction( + "No keyboard brightness control found".to_string(), + )); + } + } }) } pub fn monitor_brightness(&self) -> Result { Ok(match self { LEDNode::KbdLed(k) => k.monitor_brightness()?, - LEDNode::Rog(k, _) => k.monitor_brightness()?, + LEDNode::Rog(k, _) => { + if let Some(k) = k { + k.monitor_brightness()? + } else { + debug!("No brightness control found"); + return Err(RogError::MissingFunction( + "No keyboard brightness control found".to_string(), + )); + } + } }) } + + pub fn has_brightness_control(&self) -> bool { + match self { + LEDNode::KbdLed(k) => k.has_brightness(), + LEDNode::Rog(k, _) => { + if let Some(k) = k { + k.has_brightness() + } else { + false + } + } + } + } } /// Individual controller for one Aura device @@ -122,7 +159,7 @@ impl CtrlKbdLed { } // Check for a TUF laptop LED. Assume there is only ever one. - if let Ok(kbd_backlight) = KeyboardLed::new() { + if let Ok(kbd_backlight) = KeyboardBacklight::new() { if kbd_backlight.has_kbd_rgb_mode() { // Extra sure double-check that this isn't a laptop with crap // ACPI with borked return on the TUF rgb methods @@ -157,7 +194,14 @@ impl CtrlKbdLed { /// should be overwritten. The reason for the default config is because /// of async issues between this and udev/hidraw pub fn from_hidraw(device: HidRaw, dbus_path: OwnedObjectPath) -> Result { - let rgb_led = KeyboardLed::new()?; + let rgb_led = KeyboardBacklight::new() + .map_err(|e| { + log::error!( + "{} is missing a keyboard backlight brightness control: {e:?}", + device.prod_id() + ); + }) + .ok(); let prod_id = AuraDeviceType::from(device.prod_id()); if prod_id == AuraDeviceType::Unknown { log::error!("{} is AuraDevice::Unknown", device.prod_id()); @@ -376,7 +420,7 @@ mod tests { use rog_aura::aura_detection::LedSupportData; use rog_aura::{AuraDeviceType, AuraModeNum, AuraZone, PowerZones}; use rog_platform::hid_raw::HidRaw; - use rog_platform::keyboard_led::KeyboardLed; + use rog_platform::keyboard_led::KeyboardBacklight; use zbus::zvariant::OwnedObjectPath; use super::CtrlKbdLed; @@ -399,7 +443,10 @@ mod tests { }; let mut controller = CtrlKbdLed { led_type: AuraDeviceType::LaptopPost2021, - led_node: LEDNode::Rog(KeyboardLed::default(), HidRaw::new("19b6").unwrap()), + led_node: LEDNode::Rog( + Some(KeyboardBacklight::default()), + HidRaw::new("19b6").unwrap(), + ), supported_data: supported_basic_modes, per_key_mode_active: false, config, @@ -440,7 +487,10 @@ mod tests { }; let mut controller = CtrlKbdLed { led_type: AuraDeviceType::LaptopPost2021, - led_node: LEDNode::Rog(KeyboardLed::default(), HidRaw::new("19b6").unwrap()), + led_node: LEDNode::Rog( + Some(KeyboardBacklight::default()), + HidRaw::new("19b6").unwrap(), + ), supported_data: supported_basic_modes, per_key_mode_active: false, config, diff --git a/asusd/src/ctrl_aura/trait_impls.rs b/asusd/src/ctrl_aura/trait_impls.rs index 274f8e69..51855f5f 100644 --- a/asusd/src/ctrl_aura/trait_impls.rs +++ b/asusd/src/ctrl_aura/trait_impls.rs @@ -26,7 +26,7 @@ impl CtrlAuraZbus { } fn update_config(lock: &mut CtrlKbdLed) -> Result<(), RogError> { - let bright = lock.led_node.get_brightness()?; + let bright = lock.led_node.get_brightness().unwrap_or_default(); lock.config.read(); lock.config.brightness = bright.into(); lock.config.write(); @@ -109,8 +109,10 @@ impl CtrlAuraZbus { if ctrl.config.brightness == LedBrightness::Off { ctrl.config.brightness = LedBrightness::Med; } - ctrl.led_node - .set_brightness(ctrl.config.brightness.into())?; + if ctrl.led_node.has_brightness_control() { + ctrl.led_node + .set_brightness(ctrl.config.brightness.into())?; + } ctrl.config.write(); self.led_mode_data_invalidate(&self.1).await.ok(); @@ -148,8 +150,10 @@ impl CtrlAuraZbus { if ctrl.config.brightness == LedBrightness::Off { ctrl.config.brightness = LedBrightness::Med; } - ctrl.led_node - .set_brightness(ctrl.config.brightness.into())?; + if ctrl.led_node.has_brightness_control() { + ctrl.led_node + .set_brightness(ctrl.config.brightness.into())?; + } ctrl.config.set_builtin(effect); ctrl.config.write(); @@ -213,12 +217,14 @@ impl CtrlTask for CtrlAuraZbus { // If waking up if !start { info!("CtrlKbdLedTask reloading brightness and modes"); - lock.led_node - .set_brightness(lock.config.brightness.into()) - .map_err(|e| { - error!("CtrlKbdLedTask: {e}"); - e - })?; + if lock.led_node.has_brightness_control() { + lock.led_node + .set_brightness(lock.config.brightness.into()) + .map_err(|e| { + error!("CtrlKbdLedTask: {e}"); + e + })?; + } lock.write_current_config_mode().map_err(|e| { error!("CtrlKbdLedTask: {e}"); e @@ -264,20 +270,22 @@ impl CtrlTask for CtrlAuraZbus { let ctrl2 = self.0.clone(); let ctrl = self.0.lock().await; - let watch = ctrl.led_node.monitor_brightness()?; - tokio::spawn(async move { - let mut buffer = [0; 32]; - watch - .into_event_stream(&mut buffer) - .unwrap() - .for_each(|_| async { - if let Some(lock) = ctrl2.try_lock() { - load_save(true, lock).unwrap(); // unwrap as we want to - // bomb out of the task - } - }) - .await; - }); + if ctrl.led_node.has_brightness_control() { + let watch = ctrl.led_node.monitor_brightness()?; + tokio::spawn(async move { + let mut buffer = [0; 32]; + watch + .into_event_stream(&mut buffer) + .unwrap() + .for_each(|_| async { + if let Some(lock) = ctrl2.try_lock() { + load_save(true, lock).unwrap(); // unwrap as we want to + // bomb out of the task + } + }) + .await; + }); + } Ok(()) } diff --git a/rog-aura/data/aura_support.ron b/rog-aura/data/aura_support.ron index 1759f436..5e69671e 100644 --- a/rog-aura/data/aura_support.ron +++ b/rog-aura/data/aura_support.ron @@ -328,9 +328,9 @@ product_id: "", layout_name: "ga401q", basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse], - basic_zones: [Key1, Key2, Key3, Key4], + basic_zones: [Key1, Key2, Key3, Key4, BarLeft, BarRight], advanced_type: None, - power_zones: [Keyboard], + power_zones: [Keyboard, Lightbar], ), ( device_name: "G731", diff --git a/rog-platform/src/keyboard_led.rs b/rog-platform/src/keyboard_led.rs index 056091d1..e005ade2 100644 --- a/rog-platform/src/keyboard_led.rs +++ b/rog-platform/src/keyboard_led.rs @@ -5,12 +5,15 @@ use log::{info, warn}; use crate::error::{PlatformError, Result}; use crate::{attr_u8, has_attr, set_attr_u8_array, to_device}; +/// The sysfs control for backlight levels. This is only for the 3-step +/// backlight setting, and for TUF laptops. It is not a hard requirement +/// for Aura keyboards #[derive(Debug, Default, PartialEq, Eq, PartialOrd, Clone)] -pub struct KeyboardLed { +pub struct KeyboardBacklight { path: PathBuf, } -impl KeyboardLed { +impl KeyboardBacklight { attr_u8!("brightness", path); has_attr!("kbd_rgb_mode" path); @@ -59,7 +62,7 @@ impl KeyboardLed { }); } Err(PlatformError::MissingFunction( - "asus::kbd_backlight not found".into(), + "KeyboardLed:new(), asus::kbd_backlight not found".into(), )) } }