Anime: Better prevent await blocking. Prevent Slash taking over anime USB dev

This commit is contained in:
Luke D. Jones
2024-05-05 10:56:55 +12:00
parent 661ea8d3bf
commit 487d140bd5
9 changed files with 204 additions and 124 deletions

View File

@@ -106,7 +106,7 @@ impl AnimeConfigCached {
}
/// Config for base system actions for the anime display
#[derive(Deserialize, Serialize, Debug)]
#[derive(Deserialize, Serialize, Debug, Clone)]
pub struct AnimeConfig {
pub model_override: Option<AnimeType>,
pub system: Vec<ActionLoader>,

View File

@@ -66,26 +66,28 @@ impl CtrlAnime {
let usb = USBRaw::new(0x193b).ok();
let hid = HidRaw::new("193b").ok();
let node = if usb.is_some() {
info!("Anime using the USB interface");
unsafe { Node::Usb(usb.unwrap_unchecked()) }
} else if hid.is_some() {
info!("Anime using the HID interface");
unsafe { Node::Hid(hid.unwrap_unchecked()) }
} else {
return Err(RogError::Anime(AnimeError::NoDevice));
};
// TODO: something better to set wakeups disabled
if matches!(node, Node::Usb(_)) {
if let Ok(mut enumerator) = udev::Enumerator::new() {
enumerator.match_subsystem("usb").ok();
enumerator.match_attribute("idProduct", "193b").ok();
// if matches!(node, Node::Usb(_)) {
// if let Ok(mut enumerator) = udev::Enumerator::new() {
// enumerator.match_subsystem("usb").ok();
// enumerator.match_attribute("idProduct", "193b").ok();
if let Ok(mut enumer) = enumerator.scan_devices() {
if let Some(mut dev) = enumer.next() {
dev.set_attribute_value("power/wakeup", "disabled").ok();
}
}
}
}
// if let Ok(mut enumer) = enumerator.scan_devices() {
// if let Some(mut dev) = enumer.next() {
// dev.set_attribute_value("power/wakeup", "disabled").ok();
// }
// }
// }
// }
let mut anime_type = get_anime_type()?;
if let AnimeType::Unknown = anime_type {

View File

@@ -12,6 +12,7 @@ use rog_anime::{Animations, AnimeDataBuffer, DeviceState};
use zbus::export::futures_util::lock::Mutex;
use zbus::{interface, CacheProperties, Connection, SignalContext};
use super::config::AnimeConfig;
use super::CtrlAnime;
use crate::error::RogError;
@@ -48,42 +49,53 @@ impl CtrlAnimeZbus {
/// Writes a data stream of length. Will force system thread to exit until
/// it is restarted
async fn write(&self, input: AnimeDataBuffer) -> zbus::fdo::Result<()> {
let lock = self.0.lock().await;
lock.thread_exit.store(true, Ordering::SeqCst);
lock.write_data_buffer(input).map_err(|err| {
warn!("ctrl_anime::run_animation:callback {}", err);
err
})?;
self.0
.lock()
.await
.thread_exit
.store(true, Ordering::SeqCst);
self.0
.lock()
.await
.write_data_buffer(input)
.map_err(|err| {
warn!("ctrl_anime::run_animation:callback {}", err);
err
})?;
Ok(())
}
/// Set base brightness level
#[zbus(property)]
async fn brightness(&self) -> Brightness {
let lock = self.0.lock().await;
lock.config.display_brightness
self.0.lock().await.config.display_brightness
}
/// Set base brightness level
#[zbus(property)]
async fn set_brightness(&self, brightness: Brightness) {
let mut lock = self.0.lock().await;
lock.node
self.0
.lock()
.await
.node
.write_bytes(&pkt_set_brightness(brightness))
.map_err(|err| {
warn!("ctrl_anime::set_brightness {}", err);
})
.ok();
lock.node
self.0
.lock()
.await
.node
.write_bytes(&pkt_set_enable_display(brightness != Brightness::Off))
.map_err(|err| {
warn!("ctrl_anime::set_brightness {}", err);
})
.ok();
lock.config.display_enabled = brightness != Brightness::Off;
lock.config.display_brightness = brightness;
lock.config.write();
self.0.lock().await.config.display_enabled = brightness != Brightness::Off;
self.0.lock().await.config.display_brightness = brightness;
self.0.lock().await.config.write();
}
#[zbus(property)]
@@ -96,20 +108,27 @@ impl CtrlAnimeZbus {
/// animations" in Armory crate
#[zbus(property)]
async fn set_builtins_enabled(&self, enabled: bool) {
let mut lock = self.0.lock().await;
lock.node
.set_builtins_enabled(enabled, lock.config.display_brightness)
let brightness = self.0.lock().await.config.display_brightness;
self.0
.lock()
.await
.node
.set_builtins_enabled(enabled, brightness)
.map_err(|err| {
warn!("ctrl_anime::set_builtins_enabled {}", err);
})
.ok();
if !enabled {
let data = vec![255u8; lock.anime_type.data_length()];
if let Ok(tmp) = AnimeDataBuffer::from_vec(lock.anime_type, data).map_err(|err| {
let anime_type = self.0.lock().await.anime_type;
let data = vec![255u8; anime_type.data_length()];
if let Ok(tmp) = AnimeDataBuffer::from_vec(anime_type, data).map_err(|err| {
warn!("ctrl_anime::set_builtins_enabled {}", err);
}) {
lock.node
self.0
.lock()
.await
.node
.write_bytes(tmp.data())
.map_err(|err| {
warn!("ctrl_anime::set_builtins_enabled {}", err);
@@ -118,24 +137,29 @@ impl CtrlAnimeZbus {
}
}
lock.config.builtin_anims_enabled = enabled;
lock.config.write();
self.0.lock().await.config.builtin_anims_enabled = enabled;
self.0.lock().await.config.write();
if enabled {
lock.thread_exit.store(true, Ordering::Release);
self.0
.lock()
.await
.thread_exit
.store(true, Ordering::Release);
}
}
#[zbus(property)]
async fn builtin_animations(&self) -> Animations {
let lock = self.0.lock().await;
lock.config.builtin_anims
self.0.lock().await.config.builtin_anims
}
/// Set which builtin animation is used for each stage
#[zbus(property)]
async fn set_builtin_animations(&self, settings: Animations) {
let mut lock = self.0.lock().await;
lock.node
self.0
.lock()
.await
.node
.write_bytes(&pkt_set_builtin_animations(
settings.boot,
settings.awake,
@@ -146,114 +170,125 @@ impl CtrlAnimeZbus {
warn!("ctrl_anime::run_animation:callback {}", err);
})
.ok();
lock.node
self.0
.lock()
.await
.node
.write_bytes(&pkt_set_enable_powersave_anim(true))
.map_err(|err| {
warn!("ctrl_anime::run_animation:callback {}", err);
})
.ok();
lock.config.display_enabled = true;
lock.config.builtin_anims = settings;
lock.config.write();
self.0.lock().await.config.display_enabled = true;
self.0.lock().await.config.builtin_anims = settings;
self.0.lock().await.config.write();
}
#[zbus(property)]
async fn enable_display(&self) -> bool {
let lock = self.0.lock().await;
lock.config.display_enabled
self.0.lock().await.config.display_enabled
}
/// Set whether the AniMe is enabled at all
#[zbus(property)]
async fn set_enable_display(&self, enabled: bool) {
let mut lock = self.0.lock().await;
lock.node
self.0
.lock()
.await
.node
.write_bytes(&pkt_set_enable_display(enabled))
.map_err(|err| {
warn!("ctrl_anime::run_animation:callback {}", err);
})
.ok();
lock.config.display_enabled = enabled;
lock.config.write();
self.0.lock().await.config.display_enabled = enabled;
self.0.lock().await.config.write();
}
#[zbus(property)]
async fn off_when_unplugged(&self) -> bool {
let lock = self.0.lock().await;
lock.config.off_when_unplugged
self.0.lock().await.config.off_when_unplugged
}
/// Set if to turn the AniMe Matrix off when external power is unplugged
#[zbus(property)]
async fn set_off_when_unplugged(&self, enabled: bool) {
let mut lock = self.0.lock().await;
let manager = get_logind_manager().await;
let pow = manager.on_external_power().await.unwrap_or_default();
lock.node
self.0
.lock()
.await
.node
.write_bytes(&pkt_set_enable_display(!pow && !enabled))
.map_err(|err| {
warn!("create_sys_event_tasks::off_when_lid_closed {}", err);
})
.ok();
lock.config.off_when_unplugged = enabled;
lock.config.write();
self.0.lock().await.config.off_when_unplugged = enabled;
self.0.lock().await.config.write();
}
#[zbus(property)]
async fn off_when_suspended(&self) -> bool {
let lock = self.0.lock().await;
lock.config.off_when_suspended
self.0.lock().await.config.off_when_suspended
}
/// Set if to turn the AniMe Matrix off when the laptop is suspended
#[zbus(property)]
async fn set_off_when_suspended(&self, enabled: bool) {
let mut lock = self.0.lock().await;
lock.config.off_when_suspended = enabled;
lock.config.write();
self.0.lock().await.config.off_when_suspended = enabled;
self.0.lock().await.config.write();
}
#[zbus(property)]
async fn off_when_lid_closed(&self) -> bool {
let lock = self.0.lock().await;
lock.config.off_when_lid_closed
self.0.lock().await.config.off_when_lid_closed
}
/// Set if to turn the AniMe Matrix off when the lid is closed
#[zbus(property)]
async fn set_off_when_lid_closed(&self, enabled: bool) {
let mut lock = self.0.lock().await;
let manager = get_logind_manager().await;
let lid = manager.lid_closed().await.unwrap_or_default();
lock.node
self.0
.lock()
.await
.node
.write_bytes(&pkt_set_enable_display(lid && !enabled))
.map_err(|err| {
warn!("create_sys_event_tasks::off_when_lid_closed {}", err);
})
.ok();
lock.config.off_when_lid_closed = enabled;
lock.config.write();
self.0.lock().await.config.off_when_lid_closed = enabled;
self.0.lock().await.config.write();
}
/// The main loop is the base system set action if the user isn't running
/// the user daemon
async fn run_main_loop(&self, start: bool) {
if start {
let lock = self.0.lock().await;
lock.thread_exit.store(true, Ordering::SeqCst);
CtrlAnime::run_thread(self.0.clone(), lock.cache.system.clone(), false).await;
self.0
.lock()
.await
.thread_exit
.store(true, Ordering::SeqCst);
CtrlAnime::run_thread(
self.0.clone(),
self.0.lock().await.cache.system.clone(),
false,
)
.await;
}
}
/// Get the device state as stored by asusd
// #[zbus(property)]
async fn device_state(&self) -> DeviceState {
let lock = self.0.lock().await;
DeviceState::from(&lock.config)
DeviceState::from(&self.0.lock().await.config)
}
}
@@ -272,36 +307,53 @@ impl crate::CtrlTask for CtrlAnimeZbus {
// on_sleep
let inner = inner1.clone();
async move {
let lock = inner.lock().await;
if lock.config.display_enabled {
lock.thread_exit.store(true, Ordering::Release); // ensure clean slate
let config = inner.lock().await.config.clone();
if config.display_enabled {
inner
.lock()
.await
.thread_exit
.store(true, Ordering::Release); // ensure clean slate
lock.node
inner
.lock()
.await
.node
.write_bytes(&pkt_set_enable_display(
!(sleeping && lock.config.off_when_suspended),
!(sleeping && config.off_when_suspended),
))
.map_err(|err| {
warn!("create_sys_event_tasks::off_when_suspended {}", err);
})
.ok();
if lock.config.builtin_anims_enabled {
lock.node
if config.builtin_anims_enabled {
inner
.lock()
.await
.node
.write_bytes(&pkt_set_enable_powersave_anim(
!(sleeping && lock.config.off_when_suspended),
!(sleeping && config.off_when_suspended),
))
.map_err(|err| {
warn!("create_sys_event_tasks::off_when_suspended {}", err);
})
.ok();
} else if !sleeping && !lock.config.builtin_anims_enabled {
} else if !sleeping && !config.builtin_anims_enabled {
// Run custom wake animation
lock.node
inner
.lock()
.await
.node
.write_bytes(&pkt_set_enable_powersave_anim(false))
.ok(); // ensure builtins are disabled
CtrlAnime::run_thread(inner.clone(), lock.cache.wake.clone(), true)
.await;
CtrlAnime::run_thread(
inner.clone(),
inner.lock().await.cache.wake.clone(),
true,
)
.await;
}
}
}
@@ -310,14 +362,26 @@ impl crate::CtrlTask for CtrlAnimeZbus {
// on_shutdown
let inner = inner2.clone();
async move {
let lock = inner.lock().await;
if lock.config.display_enabled && !lock.config.builtin_anims_enabled {
let AnimeConfig {
display_enabled,
builtin_anims_enabled,
..
} = inner.lock().await.config;
if display_enabled && !builtin_anims_enabled {
if shutting_down {
CtrlAnime::run_thread(inner.clone(), lock.cache.shutdown.clone(), true)
.await;
CtrlAnime::run_thread(
inner.clone(),
inner.lock().await.cache.shutdown.clone(),
true,
)
.await;
} else {
CtrlAnime::run_thread(inner.clone(), lock.cache.boot.clone(), true)
.await;
CtrlAnime::run_thread(
inner.clone(),
inner.lock().await.cache.boot.clone(),
true,
)
.await;
}
}
}
@@ -326,17 +390,27 @@ impl crate::CtrlTask for CtrlAnimeZbus {
let inner = inner3.clone();
// on lid change
async move {
let lock = inner.lock().await;
if lock.config.off_when_lid_closed {
if lock.config.builtin_anims_enabled {
lock.node
let AnimeConfig {
off_when_lid_closed,
builtin_anims_enabled,
..
} = inner.lock().await.config;
if off_when_lid_closed {
if builtin_anims_enabled {
inner
.lock()
.await
.node
.write_bytes(&pkt_set_enable_powersave_anim(!lid_closed))
.map_err(|err| {
warn!("create_sys_event_tasks::off_when_suspended {}", err);
})
.ok();
}
lock.node
inner
.lock()
.await
.node
.write_bytes(&pkt_set_enable_display(!lid_closed))
.map_err(|err| {
warn!("create_sys_event_tasks::off_when_lid_closed {}", err);
@@ -349,25 +423,39 @@ impl crate::CtrlTask for CtrlAnimeZbus {
let inner = inner4.clone();
// on power change
async move {
let lock = inner.lock().await;
if lock.config.off_when_unplugged {
if lock.config.builtin_anims_enabled {
lock.node
let AnimeConfig {
off_when_unplugged,
builtin_anims_enabled,
brightness_on_battery,
..
} = inner.lock().await.config;
if off_when_unplugged {
if builtin_anims_enabled {
inner
.lock()
.await
.node
.write_bytes(&pkt_set_enable_powersave_anim(power_plugged))
.map_err(|err| {
warn!("create_sys_event_tasks::off_when_suspended {}", err);
})
.ok();
}
lock.node
inner
.lock()
.await
.node
.write_bytes(&pkt_set_enable_display(power_plugged))
.map_err(|err| {
warn!("create_sys_event_tasks::off_when_unplugged {}", err);
})
.ok();
} else {
lock.node
.write_bytes(&pkt_set_brightness(lock.config.brightness_on_battery))
inner
.lock()
.await
.node
.write_bytes(&pkt_set_brightness(brightness_on_battery))
.map_err(|err| {
warn!("create_sys_event_tasks::off_when_unplugged {}", err);
})

View File

@@ -44,6 +44,11 @@ pub struct CtrlSlash {
impl CtrlSlash {
#[inline]
pub fn new(config: SlashConfig) -> Result<CtrlSlash, RogError> {
let slash_type = get_slash_type()?;
if matches!(slash_type, SlashType::Unknown | SlashType::Unsupported) {
return Err(RogError::Slash(SlashError::NoDevice));
}
let usb = USBRaw::new(rog_slash::usb::PROD_ID).ok();
let hid = HidRaw::new(rog_slash::usb::PROD_ID_STR).ok();
let node = if usb.is_some() {
@@ -54,11 +59,6 @@ impl CtrlSlash {
return Err(RogError::NotSupported);
};
let slash_type = get_slash_type()?;
if slash_type == SlashType::Unknown {
return Err(RogError::Slash(SlashError::NoDevice));
}
let ctrl = CtrlSlash {
node,
config,

View File

@@ -199,16 +199,7 @@ pub trait CtrlTask {
///
/// The closures can potentially block, so execution time should be the
/// minimal possible such as save a variable.
fn create_sys_event_tasks<
Fut1,
Fut2,
Fut3,
Fut4,
F1: Send + 'static,
F2: Send + 'static,
F3: Send + 'static,
F4: Send + 'static,
>(
fn create_sys_event_tasks<Fut1, Fut2, Fut3, Fut4, F1, F2, F3, F4>(
&self,
mut on_prepare_for_sleep: F1,
mut on_prepare_for_shutdown: F2,
@@ -216,10 +207,10 @@ pub trait CtrlTask {
mut on_external_power_change: F4,
) -> impl Future<Output = ()> + Send
where
F1: FnMut(bool) -> Fut1,
F2: FnMut(bool) -> Fut2,
F3: FnMut(bool) -> Fut3,
F4: FnMut(bool) -> Fut4,
F1: FnMut(bool) -> Fut1 + Send + 'static,
F2: FnMut(bool) -> Fut2 + Send + 'static,
F3: FnMut(bool) -> Fut3 + Send + 'static,
F4: FnMut(bool) -> Fut4 + Send + 'static,
Fut1: Future<Output = ()> + Send,
Fut2: Future<Output = ()> + Send,
Fut3: Future<Output = ()> + Send,

View File

@@ -2,7 +2,7 @@
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2024-04-18 02:40+0000\n"
"POT-Creation-Date: 2024-05-04 22:54+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"

View File

@@ -122,7 +122,6 @@ impl FanCurveProfiles {
Ok(FanCurvePU::which_fans(&device))
}
///
pub fn read_from_dev_profile(
&mut self,
profile: ThrottlePolicy,

View File

@@ -13,6 +13,7 @@ use crate::error::SlashError;
pub enum SlashType {
GA403,
Unknown,
Unsupported,
}
impl FromStr for SlashType {

View File

@@ -35,8 +35,7 @@ pub fn get_slash_type() -> Result<SlashType, SlashError> {
if board_name.contains("GA403") {
return Ok(SlashType::GA403);
}
log::warn!("AniMe Slash device found but not yet supported, will default to a GA403 layout");
Ok(SlashType::Unknown)
Ok(SlashType::Unsupported)
}
/// Get the two device initialization packets. These are required for device