Guide: How to Use Libgpiod with C

ls-root1 pts0 comments

Guide: How to use libgpiod with C | ls-root's blog

Background

I own a Raspberry Pi 5, a small computer that features GPIO (General-Purpose Input/Output) pins. These pins allow you to connect external components like LEDs or sensors. Although I had never used them before, I recently wanted to add a simple software-controlled status LED to my Pi.

I researched libraries to interact with the GPIO pins and frequently found people recommending gpiozero, a Python library built exactly for this use case. Unfortunately, it didn't work. It threw an error saying it couldn't connect to the GPIO chip. After looking the error up online, I discovered this is a known issue: gpiozero doesn't yet support the Raspberry Pi 5.

So, I looked for alternatives and found libgpiod, the official library for interacting with the Linux GPIO Character Device. Originally written in C, it was later ported in v2 to C++, Python, GObject, and Rust. Since I didn't know about those other language bindings at the time, I decided to try using it with C.

It was not a straightforward experience. The official documentation reads more like an API reference than a guide. It simply lists each function with a brief description, leaving you to figure out the correct order and context for calling them yourself. In this post, I want to save you that headache and share exactly how to use libgpiod in C.

Concepts

libgpiod v2 is highly modular, this results in many structs you need to create and connect in order to get a result. Here is every concept you need to know to get started.

Chip : The physical port you are talking to

Setting : Contains configuration for only one pin

Line Config : Maps settings to specific line offsets

Request : The actual lock/handle you use to control the pin at runtime

The acutal Guide

0. Prerequisites

Of course, you'll need a computer with a GPIO chip onboard—any Single Board Computer (SBC) running Linux will do. To verify that your GPIO chips are recognized, look in /dev/ for gpiochip character devices (e.g., /dev/gpiochip4).

On a Raspberry Pi, and likely other SBCs, you will probably find multiple gpiochip devices. This is because modern boards often have dedicated chips handling internal hardware, like the power button or the Ethernet controller, separate from the main user-accessible GPIO pins. On my Raspberry Pi 5, I see five chips.

To figure out which chip corresponds to the physical header pins, install the gpiod package. This contains the library along with handy command-line tools. One of these tools is gpioinfo. Note that you must run this as root, or be part of the gpio group. Running gpioinfo will list every chip, its lines, and a description, making it easy to spot the right one. For me, it was /dev/gpiochip0.

Here is what the output looks like on a Raspberry Pi 5:

gpiochip0 - 54 lines:<br>line 0: "ID_SDA" input<br>line 1: "ID_SCL" input<br>line 2: "GPIO2" input<br>line 3: "GPIO3" input<br>line 4: "GPIO4" input<br>line 5: "GPIO5" input<br>[...]

Note: When compiling your libgpiod programs, don't forget to link the library using the -lgpiod flag (e.g., gcc main.c -o led -lgpiod).

1. Opening the chip

This is the easy part of the setup. Use gpiod_chip_open() to create a gpiod_chip struct, which contains a file descriptor and the path to the device. On success, the function returns a pointer to the struct; on failure, it returns NULL. To close the chip later, use gpiod_chip_close().

struct gpiod_chip *chip = gpiod_chip_open("/dev/gpiochip0");<br>if (!chip) {<br>fputs("Failed to open GPIO chip\n", stderr);<br>exit(1);

// Doing stuff with the chip...

gpiod_chip_close(chip);

2. Creating settings

If you have worked with microcontrollers, you know that you first need to configure the GPIO pins. Most libraries, like the Arduino one, allow you to do this in a single line. But remember, this is C—of course we can't do it in one line.

To configure a pin, you first need to create a gpiod_line_settings struct. This holds the configuration properties for a GPIO pin.

Caution: gpiod_line_settings DO NOT contain any mappings to physical line offsets, just properties for a pin.

To create one, use gpiod_line_settings_new(), which returns a pointer to the struct (or NULL on failure).

There are many functions to set and get the properties of the line settings. I recommend checking out the documentation for all available settings: https://libgpiod.readthedocs.io/en/master/core_line_settings.html. You can find the definitions for the enums used here: https://libgpiod.readthedocs.io/en/master/core_line_defs.html.

All of the set functions return 0 on success and -1 on failure.

Here is an example that creates a line settings struct for an active-high, pull-down, output pin:

struct gpiod_line_settings *settings = gpiod_line_settings_new();<br>if (!settings) {<br>fputs("Failed to create line settings\n", stderr);<br>gpiod_chip_close(chip);<br>exit(1);

gpiod_line_settings_set_direction(settings,...

line chip gpio settings libgpiod input

Related Articles