• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..--

examples/25-Apr-2025-593380

src/25-Apr-2025-1,350767

.cargo-checksum.jsonD25-Apr-20251.9 KiB11

Android.bpD25-Apr-2025930 3733

CHANGELOG.mdD25-Apr-20253 KiB7049

CODE_OF_CONDUCT.mdD25-Apr-20254.5 KiB3826

Cargo.lockD25-Apr-202523.6 KiB950847

Cargo.tomlD25-Apr-20251.8 KiB10287

LICENSED25-Apr-202510.6 KiB202169

LICENSE-APACHED25-Apr-202510.6 KiB202169

LICENSE-MITD25-Apr-20251,023 2421

METADATAD25-Apr-2025397 1817

MODULE_LICENSE_APACHE2D25-Apr-20250

MODULE_LICENSE_MITD25-Apr-20250

README.mdD25-Apr-20259.3 KiB236183

cargo_embargo.jsonD25-Apr-2025104 98

README.md

1# gpio-cdev
2
3[![Build Status](https://github.com/rust-embedded/gpio-cdev/workflows/Build/badge.svg)](https://github.com/rust-embedded/gpio-cdev/actions)
4[![Version](https://img.shields.io/crates/v/gpio-cdev.svg)](https://crates.io/crates/gpio-cdev)
5[![License](https://img.shields.io/crates/l/gpio-cdev.svg)](https://github.com/rust-embedded/gpio-cdev/blob/master/README.md#license)
6
7- [API Documentation](https://docs.rs/gpio-cdev)
8
9rust-gpio-cdev is a Rust library/crate providing access to [GPIO character device
10ABI](https://www.kernel.org/doc/Documentation/ABI/testing/gpio-cdev).  This API,
11stabilized with Linux v4.4, deprecates the legacy sysfs interface to GPIOs that is
12planned to be removed from the upstream kernel after
13year 2020 (which is coming up quickly).
14
15Use of this API is encouraged over the sysfs API used by this crate's
16predecessor [sysfs_gpio](https://crates.io/crates/sysfs_gpio) if you don't need
17to target older kernels.  For more information on differences see [Sysfs GPIO vs
18GPIO Character Device](#sysfs-gpio-vs-gpio-character-device).
19
20## Installation
21
22Add the following to your `Cargo.toml`
23
24```
25[dependencies]
26gpio-cdev = "0.4"
27```
28
29Note that the following features are available:
30
31* `async-tokio`: Adds a Stream interface for consuming GPIO events in async code
32  within a tokio runtime.
33
34## Examples
35
36There are several additional examples available in the [examples
37directory](https://github.com/rust-embedded/rust-gpio-cdev/tree/master/examples).
38
39### Read State
40
41```rust
42use gpio_cdev::{Chip, LineRequestFlags};
43
44// Read the state of GPIO4 on a raspberry pi.  /dev/gpiochip0
45// maps to the driver for the SoC (builtin) GPIO controller.
46let mut chip = Chip::new("/dev/gpiochip0")?;
47let handle = chip
48    .get_line(4)?
49    .request(LineRequestFlags::INPUT, 0, "read-input")?;
50for _ in 1..4 {
51    println!("Value: {:?}", handle.get_value()?);
52}
53```
54
55### Mirror State (Read/Write)
56
57```rust
58use gpio_cdev::{Chip, LineRequestFlags, EventRequestFlags, EventType};
59
60// Lines are offset within gpiochip0; see docs for more info on chips/lines
61//
62// This function will synchronously follow the state of one line
63// on gpiochip0 and mirror its state on another line.  With this you
64// could, for instance, control the state of an LED with a button
65// if hooked up to the right pins on a raspberry pi.
66fn mirror_gpio(inputline: u32, outputline: u32) -> Result<(), gpio_cdev::Error> {
67    let mut chip = Chip::new("/dev/gpiochip0")?;
68    let input = chip.get_line(inputline)?;
69    let output = chip.get_line(outputline)?;
70    let output_handle = output.request(LineRequestFlags::OUTPUT, 0, "mirror-gpio")?;
71    for event in input.events(
72        LineRequestFlags::INPUT,
73        EventRequestFlags::BOTH_EDGES,
74        "mirror-gpio",
75    )? {
76        let evt = event?;
77        println!("{:?}", evt);
78        match evt.event_type() {
79            EventType::RisingEdge => {
80                output_handle.set_value(1)?;
81            }
82            EventType::FallingEdge => {
83                output_handle.set_value(0)?;
84            }
85        }
86    }
87
88    Ok(())
89}
90```
91
92### Async Usage
93
94Note that this requires the addition of the `async-tokio` feature.
95
96```rust
97use futures::stream::StreamExt;
98use gpio_cdev::{Chip, AsyncLineEventHandle};
99
100async fn gpiomon(chip: String, line: u32) -> gpio_cdev::Result<()> {
101    let mut chip = Chip::new(args.chip)?;
102    let line = chip.get_line(args.line)?;
103    let mut events = AsyncLineEventHandle::new(line.events(
104        LineRequestFlags::INPUT,
105        EventRequestFlags::BOTH_EDGES,
106        "gpioevents",
107    )?)?;
108
109    while let Some(event) = events.next().await {
110        let event = event?;
111        println!("GPIO Event: {:?}", event);
112    }
113
114    Ok(())
115}
116```
117
118## Sysfs GPIO vs GPIO Character Device
119
120Compared to the sysfs gpio interface (as made available by the sysfs_gpio crate)
121the character device has several advantages and critical design differences
122(some of which are driving the deprecation in the kernel).
123
124Since many people are familiar with the sysfs interface (which is easily
125accessible via basic commands in the shell) and few people are familiar with the
126GPIO character device, an exploration of the two and key differences here may
127prove useful.
128
129### Getting Access to a GPIO
130
131In the Linux kernel, individual GPIOs are exposed via drivers that on probe register
132themselves as GPIO chips with the gpio subsystem.  Each of these chips provides
133access to a set of GPIOs.  At present, when this chip is registered a global
134base number is assigned to this driver.  The comments from the linux kernel
135[`gpio_chip_add_data`](https://elixir.bootlin.com/linux/v4.9.85/source/drivers/gpio/gpiolib.c#L1087)
136sum up the situation nicely when assigning the a base number to a GPIO chip
137on registration.
138
139    /*
140     * TODO: this allocates a Linux GPIO number base in the global
141     * GPIO numberspace for this chip. In the long run we want to
142     * get *rid* of this numberspace and use only descriptors, but
143     * it may be a pipe dream. It will not happen before we get rid
144     * of the sysfs interface anyways.
145     */
146
147The entire sysfs interface to GPIO is based around offsets from the base number
148assigned to a GPIO chip.  The base number is completely dependent on the order
149in which the chip was registered with the subsystem and the number of GPIOs that
150each of the previous chips registered.  The only reason this is usable at all is
151that most GPIOs are accessed via SoC hardware that is registered consistently
152during boot.  It's not great; in fact, it's not even good.
153
154The GPIO character device ABI provides access to GPIOs owned by a GPIO chip via
155a bus device, `/sys/bus/gpiochipN` (or `/dev/gpiochipN`).  Within a chip, the
156programmer will still need to know some details about how to access the GPIO but
157things are generally sane.  Figuring out which bus device is the desired GPIO
158chip can be done by iterating over all that are present and/or setting up
159appropriate udev rules.  One good example of this is the [`lsgpio` utility in
160the kernel source](https://github.com/torvalds/linux/blob/master/tools/gpio/lsgpio.c).
161
162In sysfs each GPIO within a chip would be exported and used individually. The
163GPIO character device allows for one or more GPIOs (referenced via offsets) to
164be read, written, configured, and monitored via a "linehandle" fd that is
165created dynamically on request.
166
167### "Exporting" a GPIO
168
169Using the sysfs API, one would write the global GPIO number to the "export" file
170to perform further operations using new files on the filesystem.  Using the
171gpiochip character device, a handle for performing operations on one or more
172GPIO offsets within a chip are available via a "linehandle" fd created using the
173`GPIO_GET_LINEHANDLE_IOCTL`. A consequence of this is that a line will remember
174its state only for as long as the fd is open; the line's state will be reset
175once the fd is closed.
176
177When a linehandle is requested, additional information is also included about
178how the individual GPIOs will be used (input, output, as-is, active-low, open
179drain, open source, etc).  Multiple lines can be grouped together in a single
180request but they must all be configured the same way if being used in that way.
181See `struct gpioevent_request`.
182
183### Reading/Writing GPIOs
184
185Via sysfs, GPIOs could be read/written using the value file.  For GPIO character
186devices, the `GPIOHANDLE_GET_LINE_VALUES_IOCTL` and
187`GPIOHANDLE_SET_LINE_VALUES_IOCTL` may be used to get/set the state of one or
188more offsets within the chip.
189
190### Input Events
191
192Via sysfs, one could setup things up using the trigger file to notify userspace
193(by polling on the value file) of a single event based on how things were setup.
194With GPIO character devices, one can setup a `gpio_eventrequest` that will create
195a new anonymous file (fd provided) for event notifications on a lines within a
196gpiochip.  Contrary to sysfs gpio events, the event file will queue multiple events
197and include with the event (best effort) nanosecond-precision timing and an
198identifier with event type.
199
200With this information one could more reasonably consider interpreting a basic
201digital signal from userspace (with rising and falling edges) from userspace
202using the queueing with timing information captured in the kernel.  Previously, one
203would need to quickly handle the event notification, make another system call
204to the value file to see the state, etc. which had far too many variables involved
205to be considered reliable.
206
207## Minimum Supported Rust Version (MSRV)
208
209This crate is guaranteed to compile on stable Rust 1.65.0 and up. It *might*
210compile with older versions but that may change in any new patch release.
211
212## License
213
214Licensed under either of
215
216- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or
217  http://www.apache.org/licenses/LICENSE-2.0)
218- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
219
220at your option.
221
222### Contribution
223
224Unless you explicitly state otherwise, any contribution intentionally submitted
225for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
226dual licensed as above, without any additional terms or conditions.
227
228## Code of Conduct
229
230Contribution to this crate is organized under the terms of the [Rust Code of
231Conduct][CoC], the maintainer of this crate, the [Embedded Linux Team][team], promises
232to intervene to uphold that code of conduct.
233
234[CoC]: CODE_OF_CONDUCT.md
235[team]: https://github.com/rust-embedded/wg#the-embedded-linux-team
236