diff --git a/daemon/src/gpu_controller.rs b/daemon/src/gpu_controller.rs index 0d2c535..4f1f92d 100644 --- a/daemon/src/gpu_controller.rs +++ b/daemon/src/gpu_controller.rs @@ -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, 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( + &path, + config.fan_control_enabled, + config.fan_curve.clone(), + ); + Some(hw_mon) + }, + _ => None, + }; - let hw_mon = HWMon::new( - &hwmon_path, - config.fan_control_enabled, - config.fan_curve.clone(), - ); 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::>(); - match split[0] { - "DRIVER" => driver = split[1].to_string(), - "PCI_ID" => { - let ids = split[1].split(':').collect::>(); - 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::>(); + 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::>(); - 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::>(); + card_vendor_id = ids.get(0).unwrap().to_string(); + card_model_id = ids.get(1).unwrap().to_string(); } _ => (), } @@ -116,38 +117,46 @@ 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(); + } - //some weird space character, don't touch - let pci_id_line = format!(" {}", model_id.to_lowercase()); - let card_ids_line = format!( - " {} {}", - card_vendor_id.to_lowercase(), - card_model_id.to_lowercase() - ); + 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!( + " {} {}", + card_vendor_id.to_lowercase(), + card_model_id.to_lowercase() + ); - let lines: Vec<&str> = full_hwid_list.split('\n').collect(); + let lines: Vec<&str> = full_hwid_list.split('\n').collect(); - //for line in full_hwid_list.split('\n') { - for i in 0..lines.len() { - let line = lines[i]; + //for line in full_hwid_list.split('\n') { + for i in 0..lines.len() { + let line = lines[i]; - 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::>()[1] - .trim_start() - .to_string(); + 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::>().last().unwrap() + .trim_start() + .to_string(); + } + } + if line.contains(&pci_id_line) { + model = line[pci_id_line.len()..].trim_start().to_string(); + } + if line.contains(&card_ids_line) { + card_model = line[card_ids_line.len()..].trim_start().to_string(); } } - if line.contains(&pci_id_line) { - model = line[pci_id_line.len()..].trim_start().to_string(); - } - if line.contains(&card_ids_line) { - 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, Err(_) => "".to_string(), @@ -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,48 +227,70 @@ impl GpuController { } pub fn start_fan_control(&mut self) -> Result<(), HWMonError> { - match self.hw_mon.start_fan_control() { - Ok(_) => { - self.config.fan_control_enabled = true; - self.config - .save(&self.config_path) - .expect("Failed to save config"); - Ok(()) - } - Err(e) => Err(e), + match &self.hw_mon { + Some(hw_mon) => { + + match hw_mon.start_fan_control() { + Ok(_) => { + self.config.fan_control_enabled = true; + self.config + .save(&self.config_path) + .expect("Failed to save config"); + Ok(()) + } + Err(e) => Err(e), + } + }, + None => Err(HWMonError::NoHWMon), } } pub fn stop_fan_control(&mut self) -> Result<(), HWMonError> { - match self.hw_mon.stop_fan_control() { - Ok(_) => { - self.config.fan_control_enabled = false; + match &self.hw_mon { + Some(hw_mon) => { + match hw_mon.stop_fan_control() { + Ok(_) => { + self.config.fan_control_enabled = false; + self.config + .save(&self.config_path) + .expect("Failed to save config"); + Ok(()) + } + Err(e) => Err(e), + } + }, + None => Err(HWMonError::NoHWMon), + } + } + + pub fn get_fan_control(&self) -> Result { + 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) -> 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(()) - } - Err(e) => Err(e), + }, + None => Err(HWMonError::NoHWMon), } } - pub fn get_fan_control(&self) -> FanControlInfo { - let control = self.hw_mon.get_fan_control(); - - FanControlInfo { - enabled: control.0, - curve: control.1, - } - } - - pub fn set_fan_curve(&mut self, curve: BTreeMap) { - self.hw_mon.set_fan_curve(curve.clone()); - self.config.fan_curve = curve; - self.config - .save(&self.config_path) - .expect("Failed to save config"); - } - fn get_vulkan_info(pci_id: &str) -> VulkanInfo { let mut device_name = String::from("Not supported"); let mut api_version = String::new(); diff --git a/daemon/src/hw_mon.rs b/daemon/src/hw_mon.rs index 800cf8b..12e22c5 100644 --- a/daemon/src/hw_mon.rs +++ b/daemon/src/hw_mon.rs @@ -15,6 +15,7 @@ use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug)] pub enum HWMonError { PermissionDenied, + NoHWMon, } #[derive(Debug, Clone)] diff --git a/daemon/src/lib.rs b/daemon/src/lib.rs index 3055576..569c68f 100644 --- a/daemon/src/lib.rs +++ b/daemon/src/lib.rs @@ -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), } diff --git a/gui/src/main.rs b/gui/src/main.rs index 364be12..699b9eb 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -146,17 +146,28 @@ fn build_ui(application: >k::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); - if fan_control.enabled { - println!("Automatic fan control disabled!"); - automatic_fan_control_switch.set_active(false); - fan_curve_frame.set_visible(true); - } else { - println!("Automatic fan control enabled"); - fan_curve_frame.set_visible(false); + match fan_control { + Ok(ref fan_control) => { + if fan_control.enabled { + println!("Automatic fan control disabled!"); + automatic_fan_control_switch.set_active(false); + fan_curve_frame.set_visible(true); + } else { + 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(); let switch = automatic_fan_control_switch.clone(); @@ -173,55 +184,62 @@ fn build_ui(application: >k::Application) { b.set_sensitive(true); }); - let curve: Arc>> = Arc::new(RwLock::new(fan_control.curve)); + match fan_control { + Ok(fan_control) => { - for i in 1..6 { - let curve_temperature_adjustment: Adjustment = builder - .get_object(&format!("curve_temperature_adjustment_{}", i)) - .unwrap(); + let curve: Arc>> = Arc::new(RwLock::new(fan_control.curve)); - let value = *curve - .read() - .unwrap() - .get(&(i * 20)) - .expect("Could not get by index"); - println!("Setting value {} on adjustment {}", value, i); - curve_temperature_adjustment.set_value(value); + for i in 1..6 { + let curve_temperature_adjustment: Adjustment = builder + .get_object(&format!("curve_temperature_adjustment_{}", i)) + .unwrap(); - let c = curve.clone(); - let b = apply_button.clone(); + let value = *curve + .read() + .unwrap() + .get(&(i * 20)) + .expect("Could not get by index"); + println!("Setting value {} on adjustment {}", value, i); + curve_temperature_adjustment.set_value(value); - curve_temperature_adjustment.connect_value_changed(move |adj| { - c.write().unwrap().insert(20 * i, adj.get_value()); - b.set_sensitive(true); - }); + let c = curve.clone(); + let b = apply_button.clone(); + + curve_temperature_adjustment.connect_value_changed(move |adj| { + c.write().unwrap().insert(20 * i, adj.get_value()); + b.set_sensitive(true); + }); + } + + apply_button.connect_clicked(move |b| { + let curve = curve.read().unwrap().clone(); + println!("setting curve to {:?}", curve); + d.set_fan_curve(current_gpu_id, curve).unwrap(); + b.set_sensitive(false); + + match automatic_fan_control_switch.get_active() { + true => { + d.stop_fan_control(current_gpu_id).unwrap(); + + let diag = MessageDialog::new( + None::<&Window>, + DialogFlags::empty(), + MessageType::Error, + ButtonsType::Ok, + "WARNING: Due to a driver bug, the GPU fan may misbehave after switching to automatic control. You may need to reboot your system to avoid issues.", + ); + diag.run(); + diag.hide(); + } + false => { + d.start_fan_control(current_gpu_id).unwrap(); + } + } + }); + }, + Err(_) => (), } - apply_button.connect_clicked(move |b| { - let curve = curve.read().unwrap().clone(); - println!("setting curve to {:?}", curve); - d.set_fan_curve(current_gpu_id, curve).unwrap(); - b.set_sensitive(false); - - match automatic_fan_control_switch.get_active() { - true => { - d.stop_fan_control(current_gpu_id).unwrap(); - - let diag = MessageDialog::new( - None::<&Window>, - DialogFlags::empty(), - MessageType::Error, - ButtonsType::Ok, - "WARNING: Due to a driver bug, the GPU fan may misbehave after switching to automatic control. You may need to reboot your system to avoid issues.", - ); - diag.run(); - diag.hide(); - } - false => { - d.start_fan_control(current_gpu_id).unwrap(); - } - } - }); main_window.set_application(Some(application));