Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions asusctl/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -668,7 +668,10 @@ fn handle_led_power_1_do_1866(
power: &LedPowerCommand1,
) -> Result<(), Box<dyn std::error::Error>> {
let mut states = Vec::new();
if power.keyboard {
// TUF exposes one keyboard zone; the generic 0x1866 command may expose
// separate keyboard and lightbar zones.
let is_tuf = aura.device_type()?.is_tuf_laptop();
if power.keyboard || (is_tuf && power.lightbar) {
states.push(AuraPowerState {
zone: PowerZones::Keyboard,
boot: power.boot.unwrap_or_default(),
Expand All @@ -677,7 +680,7 @@ fn handle_led_power_1_do_1866(
shutdown: false,
});
}
if power.lightbar {
if power.lightbar && !is_tuf {
states.push(AuraPowerState {
zone: PowerZones::Lightbar,
boot: power.boot.unwrap_or_default(),
Expand Down
21 changes: 20 additions & 1 deletion asusd/src/aura_laptop/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,16 @@ impl Aura {
} else {
config.brightness.into()
};
// These fields are derived during device discovery and deliberately
// excluded from the on-disk configuration. `read()` replaces the
// entire struct, so retain them when refreshing settings for sleep.
let led_type = config.led_type;
let support_data = config.support_data.clone();
let per_key_mode_active = config.per_key_mode_active;
config.read();
config.led_type = led_type;
config.support_data = support_data;
config.per_key_mode_active = per_key_mode_active;
config.brightness = bright.into();
config.write();
Ok(())
Expand Down Expand Up @@ -144,7 +153,17 @@ impl Aura {
if let Some(backlight) = &self.backlight {
// TODO: tuf bool array
let buf = config.enabled.to_bytes(config.led_type);
backlight.lock().await.set_kbd_rgb_state(&buf)?;
let backlight = backlight.lock().await;
// Some FA401UH firmware/kernel combinations expose brightness
// and RGB mode but not the optional power-state attribute.
// Power changes must not make the whole Aura interface fail.
if backlight.has_kbd_rgb_state() {
backlight.set_kbd_rgb_state(&buf)?;
} else {
log::debug!(
"TUF keyboard does not expose kbd_rgb_state; skipping power-state write"
);
}
}
} else if let Some(hid_raw) = &self.hid {
let hid_raw = hid_raw.lock().await;
Expand Down
82 changes: 52 additions & 30 deletions asusd/src/aura_laptop/trait_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,27 @@ impl AuraZbus {
pub async fn start_tasks(
mut self,
connection: &Connection,
// _signal_ctx: SignalEmitter<'static>,
path: OwnedObjectPath,
) -> Result<(), RogError> {
// let task = zbus.clone();
// let signal_ctx = signal_ctx.clone();
self.reload()
.await
.unwrap_or_else(|err| warn!("Controller error: {}", err));
let task = self.clone();
connection
.object_server()
.at(path.clone(), self)
.await
.map_err(|e| error!("Couldn't add server at path: {path}, {e:?}"))
.ok();
// TODO: skip this until we keep handles to tasks so they can be killed
// task.create_tasks(signal_ctx).await
// Subscribe to logind sleep/shutdown events. Without this call the
// Aura interface is available, but the keyboard controller never
// receives on_prepare_for_sleep notifications.
let signal_ctx = SignalEmitter::new(connection, AURA_ZBUS_PATH)?;
info!("Starting CtrlKbdLedTask system-event subscription");
task.create_tasks(signal_ctx).await?;
Comment thread
coderabbitai[bot] marked this conversation as resolved.
info!("Started CtrlKbdLedTask system-event subscription");
Ok(())
}
}
Expand Down Expand Up @@ -241,44 +246,61 @@ impl CtrlTask for AuraZbus {
}

async fn create_tasks(&self, _: SignalEmitter<'static>) -> Result<(), RogError> {
info!("Creating Aura system-event callbacks");
let inner1 = self.0.clone();
let inner3 = self.0.clone();
self.create_sys_event_tasks(
move |sleeping| {
let inner1 = inner1.clone();
// unwrap as we want to bomb out of the task
async move {
if !sleeping {
info!("CtrlKbdLedTask received prepare_for_sleep({sleeping})");
if sleeping {
// Re-write the user's configured power state right
// before suspend. The kernel patch re-asserts brightness
// and enables all power modes to ensure the sleep
// strobe works, but this overrides the user's "sleep
// backlight off" preference. By writing the actual
// user config here (after the kernel prepare callback
// has already run), we restore the user's intent while
// still allowing the kernel's brightness re-assertion
// to have set up the EC correctly for the strobe case.
let config = inner1.config.lock().await;
let sleep_enabled = config.enabled.states.iter()
.any(|s| s.zone == rog_aura::PowerZones::Keyboard && s.sleep);
drop(config);

if !sleep_enabled {
info!("CtrlKbdLedTask sleep: user disabled sleep backlight, re-writing power state");
let config = inner1.config.lock().await;
if let Err(e) = inner1.set_power_states(&config).await {
error!("CtrlKbdLedTask sleep power state rewrite: {e}");
}
} else {
info!("CtrlKbdLedTask sleep: sleep backlight enabled, no-op");
}
} else {
info!("CtrlKbdLedTask reloading brightness and modes");
let (brightness, led_type) = {
let config = inner1.config.lock().await;
(config.brightness.into(), config.led_type)
};
if let Some(backlight) = &inner1.backlight {
backlight
.lock()
.await
.set_brightness(inner1.config.lock().await.brightness.into())
.map_err(|e| {
error!("CtrlKbdLedTask: {e}");
e
})
.unwrap();
if let Err(e) = backlight.lock().await.set_brightness(brightness) {
error!("CtrlKbdLedTask wake brightness: {e}");
return;
}
}
let mut config = inner1.config.lock().await;
inner1
.write_current_config_mode(&mut config)
.await
.map_err(|e| {
error!("CtrlKbdLedTask: {e}");
e
})
.unwrap();
} else if sleeping {
inner1
.update_config()
.await
.map_err(|e| {
error!("CtrlKbdLedTask: {e}");
e
})
.unwrap();
if let Err(e) = inner1.write_current_config_mode(&mut config).await {
error!("CtrlKbdLedTask wake mode: {e}");
return;
}
if led_type.is_tuf_laptop()
&& let Err(e) = inner1.set_power_states(&config).await
{
error!("CtrlKbdLedTask wake power state: {e}");
}
}
}
},
Expand Down
19 changes: 13 additions & 6 deletions asusd/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -435,14 +435,21 @@ pub trait CtrlTask {
tokio::spawn({
let logind_manager = logind_manager.clone();
async move {
if let Ok(mut notif) = logind_manager.receive_prepare_for_sleep().await {
while let Some(event) = notif.next().await {
// blocks thread :|
if let Ok(args) = event.args() {
debug!("Doing on_prepare_for_sleep({})", args.start);
on_prepare_for_sleep(args.start).await;
match logind_manager.receive_prepare_for_sleep().await {
Ok(mut notif) => {
info!("Subscribed to logind PrepareForSleep");
while let Some(event) = notif.next().await {
// blocks thread :|
if let Ok(args) = event.args() {
debug!("Doing on_prepare_for_sleep({})", args.start);
on_prepare_for_sleep(args.start).await;
} else {
warn!("Failed to decode logind PrepareForSleep signal");
}
}
warn!("logind PrepareForSleep stream ended");
}
Err(err) => warn!("Could not subscribe to logind PrepareForSleep: {err}"),
}
}
});
Expand Down
9 changes: 9 additions & 0 deletions rog-aura/data/aura_support.ron
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
([
(
device_name: "FA401",
product_id: "",
layout_name: "fa507",
basic_modes: [Static, Breathe, Pulse],
basic_zones: [],
advanced_type: r#None,
power_zones: [Keyboard],
),
(
device_name: "FA506I",
product_id: "",
Expand Down
15 changes: 15 additions & 0 deletions rog-aura/src/keyboard/power.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,21 @@ mod test {
)
}

#[test]
fn tuf_power_bytes_include_boot_awake_and_sleep() {
let power = LaptopAuraPower {
states: vec![AuraPowerState {
zone: PowerZones::Keyboard,
boot: true,
awake: false,
sleep: true,
shutdown: false,
}],
};

assert_eq!(power.to_bytes(AuraDeviceType::LaptopKeyboardTuf), vec![1, 1, 0, 1, 1]);
}

#[test]
fn check_0x1866_control_bytes() {
let power = LaptopAuraPower {
Expand Down