Merge pull request #23 from Eraden/add_temp_input

Default temp input
This commit is contained in:
Adrian Woźniak 2021-08-22 21:44:03 +02:00 committed by GitHub
commit 2220c3084f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 63 additions and 53 deletions

View File

@ -3,3 +3,4 @@
cargo build --release cargo build --release
strip target/x86_64-unknown-linux-musl/release/amdfand strip target/x86_64-unknown-linux-musl/release/amdfand
upx --best --lzma target/x86_64-unknown-linux-musl/release/amdfand upx --best --lzma target/x86_64-unknown-linux-musl/release/amdfand

View File

@ -130,15 +130,11 @@ impl LogLevel {
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
pub struct Config { pub struct Config {
log_level: LogLevel, log_level: LogLevel,
cards: Vec<Card>,
speed_matrix: Vec<MatrixPoint>, speed_matrix: Vec<MatrixPoint>,
temp_input: Option<String>,
} }
impl Config { impl Config {
pub fn cards(&self) -> &[Card] {
&self.cards
}
pub fn speed_for_temp(&self, temp: f64) -> f64 { pub fn speed_for_temp(&self, temp: f64) -> f64 {
let idx = match self.speed_matrix.iter().rposition(|p| p.temp <= temp) { let idx = match self.speed_matrix.iter().rposition(|p| p.temp <= temp) {
Some(idx) => idx, Some(idx) => idx,
@ -162,6 +158,10 @@ impl Config {
self.log_level self.log_level
} }
pub fn temp_input(&self) -> Option<&str> {
self.temp_input.as_deref()
}
fn min_speed(&self) -> f64 { fn min_speed(&self) -> f64 {
self.speed_matrix.first().map(|p| p.speed).unwrap_or(0f64) self.speed_matrix.first().map(|p| p.speed).unwrap_or(0f64)
} }
@ -175,7 +175,6 @@ impl Default for Config {
fn default() -> Self { fn default() -> Self {
Self { Self {
log_level: LogLevel::Error, log_level: LogLevel::Error,
cards: vec![Card(0)],
speed_matrix: vec![ speed_matrix: vec![
MatrixPoint { MatrixPoint {
temp: 4f64, temp: 4f64,
@ -210,6 +209,7 @@ impl Default for Config {
speed: 100f64, speed: 100f64,
}, },
], ],
temp_input: Some(String::from("temp1_input")),
} }
} }
} }

View File

@ -6,23 +6,20 @@ use crate::FanMode;
/// Change card fan mode to either automatic or manual /// Change card fan mode to either automatic or manual
pub fn run(switcher: Switcher, mode: FanMode, config: Config) -> std::io::Result<()> { pub fn run(switcher: Switcher, mode: FanMode, config: Config) -> std::io::Result<()> {
let mut controllers = crate::utils::controllers(&config, true)?; let mut hw_mons = crate::utils::hw_mons(&config, true)?;
let cards = match switcher.card { let cards = match switcher.card {
Some(card_id) => match controllers Some(card_id) => match hw_mons.iter().position(|hw_mon| **hw_mon.card() == card_id) {
.iter() Some(card) => vec![hw_mons.remove(card)],
.position(|hw_mon| *hw_mon.card == card_id)
{
Some(card) => vec![controllers.remove(card)],
None => { None => {
eprintln!("Card does not exists. Available cards: "); eprintln!("Card does not exists. Available cards: ");
for hw_mon in controllers { for hw_mon in hw_mons {
eprintln!(" * {}", *hw_mon.card); eprintln!(" * {}", *hw_mon.card());
} }
return Err(not_found()); return Err(not_found());
} }
}, },
None => controllers, None => hw_mons,
}; };
for hw_mon in cards { for hw_mon in cards {

View File

@ -1,7 +1,7 @@
use std::str::FromStr; use std::str::FromStr;
use crate::config::Config; use crate::config::Config;
use crate::utils::controllers; use crate::utils::hw_mons;
use crate::AmdFanError; use crate::AmdFanError;
#[derive(Debug)] #[derive(Debug)]
@ -45,11 +45,11 @@ pub fn run(monitor: Monitor, config: Config) -> std::io::Result<()> {
} }
pub fn verbose(config: Config) -> std::io::Result<()> { pub fn verbose(config: Config) -> std::io::Result<()> {
let mut controllers = controllers(&config, true)?; let mut controllers = hw_mons(&config, true)?;
loop { loop {
print!("{esc}[2J{esc}[1;1H", esc = 27 as char); print!("{esc}[2J{esc}[1;1H", esc = 27 as char);
for hw_mon in controllers.iter_mut() { for hw_mon in controllers.iter_mut() {
println!("Card {:3}", hw_mon.card.to_string().replace("card", "")); println!("Card {:3}", hw_mon.card().to_string().replace("card", ""));
println!(" MIN | MAX | PWM | %"); println!(" MIN | MAX | PWM | %");
let min = hw_mon.pwm_min(); let min = hw_mon.pwm_min();
let max = hw_mon.pwm_max(); let max = hw_mon.pwm_max();
@ -87,13 +87,13 @@ pub fn verbose(config: Config) -> std::io::Result<()> {
} }
pub fn short(config: Config) -> std::io::Result<()> { pub fn short(config: Config) -> std::io::Result<()> {
let mut controllers = controllers(&config, true)?; let mut controllers = hw_mons(&config, true)?;
loop { loop {
print!("{esc}[2J{esc}[1;1H", esc = 27 as char); print!("{esc}[2J{esc}[1;1H", esc = 27 as char);
for hw_mon in controllers.iter_mut() { for hw_mon in controllers.iter_mut() {
println!( println!(
"Card {:3} | Temp | MIN | MAX | PWM | %", "Card {:3} | Temp | MIN | MAX | PWM | %",
hw_mon.card.to_string().replace("card", "") hw_mon.card().to_string().replace("card", "")
); );
let min = hw_mon.pwm_min(); let min = hw_mon.pwm_min();
let max = hw_mon.pwm_max(); let max = hw_mon.pwm_max();

View File

@ -5,7 +5,7 @@ use crate::io_err::not_found;
/// Start service which will change fan speed according to config and GPU temperature /// Start service which will change fan speed according to config and GPU temperature
pub fn run(config: Config) -> std::io::Result<()> { pub fn run(config: Config) -> std::io::Result<()> {
let mut controllers = crate::utils::controllers(&config, true)?; let mut controllers = crate::utils::hw_mons(&config, true)?;
if controllers.is_empty() { if controllers.is_empty() {
return Err(not_found()); return Err(not_found());
} }
@ -13,8 +13,8 @@ pub fn run(config: Config) -> std::io::Result<()> {
loop { loop {
for hw_mon in controllers.iter_mut() { for hw_mon in controllers.iter_mut() {
let gpu_temp = hw_mon.max_gpu_temp().unwrap_or_default(); let gpu_temp = hw_mon.max_gpu_temp().unwrap_or_default();
log::debug!("Current {} temperature: {}", hw_mon.card, gpu_temp); log::debug!("Current {} temperature: {}", hw_mon.card(), gpu_temp);
let last = *cache.entry(*hw_mon.card).or_insert(1_000f64); let last = *cache.entry(**hw_mon.card()).or_insert(1_000f64);
if (last - gpu_temp).abs() < 0.001f64 { if (last - gpu_temp).abs() < 0.001f64 {
log::debug!("Temperature didn't change"); log::debug!("Temperature didn't change");
@ -26,7 +26,7 @@ pub fn run(config: Config) -> std::io::Result<()> {
if let Err(e) = hw_mon.set_speed(speed) { if let Err(e) = hw_mon.set_speed(speed) {
log::error!("Failed to change speed to {}. {:?}", speed, e); log::error!("Failed to change speed to {}. {:?}", speed, e);
} }
cache.insert(*hw_mon.card, gpu_temp); cache.insert(**hw_mon.card(), gpu_temp);
} }
std::thread::sleep(std::time::Duration::from_secs(4)); std::thread::sleep(std::time::Duration::from_secs(4));
} }

View File

@ -1,7 +1,7 @@
use crate::config::Card; use crate::config::{Card, Config};
use crate::io_err::{invalid_input, not_found}; use crate::io_err::{invalid_input, not_found};
use crate::utils::linear_map; use crate::utils::linear_map;
use crate::{AmdFanError, HwMon, HW_MON_DIR, ROOT_DIR}; use crate::{AmdFanError, HW_MON_DIR, ROOT_DIR};
/// pulse width modulation fan control minimum level (0) /// pulse width modulation fan control minimum level (0)
const PULSE_WIDTH_MODULATION_MIN: &str = "pwm1_min"; const PULSE_WIDTH_MODULATION_MIN: &str = "pwm1_min";
@ -17,12 +17,28 @@ const PULSE_WIDTH_MODULATION_MODE: &str = "pwm1_enable";
// static PULSE_WIDTH_MODULATION_DISABLED: &str = "0"; // static PULSE_WIDTH_MODULATION_DISABLED: &str = "0";
const PULSE_WIDTH_MODULATION_AUTO: &str = "2"; const PULSE_WIDTH_MODULATION_AUTO: &str = "2";
const PULSE_WIDTH_MODULATION_MANUAL: &str = "1";
#[derive(Debug)]
pub struct HwMon {
/// HW MOD cord (ex. card0)
card: Card,
/// MW MOD name (ex. hwmod0)
name: String,
/// Minimal modulation (between 0-255)
pwm_min: Option<u32>,
/// Maximal modulation (between 0-255)
pwm_max: Option<u32>,
/// List of available temperature inputs for current HW MOD
temp_inputs: Vec<String>,
/// Preferred temperature input
temp_input: Option<String>,
}
impl HwMon { impl HwMon {
pub fn new(card: &Card, name: &str) -> Self { pub fn new(card: &Card, name: &str, config: &Config) -> Self {
Self { Self {
card: *card, card: *card,
temp_input: config.temp_input().map(String::from),
name: String::from(name), name: String::from(name),
pwm_min: None, pwm_min: None,
pwm_max: None, pwm_max: None,
@ -31,6 +47,12 @@ impl HwMon {
} }
pub fn max_gpu_temp(&self) -> std::io::Result<f64> { pub fn max_gpu_temp(&self) -> std::io::Result<f64> {
if let Some(input) = self.temp_input.as_deref() {
return self
.read_gpu_temp(input)
.map(|temp| temp as f64 / 1000f64)
.map_err(|_| invalid_input());
}
let mut results = Vec::with_capacity(self.temp_inputs.len()); let mut results = Vec::with_capacity(self.temp_inputs.len());
for name in self.temp_inputs.iter() { for name in self.temp_inputs.iter() {
results.push(self.read_gpu_temp(name).unwrap_or(0)); results.push(self.read_gpu_temp(name).unwrap_or(0));
@ -63,6 +85,11 @@ impl HwMon {
}) })
} }
#[inline]
pub(crate) fn card(&self) -> &Card {
&self.card
}
#[inline] #[inline]
pub(crate) fn name(&self) -> std::io::Result<String> { pub(crate) fn name(&self) -> std::io::Result<String> {
self.read("name") self.read("name")
@ -89,12 +116,6 @@ impl HwMon {
}) })
} }
pub fn is_fan_manual(&self) -> bool {
self.read(PULSE_WIDTH_MODULATION_MODE)
.map(|s| s.as_str() == PULSE_WIDTH_MODULATION_MANUAL)
.unwrap_or_default()
}
pub fn is_fan_automatic(&self) -> bool { pub fn is_fan_automatic(&self) -> bool {
self.read(PULSE_WIDTH_MODULATION_MODE) self.read(PULSE_WIDTH_MODULATION_MODE)
.map(|s| s.as_str() == PULSE_WIDTH_MODULATION_AUTO) .map(|s| s.as_str() == PULSE_WIDTH_MODULATION_AUTO)
@ -190,7 +211,7 @@ fn hw_mon_dir_path(card: &Card, name: &str) -> std::path::PathBuf {
hw_mon_dirs_path(card).join(name) hw_mon_dirs_path(card).join(name)
} }
pub(crate) fn open_hw_mon(card: Card) -> std::io::Result<HwMon> { pub(crate) fn open_hw_mon(card: Card, config: &Config) -> std::io::Result<HwMon> {
let read_path = hw_mon_dirs_path(&card); let read_path = hw_mon_dirs_path(&card);
let entries = std::fs::read_dir(read_path)?; let entries = std::fs::read_dir(read_path)?;
let name = entries let name = entries
@ -206,5 +227,5 @@ pub(crate) fn open_hw_mon(card: Card) -> std::io::Result<HwMon> {
.take(1) .take(1)
.last() .last()
.ok_or_else(not_found)?; .ok_or_else(not_found)?;
Ok(HwMon::new(&card, &name)) Ok(HwMon::new(&card, &name, config))
} }

View File

@ -3,7 +3,7 @@ use std::io::ErrorKind;
use gumdrop::Options; use gumdrop::Options;
use crate::config::{load_config, Card}; use crate::config::load_config;
mod config; mod config;
mod fan; mod fan;
@ -47,15 +47,6 @@ impl std::fmt::Display for AmdFanError {
} }
} }
#[derive(Debug)]
pub struct HwMon {
card: Card,
name: String,
pwm_min: Option<u32>,
pwm_max: Option<u32>,
temp_inputs: Vec<String>,
}
pub enum FanMode { pub enum FanMode {
Manual, Manual,
Automatic, Automatic,
@ -86,7 +77,7 @@ fn main() -> std::io::Result<()> {
let opts: Opts = Opts::parse_args_default_or_exit(); let opts: Opts = Opts::parse_args_default_or_exit();
if opts.version { if opts.version {
println!("{}", env!("CARGO_PKG_VERSION")); println!("amdfand {}", env!("CARGO_PKG_VERSION"));
std::process::exit(0); std::process::exit(0);
} }
@ -102,12 +93,12 @@ fn main() -> std::io::Result<()> {
} }
Some(fan::FanCommand::Available(_)) => { Some(fan::FanCommand::Available(_)) => {
println!("Available cards"); println!("Available cards");
utils::controllers(&config, false)? utils::hw_mons(&config, false)?
.into_iter() .into_iter()
.for_each(|hw_mon| { .for_each(|hw_mon| {
println!( println!(
" * {:6>} - {}", " * {:6>} - {}",
hw_mon.card, hw_mon.card(),
hw_mon.name().unwrap_or_default() hw_mon.name().unwrap_or_default()
); );
}); });

View File

@ -1,5 +1,6 @@
use crate::config::{Card, Config}; use crate::config::{Card, Config};
use crate::{hw_mon, HwMon, ROOT_DIR}; use crate::hw_mon::HwMon;
use crate::{hw_mon, ROOT_DIR};
/// linear mapping from the xrange to the yrange /// linear mapping from the xrange to the yrange
pub fn linear_map(x: f64, x1: f64, x2: f64, y1: f64, y2: f64) -> f64 { pub fn linear_map(x: f64, x1: f64, x2: f64, y1: f64, y2: f64) -> f64 {
@ -19,11 +20,10 @@ pub fn read_cards() -> std::io::Result<Vec<Card>> {
/// Wrap cards in HW Mon manipulator and /// Wrap cards in HW Mon manipulator and
/// filter cards so only amd and listed in config cards are accessible /// filter cards so only amd and listed in config cards are accessible
pub fn controllers(config: &Config, filter: bool) -> std::io::Result<Vec<HwMon>> { pub fn hw_mons(config: &Config, filter: bool) -> std::io::Result<Vec<HwMon>> {
Ok(read_cards()? Ok(read_cards()?
.into_iter() .into_iter()
.filter(|card| !filter || config.cards().iter().any(|name| **name == **card)) .filter_map(|card| hw_mon::open_hw_mon(card, config).ok())
.filter_map(|card| hw_mon::open_hw_mon(card).ok())
.filter(|hw_mon| !filter || { hw_mon.is_amd() }) .filter(|hw_mon| !filter || { hw_mon.is_amd() })
.filter(|hw_mon| !filter || hw_mon.name_is_amd()) .filter(|hw_mon| !filter || hw_mon.name_is_amd())
.collect()) .collect())