oxy_linux_pwm/
sysfs.rs

1use std::fs::File;
2use std::io::{Read, Write};
3use std::fmt;
4use std::{io, path::Path};
5use core::fmt::Display;
6
7pub enum Polarity {
8    Normal,
9    Inverted,
10}
11
12impl Display for Polarity {
13    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
14        match self {
15            Polarity::Normal => write!(f, "normal"),
16            Polarity::Inverted => write!(f, "inverted"),
17        }
18    }
19    
20}
21
22pub fn reset_all() {
23    // unexport all pwm channels
24    let chip_count = get_chip_count().unwrap();
25    for chip in 0..chip_count {
26        let channel_count = get_channel_count(chip).unwrap();
27        for channel in 0..channel_count {
28            let _ = export(chip, channel);
29            let _ = enable(chip, channel);
30            let _ = set_period(chip, channel, 10000);
31            let _ = set_duty_cycle(chip, channel, 0);
32            let _ = set_polarity(chip, channel, Polarity::Normal);
33            let _ = disable(chip, channel);
34            let _ = unexport(chip, channel);
35        }
36    }
37}
38
39pub fn export(pwm_chip: u8, pwm_channel: u8) -> Result<(), io::Error> {
40    let path = format!("/sys/class/pwm/pwmchip{}", pwm_chip);
41    let path = Path::new(&path);
42    if is_exported(pwm_chip, pwm_channel)? {
43        return Err(io::Error::new(io::ErrorKind::AlreadyExists, "PWM channel is already exported"))
44    }
45    if path.exists() {
46        File::create(path.join("export"))?.write_fmt(format_args!("{}", pwm_channel))?;
47        return Ok(());
48    }
49    Err(io::Error::new(io::ErrorKind::NotFound, "PWM chip not found"))
50}
51
52pub fn unexport(pwm_chip: u8, pwm_channel: u8) -> Result<(), io::Error> {
53    let path = format!("/sys/class/pwm/pwmchip{}", pwm_chip);
54    let path = Path::new(&path);
55    if !is_exported(pwm_chip, pwm_channel)? {
56        return Err(io::Error::new(io::ErrorKind::AlreadyExists, "PWM channel is not exported yet"))
57    }
58    if path.exists() {
59        File::create(path.join("unexport"))?.write_fmt(format_args!("{}", pwm_channel))?;
60        return Ok(());
61    }
62    Err(io::Error::new(io::ErrorKind::NotFound, "PWM chip not found"))
63}
64
65pub fn is_exported(pwm_chip: u8, pwm_channel: u8) -> Result<bool, io::Error> {
66    let path = format!("/sys/class/pwm/pwmchip{}/pwm{}", pwm_chip, pwm_channel);
67    let path = Path::new(&path);
68    Ok(path.exists())
69}
70
71pub fn enable(pwm_chip: u8, pwm_channel: u8) -> Result<(), io::Error> {
72    let path = format!("/sys/class/pwm/pwmchip{}/pwm{}", pwm_chip, pwm_channel);
73    let path = Path::new(&path);
74    if is_enabled(pwm_chip, pwm_channel)? {
75        return Err(io::Error::new(io::ErrorKind::AlreadyExists, format!("PWM channel {} on chip {} is already enabled", pwm_channel, pwm_chip)))
76    }
77    if path.exists() {
78        File::create(path.join("enable"))?.write_fmt(format_args!("{}", 1))?;
79        return Ok(());
80    }
81    Err(io::Error::new(io::ErrorKind::NotFound, "PWM channel not found"))
82}
83
84pub fn disable(pwm_chip: u8, pwm_channel: u8) -> Result<(), io::Error> {
85    let path = format!("/sys/class/pwm/pwmchip{}/pwm{}", pwm_chip, pwm_channel);
86    let path = Path::new(&path);
87    if !is_enabled(pwm_chip, pwm_channel)? {
88        return Err(io::Error::new(io::ErrorKind::AlreadyExists, "PWM channel is not enabled yet"))
89    }
90    if path.exists() {
91        File::create(path.join("enable"))?.write_fmt(format_args!("{}", 0))?;
92        return Ok(());
93    }
94    Err(io::Error::new(io::ErrorKind::NotFound, "PWM channel not found"))
95}
96
97pub fn is_enabled(pwm_chip: u8, pwm_channel: u8) -> Result<bool, io::Error> {
98    let path = format!("/sys/class/pwm/pwmchip{}/pwm{}/enable", pwm_chip, pwm_channel);
99    let path = Path::new(&path);
100    if path.exists() {
101        let mut file = File::open(path)?;
102        let mut contents = String::new();
103        file.read_to_string(&mut contents)?;
104        return Ok(contents.trim() == "1");
105    }
106    Err(io::Error::new(io::ErrorKind::NotFound, "PWM channel not found"))
107}
108
109pub fn set_duty_cycle(pwm_chip: u8, pwm_channel: u8, duty_cycle: u64) -> Result<(), io::Error> {
110    let path = format!("/sys/class/pwm/pwmchip{}/pwm{}", pwm_chip, pwm_channel);
111    let path = Path::new(&path);
112    if path.exists() {
113        File::create(path.join("duty_cycle"))?.write_fmt(format_args!("{}", duty_cycle))?;
114        return Ok(());
115    }
116    Err(io::Error::new(io::ErrorKind::NotFound, "PWM channel not found"))
117}
118
119pub fn get_duty_cycle(pwm_chip: u8, pwm_channel: u8) -> Result<u64, io::Error> {
120    let path = format!("/sys/class/pwm/pwmchip{}/pwm{}/duty_cycle", pwm_chip, pwm_channel);
121    let path = Path::new(&path);
122    if path.exists() {
123        let mut file = File::open(path)?;
124        let mut contents = String::new();
125        file.read_to_string(&mut contents)?;
126        return Ok(contents.trim().parse().unwrap());
127    }
128    Err(io::Error::new(io::ErrorKind::NotFound, "PWM channel not found"))
129}
130
131pub fn set_period(pwm_chip: u8, pwm_channel: u8, period: u64) -> Result<(), io::Error> {
132    let path = format!("/sys/class/pwm/pwmchip{}/pwm{}", pwm_chip, pwm_channel);
133    let path = Path::new(&path);
134    if path.exists() {
135        File::create(path.join("period"))?.write_fmt(format_args!("{}", period))?;
136        return Ok(());
137    }
138    Err(io::Error::new(io::ErrorKind::NotFound, "PWM channel not found"))
139}
140
141pub fn get_period(pwm_chip: u8, pwm_channel: u8) -> Result<u64, io::Error> {
142    let path = format!("/sys/class/pwm/pwmchip{}/pwm{}/period", pwm_chip, pwm_channel);
143    let path = Path::new(&path);
144    if path.exists() {
145        let mut file = File::open(path)?;
146        let mut contents = String::new();
147        file.read_to_string(&mut contents)?;
148        return Ok(contents.trim().parse().unwrap());
149    }
150    Err(io::Error::new(io::ErrorKind::NotFound, "PWM channel not found"))
151}
152
153pub fn set_polarity(pwm_chip: u8, pwm_channel: u8, polarity: Polarity) -> Result<(), io::Error> {
154    let path = format!("/sys/class/pwm/pwmchip{}/pwm{}", pwm_chip, pwm_channel);
155    let path = Path::new(&path);
156    if path.exists() {
157        File::create(path.join("polarity"))?.write_fmt(format_args!("{}", polarity))?;
158        return Ok(());
159    }
160    Err(io::Error::new(io::ErrorKind::NotFound, "PWM channel not found"))
161}
162
163pub fn get_polarity(pwm_chip: u8, pwm_channel: u8) -> Result<Polarity, io::Error> {
164    let path = format!("/sys/class/pwm/pwmchip{}/pwm{}/polarity", pwm_chip, pwm_channel);
165    let path = Path::new(&path);
166    if path.exists() {
167        let mut file = File::open(path)?;
168        let mut contents = String::new();
169        file.read_to_string(&mut contents)?;
170        return match contents.trim() {
171            "normal" => Ok(Polarity::Normal),
172            "inverted" => Ok(Polarity::Inverted),
173            _ => Err(io::Error::new(io::ErrorKind::InvalidData, "Invalid polarity value")),
174        }
175    }
176    Err(io::Error::new(io::ErrorKind::NotFound, "PWM channel not found"))
177}
178
179pub fn get_chip_count() -> Result<u8, io::Error> {
180    let path = Path::new("/sys/class/pwm");
181    if path.exists() {
182        let mut count = 0;
183        for entry in path.read_dir()? {
184            let entry = entry?;
185            let path = entry.path();
186            if path.is_dir() {
187                count += 1;
188            }
189        }
190        return Ok(count);
191    }
192    Err(io::Error::new(io::ErrorKind::NotFound, "PWM chip not found"))
193}
194
195pub fn get_channel_count(pwm_chip: u8) -> Result<u8, io::Error> {
196    let path = format!("/sys/class/pwm/pwmchip{}", pwm_chip);
197    let path = Path::new(&path);
198    if path.exists() {
199        let buffer = &mut String::new();
200        File::open(path.join("npwm"))?.read_to_string(buffer)?;
201        let count = buffer.trim().parse().unwrap();
202        return Ok(count);
203    }
204    Err(io::Error::new(io::ErrorKind::NotFound, "PWM chip not found"))
205}