Merge pull request #17 from Eraden/prepare-for-voltage
[WIP] Prepare code for adding voltage
This commit is contained in:
commit
5f5b3bc69b
4
.github/workflows/rust.yml
vendored
4
.github/workflows/rust.yml
vendored
@ -21,6 +21,10 @@ jobs:
|
|||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Add target
|
- name: Add target
|
||||||
run: rustup target install x86_64-unknown-linux-musl
|
run: rustup target install x86_64-unknown-linux-musl
|
||||||
|
- name: Run clippy
|
||||||
|
run: cargo clippy -- -D warnings
|
||||||
|
- name: Run fmt check
|
||||||
|
run: cargo fmt -- --check
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: cargo test --verbose
|
run: cargo test --verbose
|
||||||
- name: Install binary compressor
|
- name: Install binary compressor
|
||||||
|
@ -26,7 +26,7 @@ impl FromStr for Card {
|
|||||||
value[4..]
|
value[4..]
|
||||||
.parse::<u32>()
|
.parse::<u32>()
|
||||||
.map_err(|e| AmdFanError::InvalidSuffix(format!("{:?}", e)))
|
.map_err(|e| AmdFanError::InvalidSuffix(format!("{:?}", e)))
|
||||||
.map(|n| Card(n))
|
.map(Card)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ impl<'de> Deserialize<'de> for Card {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
deserializer.deserialize_str(CardVisitor).map(|v| Card(v))
|
deserializer.deserialize_str(CardVisitor).map(Card)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,7 +115,7 @@ pub enum LogLevel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl LogLevel {
|
impl LogLevel {
|
||||||
pub fn to_str(&self) -> &str {
|
pub fn as_str(&self) -> &str {
|
||||||
match self {
|
match self {
|
||||||
LogLevel::Off => "OFF",
|
LogLevel::Off => "OFF",
|
||||||
LogLevel::Error => "ERROR",
|
LogLevel::Error => "ERROR",
|
||||||
@ -149,7 +149,7 @@ impl Config {
|
|||||||
return self.max_speed();
|
return self.max_speed();
|
||||||
}
|
}
|
||||||
|
|
||||||
crate::linear_map(
|
crate::utils::linear_map(
|
||||||
temp,
|
temp,
|
||||||
self.speed_matrix[idx].temp,
|
self.speed_matrix[idx].temp,
|
||||||
self.speed_matrix[idx + 1].temp,
|
self.speed_matrix[idx + 1].temp,
|
||||||
|
51
src/fan/change_mode.rs
Normal file
51
src/fan/change_mode.rs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
use gumdrop::Options;
|
||||||
|
|
||||||
|
use crate::config::Config;
|
||||||
|
use crate::io_err::not_found;
|
||||||
|
use crate::FanMode;
|
||||||
|
|
||||||
|
/// Change card fan mode to either automatic or manual
|
||||||
|
pub fn run(switcher: Switcher, mode: FanMode, config: Config) -> std::io::Result<()> {
|
||||||
|
let mut controllers = crate::utils::controllers(&config, true)?;
|
||||||
|
|
||||||
|
let cards = match switcher.card {
|
||||||
|
Some(card_id) => match controllers
|
||||||
|
.iter()
|
||||||
|
.position(|hw_mon| *hw_mon.card == card_id)
|
||||||
|
{
|
||||||
|
Some(card) => vec![controllers.remove(card)],
|
||||||
|
None => {
|
||||||
|
eprintln!("Card does not exists. Available cards: ");
|
||||||
|
for hw_mon in controllers {
|
||||||
|
eprintln!(" * {}", *hw_mon.card);
|
||||||
|
}
|
||||||
|
return Err(not_found());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => controllers,
|
||||||
|
};
|
||||||
|
|
||||||
|
for hw_mon in cards {
|
||||||
|
match mode {
|
||||||
|
FanMode::Automatic => {
|
||||||
|
if let Err(e) = hw_mon.set_automatic() {
|
||||||
|
log::error!("{:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FanMode::Manual => {
|
||||||
|
if let Err(e) = hw_mon.set_manual() {
|
||||||
|
log::error!("{:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Options)]
|
||||||
|
pub struct Switcher {
|
||||||
|
#[options(help = "Print help message")]
|
||||||
|
help: bool,
|
||||||
|
#[options(help = "GPU Card number")]
|
||||||
|
card: Option<u32>,
|
||||||
|
}
|
25
src/fan/mod.rs
Normal file
25
src/fan/mod.rs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
use gumdrop::Options;
|
||||||
|
|
||||||
|
pub mod change_mode;
|
||||||
|
pub mod monitor;
|
||||||
|
pub mod service;
|
||||||
|
|
||||||
|
#[derive(Debug, Options)]
|
||||||
|
pub struct AvailableCards {
|
||||||
|
#[options(help = "Help message")]
|
||||||
|
help: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Options)]
|
||||||
|
pub enum FanCommand {
|
||||||
|
#[options(help = "Print current temp and fan speed")]
|
||||||
|
Monitor(monitor::Monitor),
|
||||||
|
#[options(help = "Set fan speed depends on GPU temperature")]
|
||||||
|
Service(service::Service),
|
||||||
|
#[options(help = "Switch to GPU automatic fan speed control")]
|
||||||
|
SetAutomatic(change_mode::Switcher),
|
||||||
|
#[options(help = "Switch to GPU manual fan speed control")]
|
||||||
|
SetManual(change_mode::Switcher),
|
||||||
|
#[options(help = "Print available cards")]
|
||||||
|
Available(AvailableCards),
|
||||||
|
}
|
@ -1,7 +1,9 @@
|
|||||||
use crate::config::Config;
|
|
||||||
use crate::{controllers, AmdFanError};
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use crate::config::Config;
|
||||||
|
use crate::utils::controllers;
|
||||||
|
use crate::AmdFanError;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum MonitorFormat {
|
pub enum MonitorFormat {
|
||||||
Short,
|
Short,
|
||||||
@ -34,6 +36,7 @@ pub struct Monitor {
|
|||||||
format: MonitorFormat,
|
format: MonitorFormat,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Start print cards temperature and fan speed
|
||||||
pub fn run(monitor: Monitor, config: Config) -> std::io::Result<()> {
|
pub fn run(monitor: Monitor, config: Config) -> std::io::Result<()> {
|
||||||
match monitor.format {
|
match monitor.format {
|
||||||
MonitorFormat::Short => short(config),
|
MonitorFormat::Short => short(config),
|
||||||
@ -57,7 +60,14 @@ pub fn verbose(config: Config) -> std::io::Result<()> {
|
|||||||
hw_mon
|
hw_mon
|
||||||
.pwm()
|
.pwm()
|
||||||
.map_or_else(|_e| String::from("FAILED"), |f| f.to_string()),
|
.map_or_else(|_e| String::from("FAILED"), |f| f.to_string()),
|
||||||
(crate::linear_map(hw_mon.pwm().unwrap_or_default() as f64, min as f64, max as f64, 0f64, 100f64)).round(),
|
(crate::utils::linear_map(
|
||||||
|
hw_mon.pwm().unwrap_or_default() as f64,
|
||||||
|
min as f64,
|
||||||
|
max as f64,
|
||||||
|
0f64,
|
||||||
|
100f64
|
||||||
|
))
|
||||||
|
.round(),
|
||||||
);
|
);
|
||||||
|
|
||||||
println!();
|
println!();
|
||||||
@ -93,7 +103,14 @@ pub fn short(config: Config) -> std::io::Result<()> {
|
|||||||
min,
|
min,
|
||||||
max,
|
max,
|
||||||
hw_mon.pwm().unwrap_or_default(),
|
hw_mon.pwm().unwrap_or_default(),
|
||||||
crate::linear_map(hw_mon.pwm().unwrap_or_default() as f64, min as f64, max as f64, 0f64, 100f64).round(),
|
crate::utils::linear_map(
|
||||||
|
hw_mon.pwm().unwrap_or_default() as f64,
|
||||||
|
min as f64,
|
||||||
|
max as f64,
|
||||||
|
0f64,
|
||||||
|
100f64
|
||||||
|
)
|
||||||
|
.round(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
std::thread::sleep(std::time::Duration::from_secs(4));
|
std::thread::sleep(std::time::Duration::from_secs(4));
|
39
src/fan/service.rs
Normal file
39
src/fan/service.rs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
use gumdrop::Options;
|
||||||
|
|
||||||
|
use crate::config::Config;
|
||||||
|
use crate::io_err::not_found;
|
||||||
|
|
||||||
|
/// Start service which will change fan speed according to config and GPU temperature
|
||||||
|
pub fn run(config: Config) -> std::io::Result<()> {
|
||||||
|
let mut controllers = crate::utils::controllers(&config, true)?;
|
||||||
|
if controllers.is_empty() {
|
||||||
|
return Err(not_found());
|
||||||
|
}
|
||||||
|
let mut cache = std::collections::HashMap::new();
|
||||||
|
loop {
|
||||||
|
for hw_mon in controllers.iter_mut() {
|
||||||
|
let gpu_temp = hw_mon.max_gpu_temp().unwrap_or_default();
|
||||||
|
log::debug!("Current {} temperature: {}", hw_mon.card, gpu_temp);
|
||||||
|
let last = *cache.entry(*hw_mon.card).or_insert(1_000f64);
|
||||||
|
|
||||||
|
if (last - gpu_temp).abs() < 0.001f64 {
|
||||||
|
log::debug!("Temperature didn't change");
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
let speed = config.speed_for_temp(gpu_temp);
|
||||||
|
log::debug!("Resolved speed {:.2}", speed);
|
||||||
|
|
||||||
|
if let Err(e) = hw_mon.set_speed(speed) {
|
||||||
|
log::error!("Failed to change speed to {}. {:?}", speed, e);
|
||||||
|
}
|
||||||
|
cache.insert(*hw_mon.card, gpu_temp);
|
||||||
|
}
|
||||||
|
std::thread::sleep(std::time::Duration::from_secs(4));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Options)]
|
||||||
|
pub struct Service {
|
||||||
|
#[options(help = "Help message")]
|
||||||
|
help: bool,
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
use crate::config::Card;
|
use crate::config::Card;
|
||||||
use crate::io_err::{invalid_input, not_found};
|
use crate::io_err::{invalid_input, not_found};
|
||||||
use crate::{linear_map, AmdFanError, HwMon, HW_MON_DIR, ROOT_DIR};
|
use crate::utils::linear_map;
|
||||||
|
use crate::{AmdFanError, HwMon, 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";
|
||||||
@ -21,11 +22,11 @@ const PULSE_WIDTH_MODULATION_MANUAL: &str = "1";
|
|||||||
impl HwMon {
|
impl HwMon {
|
||||||
pub fn new(card: &Card, name: &str) -> Self {
|
pub fn new(card: &Card, name: &str) -> Self {
|
||||||
Self {
|
Self {
|
||||||
card: card.clone(),
|
card: *card,
|
||||||
name: String::from(name),
|
name: String::from(name),
|
||||||
pwm_min: None,
|
pwm_min: None,
|
||||||
pwm_max: None,
|
pwm_max: None,
|
||||||
temp_inputs: load_temp_inputs(&card, name),
|
temp_inputs: load_temp_inputs(card, name),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,7 +35,7 @@ impl HwMon {
|
|||||||
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));
|
||||||
}
|
}
|
||||||
results.sort();
|
results.sort_unstable();
|
||||||
results
|
results
|
||||||
.last()
|
.last()
|
||||||
.copied()
|
.copied()
|
||||||
@ -186,7 +187,7 @@ fn hw_mon_dirs_path(card: &Card) -> std::path::PathBuf {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hw_mon_dir_path(card: &Card, name: &str) -> std::path::PathBuf {
|
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) -> std::io::Result<HwMon> {
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
use std::io::Error as IoErr;
|
use std::io::Error as IoErr;
|
||||||
use std::io::ErrorKind;
|
use std::io::ErrorKind;
|
||||||
|
|
||||||
pub fn invalid_data() -> IoErr {
|
#[inline(always)]
|
||||||
IoErr::from(ErrorKind::InvalidData)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn not_found() -> IoErr {
|
pub fn not_found() -> IoErr {
|
||||||
IoErr::from(ErrorKind::NotFound)
|
IoErr::from(ErrorKind::NotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
pub fn invalid_input() -> IoErr {
|
pub fn invalid_input() -> IoErr {
|
||||||
IoErr::from(ErrorKind::NotFound)
|
IoErr::from(ErrorKind::NotFound)
|
||||||
}
|
}
|
||||||
|
188
src/main.rs
188
src/main.rs
@ -1,16 +1,18 @@
|
|||||||
mod config;
|
use std::fmt::Formatter;
|
||||||
mod hw_mon;
|
|
||||||
mod io_err;
|
|
||||||
mod monitor;
|
|
||||||
|
|
||||||
extern crate log;
|
|
||||||
|
|
||||||
use std::io::ErrorKind;
|
use std::io::ErrorKind;
|
||||||
|
|
||||||
use crate::config::{load_config, Card, Config};
|
|
||||||
use crate::io_err::{invalid_data, not_found};
|
|
||||||
use gumdrop::Options;
|
use gumdrop::Options;
|
||||||
use std::fmt::Formatter;
|
|
||||||
|
use crate::config::{load_config, Card};
|
||||||
|
|
||||||
|
mod config;
|
||||||
|
mod fan;
|
||||||
|
mod hw_mon;
|
||||||
|
mod io_err;
|
||||||
|
mod utils;
|
||||||
|
mod voltage;
|
||||||
|
|
||||||
|
extern crate log;
|
||||||
|
|
||||||
static CONFIG_DIR: &str = "/etc/amdfand";
|
static CONFIG_DIR: &str = "/etc/amdfand";
|
||||||
static CONFIG_PATH: &str = "/etc/amdfand/config.toml";
|
static CONFIG_PATH: &str = "/etc/amdfand/config.toml";
|
||||||
@ -45,12 +47,6 @@ impl std::fmt::Display for AmdFanError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// linear mapping from the xrange to the yrange
|
|
||||||
fn linear_map(x: f64, x1: f64, x2: f64, y1: f64, y2: f64) -> f64 {
|
|
||||||
let m = (y2 - y1) / (x2 - x1);
|
|
||||||
m * (x - x1) + y1
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct HwMon {
|
pub struct HwMon {
|
||||||
card: Card,
|
card: Card,
|
||||||
@ -65,38 +61,12 @@ pub enum FanMode {
|
|||||||
Automatic,
|
Automatic,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Options)]
|
#[derive(Options)]
|
||||||
pub struct Service {
|
|
||||||
#[options(help = "Help message")]
|
|
||||||
help: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Options)]
|
|
||||||
pub struct Switcher {
|
|
||||||
#[options(help = "Print help message")]
|
|
||||||
help: bool,
|
|
||||||
#[options(help = "GPU Card number")]
|
|
||||||
card: Option<u32>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Options)]
|
|
||||||
pub struct AvailableCards {
|
|
||||||
#[options(help = "Help message")]
|
|
||||||
help: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Options)]
|
|
||||||
pub enum Command {
|
pub enum Command {
|
||||||
#[options(help = "Print current temp and fan speed")]
|
#[options(help = "GPU card fan control")]
|
||||||
Monitor(monitor::Monitor),
|
Fan(fan::FanCommand),
|
||||||
#[options(help = "Set fan speed depends on GPU temperature")]
|
#[options(help = "Overclock GPU card")]
|
||||||
Service(Service),
|
Voltage(voltage::VoltageCommand),
|
||||||
#[options(help = "Switch to GPU automatic fan speed control")]
|
|
||||||
SetAutomatic(Switcher),
|
|
||||||
#[options(help = "Switch to GPU manual fan speed control")]
|
|
||||||
SetManual(Switcher),
|
|
||||||
#[options(help = "Print available cards")]
|
|
||||||
Available(AvailableCards),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Options)]
|
#[derive(Options)]
|
||||||
@ -109,105 +79,6 @@ pub struct Opts {
|
|||||||
command: Option<Command>,
|
command: Option<Command>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_cards() -> std::io::Result<Vec<Card>> {
|
|
||||||
let mut cards = vec![];
|
|
||||||
let entries = std::fs::read_dir(ROOT_DIR)?;
|
|
||||||
for entry in entries {
|
|
||||||
match entry
|
|
||||||
.and_then(|entry| {
|
|
||||||
entry
|
|
||||||
.file_name()
|
|
||||||
.as_os_str()
|
|
||||||
.to_str()
|
|
||||||
.map(String::from)
|
|
||||||
.ok_or_else(invalid_data)
|
|
||||||
})
|
|
||||||
.and_then(|file_name| file_name.parse::<Card>().map_err(|_| invalid_data()))
|
|
||||||
{
|
|
||||||
Ok(card) => {
|
|
||||||
cards.push(card);
|
|
||||||
}
|
|
||||||
_ => continue,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
Ok(cards)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn controllers(config: &Config, filter: bool) -> std::io::Result<Vec<HwMon>> {
|
|
||||||
Ok(read_cards()?
|
|
||||||
.into_iter()
|
|
||||||
.filter(|card| !filter || config.cards().iter().find(|name| **name == *card).is_some())
|
|
||||||
.filter_map(|card| hw_mon::open_hw_mon(card).ok())
|
|
||||||
.filter(|hw_mon| !filter || { hw_mon.is_amd() })
|
|
||||||
.filter(|hw_mon| !filter || hw_mon.name_is_amd())
|
|
||||||
.collect())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn service(config: Config) -> std::io::Result<()> {
|
|
||||||
let mut controllers = controllers(&config, true)?;
|
|
||||||
if controllers.is_empty() {
|
|
||||||
return Err(not_found());
|
|
||||||
}
|
|
||||||
let mut cache = std::collections::HashMap::new();
|
|
||||||
loop {
|
|
||||||
for hw_mon in controllers.iter_mut() {
|
|
||||||
let gpu_temp = hw_mon.max_gpu_temp().unwrap_or_default();
|
|
||||||
log::debug!("Current {} temperature: {}", hw_mon.card, gpu_temp);
|
|
||||||
let last = *cache.entry(*hw_mon.card).or_insert(1_000f64);
|
|
||||||
|
|
||||||
if (last - gpu_temp).abs() < 0.001f64 {
|
|
||||||
log::debug!("Temperature didn't change");
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
let speed = config.speed_for_temp(gpu_temp);
|
|
||||||
log::debug!("Resolved speed {:.2}", speed);
|
|
||||||
|
|
||||||
if let Err(e) = hw_mon.set_speed(speed) {
|
|
||||||
log::error!("Failed to change speed to {}. {:?}", speed, e);
|
|
||||||
}
|
|
||||||
cache.insert(*hw_mon.card, gpu_temp);
|
|
||||||
}
|
|
||||||
std::thread::sleep(std::time::Duration::from_secs(4));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn change_mode(switcher: Switcher, mode: FanMode, config: Config) -> std::io::Result<()> {
|
|
||||||
let mut controllers = controllers(&config, true)?;
|
|
||||||
|
|
||||||
let cards = match switcher.card {
|
|
||||||
Some(card_id) => match controllers
|
|
||||||
.iter()
|
|
||||||
.position(|hw_mon| *hw_mon.card == card_id)
|
|
||||||
{
|
|
||||||
Some(card) => vec![controllers.remove(card)],
|
|
||||||
None => {
|
|
||||||
eprintln!("Card does not exists. Available cards: ");
|
|
||||||
for hw_mon in controllers {
|
|
||||||
eprintln!(" * {}", *hw_mon.card);
|
|
||||||
}
|
|
||||||
return Err(not_found());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => controllers,
|
|
||||||
};
|
|
||||||
|
|
||||||
for hw_mon in cards {
|
|
||||||
match mode {
|
|
||||||
FanMode::Automatic => {
|
|
||||||
if let Err(e) = hw_mon.set_automatic() {
|
|
||||||
log::error!("{:?}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FanMode::Manual => {
|
|
||||||
if let Err(e) = hw_mon.set_manual() {
|
|
||||||
log::error!("{:?}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> std::io::Result<()> {
|
fn main() -> std::io::Result<()> {
|
||||||
if std::fs::read(CONFIG_DIR).map_err(|e| e.kind() == ErrorKind::NotFound) == Err(true) {
|
if std::fs::read(CONFIG_DIR).map_err(|e| e.kind() == ErrorKind::NotFound) == Err(true) {
|
||||||
std::fs::create_dir_all(CONFIG_DIR)?;
|
std::fs::create_dir_all(CONFIG_DIR)?;
|
||||||
@ -215,7 +86,7 @@ fn main() -> std::io::Result<()> {
|
|||||||
|
|
||||||
let config = load_config()?;
|
let config = load_config()?;
|
||||||
|
|
||||||
std::env::set_var("RUST_LOG", config.log_level().to_str());
|
std::env::set_var("RUST_LOG", config.log_level().as_str());
|
||||||
pretty_env_logger::init();
|
pretty_env_logger::init();
|
||||||
|
|
||||||
let opts: Opts = Opts::parse_args_default_or_exit();
|
let opts: Opts = Opts::parse_args_default_or_exit();
|
||||||
@ -226,14 +97,20 @@ fn main() -> std::io::Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
match opts.command {
|
match opts.command {
|
||||||
None => service(config),
|
None => fan::service::run(config),
|
||||||
Some(Command::Monitor(monitor)) => monitor::run(monitor, config),
|
Some(Command::Fan(fan::FanCommand::Monitor(monitor))) => fan::monitor::run(monitor, config),
|
||||||
Some(Command::Service(_)) => service(config),
|
Some(Command::Fan(fan::FanCommand::Service(_))) => fan::service::run(config),
|
||||||
Some(Command::SetAutomatic(switcher)) => change_mode(switcher, FanMode::Automatic, config),
|
Some(Command::Fan(fan::FanCommand::SetAutomatic(switcher))) => {
|
||||||
Some(Command::SetManual(switcher)) => change_mode(switcher, FanMode::Manual, config),
|
fan::change_mode::run(switcher, FanMode::Automatic, config)
|
||||||
Some(Command::Available(_)) => {
|
}
|
||||||
|
Some(Command::Fan(fan::FanCommand::SetManual(switcher))) => {
|
||||||
|
fan::change_mode::run(switcher, FanMode::Manual, config)
|
||||||
|
}
|
||||||
|
Some(Command::Fan(fan::FanCommand::Available(_))) => {
|
||||||
println!("Available cards");
|
println!("Available cards");
|
||||||
controllers(&config, false)?.into_iter().for_each(|hw_mon| {
|
utils::controllers(&config, false)?
|
||||||
|
.into_iter()
|
||||||
|
.for_each(|hw_mon| {
|
||||||
println!(
|
println!(
|
||||||
" * {:6>} - {}",
|
" * {:6>} - {}",
|
||||||
hw_mon.card,
|
hw_mon.card,
|
||||||
@ -242,5 +119,8 @@ fn main() -> std::io::Result<()> {
|
|||||||
});
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Some(Command::Voltage(voltage::VoltageCommand::Placeholder(_))) => {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
30
src/utils.rs
Normal file
30
src/utils.rs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
use crate::config::{Card, Config};
|
||||||
|
use crate::{hw_mon, HwMon, ROOT_DIR};
|
||||||
|
|
||||||
|
/// linear mapping from the xrange to the yrange
|
||||||
|
pub fn linear_map(x: f64, x1: f64, x2: f64, y1: f64, y2: f64) -> f64 {
|
||||||
|
let m = (y2 - y1) / (x2 - x1);
|
||||||
|
m * (x - x1) + y1
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read all available graphic cards from direct rendering manager
|
||||||
|
pub fn read_cards() -> std::io::Result<Vec<Card>> {
|
||||||
|
Ok(std::fs::read_dir(ROOT_DIR)?
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|entry| entry.ok())
|
||||||
|
.filter_map(|entry| entry.file_name().as_os_str().to_str().map(String::from))
|
||||||
|
.filter_map(|file_name| file_name.parse::<Card>().ok())
|
||||||
|
.collect())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wrap cards in HW Mon manipulator and
|
||||||
|
/// filter cards so only amd and listed in config cards are accessible
|
||||||
|
pub fn controllers(config: &Config, filter: bool) -> std::io::Result<Vec<HwMon>> {
|
||||||
|
Ok(read_cards()?
|
||||||
|
.into_iter()
|
||||||
|
.filter(|card| !filter || config.cards().iter().any(|name| **name == **card))
|
||||||
|
.filter_map(|card| hw_mon::open_hw_mon(card).ok())
|
||||||
|
.filter(|hw_mon| !filter || { hw_mon.is_amd() })
|
||||||
|
.filter(|hw_mon| !filter || hw_mon.name_is_amd())
|
||||||
|
.collect())
|
||||||
|
}
|
9
src/voltage/mod.rs
Normal file
9
src/voltage/mod.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#[derive(Debug, gumdrop::Options)]
|
||||||
|
pub enum VoltageCommand {
|
||||||
|
Placeholder(Placeholder),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, gumdrop::Options)]
|
||||||
|
pub struct Placeholder {
|
||||||
|
help: bool,
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user