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 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}