Skip to content

Commit c921d3f

Browse files
bors[bot]almusil
andauthored
Merge #30
30: Add support for character device GPIO r=posborne a=almusil Co-authored-by: Ales Musil <[email protected]>
2 parents 9c692b4 + 0b8e373 commit c921d3f

File tree

6 files changed

+169
-74
lines changed

6 files changed

+169
-74
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1212
### Added
1313

1414
- Added serial::Read/Write implementation.
15+
- Added feature flag for Chardev GPIO
1516

1617
### Fixed
1718

@@ -23,6 +24,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
2324
- Use embedded-hal::digital::v2 traits.
2425
- Updated to i2cdev 0.4.3 (necessary for trasactional write-read).
2526
- Updated to spidev 0.4
27+
- Added feature flag for Sysfs GPIO
2628

2729
## [v0.2.2] - 2018-12-21
2830

Cargo.toml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,18 @@ name = "linux-embedded-hal"
88
repository = "https://github.com/japaric/linux-embedded-hal"
99
version = "0.3.0"
1010

11+
[features]
12+
default = []
13+
gpio_sysfs = ["sysfs_gpio"]
14+
gpio_cdev = ["gpio-cdev"]
15+
1116
[dependencies]
1217
embedded-hal = { version = "0.2.3", features = ["unproven"] }
18+
gpio-cdev = { version = "0.2", optional = true }
19+
sysfs_gpio = { version = "0.5", optional = true }
20+
1321
i2cdev = "0.4.3"
1422
spidev = "0.4"
15-
sysfs_gpio = "0.5"
1623
serial-unix = "0.4.0"
1724
serial-core = "0.4.0"
1825
nb = "0.1.1"

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,20 @@ This project is developed and maintained by the [Embedded Linux team][team].
88

99
## [Documentation](https://docs.rs/linux-embedded-hal)
1010

11+
## GPIO character device
12+
13+
Since Linux kernel v4.4 the use of sysfs GPIO was deprecated and replaced by the character device GPIO.
14+
See [gpio-cdev documentation](https://github.com/rust-embedded/gpio-cdev#sysfs-gpio-vs-gpio-character-device) for details.
15+
16+
This crate includes feature flag `gpio_cdev` that exposes `CdevPin` as wrapper around `LineHandle` from [gpio-cdev](https://crates.io/crates/gpio-cdev).
17+
To enable it update your Cargo.toml. Please note that in order to prevent `LineHandle` fd from closing you should
18+
assign to a variable, see [cdev issue](https://github.com/rust-embedded/gpio-cdev/issues/29) for more details.
19+
```
20+
linux-embedded-hal = { version = "0.3", features = ["gpio_cdev"] }
21+
```
22+
23+
`SysfsPin` can be still used with feature flag `gpio_sysfs`.
24+
1125
## License
1226

1327
Licensed under either of

src/cdev_pin.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
use core::ops;
2+
3+
/// Newtype around [`gpio_cdev::LineHandle`] that implements the `embedded-hal` traits
4+
///
5+
/// [`gpio_cdev::LineHandle`]: https://docs.rs/gpio-cdev/0.2.0/gpio_cdev/struct.LineHandle.html
6+
pub struct CdevPin(pub gpio_cdev::LineHandle, bool);
7+
8+
impl CdevPin {
9+
/// See [`gpio_cdev::Line::request`][0] for details.
10+
///
11+
/// [0]: https://docs.rs/gpio-cdev/0.2.0/gpio_cdev/struct.Line.html#method.request
12+
pub fn new(handle: gpio_cdev::LineHandle) -> Result<Self, gpio_cdev::errors::Error> {
13+
let info = handle.line().info()?;
14+
Ok(CdevPin(handle, info.is_active_low()))
15+
}
16+
}
17+
18+
impl hal::digital::v2::OutputPin for CdevPin {
19+
type Error = gpio_cdev::errors::Error;
20+
21+
fn set_low(&mut self) -> Result<(), Self::Error> {
22+
self.0.set_value(0)
23+
}
24+
25+
fn set_high(&mut self) -> Result<(), Self::Error> {
26+
self.0.set_value(1)
27+
}
28+
}
29+
30+
impl hal::digital::v2::InputPin for CdevPin {
31+
type Error = gpio_cdev::errors::Error;
32+
33+
fn is_high(&self) -> Result<bool, Self::Error> {
34+
if !self.1 {
35+
self.0.get_value().map(|val| val != 0)
36+
} else {
37+
self.0.get_value().map(|val| val == 0)
38+
}
39+
}
40+
41+
fn is_low(&self) -> Result<bool, Self::Error> {
42+
self.is_high().map(|val| !val)
43+
}
44+
}
45+
46+
impl ops::Deref for CdevPin {
47+
type Target = gpio_cdev::LineHandle;
48+
49+
fn deref(&self) -> &Self::Target {
50+
&self.0
51+
}
52+
}
53+
54+
impl ops::DerefMut for CdevPin {
55+
fn deref_mut(&mut self) -> &mut Self::Target {
56+
&mut self.0
57+
}
58+
}

src/lib.rs

Lines changed: 19 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,17 @@
1313
#![deny(missing_docs)]
1414

1515
extern crate cast;
16+
extern crate core;
1617
extern crate embedded_hal as hal;
18+
#[cfg(feature = "gpio_cdev")]
19+
pub extern crate gpio_cdev;
1720
pub extern crate i2cdev;
21+
pub extern crate nb;
22+
pub extern crate serial_core;
23+
pub extern crate serial_unix;
1824
pub extern crate spidev;
25+
#[cfg(feature = "gpio_sysfs")]
1926
pub extern crate sysfs_gpio;
20-
pub extern crate serial_unix;
21-
pub extern crate serial_core;
22-
pub extern crate nb;
2327

2428
use std::io::{self, Write};
2529
use std::path::{Path, PathBuf};
@@ -33,7 +37,18 @@ use spidev::SpidevTransfer;
3337

3438
mod serial;
3539

40+
#[cfg(feature = "gpio_cdev")]
41+
/// Cdev Pin wrapper module
42+
mod cdev_pin;
43+
#[cfg(feature = "gpio_sysfs")]
44+
/// Sysfs Pin wrapper module
45+
mod sysfs_pin;
46+
47+
#[cfg(feature = "gpio_cdev")]
48+
pub use cdev_pin::CdevPin;
3649
pub use serial::Serial;
50+
#[cfg(feature = "gpio_sysfs")]
51+
pub use sysfs_pin::SysfsPin;
3752

3853
/// Empty struct that provides delay functionality on top of `thread::sleep`
3954
pub struct Delay;
@@ -92,72 +107,6 @@ impl hal::blocking::delay::DelayMs<u64> for Delay {
92107
}
93108
}
94109

95-
/// Newtype around [`sysfs_gpio::Pin`] that implements the `embedded-hal` traits
96-
///
97-
/// [`sysfs_gpio::Pin`]: https://docs.rs/sysfs_gpio/0.5.1/sysfs_gpio/struct.Pin.html
98-
pub struct Pin(pub sysfs_gpio::Pin);
99-
100-
impl Pin {
101-
/// See [`sysfs_gpio::Pin::new`][0] for details.
102-
///
103-
/// [0]: https://docs.rs/sysfs_gpio/0.5.1/sysfs_gpio/struct.Pin.html#method.new
104-
pub fn new(pin_num: u64) -> Pin {
105-
Pin(sysfs_gpio::Pin::new(pin_num))
106-
}
107-
108-
/// See [`sysfs_gpio::Pin::from_path`][0] for details.
109-
///
110-
/// [0]: https://docs.rs/sysfs_gpio/0.5.1/sysfs_gpio/struct.Pin.html#method.from_path
111-
pub fn from_path<P>(path: P) -> sysfs_gpio::Result<Pin>
112-
where
113-
P: AsRef<Path>,
114-
{
115-
sysfs_gpio::Pin::from_path(path).map(Pin)
116-
}
117-
}
118-
119-
impl hal::digital::v2::OutputPin for Pin {
120-
type Error = sysfs_gpio::Error;
121-
122-
fn set_low(&mut self) -> Result<(), Self::Error> {
123-
self.0.set_value(0)
124-
}
125-
126-
fn set_high(&mut self) -> Result<(), Self::Error> {
127-
self.0.set_value(1)
128-
}
129-
}
130-
131-
impl hal::digital::v2::InputPin for Pin {
132-
type Error = sysfs_gpio::Error;
133-
134-
fn is_high(&self) -> Result<bool, Self::Error> {
135-
if !self.0.get_active_low()? {
136-
self.0.get_value().map(|val| val != 0)
137-
} else {
138-
self.0.get_value().map(|val| val == 0)
139-
}
140-
}
141-
142-
fn is_low(&self) -> Result<bool, Self::Error> {
143-
self.is_high().map(|val| !val)
144-
}
145-
}
146-
147-
impl ops::Deref for Pin {
148-
type Target = sysfs_gpio::Pin;
149-
150-
fn deref(&self) -> &Self::Target {
151-
&self.0
152-
}
153-
}
154-
155-
impl ops::DerefMut for Pin {
156-
fn deref_mut(&mut self) -> &mut Self::Target {
157-
&mut self.0
158-
}
159-
}
160-
161110
/// Newtype around [`i2cdev::linux::LinuxI2CDevice`] that implements the `embedded-hal` traits
162111
///
163112
/// [`i2cdev::linux::LinuxI2CDevice`]: https://docs.rs/i2cdev/0.3.1/i2cdev/linux/struct.LinuxI2CDevice.html
@@ -220,10 +169,7 @@ impl hal::blocking::i2c::WriteRead for I2cdev {
220169
buffer: &mut [u8],
221170
) -> Result<(), Self::Error> {
222171
self.set_address(address)?;
223-
let mut messages = [
224-
LinuxI2CMessage::write(bytes),
225-
LinuxI2CMessage::read(buffer),
226-
];
172+
let mut messages = [LinuxI2CMessage::write(bytes), LinuxI2CMessage::read(buffer)];
227173
self.inner.transfer(&mut messages).map(drop)
228174
}
229175
}

src/sysfs_pin.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
use std::ops;
2+
use std::path::Path;
3+
4+
/// Newtype around [`sysfs_gpio::Pin`] that implements the `embedded-hal` traits
5+
///
6+
/// [`sysfs_gpio::Pin`]: https://docs.rs/sysfs_gpio/0.5.1/sysfs_gpio/struct.Pin.html
7+
pub struct SysfsPin(pub sysfs_gpio::Pin);
8+
9+
impl SysfsPin {
10+
/// See [`sysfs_gpio::Pin::new`][0] for details.
11+
///
12+
/// [0]: https://docs.rs/sysfs_gpio/0.5.1/sysfs_gpio/struct.Pin.html#method.new
13+
pub fn new(pin_num: u64) -> Self {
14+
SysfsPin(sysfs_gpio::Pin::new(pin_num))
15+
}
16+
17+
/// See [`sysfs_gpio::Pin::from_path`][0] for details.
18+
///
19+
/// [0]: https://docs.rs/sysfs_gpio/0.5.1/sysfs_gpio/struct.Pin.html#method.from_path
20+
pub fn from_path<P>(path: P) -> sysfs_gpio::Result<Self>
21+
where
22+
P: AsRef<Path>,
23+
{
24+
sysfs_gpio::Pin::from_path(path).map(SysfsPin)
25+
}
26+
}
27+
28+
impl hal::digital::v2::OutputPin for SysfsPin {
29+
type Error = sysfs_gpio::Error;
30+
31+
fn set_low(&mut self) -> Result<(), Self::Error> {
32+
self.0.set_value(0)
33+
}
34+
35+
fn set_high(&mut self) -> Result<(), Self::Error> {
36+
self.0.set_value(1)
37+
}
38+
}
39+
40+
impl hal::digital::v2::InputPin for SysfsPin {
41+
type Error = sysfs_gpio::Error;
42+
43+
fn is_high(&self) -> Result<bool, Self::Error> {
44+
if !self.0.get_active_low()? {
45+
self.0.get_value().map(|val| val != 0)
46+
} else {
47+
self.0.get_value().map(|val| val == 0)
48+
}
49+
}
50+
51+
fn is_low(&self) -> Result<bool, Self::Error> {
52+
self.is_high().map(|val| !val)
53+
}
54+
}
55+
56+
impl ops::Deref for SysfsPin {
57+
type Target = sysfs_gpio::Pin;
58+
59+
fn deref(&self) -> &Self::Target {
60+
&self.0
61+
}
62+
}
63+
64+
impl ops::DerefMut for SysfsPin {
65+
fn deref_mut(&mut self) -> &mut Self::Target {
66+
&mut self.0
67+
}
68+
}

0 commit comments

Comments
 (0)