mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
Anime: fixups, GU604 support
This commit is contained in:
@@ -225,7 +225,8 @@ fn handle_anime(
|
||||
if (cmd.command.is_none()
|
||||
&& cmd.enable.is_none()
|
||||
&& cmd.boot_enable.is_none()
|
||||
&& cmd.brightness.is_none())
|
||||
&& cmd.brightness.is_none()
|
||||
&& !cmd.clear)
|
||||
|| cmd.help
|
||||
{
|
||||
println!("Missing arg or command\n\n{}", cmd.self_usage());
|
||||
@@ -234,14 +235,14 @@ fn handle_anime(
|
||||
}
|
||||
}
|
||||
if let Some(anime_turn) = cmd.enable {
|
||||
dbus.proxies().anime().set_on_off(anime_turn)?;
|
||||
dbus.proxies().anime().set_awake_enabled(anime_turn)?;
|
||||
}
|
||||
if let Some(anime_boot) = cmd.boot_enable {
|
||||
dbus.proxies().anime().set_boot_on_off(anime_boot)?;
|
||||
dbus.proxies().anime().set_animation_enabled(anime_boot)?;
|
||||
}
|
||||
if let Some(bright) = cmd.brightness {
|
||||
verify_brightness(bright);
|
||||
dbus.proxies().anime().set_brightness(bright)?;
|
||||
dbus.proxies().anime().set_image_brightness(bright)?;
|
||||
}
|
||||
if cmd.clear {
|
||||
let anime_type = get_anime_type()?;
|
||||
|
||||
@@ -360,13 +360,13 @@ impl CtrlAnime<'static> {
|
||||
pub fn set_state(&mut self, on: bool) -> zbus::fdo::Result<()> {
|
||||
// Operations here need to be in specific order
|
||||
if on {
|
||||
self.client.proxies().anime().set_on_off(on).ok();
|
||||
self.client.proxies().anime().set_awake_enabled(on).ok();
|
||||
// Let the inner loop run
|
||||
self.inner_early_return.store(false, Ordering::SeqCst);
|
||||
} else {
|
||||
// Must make the inner run loop return early
|
||||
self.inner_early_return.store(true, Ordering::SeqCst);
|
||||
self.client.proxies().anime().set_on_off(on).ok();
|
||||
self.client.proxies().anime().set_awake_enabled(on).ok();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ use rog_anime::usb::{get_anime_type, pkt_for_flush, pkts_for_init};
|
||||
use rog_anime::{ActionData, AnimeDataBuffer, AnimePacketType, AnimeType};
|
||||
use rog_platform::hid_raw::HidRaw;
|
||||
use rog_platform::supported::AnimeSupportedFunctions;
|
||||
use rog_platform::usb_raw::USBRaw;
|
||||
|
||||
use self::config::{AnimeConfig, AnimeConfigCached};
|
||||
use crate::error::RogError;
|
||||
@@ -29,7 +30,8 @@ impl GetSupported for CtrlAnime {
|
||||
}
|
||||
|
||||
pub struct CtrlAnime {
|
||||
node: HidRaw,
|
||||
// node: HidRaw,
|
||||
node: USBRaw,
|
||||
anime_type: AnimeType,
|
||||
cache: AnimeConfigCached,
|
||||
config: AnimeConfig,
|
||||
@@ -42,10 +44,11 @@ pub struct CtrlAnime {
|
||||
impl CtrlAnime {
|
||||
#[inline]
|
||||
pub fn new(config: AnimeConfig) -> Result<CtrlAnime, Box<dyn Error>> {
|
||||
let node = HidRaw::new("193b")?;
|
||||
// let node = HidRaw::new("193b")?;
|
||||
let node = USBRaw::new(0x193b)?;
|
||||
let anime_type = get_anime_type().unwrap_or(AnimeType::GA401);
|
||||
|
||||
info!("Device has an AniMe Matrix display");
|
||||
info!("Device has an AniMe Matrix display: {anime_type:?}");
|
||||
let mut cache = AnimeConfigCached::default();
|
||||
cache.init_from_config(&config, anime_type)?;
|
||||
|
||||
|
||||
@@ -4,7 +4,9 @@ use std::sync::Arc;
|
||||
use async_trait::async_trait;
|
||||
use config_traits::StdConfig;
|
||||
use log::warn;
|
||||
use rog_anime::usb::{pkt_for_apply, pkt_for_set_boot, pkt_for_set_on};
|
||||
use rog_anime::usb::{
|
||||
pkt_for_enable_animation, pkt_for_set_awake_enabled, pkt_for_set_boot, pkt_for_set_brightness,
|
||||
};
|
||||
use rog_anime::{AnimeDataBuffer, AnimePowerStates};
|
||||
use zbus::export::futures_util::lock::Mutex;
|
||||
use zbus::{dbus_interface, Connection, SignalContext};
|
||||
@@ -43,7 +45,7 @@ impl CtrlAnimeZbus {
|
||||
}
|
||||
|
||||
/// Set the global AniMe brightness
|
||||
async fn set_brightness(&self, bright: f32) {
|
||||
async fn set_image_brightness(&self, bright: f32) {
|
||||
let mut lock = self.0.lock().await;
|
||||
let mut bright = bright;
|
||||
if bright < 0.0 {
|
||||
@@ -55,11 +57,40 @@ impl CtrlAnimeZbus {
|
||||
lock.config.write();
|
||||
}
|
||||
|
||||
/// Set whether the AniMe is displaying images/data
|
||||
async fn set_on_off(&self, #[zbus(signal_context)] ctxt: SignalContext<'_>, status: bool) {
|
||||
/// Set base brightness level
|
||||
// TODO: enum for brightness
|
||||
async fn set_brightness(&self, #[zbus(signal_context)] ctxt: SignalContext<'_>, status: bool) {
|
||||
let mut lock = self.0.lock().await;
|
||||
lock.node
|
||||
.write_bytes(&pkt_for_set_on(status))
|
||||
.write_bytes(&pkt_for_set_brightness(status))
|
||||
.map_err(|err| {
|
||||
warn!("rog_anime::run_animation:callback {}", err);
|
||||
})
|
||||
.ok();
|
||||
lock.config.awake_enabled = status;
|
||||
lock.config.write();
|
||||
|
||||
Self::notify_power_states(
|
||||
&ctxt,
|
||||
AnimePowerStates {
|
||||
brightness: lock.config.brightness.floor() as u8,
|
||||
enabled: lock.config.awake_enabled,
|
||||
boot_anim_enabled: lock.config.boot_anim_enabled,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.ok();
|
||||
}
|
||||
|
||||
/// Set whether the AniMe is displaying images/data
|
||||
async fn set_awake_enabled(
|
||||
&self,
|
||||
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
||||
status: bool,
|
||||
) {
|
||||
let mut lock = self.0.lock().await;
|
||||
lock.node
|
||||
.write_bytes(&pkt_for_set_awake_enabled(status))
|
||||
.map_err(|err| {
|
||||
warn!("rog_anime::run_animation:callback {}", err);
|
||||
})
|
||||
@@ -80,7 +111,11 @@ impl CtrlAnimeZbus {
|
||||
}
|
||||
|
||||
/// Set whether the AniMe will show boot, suspend, or off animations
|
||||
async fn set_boot_on_off(&self, #[zbus(signal_context)] ctxt: SignalContext<'_>, on: bool) {
|
||||
async fn set_animation_enabled(
|
||||
&self,
|
||||
#[zbus(signal_context)] ctxt: SignalContext<'_>,
|
||||
on: bool,
|
||||
) {
|
||||
let mut lock = self.0.lock().await;
|
||||
lock.node
|
||||
.write_bytes(&pkt_for_set_boot(on))
|
||||
@@ -89,7 +124,7 @@ impl CtrlAnimeZbus {
|
||||
})
|
||||
.ok();
|
||||
lock.node
|
||||
.write_bytes(&pkt_for_apply())
|
||||
.write_bytes(&pkt_for_enable_animation())
|
||||
.map_err(|err| {
|
||||
warn!("rog_anime::run_animation:callback {}", err);
|
||||
})
|
||||
@@ -128,7 +163,7 @@ impl CtrlAnimeZbus {
|
||||
|
||||
/// Get the status of if factory system-status animations are enabled
|
||||
#[dbus_interface(property)]
|
||||
async fn boot_enabled(&self) -> bool {
|
||||
async fn animation_enabled(&self) -> bool {
|
||||
let lock = self.0.lock().await;
|
||||
lock.config.boot_anim_enabled
|
||||
}
|
||||
@@ -198,11 +233,9 @@ impl crate::Reloadable for CtrlAnimeZbus {
|
||||
async fn reload(&mut self) -> Result<(), RogError> {
|
||||
if let Some(lock) = self.0.try_lock() {
|
||||
lock.node
|
||||
.write_bytes(&pkt_for_set_on(lock.config.awake_enabled))?;
|
||||
lock.node.write_bytes(&pkt_for_apply())?;
|
||||
.write_bytes(&pkt_for_set_brightness(lock.config.awake_enabled))?;
|
||||
lock.node
|
||||
.write_bytes(&pkt_for_set_boot(lock.config.boot_anim_enabled))?;
|
||||
lock.node.write_bytes(&pkt_for_apply())?;
|
||||
|
||||
let action = lock.cache.boot.clone();
|
||||
CtrlAnime::run_thread(self.0.clone(), action, true);
|
||||
|
||||
@@ -38,6 +38,7 @@ pub struct AnimePowerStates {
|
||||
pub enum AnimeType {
|
||||
GA401,
|
||||
GA402,
|
||||
GU604,
|
||||
Unknown,
|
||||
}
|
||||
|
||||
@@ -46,6 +47,7 @@ impl AnimeType {
|
||||
pub fn width(&self) -> usize {
|
||||
match self {
|
||||
AnimeType::GA401 | AnimeType::GA402 => 74,
|
||||
AnimeType::GU604 => 74,
|
||||
AnimeType::Unknown => 0,
|
||||
}
|
||||
}
|
||||
@@ -55,6 +57,7 @@ impl AnimeType {
|
||||
match self {
|
||||
AnimeType::GA401 => 36,
|
||||
AnimeType::GA402 => 39,
|
||||
AnimeType::GU604 => 39,
|
||||
AnimeType::Unknown => 0,
|
||||
}
|
||||
}
|
||||
@@ -64,6 +67,7 @@ impl AnimeType {
|
||||
match self {
|
||||
AnimeType::GA401 => PANE_LEN * 2,
|
||||
AnimeType::GA402 => PANE_LEN * 3,
|
||||
AnimeType::GU604 => PANE_LEN * 3,
|
||||
AnimeType::Unknown => 0,
|
||||
}
|
||||
}
|
||||
@@ -115,7 +119,7 @@ impl AnimeDataBuffer {
|
||||
}
|
||||
}
|
||||
|
||||
/// The two packets to be written to USB
|
||||
/// The packets to be written to USB
|
||||
pub type AnimePacketType = Vec<[u8; 640]>;
|
||||
|
||||
impl TryFrom<AnimeDataBuffer> for AnimePacketType {
|
||||
@@ -128,8 +132,7 @@ impl TryFrom<AnimeDataBuffer> for AnimePacketType {
|
||||
|
||||
let mut buffers = match anime.anime {
|
||||
AnimeType::GA401 => vec![[0; 640]; 2],
|
||||
AnimeType::GA402 => vec![[0; 640]; 3],
|
||||
AnimeType::Unknown => vec![[0; 640]; 1],
|
||||
AnimeType::GA402 | AnimeType::GU604 | AnimeType::Unknown => vec![[0; 640]; 3],
|
||||
};
|
||||
|
||||
for (idx, chunk) in anime.data.as_slice().chunks(PANE_LEN).enumerate() {
|
||||
@@ -138,7 +141,10 @@ impl TryFrom<AnimeDataBuffer> for AnimePacketType {
|
||||
buffers[0][..7].copy_from_slice(&USB_PREFIX1);
|
||||
buffers[1][..7].copy_from_slice(&USB_PREFIX2);
|
||||
|
||||
if matches!(anime.anime, AnimeType::GA402) {
|
||||
if matches!(
|
||||
anime.anime,
|
||||
AnimeType::GA402 | AnimeType::GU604 | AnimeType::Unknown
|
||||
) {
|
||||
buffers[2][..7].copy_from_slice(&USB_PREFIX3);
|
||||
}
|
||||
Ok(buffers)
|
||||
|
||||
@@ -139,6 +139,7 @@ impl AnimeDiagonal {
|
||||
match anime_type {
|
||||
AnimeType::GA401 => self.to_ga401_packets(),
|
||||
AnimeType::GA402 => self.to_ga402_packets(),
|
||||
AnimeType::GU604 => self.to_ga402_packets(),
|
||||
AnimeType::Unknown => self.to_unknown_packets(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,6 +118,7 @@ impl AnimeImage {
|
||||
match anime_type {
|
||||
AnimeType::GA401 => 0.8,
|
||||
AnimeType::GA402 => 0.77,
|
||||
AnimeType::GU604 => 0.77,
|
||||
AnimeType::Unknown => 0.0,
|
||||
}
|
||||
}
|
||||
@@ -134,6 +135,7 @@ impl AnimeImage {
|
||||
match anime_type {
|
||||
AnimeType::GA401 => 0.3,
|
||||
AnimeType::GA402 => 0.283,
|
||||
AnimeType::GU604 => 0.283,
|
||||
AnimeType::Unknown => 0.0,
|
||||
}
|
||||
}
|
||||
@@ -175,6 +177,14 @@ impl AnimeImage {
|
||||
// and then their offset grows by one every two rows
|
||||
(y + 1) / 2 - 5
|
||||
}
|
||||
AnimeType::GU604 => {
|
||||
// first 11 rows start at zero
|
||||
if y <= 9 {
|
||||
return 0;
|
||||
}
|
||||
// and then their offset grows by one every two rows
|
||||
(y + 1) / 2 - 5
|
||||
}
|
||||
AnimeType::Unknown => 0,
|
||||
}
|
||||
}
|
||||
@@ -209,6 +219,12 @@ impl AnimeImage {
|
||||
}
|
||||
39 - y / 2
|
||||
}
|
||||
AnimeType::GU604 => {
|
||||
if y <= 9 {
|
||||
return 39;
|
||||
}
|
||||
44 - y / 2
|
||||
}
|
||||
AnimeType::Unknown => 0,
|
||||
}
|
||||
}
|
||||
@@ -219,6 +235,7 @@ impl AnimeImage {
|
||||
// 33.0 = Longest row LED count (physical) plus half-pixel offset
|
||||
AnimeType::GA401 => (33.0 + 0.5) * Self::scale_x(anime_type),
|
||||
AnimeType::GA402 => (35.0 + 0.5) * Self::scale_x(anime_type),
|
||||
AnimeType::GU604 => (35.0 + 0.5) * Self::scale_x(anime_type),
|
||||
AnimeType::Unknown => 0.0,
|
||||
}
|
||||
}
|
||||
@@ -228,6 +245,7 @@ impl AnimeImage {
|
||||
match anime_type {
|
||||
AnimeType::GA401 => 55,
|
||||
AnimeType::GA402 => 61,
|
||||
AnimeType::GU604 => 61,
|
||||
AnimeType::Unknown => 0,
|
||||
}
|
||||
}
|
||||
@@ -239,6 +257,7 @@ impl AnimeImage {
|
||||
AnimeType::GA401 => (54.0 + 1.0) * Self::scale_y(anime_type),
|
||||
// GA402 may not have dead pixels and require only the physical LED count
|
||||
AnimeType::GA402 => 61.0 * Self::scale_y(anime_type),
|
||||
AnimeType::GU604 => 61.0 * Self::scale_y(anime_type),
|
||||
AnimeType::Unknown => 0.0,
|
||||
}
|
||||
}
|
||||
@@ -253,6 +272,7 @@ impl AnimeImage {
|
||||
},
|
||||
// GA402 does not have padding, equivalent to width
|
||||
AnimeType::GA402 => AnimeImage::width(anime_type, y),
|
||||
AnimeType::GU604 => AnimeImage::width(anime_type, y),
|
||||
AnimeType::Unknown => 0,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,9 +11,6 @@
|
||||
use crate::error::AnimeError;
|
||||
use crate::AnimeType;
|
||||
|
||||
const INIT_STR: [u8; 15] = [
|
||||
0x5e, b'A', b'S', b'U', b'S', b' ', b'T', b'e', b'c', b'h', b'.', b'I', b'n', b'c', b'.',
|
||||
];
|
||||
const PACKET_SIZE: usize = 640;
|
||||
const DEV_PAGE: u8 = 0x5e;
|
||||
pub const VENDOR_ID: u16 = 0x0b05;
|
||||
@@ -33,6 +30,8 @@ pub fn get_anime_type() -> Result<AnimeType, AnimeError> {
|
||||
return Ok(AnimeType::GA401);
|
||||
} else if board_name.contains("GA402R") {
|
||||
return Ok(AnimeType::GA402);
|
||||
} else if board_name.contains("GU604V") {
|
||||
return Ok(AnimeType::GU604);
|
||||
}
|
||||
log::warn!("AniMe Matrix device found but not yet supported");
|
||||
Ok(AnimeType::Unknown)
|
||||
@@ -45,12 +44,14 @@ pub const fn pkts_for_init() -> [[u8; PACKET_SIZE]; 2] {
|
||||
let mut packets = [[0; PACKET_SIZE]; 2];
|
||||
packets[0][0] = DEV_PAGE; // This is the USB page we're using throughout
|
||||
let mut count = 0;
|
||||
while count < INIT_STR.len() {
|
||||
packets[0][count] = INIT_STR[count];
|
||||
// TODO: memcpy or slice copy
|
||||
let bytes = "ASUS Tech.Inc.".as_bytes();
|
||||
while count < bytes.len() {
|
||||
packets[0][count + 1] = bytes[count];
|
||||
count += 1;
|
||||
}
|
||||
//
|
||||
packets[1][0] = DEV_PAGE; // write it to be sure?
|
||||
packets[1][0] = DEV_PAGE;
|
||||
packets[1][1] = 0xc2;
|
||||
packets
|
||||
}
|
||||
@@ -80,8 +81,9 @@ pub const fn pkt_for_set_boot(status: bool) -> [u8; PACKET_SIZE] {
|
||||
|
||||
/// Get the packet required for setting the device to on. Requires
|
||||
/// `pkt_for_apply()` to be written after.
|
||||
// TODO: change the users of this method
|
||||
#[inline]
|
||||
pub const fn pkt_for_set_on(on: bool) -> [u8; PACKET_SIZE] {
|
||||
pub const fn pkt_for_set_brightness(on: bool) -> [u8; PACKET_SIZE] {
|
||||
let mut pkt = [0; PACKET_SIZE];
|
||||
pkt[0] = DEV_PAGE;
|
||||
pkt[1] = 0xc0;
|
||||
@@ -90,9 +92,19 @@ pub const fn pkt_for_set_on(on: bool) -> [u8; PACKET_SIZE] {
|
||||
pkt
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn pkt_for_set_awake_enabled(enable: bool) -> [u8; PACKET_SIZE] {
|
||||
let mut pkt = [0; PACKET_SIZE];
|
||||
pkt[0] = DEV_PAGE;
|
||||
pkt[1] = 0xc3;
|
||||
pkt[2] = 0x01;
|
||||
pkt[3] = if enable { 0x80 } else { 0x00 };
|
||||
pkt
|
||||
}
|
||||
|
||||
/// Packet required to apply a device setting
|
||||
#[inline]
|
||||
pub const fn pkt_for_apply() -> [u8; PACKET_SIZE] {
|
||||
pub const fn pkt_for_enable_animation() -> [u8; PACKET_SIZE] {
|
||||
let mut pkt = [0; PACKET_SIZE];
|
||||
pkt[0] = DEV_PAGE;
|
||||
pkt[1] = 0xc4;
|
||||
|
||||
@@ -204,7 +204,7 @@ impl AnimeState {
|
||||
pub fn new(supported: &SupportedFunctions, dbus: &RogDbusClientBlocking<'_>) -> Result<Self> {
|
||||
Ok(Self {
|
||||
boot: if supported.anime_ctrl.0 {
|
||||
dbus.proxies().anime().boot_enabled()?
|
||||
dbus.proxies().anime().animation_enabled()?
|
||||
} else {
|
||||
false
|
||||
},
|
||||
|
||||
@@ -42,7 +42,7 @@ pub fn anime_power_group(_supported: &SupportedFunctions, states: &mut SystemSta
|
||||
.asus_dbus
|
||||
.proxies()
|
||||
.anime()
|
||||
.set_boot_on_off(states.anime.boot)
|
||||
.set_animation_enabled(states.anime.boot)
|
||||
.map_err(|err| {
|
||||
states.error = Some(err.to_string());
|
||||
})
|
||||
@@ -55,7 +55,7 @@ pub fn anime_power_group(_supported: &SupportedFunctions, states: &mut SystemSta
|
||||
.asus_dbus
|
||||
.proxies()
|
||||
.anime()
|
||||
.set_on_off(states.anime.awake)
|
||||
.set_awake_enabled(states.anime.awake)
|
||||
.map_err(|err| {
|
||||
states.error = Some(err.to_string());
|
||||
})
|
||||
|
||||
@@ -7,13 +7,13 @@ use zbus::dbus_proxy;
|
||||
)]
|
||||
trait Anime {
|
||||
/// Set whether the AniMe will show boot, suspend, or off animations
|
||||
fn set_boot_on_off(&self, status: bool) -> zbus::Result<()>;
|
||||
fn set_animation_enabled(&self, status: bool) -> zbus::Result<()>;
|
||||
|
||||
/// Set the global AniMe brightness
|
||||
fn set_brightness(&self, bright: f32) -> zbus::Result<()>;
|
||||
fn set_image_brightness(&self, bright: f32) -> zbus::Result<()>;
|
||||
|
||||
/// Set whether the AniMe is displaying images/data
|
||||
fn set_on_off(&self, status: bool) -> zbus::Result<()>;
|
||||
fn set_awake_enabled(&self, status: bool) -> zbus::Result<()>;
|
||||
|
||||
/// Writes a data stream of length. Will force system thread to exit until
|
||||
/// it is restarted
|
||||
@@ -25,7 +25,7 @@ trait Anime {
|
||||
|
||||
/// Get the status of if factory system-status animations are enabled
|
||||
#[dbus_proxy(property)]
|
||||
fn boot_enabled(&self) -> zbus::Result<bool>;
|
||||
fn animation_enabled(&self) -> zbus::Result<bool>;
|
||||
|
||||
/// Notify listeners of the status of AniMe LED power and factory
|
||||
/// system-status animations
|
||||
|
||||
Reference in New Issue
Block a user