Fluke/dbus refactor

This commit is contained in:
Luke Jones
2023-12-03 20:44:01 +00:00
parent f6e4cc0626
commit 0a69c23288
143 changed files with 5421 additions and 10343 deletions

View File

@@ -6,49 +6,14 @@ use log::{info, warn};
use rog_aura::advanced::{LedUsbPackets, UsbPackets};
use rog_aura::aura_detection::{LaptopLedData, ASUS_KEYBOARD_DEVICES};
use rog_aura::usb::{AuraDevice, LED_APPLY, LED_SET};
use rog_aura::{AuraEffect, AuraZone, Direction, LedBrightness, Speed, GRADIENT, LED_MSG_LEN};
use rog_aura::{AuraEffect, Direction, LedBrightness, Speed, GRADIENT, LED_MSG_LEN};
use rog_platform::hid_raw::HidRaw;
use rog_platform::keyboard_led::KeyboardLed;
use rog_platform::supported::LedSupportedFunctions;
use super::config::{AuraConfig, AuraPowerConfig};
use crate::error::RogError;
use crate::GetSupported;
impl GetSupported for CtrlKbdLed {
type A = LedSupportedFunctions;
fn get_supported() -> Self::A {
// let mode = <&str>::from(&<AuraModes>::from(*mode));
let laptop = LaptopLedData::get_data();
let mut prod_id = AuraDevice::Unknown;
for prod in ASUS_KEYBOARD_DEVICES {
if HidRaw::new(prod.into()).is_ok() {
prod_id = prod;
break;
}
}
let rgb = KeyboardLed::new();
if let Ok(p) = rgb.as_ref() {
if p.has_kbd_rgb_mode() {
prod_id = AuraDevice::Tuf;
}
}
LedSupportedFunctions {
dev_id: prod_id,
brightness: rgb.is_ok(),
basic_modes: laptop.basic_modes,
basic_zones: laptop.basic_zones,
advanced_type: laptop.advanced_type.into(),
power_zones: laptop.power_zones,
}
}
}
#[derive(Debug, PartialEq, Eq)]
#[derive(Debug)]
pub enum LEDNode {
KbdLed(KeyboardLed),
Rog(HidRaw),
@@ -59,9 +24,8 @@ pub struct CtrlKbdLed {
// TODO: config stores the keyboard type as an AuraPower, use or update this
pub led_prod: AuraDevice,
pub led_node: LEDNode,
pub kd_brightness: KeyboardLed,
pub sysfs_node: KeyboardLed,
pub supported_modes: LaptopLedData,
pub flip_effect_write: bool,
pub per_key_mode_active: bool,
pub config: AuraConfig,
}
@@ -145,50 +109,15 @@ impl CtrlKbdLed {
let ctrl = CtrlKbdLed {
led_prod,
led_node, // on TUF this is the same as rgb_led / kd_brightness
kd_brightness: rgb_led, // If was none then we already returned above
led_node, // on TUF this is the same as rgb_led / kd_brightness
sysfs_node: rgb_led, // If was none then we already returned above
supported_modes,
flip_effect_write: false,
per_key_mode_active: false,
config: config_loaded,
};
Ok(ctrl)
}
pub(super) fn get_brightness(&self) -> Result<u8, RogError> {
self.kd_brightness
.get_brightness()
.map_err(RogError::Platform)
}
pub(super) fn set_brightness(&self, brightness: LedBrightness) -> Result<(), RogError> {
self.kd_brightness
.set_brightness(brightness as u8)
.map_err(RogError::Platform)
}
pub fn next_brightness(&mut self) -> Result<(), RogError> {
let mut bright = (self.config.brightness as u32) + 1;
if bright > 3 {
bright = 0;
}
self.config.brightness = <LedBrightness>::from(bright);
self.config.write();
self.set_brightness(self.config.brightness)
}
pub fn prev_brightness(&mut self) -> Result<(), RogError> {
let mut bright = self.config.brightness as u32;
if bright == 0 {
bright = 3;
} else {
bright -= 1;
}
self.config.brightness = <LedBrightness>::from(bright);
self.config.write();
self.set_brightness(self.config.brightness)
}
/// Set combination state for boot animation/sleep animation/all leds/keys
/// leds/side leds LED active
pub(super) fn set_power_states(&mut self) -> Result<(), RogError> {
@@ -209,29 +138,6 @@ impl CtrlKbdLed {
Ok(())
}
/// 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 stored and config written to disk.
pub(crate) fn set_effect(&mut self, effect: AuraEffect) -> Result<(), RogError> {
if !self.supported_modes.basic_modes.contains(&effect.mode)
|| effect.zone != AuraZone::None
&& !self.supported_modes.basic_zones.contains(&effect.zone)
{
return Err(RogError::AuraEffectNotSupported);
}
self.write_mode(&effect)?;
self.config.read(); // refresh config if successful
self.config.set_builtin(effect);
if self.config.brightness == LedBrightness::Off {
self.config.brightness = LedBrightness::Med;
}
self.config.write();
self.set_brightness(self.config.brightness)?;
Ok(())
}
/// Write an effect block. This is for per-key, but can be repurposed to
/// write the raw factory mode packets - when doing this it is expected that
/// only the first `Vec` (`effect[0]`) is valid.
@@ -271,47 +177,11 @@ impl CtrlKbdLed {
tuf.set_kbd_rgb_mode(&[0, 0, r, g, b, 0])?;
}
}
self.flip_effect_write = !self.flip_effect_write;
}
Ok(())
}
pub(super) fn toggle_mode(&mut self, reverse: bool) -> Result<(), RogError> {
let current = self.config.current_mode;
if let Some(idx) = self
.supported_modes
.basic_modes
.iter()
.position(|v| *v == current)
{
let mut idx = idx;
// goes past end of array
if reverse {
if idx == 0 {
idx = self.supported_modes.basic_modes.len() - 1;
} else {
idx -= 1;
}
} else {
idx += 1;
if idx == self.supported_modes.basic_modes.len() {
idx = 0;
}
}
let next = self.supported_modes.basic_modes[idx];
self.config.read();
// if self.config.builtins.contains_key(&next) {
self.config.current_mode = next;
self.write_current_config_mode()?;
// }
self.config.write();
}
Ok(())
}
fn write_mode(&mut self, mode: &AuraEffect) -> Result<(), RogError> {
pub fn write_mode(&mut self, mode: &AuraEffect) -> Result<(), RogError> {
if let LEDNode::KbdLed(platform) = &self.led_node {
let buf = [
1,
@@ -404,82 +274,13 @@ impl CtrlKbdLed {
mod tests {
use rog_aura::aura_detection::{LaptopLedData, PowerZones};
use rog_aura::usb::AuraDevice;
use rog_aura::{AuraEffect, AuraModeNum, AuraZone, Colour};
use rog_aura::{AuraModeNum, AuraZone};
use rog_platform::keyboard_led::KeyboardLed;
use super::CtrlKbdLed;
use crate::ctrl_aura::config::AuraConfig;
use crate::ctrl_aura::controller::LEDNode;
#[test]
// #[ignore = "Must be manually run due to detection stage"]
fn check_set_mode_errors() {
// Checking to ensure set_mode errors when unsupported modes are tried
let config = AuraConfig::from_default_support(AuraDevice::X19b6, &LaptopLedData::default());
let supported_modes = LaptopLedData {
board_name: String::new(),
layout_name: "ga401".to_owned(),
basic_modes: vec![AuraModeNum::Static],
basic_zones: vec![],
advanced_type: rog_aura::AdvancedAuraType::None,
power_zones: vec![PowerZones::Keyboard, PowerZones::RearGlow],
};
let mut controller = CtrlKbdLed {
led_prod: AuraDevice::X19b6,
led_node: LEDNode::None,
kd_brightness: KeyboardLed::default(),
supported_modes,
flip_effect_write: false,
per_key_mode_active: false,
config,
};
let mut effect = AuraEffect {
colour1: Colour {
r: 0xff,
g: 0x00,
b: 0xff,
},
zone: AuraZone::None,
..Default::default()
};
// This error comes from write_bytes because we don't have a keyboard node
// stored
assert_eq!(
controller
.set_effect(effect.clone())
.unwrap_err()
.to_string(),
"No supported Aura keyboard"
);
effect.mode = AuraModeNum::Laser;
assert_eq!(
controller
.set_effect(effect.clone())
.unwrap_err()
.to_string(),
"Aura effect not supported"
);
effect.mode = AuraModeNum::Static;
effect.zone = AuraZone::Key2;
assert_eq!(
controller
.set_effect(effect.clone())
.unwrap_err()
.to_string(),
"Aura effect not supported"
);
controller.supported_modes.basic_zones.push(AuraZone::Key2);
assert_eq!(
controller.set_effect(effect).unwrap_err().to_string(),
"No supported Aura keyboard"
);
}
#[test]
fn create_multizone_if_no_config() {
// Checking to ensure set_mode errors when unsupported modes are tried
@@ -495,9 +296,8 @@ mod tests {
let mut controller = CtrlKbdLed {
led_prod: AuraDevice::X19b6,
led_node: LEDNode::None,
kd_brightness: KeyboardLed::default(),
sysfs_node: KeyboardLed::default(),
supported_modes,
flip_effect_write: false,
per_key_mode_active: false,
config,
};
@@ -534,9 +334,8 @@ mod tests {
let mut controller = CtrlKbdLed {
led_prod: AuraDevice::X19b6,
led_node: LEDNode::None,
kd_brightness: KeyboardLed::default(),
sysfs_node: KeyboardLed::default(),
supported_modes,
flip_effect_write: false,
per_key_mode_active: false,
config,
};

View File

@@ -6,34 +6,36 @@ use config_traits::StdConfig;
use log::{debug, error, info, warn};
use rog_aura::advanced::UsbPackets;
use rog_aura::usb::{AuraDevice, AuraPowerDev};
use rog_aura::{AuraEffect, AuraModeNum, LedBrightness};
use rog_aura::{AuraEffect, AuraModeNum, AuraZone, LedBrightness};
use zbus::export::futures_util::lock::{Mutex, MutexGuard};
use zbus::export::futures_util::StreamExt;
use zbus::fdo::Error as ZbErr;
use zbus::{dbus_interface, Connection, SignalContext};
use super::controller::CtrlKbdLed;
use crate::error::RogError;
use crate::CtrlTask;
pub(super) const ZBUS_PATH: &str = "/org/asuslinux/Aura";
pub const AURA_ZBUS_NAME: &str = "Aura";
pub const AURA_ZBUS_PATH: &str = "/org/asuslinux/Aura";
#[derive(Clone)]
pub struct CtrlKbdLedZbus(pub Arc<Mutex<CtrlKbdLed>>);
pub struct CtrlAuraZbus(pub Arc<Mutex<CtrlKbdLed>>);
impl CtrlKbdLedZbus {
impl CtrlAuraZbus {
fn update_config(lock: &mut CtrlKbdLed) -> Result<(), RogError> {
let bright = lock.kd_brightness.get_brightness()?;
let bright = lock.sysfs_node.get_brightness()?;
lock.config.read();
lock.config.brightness = (bright as u32).into();
lock.config.brightness = bright.into();
lock.config.write();
Ok(())
}
}
#[async_trait]
impl crate::ZbusRun for CtrlKbdLedZbus {
impl crate::ZbusRun for CtrlAuraZbus {
async fn add_to_server(self, server: &mut Connection) {
Self::add_to_server_helper(self, ZBUS_PATH, server).await;
Self::add_to_server_helper(self, AURA_ZBUS_PATH, server).await;
}
}
@@ -41,25 +43,130 @@ impl crate::ZbusRun for CtrlKbdLedZbus {
///
/// LED commands are split between Brightness, Modes, Per-Key
#[dbus_interface(name = "org.asuslinux.Daemon")]
impl CtrlKbdLedZbus {
/// Set the keyboard brightness level (0-3)
async fn set_brightness(&mut self, brightness: LedBrightness) {
impl CtrlAuraZbus {
/// Return the device type for this Aura keyboard
#[dbus_interface(property)]
async fn device_type(&self) -> AuraDevice {
let ctrl = self.0.lock().await;
ctrl.set_brightness(brightness)
.map_err(|err| warn!("{}", err))
.ok();
ctrl.led_prod
}
/// Return the current LED brightness
#[dbus_interface(property)]
async fn brightness(&self) -> Result<LedBrightness, ZbErr> {
let ctrl = self.0.lock().await;
Ok(ctrl.sysfs_node.get_brightness().map(|n| n.into())?)
}
/// Set the keyboard brightness level (0-3)
#[dbus_interface(property)]
async fn set_brightness(&mut self, brightness: LedBrightness) -> Result<(), ZbErr> {
let ctrl = self.0.lock().await;
Ok(ctrl.sysfs_node.set_brightness(brightness.into())?)
}
/// Total levels of brightness available
#[dbus_interface(property)]
async fn supported_brightness(&self) -> Vec<LedBrightness> {
vec![
LedBrightness::Off,
LedBrightness::Low,
LedBrightness::Med,
LedBrightness::High,
]
}
/// The total available modes
#[dbus_interface(property)]
async fn supported_modes(&self) -> Result<Vec<AuraModeNum>, ZbErr> {
let ctrl = self.0.lock().await;
Ok(ctrl.config.builtins.keys().cloned().collect())
}
/// The current mode data
#[dbus_interface(property)]
async fn led_mode(&self) -> Result<AuraModeNum, ZbErr> {
let ctrl = self.0.lock().await;
Ok(ctrl.config.current_mode)
}
/// 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 stored and config written to disk.
#[dbus_interface(property)]
async fn set_led_mode(&mut self, num: AuraModeNum) -> Result<(), ZbErr> {
let mut ctrl = self.0.lock().await;
ctrl.config.current_mode = num;
ctrl.write_current_config_mode()?;
if ctrl.config.brightness == LedBrightness::Off {
ctrl.config.brightness = LedBrightness::Med;
}
ctrl.sysfs_node
.set_brightness(ctrl.config.brightness.into())?;
ctrl.config.write();
Ok(())
}
/// The current mode data
#[dbus_interface(property)]
async fn led_mode_data(&self) -> Result<AuraEffect, ZbErr> {
let ctrl = self.0.lock().await;
let mode = ctrl.config.current_mode;
match ctrl.config.builtins.get(&mode) {
Some(effect) => Ok(effect.clone()),
None => Err(ZbErr::Failed("Could not get the current effect".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 stored and config written to disk.
#[dbus_interface(property)]
async fn set_led_mode_data(&mut self, effect: AuraEffect) -> Result<(), ZbErr> {
let mut ctrl = self.0.lock().await;
if !ctrl.supported_modes.basic_modes.contains(&effect.mode)
|| effect.zone != AuraZone::None
&& !ctrl.supported_modes.basic_zones.contains(&effect.zone)
{
return Err(ZbErr::NotSupported(format!(
"The Aura effect is not supported: {effect:?}"
)));
}
ctrl.write_mode(&effect)?;
if ctrl.config.brightness == LedBrightness::Off {
ctrl.config.brightness = LedBrightness::Med;
}
ctrl.sysfs_node
.set_brightness(ctrl.config.brightness.into())?;
ctrl.config.set_builtin(effect);
ctrl.config.write();
Ok(())
}
/// Get the data set for every mode available
async fn all_mode_data(&self) -> BTreeMap<AuraModeNum, AuraEffect> {
let ctrl = self.0.lock().await;
ctrl.config.builtins.clone()
}
// As property doesn't work for AuraPowerDev (complexity of serialization?)
#[dbus_interface(property)]
async fn led_power(&self) -> AuraPowerDev {
let ctrl = self.0.lock().await;
AuraPowerDev::from(&ctrl.config.enabled)
}
/// Set a variety of states, input is array of enum.
/// `enabled` sets if the sent array should be disabled or enabled
///
/// For Modern ROG devices the "enabled" flag is ignored.
async fn set_led_power(
&mut self,
#[zbus(signal_context)] ctxt: SignalContext<'_>,
options: AuraPowerDev,
enabled: bool,
) -> zbus::fdo::Result<()> {
#[dbus_interface(property)]
async fn set_led_power(&mut self, options: (AuraPowerDev, bool)) -> Result<(), ZbErr> {
let enabled = options.1;
let options = options.0;
let mut ctrl = self.0.lock().await;
for p in options.tuf {
ctrl.config.enabled.set_tuf(p, enabled);
@@ -68,158 +175,27 @@ impl CtrlKbdLedZbus {
ctrl.config.enabled.set_0x1866(p, enabled);
}
ctrl.config.enabled.set_0x19b6(options.rog);
ctrl.config.write();
ctrl.set_power_states().map_err(|e| {
Ok(ctrl.set_power_states().map_err(|e| {
warn!("{}", e);
e
})?;
Self::notify_power_states(&ctxt, &AuraPowerDev::from(&ctrl.config.enabled))
.await
.unwrap_or_else(|err| warn!("{}", err));
Ok(())
}
async fn set_led_mode(
&mut self,
#[zbus(signal_context)] ctxt: SignalContext<'_>,
effect: AuraEffect,
) -> zbus::fdo::Result<()> {
let mut ctrl = self.0.lock().await;
ctrl.set_effect(effect).map_err(|e| {
warn!("{}", e);
e
})?;
ctrl.set_brightness(ctrl.config.brightness).map_err(|e| {
warn!("{}", e);
e
})?;
if let Some(mode) = ctrl.config.builtins.get(&ctrl.config.current_mode) {
Self::notify_led(&ctxt, mode.clone())
.await
.unwrap_or_else(|err| warn!("{}", err));
}
Ok(())
}
async fn next_led_mode(
&self,
#[zbus(signal_context)] ctxt: SignalContext<'_>,
) -> zbus::fdo::Result<()> {
let mut ctrl = self.0.lock().await;
ctrl.toggle_mode(false).map_err(|e| {
warn!("{}", e);
e
})?;
if let Some(mode) = ctrl.config.builtins.get(&ctrl.config.current_mode) {
Self::notify_led(&ctxt, mode.clone())
.await
.unwrap_or_else(|err| warn!("{}", err));
}
Ok(())
}
async fn prev_led_mode(
&self,
#[zbus(signal_context)] ctxt: SignalContext<'_>,
) -> zbus::fdo::Result<()> {
let mut ctrl = self.0.lock().await;
ctrl.toggle_mode(true).map_err(|e| {
warn!("{}", e);
e
})?;
if let Some(mode) = ctrl.config.builtins.get(&ctrl.config.current_mode) {
Self::notify_led(&ctxt, mode.clone())
.await
.unwrap_or_else(|err| warn!("{}", err));
}
Ok(())
}
async fn next_led_brightness(&self) -> zbus::fdo::Result<()> {
let mut ctrl = self.0.lock().await;
ctrl.next_brightness().map_err(|e| {
warn!("{}", e);
e
})?;
Ok(())
}
async fn prev_led_brightness(&self) -> zbus::fdo::Result<()> {
let mut ctrl = self.0.lock().await;
ctrl.prev_brightness().map_err(|e| {
warn!("{}", e);
e
})?;
Ok(())
}
/// Return the device type for this Aura keyboard
async fn device_type(&self) -> AuraDevice {
let ctrl = self.0.lock().await;
ctrl.led_prod
}
// As property doesn't work for AuraPowerDev (complexity of serialization?)
// #[dbus_interface(property)]
async fn led_power(&self) -> AuraPowerDev {
let ctrl = self.0.lock().await;
AuraPowerDev::from(&ctrl.config.enabled)
}
/// Return the current mode data
async fn led_mode(&self) -> AuraModeNum {
let ctrl = self.0.lock().await;
ctrl.config.current_mode
}
/// Return a list of available modes
async fn led_modes(&self) -> BTreeMap<AuraModeNum, AuraEffect> {
let ctrl = self.0.lock().await;
ctrl.config.builtins.clone()
})?)
}
/// On machine that have some form of either per-key keyboard or per-zone
/// this can be used to write custom effects over dbus. The input is a
/// nested `Vec<Vec<8>>` where `Vec<u8>` is a raw USB packet
async fn direct_addressing_raw(&self, data: UsbPackets) -> zbus::fdo::Result<()> {
async fn direct_addressing_raw(&self, data: UsbPackets) -> Result<(), ZbErr> {
let mut ctrl = self.0.lock().await;
ctrl.write_effect_block(&data)?;
Ok(())
}
/// Return the current LED brightness
#[dbus_interface(property)]
async fn led_brightness(&self) -> i8 {
let ctrl = self.0.lock().await;
ctrl.get_brightness().map(|n| n as i8).unwrap_or(-1)
}
#[dbus_interface(signal)]
async fn notify_led(signal_ctxt: &SignalContext<'_>, data: AuraEffect) -> zbus::Result<()>;
#[dbus_interface(signal)]
async fn notify_power_states(
signal_ctxt: &SignalContext<'_>,
data: &AuraPowerDev,
) -> zbus::Result<()>;
}
#[async_trait]
impl CtrlTask for CtrlKbdLedZbus {
impl CtrlTask for CtrlAuraZbus {
fn zbus_path() -> &'static str {
ZBUS_PATH
AURA_ZBUS_PATH
}
async fn create_tasks(&self, _: SignalContext<'static>) -> Result<(), RogError> {
@@ -227,7 +203,8 @@ impl CtrlTask for CtrlKbdLedZbus {
// If waking up
if !start {
info!("CtrlKbdLedTask reloading brightness and modes");
lock.set_brightness(lock.config.brightness)
lock.sysfs_node
.set_brightness(lock.config.brightness.into())
.map_err(|e| error!("CtrlKbdLedTask: {e}"))
.ok();
lock.write_current_config_mode()
@@ -270,7 +247,7 @@ impl CtrlTask for CtrlKbdLedZbus {
let ctrl2 = self.0.clone();
let ctrl = self.0.lock().await;
let watch = ctrl.kd_brightness.monitor_brightness()?;
let watch = ctrl.sysfs_node.monitor_brightness()?;
tokio::spawn(async move {
let mut buffer = [0; 32];
watch
@@ -289,7 +266,7 @@ impl CtrlTask for CtrlKbdLedZbus {
}
#[async_trait]
impl crate::Reloadable for CtrlKbdLedZbus {
impl crate::Reloadable for CtrlAuraZbus {
async fn reload(&mut self) -> Result<(), RogError> {
let mut ctrl = self.0.lock().await;
debug!("CtrlKbdLedZbus: reloading keyboard mode");