1
Fork 0
mirror of https://github.com/RGBCube/superfreq synced 2025-07-28 01:17:45 +00:00

Merge pull request #6 from NotAShelf/push-lwuuusounywk

cpu: check if platform profile is in available_profiles
This commit is contained in:
raf 2025-05-13 20:25:26 +03:00 committed by GitHub
commit c8361f0e26
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1,8 +1,10 @@
use crate::core::TurboSetting; use crate::core::TurboSetting;
use crate::monitor::Result as MonitorResult; use crate::monitor::Result as MonitorResult;
use core::str;
use std::{ use std::{
fs, io, fs, io,
path::{Path, PathBuf}, path::{Path, PathBuf},
string::ToString,
}; };
#[derive(Debug)] #[derive(Debug)]
@ -12,6 +14,7 @@ pub enum ControlError {
InvalidValueError(String), InvalidValueError(String),
NotSupported(String), NotSupported(String),
PermissionDenied(String), PermissionDenied(String),
InvalidProfile(String),
} }
impl From<io::Error> for ControlError { impl From<io::Error> for ControlError {
@ -33,6 +36,13 @@ impl std::fmt::Display for ControlError {
ControlError::PermissionDenied(s) => { ControlError::PermissionDenied(s) => {
write!(f, "Permission denied: {}. Try running with sudo.", s) write!(f, "Permission denied: {}. Try running with sudo.", s)
} }
ControlError::InvalidProfile(s) => {
write!(
f,
"Invalid platform control profile {} supplied, please provide a valid one.",
s
)
}
} }
} }
} }
@ -217,17 +227,70 @@ pub fn set_max_frequency(freq_mhz: u32, core_id: Option<u32>) -> Result<()> {
} }
} }
/// Sets the platform profile.
/// This changes the system performance, temperature, fan, and other hardware replated characteristics.
///
/// Also see [`The Kernel docs`] for this.
///
/// [`The Kernel docs`]: <https://docs.kernel.org/userspace-api/sysfs-platform_profile.html>
///
/// # Examples
///
/// ```
/// set_platform_profile("balanced");
/// ```
///
pub fn set_platform_profile(profile: &str) -> Result<()> { pub fn set_platform_profile(profile: &str) -> Result<()> {
let path = "/sys/firmware/acpi/platform_profile"; let path = "/sys/firmware/acpi/platform_profile";
if Path::new(path).exists() { if !Path::new(path).exists() {
// Before writing, it'd be nice to check if the profile is in available_profiles return Err(ControlError::NotSupported(format!(
// Reading available profiles: /sys/firmware/acpi/platform_profile_choices "Platform profile control not found at {path}.",
// TODO: Validate profile against available profiles here for a cleaner impl. )));
write_sysfs_value(path, profile)
} else {
Err(ControlError::NotSupported(
"Platform profile control not found at /sys/firmware/acpi/platform_profile."
.to_string(),
))
} }
let available_profiles = get_platform_profiles()?;
if !available_profiles.contains(&profile.to_string()) {
return Err(ControlError::InvalidProfile(format!(
"Invalid platform control profile provided.\n\
Provided profile: {} \n\
Available profiles:\n\
{}",
profile,
available_profiles.join(", ")
)));
}
write_sysfs_value(path, profile)
}
/// Returns the list of available platform profiles.
///
/// # Errors
///
/// Returns [`ControlError::NotSupported`] if:
/// - The file `/sys/firmware/acpi/platform_profile_choices` does not exist.
/// - The file `/sys/firmware/acpi/platform_profile_choices` is empty.
///
/// Returns [`ControlError::PermissionDenied`] if the file `/sys/firmware/acpi/platform_profile_choices` cannot be read.
///
pub fn get_platform_profiles() -> Result<Vec<String>> {
let path = "/sys/firmware/acpi/platform_profile_choices";
if !Path::new(path).exists() {
return Err(ControlError::NotSupported(format!(
"Platform profile choices not found at {path}."
)));
}
let buf = fs::read(path)
.map_err(|_| ControlError::PermissionDenied(format!("Cannot read contents of {path}.")))?;
let content = str::from_utf8(&buf).map_err(|_| {
ControlError::NotSupported(format!("No platform profile choices found at {path}."))
})?;
Ok(content
.split_whitespace()
.map(ToString::to_string)
.collect())
} }