Add extra models to ledmodes

- Configurable anime example
- Gfx power states as enum

Closes #72
This commit is contained in:
Luke D Jones
2021-03-29 19:36:30 +13:00
parent fbc248177a
commit 7ff01f12e9
52 changed files with 2983 additions and 564 deletions

View File

@@ -1,6 +1,6 @@
[package]
name = "daemon"
version = "3.3.0"
version = "3.3.1"
license = "MPL-2.0"
readme = "README.md"
authors = ["Luke <luke@ljones.dev>"]
@@ -18,6 +18,7 @@ name = "asusd"
path = "src/daemon.rs"
[dependencies]
rog_anime = { path = "../rog-anime" }
rog_types = { path = "../rog-types" }
rog_dbus = { path = "../rog-dbus" }
rusb = "^0.7"

View File

@@ -14,12 +14,7 @@ const APPLY: u8 = 0xc4;
const ON_OFF: u8 = 0x04;
use log::{error, info, warn};
use rog_types::{
anime_matrix::{
AniMeDataBuffer, AniMeImageBuffer, AniMePacketType, ANIME_PANE1_PREFIX, ANIME_PANE2_PREFIX,
},
error::AuraError,
};
use rog_anime::{AniMeDataBuffer, AniMePacketType};
use rusb::{Device, DeviceHandle};
use std::error::Error;
use std::time::Duration;
@@ -45,11 +40,8 @@ pub struct CtrlAnimeDisplay {
//AnimatrixWrite
pub trait Dbus {
/// Write an image 34x56 pixels. Each pixel is 0-255 greyscale.
fn write_image(&self, input: AniMeImageBuffer);
/// Write a direct stream of data
fn write_direct(&self, input: AniMeDataBuffer);
fn write(&self, input: AniMeDataBuffer);
fn set_on_off(&self, status: bool);
@@ -70,16 +62,9 @@ impl crate::ZbusAdd for CtrlAnimeDisplay {
#[dbus_interface(name = "org.asuslinux.Daemon")]
impl Dbus for CtrlAnimeDisplay {
/// Writes a 34x56 image
fn write_image(&self, input: AniMeImageBuffer) {
self.write_image_buffer(input)
.map_or_else(|err| warn!("{}", err), |()| info!("Writing image to Anime"));
}
/// Writes a data stream of length
fn write_direct(&self, input: AniMeDataBuffer) {
self.write_data_buffer(input)
.map_or_else(|err| warn!("{}", err), |()| info!("Writing data to Anime"));
fn write(&self, input: AniMeDataBuffer) {
self.write_data_buffer(input);
}
fn set_on_off(&self, status: bool) {
@@ -98,16 +83,8 @@ impl Dbus for CtrlAnimeDisplay {
}
fn set_boot_on_off(&self, status: bool) {
let status_str = if status { "on" } else { "off" };
self.do_set_boot(status).map_or_else(
|err| warn!("{}", err),
|()| info!("Turning {} the AniMe at boot/shutdown", status_str),
);
self.do_apply().map_or_else(
|err| warn!("{}", err),
|()| info!("Turning {} the AniMe at boot/shutdown", status_str),
);
self.do_set_boot(status);
self.do_apply();
}
}
@@ -132,7 +109,7 @@ impl CtrlAnimeDisplay {
info!("Device has an AniMe Matrix display");
let ctrl = CtrlAnimeDisplay { handle: device };
ctrl.do_initialization()?;
ctrl.do_initialization();
Ok(ctrl)
}
@@ -167,48 +144,16 @@ impl CtrlAnimeDisplay {
}
}
#[inline]
fn write_data_buffer(&self, buffer: AniMeDataBuffer) -> Result<(), AuraError> {
let mut image = AniMePacketType::from(buffer);
image[0][..7].copy_from_slice(&ANIME_PANE1_PREFIX);
image[1][..7].copy_from_slice(&ANIME_PANE2_PREFIX);
for row in image.iter() {
fn write_data_buffer(&self, buffer: AniMeDataBuffer) {
let data = AniMePacketType::from(buffer);
for row in data.iter() {
self.write_bytes(row);
}
self.do_flush()?;
Ok(())
}
/// Write an Animatrix image
///
/// The expected USB input here is *two* Vectors, 640 bytes in length. The two vectors
/// are each one half of the full image write.
///
/// After each write a flush is written, it is assumed that this tells the device to
/// go ahead and display the written bytes
///
/// # Note:
/// The vectors are expected to contain the full sequence of bytes as follows
///
/// - Write pane 1: 0x5e 0xc0 0x02 0x01 0x00 0x73 0x02 .. <led brightness>
/// - Write pane 2: 0x5e 0xc0 0x02 0x74 0x02 0x73 0x02 .. <led brightness>
///
/// Where led brightness is 0..255, low to high
#[inline]
fn write_image_buffer(&self, buffer: AniMeImageBuffer) -> Result<(), AuraError> {
let mut image = AniMePacketType::from(buffer);
image[0][..7].copy_from_slice(&ANIME_PANE1_PREFIX);
image[1][..7].copy_from_slice(&ANIME_PANE2_PREFIX);
for row in image.iter() {
self.write_bytes(row);
}
self.do_flush()?;
Ok(())
self.do_flush();
}
#[inline]
fn do_initialization(&self) -> Result<(), AuraError> {
fn do_initialization(&self) {
let mut init = [0; PACKET_SIZE];
init[0] = DEV_PAGE; // This is the USB page we're using throughout
for (idx, byte) in INIT_STR.as_bytes().iter().enumerate() {
@@ -224,22 +169,20 @@ impl CtrlAnimeDisplay {
init[1] = INIT;
self.write_bytes(&init);
Ok(())
}
#[inline]
fn do_flush(&self) -> Result<(), AuraError> {
fn do_flush(&self) {
let mut flush = [0; PACKET_SIZE];
flush[0] = DEV_PAGE;
flush[1] = WRITE;
flush[2] = 0x03;
self.write_bytes(&flush);
Ok(())
}
#[inline]
fn do_set_boot(&self, status: bool) -> Result<(), AuraError> {
fn do_set_boot(&self, status: bool) {
let mut flush = [0; PACKET_SIZE];
flush[0] = DEV_PAGE;
flush[1] = SET;
@@ -247,11 +190,10 @@ impl CtrlAnimeDisplay {
flush[3] = if status { 0x00 } else { 0x80 };
self.write_bytes(&flush);
Ok(())
}
#[inline]
fn do_apply(&self) -> Result<(), AuraError> {
fn do_apply(&self) {
let mut flush = [0; PACKET_SIZE];
flush[0] = DEV_PAGE;
flush[1] = APPLY;
@@ -259,6 +201,5 @@ impl CtrlAnimeDisplay {
flush[3] = 0x80;
self.write_bytes(&flush);
Ok(())
}
}

View File

@@ -14,7 +14,7 @@ static FAN_TYPE_1_PATH: &str = "/sys/devices/platform/asus-nb-wmi/throttle_therm
static FAN_TYPE_2_PATH: &str = "/sys/devices/platform/asus-nb-wmi/fan_boost_mode";
static AMD_BOOST_PATH: &str = "/sys/devices/system/cpu/cpufreq/boost";
pub struct CtrlFanAndCPU {
pub struct CtrlFanAndCpu {
pub path: &'static str,
config: Arc<Mutex<Config>>,
}
@@ -26,12 +26,12 @@ pub struct FanCpuSupportedFunctions {
pub fan_curve_set: bool,
}
impl GetSupported for CtrlFanAndCPU {
impl GetSupported for CtrlFanAndCpu {
type A = FanCpuSupportedFunctions;
fn get_supported() -> Self::A {
FanCpuSupportedFunctions {
stock_fan_modes: CtrlFanAndCPU::get_fan_path().is_ok(),
stock_fan_modes: CtrlFanAndCpu::get_fan_path().is_ok(),
min_max_freq: intel_pstate::PState::new().is_ok(),
fan_curve_set: rog_fan_curve::Board::from_board_name().is_some(),
}
@@ -39,11 +39,11 @@ impl GetSupported for CtrlFanAndCPU {
}
pub struct DbusFanAndCpu {
inner: Arc<Mutex<CtrlFanAndCPU>>,
inner: Arc<Mutex<CtrlFanAndCpu>>,
}
impl DbusFanAndCpu {
pub fn new(inner: Arc<Mutex<CtrlFanAndCPU>>) -> Self {
pub fn new(inner: Arc<Mutex<CtrlFanAndCpu>>) -> Self {
Self { inner }
}
}
@@ -189,7 +189,7 @@ impl crate::ZbusAdd for DbusFanAndCpu {
}
}
impl crate::Reloadable for CtrlFanAndCPU {
impl crate::Reloadable for CtrlFanAndCpu {
fn reload(&mut self) -> Result<(), RogError> {
if let Ok(mut config) = self.config.clone().try_lock() {
let profile = config.active_profile.clone();
@@ -203,11 +203,11 @@ impl crate::Reloadable for CtrlFanAndCPU {
}
}
impl CtrlFanAndCPU {
impl CtrlFanAndCpu {
pub fn new(config: Arc<Mutex<Config>>) -> Result<Self, RogError> {
let path = CtrlFanAndCPU::get_fan_path()?;
let path = CtrlFanAndCpu::get_fan_path()?;
info!("Device has thermal throttle control");
Ok(CtrlFanAndCPU { path, config })
Ok(CtrlFanAndCpu { path, config })
}
fn get_fan_path() -> Result<&'static str, RogError> {

View File

@@ -6,6 +6,7 @@ use crate::error::RogError;
#[derive(Debug)]
pub enum GfxError {
ParseVendor,
ParsePower,
Bus(String, std::io::Error),
DisplayManagerAction(String, ExitStatus),
DisplayManagerTimeout(String),
@@ -22,6 +23,7 @@ impl fmt::Display for GfxError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
GfxError::ParseVendor => write!(f, "Could not parse vendor name"),
GfxError::ParsePower => write!(f, "Could not parse dGPU power status"),
GfxError::Bus(func, error) => write!(f, "Bus error: {}: {}", func, error),
GfxError::DisplayManagerAction(action, status) => {
write!(f, "Display-manager action {} failed: {}", action, status)

View File

@@ -6,11 +6,11 @@ use logind_zbus::{
types::{SessionClass, SessionInfo, SessionState, SessionType},
ManagerProxy, SessionProxy,
};
use rog_types::gfx_vendors::{GfxRequiredUserAction, GfxVendors};
use std::sync::mpsc;
use rog_types::gfx_vendors::{GfxPower, GfxRequiredUserAction, GfxVendors};
use std::{io::Write, ops::Add, path::Path, time::Instant};
use std::{iter::FromIterator, thread::JoinHandle};
use std::{process::Command, thread::sleep, time::Duration};
use std::{str::FromStr, sync::mpsc};
use std::{sync::Arc, sync::Mutex};
use sysfs_class::{PciDevice, SysClass};
use system::{GraphicsDevice, PciBus};
@@ -33,7 +33,7 @@ pub struct CtrlGraphics {
trait Dbus {
fn vendor(&self) -> zbus::fdo::Result<GfxVendors>;
fn power(&self) -> String;
fn power(&self) -> zbus::fdo::Result<GfxPower>;
fn set_vendor(&mut self, vendor: GfxVendors) -> zbus::fdo::Result<GfxRequiredUserAction>;
fn notify_gfx(&self, vendor: &GfxVendors) -> zbus::Result<()>;
fn notify_action(&self, action: &GfxRequiredUserAction) -> zbus::Result<()>;
@@ -48,8 +48,11 @@ impl Dbus for CtrlGraphics {
})
}
fn power(&self) -> String {
Self::get_runtime_status().unwrap_or_else(|err| format!("Get power status failed: {}", err))
fn power(&self) -> zbus::fdo::Result<GfxPower> {
Self::get_runtime_status().map_err(|err| {
error!("GFX: {}", err);
zbus::fdo::Error::Failed(format!("GFX fail: {}", err))
})
}
fn set_vendor(&mut self, vendor: GfxVendors) -> zbus::fdo::Result<GfxRequiredUserAction> {
@@ -178,10 +181,19 @@ impl CtrlGraphics {
Ok(GfxVendors::Hybrid)
}
fn get_runtime_status() -> Result<String, RogError> {
const PATH: &str = "/sys/bus/pci/devices/0000:01:00.0/power/runtime_status";
let buf = std::fs::read_to_string(PATH).map_err(|err| RogError::Read(PATH.into(), err))?;
Ok(buf)
fn get_runtime_status() -> Result<GfxPower, RogError> {
let path = Path::new("/sys/bus/pci/devices/0000:01:00.0/power/runtime_status");
if path.exists() {
let buf = std::fs::read_to_string(path).map_err(|err| {
RogError::Read(
"/sys/bus/pci/devices/0000:01:00.0/power/runtime_status".to_string(),
err,
)
})?;
Ok(GfxPower::from_str(&buf)?)
} else {
Ok(GfxPower::Off)
}
}
/// Some systems have a fallback service to load nouveau if nvidia fails

View File

@@ -248,7 +248,7 @@ impl crate::CtrlTask for CtrlKbdBacklight {
}
return Ok(());
}
Err(RogError::ParseLED)
Err(RogError::ParseLed)
}
}

View File

@@ -5,7 +5,7 @@ use zbus::dbus_interface;
use crate::{
ctrl_anime::{AnimeSupportedFunctions, CtrlAnimeDisplay},
ctrl_charge::{ChargeSupportedFunctions, CtrlCharge},
ctrl_fan_cpu::{CtrlFanAndCPU, FanCpuSupportedFunctions},
ctrl_fan_cpu::{CtrlFanAndCpu, FanCpuSupportedFunctions},
ctrl_leds::{CtrlKbdBacklight, LedSupportedFunctions},
ctrl_rog_bios::{CtrlRogBios, RogBiosSupportedFunctions},
GetSupported,
@@ -47,7 +47,7 @@ impl GetSupported for SupportedFunctions {
keyboard_led: CtrlKbdBacklight::get_supported(),
anime_ctrl: CtrlAnimeDisplay::get_supported(),
charge_ctrl: CtrlCharge::get_supported(),
fan_cpu_ctrl: CtrlFanAndCPU::get_supported(),
fan_cpu_ctrl: CtrlFanAndCpu::get_supported(),
rog_bios_ctrl: CtrlRogBios::get_supported(),
}
}

View File

@@ -5,7 +5,7 @@ use daemon::{
use daemon::{config_aura::AuraConfig, ctrl_charge::CtrlCharge};
use daemon::{ctrl_anime::CtrlAnimeDisplay, ctrl_gfx::gfx::CtrlGraphics};
use daemon::{
ctrl_fan_cpu::{CtrlFanAndCPU, DbusFanAndCpu},
ctrl_fan_cpu::{CtrlFanAndCpu, DbusFanAndCpu},
laptops::LaptopLedData,
};
@@ -134,7 +134,7 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
// Collect tasks for task thread
let mut tasks: Vec<Arc<Mutex<dyn CtrlTask + Send>>> = Vec::new();
if let Ok(mut ctrl) = CtrlFanAndCPU::new(config).map_err(|err| {
if let Ok(mut ctrl) = CtrlFanAndCpu::new(config).map_err(|err| {
error!("Profile control: {}", err);
}) {
ctrl.reload()

View File

@@ -10,7 +10,7 @@ use crate::ctrl_gfx::error::GfxError;
pub enum RogError {
ParseFanLevel,
ParseVendor,
ParseLED,
ParseLed,
MissingProfile(String),
Udev(String, std::io::Error),
Path(String, std::io::Error),
@@ -38,7 +38,7 @@ impl fmt::Display for RogError {
match self {
RogError::ParseFanLevel => write!(f, "Parse profile error"),
RogError::ParseVendor => write!(f, "Parse gfx vendor error"),
RogError::ParseLED => write!(f, "Parse LED error"),
RogError::ParseLed => write!(f, "Parse LED error"),
RogError::MissingProfile(profile) => write!(f, "Profile does not exist {}", profile),
RogError::Udev(deets, error) => write!(f, "udev {}: {}", deets, error),
RogError::Path(path, error) => write!(f, "Path {}: {}", path, error),
@@ -80,6 +80,7 @@ impl From<GraphicsError> for RogError {
fn from(err: GraphicsError) -> Self {
match err {
GraphicsError::ParseVendor => RogError::GfxSwitching(GfxError::ParseVendor),
GraphicsError::ParsePower => RogError::GfxSwitching(GfxError::ParsePower),
}
}
}