mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
split out types, dbus
This commit is contained in:
238
rog-types/src/anime_matrix.rs
Normal file
238
rog-types/src/anime_matrix.rs
Normal file
@@ -0,0 +1,238 @@
|
||||
pub const WIDTH: usize = 34; // Width is definitely 34 items
|
||||
pub const HEIGHT: usize = 56;
|
||||
pub type AniMeBufferType = [[u8; WIDTH]; HEIGHT];
|
||||
pub type AniMePacketType = [[u8; 640]; 2];
|
||||
const BLOCK_START: usize = 7;
|
||||
const BLOCK_END: usize = 634;
|
||||
|
||||
pub const ANIME_PANE1_PREFIX: [u8; 7] = [0x5e, 0xc0, 0x02, 0x01, 0x00, 0x73, 0x02];
|
||||
pub const ANIME_PANE2_PREFIX: [u8; 7] = [0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02];
|
||||
|
||||
/// Helper structure for writing images.
|
||||
///
|
||||
/// See the examples for ways to write an image to `AniMeMatrix` format.
|
||||
pub struct AniMeMatrix(AniMeBufferType);
|
||||
|
||||
impl Default for AniMeMatrix {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl AniMeMatrix {
|
||||
pub fn new() -> Self {
|
||||
AniMeMatrix([[0u8; WIDTH]; HEIGHT])
|
||||
}
|
||||
|
||||
pub fn get(&self) -> &AniMeBufferType {
|
||||
&self.0
|
||||
}
|
||||
|
||||
pub fn get_mut(&mut self) -> &mut AniMeBufferType {
|
||||
&mut self.0
|
||||
}
|
||||
|
||||
pub fn fill_with(&mut self, fill: u8) {
|
||||
for row in self.0.iter_mut() {
|
||||
for x in row.iter_mut() {
|
||||
*x = fill;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn debug_print(&self) {
|
||||
// this is the index from right. It is used to progressively shorten rows
|
||||
let mut prog_row_len = WIDTH - 2;
|
||||
|
||||
for (count, row) in self.0.iter().enumerate() {
|
||||
// Write the top block of LEDs (first 7 rows)
|
||||
if count < 6 {
|
||||
if count % 2 != 0 {
|
||||
print!(" ");
|
||||
} else {
|
||||
print!("");
|
||||
}
|
||||
let tmp = if count == 0 || count == 1 || count == 3 || count == 5 {
|
||||
row[1..].iter()
|
||||
} else {
|
||||
row.iter()
|
||||
};
|
||||
for _ in tmp {
|
||||
print!(" XY");
|
||||
}
|
||||
|
||||
println!();
|
||||
} else {
|
||||
// Switch to next block (looks like )
|
||||
if count % 2 != 0 {
|
||||
// Row after 6 is only 1 less, then rows after 7 follow pattern
|
||||
if count == 7 {
|
||||
prog_row_len -= 1;
|
||||
} else {
|
||||
prog_row_len -= 2;
|
||||
}
|
||||
} else {
|
||||
prog_row_len += 1; // if count 6, 0
|
||||
}
|
||||
|
||||
let index = row.len() - prog_row_len;
|
||||
|
||||
if count % 2 == 0 {
|
||||
print!(" ");
|
||||
}
|
||||
for (i, _) in row.iter().enumerate() {
|
||||
if i >= index {
|
||||
print!(" XY");
|
||||
} else {
|
||||
print!(" ");
|
||||
}
|
||||
}
|
||||
println!();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AniMeMatrix> for AniMePacketType {
|
||||
/// Do conversion from the nested Vec in AniMeMatrix to the two required
|
||||
/// packets suitable for sending over USB
|
||||
#[inline]
|
||||
fn from(anime: AniMeMatrix) -> Self {
|
||||
let mut buffers = [[0; 640]; 2];
|
||||
|
||||
let mut write_index = BLOCK_START;
|
||||
let mut write_block = &mut buffers[0];
|
||||
let mut block1_done = false;
|
||||
|
||||
// this is the index from right. It is used to progressively shorten rows
|
||||
let mut prog_row_len = WIDTH - 2;
|
||||
|
||||
for (count, row) in anime.0.iter().enumerate() {
|
||||
// Write the top block of LEDs (first 7 rows)
|
||||
if count < 6 {
|
||||
for (i, x) in row.iter().enumerate() {
|
||||
// Rows 0, 1, 3, 5 are short and misaligned
|
||||
if count == 0 || count == 1 || count == 3 || count == 5 {
|
||||
if i > 0 {
|
||||
write_block[write_index - 1] = *x;
|
||||
}
|
||||
} else {
|
||||
write_block[write_index] = *x;
|
||||
}
|
||||
write_index += 1;
|
||||
}
|
||||
} else {
|
||||
// Switch to next block (looks like )
|
||||
if count % 2 != 0 {
|
||||
// Row after 6 is only 1 less, then rows after 7 follow pattern
|
||||
if count == 7 {
|
||||
prog_row_len -= 1;
|
||||
} else {
|
||||
prog_row_len -= 2;
|
||||
}
|
||||
} else {
|
||||
prog_row_len += 1; // if count 6, 0
|
||||
}
|
||||
|
||||
let index = row.len() - prog_row_len;
|
||||
for n in row.iter().skip(index) {
|
||||
// Require a special case to catch the correct end-of-packet which is
|
||||
// 6 bytes from the end
|
||||
if write_index == BLOCK_END && !block1_done {
|
||||
block1_done = true;
|
||||
write_block = &mut buffers[1];
|
||||
write_index = BLOCK_START;
|
||||
}
|
||||
|
||||
write_block[write_index] = *n;
|
||||
write_index += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
buffers
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::anime_matrix::{AniMeMatrix, AniMePacketType};
|
||||
|
||||
#[test]
|
||||
fn check_data_alignment() {
|
||||
let mut matrix = AniMeMatrix::new();
|
||||
{
|
||||
let tmp = matrix.get_mut();
|
||||
for row in tmp.iter_mut() {
|
||||
row[row.len() - 1] = 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
let matrix: AniMePacketType = AniMePacketType::from(matrix);
|
||||
|
||||
// The bytes at the right of the initial AniMeMatrix should always end up aligned in the
|
||||
// same place after conversion to data packets
|
||||
|
||||
// Check against manually worked out right align
|
||||
assert_eq!(
|
||||
matrix[0].to_vec(),
|
||||
[
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
]
|
||||
.to_vec()
|
||||
);
|
||||
assert_eq!(
|
||||
matrix[1].to_vec(),
|
||||
[
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0,
|
||||
0, 0, 0, 0
|
||||
]
|
||||
.to_vec()
|
||||
);
|
||||
}
|
||||
}
|
||||
310
rog-types/src/aura_modes.rs
Normal file
310
rog-types/src/aura_modes.rs
Normal file
@@ -0,0 +1,310 @@
|
||||
use crate::cli_options::SetAuraBuiltin;
|
||||
use crate::error::AuraError;
|
||||
use gumdrop::Options;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::str::FromStr;
|
||||
|
||||
pub const STATIC: u8 = 0x00;
|
||||
pub const BREATHING: u8 = 0x01;
|
||||
pub const STROBE: u8 = 0x02;
|
||||
pub const RAINBOW: u8 = 0x03;
|
||||
pub const STAR: u8 = 0x04;
|
||||
pub const RAIN: u8 = 0x05;
|
||||
pub const HIGHLIGHT: u8 = 0x06;
|
||||
pub const LASER: u8 = 0x07;
|
||||
pub const RIPPLE: u8 = 0x08;
|
||||
pub const PULSE: u8 = 0x0a;
|
||||
pub const COMET: u8 = 0x0b;
|
||||
pub const FLASH: u8 = 0x0c;
|
||||
pub const MULTISTATIC: u8 = 0x0d;
|
||||
pub const MULTIBREATHE: u8 = 0x0e;
|
||||
pub const PER_KEY: u8 = 0xff;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct Colour(pub u8, pub u8, pub u8);
|
||||
|
||||
impl Default for Colour {
|
||||
fn default() -> Self {
|
||||
Colour(128, 0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Colour {
|
||||
type Err = AuraError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
if s.len() < 6 {
|
||||
return Err(AuraError::ParseColour);
|
||||
}
|
||||
let r = u8::from_str_radix(&s[0..2], 16).or(Err(AuraError::ParseColour))?;
|
||||
let g = u8::from_str_radix(&s[2..4], 16).or(Err(AuraError::ParseColour))?;
|
||||
let b = u8::from_str_radix(&s[4..6], 16).or(Err(AuraError::ParseColour))?;
|
||||
Ok(Colour(r, g, b))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Deserialize, Serialize)]
|
||||
pub enum Speed {
|
||||
Low = 0xe1,
|
||||
Med = 0xeb,
|
||||
High = 0xf5,
|
||||
}
|
||||
impl Default for Speed {
|
||||
fn default() -> Self {
|
||||
Speed::Med
|
||||
}
|
||||
}
|
||||
impl FromStr for Speed {
|
||||
type Err = AuraError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let s = s.to_lowercase();
|
||||
match s.as_str() {
|
||||
"low" => Ok(Speed::Low),
|
||||
"med" => Ok(Speed::Med),
|
||||
"high" => Ok(Speed::High),
|
||||
_ => Err(AuraError::ParseSpeed),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Used for Rainbow mode.
|
||||
///
|
||||
/// Enum corresponds to the required integer value
|
||||
#[derive(Debug, Copy, Clone, Deserialize, Serialize)]
|
||||
pub enum Direction {
|
||||
Right,
|
||||
Left,
|
||||
Up,
|
||||
Down,
|
||||
}
|
||||
impl Default for Direction {
|
||||
fn default() -> Self {
|
||||
Direction::Right
|
||||
}
|
||||
}
|
||||
impl FromStr for Direction {
|
||||
type Err = AuraError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let s = s.to_lowercase();
|
||||
match s.as_str() {
|
||||
"right" => Ok(Direction::Right),
|
||||
"up" => Ok(Direction::Up),
|
||||
"down" => Ok(Direction::Down),
|
||||
"left" => Ok(Direction::Left),
|
||||
_ => Err(AuraError::ParseDirection),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Options, Default, Deserialize, Serialize)]
|
||||
pub struct SingleSpeed {
|
||||
#[serde(skip)]
|
||||
#[options(help = "print help message")]
|
||||
help: bool,
|
||||
#[options(no_long, meta = "WORD", help = "set the speed: low, med, high")]
|
||||
pub speed: Speed,
|
||||
}
|
||||
#[derive(Debug, Clone, Options, Default, Deserialize, Serialize)]
|
||||
pub struct SingleSpeedDirection {
|
||||
#[serde(skip)]
|
||||
#[options(help = "print help message")]
|
||||
help: bool,
|
||||
#[options(no_long, meta = "", help = "set the direction: up, down, left, right")]
|
||||
pub direction: Direction,
|
||||
#[options(no_long, meta = "", help = "set the speed: low, med, high")]
|
||||
pub speed: Speed,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Options, Deserialize, Serialize)]
|
||||
pub struct SingleColour {
|
||||
#[serde(skip)]
|
||||
#[options(help = "print help message")]
|
||||
help: bool,
|
||||
#[options(no_long, meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||
pub colour: Colour,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Options, Deserialize, Serialize)]
|
||||
pub struct SingleColourSpeed {
|
||||
#[serde(skip)]
|
||||
#[options(help = "print help message")]
|
||||
help: bool,
|
||||
#[options(no_long, meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||
pub colour: Colour,
|
||||
#[options(no_long, meta = "", help = "set the speed: low, med, high")]
|
||||
pub speed: Speed,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Options, Default, Deserialize, Serialize)]
|
||||
pub struct TwoColourSpeed {
|
||||
#[serde(skip)]
|
||||
#[options(help = "print help message")]
|
||||
help: bool,
|
||||
#[options(no_long, meta = "", help = "set the first RGB value e.g, ff00ff")]
|
||||
pub colour: Colour,
|
||||
#[options(no_long, meta = "", help = "set the second RGB value e.g, ff00ff")]
|
||||
pub colour2: Colour,
|
||||
#[options(no_long, meta = "", help = "set the speed: low, med, high")]
|
||||
pub speed: Speed,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Options, Deserialize, Serialize)]
|
||||
pub struct MultiColour {
|
||||
#[serde(skip)]
|
||||
#[options(help = "print help message")]
|
||||
help: bool,
|
||||
#[options(short = "a", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||
pub colour1: Colour,
|
||||
#[options(short = "b", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||
pub colour2: Colour,
|
||||
#[options(short = "c", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||
pub colour3: Colour,
|
||||
#[options(short = "d", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||
pub colour4: Colour,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Options, Deserialize, Serialize)]
|
||||
pub struct MultiColourSpeed {
|
||||
#[options(help = "print help message")]
|
||||
help: bool,
|
||||
#[options(short = "a", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||
pub colour1: Colour,
|
||||
#[options(short = "b", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||
pub colour2: Colour,
|
||||
#[options(short = "c", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||
pub colour3: Colour,
|
||||
#[options(short = "d", meta = "", help = "set the RGB value e.g, ff00ff")]
|
||||
pub colour4: Colour,
|
||||
#[options(no_long, meta = "", help = "set the speed: low, med, high")]
|
||||
pub speed: Speed,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub enum AuraModes {
|
||||
Static(SingleColour),
|
||||
Breathe(TwoColourSpeed),
|
||||
Strobe(SingleSpeed),
|
||||
Rainbow(SingleSpeedDirection),
|
||||
Star(TwoColourSpeed),
|
||||
Rain(SingleSpeed),
|
||||
Highlight(SingleColourSpeed),
|
||||
Laser(SingleColourSpeed),
|
||||
Ripple(SingleColourSpeed),
|
||||
Pulse(SingleColour),
|
||||
Comet(SingleColour),
|
||||
Flash(SingleColour),
|
||||
MultiStatic(MultiColour),
|
||||
MultiBreathe(MultiColourSpeed),
|
||||
LedBrightness(u8),
|
||||
// TODO: use a serializable structure for this (KeyColourArray)
|
||||
PerKey(Vec<Vec<u8>>),
|
||||
}
|
||||
|
||||
impl From<SetAuraBuiltin> for AuraModes {
|
||||
fn from(mode: SetAuraBuiltin) -> Self {
|
||||
match mode {
|
||||
SetAuraBuiltin::Static(x) => AuraModes::Static(x.into()),
|
||||
SetAuraBuiltin::Breathe(x) => AuraModes::Breathe(x.into()),
|
||||
SetAuraBuiltin::Strobe(x) => AuraModes::Strobe(x.into()),
|
||||
SetAuraBuiltin::Rainbow(x) => AuraModes::Rainbow(x.into()),
|
||||
SetAuraBuiltin::Star(x) => AuraModes::Star(x.into()),
|
||||
SetAuraBuiltin::Rain(x) => AuraModes::Rain(x.into()),
|
||||
SetAuraBuiltin::Highlight(x) => AuraModes::Highlight(x.into()),
|
||||
SetAuraBuiltin::Laser(x) => AuraModes::Laser(x.into()),
|
||||
SetAuraBuiltin::Ripple(x) => AuraModes::Ripple(x.into()),
|
||||
SetAuraBuiltin::Pulse(x) => AuraModes::Pulse(x.into()),
|
||||
SetAuraBuiltin::Comet(x) => AuraModes::Comet(x.into()),
|
||||
SetAuraBuiltin::Flash(x) => AuraModes::Flash(x.into()),
|
||||
SetAuraBuiltin::MultiStatic(x) => AuraModes::MultiStatic(x.into()),
|
||||
SetAuraBuiltin::MultiBreathe(x) => AuraModes::MultiBreathe(x.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Very specific mode conversion required because numbering isn't linear
|
||||
impl From<AuraModes> for u8 {
|
||||
fn from(mode: AuraModes) -> Self {
|
||||
u8::from(&mode)
|
||||
}
|
||||
}
|
||||
|
||||
/// Very specific mode conversion required because numbering isn't linear
|
||||
impl From<&mut AuraModes> for u8 {
|
||||
fn from(mode: &mut AuraModes) -> Self {
|
||||
u8::from(&*mode)
|
||||
}
|
||||
}
|
||||
|
||||
/// Very specific mode conversion required because numbering isn't linear
|
||||
impl From<&AuraModes> for u8 {
|
||||
fn from(mode: &AuraModes) -> Self {
|
||||
match mode {
|
||||
AuraModes::Static(_) => STATIC,
|
||||
AuraModes::Breathe(_) => BREATHING,
|
||||
AuraModes::Strobe(_) => STROBE,
|
||||
AuraModes::Rainbow(_) => RAINBOW,
|
||||
AuraModes::Star(_) => STAR,
|
||||
AuraModes::Rain(_) => RAIN,
|
||||
AuraModes::Highlight(_) => HIGHLIGHT,
|
||||
AuraModes::Laser(_) => LASER,
|
||||
AuraModes::Ripple(_) => RIPPLE,
|
||||
AuraModes::Pulse(_) => PULSE,
|
||||
AuraModes::Comet(_) => COMET,
|
||||
AuraModes::Flash(_) => FLASH,
|
||||
AuraModes::MultiStatic(_) => MULTISTATIC,
|
||||
AuraModes::MultiBreathe(_) => MULTIBREATHE,
|
||||
AuraModes::PerKey(_) => PER_KEY,
|
||||
_ => panic!("Invalid mode"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&AuraModes> for &str {
|
||||
fn from(mode: &AuraModes) -> Self {
|
||||
match mode {
|
||||
AuraModes::Static(_) => "Static",
|
||||
AuraModes::Breathe(_) => "Breathing",
|
||||
AuraModes::Strobe(_) => "Strobing",
|
||||
AuraModes::Rainbow(_) => "Rainbow",
|
||||
AuraModes::Star(_) => "Stars",
|
||||
AuraModes::Rain(_) => "Rain",
|
||||
AuraModes::Highlight(_) => "Keypress Highlight",
|
||||
AuraModes::Laser(_) => "Keypress Laser",
|
||||
AuraModes::Ripple(_) => "Keypress Ripple",
|
||||
AuraModes::Pulse(_) => "Pulse",
|
||||
AuraModes::Comet(_) => "Comet",
|
||||
AuraModes::Flash(_) => "Flash",
|
||||
AuraModes::MultiStatic(_) => "4-Zone Static Colours",
|
||||
AuraModes::MultiBreathe(_) => "4-Zone Breathing Colours",
|
||||
AuraModes::PerKey(_) => "RGB per-key",
|
||||
_ => panic!("Invalid mode"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Exists to convert back from correct bytes. PER_KEY byte intentionally left off as it
|
||||
/// does not correspond to an actual pre-set mode, nor does brightness.
|
||||
impl From<u8> for AuraModes {
|
||||
fn from(byte: u8) -> Self {
|
||||
match byte {
|
||||
STATIC => AuraModes::Static(SingleColour::default()),
|
||||
BREATHING => AuraModes::Breathe(TwoColourSpeed::default()),
|
||||
STROBE => AuraModes::Strobe(SingleSpeed::default()),
|
||||
RAINBOW => AuraModes::Rainbow(SingleSpeedDirection::default()),
|
||||
STAR => AuraModes::Star(TwoColourSpeed::default()),
|
||||
RAIN => AuraModes::Rain(SingleSpeed::default()),
|
||||
HIGHLIGHT => AuraModes::Highlight(SingleColourSpeed::default()),
|
||||
LASER => AuraModes::Laser(SingleColourSpeed::default()),
|
||||
RIPPLE => AuraModes::Ripple(SingleColourSpeed::default()),
|
||||
PULSE => AuraModes::Pulse(SingleColour::default()),
|
||||
COMET => AuraModes::Comet(SingleColour::default()),
|
||||
FLASH => AuraModes::Flash(SingleColour::default()),
|
||||
MULTISTATIC => AuraModes::MultiStatic(MultiColour::default()),
|
||||
MULTIBREATHE => AuraModes::MultiBreathe(MultiColourSpeed::default()),
|
||||
PER_KEY => AuraModes::PerKey(vec![]),
|
||||
_ => panic!("Invalid mode byte"),
|
||||
}
|
||||
}
|
||||
}
|
||||
150
rog-types/src/cli_options.rs
Normal file
150
rog-types/src/cli_options.rs
Normal file
@@ -0,0 +1,150 @@
|
||||
use crate::{
|
||||
aura_modes::{
|
||||
MultiColour, MultiColourSpeed, SingleColour, SingleColourSpeed, SingleSpeed,
|
||||
SingleSpeedDirection, TwoColourSpeed,
|
||||
},
|
||||
error::AuraError,
|
||||
};
|
||||
use gumdrop::Options;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(Options)]
|
||||
pub struct LedBrightness {
|
||||
level: Option<u8>,
|
||||
}
|
||||
impl LedBrightness {
|
||||
pub fn new(level: Option<u8>) -> Self {
|
||||
LedBrightness { level }
|
||||
}
|
||||
|
||||
pub fn level(&self) -> Option<u8> {
|
||||
self.level
|
||||
}
|
||||
}
|
||||
impl FromStr for LedBrightness {
|
||||
type Err = AuraError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let s = s.to_lowercase();
|
||||
match s.as_str() {
|
||||
"off" => Ok(LedBrightness { level: Some(0x00) }),
|
||||
"low" => Ok(LedBrightness { level: Some(0x01) }),
|
||||
"med" => Ok(LedBrightness { level: Some(0x02) }),
|
||||
"high" => Ok(LedBrightness { level: Some(0x03) }),
|
||||
_ => {
|
||||
print!(
|
||||
"{}\n{}\n",
|
||||
"Invalid argument, must be one of:", "off, low, med, high"
|
||||
);
|
||||
Err(AuraError::ParseBrightness)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
impl ToString for LedBrightness {
|
||||
fn to_string(&self) -> String {
|
||||
let s = match self.level {
|
||||
Some(0x00) => "low",
|
||||
Some(0x01) => "med",
|
||||
Some(0x02) => "high",
|
||||
_ => "unknown",
|
||||
};
|
||||
s.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
/// Byte value for setting the built-in mode.
|
||||
///
|
||||
/// Enum corresponds to the required integer value
|
||||
#[derive(Options, Deserialize, Serialize)]
|
||||
pub enum SetAuraBuiltin {
|
||||
#[options(help = "set a single static colour")]
|
||||
Static(SingleColour),
|
||||
#[options(help = "pulse between one or two colours")]
|
||||
Breathe(TwoColourSpeed),
|
||||
#[options(help = "strobe through all colours")]
|
||||
Strobe(SingleSpeed),
|
||||
#[options(help = "rainbow cycling in one of four directions")]
|
||||
Rainbow(SingleSpeedDirection),
|
||||
#[options(help = "rain pattern mimicking raindrops")]
|
||||
Star(TwoColourSpeed),
|
||||
#[options(help = "rain pattern of three preset colours")]
|
||||
Rain(SingleSpeed),
|
||||
#[options(help = "pressed keys are highlighted to fade")]
|
||||
Highlight(SingleColourSpeed),
|
||||
#[options(help = "pressed keys generate horizontal laser")]
|
||||
Laser(SingleColourSpeed),
|
||||
#[options(help = "pressed keys ripple outwards like a splash")]
|
||||
Ripple(SingleColourSpeed),
|
||||
#[options(help = "set a rapid pulse")]
|
||||
Pulse(SingleColour),
|
||||
#[options(help = "set a vertical line zooming from left")]
|
||||
Comet(SingleColour),
|
||||
#[options(help = "set a wide vertical line zooming from left")]
|
||||
Flash(SingleColour),
|
||||
#[options(help = "4-zone multi-colour")]
|
||||
MultiStatic(MultiColour),
|
||||
#[options(help = "4-zone multi-colour breathing")]
|
||||
MultiBreathe(MultiColourSpeed),
|
||||
}
|
||||
|
||||
impl Default for SetAuraBuiltin {
|
||||
fn default() -> Self {
|
||||
SetAuraBuiltin::Static(SingleColour::default())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum AniMeStatusValue {
|
||||
On,
|
||||
Off,
|
||||
}
|
||||
impl FromStr for AniMeStatusValue {
|
||||
type Err = AuraError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let s = s.to_lowercase();
|
||||
match s.as_str() {
|
||||
"on" => Ok(AniMeStatusValue::On),
|
||||
"off" => Ok(AniMeStatusValue::Off),
|
||||
_ => {
|
||||
print!("{}\n{}\n", "Invalid argument, must be one of:", "on, off");
|
||||
Err(AuraError::ParseAnime)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
impl From<AniMeStatusValue> for bool {
|
||||
fn from(value: AniMeStatusValue) -> Self {
|
||||
match value {
|
||||
AniMeStatusValue::On => true,
|
||||
AniMeStatusValue::Off => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Options)]
|
||||
pub struct AniMeLeds {
|
||||
#[options(help = "print help message")]
|
||||
help: bool,
|
||||
#[options(
|
||||
no_long,
|
||||
required,
|
||||
short = "b",
|
||||
meta = "",
|
||||
help = "set all leds brightness value"
|
||||
)]
|
||||
led_brightness: u8,
|
||||
}
|
||||
impl AniMeLeds {
|
||||
pub fn led_brightness(&self) -> u8 {
|
||||
self.led_brightness
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Options)]
|
||||
pub enum AniMeActions {
|
||||
#[options(help = "change all leds brightness")]
|
||||
Leds(AniMeLeds),
|
||||
}
|
||||
42
rog-types/src/error.rs
Normal file
42
rog-types/src/error.rs
Normal file
@@ -0,0 +1,42 @@
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum AuraError {
|
||||
ParseColour,
|
||||
ParseSpeed,
|
||||
ParseDirection,
|
||||
ParseBrightness,
|
||||
ParseAnime,
|
||||
}
|
||||
|
||||
impl fmt::Display for AuraError {
|
||||
// This trait requires `fmt` with this exact signature.
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
AuraError::ParseColour => write!(f, "Could not parse colour"),
|
||||
AuraError::ParseSpeed => write!(f, "Could not parse speed"),
|
||||
AuraError::ParseDirection => write!(f, "Could not parse direction"),
|
||||
AuraError::ParseBrightness => write!(f, "Could not parse brightness"),
|
||||
AuraError::ParseAnime => write!(f, "Could not parse anime"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for AuraError {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum GraphicsError {
|
||||
ParseVendor,
|
||||
}
|
||||
|
||||
impl fmt::Display for GraphicsError {
|
||||
// This trait requires `fmt` with this exact signature.
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
GraphicsError::ParseVendor => write!(f, "Could not parse vendor name"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for GraphicsError {}
|
||||
455
rog-types/src/fancy.rs
Normal file
455
rog-types/src/fancy.rs
Normal file
@@ -0,0 +1,455 @@
|
||||
/// A `KeyColourArray` contains all data to change the full set of keyboard
|
||||
/// key colours individually.
|
||||
///
|
||||
/// Each row of the internal array is a full HID packet that can be sent
|
||||
/// to the keyboard EC. One row controls one group of keys, these keys are not
|
||||
/// necessarily all on the same row of the keyboard, with some splitting between
|
||||
/// two rows.
|
||||
#[derive(Clone)]
|
||||
pub struct KeyColourArray([[u8; 64]; 11]);
|
||||
impl Default for KeyColourArray {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
impl KeyColourArray {
|
||||
pub fn new() -> Self {
|
||||
let mut set = [[0u8; 64]; 11];
|
||||
for (count, row) in set.iter_mut().enumerate() {
|
||||
row[0] = 0x5d; // Report ID
|
||||
row[1] = 0xbc; // Mode = custom??, 0xb3 is builtin
|
||||
row[2] = 0x00;
|
||||
row[3] = 0x01; // ??
|
||||
row[4] = 0x01; // ??, 4,5,6 are normally RGB for builtin mode colours
|
||||
row[5] = 0x01; // ??
|
||||
row[6] = (count as u8) << 4; // Key group
|
||||
if count == 10 {
|
||||
row[7] = 0x08; // 0b00001000
|
||||
} else {
|
||||
row[7] = 0x10; // 0b00010000 addressing? flips for group a0
|
||||
}
|
||||
row[8] = 0x00;
|
||||
}
|
||||
KeyColourArray(set)
|
||||
}
|
||||
|
||||
/// Initialise and clear the keyboard for custom effects
|
||||
#[inline]
|
||||
pub fn get_init_msg() -> Vec<u8> {
|
||||
let mut init = vec![0u8; 64];
|
||||
init[0] = 0x5d; // Report ID
|
||||
init[1] = 0xbc; // Mode = custom??, 0xb3 is builtin
|
||||
init
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set(&mut self, key: Key, r: u8, g: u8, b: u8) {
|
||||
if let Some((rr, gg, bb)) = self.key(key) {
|
||||
*rr = r;
|
||||
*gg = g;
|
||||
*bb = b;
|
||||
}
|
||||
}
|
||||
|
||||
/// Indexes in to `KeyColourArray` at the correct row and column
|
||||
/// to set a series of three bytes to the chosen R,G,B values
|
||||
pub fn key(&mut self, key: Key) -> Option<(&mut u8, &mut u8, &mut u8)> {
|
||||
// Tuples are indexes in to array
|
||||
let (row, col) = match key {
|
||||
Key::VolDown => (0, 15),
|
||||
Key::VolUp => (0, 18),
|
||||
Key::MicMute => (0, 21),
|
||||
Key::ROG => (0, 24),
|
||||
//
|
||||
Key::Esc => (1, 24),
|
||||
Key::F1 => (1, 30),
|
||||
Key::F2 => (1, 33),
|
||||
Key::F3 => (1, 36),
|
||||
Key::F4 => (1, 39),
|
||||
Key::F5 => (1, 45),
|
||||
Key::F6 => (1, 48),
|
||||
Key::F7 => (1, 51),
|
||||
Key::F8 => (1, 54),
|
||||
//
|
||||
Key::F9 => (2, 12),
|
||||
Key::F10 => (2, 15),
|
||||
Key::F11 => (2, 18),
|
||||
Key::F12 => (2, 21),
|
||||
Key::Del => (2, 24),
|
||||
Key::Tilde => (2, 39),
|
||||
Key::N1 => (2, 42),
|
||||
Key::N2 => (2, 45),
|
||||
Key::N3 => (2, 48),
|
||||
Key::N4 => (2, 51),
|
||||
Key::N5 => (2, 54),
|
||||
//
|
||||
Key::N6 => (3, 9),
|
||||
Key::N7 => (3, 12),
|
||||
Key::N8 => (3, 15),
|
||||
Key::N9 => (3, 18),
|
||||
Key::N0 => (3, 21),
|
||||
Key::Hyphen => (3, 24),
|
||||
Key::Equals => (3, 27),
|
||||
Key::BkSpc1 => (3, 30),
|
||||
Key::BkSpc2 => (3, 33),
|
||||
Key::BkSpc3 => (3, 36),
|
||||
Key::Home => (3, 39),
|
||||
Key::Tab => (3, 54),
|
||||
//
|
||||
Key::Q => (4, 9),
|
||||
Key::W => (4, 12),
|
||||
Key::E => (4, 15),
|
||||
Key::R => (4, 18),
|
||||
Key::T => (4, 21),
|
||||
Key::Y => (4, 24),
|
||||
Key::U => (4, 27),
|
||||
Key::I => (4, 30),
|
||||
Key::O => (4, 33),
|
||||
Key::P => (4, 36),
|
||||
Key::LBracket => (4, 39),
|
||||
Key::RBracket => (4, 42),
|
||||
Key::BackSlash => (4, 45),
|
||||
Key::PgUp => (4, 54),
|
||||
//
|
||||
Key::Caps => (5, 21),
|
||||
Key::A => (5, 24),
|
||||
Key::S => (5, 27),
|
||||
Key::D => (5, 30),
|
||||
Key::F => (5, 33),
|
||||
Key::G => (5, 36),
|
||||
Key::H => (5, 39),
|
||||
Key::J => (5, 42),
|
||||
Key::K => (5, 45),
|
||||
Key::L => (5, 48),
|
||||
Key::SemiColon => (5, 51),
|
||||
Key::Quote => (5, 54),
|
||||
//
|
||||
Key::Ret1 => (6, 12),
|
||||
Key::Ret2 => (6, 15),
|
||||
Key::Ret3 => (6, 18),
|
||||
Key::PgDn => (6, 21),
|
||||
Key::LShift => (6, 36),
|
||||
Key::Z => (6, 42),
|
||||
Key::X => (6, 45),
|
||||
Key::C => (6, 48),
|
||||
Key::V => (6, 51),
|
||||
Key::B => (6, 54),
|
||||
//
|
||||
Key::N => (7, 9),
|
||||
Key::M => (7, 12),
|
||||
Key::Comma => (7, 15),
|
||||
Key::Period => (7, 18),
|
||||
Key::FwdSlash => (7, 21),
|
||||
Key::Rshift1 => (7, 27),
|
||||
Key::Rshift2 => (7, 30),
|
||||
Key::Rshift3 => (7, 33),
|
||||
Key::End => (7, 36),
|
||||
Key::LCtrl => (7, 51),
|
||||
Key::LFn => (7, 54),
|
||||
//
|
||||
Key::Meta => (8, 9),
|
||||
Key::LAlt => (8, 12),
|
||||
Key::Space1 => (8, 15),
|
||||
Key::Space2 => (8, 18),
|
||||
Key::Space3 => (8, 21),
|
||||
Key::Space4 => (8, 24),
|
||||
Key::RAlt => (8, 30),
|
||||
Key::PrtSc => (8, 33),
|
||||
Key::RCtrl => (8, 36),
|
||||
Key::Up => (8, 42),
|
||||
Key::RFn => (8, 51),
|
||||
//
|
||||
Key::Left => (9, 54),
|
||||
//
|
||||
Key::Down => (10, 9),
|
||||
Key::Right => (10, 12),
|
||||
Key::None => return None,
|
||||
};
|
||||
// LOLOLOLOLOLOLOL! Look it's safe okay
|
||||
unsafe {
|
||||
Some((
|
||||
&mut *(&mut self.0[row][col] as *mut u8),
|
||||
&mut *(&mut self.0[row][col + 1] as *mut u8),
|
||||
&mut *(&mut self.0[row][col + 2] as *mut u8),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get(&self) -> &[[u8; 64]; 11] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||
pub enum Key {
|
||||
VolUp,
|
||||
VolDown,
|
||||
MicMute,
|
||||
ROG,
|
||||
Esc,
|
||||
F1,
|
||||
F2,
|
||||
F3,
|
||||
F4,
|
||||
F5,
|
||||
F6,
|
||||
F7,
|
||||
F8,
|
||||
F9,
|
||||
F10,
|
||||
F11,
|
||||
F12,
|
||||
Del,
|
||||
Tilde,
|
||||
N1,
|
||||
N2,
|
||||
N3,
|
||||
N4,
|
||||
N5,
|
||||
N6,
|
||||
N7,
|
||||
N8,
|
||||
N9,
|
||||
N0,
|
||||
Hyphen,
|
||||
Equals,
|
||||
BkSpc1,
|
||||
BkSpc2,
|
||||
BkSpc3,
|
||||
Home,
|
||||
Tab,
|
||||
Q,
|
||||
W,
|
||||
E,
|
||||
R,
|
||||
T,
|
||||
Y,
|
||||
U,
|
||||
I,
|
||||
O,
|
||||
P,
|
||||
LBracket,
|
||||
RBracket,
|
||||
BackSlash,
|
||||
PgUp,
|
||||
Caps,
|
||||
A,
|
||||
S,
|
||||
D,
|
||||
F,
|
||||
G,
|
||||
H,
|
||||
J,
|
||||
K,
|
||||
L,
|
||||
SemiColon,
|
||||
Quote,
|
||||
Ret1,
|
||||
Ret2,
|
||||
Ret3,
|
||||
PgDn,
|
||||
LShift,
|
||||
Z,
|
||||
X,
|
||||
C,
|
||||
V,
|
||||
B,
|
||||
N,
|
||||
M,
|
||||
Comma,
|
||||
Period,
|
||||
FwdSlash,
|
||||
Rshift1,
|
||||
Rshift2,
|
||||
Rshift3,
|
||||
End,
|
||||
LCtrl,
|
||||
LFn,
|
||||
Meta,
|
||||
LAlt,
|
||||
Space1,
|
||||
Space2,
|
||||
Space3,
|
||||
Space4,
|
||||
RAlt,
|
||||
PrtSc,
|
||||
RCtrl,
|
||||
Up,
|
||||
Down,
|
||||
Left,
|
||||
Right,
|
||||
RFn,
|
||||
None,
|
||||
}
|
||||
|
||||
pub trait KeyLayout {
|
||||
fn get_rows(&self) -> &Vec<[Key; 17]>;
|
||||
}
|
||||
|
||||
pub struct GX502Layout(Vec<[Key; 17]>);
|
||||
|
||||
impl KeyLayout for GX502Layout {
|
||||
fn get_rows(&self) -> &Vec<[Key; 17]> {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for GX502Layout {
|
||||
fn default() -> Self {
|
||||
GX502Layout(vec![
|
||||
[
|
||||
Key::None,
|
||||
Key::None,
|
||||
Key::VolDown,
|
||||
Key::VolUp,
|
||||
Key::MicMute,
|
||||
Key::ROG,
|
||||
Key::None,
|
||||
Key::None,
|
||||
Key::None,
|
||||
Key::None,
|
||||
Key::None,
|
||||
Key::None,
|
||||
Key::None,
|
||||
Key::None,
|
||||
Key::None,
|
||||
Key::None,
|
||||
Key::None,
|
||||
],
|
||||
[
|
||||
Key::Esc,
|
||||
Key::None,
|
||||
Key::F1,
|
||||
Key::F2,
|
||||
Key::F3,
|
||||
Key::F4,
|
||||
Key::None, // not sure which key to put here
|
||||
Key::F5,
|
||||
Key::F6,
|
||||
Key::F7,
|
||||
Key::F8,
|
||||
Key::F9,
|
||||
Key::F9,
|
||||
Key::F10,
|
||||
Key::F11,
|
||||
Key::F12,
|
||||
Key::Del,
|
||||
],
|
||||
[
|
||||
Key::Tilde,
|
||||
Key::N1,
|
||||
Key::N2,
|
||||
Key::N3,
|
||||
Key::N4,
|
||||
Key::N5,
|
||||
Key::N6,
|
||||
Key::N7,
|
||||
Key::N8,
|
||||
Key::N9,
|
||||
Key::N0,
|
||||
Key::Hyphen,
|
||||
Key::Equals,
|
||||
Key::BkSpc1,
|
||||
Key::BkSpc2,
|
||||
Key::BkSpc3,
|
||||
Key::Home,
|
||||
],
|
||||
[
|
||||
Key::Tab,
|
||||
Key::Q,
|
||||
Key::W,
|
||||
Key::E,
|
||||
Key::R,
|
||||
Key::T,
|
||||
Key::Y,
|
||||
Key::U,
|
||||
Key::I,
|
||||
Key::O,
|
||||
Key::P,
|
||||
Key::LBracket,
|
||||
Key::RBracket,
|
||||
Key::BackSlash,
|
||||
Key::BackSlash,
|
||||
Key::BackSlash,
|
||||
Key::PgUp,
|
||||
],
|
||||
[
|
||||
Key::Caps,
|
||||
Key::A,
|
||||
Key::S,
|
||||
Key::D,
|
||||
Key::F,
|
||||
Key::G,
|
||||
Key::H,
|
||||
Key::J,
|
||||
Key::K,
|
||||
Key::L,
|
||||
Key::SemiColon,
|
||||
Key::Quote,
|
||||
Key::Quote,
|
||||
Key::Ret1,
|
||||
Key::Ret2,
|
||||
Key::Ret3,
|
||||
Key::PgDn,
|
||||
],
|
||||
[
|
||||
Key::LShift,
|
||||
Key::LShift,
|
||||
Key::Z,
|
||||
Key::X,
|
||||
Key::C,
|
||||
Key::V,
|
||||
Key::B,
|
||||
Key::N,
|
||||
Key::M,
|
||||
Key::Comma,
|
||||
Key::Period,
|
||||
Key::FwdSlash,
|
||||
Key::FwdSlash,
|
||||
Key::Rshift1,
|
||||
Key::Rshift2,
|
||||
Key::Rshift3,
|
||||
Key::End,
|
||||
],
|
||||
[
|
||||
Key::LCtrl,
|
||||
Key::LFn,
|
||||
Key::Meta,
|
||||
Key::LAlt,
|
||||
Key::Space1,
|
||||
Key::Space2,
|
||||
Key::Space3,
|
||||
Key::Space4,
|
||||
Key::Space4,
|
||||
Key::RAlt,
|
||||
Key::PrtSc,
|
||||
Key::RCtrl,
|
||||
Key::RCtrl,
|
||||
Key::Left,
|
||||
Key::Up,
|
||||
Key::Right,
|
||||
Key::RFn,
|
||||
],
|
||||
[
|
||||
Key::None,
|
||||
Key::None,
|
||||
Key::None,
|
||||
Key::None,
|
||||
Key::None,
|
||||
Key::None,
|
||||
Key::None,
|
||||
Key::None,
|
||||
Key::None,
|
||||
Key::None,
|
||||
Key::None,
|
||||
Key::None,
|
||||
Key::None,
|
||||
Key::Left,
|
||||
Key::Down,
|
||||
Key::Right,
|
||||
Key::None,
|
||||
],
|
||||
])
|
||||
}
|
||||
}
|
||||
281
rog-types/src/lib.rs
Normal file
281
rog-types/src/lib.rs
Normal file
@@ -0,0 +1,281 @@
|
||||
pub static DBUS_NAME: &str = "org.asuslinux.Daemon";
|
||||
pub static DBUS_PATH: &str = "/org/asuslinux/Daemon";
|
||||
pub static DBUS_IFACE: &str = "org.asuslinux.Daemon";
|
||||
pub const LED_MSG_LEN: usize = 17;
|
||||
|
||||
pub mod aura_modes;
|
||||
use aura_modes::AuraModes;
|
||||
|
||||
pub mod profile;
|
||||
|
||||
/// Contains mostly only what is required for parsing CLI options
|
||||
pub mod cli_options;
|
||||
|
||||
/// Enables you to create fancy RGB effects
|
||||
pub mod fancy;
|
||||
|
||||
/// Helper functions for the AniMe display
|
||||
pub mod anime_matrix;
|
||||
|
||||
pub mod error;
|
||||
|
||||
pub static VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
// static LED_INIT1: [u8; 2] = [0x5d, 0xb9];
|
||||
// static LED_INIT2: &str = "]ASUS Tech.Inc."; // ] == 0x5d
|
||||
// static LED_INIT3: [u8; 6] = [0x5d, 0x05, 0x20, 0x31, 0, 0x08];
|
||||
// static LED_INIT4: &str = "^ASUS Tech.Inc."; // ^ == 0x5e
|
||||
// static LED_INIT5: [u8; 6] = [0x5e, 0x05, 0x20, 0x31, 0, 0x08];
|
||||
|
||||
/// Writes aout the correct byte string for brightness
|
||||
///
|
||||
/// The HID descriptor looks like:
|
||||
///
|
||||
/// ```ignore
|
||||
/// 0x06, 0x31, 0xFF, // Usage Page (Vendor Defined 0xFF31)
|
||||
/// 0x09, 0x76, // Usage (0x76)
|
||||
/// 0xA1, 0x01, // Collection (Application)
|
||||
/// 0x85, 0x5A, // Report ID (90)
|
||||
/// 0x19, 0x00, // Usage Minimum (0x00)
|
||||
/// 0x2A, 0xFF, 0x00, // Usage Maximum (0xFF)
|
||||
/// 0x15, 0x00, // Logical Minimum (0)
|
||||
/// 0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||
/// 0x75, 0x08, // Report Size (8)
|
||||
/// 0x95, 0x05, // Report Count (5)
|
||||
/// 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
/// 0x19, 0x00, // Usage Minimum (0x00)
|
||||
/// 0x2A, 0xFF, 0x00, // Usage Maximum (0xFF)
|
||||
/// 0x15, 0x00, // Logical Minimum (0)
|
||||
/// 0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||
/// 0x75, 0x08, // Report Size (8)
|
||||
/// 0x95, 0x3F, // Report Count (63)
|
||||
/// 0xB1, 0x00, // Feature (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
/// 0xC0, // End Collection
|
||||
/// ```
|
||||
pub fn aura_brightness_bytes(brightness: u8) -> [u8; 17] {
|
||||
// TODO: check brightness range
|
||||
[
|
||||
0x5A, 0xBA, 0xC5, 0xC4, brightness, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
]
|
||||
}
|
||||
|
||||
/// Parses `AuraCommands` in to packet data
|
||||
///
|
||||
/// Byte structure:
|
||||
///
|
||||
/// ```ignore
|
||||
/// | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10| 11| 12|
|
||||
/// |---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||
/// |5d |b3 |00 |03 |ff |00 |00 |00 |00 |00 |00 |ff |00 |
|
||||
/// ```
|
||||
///
|
||||
/// Bytes 0 and 1 should always be 5d, b3
|
||||
///
|
||||
/// On multizone laptops byte 2 is the zone number, RGB in usual
|
||||
/// place, byte 3 set to zero
|
||||
///
|
||||
/// Byte 3 sets the mode type:
|
||||
/// - 00 = static
|
||||
/// - 01 = breathe (can set two colours)
|
||||
/// - 02 = strobe (through all colours)
|
||||
/// - 03 = rainbow
|
||||
/// - 04 = star (byte 9 sets rain colour)
|
||||
/// - 05 = rain keys, red, white, turquoise
|
||||
/// - 06 = pressed keys light up and fade
|
||||
/// - 07 = pressed key emits laser
|
||||
/// - 08 = pressed key emits water ripple
|
||||
/// - 09 = no effect/not used
|
||||
/// - 0a fast pulse (no speed setting)
|
||||
/// - 0b vertical line racing to right (no speed setting)
|
||||
/// - 0c wider vertical line racing to right (no speed setting)
|
||||
///
|
||||
/// Bytes 4, 5, 6 are Red, Green, Blue
|
||||
///
|
||||
/// Byte 7 sets speed from
|
||||
/// - 0x00 = Off
|
||||
/// - 0xe1 = Slow
|
||||
/// - 0xeb = Medium
|
||||
/// - 0xf5 = Fast
|
||||
///
|
||||
/// Byte 8 sets rainbow direction:
|
||||
/// - 0x00 = rightwards
|
||||
/// - 0x01 = leftwards
|
||||
/// - 0x02 = upwards
|
||||
/// - 0x03 = downwards
|
||||
///
|
||||
/// Bytes 10, 11, 12 are Red, Green, Blue for second colour if mode supports it
|
||||
///
|
||||
/// The HID descriptor looks like:
|
||||
/// ```ignore
|
||||
/// 0x06, 0x31, 0xFF, // Usage Page (Vendor Defined 0xFF31)
|
||||
/// 0x09, 0x79, // Usage (0x79)
|
||||
/// 0xA1, 0x01, // Collection (Application)
|
||||
/// 0x85, 0x5D, // Report ID (93)
|
||||
/// 0x19, 0x00, // Usage Minimum (0x00)
|
||||
/// 0x2A, 0xFF, 0x00, // Usage Maximum (0xFF)
|
||||
/// 0x15, 0x00, // Logical Minimum (0)
|
||||
/// 0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||
/// 0x75, 0x08, // Report Size (8)
|
||||
/// 0x95, 0x1F, // Report Count (31)
|
||||
/// 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
/// 0x19, 0x00, // Usage Minimum (0x00)
|
||||
/// 0x2A, 0xFF, 0x00, // Usage Maximum (0xFF)
|
||||
/// 0x15, 0x00, // Logical Minimum (0)
|
||||
/// 0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||
/// 0x75, 0x08, // Report Size (8)
|
||||
/// 0x95, 0x3F, // Report Count (63)
|
||||
/// 0x91, 0x00, // Output (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
/// 0x19, 0x00, // Usage Minimum (0x00)
|
||||
/// 0x2A, 0xFF, 0x00, // Usage Maximum (0xFF)
|
||||
/// 0x15, 0x00, // Logical Minimum (0)
|
||||
/// 0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||
/// 0x75, 0x08, // Report Size (8)
|
||||
/// 0x95, 0x3F, // Report Count (63)
|
||||
/// 0xB1, 0x00, // Feature (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
/// 0xC0, // End Collection
|
||||
/// ```
|
||||
///
|
||||
/// This descriptor is also used for the per-key LED settings
|
||||
impl From<&AuraModes> for [u8; LED_MSG_LEN] {
|
||||
fn from(mode: &AuraModes) -> Self {
|
||||
let mut msg = [0u8; LED_MSG_LEN];
|
||||
msg[0] = 0x5d;
|
||||
msg[1] = 0xb3;
|
||||
msg[7] = 0xeb;
|
||||
match mode {
|
||||
AuraModes::LedBrightness(n) => return aura_brightness_bytes(*n),
|
||||
AuraModes::Static(_) => msg[3] = 0x00,
|
||||
AuraModes::Breathe(_) => msg[3] = 0x01,
|
||||
AuraModes::Strobe(_) => msg[3] = 0x02,
|
||||
AuraModes::Rainbow(_) => msg[3] = 0x03,
|
||||
AuraModes::Star(_) => msg[3] = 0x04,
|
||||
AuraModes::Rain(_) => msg[3] = 0x05,
|
||||
AuraModes::Highlight(_) => msg[3] = 0x06,
|
||||
AuraModes::Laser(_) => msg[3] = 0x07,
|
||||
AuraModes::Ripple(_) => msg[3] = 0x08,
|
||||
AuraModes::Pulse(_) => msg[3] = 0x0a,
|
||||
AuraModes::Comet(_) => msg[3] = 0x0b,
|
||||
AuraModes::Flash(_) => msg[3] = 0x0c,
|
||||
_ => panic!("Mode not convertable to 1D array: {}", <&str>::from(mode)),
|
||||
}
|
||||
|
||||
match mode {
|
||||
AuraModes::Rainbow(settings) => {
|
||||
msg[7] = settings.speed as u8;
|
||||
msg[8] = settings.direction as u8;
|
||||
}
|
||||
AuraModes::Star(settings) => {
|
||||
msg[4] = settings.colour.0;
|
||||
msg[5] = settings.colour.1;
|
||||
msg[6] = settings.colour.2;
|
||||
msg[7] = settings.speed as u8;
|
||||
msg[9] = settings.colour2.2;
|
||||
}
|
||||
AuraModes::Breathe(settings) => {
|
||||
msg[4] = settings.colour.0;
|
||||
msg[5] = settings.colour.1;
|
||||
msg[6] = settings.colour.2;
|
||||
msg[7] = settings.speed as u8;
|
||||
msg[10] = settings.colour2.0;
|
||||
msg[11] = settings.colour2.1;
|
||||
msg[12] = settings.colour2.2;
|
||||
}
|
||||
AuraModes::Strobe(settings) | AuraModes::Rain(settings) => {
|
||||
msg[7] = settings.speed as u8;
|
||||
}
|
||||
AuraModes::Highlight(settings)
|
||||
| AuraModes::Laser(settings)
|
||||
| AuraModes::Ripple(settings) => {
|
||||
msg[4] = settings.colour.0;
|
||||
msg[5] = settings.colour.1;
|
||||
msg[6] = settings.colour.2;
|
||||
msg[7] = settings.speed as u8;
|
||||
}
|
||||
AuraModes::Static(settings)
|
||||
| AuraModes::Pulse(settings)
|
||||
| AuraModes::Comet(settings)
|
||||
| AuraModes::Flash(settings) => {
|
||||
msg[4] = settings.colour.0;
|
||||
msg[5] = settings.colour.1;
|
||||
msg[6] = settings.colour.2;
|
||||
}
|
||||
_ => panic!("Mode not convertable to 1D array: {}", <&str>::from(mode)),
|
||||
}
|
||||
msg
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AuraModes> for [u8; LED_MSG_LEN] {
|
||||
#[inline]
|
||||
fn from(mode: AuraModes) -> Self {
|
||||
<[u8; LED_MSG_LEN]>::from(&mode)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AuraModes> for [[u8; LED_MSG_LEN]; 4] {
|
||||
#[inline]
|
||||
fn from(mode: AuraModes) -> Self {
|
||||
<[[u8; LED_MSG_LEN]; 4]>::from(&mode)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&AuraModes> for [[u8; LED_MSG_LEN]; 4] {
|
||||
#[inline]
|
||||
fn from(mode: &AuraModes) -> Self {
|
||||
let mut msg = [[0u8; LED_MSG_LEN]; 4];
|
||||
match mode {
|
||||
AuraModes::MultiStatic(settings) => {
|
||||
for (i, row) in msg.iter_mut().enumerate() {
|
||||
row[0] = 0x5d;
|
||||
row[1] = 0xb3;
|
||||
row[2] = i as u8 + 1; // zone
|
||||
row[3] = 0x00; // mode
|
||||
row[7] = 0xeb; // static needs speed?
|
||||
}
|
||||
msg[0][4] = settings.colour1.0;
|
||||
msg[0][5] = settings.colour1.1;
|
||||
msg[0][6] = settings.colour1.2;
|
||||
msg[1][4] = settings.colour2.0;
|
||||
msg[1][5] = settings.colour2.1;
|
||||
msg[1][6] = settings.colour2.2;
|
||||
msg[2][4] = settings.colour3.0;
|
||||
msg[2][5] = settings.colour3.1;
|
||||
msg[2][6] = settings.colour3.2;
|
||||
msg[3][4] = settings.colour4.0;
|
||||
msg[3][5] = settings.colour4.1;
|
||||
msg[3][6] = settings.colour4.2;
|
||||
}
|
||||
AuraModes::MultiBreathe(settings) => {
|
||||
for (i, row) in msg.iter_mut().enumerate() {
|
||||
row[0] = 0x5d;
|
||||
row[1] = 0xb3;
|
||||
row[2] = i as u8 + 1; // zone
|
||||
row[3] = 0x01; // mode
|
||||
}
|
||||
let speed = match settings.speed {
|
||||
aura_modes::Speed::Low => 0xfd,
|
||||
aura_modes::Speed::Med => 0xfe,
|
||||
aura_modes::Speed::High => 0xff,
|
||||
};
|
||||
msg[0][4] = settings.colour1.0;
|
||||
msg[0][5] = settings.colour1.1;
|
||||
msg[0][6] = settings.colour1.2;
|
||||
msg[0][7] = speed; // fd, fe, ff
|
||||
msg[1][4] = settings.colour2.0;
|
||||
msg[1][5] = settings.colour2.1;
|
||||
msg[1][6] = settings.colour2.2;
|
||||
msg[1][7] = speed;
|
||||
msg[2][4] = settings.colour3.0;
|
||||
msg[2][5] = settings.colour3.1;
|
||||
msg[2][6] = settings.colour3.2;
|
||||
msg[2][7] = speed;
|
||||
msg[3][4] = settings.colour4.0;
|
||||
msg[3][5] = settings.colour4.1;
|
||||
msg[3][6] = settings.colour4.2;
|
||||
msg[3][7] = speed;
|
||||
}
|
||||
_ => panic!("Mode not convertable to 2D array: {}", <&str>::from(mode)),
|
||||
}
|
||||
msg
|
||||
}
|
||||
}
|
||||
97
rog-types/src/profile.rs
Normal file
97
rog-types/src/profile.rs
Normal file
@@ -0,0 +1,97 @@
|
||||
use gumdrop::Options;
|
||||
use rog_fan_curve::{Curve, Fan};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub enum ProfileEvent {
|
||||
Cli(ProfileCommand),
|
||||
ChangeMode(u8),
|
||||
Toggle,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum FanLevel {
|
||||
Normal,
|
||||
Boost,
|
||||
Silent,
|
||||
}
|
||||
|
||||
impl FromStr for FanLevel {
|
||||
type Err = &'static str;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s.to_lowercase().as_str() {
|
||||
"normal" => Ok(FanLevel::Normal),
|
||||
"boost" => Ok(FanLevel::Boost),
|
||||
"silent" => Ok(FanLevel::Silent),
|
||||
_ => Err("Invalid fan level"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u8> for FanLevel {
|
||||
fn from(n: u8) -> Self {
|
||||
match n {
|
||||
0 => FanLevel::Normal,
|
||||
1 => FanLevel::Boost,
|
||||
2 => FanLevel::Silent,
|
||||
_ => FanLevel::Normal,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FanLevel> for u8 {
|
||||
fn from(n: FanLevel) -> Self {
|
||||
match n {
|
||||
FanLevel::Normal => 0,
|
||||
FanLevel::Boost => 1,
|
||||
FanLevel::Silent => 2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&FanLevel> for u8 {
|
||||
fn from(n: &FanLevel) -> Self {
|
||||
match n {
|
||||
FanLevel::Normal => 0,
|
||||
FanLevel::Boost => 1,
|
||||
FanLevel::Silent => 2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_fan_curve(data: &str) -> Result<Curve, String> {
|
||||
let curve = Curve::from_config_str(data)?;
|
||||
if let Err(err) = curve.check_safety(Fan::Cpu) {
|
||||
return Err(format!("Unsafe curve {:?}", err));
|
||||
}
|
||||
if let Err(err) = curve.check_safety(Fan::Gpu) {
|
||||
return Err(format!("Unsafe curve {:?}", err));
|
||||
}
|
||||
Ok(curve)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Options, Serialize, Deserialize)]
|
||||
pub struct ProfileCommand {
|
||||
#[options(help = "print help message")]
|
||||
pub help: bool,
|
||||
#[options(help = "toggle to next profile in list")]
|
||||
pub next: bool,
|
||||
#[options(help = "create the profile if it doesn't exist")]
|
||||
pub create: bool,
|
||||
|
||||
#[options(help = "enable or disable cpu turbo")]
|
||||
pub turbo: Option<bool>,
|
||||
#[options(help = "set min cpu scaling (intel)")]
|
||||
pub min_percentage: Option<u8>,
|
||||
#[options(help = "set max cpu scaling (intel)")]
|
||||
pub max_percentage: Option<u8>,
|
||||
|
||||
#[options(meta = "PWR", help = "<silent, normal, boost>")]
|
||||
pub preset: Option<FanLevel>,
|
||||
#[options(parse(try_from_str = "parse_fan_curve"), help = "set fan curve")]
|
||||
pub curve: Option<Curve>,
|
||||
#[options(free)]
|
||||
pub profile: Option<String>,
|
||||
}
|
||||
Reference in New Issue
Block a user