My understanding so far is that (as has been stated) the sysfs interface is deprecated.
There are at least two relatively new C APIs in user space (apologies to WiringPi and PiGpio). One or both seem to have the label libgpiod
They can be installed on buster (but not jessie) with:
apt-get install gpiod libgpiod-dev libgpiod-doc
Not sure about stretch.
Also not sure which API requires which installs.
1) The first C API relies on /usr/include/linux/gpio.h which holds data structures and defines used with system calls to interact with the gpios. This is written by Linus Walleij. An example of this API is shown below, and is derived from a talk by Linus Walleij indicated in the code comments. Programs using this API must have the #includes shown in the example below but don't need to be compiled with any libraries (AFAIK).
2) The second C API relies on /usr/include/gpiod.h which provides a simplified interface that abstracts setup and handles and allows contextless reads, writes, and other functions. This is maintained by Bartosz Golaszewski. An introduction to the API is given in some slides by Bartosz which can be found at:
https://ostconf.com/system/attachments/files/000/001/532/original/Linux_Piter_2018_-_New_GPIO_interface_for_linux_userspace.pdf?1541021776
Some good examples using this API can be found at:
https://framagit.org/cpb/example-programs-using-libgpiod/-/tree/master/
Note that programs using this API must:
#include <gpiod.h>
and be compiled with the -lgpiod library (for example):
gcc -o read-gpio -lgpiod read-gpio.c
I've successfully compiled and run some of the examples.
**
There is a C++ API also provided by Bartosz Golaszewski that depends on /usr/include/gpiod.hpp. It is a C++ a wrapper based on the C API and depends on the C++11 standard.
Programs using this API must:
#include <gpiod.hpp>
An example of using this API is found in the same slides as the C API.
https://ostconf.com/system/attachments/files/000/001/532/original/Linux_Piter_2018_-_New_GPIO_interface_for_linux_userspace.pdf?1541021776
I have yet to get these examples to compile, but suspect there is a library inclusion I have yet to discover.
Below is an example gpio read program using the C API number 1 from above (the one authored by Linus Walleij). It repeatedly reads gpio 4 on /dev/gpiochip0 and prints it's value.
/****
* gpio-read.c -- example program for reading gpio values using the <linux/gpio.h> C API
* The API consists primarily of data structures used as parameters to system calls.
* Adapted from from a youtube video of Linus Walleij at the Embedded Linux Conference Europe
* GPIO for Engineers and Makers: starting at timestamp 44:11
* For simplicity, there is no error checking.
****/
//Need the gpio API and support for the system calls.
#include <linux/gpio.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <string.h>
#include <unistd.h>
int main(){
//Opening device and getting file descriptor.
int fd = open("/dev/gpiochip0",O_RDONLY);
//structure for holding chip information
//This structure is defined in /usr/include/linux/gpio.h
struct gpiochip_info cinfo;
//Getting the chip information via the ioctl system call
//GPIO_GET_CHIPINFO_IOCTL defined also in /usr/include/linux/gpio.h
int ret = ioctl(fd,GPIO_GET_CHIPINFO_IOCTL,&cinfo);
//print out the chip information
fprintf(stdout, "GPIO chip: %s, \"%s\", %u GPIO lines\n",
cinfo.name, cinfo.label, cinfo.lines);
//structure for holding line information.
//structure defined in /usr/include/linux/gpio.h
struct gpioline_info linfo;
//get generic line information from system call
ret = ioctl(fd,GPIO_GET_LINEINFO_IOCTL, &linfo);
//Not sure what this line_offset is, but we specify the gpio number later.
fprintf(stdout,"line %2d: %s\n",linfo.line_offset,linfo.name);
//Reading lines
//Set up some handles for requests and data
struct gpiohandle_request req;
struct gpiohandle_data data;
//Although req and data can read multiple gpios at a time, we'll use just one
//This reads line offset 4, which corresponds to the BCM value in "gpio readall"
req.lineoffsets[0] = 4;
//have to indicate how many lines we are reading.
req.lines = 1;
//Make this an input request
req.flags = GPIOHANDLE_REQUEST_INPUT;
//Optionally give the line a name
strcpy(req.consumer_label, "First Switch");
//Get a line handle. Note that req.fd is provided a handle for the next ioctl.
int lhfd = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
//Loop with some delay that keeps checking the input and displaying the value
for(int ii = 0; ii < 1000; ++ii){
ret = ioctl(req.fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data);
printf("line %d is %s\n",req.lineoffsets[0], data.values[0] ? "high" : "low");
//wait 0.25 seconds
usleep(250000);
}
return 0;
}
Compile with
gcc -o gpio-read gpio-read.c
Execute:
./gpio-read
This will show the value of the specific gpio offset every 0.25 seconds.
/sys/class/gpio/export
they access the hardware directly, although they CAN use kernel services. Certainly WiringPi and AFAIK pigpiod directly access SoC registers. – Milliways Aug 19 '19 at 00:58