Parse percentages in fan curve only if '%' provided otherwise range is 0-255

This commit is contained in:
Luke D. Jones
2021-10-27 22:35:45 +13:00
parent 328ff0251b
commit 3f0df82f2d
4 changed files with 31 additions and 5 deletions

View File

@@ -12,6 +12,7 @@ pub enum ProfileError {
ParseFanCurveDigit(std::num::ParseIntError),
/// (pwm/temp, prev, next)
ParseFanCurvePrevHigher(&'static str, u8, u8),
ParseFanCurvePercentOver100(u8),
// Zbus(zbus::Error),
}
@@ -34,6 +35,9 @@ impl fmt::Display for ProfileError {
"Invalid {}, previous value {} is higher than next value {}",
part, prev, next
),
ProfileError::ParseFanCurvePercentOver100(value) => {
write!(f, "Invalid percentage, {} is higher than 100", value)
}
// Error::Zbus(detail) => write!(f, "Zbus error: {}", detail),
}
}

View File

@@ -37,14 +37,24 @@ pub struct CurveData {
impl std::str::FromStr for CurveData {
type Err = ProfileError;
/// Parse a string to the correct values that the fan curve kernel driver expects
///
/// If the fan curve is given with percentage char '%' then the fan power values are converted
/// otherwise the expected fan power range is 0-255.
///
/// Temperature range is 0-255 in degrees C. You don't want to be setting over 100.
fn from_str(input: &str) -> Result<Self, Self::Err> {
let mut temp = [0u8; 8];
let mut pwm = [0u8; 8];
let mut temp_prev = 0;
let mut pwm_prev = 0;
let mut percentages = false;
for (index, value) in input.split(',').enumerate() {
for (select, num) in value.splitn(2, |c| c == 'c' || c == ':').enumerate() {
if num.contains('%') {
percentages = true;
}
let r = num.trim_matches(|c| c == 'c' || c == ':' || c == '%');
let r = r.parse::<u8>().map_err(ProfileError::ParseFanCurveDigit)?;
@@ -59,15 +69,22 @@ impl std::str::FromStr for CurveData {
temp_prev = r;
temp[index] = r;
} else {
if pwm_prev > r {
let mut p = r;
if percentages {
p *= 255 / 100;
if p > 100 {
return Err(ProfileError::ParseFanCurvePercentOver100(r));
}
}
if pwm_prev > p {
return Err(ProfileError::ParseFanCurvePrevHigher(
"percentage",
pwm_prev,
r,
p,
));
}
pwm_prev = r;
pwm[index] = r;
pwm_prev = p;
pwm[index] = p;
}
}
}