libgpiod/
line_settings.rs1use std::time::Duration;
6
7use super::{
8 Error, OperationType, Result, gpiod,
9 line::{Bias, Direction, Drive, Edge, EventClock, SettingKind, SettingVal, Value},
10};
11
12#[derive(Debug, Eq, PartialEq)]
23pub struct Settings {
24 pub(crate) settings: *mut gpiod::gpiod_line_settings,
25}
26
27unsafe impl Send for Settings {}
30
31impl Settings {
32 pub fn new() -> Result<Self> {
34 let settings = unsafe { gpiod::gpiod_line_settings_new() };
37
38 if settings.is_null() {
39 return Err(Error::OperationFailed(
40 OperationType::LineSettingsNew,
41 errno::errno(),
42 ));
43 }
44
45 Ok(Self { settings })
46 }
47
48 pub(crate) unsafe fn from_raw(settings: *mut gpiod::gpiod_line_settings) -> Self {
57 Self { settings }
58 }
59
60 pub fn reset(&mut self) {
62 unsafe { gpiod::gpiod_line_settings_reset(self.settings) }
64 }
65
66 pub fn try_clone(&self) -> Result<Self> {
68 let settings = unsafe { gpiod::gpiod_line_settings_copy(self.settings) };
70 if settings.is_null() {
71 return Err(Error::OperationFailed(
72 OperationType::LineSettingsCopy,
73 errno::errno(),
74 ));
75 }
76
77 Ok(Self { settings })
78 }
79
80 pub fn set_prop(&mut self, props: &[SettingVal]) -> Result<&mut Self> {
82 for property in props {
83 match property {
84 SettingVal::Direction(prop) => self.set_direction(*prop)?,
85 SettingVal::EdgeDetection(prop) => self.set_edge_detection(*prop)?,
86 SettingVal::Bias(prop) => self.set_bias(*prop)?,
87 SettingVal::Drive(prop) => self.set_drive(*prop)?,
88 SettingVal::ActiveLow(prop) => self.set_active_low(*prop),
89 SettingVal::DebouncePeriod(prop) => self.set_debounce_period(*prop),
90 SettingVal::EventClock(prop) => self.set_event_clock(*prop)?,
91 SettingVal::OutputValue(prop) => self.set_output_value(*prop)?,
92 };
93 }
94
95 Ok(self)
96 }
97
98 pub fn prop(&self, property: SettingKind) -> Result<SettingVal> {
100 Ok(match property {
101 SettingKind::Direction => SettingVal::Direction(self.direction()?),
102 SettingKind::EdgeDetection => SettingVal::EdgeDetection(self.edge_detection()?),
103 SettingKind::Bias => SettingVal::Bias(self.bias()?),
104 SettingKind::Drive => SettingVal::Drive(self.drive()?),
105 SettingKind::ActiveLow => SettingVal::ActiveLow(self.active_low()),
106 SettingKind::DebouncePeriod => SettingVal::DebouncePeriod(self.debounce_period()?),
107 SettingKind::EventClock => SettingVal::EventClock(self.event_clock()?),
108 SettingKind::OutputValue => SettingVal::OutputValue(self.output_value()?),
109 })
110 }
111
112 pub fn set_direction(&mut self, direction: Direction) -> Result<&mut Self> {
114 let ret = unsafe {
116 gpiod::gpiod_line_settings_set_direction(self.settings, direction.gpiod_direction())
117 };
118
119 if ret == -1 {
120 Err(Error::OperationFailed(
121 OperationType::LineSettingsSetDirection,
122 errno::errno(),
123 ))
124 } else {
125 Ok(self)
126 }
127 }
128
129 pub fn direction(&self) -> Result<Direction> {
131 Direction::new(unsafe { gpiod::gpiod_line_settings_get_direction(self.settings) })
133 }
134
135 pub fn set_edge_detection(&mut self, edge: Option<Edge>) -> Result<&mut Self> {
137 let ret = unsafe {
139 gpiod::gpiod_line_settings_set_edge_detection(self.settings, Edge::gpiod_edge(edge))
140 };
141
142 if ret == -1 {
143 Err(Error::OperationFailed(
144 OperationType::LineSettingsSetEdgeDetection,
145 errno::errno(),
146 ))
147 } else {
148 Ok(self)
149 }
150 }
151
152 pub fn edge_detection(&self) -> Result<Option<Edge>> {
154 Edge::new(unsafe { gpiod::gpiod_line_settings_get_edge_detection(self.settings) })
156 }
157
158 pub fn set_bias(&mut self, bias: Option<Bias>) -> Result<&mut Self> {
160 let ret =
162 unsafe { gpiod::gpiod_line_settings_set_bias(self.settings, Bias::gpiod_bias(bias)) };
163
164 if ret == -1 {
165 Err(Error::OperationFailed(
166 OperationType::LineSettingsSetBias,
167 errno::errno(),
168 ))
169 } else {
170 Ok(self)
171 }
172 }
173
174 pub fn bias(&self) -> Result<Option<Bias>> {
176 Bias::new(unsafe { gpiod::gpiod_line_settings_get_bias(self.settings) })
178 }
179
180 pub fn set_drive(&mut self, drive: Drive) -> Result<&mut Self> {
182 let ret =
184 unsafe { gpiod::gpiod_line_settings_set_drive(self.settings, drive.gpiod_drive()) };
185
186 if ret == -1 {
187 Err(Error::OperationFailed(
188 OperationType::LineSettingsSetDrive,
189 errno::errno(),
190 ))
191 } else {
192 Ok(self)
193 }
194 }
195
196 pub fn drive(&self) -> Result<Drive> {
198 Drive::new(unsafe { gpiod::gpiod_line_settings_get_drive(self.settings) })
200 }
201
202 pub fn set_active_low(&mut self, active_low: bool) -> &mut Self {
204 unsafe {
206 gpiod::gpiod_line_settings_set_active_low(self.settings, active_low);
207 }
208 self
209 }
210
211 pub fn active_low(&self) -> bool {
213 unsafe { gpiod::gpiod_line_settings_get_active_low(self.settings) }
215 }
216
217 pub fn set_debounce_period(&mut self, period: Duration) -> &mut Self {
219 unsafe {
221 gpiod::gpiod_line_settings_set_debounce_period_us(
222 self.settings,
223 period.as_micros().try_into().unwrap(),
224 );
225 }
226
227 self
228 }
229
230 pub fn debounce_period(&self) -> Result<Duration> {
232 #[allow(clippy::unnecessary_cast)]
235 Ok(Duration::from_micros(unsafe {
237 gpiod::gpiod_line_settings_get_debounce_period_us(self.settings) as u64
238 }))
239 }
240
241 pub fn set_event_clock(&mut self, clock: EventClock) -> Result<&mut Self> {
243 let ret = unsafe {
245 gpiod::gpiod_line_settings_set_event_clock(self.settings, clock.gpiod_clock())
246 };
247
248 if ret == -1 {
249 Err(Error::OperationFailed(
250 OperationType::LineSettingsSetEventClock,
251 errno::errno(),
252 ))
253 } else {
254 Ok(self)
255 }
256 }
257
258 pub fn event_clock(&self) -> Result<EventClock> {
260 EventClock::new(unsafe { gpiod::gpiod_line_settings_get_event_clock(self.settings) })
262 }
263
264 pub fn set_output_value(&mut self, value: Value) -> Result<&mut Self> {
266 let ret =
268 unsafe { gpiod::gpiod_line_settings_set_output_value(self.settings, value.value()) };
269
270 if ret == -1 {
271 Err(Error::OperationFailed(
272 OperationType::LineSettingsSetOutputValue,
273 errno::errno(),
274 ))
275 } else {
276 Ok(self)
277 }
278 }
279
280 pub fn output_value(&self) -> Result<Value> {
282 let value = unsafe { gpiod::gpiod_line_settings_get_output_value(self.settings) };
284
285 if value != 0 && value != 1 {
286 Err(Error::OperationFailed(
287 OperationType::LineSettingsGetOutVal,
288 errno::errno(),
289 ))
290 } else {
291 Value::new(value)
292 }
293 }
294}
295
296impl Drop for Settings {
297 fn drop(&mut self) {
299 unsafe { gpiod::gpiod_line_settings_free(self.settings) }
301 }
302}