Name |
Date |
Size |
#Lines |
LOC |
||
---|---|---|---|---|---|---|
.. | - | - | ||||
examples/ | 25-Apr-2025 | - | 593 | 380 | ||
src/ | 25-Apr-2025 | - | 1,350 | 767 | ||
.cargo-checksum.json | D | 25-Apr-2025 | 1.9 KiB | 1 | 1 | |
Android.bp | D | 25-Apr-2025 | 930 | 37 | 33 | |
CHANGELOG.md | D | 25-Apr-2025 | 3 KiB | 70 | 49 | |
CODE_OF_CONDUCT.md | D | 25-Apr-2025 | 4.5 KiB | 38 | 26 | |
Cargo.lock | D | 25-Apr-2025 | 23.6 KiB | 950 | 847 | |
Cargo.toml | D | 25-Apr-2025 | 1.8 KiB | 102 | 87 | |
LICENSE | D | 25-Apr-2025 | 10.6 KiB | 202 | 169 | |
LICENSE-APACHE | D | 25-Apr-2025 | 10.6 KiB | 202 | 169 | |
LICENSE-MIT | D | 25-Apr-2025 | 1,023 | 24 | 21 | |
METADATA | D | 25-Apr-2025 | 397 | 18 | 17 | |
MODULE_LICENSE_APACHE2 | D | 25-Apr-2025 | 0 | |||
MODULE_LICENSE_MIT | D | 25-Apr-2025 | 0 | |||
README.md | D | 25-Apr-2025 | 9.3 KiB | 236 | 183 | |
cargo_embargo.json | D | 25-Apr-2025 | 104 | 9 | 8 |
README.md
1# gpio-cdev 2 3[](https://github.com/rust-embedded/gpio-cdev/actions) 4[](https://crates.io/crates/gpio-cdev) 5[](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