linux_embedded_hal/
cdev_pin.rs1use std::fmt;
6
7pub struct CdevPin(pub gpio_cdev::LineHandle, gpio_cdev::LineInfo);
11
12impl CdevPin {
13 pub fn new(handle: gpio_cdev::LineHandle) -> Result<Self, gpio_cdev::errors::Error> {
17 let info = handle.line().info()?;
18 Ok(CdevPin(handle, info))
19 }
20
21 fn get_input_flags(&self) -> gpio_cdev::LineRequestFlags {
22 if self.1.is_active_low() {
23 return gpio_cdev::LineRequestFlags::INPUT | gpio_cdev::LineRequestFlags::ACTIVE_LOW;
24 }
25 gpio_cdev::LineRequestFlags::INPUT
26 }
27
28 fn get_output_flags(&self) -> gpio_cdev::LineRequestFlags {
29 let mut flags = gpio_cdev::LineRequestFlags::OUTPUT;
30 if self.1.is_active_low() {
31 flags.insert(gpio_cdev::LineRequestFlags::ACTIVE_LOW);
32 }
33 if self.1.is_open_drain() {
34 flags.insert(gpio_cdev::LineRequestFlags::OPEN_DRAIN);
35 } else if self.1.is_open_source() {
36 flags.insert(gpio_cdev::LineRequestFlags::OPEN_SOURCE);
37 }
38 flags
39 }
40
41 pub fn into_input_pin(self) -> Result<CdevPin, gpio_cdev::errors::Error> {
43 if self.1.direction() == gpio_cdev::LineDirection::In {
44 return Ok(self);
45 }
46 let line = self.0.line().clone();
47 let input_flags = self.get_input_flags();
48 let consumer = self.1.consumer().unwrap_or("").to_owned();
49
50 std::mem::drop(self);
52
53 CdevPin::new(line.request(input_flags, 0, &consumer)?)
54 }
55
56 pub fn into_output_pin(
58 self,
59 state: embedded_hal::digital::PinState,
60 ) -> Result<CdevPin, gpio_cdev::errors::Error> {
61 if self.1.direction() == gpio_cdev::LineDirection::Out {
62 return Ok(self);
63 }
64
65 let line = self.0.line().clone();
66 let output_flags = self.get_output_flags();
67 let consumer = self.1.consumer().unwrap_or("").to_owned();
68
69 std::mem::drop(self);
71
72 let is_active_low = output_flags.intersects(gpio_cdev::LineRequestFlags::ACTIVE_LOW);
73 CdevPin::new(line.request(
74 output_flags,
75 state_to_value(state, is_active_low),
76 &consumer,
77 )?)
78 }
79}
80
81fn state_to_value(state: embedded_hal::digital::PinState, is_active_low: bool) -> u8 {
84 if is_active_low {
85 match state {
86 embedded_hal::digital::PinState::High => 0,
87 embedded_hal::digital::PinState::Low => 1,
88 }
89 } else {
90 match state {
91 embedded_hal::digital::PinState::High => 1,
92 embedded_hal::digital::PinState::Low => 0,
93 }
94 }
95}
96
97#[derive(Debug)]
99pub struct CdevPinError {
100 err: gpio_cdev::errors::Error,
101}
102
103impl CdevPinError {
104 pub fn inner(&self) -> &gpio_cdev::errors::Error {
106 &self.err
107 }
108}
109
110impl From<gpio_cdev::errors::Error> for CdevPinError {
111 fn from(err: gpio_cdev::errors::Error) -> Self {
112 Self { err }
113 }
114}
115
116impl fmt::Display for CdevPinError {
117 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118 write!(f, "{}", self.err)
119 }
120}
121
122impl std::error::Error for CdevPinError {
123 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
124 Some(&self.err)
125 }
126}
127
128impl embedded_hal::digital::Error for CdevPinError {
129 fn kind(&self) -> embedded_hal::digital::ErrorKind {
130 use embedded_hal::digital::ErrorKind;
131 ErrorKind::Other
132 }
133}
134
135impl embedded_hal::digital::ErrorType for CdevPin {
136 type Error = CdevPinError;
137}
138
139impl embedded_hal::digital::OutputPin for CdevPin {
140 fn set_low(&mut self) -> Result<(), Self::Error> {
141 self.0
142 .set_value(state_to_value(
143 embedded_hal::digital::PinState::Low,
144 self.1.is_active_low(),
145 ))
146 .map_err(CdevPinError::from)
147 }
148
149 fn set_high(&mut self) -> Result<(), Self::Error> {
150 self.0
151 .set_value(state_to_value(
152 embedded_hal::digital::PinState::High,
153 self.1.is_active_low(),
154 ))
155 .map_err(CdevPinError::from)
156 }
157}
158
159impl embedded_hal::digital::InputPin for CdevPin {
160 fn is_high(&mut self) -> Result<bool, Self::Error> {
161 self.0
162 .get_value()
163 .map(|val| {
164 val == state_to_value(
165 embedded_hal::digital::PinState::High,
166 self.1.is_active_low(),
167 )
168 })
169 .map_err(CdevPinError::from)
170 }
171
172 fn is_low(&mut self) -> Result<bool, Self::Error> {
173 self.is_high().map(|val| !val)
174 }
175}
176
177impl core::ops::Deref for CdevPin {
178 type Target = gpio_cdev::LineHandle;
179
180 fn deref(&self) -> &Self::Target {
181 &self.0
182 }
183}
184
185impl core::ops::DerefMut for CdevPin {
186 fn deref_mut(&mut self) -> &mut Self::Target {
187 &mut self.0
188 }
189}