framework_tool_tui/
framework.rs1use std::sync::Arc;
2
3use color_eyre::eyre::Report;
4use framework_lib::chromium_ec::CrosEc;
5use framework_lib::chromium_ec::CrosEcDriver;
6use framework_lib::chromium_ec::EcError;
7use framework_lib::smbios;
8
9use crate::framework::fingerprint::led_brightness_percentage_to_level;
10use crate::framework::fingerprint::Fingerprint;
11use crate::framework::fingerprint::FpLedBrightnessCapability;
12use crate::framework::info::FrameworkInfo;
13
14pub mod fingerprint;
15pub mod info;
16
17const EC_MEMMAP_FAN: u16 = 0x10; const EC_FAN_SPEED_ENTRIES: usize = 4;
20const EC_FAN_SPEED_NOT_PRESENT: u16 = 0xFFFF;
22
23pub struct Framework {
24 ec: CrosEc,
25 fingerprint: Arc<Fingerprint>,
26}
27
28#[derive(Debug)]
29pub struct EcErrorWrapper(pub EcError);
30
31impl std::fmt::Display for EcErrorWrapper {
32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33 write!(f, "{:?}", self.0)
34 }
35}
36
37impl std::error::Error for EcErrorWrapper {}
38
39impl Framework {
40 pub fn new(ec: CrosEc, fingerprint: Arc<Fingerprint>) -> Self {
41 Framework { ec, fingerprint }
42 }
43
44 pub fn set_max_charge_limit(&self, value: u8) -> color_eyre::Result<()> {
45 self.ec
46 .set_charge_limit(0, value)
47 .map_err(|error| Report::from(EcErrorWrapper(error)))
48 }
49
50 pub fn set_fp_brightness(&self, percentage: u8) -> color_eyre::Result<()> {
51 let result = match self.fingerprint.led_brightness_capability {
52 FpLedBrightnessCapability::Level => {
53 let level = led_brightness_percentage_to_level(percentage);
54
55 self.ec.set_fp_led_level(level)
56 }
57 FpLedBrightnessCapability::Percentage => self.ec.set_fp_led_percentage(percentage),
58 };
59
60 result.map_err(|error| Report::from(EcErrorWrapper(error)))
61 }
62
63 pub fn set_kb_brightness(&self, percentage: u8) {
65 self.ec.set_keyboard_backlight(percentage);
66 }
67
68 pub fn get_info(&mut self) -> FrameworkInfo {
69 let power = framework_lib::power::power_info(&self.ec);
70 let charge_limit = self.ec.get_charge_limit().ok();
71 let privacy = self.ec.get_privacy_info().ok();
72 let fp_brightness = self.ec.get_fp_led_level().ok();
73 let kb_brightness = self.ec.get_keyboard_backlight().ok();
74 let smbios = smbios::get_smbios();
75 let pd_ports = framework_lib::power::get_pd_info(&self.ec, 4)
76 .into_iter()
77 .map(Result::ok)
78 .collect();
79 let fan_rpm = self.get_fan_rpm().ok();
80 let platform = smbios::get_platform();
81
82 FrameworkInfo::new(
83 &power,
84 &charge_limit,
85 &privacy,
86 &fp_brightness,
87 kb_brightness,
88 &smbios,
89 pd_ports,
90 fan_rpm,
91 platform,
92 )
93 }
94
95 fn get_fan_rpm(&self) -> color_eyre::Result<Vec<u16>> {
96 let fans = self
97 .ec
98 .read_memory(EC_MEMMAP_FAN, 0x08)
99 .ok_or(Report::msg("Couldn't read fan info"))?;
100 let mut rpms = Vec::new();
101
102 for i in 0..EC_FAN_SPEED_ENTRIES {
103 let rpm = u16::from_le_bytes([fans[i * 2], fans[1 + i * 2]]);
104
105 if rpm == EC_FAN_SPEED_NOT_PRESENT {
106 continue;
107 }
108
109 rpms.push(rpm);
110 }
111
112 Ok(rpms)
113 }
114}