diff --git a/asusd/src/ctrl_fancurves.rs b/asusd/src/ctrl_fancurves.rs index d68d9b170..9a73c307f 100644 --- a/asusd/src/ctrl_fancurves.rs +++ b/asusd/src/ctrl_fancurves.rs @@ -221,6 +221,7 @@ impl CtrlFanCurveZbus { profile: PlatformProfile, curve: CurveData, ) -> zbus::fdo::Result<()> { + curve.validate()?; self.config .lock() .await diff --git a/rog-profiles/src/fan_curve_set.rs b/rog-profiles/src/fan_curve_set.rs index 039406bf4..d6a85bbeb 100644 --- a/rog-profiles/src/fan_curve_set.rs +++ b/rog-profiles/src/fan_curve_set.rs @@ -65,8 +65,6 @@ impl std::str::FromStr for CurveData { fn from_str(input: &str) -> Result { let mut temp = [0u8; 8]; let mut pwm = [0u8; 8]; - let mut temp_prev = 0; - let mut pwm_prev = 0; let mut percentages = false; if input.split(',').count() < 8 { @@ -82,12 +80,6 @@ impl std::str::FromStr for CurveData { let r = r.parse::().map_err(ProfileError::ParseFanCurveDigit)?; if select == 0 { - if temp_prev > r { - return Err(ProfileError::ParseFanCurvePrevHigher( - "temperature", temp_prev, r, - )); - } - temp_prev = r; temp[index] = r; } else { let mut p = r; @@ -97,12 +89,6 @@ impl std::str::FromStr for CurveData { } p = (p as f32 * 2.55).round() as u8; } - if pwm_prev > p { - return Err(ProfileError::ParseFanCurvePrevHigher( - "percentage", pwm_prev, p, - )); - } - pwm_prev = p; pwm[index] = p; } } @@ -121,6 +107,25 @@ impl CurveData { self.fan = fan; } + /// Check that both temperature and fan power ascend across the eight + /// points. Equal adjacent values are allowed so that flat sections of a + /// curve remain valid. + pub fn validate(&self) -> Result<(), ProfileError> { + for (label, points) in [ + ("temperature", &self.temp), + ("percentage", &self.pwm), + ] { + for pair in points.windows(2) { + if pair[0] > pair[1] { + return Err(ProfileError::ParseFanCurvePrevHigher( + label, pair[0], pair[1], + )); + } + } + } + Ok(()) + } + fn set_val_from_attr(tmp: &str, device: &Device, buf: &mut [u8; 8]) { if let Some(n) = tmp.chars().nth(15) { if let Some(digit) = n.to_digit(10) { @@ -244,14 +249,33 @@ mod tests { } #[test] - fn curve_data_from_str_invalid_pwm() { + fn validate_invalid_pwm() -> Result<(), Box> { let curve = - CurveData::from_str("30c:4%,49c:2%,59c:3%,69c:4%,79c:31%,89c:49%,99c:56%,109c:58%"); - assert!(&curve.is_err()); + CurveData::from_str("30c:4%,49c:2%,59c:3%,69c:4%,79c:31%,89c:49%,99c:56%,109c:58%")?; assert!(matches!( - curve, - Err(ProfileError::ParseFanCurvePrevHigher(_, _, _)) + curve.validate(), + Err(ProfileError::ParseFanCurvePrevHigher("percentage", _, _)) )); + Ok(()) + } + + #[test] + fn validate_invalid_temp() -> Result<(), Box> { + let curve = + CurveData::from_str("100c:1%,50c:2%,59c:3%,69c:4%,79c:31%,89c:49%,99c:56%,109c:58%")?; + assert!(matches!( + curve.validate(), + Err(ProfileError::ParseFanCurvePrevHigher("temperature", _, _)) + )); + Ok(()) + } + + #[test] + fn validate_accepts_flat_sections() -> Result<(), Box> { + let curve = + CurveData::from_str("30c:1%,30c:1%,59c:3%,69c:4%,79c:31%,89c:49%,99c:56%,109c:58%")?; + assert!(curve.validate().is_ok()); + Ok(()) } #[test]