thinkpad_backlight_api/
lib.rs1use std::io::{Read, Write};
2
3const BRIGHTNESS_PATH: &str = "/sys/class/leds/tpacpi::kbd_backlight/brightness";
4
5#[derive(Clone, Debug)]
6pub enum Error {
7 PermissionDenied,
8 FileNotFound(String),
9 IoError(String),
10 InvalidLevel(String),
11}
12
13#[derive(Clone, Debug)]
14pub enum LightLevel {
15 Off = 0,
16 Medium = 1,
17 Full = 2,
18}
19
20impl LightLevel {
21 pub fn from_u8(level: u8) -> Result<Self, Error> {
22 match level {
23 0 => Ok(Self::Off),
24 1 => Ok(Self::Medium),
25 2 => Ok(Self::Full),
26 _ => Err(Error::InvalidLevel(format!(
27 "Unexpected level: {}",
28 level
29 ))),
30 }
31 }
32
33 pub fn as_u8(self) -> u8 {
34 self as u8
35 }
36}
37
38pub struct KeyboardBacklight;
39
40impl KeyboardBacklight {
41 fn ensure_root() -> Result<(), Error> {
42 if unsafe { libc::getuid() } != 0 {
43 return Err(Error::PermissionDenied);
44 }
45 Ok(())
46 }
47
48 pub fn set(level: LightLevel) -> Result<(), Error> {
49 Self::ensure_root()?;
50
51 let mut file = std::fs::OpenOptions::new()
52 .write(true)
53 .open(BRIGHTNESS_PATH)
54 .map_err(|e| Error::FileNotFound(format!("Cannot open file: {}", e)))?;
55
56 file.write_all(level.as_u8().to_string().as_bytes())
57 .map_err(|e| Error::IoError(format!("Failed to set brightness level: {}", e)))?;
58
59 Ok(())
60 }
61
62 pub fn get() -> Result<LightLevel, Error> {
63 Self::ensure_root()?;
64
65 let mut file = std::fs::OpenOptions::new()
66 .read(true)
67 .open(BRIGHTNESS_PATH)
68 .map_err(|e| Error::FileNotFound(format!("Cannot open file: {}", e)))?;
69
70 let mut content = String::new();
71 file.read_to_string(&mut content)
72 .map_err(|e| Error::IoError(format!("Failed to get brightness level: {}", e)))?;
73
74 let level: u8 = content
75 .trim()
76 .parse()
77 .map_err(|_| Error::InvalidLevel(format!("Invalid brightness value: {}", content)))?;
78
79 LightLevel::from_u8(level)
80 }
81}