mirror of
https://github.com/RGBCube/superfreq
synced 2025-07-27 17:07:44 +00:00
docs: mention battery management; update sample config
This commit is contained in:
parent
09a38dd136
commit
099e5c4ba6
4 changed files with 73 additions and 32 deletions
28
README.md
28
README.md
|
@ -111,6 +111,26 @@ sudo superfreq set-min-freq 1200 --core-id 0
|
|||
sudo superfreq set-max-freq 2800 --core-id 1
|
||||
```
|
||||
|
||||
### Battery Management
|
||||
|
||||
```bash
|
||||
# Set battery charging thresholds to extend battery lifespan
|
||||
sudo superfreq set-battery-thresholds 40 80 # Start charging at 40%, stop at 80%
|
||||
```
|
||||
|
||||
Battery charging thresholds help extend battery longevity by preventing constant
|
||||
charging to 100%. Different laptop vendors implement this feature differently,
|
||||
but Superfreq attempts to support multiple vendor implementations including:
|
||||
|
||||
- Lenovo ThinkPad/IdeaPad (Standard implementation)
|
||||
- ASUS laptops
|
||||
- Huawei laptops
|
||||
- Other devices using the standard Linux power_supply API
|
||||
|
||||
Note that battery management is sensitive, and that your mileage may vary.
|
||||
Please open an issue if your vendor is not supported, but patches would help
|
||||
more than issue reports, as supporting hardware _needs_ hardware.
|
||||
|
||||
## Configuration
|
||||
|
||||
Superfreq uses TOML configuration files. Default locations:
|
||||
|
@ -139,6 +159,8 @@ platform_profile = "performance"
|
|||
# Min/max frequency in MHz (optional)
|
||||
min_freq_mhz = 800
|
||||
max_freq_mhz = 3500
|
||||
# Optional: Profile-specific battery charge thresholds (overrides global setting)
|
||||
# battery_charge_thresholds = [40, 80] # Start at 40%, stop at 80%
|
||||
|
||||
# Settings for when on battery power
|
||||
[battery]
|
||||
|
@ -149,6 +171,12 @@ epb = "balance_power"
|
|||
platform_profile = "low-power"
|
||||
min_freq_mhz = 800
|
||||
max_freq_mhz = 2500
|
||||
# Optional: Profile-specific battery charge thresholds (overrides global setting)
|
||||
# battery_charge_thresholds = [60, 80] # Start at 60%, stop at 80% (more conservative)
|
||||
|
||||
# Global battery charging thresholds (applied to both profiles unless overridden)
|
||||
# Start charging at 40%, stop at 80% - extends battery lifespan
|
||||
battery_charge_thresholds = [40, 80]
|
||||
|
||||
# Daemon configuration
|
||||
[daemon]
|
||||
|
|
31
src/cpu.rs
31
src/cpu.rs
|
@ -2,7 +2,11 @@ use crate::core::{GovernorOverrideMode, TurboSetting};
|
|||
use crate::util::error::ControlError;
|
||||
use core::str;
|
||||
use log::debug;
|
||||
use std::{fs, io, path::{Path, PathBuf}, string::ToString};
|
||||
use std::{
|
||||
fs, io,
|
||||
path::{Path, PathBuf},
|
||||
string::ToString,
|
||||
};
|
||||
|
||||
pub type Result<T, E = ControlError> = std::result::Result<T, E>;
|
||||
|
||||
|
@ -399,7 +403,7 @@ pub fn set_battery_charge_thresholds(start_threshold: u8, stop_threshold: u8) ->
|
|||
let power_supply_path = Path::new("/sys/class/power_supply");
|
||||
if !power_supply_path.exists() {
|
||||
return Err(ControlError::NotSupported(
|
||||
"Power supply path not found, battery threshold control not supported".to_string()
|
||||
"Power supply path not found, battery threshold control not supported".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -447,7 +451,7 @@ pub fn set_battery_charge_thresholds(start_threshold: u8, stop_threshold: u8) ->
|
|||
|
||||
if supported_batteries.is_empty() {
|
||||
return Err(ControlError::NotSupported(
|
||||
"No batteries with charge threshold control support found".to_string()
|
||||
"No batteries with charge threshold control support found".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -462,16 +466,20 @@ pub fn set_battery_charge_thresholds(start_threshold: u8, stop_threshold: u8) ->
|
|||
// Attempt to set both thresholds
|
||||
match (
|
||||
write_sysfs_value(&start_path, &start_threshold.to_string()),
|
||||
write_sysfs_value(&stop_path, &stop_threshold.to_string())
|
||||
write_sysfs_value(&stop_path, &stop_threshold.to_string()),
|
||||
) {
|
||||
(Ok(_), Ok(_)) => {
|
||||
debug!("Set {}-{}% charge thresholds for {} battery '{}'",
|
||||
start_threshold, stop_threshold, battery.pattern.description, battery.name);
|
||||
debug!(
|
||||
"Set {}-{}% charge thresholds for {} battery '{}'",
|
||||
start_threshold, stop_threshold, battery.pattern.description, battery.name
|
||||
);
|
||||
success_count += 1;
|
||||
},
|
||||
}
|
||||
(start_result, stop_result) => {
|
||||
let mut error_msg = format!("Failed to set thresholds for {} battery '{}'",
|
||||
battery.pattern.description, battery.name);
|
||||
let mut error_msg = format!(
|
||||
"Failed to set thresholds for {} battery '{}'",
|
||||
battery.pattern.description, battery.name
|
||||
);
|
||||
|
||||
if let Err(e) = start_result {
|
||||
error_msg.push_str(&format!(": start threshold error: {}", e));
|
||||
|
@ -488,7 +496,10 @@ pub fn set_battery_charge_thresholds(start_threshold: u8, stop_threshold: u8) ->
|
|||
if success_count > 0 {
|
||||
// As long as we successfully set thresholds on at least one battery, consider it a success
|
||||
if !errors.is_empty() {
|
||||
debug!("Partial success setting battery thresholds: {}", errors.join("; "));
|
||||
debug!(
|
||||
"Partial success setting battery thresholds: {}",
|
||||
errors.join("; ")
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
} else {
|
||||
|
|
|
@ -216,7 +216,9 @@ fn apply_battery_charge_thresholds(
|
|||
} else {
|
||||
// For permission errors, provide more helpful message
|
||||
if matches!(e, ControlError::PermissionDenied(_)) {
|
||||
debug!("Permission denied setting battery thresholds - requires root privileges");
|
||||
debug!(
|
||||
"Permission denied setting battery thresholds - requires root privileges"
|
||||
);
|
||||
}
|
||||
Err(EngineError::ControlError(e))
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue