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),
}
impl Default for AuraPowerConfig {
fn default() -> Self {
Self::AuraDevTuf(HashSet::default())
}
}
impl AuraPowerConfig {
/// Invalid for TUF laptops
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)]
pub struct AuraConfig {
pub config_name: String,

View File

@@ -62,7 +62,7 @@ impl CtrlKbdLed {
pub fn find_all(data: &LaptopLedData) -> Result<Vec<Self>, RogError> {
info!("Searching for all Aura devices");
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| {
warn!("{}", err);
@@ -92,13 +92,14 @@ impl CtrlKbdLed {
}
// 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
let mut aura_dev = AuraDevice::Unknown;
if let Some(usb_id) = usb_device.attribute_value("idProduct") {
let prod_id = AuraDevice::from(usb_id.to_str().unwrap());
if prod_id == AuraDevice::Unknown || found.contains(&prod_id) {
aura_dev = AuraDevice::from(usb_id.to_str().unwrap());
if aura_dev == AuraDevice::Unknown || found.contains(&aura_dev) {
log::debug!("Unknown or invalid device: {usb_id:?}, skipping");
continue;
}
found.insert(prod_id);
found.insert(aura_dev);
}
let dev_node = if let Some(dev_node) = usb_device.devnode() {
@@ -110,7 +111,8 @@ impl CtrlKbdLed {
info!("AuraControl found device at: {:?}", dev_node);
let dbus_path = dbus_path_for_dev(&usb_device).unwrap_or_default();
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);
}
}
@@ -119,6 +121,9 @@ impl CtrlKbdLed {
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(
device: HidRaw,
dbus_path: OwnedObjectPath,
@@ -132,20 +137,20 @@ impl CtrlKbdLed {
}
// 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 {
led_prod: prod_id,
led_node: LEDNode::Rog(rgb_led, device),
supported_data: data.clone(),
per_key_mode_active: false,
config,
config: AuraConfig::default(),
dbus_path,
};
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
let mut config_init = AuraConfig::new_with(prod_id);
// config_init.set_filename(prod_id);

View File

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

View File

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