auto_cpufreq/battery/
mod.rs1use anyhow::Result;
3use std::fs;
4use std::path::Path;
5use std::process::Command;
6
7pub mod asus;
8pub mod ideapad_acpi;
9pub mod ideapad_laptop;
10pub mod thinkpad;
11
12use crate::config::Config;
13
14const POWER_SUPPLY_DIR: &str = "/sys/class/power_supply/";
15
16#[derive(Debug, Clone, Copy, PartialEq)]
18pub enum LaptopModule {
19 IdeapadAcpi,
20 IdeapadLaptop,
21 ThinkpadAcpi,
22 AsusWmi,
23 None,
24}
25
26impl LaptopModule {
27 pub fn detect() -> Self {
28 if is_module_loaded("ideapad_acpi") {
29 Self::IdeapadAcpi
30 } else if is_module_loaded("ideapad_laptop") {
31 Self::IdeapadLaptop
32 } else if is_module_loaded("thinkpad_acpi") {
33 Self::ThinkpadAcpi
34 } else if is_module_loaded("asus_wmi") {
35 Self::AsusWmi
36 } else {
37 Self::None
38 }
39 }
40
41 pub fn name(&self) -> &str {
42 match self {
43 Self::IdeapadAcpi => "ideapad_acpi",
44 Self::IdeapadLaptop => "ideapad_laptop",
45 Self::ThinkpadAcpi => "thinkpad_acpi",
46 Self::AsusWmi => "asus_wmi",
47 Self::None => "none",
48 }
49 }
50}
51
52fn is_module_loaded(module: &str) -> bool {
53 Command::new("lsmod")
54 .output()
55 .ok()
56 .and_then(|output| String::from_utf8(output.stdout).ok())
57 .map(|stdout| stdout.contains(module))
58 .unwrap_or(false)
59}
60
61pub fn get_batteries() -> Result<Vec<String>> {
63 let power_dir = Path::new(POWER_SUPPLY_DIR);
64
65 if !power_dir.exists() {
66 return Ok(Vec::new());
67 }
68
69 let mut batteries = Vec::new();
70
71 for entry in fs::read_dir(power_dir)? {
72 let entry = entry?;
73 let name = entry.file_name();
74 let name_str = name.to_string_lossy();
75
76 if name_str.starts_with("BAT") {
77 batteries.push(name_str.to_string());
78 }
79 }
80
81 batteries.sort();
82 Ok(batteries)
83}
84
85pub trait BatteryManager {
87 fn setup(&self, config: &Config) -> Result<()>;
88 fn print_thresholds(&self) -> Result<()>;
89}
90
91pub fn battery_setup(config: &Config) -> Result<()> {
93 let module = LaptopModule::detect();
94
95 match module {
96 LaptopModule::IdeapadAcpi => ideapad_acpi::IdeapadAcpiManager.setup(config),
97 LaptopModule::IdeapadLaptop => ideapad_laptop::IdeapadLaptopManager.setup(config),
98 LaptopModule::ThinkpadAcpi => thinkpad::ThinkpadManager.setup(config),
99 LaptopModule::AsusWmi => asus::AsusManager.setup(config),
100 LaptopModule::None => {
101 Ok(()) }
103 }
104}
105
106pub fn battery_get_thresholds() -> Result<()> {
108 let module = LaptopModule::detect();
109
110 match module {
111 LaptopModule::IdeapadAcpi => ideapad_acpi::IdeapadAcpiManager.print_thresholds(),
112 LaptopModule::IdeapadLaptop => ideapad_laptop::IdeapadLaptopManager.print_thresholds(),
113 LaptopModule::ThinkpadAcpi => thinkpad::ThinkpadManager.print_thresholds(),
114 LaptopModule::AsusWmi => asus::AsusManager.print_thresholds(),
115 LaptopModule::None => {
116 Ok(()) }
118 }
119}