feat(commands): add cooling command implementation and status integration

- New Features
  - Implement fan_mode control for Ideapad laptops
  - Implement thermal policy control for ASUS laptops via WMI
  - Provide cooling command supporting performance, balanced, and quiet profiles

- Enhancements
  - Display current cooling profile in `lapctl status` output

- Bug Fixes
  - None
This commit is contained in:
sankalp committed 2026-03-12 00:01:48 +05:45
1 parent bc31ce6506
commit 0327885bef
3 files changed
+109

No files matched your search

+69
View File
@@ -0,0 +1,69 @@
use crate::cli::CoolingCommands;
use crate::utils::system::assert_root;
use log::{debug, info};
use std::fs;
use std::path::Path;
fn set_ideapad_fan_mode(mode: &str) -> bool {
let mut success = false;
if let Ok(entries) = fs::read_dir("/sys/bus/platform/drivers/ideapad_acpi") {
for entry in entries.flatten() {
let path = entry.path().join("fan_mode");
if path.exists() {
match fs::write(&path, mode) {
Ok(_) => {
info!("Set Ideapad fan_mode to {}", mode);
success = true;
}
Err(e) => debug!("Failed to write to {}: {}", path.display(), e),
}
}
}
}
success
}
fn set_asus_throttle_policy(mode: &str) -> bool {
let mut success = false;
let path = Path::new("/sys/devices/platform/asus-nb-wmi/throttle_thermal_policy");
if path.exists() {
match fs::write(path, mode) {
Ok(_) => {
info!("Set ASUS WMI thermal policy to {}", mode);
success = true;
}
Err(e) => debug!("Failed to write to {}: {}", path.display(), e),
}
}
success
}
pub fn execute(command: &CoolingCommands) {
assert_root();
let (ideapad_mode, asus_mode, desc) = match command {
CoolingCommands::Performance => ("1", "1", "Performance"),
CoolingCommands::Balanced => ("0", "0", "Balanced"),
CoolingCommands::Quiet => ("2", "2", "Quiet"),
};
println!("Setting thermal/cooling profile to {}", desc);
let mut applied = false;
if set_ideapad_fan_mode(ideapad_mode) {
applied = true;
println!("Ideapad fan mode applied.");
}
if set_asus_throttle_policy(asus_mode) {
applied = true;
println!("ASUS thermal policy applied.");
}
if applied {
println!("Operation completed successfully.");
} else {
println!("Hardware does not respond to standard ACPI thermal overrides (Ideapad/ASUS).");
}
}
+1
View File
@@ -1,4 +1,5 @@
pub mod battery;
pub mod cooling;
pub mod gpu;
pub mod power;
pub mod status;
+39
View File
@@ -1,5 +1,6 @@
use crate::hardware::gpu;
use std::fs;
use std::path::Path;
pub fn execute() {
println!("--- lapctl status ---");
@@ -54,4 +55,42 @@ pub fn execute() {
} else {
println!("Power Profile: Unknown");
}
// Cooling / Thermal Status
let mut thermal_found = false;
if let Ok(ideapad_entries) = fs::read_dir("/sys/bus/platform/drivers/ideapad_acpi") {
for ideapad_entry in ideapad_entries.flatten() {
let fan_path = ideapad_entry.path().join("fan_mode");
if fan_path.exists() {
if let Ok(mode) = fs::read_to_string(&fan_path) {
thermal_found = true;
let desc = match mode.trim() {
"1" => "Performance",
"0" => "Balanced",
"2" => "Quiet / Battery Saving",
_ => mode.trim()
};
println!("Cooling Profile: {} (Ideapad)", desc);
}
}
}
}
let asus_path = Path::new("/sys/devices/platform/asus-nb-wmi/throttle_thermal_policy");
if asus_path.exists() {
if let Ok(mode) = fs::read_to_string(asus_path) {
thermal_found = true;
let desc = match mode.trim() {
"1" => "Performance",
"0" => "Balanced",
"2" => "Quiet / Battery Saving",
_ => mode.trim()
};
println!("Cooling Profile: {} (ASUS)", desc);
}
}
if !thermal_found {
println!("Cooling Profile: Unknown / Firmware managed");
}
}