Added pci.ids path for ubuntu and fixed crash for GPUs without hwmon interface

This commit is contained in:
Ilya Zlobintsev 2020-11-11 17:25:37 +02:00
parent 55bc2ee468
commit d5d0829e4e
4 changed files with 191 additions and 137 deletions

View File

@ -1,7 +1,7 @@
use crate::config::Config;
use crate::hw_mon::{HWMon, HWMonError};
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
use std::path::{Path, PathBuf};
use std::{collections::BTreeMap, fs};
use vulkano::instance::{Instance, InstanceExtensions, PhysicalDevice};
@ -27,7 +27,7 @@ pub struct FanControlInfo {
#[derive(Clone)]
pub struct GpuController {
hw_path: PathBuf,
hw_mon: HWMon,
hw_mon: Option<HWMon>,
pub gpu_info: GpuInfo,
config: Config,
config_path: PathBuf,
@ -58,18 +58,19 @@ pub struct GpuInfo {
impl GpuController {
pub fn new(hw_path: PathBuf, config: Config, config_path: PathBuf) -> Self {
let hwmon_path = fs::read_dir(&hw_path.join("hwmon"))
.unwrap()
.next()
.unwrap()
.unwrap()
.path();
let hw_mon = match fs::read_dir(&hw_path.join("hwmon")) {
Ok(mut path) => {
let path = path.next().unwrap().unwrap().path();
let hw_mon = HWMon::new(
&hwmon_path,
&path,
config.fan_control_enabled,
config.fan_curve.clone(),
);
Some(hw_mon)
},
_ => None,
};
let mut controller = GpuController {
hw_path: hw_path.clone(),
@ -95,17 +96,17 @@ impl GpuController {
for line in uevent.split('\n') {
let split = line.split('=').collect::<Vec<&str>>();
match split[0] {
"DRIVER" => driver = split[1].to_string(),
"PCI_ID" => {
let ids = split[1].split(':').collect::<Vec<&str>>();
vendor_id = ids[0].to_string();
model_id = ids[1].to_string();
match split.get(0).unwrap() {
&"DRIVER" => driver = split.get(1).unwrap().to_string(),
&"PCI_ID" => {
let ids = split.last().expect("failed to get split").split(':').collect::<Vec<&str>>();
vendor_id = ids.get(0).unwrap().to_string();
model_id = ids.get(0).unwrap().to_string();
}
"PCI_SUBSYS_ID" => {
let ids = split[1].split(':').collect::<Vec<&str>>();
card_vendor_id = ids[0].to_string();
card_model_id = ids[1].to_string();
&"PCI_SUBSYS_ID" => {
let ids = split.last().expect("failed to get split").split(':').collect::<Vec<&str>>();
card_vendor_id = ids.get(0).unwrap().to_string();
card_model_id = ids.get(1).unwrap().to_string();
}
_ => (),
}
@ -116,9 +117,14 @@ impl GpuController {
let mut card_vendor = String::new();
let mut card_model = String::new();
let full_hwid_list = fs::read_to_string("/usr/share/hwdata/pci.ids")
.expect("Could not read pci.ids. Perhaps the \"hwids\" package is not installed?");
let mut full_hwid_list = String::new();
if Path::exists(&PathBuf::from("/usr/share/hwdata/pci.ids")) {
full_hwid_list = fs::read_to_string("/usr/share/hwdata/pci.ids").unwrap();
} else if Path::exists(&PathBuf::from("/usr/share/misc/pci.ids")) {
full_hwid_list = fs::read_to_string("/usr/share/misc/pci.ids").unwrap();
}
if !full_hwid_list.is_empty() {
//some weird space character, don't touch
let pci_id_line = format!(" {}", model_id.to_lowercase());
let card_ids_line = format!(
@ -135,7 +141,7 @@ impl GpuController {
if line.len() > card_vendor_id.len() {
if line[0..card_vendor_id.len()] == card_vendor_id.to_lowercase() {
card_vendor = line.splitn(2, ' ').collect::<Vec<&str>>()[1]
card_vendor = line.splitn(2, ' ').collect::<Vec<&str>>().last().unwrap()
.trim_start()
.to_string();
}
@ -147,6 +153,9 @@ impl GpuController {
card_model = line[card_ids_line.len()..].trim_start().to_string();
}
}
}
let vbios_version = match fs::read_to_string(self.hw_path.join("vbios_version")) {
Ok(v) => v,
@ -199,11 +208,10 @@ impl GpuController {
Err(_) => 0,
};
let (mem_freq, gpu_freq) = (self.hw_mon.get_mem_freq(), self.hw_mon.get_gpu_freq());
let gpu_temp = self.hw_mon.get_gpu_temp();
let (power_avg, power_max) = (self.hw_mon.get_power_avg(), self.hw_mon.get_power_cap());
let fan_speed = self.hw_mon.get_fan_speed();
let max_fan_speed = self.hw_mon.fan_max_speed;
let (mem_freq, gpu_freq, gpu_temp, power_avg, power_max, fan_speed, max_fan_speed) = match &self.hw_mon {
Some(hw_mon) => (hw_mon.get_mem_freq(), hw_mon.get_gpu_freq(), hw_mon.get_gpu_temp(), hw_mon.get_power_avg(), hw_mon.get_power_cap(), hw_mon.get_fan_speed(), hw_mon.fan_max_speed),
None => (0, 0, 0, 0, 0, 0, 0),
};
GpuStats {
mem_total,
@ -219,7 +227,10 @@ impl GpuController {
}
pub fn start_fan_control(&mut self) -> Result<(), HWMonError> {
match self.hw_mon.start_fan_control() {
match &self.hw_mon {
Some(hw_mon) => {
match hw_mon.start_fan_control() {
Ok(_) => {
self.config.fan_control_enabled = true;
self.config
@ -229,10 +240,15 @@ impl GpuController {
}
Err(e) => Err(e),
}
},
None => Err(HWMonError::NoHWMon),
}
}
pub fn stop_fan_control(&mut self) -> Result<(), HWMonError> {
match self.hw_mon.stop_fan_control() {
match &self.hw_mon {
Some(hw_mon) => {
match hw_mon.stop_fan_control() {
Ok(_) => {
self.config.fan_control_enabled = false;
self.config
@ -242,23 +258,37 @@ impl GpuController {
}
Err(e) => Err(e),
}
},
None => Err(HWMonError::NoHWMon),
}
}
pub fn get_fan_control(&self) -> FanControlInfo {
let control = self.hw_mon.get_fan_control();
FanControlInfo {
pub fn get_fan_control(&self) -> Result<FanControlInfo, HWMonError> {
match &self.hw_mon {
Some(hw_mon) => {
let control = hw_mon.get_fan_control();
Ok(FanControlInfo {
enabled: control.0,
curve: control.1,
}
})
},
None => Err(HWMonError::NoHWMon),
}
pub fn set_fan_curve(&mut self, curve: BTreeMap<i32, f64>) {
self.hw_mon.set_fan_curve(curve.clone());
}
pub fn set_fan_curve(&mut self, curve: BTreeMap<i32, f64>) -> Result<(), HWMonError> {
match &self.hw_mon {
Some(hw_mon) => {
hw_mon.set_fan_curve(curve.clone());
self.config.fan_curve = curve;
self.config
.save(&self.config_path)
.expect("Failed to save config");
Ok(())
},
None => Err(HWMonError::NoHWMon),
}
}
fn get_vulkan_info(pci_id: &str) -> VulkanInfo {

View File

@ -15,6 +15,7 @@ use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
pub enum HWMonError {
PermissionDenied,
NoHWMon,
}
#[derive(Debug, Clone)]

View File

@ -150,7 +150,10 @@ impl Daemon {
None => Err(DaemonError::InvalidID),
},
Action::GetFanControl(i) => match gpu_controllers.get(&i) {
Some(controller) => Ok(DaemonResponse::FanControlInfo(controller.get_fan_control())),
Some(controller) => match controller.get_fan_control() {
Ok(info) => Ok(DaemonResponse::FanControlInfo(info)),
Err(_) => Err(DaemonError::HWMonError),
}
None => Err(DaemonError::InvalidID),
}
Action::SetFanCurve(i, curve) => match gpu_controllers.get_mut(&i) {
@ -159,9 +162,11 @@ impl Daemon {
let mut buffer = Vec::new();
stream.read_to_end(&mut buffer).unwrap();
controller.set_fan_curve(curve);
match controller.set_fan_curve(curve) {
Ok(_) => Ok(DaemonResponse::OK),
Err(_) => Err(DaemonError::HWMonError),
}
Ok(DaemonResponse::OK)
},
None => Err(DaemonError::InvalidID),
}

View File

@ -146,8 +146,10 @@ fn build_ui(application: &gtk::Application) {
glib::Continue(true)
});
let fan_control = d.get_fan_control(current_gpu_id).unwrap();
let fan_control = d.get_fan_control(current_gpu_id);
match fan_control {
Ok(ref fan_control) => {
if fan_control.enabled {
println!("Automatic fan control disabled!");
automatic_fan_control_switch.set_active(false);
@ -156,6 +158,15 @@ fn build_ui(application: &gtk::Application) {
println!("Automatic fan control enabled");
fan_curve_frame.set_visible(false);
}
},
Err(_) => {
automatic_fan_control_switch.set_sensitive(false);
automatic_fan_control_switch.set_tooltip_text(Some("Unavailable"));
fan_curve_frame.set_visible(false);
}
}
let b = apply_button.clone();
@ -173,6 +184,9 @@ fn build_ui(application: &gtk::Application) {
b.set_sensitive(true);
});
match fan_control {
Ok(fan_control) => {
let curve: Arc<RwLock<BTreeMap<i32, f64>>> = Arc::new(RwLock::new(fan_control.curve));
for i in 1..6 {
@ -222,6 +236,10 @@ fn build_ui(application: &gtk::Application) {
}
}
});
},
Err(_) => (),
}
main_window.set_application(Some(application));