From 0d2cd4eb10f5305981ae63ee36bda080c73e8e9b Mon Sep 17 00:00:00 2001 From: Josh Dariano Date: Fri, 16 Jan 2026 13:57:35 -0500 Subject: [PATCH 1/4] Fix keyboard light --- rog-aura/data/aura_support.ron | 18 ++++++++++++++++++ rog-aura/src/lib.rs | 4 ++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/rog-aura/data/aura_support.ron b/rog-aura/data/aura_support.ron index dda614b5..70785ed8 100644 --- a/rog-aura/data/aura_support.ron +++ b/rog-aura/data/aura_support.ron @@ -971,6 +971,24 @@ advanced_type: r#None, power_zones: [Keyboard], ), + ( + device_name: "GZ302", + product_id: "18c6", + layout_name: "", + basic_modes: [Static, Breathe, Pulse], + basic_zones: [], + advanced_type: r#None, + power_zones: [Logo], + ), + ( + device_name: "GZ302", + product_id: "1a30", + layout_name: "ga401q", + basic_modes: [Static, Breathe, Pulse], + basic_zones: [], + advanced_type: r#None, + power_zones: [Keyboard], + ), ( device_name: "RC71L", product_id: "", diff --git a/rog-aura/src/lib.rs b/rog-aura/src/lib.rs index 6ff39133..9a7bdd45 100644 --- a/rog-aura/src/lib.rs +++ b/rog-aura/src/lib.rs @@ -106,10 +106,10 @@ impl From<&str> for AuraDeviceType { match s.to_lowercase().trim_start_matches("0x") { "tuf" => AuraDeviceType::LaptopKeyboardTuf, "1932" => AuraDeviceType::ScsiExtDisk, - "1866" | "18c6" | "1869" | "1854" => Self::LaptopKeyboardPre2021, + "1866" | "1869" | "1854" => Self::LaptopKeyboardPre2021, "1abe" | "1b4c" => Self::Ally, "19b3" | "193b" => Self::AnimeOrSlash, - "19b6" => Self::LaptopKeyboard2021, + "19b6" | "1a30" | "18c6" => Self::LaptopKeyboard2021, _ => Self::Unknown, } } From 9d629b62ca1d822ef052578f1b185853567e200f Mon Sep 17 00:00:00 2001 From: Josh Dariano Date: Fri, 16 Jan 2026 15:33:30 -0500 Subject: [PATCH 2/4] Fix aura backlight for z13 --- asusd/src/aura_laptop/mod.rs | 67 +++++++++++++++++++++++++++++++++- rog-aura/src/keyboard/power.rs | 31 ++++++++++------ 2 files changed, 85 insertions(+), 13 deletions(-) diff --git a/asusd/src/aura_laptop/mod.rs b/asusd/src/aura_laptop/mod.rs index 7fabceba..21b062f3 100644 --- a/asusd/src/aura_laptop/mod.rs +++ b/asusd/src/aura_laptop/mod.rs @@ -25,6 +25,24 @@ pub struct Aura { impl Aura { /// Initialise the device if required. pub async fn do_initialization(&self) -> Result<(), RogError> { + if let Some(hid) = &self.hid { + let hid = hid.lock().await; + let init_1: [u8; 2] = [0x5d, 0xb9]; + let init_2 = b"]ASUS Tech.Inc."; + let init_3: [u8; 6] = [0x5d, 0x05, 0x20, 0x31, 0, 0x1a]; + + hid.write_bytes(&init_1)?; + hid.write_bytes(init_2)?; + hid.write_bytes(&init_3)?; + + let config = self.config.lock().await; + if config.support_data.device_name.contains("GZ30") + || config.support_data.device_name.contains("Z13") + { + let z13_init: [u8; 4] = [0x5d, 0xc0, 0x03, 0x01]; + hid.write_bytes(&z13_init)?; + } + } Ok(()) } @@ -152,9 +170,54 @@ impl Aura { } } - let bytes = config.enabled.to_bytes(config.led_type); + let mut enabled = config.enabled.clone(); + if config.support_data.device_name.contains("GZ30") + || config.support_data.device_name.contains("Z13") + { + let logo_state = enabled + .states + .iter() + .find(|s| s.zone == PowerZones::Logo) + .cloned(); + if let Some(logo) = logo_state { + let mut lid_found = false; + let mut bar_found = false; + + for s in enabled.states.iter_mut() { + if s.zone == PowerZones::Lid { + s.boot = logo.boot; + s.awake = logo.awake; + s.sleep = logo.sleep; + s.shutdown = logo.shutdown; + lid_found = true; + } + if s.zone == PowerZones::Lightbar { + s.boot = logo.boot; + s.awake = logo.awake; + s.sleep = logo.sleep; + s.shutdown = logo.shutdown; + bar_found = true; + } + } + + if !lid_found { + let mut new_state = logo; + new_state.zone = PowerZones::Lid; + enabled.states.push(new_state.clone()); + new_state.zone = PowerZones::Lightbar; + enabled.states.push(new_state); + } else if !bar_found { + // Lid found but not bar? + let mut new_state = logo; + new_state.zone = PowerZones::Lightbar; + enabled.states.push(new_state); + } + } + } + + let bytes = enabled.to_bytes(config.led_type); let msg = [ - 0x5d, 0xbd, 0x01, bytes[0], bytes[1], bytes[2], bytes[3], + 0x5d, 0xbd, 0x01, bytes[0], bytes[1], bytes[2], bytes[3], 0xff, ]; hid_raw.write_bytes(&msg)?; } diff --git a/rog-aura/src/keyboard/power.rs b/rog-aura/src/keyboard/power.rs index 7b5b1f53..5019ec91 100644 --- a/rog-aura/src/keyboard/power.rs +++ b/rog-aura/src/keyboard/power.rs @@ -123,7 +123,8 @@ impl AuraPowerState { | ((self.shutdown as u32) << 7) } PowerZones::Lightbar => { - ((self.boot as u32) << (7 + 2)) + ((self.awake as u32) << (7 + 1)) + | ((self.boot as u32) << (7 + 2)) | ((self.awake as u32) << (7 + 3)) | ((self.sleep as u32) << (7 + 4)) | ((self.shutdown as u32) << (7 + 5)) @@ -133,12 +134,20 @@ impl AuraPowerState { | ((self.awake as u32) << (15 + 2)) | ((self.sleep as u32) << (15 + 3)) | ((self.shutdown as u32) << (15 + 4)) + | ((self.boot as u32) << (15 + 5)) + | ((self.awake as u32) << (15 + 6)) + | ((self.sleep as u32) << (15 + 7)) + | ((self.shutdown as u32) << (15 + 8)) } PowerZones::RearGlow => { ((self.boot as u32) << (23 + 1)) | ((self.awake as u32) << (23 + 2)) | ((self.sleep as u32) << (23 + 3)) | ((self.shutdown as u32) << (23 + 4)) + | ((self.boot as u32) << (23 + 5)) + | ((self.awake as u32) << (23 + 6)) + | ((self.sleep as u32) << (23 + 7)) + | ((self.shutdown as u32) << (23 + 8)) } PowerZones::None | PowerZones::KeyboardAndLightbar => 0, } @@ -618,19 +627,19 @@ mod test { assert_eq!(shut_keyb_, "10000000, 00000000, 00000000, 00000000"); // assert_eq!(boot_bar__, "00000000, 00000010, 00000000, 00000000"); - assert_eq!(awake_bar_, "00000000, 00000100, 00000000, 00000000"); + assert_eq!(awake_bar_, "00000000, 00000101, 00000000, 00000000"); assert_eq!(sleep_bar_, "00000000, 00001000, 00000000, 00000000"); assert_eq!(shut_bar__, "00000000, 00010000, 00000000, 00000000"); // - assert_eq!(boot_lid__, "00000000, 00000000, 00000001, 00000000"); - assert_eq!(awake_lid_, "00000000, 00000000, 00000010, 00000000"); - assert_eq!(sleep_lid_, "00000000, 00000000, 00000100, 00000000"); - assert_eq!(shut_lid__, "00000000, 00000000, 00001000, 00000000"); + assert_eq!(boot_lid__, "00000000, 00000000, 00010001, 00000000"); + assert_eq!(awake_lid_, "00000000, 00000000, 00100010, 00000000"); + assert_eq!(sleep_lid_, "00000000, 00000000, 01000100, 00000000"); + assert_eq!(shut_lid__, "00000000, 00000000, 10001000, 00000000"); // - assert_eq!(boot_rear_, "00000000, 00000000, 00000000, 00000001"); - assert_eq!(awake_rear, "00000000, 00000000, 00000000, 00000010"); - assert_eq!(sleep_rear, "00000000, 00000000, 00000000, 00000100"); - assert_eq!(shut_rear_, "00000000, 00000000, 00000000, 00001000"); + assert_eq!(boot_rear_, "00000000, 00000000, 00000000, 00010001"); + assert_eq!(awake_rear, "00000000, 00000000, 00000000, 00100010"); + assert_eq!(sleep_rear, "00000000, 00000000, 00000000, 01000100"); + assert_eq!(shut_rear_, "00000000, 00000000, 00000000, 10001000"); // All on let byte1 = to_binary_string_post2021(&LaptopAuraPower { @@ -657,6 +666,6 @@ mod test { }, ], }); - assert_eq!(byte1, "11111111, 00011110, 00001111, 00001111"); + assert_eq!(byte1, "11111111, 00011111, 11111111, 11111111"); } } From 8095ac34ed4cbb83aef414d76ba551760b9102b4 Mon Sep 17 00:00:00 2001 From: Josh Dariano Date: Fri, 16 Jan 2026 15:48:02 -0500 Subject: [PATCH 3/4] Fix formatting --- asusd/src/aura_laptop/mod.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/asusd/src/aura_laptop/mod.rs b/asusd/src/aura_laptop/mod.rs index 21b062f3..4882770d 100644 --- a/asusd/src/aura_laptop/mod.rs +++ b/asusd/src/aura_laptop/mod.rs @@ -27,9 +27,13 @@ impl Aura { pub async fn do_initialization(&self) -> Result<(), RogError> { if let Some(hid) = &self.hid { let hid = hid.lock().await; - let init_1: [u8; 2] = [0x5d, 0xb9]; + let init_1: [u8; 2] = [ + 0x5d, 0xb9, + ]; let init_2 = b"]ASUS Tech.Inc."; - let init_3: [u8; 6] = [0x5d, 0x05, 0x20, 0x31, 0, 0x1a]; + let init_3: [u8; 6] = [ + 0x5d, 0x05, 0x20, 0x31, 0, 0x1a, + ]; hid.write_bytes(&init_1)?; hid.write_bytes(init_2)?; @@ -39,7 +43,9 @@ impl Aura { if config.support_data.device_name.contains("GZ30") || config.support_data.device_name.contains("Z13") { - let z13_init: [u8; 4] = [0x5d, 0xc0, 0x03, 0x01]; + let z13_init: [u8; 4] = [ + 0x5d, 0xc0, 0x03, 0x01, + ]; hid.write_bytes(&z13_init)?; } } @@ -207,7 +213,7 @@ impl Aura { new_state.zone = PowerZones::Lightbar; enabled.states.push(new_state); } else if !bar_found { - // Lid found but not bar? + // Lid found but not bar? let mut new_state = logo; new_state.zone = PowerZones::Lightbar; enabled.states.push(new_state); From f471f340d45af028223e249fcc59281b7686f7ed Mon Sep 17 00:00:00 2001 From: Josh Dariano Date: Fri, 16 Jan 2026 16:37:15 -0500 Subject: [PATCH 4/4] Fix fan controls on z13 --- rog-profiles/src/fan_curve_set.rs | 17 +++++++++++++---- rog-profiles/src/lib.rs | 26 ++++++++++++++++++++------ 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/rog-profiles/src/fan_curve_set.rs b/rog-profiles/src/fan_curve_set.rs index 79fd6990..9efeb373 100644 --- a/rog-profiles/src/fan_curve_set.rs +++ b/rog-profiles/src/fan_curve_set.rs @@ -162,7 +162,6 @@ impl CurveData { /// Write this curve to the device fan specified by `self.fan` pub fn write_to_device(&self, device: &mut Device) -> std::io::Result<()> { let pwm_num: char = self.fan.into(); - let enable = if self.enabled { '1' } else { '2' }; for (index, out) in self.pwm.iter().enumerate() { let pwm = pwm_str(pwm_num, index); @@ -176,10 +175,20 @@ impl CurveData { device.set_attribute_value(&temp, out.to_string())?; } - // Enable must be done *after* all points are written pwm3_enable + // Note: pwm_enable is set by write_profile_curve_to_platform after all + // curves are written, because on some devices (e.g., ASUS Z13 2025) + // setting any pwm_enable to 2 resets ALL fan enables. + Ok(()) + } + + /// Set the enable state for this fan curve + pub fn set_enable(&self, device: &mut Device) -> std::io::Result<()> { + let pwm_num: char = self.fan.into(); + let enable = if self.enabled { "1" } else { "2" }; + let enable_attr = format!("pwm{pwm_num}_enable"); device - .set_attribute_value(format!("pwm{pwm_num}_enable"), enable.to_string()) - .map_err(|e| error!("Failed to set pwm{pwm_num}_enable to {enable}: {e:?}")) + .set_attribute_value(&enable_attr, enable.to_string()) + .map_err(|e| error!("Failed to set {enable_attr} to {enable}: {e:?}")) .ok(); Ok(()) } diff --git a/rog-profiles/src/lib.rs b/rog-profiles/src/lib.rs index 51e91d88..cca3de71 100644 --- a/rog-profiles/src/lib.rs +++ b/rog-profiles/src/lib.rs @@ -181,15 +181,29 @@ impl FanCurveProfiles { PlatformProfile::Quiet | PlatformProfile::LowPower => &mut self.quiet, PlatformProfile::Custom => &mut self.custom, }; - for fan in fans.iter().filter(|f| !f.enabled) { - debug!("write_profile_curve_to_platform: writing profile:{profile}, {fan:?}"); + + // First write all curve data (pwm/temp values) for all fans + for fan in fans.iter() { + debug!("write_profile_curve_to_platform: writing curve data for profile:{profile}, {fan:?}"); fan.write_to_device(device)?; } - // Write enabled fans last because the kernel currently resets *all* if one is - // disabled + + // Then set enables: disabled fans first, then enabled fans last. + // This order is important because on some devices (e.g., ASUS Z13 2025) + // setting any pwm_enable to 2 (disabled) resets ALL fan enables. + for fan in fans.iter().filter(|f| !f.enabled) { + debug!( + "write_profile_curve_to_platform: disabling fan for profile:{profile}, {:?}", + fan.fan + ); + fan.set_enable(device)?; + } for fan in fans.iter().filter(|f| f.enabled) { - debug!("write_profile_curve_to_platform: writing profile:{profile}, {fan:?}"); - fan.write_to_device(device)?; + debug!( + "write_profile_curve_to_platform: enabling fan for profile:{profile}, {:?}", + fan.fan + ); + fan.set_enable(device)?; } Ok(()) }