Sysfs was used to control GPIOs on Linux system with the GPIOs defined in /sys/class/gpio, but starting with Linux 4.8, a new GPIO interface for user space was introduced, with gpiochip becoming char devices foudn in /dev/gpiochip0, dev/gpiochip1, etc.. , and sysfs allegedly become deprecated.
But a quick check in NanoPi Duo with Linux 4.11 shows both GPIO user space interfaces appear to be enabled:
1 2 3 4 |
ls /sys/class/gpio/ export gpiochip0 gpiochip352 unexport ls /dev/gpiochip gpiochip0 gpiochip1 |
Nevertheless overtime, sysfs will die out, and the new subsystem will likely be used by all systems, so it might be useful to learn more about it.
One way to do that is to watch Bartosz Golaszewski’s ELCE 2017 talk entitled “New GPIO Interface for User Space” with the video embedded below. But I first I’ll summarize some of the key points.
Now GPIO handling from user space becomes similar to other char driver with ioctl, poll and read functions, and beside assigning numbers to GPIOs you can assign names. The API (in linux/gpio.h) provides access to chip info, line info, line request for values, reading values, settings values, line request for events (rise/falling edges), polling for events, and reading events. Bartosz goes into details for each function in his talk.
Since the kernel API is a bit complicated to use, there’s also a C library called libgpiod, which comes with some tools like gpiodetect, gpioinfo, gpioset, gpioget, gpiofind & gpiomon. Further work includes C++ and Python bindings, as well as a GPIO daemon and client. Example code for libgpiod:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
struct gpiod_chip *chip; struct gpiod_line *line; int rv, value; chip = gpiod_chip_open("/dev/gpiochip0"); if (!chip) return -1; line = gpiod_chip_get_line(chip, 3); if (!line) { gpiod_chip_close(chip); return -1 } rv = gpiod_line_input(line, “foobar”); if (rv) { gpiod_chip_close(chip); return -1; } value = gpiod_line_get_value(line); gpiod_chip_close(chip) |
Some example of user space tools found in libgpiod:
1 2 3 4 5 6 7 8 9 10 11 12 |
gpiodetect gpiochip2 [gpio-mockup-C] (8 lines) gpiochip1 [gpio-mockup-B] (8 lines) gpiochip0 [gpio-mockup-A] (8 lines) gpioset gpiochip1 3=1 gpioget gpiochip1 1 2 3 4 5 0 0 1 0 0 gpiomon gpiochip0 2 event: RISING EDGE offset: 2 timestamp: [1508094667.935877214] |
The first command return the list of gpio chips, their names, and number of lines, the second set the 3rd pin of Chip 1 to high, the third return the values of 5 different pins, and the last one monitor a pin to detect an event and return the time when it happened.
You can check out the latest libgpiod source code, or download the latest stable release of the code as a tarball. libgpiod is already available in meta-openembedded & buildroot, and packaged in Fedora and Arch Linux.
You may also be interested in the slides.

Jean-Luc started CNX Software in 2010 as a part-time endeavor, before quitting his job as a software engineering manager, and starting to write daily news, and reviews full time later in 2011.
Support CNX Software! Donate via cryptocurrencies, become a Patron on Patreon, or purchase goods on Amazon or Aliexpress