{"id":20446287,"url":"https://github.com/rust-embedded/gpio-cdev","last_synced_at":"2025-05-16T07:07:53.235Z","repository":{"id":44744042,"uuid":"123741214","full_name":"rust-embedded/gpio-cdev","owner":"rust-embedded","description":"Rust interface to the Linux GPIO Character Device API (/dev/gpiochip...)","archived":false,"fork":false,"pushed_at":"2024-05-25T03:14:21.000Z","size":152,"stargazers_count":219,"open_issues_count":11,"forks_count":37,"subscribers_count":21,"default_branch":"master","last_synced_at":"2025-05-12T10:56:28.302Z","etag":null,"topics":["embedded","gpio","gpio-cdev","gpio-character-device","linux","rust"],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rust-embedded.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-03-03T23:48:44.000Z","updated_at":"2025-05-02T03:31:40.000Z","dependencies_parsed_at":"2024-06-19T00:23:17.777Z","dependency_job_id":"80ebdb90-8429-4d60-988c-63f84b48a8bf","html_url":"https://github.com/rust-embedded/gpio-cdev","commit_stats":{"total_commits":90,"total_committers":16,"mean_commits":5.625,"dds":0.6333333333333333,"last_synced_commit":"cca34240738273f6666e6b84237391fabbc7fdfd"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rust-embedded%2Fgpio-cdev","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rust-embedded%2Fgpio-cdev/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rust-embedded%2Fgpio-cdev/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rust-embedded%2Fgpio-cdev/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rust-embedded","download_url":"https://codeload.github.com/rust-embedded/gpio-cdev/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254485064,"owners_count":22078767,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["embedded","gpio","gpio-cdev","gpio-character-device","linux","rust"],"created_at":"2024-11-15T10:18:54.671Z","updated_at":"2025-05-16T07:07:48.219Z","avatar_url":"https://github.com/rust-embedded.png","language":"Rust","readme":"# gpio-cdev\n\n[![Build Status](https://github.com/rust-embedded/gpio-cdev/workflows/Build/badge.svg)](https://github.com/rust-embedded/gpio-cdev/actions)\n[![Version](https://img.shields.io/crates/v/gpio-cdev.svg)](https://crates.io/crates/gpio-cdev)\n[![License](https://img.shields.io/crates/l/gpio-cdev.svg)](https://github.com/rust-embedded/gpio-cdev/blob/master/README.md#license)\n\n- [API Documentation](https://docs.rs/gpio-cdev)\n\nrust-gpio-cdev is a Rust library/crate providing access to [GPIO character device\nABI](https://www.kernel.org/doc/Documentation/ABI/testing/gpio-cdev).  This API,\nstabilized with Linux v4.4, deprecates the legacy sysfs interface to GPIOs that is\nplanned to be removed from the upstream kernel after\nyear 2020 (which is coming up quickly).\n\nUse of this API is encouraged over the sysfs API used by this crate's\npredecessor [sysfs_gpio](https://crates.io/crates/sysfs_gpio) if you don't need\nto target older kernels.  For more information on differences see [Sysfs GPIO vs\nGPIO Character Device](#sysfs-gpio-vs-gpio-character-device).\n\n## Installation\n\nAdd the following to your `Cargo.toml`\n\n```\n[dependencies]\ngpio-cdev = \"0.4\"\n```\n\nNote that the following features are available:\n\n* `async-tokio`: Adds a Stream interface for consuming GPIO events in async code\n  within a tokio runtime.\n\n## Examples\n\nThere are several additional examples available in the [examples\ndirectory](https://github.com/rust-embedded/rust-gpio-cdev/tree/master/examples).\n\n### Read State\n\n```rust\nuse gpio_cdev::{Chip, LineRequestFlags};\n\n// Read the state of GPIO4 on a raspberry pi.  /dev/gpiochip0\n// maps to the driver for the SoC (builtin) GPIO controller.\nlet mut chip = Chip::new(\"/dev/gpiochip0\")?;\nlet handle = chip\n    .get_line(4)?\n    .request(LineRequestFlags::INPUT, 0, \"read-input\")?;\nfor _ in 1..4 {\n    println!(\"Value: {:?}\", handle.get_value()?);\n}\n```\n\n### Mirror State (Read/Write)\n\n```rust\nuse gpio_cdev::{Chip, LineRequestFlags, EventRequestFlags, EventType};\n\n// Lines are offset within gpiochip0; see docs for more info on chips/lines\n//\n// This function will synchronously follow the state of one line\n// on gpiochip0 and mirror its state on another line.  With this you\n// could, for instance, control the state of an LED with a button\n// if hooked up to the right pins on a raspberry pi.\nfn mirror_gpio(inputline: u32, outputline: u32) -\u003e Result\u003c(), gpio_cdev::Error\u003e {\n    let mut chip = Chip::new(\"/dev/gpiochip0\")?;\n    let input = chip.get_line(inputline)?;\n    let output = chip.get_line(outputline)?;\n    let output_handle = output.request(LineRequestFlags::OUTPUT, 0, \"mirror-gpio\")?;\n    for event in input.events(\n        LineRequestFlags::INPUT,\n        EventRequestFlags::BOTH_EDGES,\n        \"mirror-gpio\",\n    )? {\n        let evt = event?;\n        println!(\"{:?}\", evt);\n        match evt.event_type() {\n            EventType::RisingEdge =\u003e {\n                output_handle.set_value(1)?;\n            }\n            EventType::FallingEdge =\u003e {\n                output_handle.set_value(0)?;\n            }\n        }\n    }\n\n    Ok(())\n}\n```\n\n### Async Usage\n\nNote that this requires the addition of the `async-tokio` feature.\n\n```rust\nuse futures::stream::StreamExt;\nuse gpio_cdev::{Chip, AsyncLineEventHandle};\n\nasync fn gpiomon(chip: String, line: u32) -\u003e gpio_cdev::Result\u003c()\u003e {\n    let mut chip = Chip::new(args.chip)?;\n    let line = chip.get_line(args.line)?;\n    let mut events = AsyncLineEventHandle::new(line.events(\n        LineRequestFlags::INPUT,\n        EventRequestFlags::BOTH_EDGES,\n        \"gpioevents\",\n    )?)?;\n\n    while let Some(event) = events.next().await {\n        let event = event?;\n        println!(\"GPIO Event: {:?}\", event);\n    }\n\n    Ok(())\n}\n```\n\n## Sysfs GPIO vs GPIO Character Device\n\nCompared to the sysfs gpio interface (as made available by the sysfs_gpio crate)\nthe character device has several advantages and critical design differences\n(some of which are driving the deprecation in the kernel).\n\nSince many people are familiar with the sysfs interface (which is easily\naccessible via basic commands in the shell) and few people are familiar with the\nGPIO character device, an exploration of the two and key differences here may\nprove useful.\n\n### Getting Access to a GPIO\n\nIn the Linux kernel, individual GPIOs are exposed via drivers that on probe register\nthemselves as GPIO chips with the gpio subsystem.  Each of these chips provides\naccess to a set of GPIOs.  At present, when this chip is registered a global\nbase number is assigned to this driver.  The comments from the linux kernel\n[`gpio_chip_add_data`](https://elixir.bootlin.com/linux/v4.9.85/source/drivers/gpio/gpiolib.c#L1087)\nsum up the situation nicely when assigning the a base number to a GPIO chip\non registration.\n\n    /*\n     * TODO: this allocates a Linux GPIO number base in the global\n     * GPIO numberspace for this chip. In the long run we want to\n     * get *rid* of this numberspace and use only descriptors, but\n     * it may be a pipe dream. It will not happen before we get rid\n     * of the sysfs interface anyways.\n     */\n\nThe entire sysfs interface to GPIO is based around offsets from the base number\nassigned to a GPIO chip.  The base number is completely dependent on the order\nin which the chip was registered with the subsystem and the number of GPIOs that\neach of the previous chips registered.  The only reason this is usable at all is\nthat most GPIOs are accessed via SoC hardware that is registered consistently\nduring boot.  It's not great; in fact, it's not even good.\n\nThe GPIO character device ABI provides access to GPIOs owned by a GPIO chip via\na bus device, `/sys/bus/gpiochipN` (or `/dev/gpiochipN`).  Within a chip, the\nprogrammer will still need to know some details about how to access the GPIO but\nthings are generally sane.  Figuring out which bus device is the desired GPIO\nchip can be done by iterating over all that are present and/or setting up\nappropriate udev rules.  One good example of this is the [`lsgpio` utility in\nthe kernel source](https://github.com/torvalds/linux/blob/master/tools/gpio/lsgpio.c).\n\nIn sysfs each GPIO within a chip would be exported and used individually. The\nGPIO character device allows for one or more GPIOs (referenced via offsets) to\nbe read, written, configured, and monitored via a \"linehandle\" fd that is\ncreated dynamically on request.\n\n### \"Exporting\" a GPIO\n\nUsing the sysfs API, one would write the global GPIO number to the \"export\" file\nto perform further operations using new files on the filesystem.  Using the\ngpiochip character device, a handle for performing operations on one or more\nGPIO offsets within a chip are available via a \"linehandle\" fd created using the\n`GPIO_GET_LINEHANDLE_IOCTL`. A consequence of this is that a line will remember\nits state only for as long as the fd is open; the line's state will be reset\nonce the fd is closed.\n\nWhen a linehandle is requested, additional information is also included about\nhow the individual GPIOs will be used (input, output, as-is, active-low, open\ndrain, open source, etc).  Multiple lines can be grouped together in a single\nrequest but they must all be configured the same way if being used in that way.\nSee `struct gpioevent_request`.\n\n### Reading/Writing GPIOs\n\nVia sysfs, GPIOs could be read/written using the value file.  For GPIO character\ndevices, the `GPIOHANDLE_GET_LINE_VALUES_IOCTL` and\n`GPIOHANDLE_SET_LINE_VALUES_IOCTL` may be used to get/set the state of one or\nmore offsets within the chip.\n\n### Input Events\n\nVia sysfs, one could setup things up using the trigger file to notify userspace\n(by polling on the value file) of a single event based on how things were setup.\nWith GPIO character devices, one can setup a `gpio_eventrequest` that will create\na new anonymous file (fd provided) for event notifications on a lines within a\ngpiochip.  Contrary to sysfs gpio events, the event file will queue multiple events\nand include with the event (best effort) nanosecond-precision timing and an\nidentifier with event type.\n\nWith this information one could more reasonably consider interpreting a basic\ndigital signal from userspace (with rising and falling edges) from userspace\nusing the queueing with timing information captured in the kernel.  Previously, one\nwould need to quickly handle the event notification, make another system call\nto the value file to see the state, etc. which had far too many variables involved\nto be considered reliable.\n\n## Minimum Supported Rust Version (MSRV)\n\nThis crate is guaranteed to compile on stable Rust 1.65.0 and up. It *might*\ncompile with older versions but that may change in any new patch release.\n\n## License\n\nLicensed under either of\n\n- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or\n  http://www.apache.org/licenses/LICENSE-2.0)\n- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)\n\nat your option.\n\n### Contribution\n\nUnless you explicitly state otherwise, any contribution intentionally submitted\nfor inclusion in the work by you, as defined in the Apache-2.0 license, shall be\ndual licensed as above, without any additional terms or conditions.\n\n## Code of Conduct\n\nContribution to this crate is organized under the terms of the [Rust Code of\nConduct][CoC], the maintainer of this crate, the [Embedded Linux Team][team], promises\nto intervene to uphold that code of conduct.\n\n[CoC]: CODE_OF_CONDUCT.md\n[team]: https://github.com/rust-embedded/wg#the-embedded-linux-team\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frust-embedded%2Fgpio-cdev","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frust-embedded%2Fgpio-cdev","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frust-embedded%2Fgpio-cdev/lists"}