Initial pass of async task sync in aura

This commit is contained in:
Luke D. Jones
2024-03-23 23:15:38 +13:00
parent ac605cbc00
commit 4b34ab83fb
5 changed files with 126 additions and 87 deletions

View File

@@ -18,6 +18,12 @@ pub enum AuraPowerConfig {
AuraDevRog2(AuraPower), AuraDevRog2(AuraPower),
} }
impl Default for AuraPowerConfig {
fn default() -> Self {
Self::AuraDevTuf(HashSet::default())
}
}
impl AuraPowerConfig { impl AuraPowerConfig {
/// Invalid for TUF laptops /// Invalid for TUF laptops
pub fn to_bytes(control: &Self) -> [u8; 4] { pub fn to_bytes(control: &Self) -> [u8; 4] {
@@ -101,7 +107,7 @@ impl From<&AuraPowerConfig> for AuraPowerDev {
} }
} }
#[derive(Deserialize, Serialize, Debug, Clone)] #[derive(Deserialize, Serialize, Default, Debug, Clone)]
// #[serde(default)] // #[serde(default)]
pub struct AuraConfig { pub struct AuraConfig {
pub config_name: String, pub config_name: String,

View File

@@ -62,7 +62,7 @@ impl CtrlKbdLed {
pub fn find_all(data: &LaptopLedData) -> Result<Vec<Self>, RogError> { pub fn find_all(data: &LaptopLedData) -> Result<Vec<Self>, RogError> {
info!("Searching for all Aura devices"); info!("Searching for all Aura devices");
let mut devices = Vec::new(); let mut devices = Vec::new();
let mut found = HashSet::new(); let mut found = HashSet::new(); // track and ensure we use only one hidraw per prod_id
let mut enumerator = udev::Enumerator::new().map_err(|err| { let mut enumerator = udev::Enumerator::new().map_err(|err| {
warn!("{}", err); warn!("{}", err);
@@ -92,13 +92,14 @@ impl CtrlKbdLed {
} }
// Device is something like 002, while its parent is the MCU // Device is something like 002, while its parent is the MCU
// Think of it like the device is an endpoint of the USB device attached // Think of it like the device is an endpoint of the USB device attached
let mut aura_dev = AuraDevice::Unknown;
if let Some(usb_id) = usb_device.attribute_value("idProduct") { if let Some(usb_id) = usb_device.attribute_value("idProduct") {
let prod_id = AuraDevice::from(usb_id.to_str().unwrap()); aura_dev = AuraDevice::from(usb_id.to_str().unwrap());
if prod_id == AuraDevice::Unknown || found.contains(&prod_id) { if aura_dev == AuraDevice::Unknown || found.contains(&aura_dev) {
log::debug!("Unknown or invalid device: {usb_id:?}, skipping"); log::debug!("Unknown or invalid device: {usb_id:?}, skipping");
continue; continue;
} }
found.insert(prod_id); found.insert(aura_dev);
} }
let dev_node = if let Some(dev_node) = usb_device.devnode() { let dev_node = if let Some(dev_node) = usb_device.devnode() {
@@ -110,7 +111,8 @@ impl CtrlKbdLed {
info!("AuraControl found device at: {:?}", dev_node); info!("AuraControl found device at: {:?}", dev_node);
let dbus_path = dbus_path_for_dev(&usb_device).unwrap_or_default(); let dbus_path = dbus_path_for_dev(&usb_device).unwrap_or_default();
let dev = HidRaw::from_device(end_point)?; let dev = HidRaw::from_device(end_point)?;
let dev = Self::from_hidraw(dev, dbus_path, data)?; let mut dev = Self::from_hidraw(dev, dbus_path, data)?;
dev.config = Self::init_config(aura_dev, data);
devices.push(dev); devices.push(dev);
} }
} }
@@ -119,6 +121,9 @@ impl CtrlKbdLed {
Ok(devices) Ok(devices)
} }
/// The generated data from this function has a default config. This config
/// should be overwritten. The reason for the default config is because
/// of async issues between this and udev/hidraw
pub fn from_hidraw( pub fn from_hidraw(
device: HidRaw, device: HidRaw,
dbus_path: OwnedObjectPath, dbus_path: OwnedObjectPath,
@@ -132,20 +137,20 @@ impl CtrlKbdLed {
} }
// New loads data from the DB also // New loads data from the DB also
let config = Self::init_config(prod_id, data); // let config = Self::init_config(prod_id, data);
let ctrl = CtrlKbdLed { let ctrl = CtrlKbdLed {
led_prod: prod_id, led_prod: prod_id,
led_node: LEDNode::Rog(rgb_led, device), led_node: LEDNode::Rog(rgb_led, device),
supported_data: data.clone(), supported_data: data.clone(),
per_key_mode_active: false, per_key_mode_active: false,
config, config: AuraConfig::default(),
dbus_path, dbus_path,
}; };
Ok(ctrl) Ok(ctrl)
} }
fn init_config(prod_id: AuraDevice, supported_basic_modes: &LaptopLedData) -> AuraConfig { pub fn init_config(prod_id: AuraDevice, supported_basic_modes: &LaptopLedData) -> AuraConfig {
// New loads data from the DB also // New loads data from the DB also
let mut config_init = AuraConfig::new_with(prod_id); let mut config_init = AuraConfig::new_with(prod_id);
// config_init.set_filename(prod_id); // config_init.set_filename(prod_id);

View File

@@ -4,7 +4,7 @@
// - Add it to Zbus server // - Add it to Zbus server
// - If udev sees device removed then remove the zbus path // - If udev sees device removed then remove the zbus path
use std::collections::HashMap; use std::collections::HashSet;
use std::sync::Arc; use std::sync::Arc;
use log::{debug, error, info, warn}; use log::{debug, error, info, warn};
@@ -26,20 +26,19 @@ use crate::{CtrlTask, Reloadable};
pub struct AuraManager { pub struct AuraManager {
_connection: Connection, _connection: Connection,
interfaces: Arc<Mutex<HashMap<AuraDevice, OwnedObjectPath>>>,
} }
impl AuraManager { impl AuraManager {
pub async fn new(mut connection: Connection) -> Result<Self, RogError> { pub async fn new(mut connection: Connection) -> Result<Self, RogError> {
let conn_copy = connection.clone(); let conn_copy = connection.clone();
let data = LaptopLedData::get_data(); let data = LaptopLedData::get_data();
let mut interfaces = HashMap::new(); let mut interfaces = HashSet::new();
// Do the initial keyboard detection: // Do the initial keyboard detection:
let all = CtrlKbdLed::find_all(&data)?; let all = CtrlKbdLed::find_all(&data)?;
for ctrl in all { for ctrl in all {
let path = ctrl.dbus_path.clone(); let path = ctrl.dbus_path.clone();
interfaces.insert(ctrl.led_prod, path.clone()); // ensure we record the initial stuff interfaces.insert(path.clone()); // ensure we record the initial stuff
let sig_ctx = CtrlAuraZbus::signal_context(&connection)?; let sig_ctx = CtrlAuraZbus::signal_context(&connection)?;
let sig_ctx2 = sig_ctx.clone(); let sig_ctx2 = sig_ctx.clone();
let zbus = CtrlAuraZbus::new(ctrl, sig_ctx); let zbus = CtrlAuraZbus::new(ctrl, sig_ctx);
@@ -51,11 +50,10 @@ impl AuraManager {
let manager = Self { let manager = Self {
_connection: connection, _connection: connection,
interfaces: Arc::new(Mutex::new(interfaces)),
}; };
let interfaces_copy = manager.interfaces.clone();
// detect all plugged in aura devices (eventually) // detect all plugged in aura devices (eventually)
let interfaces = Arc::new(Mutex::new(interfaces));
tokio::spawn(async move { tokio::spawn(async move {
let mut monitor = MonitorBuilder::new()?.match_subsystem("hidraw")?.listen()?; let mut monitor = MonitorBuilder::new()?.match_subsystem("hidraw")?.listen()?;
let mut poll = Poll::new()?; let mut poll = Poll::new()?;
@@ -64,8 +62,13 @@ impl AuraManager {
.register(&mut monitor, Token(0), Interest::READABLE)?; .register(&mut monitor, Token(0), Interest::READABLE)?;
loop { loop {
poll.poll(&mut events, None).unwrap(); if poll.poll(&mut events, None).is_err() {
continue;
}
for event in monitor.iter() { for event in monitor.iter() {
if event.parent_with_subsystem("hidraw").is_err() {
continue;
}
if let Some(parent) = if let Some(parent) =
event.parent_with_subsystem_devtype("usb", "usb_device")? event.parent_with_subsystem_devtype("usb", "usb_device")?
{ {
@@ -75,51 +78,62 @@ impl AuraManager {
continue; continue;
}; };
let path = if let Some(path) = dbus_path_for_dev(&parent) {
path
} else {
continue;
};
if action == "remove" { if action == "remove" {
if let Some(id_product) = parent.attribute_value("idProduct") { dbg!("REMOVING");
let id_product = AuraDevice::from(id_product.to_str().unwrap()); if let Some(_) = parent.attribute_value("idProduct") {
let interfaces_copy = interfaces_copy.clone(); info!("AuraManager removing: {path:?}");
let conn_copy = conn_copy.clone(); let conn_copy = conn_copy.clone();
let interfaces_copy = interfaces.clone();
tokio::spawn(async move { tokio::spawn(async move {
let mut interfaces = interfaces_copy.lock().await; let mut interfaces = interfaces_copy.lock().await;
if let Some(path) = interfaces.remove(&id_product) { let res = conn_copy
info!("AuraManager removing: {path:?}"); .object_server()
let res = conn_copy .remove::<CtrlAuraZbus, _>(&path)
.object_server() .await
.remove::<CtrlAuraZbus, _>(&path) .map_err(|e| {
.await error!("Failed to remove {path:?}, {e:?}");
.map_err(|e| { e
error!("Failed to remove {path:?}, {e:?}"); })?;
e info!("AuraManager removed: {path:?}, {res}");
})?; interfaces.remove(&path);
info!("AuraManager removed: {path:?}, {res}"); debug!("Removed {path:?}");
}
Ok::<(), RogError>(()) Ok::<(), RogError>(())
}); });
} }
} } else if action == "add" {
dbg!("ADDING");
let id_product = let id_product =
if let Some(id_product) = parent.attribute_value("idProduct") { if let Some(id_product) = parent.attribute_value("idProduct") {
id_product.to_string_lossy().to_string() id_product.to_string_lossy().to_string()
} else { } else {
continue; continue;
}; };
if let Some(p2) = event.parent() { if let Some(p2) = event.parent() {
if let Some(driver) = p2.driver() { if let Some(driver) = p2.driver() {
// There is a tree of devices added so filter by driver // There is a tree of devices added so filter by driver
if driver != "asus" { if driver != "asus" {
continue;
}
} else {
continue; continue;
} }
} else {
continue;
} }
}
// try conversion to known idProduct // try conversion to known idProduct
let aura_device = AuraDevice::from(id_product.as_str()); let aura_device = AuraDevice::from(id_product.as_str());
if aura_device != AuraDevice::Unknown { if aura_device != AuraDevice::Unknown {
if action == "add" { let path = if let Some(path) = dbus_path_for_dev(&parent) {
path
} else {
continue;
};
let dev_node = if let Some(dev_node) = event.devnode() { let dev_node = if let Some(dev_node) = event.devnode() {
dev_node dev_node
} else { } else {
@@ -129,26 +143,31 @@ impl AuraManager {
if let Ok(raw) = HidRaw::from_device(event.device()) if let Ok(raw) = HidRaw::from_device(event.device())
.map_err(|e| error!("device path error: {e:?}")) .map_err(|e| error!("device path error: {e:?}"))
{ {
let path = if let Some(path) = dbus_path_for_dev(&parent) { // bah... shitty clone TODO: fix
path let data_clone = data.clone();
} else { if let Ok(mut ctrl) =
continue;
};
if let Ok(ctrl) =
CtrlKbdLed::from_hidraw(raw, path.clone(), &data) CtrlKbdLed::from_hidraw(raw, path.clone(), &data)
{ {
info!("AuraManager found device at: {:?}", dev_node); info!(
"AuraManager found device at: {dev_node:?}, {path:?}"
);
let mut conn_copy = conn_copy.clone(); let mut conn_copy = conn_copy.clone();
let interfaces_copy = interfaces_copy.clone(); let interfaces_copy = interfaces.clone();
// //
tokio::spawn(async move { tokio::spawn(async move {
let mut interfaces = interfaces_copy.lock().await; let mut interfaces = interfaces_copy.lock().await;
interfaces.insert(aura_device, path.clone()); if interfaces.contains(&path) {
debug!("Already a ctrl at {path:?}");
return Ok(());
}
debug!("Starting Aura at {path}");
interfaces.insert(path.clone());
let sig_ctx = CtrlAuraZbus::signal_context(&conn_copy)?; let sig_ctx = CtrlAuraZbus::signal_context(&conn_copy)?;
ctrl.config =
CtrlKbdLed::init_config(aura_device, &data_clone);
let zbus = CtrlAuraZbus::new(ctrl, sig_ctx); let zbus = CtrlAuraZbus::new(ctrl, sig_ctx);
// Now add it to device list // Now add it to device list
let sig_ctx = CtrlAuraZbus::signal_context(&conn_copy)?; let sig_ctx = CtrlAuraZbus::signal_context(&conn_copy)?;
debug!("Starting Aura at {path}");
start_tasks(zbus, &mut conn_copy, sig_ctx, &path) start_tasks(zbus, &mut conn_copy, sig_ctx, &path)
.await?; .await?;
Ok::<(), RogError>(()) Ok::<(), RogError>(())
@@ -156,9 +175,9 @@ impl AuraManager {
// MonitorSocket // MonitorSocket
} }
} }
} else {
warn!("idProduct:{id_product:?} is unknown, not using")
} }
} else {
warn!("idProduct:{id_product:?} is unknown, not using")
} }
} }
} }

View File

@@ -210,23 +210,29 @@ impl CtrlTask for CtrlAuraZbus {
} }
async fn create_tasks(&self, _: SignalContext<'static>) -> Result<(), RogError> { async fn create_tasks(&self, _: SignalContext<'static>) -> Result<(), RogError> {
let load_save = |start: bool, mut lock: MutexGuard<'_, CtrlKbdLed>| { let load_save =
// If waking up |start: bool, mut lock: MutexGuard<'_, CtrlKbdLed>| -> Result<(), RogError> {
if !start { // If waking up
info!("CtrlKbdLedTask reloading brightness and modes"); if !start {
lock.led_node info!("CtrlKbdLedTask reloading brightness and modes");
.set_brightness(lock.config.brightness.into()) lock.led_node
.map_err(|e| error!("CtrlKbdLedTask: {e}")) .set_brightness(lock.config.brightness.into())
.ok(); .map_err(|e| {
lock.write_current_config_mode() error!("CtrlKbdLedTask: {e}");
.map_err(|e| error!("CtrlKbdLedTask: {e}")) e
.ok(); })?;
} else if start { lock.write_current_config_mode().map_err(|e| {
Self::update_config(&mut lock) error!("CtrlKbdLedTask: {e}");
.map_err(|e| error!("CtrlKbdLedTask: {e}")) e
.ok(); })?;
} } else if start {
}; Self::update_config(&mut lock).map_err(|e| {
error!("CtrlKbdLedTask: {e}");
e
})?;
}
Ok(())
};
let inner1 = self.0.clone(); let inner1 = self.0.clone();
let inner3 = self.0.clone(); let inner3 = self.0.clone();
@@ -235,14 +241,16 @@ impl CtrlTask for CtrlAuraZbus {
let inner1 = inner1.clone(); let inner1 = inner1.clone();
async move { async move {
let lock = inner1.lock().await; let lock = inner1.lock().await;
load_save(sleeping, lock); load_save(sleeping, lock).unwrap(); // unwrap as we want to
// bomb out of the task
} }
}, },
move |_shutting_down| { move |_shutting_down| {
let inner3 = inner3.clone(); let inner3 = inner3.clone();
async move { async move {
let lock = inner3.lock().await; let lock = inner3.lock().await;
load_save(false, lock); load_save(false, lock).unwrap(); // unwrap as we want to
// bomb out of the task
} }
}, },
move |_lid_closed| { move |_lid_closed| {
@@ -266,7 +274,8 @@ impl CtrlTask for CtrlAuraZbus {
.unwrap() .unwrap()
.for_each(|_| async { .for_each(|_| async {
if let Some(lock) = ctrl2.try_lock() { if let Some(lock) = ctrl2.try_lock() {
load_save(true, lock); load_save(true, lock).unwrap(); // unwrap as we want to
// bomb out of the task
} }
}) })
.await; .await;

View File

@@ -29,7 +29,7 @@ macro_rules! platform_get_value {
$self.platform $self.platform
.get() .get()
.map_err(|err| { .map_err(|err| {
warn!("RogPlatform: {}: {}", $prop_name, err); warn!("{}: {}", $prop_name, err);
FdoErr::Failed(format!("RogPlatform: {}: {}", $prop_name, err)) FdoErr::Failed(format!("RogPlatform: {}: {}", $prop_name, err))
}) })
}) })
@@ -373,7 +373,7 @@ impl CtrlPlatform {
#[zbus(property)] #[zbus(property)]
fn gpu_mux_mode(&self) -> Result<u8, FdoErr> { fn gpu_mux_mode(&self) -> Result<u8, FdoErr> {
self.platform.get_gpu_mux_mode().map_err(|err| { self.platform.get_gpu_mux_mode().map_err(|err| {
warn!("RogPlatform: set_gpu_mux_mode {err}"); warn!("get_gpu_mux_mode {err}");
FdoErr::NotSupported("RogPlatform: set_gpu_mux_mode not supported".to_owned()) FdoErr::NotSupported("RogPlatform: set_gpu_mux_mode not supported".to_owned())
}) })
} }
@@ -382,7 +382,7 @@ impl CtrlPlatform {
async fn set_gpu_mux_mode(&mut self, mode: u8) -> Result<(), FdoErr> { async fn set_gpu_mux_mode(&mut self, mode: u8) -> Result<(), FdoErr> {
if self.platform.has_gpu_mux_mode() { if self.platform.has_gpu_mux_mode() {
self.set_gfx_mode(mode.into()).map_err(|err| { self.set_gfx_mode(mode.into()).map_err(|err| {
warn!("RogPlatform: set_gpu_mux_mode {}", err); warn!("set_gpu_mux_mode {}", err);
FdoErr::Failed(format!("RogPlatform: set_gpu_mux_mode: {err}")) FdoErr::Failed(format!("RogPlatform: set_gpu_mux_mode: {err}"))
})?; })?;
self.config.lock().await.write(); self.config.lock().await.write();
@@ -412,7 +412,7 @@ impl CtrlPlatform {
self.platform self.platform
.set_throttle_thermal_policy(policy.into()) .set_throttle_thermal_policy(policy.into())
.map_err(|err| { .map_err(|err| {
warn!("RogPlatform: throttle_thermal_policy {}", err); warn!("throttle_thermal_policy {}", err);
FdoErr::Failed(format!("RogPlatform: throttle_thermal_policy: {err}")) FdoErr::Failed(format!("RogPlatform: throttle_thermal_policy: {err}"))
})?; })?;
Ok(self.throttle_thermal_policy_changed(&ctxt).await?) Ok(self.throttle_thermal_policy_changed(&ctxt).await?)
@@ -440,7 +440,7 @@ impl CtrlPlatform {
self.platform self.platform
.set_throttle_thermal_policy(policy.into()) .set_throttle_thermal_policy(policy.into())
.map_err(|err| { .map_err(|err| {
warn!("RogPlatform: throttle_thermal_policy {}", err); warn!("throttle_thermal_policy {}", err);
FdoErr::Failed(format!("RogPlatform: throttle_thermal_policy: {err}")) FdoErr::Failed(format!("RogPlatform: throttle_thermal_policy: {err}"))
}) })
} else { } else {