mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
Advanced Aura feature
Groundwork for 'advanced' aura modes Add single zone + Doom light flash Fix mocking for ROGCC Better prepare & change to mapping of keyboard layouts to models and functions Refactor and begin using new key layout stuff Enable first arg to rogcc to set layout in mocking feature mode Complete refactor of key layouts, and to RON serde
This commit is contained in:
@@ -1,20 +1,17 @@
|
||||
use std::{
|
||||
convert::TryFrom,
|
||||
thread::sleep,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
use std::convert::TryFrom;
|
||||
use std::thread::sleep;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use log::info;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
#[cfg(feature = "dbus")]
|
||||
use zbus::zvariant::Type;
|
||||
|
||||
use crate::{
|
||||
error::{AnimeError, Result},
|
||||
AnimTime, AnimeGif,
|
||||
};
|
||||
use crate::error::{AnimeError, Result};
|
||||
use crate::{AnimTime, AnimeGif};
|
||||
|
||||
/// The first 7 bytes of a USB packet are accounted for by `USB_PREFIX1` and `USB_PREFIX2`
|
||||
/// The first 7 bytes of a USB packet are accounted for by `USB_PREFIX1` and
|
||||
/// `USB_PREFIX2`
|
||||
const BLOCK_START: usize = 7;
|
||||
/// *Not* inclusive, the byte before this is the final for each "pane"
|
||||
const BLOCK_END: usize = 634;
|
||||
@@ -143,9 +140,11 @@ impl TryFrom<AnimeDataBuffer> for AnimePacketType {
|
||||
}
|
||||
}
|
||||
|
||||
/// This runs the animations as a blocking loop by using the `callback` to write data
|
||||
/// This runs the animations as a blocking loop by using the `callback` to write
|
||||
/// data
|
||||
///
|
||||
/// If `callback` is `Ok(true)` then `run_animation` will exit the animation loop early.
|
||||
/// If `callback` is `Ok(true)` then `run_animation` will exit the animation
|
||||
/// loop early.
|
||||
pub fn run_animation(frames: &AnimeGif, callback: &dyn Fn(AnimeDataBuffer) -> Result<bool>) {
|
||||
let mut count = 0;
|
||||
let start = Instant::now();
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
use std::{path::Path, time::Duration};
|
||||
use std::path::Path;
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::{
|
||||
data::AnimeDataBuffer,
|
||||
error::{AnimeError, Result},
|
||||
AnimeType,
|
||||
};
|
||||
use crate::data::AnimeDataBuffer;
|
||||
use crate::error::{AnimeError, Result};
|
||||
use crate::AnimeType;
|
||||
|
||||
/// Mostly intended to be used with ASUS gifs, but can be used for other purposes (like images)
|
||||
/// Mostly intended to be used with ASUS gifs, but can be used for other
|
||||
/// purposes (like images)
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AnimeDiagonal(AnimeType, Vec<Vec<u8>>, Option<Duration>);
|
||||
|
||||
@@ -25,7 +25,8 @@ impl AnimeDiagonal {
|
||||
&mut self.1
|
||||
}
|
||||
|
||||
/// Get a full diagonal row where `x` `y` is the starting point and `len` is the length of data.
|
||||
/// Get a full diagonal row where `x` `y` is the starting point and `len`
|
||||
/// is the length of data.
|
||||
fn get_row(&self, x: usize, y: usize, len: usize) -> Vec<u8> {
|
||||
let mut buf = Vec::with_capacity(len);
|
||||
for i in 0..len {
|
||||
@@ -36,8 +37,9 @@ impl AnimeDiagonal {
|
||||
buf
|
||||
}
|
||||
|
||||
/// Generate the base image from inputs. The result can be displayed as is or
|
||||
/// updated via scale, position, or angle then displayed again after `update()`.
|
||||
/// Generate the base image from inputs. The result can be displayed as is
|
||||
/// or updated via scale, position, or angle then displayed again after
|
||||
/// `update()`.
|
||||
#[inline]
|
||||
pub fn from_png(
|
||||
path: &Path,
|
||||
@@ -290,7 +292,8 @@ impl AnimeDiagonal {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::{convert::TryFrom, path::PathBuf};
|
||||
use std::convert::TryFrom;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::{AnimeDiagonal, AnimePacketType, AnimeType};
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
use gif::DecodingError;
|
||||
use png_pong::decode::Error as PngError;
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
|
||||
use gif::DecodingError;
|
||||
use png_pong::decode::Error as PngError;
|
||||
|
||||
pub type Result<T> = std::result::Result<T, AnimeError>;
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -12,7 +13,8 @@ pub enum AnimeError {
|
||||
Png(PngError),
|
||||
Gif(DecodingError),
|
||||
Format,
|
||||
/// The input was incorrect size, expected size is `IncorrectSize(width, height)`
|
||||
/// The input was incorrect size, expected size is `IncorrectSize(width,
|
||||
/// height)`
|
||||
IncorrectSize(u32, u32),
|
||||
Dbus(String),
|
||||
Udev(String, std::io::Error),
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
use std::convert::TryFrom;
|
||||
use std::fs::File;
|
||||
use std::path::Path;
|
||||
use std::time::Duration;
|
||||
|
||||
use glam::Vec2;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::convert::TryFrom;
|
||||
use std::{fs::File, path::Path, time::Duration};
|
||||
|
||||
use crate::error::AnimeError;
|
||||
use crate::{error::Result, AnimeDataBuffer, AnimeDiagonal, AnimeImage, AnimeType, Pixel};
|
||||
use crate::error::{AnimeError, Result};
|
||||
use crate::{AnimeDataBuffer, AnimeDiagonal, AnimeImage, AnimeType, Pixel};
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct AnimeFrame {
|
||||
/// Precomputed data for the frame. This can be transferred directly to the
|
||||
/// the `asusd` daemon over dbus or converted to USB packet with `AnimePacketType::from(buffer)`
|
||||
/// the `asusd` daemon over dbus or converted to USB packet with
|
||||
/// `AnimePacketType::from(buffer)`
|
||||
data: AnimeDataBuffer,
|
||||
delay: Duration,
|
||||
}
|
||||
@@ -33,7 +37,8 @@ impl AnimeFrame {
|
||||
pub enum AnimTime {
|
||||
/// Time in milliseconds for animation to run
|
||||
Time(Duration),
|
||||
/// How many full animation loops to run or how many seconds if image is static
|
||||
/// How many full animation loops to run or how many seconds if image is
|
||||
/// static
|
||||
Count(u32),
|
||||
/// Run for infinite time
|
||||
Infinite,
|
||||
@@ -169,8 +174,8 @@ impl AnimeGif {
|
||||
Ok(Self(frames, duration))
|
||||
}
|
||||
|
||||
/// Create an animation using a gif of any size. This method must precompute the
|
||||
/// result.
|
||||
/// Create an animation using a gif of any size. This method must precompute
|
||||
/// the result.
|
||||
#[inline]
|
||||
pub fn from_gif(
|
||||
file_name: &Path,
|
||||
@@ -243,9 +248,10 @@ impl AnimeGif {
|
||||
Ok(Self(frames, duration))
|
||||
}
|
||||
|
||||
/// Make a static gif out of a greyscale png. If no duration is specified then the default
|
||||
/// will be 1 second long. If `AnimTime::Cycles` is specified for `duration` then this can
|
||||
/// be considered how many seconds the image will show for.
|
||||
/// Make a static gif out of a greyscale png. If no duration is specified
|
||||
/// then the default will be 1 second long. If `AnimTime::Cycles` is
|
||||
/// specified for `duration` then this can be considered how many
|
||||
/// seconds the image will show for.
|
||||
#[inline]
|
||||
pub fn from_png(
|
||||
file_name: &Path,
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
use std::{convert::TryFrom, path::Path};
|
||||
use std::convert::TryFrom;
|
||||
use std::path::Path;
|
||||
|
||||
pub use glam::Vec2;
|
||||
use glam::{Mat3, Vec3};
|
||||
|
||||
use crate::{
|
||||
data::AnimeDataBuffer,
|
||||
error::{AnimeError, Result},
|
||||
AnimeType,
|
||||
};
|
||||
use crate::data::AnimeDataBuffer;
|
||||
use crate::error::{AnimeError, Result};
|
||||
use crate::AnimeType;
|
||||
|
||||
/// A single greyscale + alpha pixel in the image
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
@@ -29,8 +28,8 @@ impl Default for Pixel {
|
||||
/// A single LED position and brightness. The intention of this struct
|
||||
/// is to be used to sample an image and set the LED brightness.
|
||||
///
|
||||
/// The position of the Led in `LedPositions` determines the placement in the final
|
||||
/// data packets when written to the `AniMe`.
|
||||
/// The position of the Led in `LedPositions` determines the placement in the
|
||||
/// final data packets when written to the `AniMe`.
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct Led(f32, f32, u8);
|
||||
|
||||
@@ -73,8 +72,9 @@ pub struct AnimeImage {
|
||||
img_pixels: Vec<Pixel>,
|
||||
/// width of the image
|
||||
width: u32,
|
||||
/// The type of the display. The GA401 and GA402 use the same controller and therefore same ID,
|
||||
/// so the identifier must be by laptop model in `AnimeType`.
|
||||
/// The type of the display. The GA401 and GA402 use the same controller and
|
||||
/// therefore same ID, so the identifier must be by laptop model in
|
||||
/// `AnimeType`.
|
||||
anime_type: AnimeType,
|
||||
}
|
||||
|
||||
@@ -108,9 +108,9 @@ impl AnimeImage {
|
||||
|
||||
/// Scale ratio in CM
|
||||
///
|
||||
/// This is worked out by measuring the physical width of the display from pixel center to
|
||||
/// center, then dividing by `<horizontal LED count> + 0.5`, where the LED count is
|
||||
/// first/longest row.
|
||||
/// This is worked out by measuring the physical width of the display from
|
||||
/// pixel center to center, then dividing by `<horizontal LED count> +
|
||||
/// 0.5`, where the LED count is first/longest row.
|
||||
///
|
||||
/// For GA401 this is `26.8 / (33 + 0.5) = 0.8`
|
||||
/// For GA402 this is `27.4 / (35 + 0.5) = 0.77`
|
||||
@@ -123,9 +123,9 @@ impl AnimeImage {
|
||||
|
||||
/// Scale ratio in CM
|
||||
///
|
||||
/// This is worked out by measuring the physical height of the display from pixel center to
|
||||
/// pixel center, then dividing by `<vertical LED count> + 1.0`, where the LED count is
|
||||
/// first/longest row.
|
||||
/// This is worked out by measuring the physical height of the display from
|
||||
/// pixel center to pixel center, then dividing by `<vertical LED
|
||||
/// count> + 1.0`, where the LED count is first/longest row.
|
||||
///
|
||||
/// For GA401 this is `16.5 / (54.0 + 1.0) = 0.3`
|
||||
/// For GA402 this is `17.3 / (61.0) = 0.283`
|
||||
@@ -136,12 +136,12 @@ impl AnimeImage {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the starting X position for the data we actually require when writing
|
||||
/// it out to LEDs.
|
||||
/// Get the starting X position for the data we actually require when
|
||||
/// writing it out to LEDs.
|
||||
///
|
||||
/// In relation to the display itself you should think of it as a full square grid, so `first_x`
|
||||
/// is the x position on that grid where the LED is actually positioned in relation to the Y.
|
||||
/// ```text
|
||||
/// In relation to the display itself you should think of it as a full
|
||||
/// square grid, so `first_x` is the x position on that grid where the
|
||||
/// LED is actually positioned in relation to the Y. ```text
|
||||
/// +------------+
|
||||
/// | |
|
||||
/// | |
|
||||
@@ -251,8 +251,8 @@ impl AnimeImage {
|
||||
&mut self.img_pixels
|
||||
}
|
||||
|
||||
/// Generate a list of LED positions. These are then used to sample the Image data,
|
||||
/// and will contain their resulting brightness.
|
||||
/// Generate a list of LED positions. These are then used to sample the
|
||||
/// Image data, and will contain their resulting brightness.
|
||||
#[inline]
|
||||
pub fn generate_image_positioning(anime_type: AnimeType) -> Vec<Option<Led>> {
|
||||
(0..AnimeImage::height(anime_type))
|
||||
@@ -274,8 +274,8 @@ impl AnimeImage {
|
||||
/// samples, the result can then been transformed to the appropriate data
|
||||
/// for displaying.
|
||||
///
|
||||
/// The internal for loop iterates over the LED positions, skipping the blank/dead
|
||||
/// pixels if any.
|
||||
/// The internal for loop iterates over the LED positions, skipping the
|
||||
/// blank/dead pixels if any.
|
||||
#[inline]
|
||||
pub fn update(&mut self) {
|
||||
let width = self.width as i32;
|
||||
@@ -343,7 +343,7 @@ impl AnimeImage {
|
||||
}
|
||||
last_was_led = true;
|
||||
} else if last_was_led {
|
||||
//ends.push(idx);
|
||||
// ends.push(idx);
|
||||
last_was_led = false;
|
||||
}
|
||||
}
|
||||
@@ -382,8 +382,9 @@ impl AnimeImage {
|
||||
led_from_px.inverse()
|
||||
}
|
||||
|
||||
/// Generate the base image from inputs. The result can be displayed as is or
|
||||
/// updated via scale, position, or angle then displayed again after `update()`.
|
||||
/// Generate the base image from inputs. The result can be displayed as is
|
||||
/// or updated via scale, position, or angle then displayed again after
|
||||
/// `update()`.
|
||||
#[inline]
|
||||
pub fn from_png(
|
||||
path: &Path,
|
||||
@@ -491,8 +492,8 @@ impl AnimeImage {
|
||||
impl TryFrom<&AnimeImage> for AnimeDataBuffer {
|
||||
type Error = AnimeError;
|
||||
|
||||
/// Do conversion from the nested Vec in `AnimeDataBuffer` to the two required
|
||||
/// packets suitable for sending over USB
|
||||
/// Do conversion from the nested Vec in `AnimeDataBuffer` to the two
|
||||
/// required packets suitable for sending over USB
|
||||
fn try_from(leds: &AnimeImage) -> Result<Self> {
|
||||
let mut l: Vec<u8> = leds
|
||||
.led_pos
|
||||
@@ -511,9 +512,11 @@ impl TryFrom<&AnimeImage> for AnimeDataBuffer {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::{convert::TryFrom, path::PathBuf};
|
||||
use std::convert::TryFrom;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::{image::*, AnimTime, AnimeGif, AnimePacketType};
|
||||
use crate::image::*;
|
||||
use crate::{AnimTime, AnimeGif, AnimePacketType};
|
||||
|
||||
#[test]
|
||||
fn led_positions() {
|
||||
|
||||
@@ -11,8 +11,8 @@ pub use grid::*;
|
||||
mod image;
|
||||
pub use image::*;
|
||||
|
||||
/// A grid of data that is intended to be read out and displayed on the `AniMe` as
|
||||
/// a diagonal
|
||||
/// A grid of data that is intended to be read out and displayed on the `AniMe`
|
||||
/// as a diagonal
|
||||
mod diagonal;
|
||||
pub use diagonal::*;
|
||||
|
||||
@@ -21,8 +21,8 @@ pub use diagonal::*;
|
||||
mod gif;
|
||||
pub use crate::gif::*;
|
||||
|
||||
/// A container of images/grids/gifs/pauses which can be iterated over to generate
|
||||
/// cool effects
|
||||
/// A container of images/grids/gifs/pauses which can be iterated over to
|
||||
/// generate cool effects
|
||||
mod sequencer;
|
||||
pub use sequencer::*;
|
||||
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
use std::convert::TryFrom;
|
||||
use std::path::PathBuf;
|
||||
use std::time::Duration;
|
||||
|
||||
use glam::Vec2;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::convert::TryFrom;
|
||||
use std::{path::PathBuf, time::Duration};
|
||||
|
||||
use crate::{
|
||||
error::Result, AnimTime, AnimeDataBuffer, AnimeDiagonal, AnimeGif, AnimeImage, AnimeType,
|
||||
};
|
||||
use crate::error::Result;
|
||||
use crate::{AnimTime, AnimeDataBuffer, AnimeDiagonal, AnimeGif, AnimeImage, AnimeType};
|
||||
|
||||
/// All the possible `AniMe` actions that can be used. This enum is intended to be
|
||||
/// a helper for loading up `ActionData`.
|
||||
/// All the possible `AniMe` actions that can be used. This enum is intended to
|
||||
/// be a helper for loading up `ActionData`.
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub enum ActionLoader {
|
||||
/// Full gif sequence. Immutable.
|
||||
@@ -23,7 +24,8 @@ pub enum ActionLoader {
|
||||
time: AnimTime,
|
||||
brightness: f32,
|
||||
},
|
||||
/// Animated gif. If the file is a png a static gif is created using the `time` properties
|
||||
/// Animated gif. If the file is a png a static gif is created using the
|
||||
/// `time` properties
|
||||
ImageAnimation {
|
||||
file: PathBuf,
|
||||
scale: f32,
|
||||
@@ -44,13 +46,14 @@ pub enum ActionLoader {
|
||||
Pause(Duration),
|
||||
}
|
||||
|
||||
/// All the possible `AniMe` actions that can be used. The enum is intended to be
|
||||
/// used in a array allowing the user to cycle through a series of actions.
|
||||
/// All the possible `AniMe` actions that can be used. The enum is intended to
|
||||
/// be used in a array allowing the user to cycle through a series of actions.
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub enum ActionData {
|
||||
/// Full gif sequence. Immutable.
|
||||
Animation(AnimeGif),
|
||||
/// Basic image, can have properties changed and image updated via those properties
|
||||
/// Basic image, can have properties changed and image updated via those
|
||||
/// properties
|
||||
Image(Box<AnimeDataBuffer>),
|
||||
/// A pause to be used between sequences
|
||||
Pause(Duration),
|
||||
@@ -174,8 +177,8 @@ impl Sequences {
|
||||
Self(Vec::new(), anime_type)
|
||||
}
|
||||
|
||||
/// Use a base `AnimeAction` to generate the precomputed data and insert in to
|
||||
/// the run buffer
|
||||
/// Use a base `AnimeAction` to generate the precomputed data and insert in
|
||||
/// to the run buffer
|
||||
#[inline]
|
||||
pub fn insert(&mut self, index: usize, action: &ActionLoader) -> Result<()> {
|
||||
self.0
|
||||
@@ -183,9 +186,9 @@ impl Sequences {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Remove an item at this position from the run buffer. If the `index` supplied
|
||||
/// is not in range then `None` is returned, otherwise the `ActionData` at that location
|
||||
/// is yeeted and returned.
|
||||
/// Remove an item at this position from the run buffer. If the `index`
|
||||
/// supplied is not in range then `None` is returned, otherwise the
|
||||
/// `ActionData` at that location is yeeted and returned.
|
||||
#[inline]
|
||||
pub fn remove_item(&mut self, index: usize) -> Option<ActionData> {
|
||||
if index < self.0.len() {
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
//! Utils for writing to the `AniMe` USB device
|
||||
//!
|
||||
//! Use of the device requires a few steps:
|
||||
//! 1. Initialise the device by writing the two packets from `get_init_packets()`
|
||||
//! 2. Write data from `AnimePacketType`
|
||||
//! 3. Write the packet from `get_flush_packet()`, which tells the device to display the data from step 2
|
||||
//! 1. Initialise the device by writing the two packets from
|
||||
//! `get_init_packets()` 2. Write data from `AnimePacketType`
|
||||
//! 3. Write the packet from `get_flush_packet()`, which tells the device to
|
||||
//! display the data from step 2
|
||||
//!
|
||||
//! Step 1 need to applied only on fresh system boot.
|
||||
|
||||
use crate::{error::AnimeError, AnimeType};
|
||||
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'.',
|
||||
@@ -17,8 +19,9 @@ const DEV_PAGE: u8 = 0x5e;
|
||||
pub const VENDOR_ID: u16 = 0x0b05;
|
||||
pub const PROD_ID: u16 = 0x193b;
|
||||
|
||||
/// `get_anime_type` is very broad, matching on part of the laptop board name only. For this
|
||||
/// reason `find_node()` must be used also to verify if the USB device is available.
|
||||
/// `get_anime_type` is very broad, matching on part of the laptop board name
|
||||
/// only. For this reason `find_node()` must be used also to verify if the USB
|
||||
/// device is available.
|
||||
///
|
||||
/// The currently known USB device is `19b6`.
|
||||
#[inline]
|
||||
@@ -34,8 +37,8 @@ pub fn get_anime_type() -> Result<AnimeType, AnimeError> {
|
||||
Err(AnimeError::UnsupportedDevice)
|
||||
}
|
||||
|
||||
/// Get the two device initialization packets. These are required for device start
|
||||
/// after the laptop boots.
|
||||
/// Get the two device initialization packets. These are required for device
|
||||
/// start after the laptop boots.
|
||||
#[inline]
|
||||
pub const fn pkts_for_init() -> [[u8; PACKET_SIZE]; 2] {
|
||||
let mut packets = [[0; PACKET_SIZE]; 2];
|
||||
@@ -74,8 +77,8 @@ pub const fn pkt_for_set_boot(status: bool) -> [u8; PACKET_SIZE] {
|
||||
pkt
|
||||
}
|
||||
|
||||
/// Get the packet required for setting the device to on. Requires `pkt_for_apply()`
|
||||
/// to be written after.
|
||||
/// Get the packet required for setting the device to on. Requires
|
||||
/// `pkt_for_apply()` to be written after.
|
||||
#[inline]
|
||||
pub const fn pkt_for_set_on(on: bool) -> [u8; PACKET_SIZE] {
|
||||
let mut pkt = [0; PACKET_SIZE];
|
||||
|
||||
Reference in New Issue
Block a user