Skip to content

Commit

Permalink
Config updates, including breaking change
Browse files Browse the repository at this point in the history
- Add custom register config name (breaking change, since it is required)

- Add enabled state to custom register configs (true by default for compatibility with older configs)

- Add better config validation (this may render some previously "valid" configs invalid, even when adding custom register config names)

- Some code doc updates
  • Loading branch information
Sparronator9999 committed Dec 18, 2024
1 parent e63e3a3 commit 38e0b97
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 59 deletions.
10 changes: 5 additions & 5 deletions YAMDCC.Config/ChargeLimitConf.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,30 +19,30 @@
namespace YAMDCC.Config
{
/// <summary>
/// Represents a charge threshold (a.k.a charge limit) config for a laptop.
/// Represents a charge limit config for a laptop.
/// </summary>
public sealed class ChargeLimitConf
{
/// <summary>
/// The register that controls the charge threshold.
/// The register that controls the charge limit.
/// </summary>
[XmlElement]
public byte Reg { get; set; }

/// <summary>
/// The value that corresponds to 0% battery threshold.
/// The value that corresponds to 0% charge limit (i.e. disabled).
/// </summary>
[XmlElement]
public byte MinVal { get; set; }

/// <summary>
/// The value that corresponds to 100% battery threshold.
/// The value that corresponds to 100% charge limit.
/// </summary>
[XmlElement]
public byte MaxVal { get; set; }

/// <summary>
/// The currently set Charge Threshold value.
/// The currently set charge limit value.
/// </summary>
[XmlElement]
public byte CurVal { get; set; }
Expand Down
2 changes: 1 addition & 1 deletion YAMDCC.Config/FanConf.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace YAMDCC.Config
public sealed class FanConf
{
/// <summary>
/// The display name of the fan in the curve editor.
/// The display name of the fan in the config editor.
/// </summary>
[XmlElement]
public string Name { get; set; }
Expand Down
20 changes: 16 additions & 4 deletions YAMDCC.Config/RegConf.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,28 @@
namespace YAMDCC.Config
{
/// <summary>
/// Represents miscellaneous register configurations for the target
/// system. May be required to enable fan control via YAMDCC.
/// Represents miscellaneous EC register configurations for the target
/// computer. May be required to enable fan control via YAMDCC.
/// </summary>
/// <remarks>
/// All RegConfigs defined here will be applied on service start.
/// All RegConfs defined here will be applied on service start (unless disabled).
/// </remarks>
public sealed class RegConf
{
/// <summary>
/// A description of what this config does.
/// Should this <see cref="RegConf"/> be applied?
/// </summary>
[XmlElement]
public bool Enabled { get; set; } = true;

/// <summary>
/// A short name for this EC register config.
/// </summary>
[XmlElement]
public string Name { get; set; }

/// <summary>
/// A longer description of what this config does.
/// </summary>
[XmlElement]
public string Desc { get; set; }
Expand Down
178 changes: 129 additions & 49 deletions YAMDCC.Config/YAMDCC_Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,17 +112,18 @@ public sealed class YAMDCC_Config
/// A list of registers to write when applying a fan config.
/// </summary>
/// <remarks>
/// May be <c>null</c>, but if not <c>null</c>, must have
/// at least one <see cref="RegConf"/>.
/// May be <c>null</c> or empty if not needed.
/// </remarks>
[XmlArray]
public RegConf[] RegConfs { get; set; }

/// <summary>
/// Parses a YAMDCC config XML and returns an
/// Parses a YAMDCC config XML and returns a
/// <see cref="YAMDCC_Config"/> object.
/// </summary>
/// <param name="xmlFile">The path to an XML config file.</param>
/// <param name="xmlFile">
/// The path to an XML config file.
/// </param>
/// <exception cref="InvalidConfigException"/>
/// <exception cref="ArgumentNullException"/>
/// <exception cref="FileNotFoundException"/>
Expand All @@ -140,7 +141,9 @@ public static YAMDCC_Config Load(string xmlFile)
/// <summary>
/// Saves a YAMDCC config to the specified location.
/// </summary>
/// <param name="xmlFile">The XML file to write to.</param>
/// <param name="xmlFile">
/// The XML file to write to.
/// </param>
/// <exception cref="ArgumentNullException"/>
/// <exception cref="InvalidOperationException"/>
public void Save(string xmlFile)
Expand All @@ -164,6 +167,7 @@ public void Save(string xmlFile)
/// </summary>
/// <remarks>
/// This does NOT guarantee the loaded config is valid!
/// (e.g. register values are not checked)
/// </remarks>
/// <returns>
/// <c>true</c> if the config is valid, otherwise <c>false</c>.
Expand All @@ -188,76 +192,152 @@ private bool IsValid()

// 1. Check if FanConfigs is not null
// 2. Check if there's at least 1 FanConfig
if (FanConfs?.Length >= 1)
if (FanConfs?.Length < 1)
{
for (int i = 0; i < FanConfs.Length; i++)
return false;
}

for (int i = 0; i < FanConfs.Length; i++)
{
FanConf cfg = FanConfs[i];

if (string.IsNullOrEmpty(cfg.Name))
{
FanConf cfg = FanConfs[i];
return false;
}

if (string.IsNullOrEmpty(cfg.Name))
{
return false;
}
// YAMDCC doesn't handle MinSpeed lower than MaxSpeed,
// so return false if MinSpeed is lower or equal to MaxSpeed:
if (cfg.MinSpeed >= cfg.MaxSpeed)
{
return false;
}

// the selected fan curve shouldn't be higher than
// the number of fan curves in the config.
if (cfg.CurveSel >= FanConfs[i].FanCurveConfs.Length ||
cfg.CurveSel < 0)
{
// if the fan profile selection is out of range,
// silently set it to 0 (the first fan curve)
// which should always exist:
cfg.CurveSel = 0;
}
// the selected fan curve shouldn't be higher than
// the number of fan curves in the config.
if (cfg.CurveSel >= FanConfs[i].FanCurveConfs.Length ||
cfg.CurveSel < 0)
{
// if the fan profile selection is out of range,
// silently set it to 0 (the first fan curve)
// which should always exist:
cfg.CurveSel = 0;
}

if (cfg.UpThresholdRegs?.Length >= 1 &&
cfg.DownThresholdRegs?.Length >= 1 &&
cfg.FanCurveRegs?.Length >= 2 &&
cfg.FanCurveConfs?.Length >= 1)
{
for (int j = 0; j < cfg.FanCurveConfs.Length; j++)
{
FanCurveConf curveCfg = cfg.FanCurveConfs[j];
if (string.IsNullOrEmpty(curveCfg.Name) ||
string.IsNullOrEmpty(curveCfg.Desc) ||
// there should be exactly one temperature threshold
// per fan curve register; if there isn't, return false
curveCfg.TempThresholds?.Length != cfg.FanCurveRegs.Length)
{
return false;
}
}
}
else
// make sure that:
// - there is at least one each of up threshold, down threshold,
// and fan curve registers
// - there are the same amount of up threshold registers
// as down threshold registers
// - there is one more fan curve register than up/down threshold registers
// - there is at least one fan profile to apply (first should be Default)
if (cfg.UpThresholdRegs?.Length < 1 ||
cfg.UpThresholdRegs?.Length != cfg.DownThresholdRegs?.Length ||
cfg.FanCurveRegs?.Length != cfg.UpThresholdRegs?.Length + 1 ||
cfg.FanCurveConfs?.Length < 1)
{
return false;
}

for (int j = 0; j < cfg.FanCurveConfs.Length; j++)
{
FanCurveConf curveCfg = cfg.FanCurveConfs[j];
if (string.IsNullOrEmpty(curveCfg.Name) ||
string.IsNullOrEmpty(curveCfg.Desc) ||
// there should be exactly one temperature threshold
// per fan curve register; if there isn't, return false
curveCfg.TempThresholds?.Length != cfg.FanCurveRegs.Length)
{
return false;
}
}
}
else

if (FullBlastConf is not null)
{
return false;
// full blast mask shouldn't be 0, as that would make it impossible
// to change the full blast register's value when full blast toggled on/off
if (FullBlastConf.Mask == 0)
{
return false;
}
}

// If the RegConfigs tag is defined in the XML,
// but has no elements, return false
if (RegConfs?.Length == 0)
if (ChargeLimitConf is not null)
{
return false;
// YAMDCC cannot handle a lower min value than max value,
// so return false if that's the case for this config
if (ChargeLimitConf.MinVal >= ChargeLimitConf.MaxVal)
{
return false;
}

// make sure charge limit to apply is within the config's
// defined bounds, but don't fail validation if it's not:
if (ChargeLimitConf.CurVal > ChargeLimitConf.MaxVal - ChargeLimitConf.MinVal)
{
ChargeLimitConf.CurVal = ChargeLimitConf.MaxVal;
}
else if (ChargeLimitConf.CurVal < 0)
{
ChargeLimitConf.CurVal = ChargeLimitConf.MinVal;
}
}

if (PerfModeConf is not null)
{
if (PerfModeConf.PerfModes?.Length < 1)
{
return false;
}

// the selected performance mode shouldn't be higher than
// the number of performance modes in the config
if (PerfModeConf.ModeSel >= PerfModeConf.PerfModes.Length ||
PerfModeConf.ModeSel < 0)
{
return false;
// same as fan profile selection, set the performance
// mode to the first available performance mode:
PerfModeConf.ModeSel = 0;
}

for (int i = 0; i < PerfModeConf.PerfModes.Length; i++)
{
PerfMode perfMode = PerfModeConf.PerfModes[i];

if (string.IsNullOrEmpty(perfMode.Name) ||
string.IsNullOrEmpty(perfMode.Desc))
{
return false;
}
}
}

if (KeySwapConf?.OnVal == KeySwapConf?.OffVal)
{
return false;
}

if (KeyLightConf?.MinVal >= KeyLightConf?.MaxVal)
{
return false;
}

if (RegConfs?.Length > 0)
{
for (int i = 0; i < RegConfs.Length; i++)
{
if (string.IsNullOrEmpty(RegConfs[i].Name) ||
string.IsNullOrEmpty(RegConfs[i].Desc))
{
return false;
}
}
}

// All other values are considered to be valid; return true
// All other values are considered to be valid; return true.
// Note that registers aren't checked and are (almost) always
// expected to be nonzero.
return true;
}
}
Expand Down

0 comments on commit 38e0b97

Please sign in to comment.