Commit 6c59e77d authored by Christophe Blaess's avatar Christophe Blaess

First release.

parents
ioctl-gpio-list
ioctl-invert-gpio
ioctl-poll-gpio
ioctl-toggle-gpio
*~
*.o
CROSS_COMPILE ?=
CC = $(CROSS_COMPILE)gcc
CFLAGS = -Wall -g
EXE = \
ioctl-gpio-list \
ioctl-invert-gpio \
ioctl-poll-gpio \
ioctl-toggle-gpio \
.PHONY: all
all:$(EXE)
.PHONY: clean
clean:
rm -f $(EXE) *.o
# Ioctl Access to Gpio
Christophe BLAESS 2018
This project is a set of examples programs to access the GPIO lines using the new Linux API with the `ioctl()` syscall.
The explaining (french) article will be released on October 22, 2018 at <https://www.blaess.fr/christophe/>.
// ---------------------------------------------------------------------
// ioctl-gpio-list.c
//
// This is a small example of ioctl() accesses to the new GPIO
// user-space API under Linux to list all the GPIO controllers
// and their GPIO lines.
//
// Copyright 2018 Christophe BLAESS (christophe@blaess.fr)
// License GPL v2.
// ---------------------------------------------------------------------
#include <dirent.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <linux/gpio.h>
#include <sys/ioctl.h>
static int filter_chips_files (const struct dirent *entry);
static void display_chip_info (const char *filename);
static void display_line_info (int fd, int offset);
int main(int argc, char *argv[])
{
int i;
int chips_count;
struct dirent **chips_files;
chips_count = scandir("/dev", &chips_files, filter_chips_files, alphasort);
if (chips_count <= 0) {
fprintf(stderr, "%s: unable to find any GPIO chip.\n", argv[0]);
exit(EXIT_FAILURE);
}
for (i = 0; i < chips_count; i++)
display_chip_info(chips_files[i]->d_name);
free(chips_files);
}
static int filter_chips_files(const struct dirent *entry)
{
return strncmp(entry->d_name, "gpiochip", 7) == 0;
}
static void display_chip_info(const char *filename)
{
int i;
int fd;
struct gpiochip_info info;
if (chdir("/dev") != 0) {
perror("/dev");
return;
}
fd = open(filename, O_RDONLY);
if (fd < 0) {
perror(filename);
return;
}
if (ioctl(fd, GPIO_GET_CHIPINFO_IOCTL, &info) < 0) {
perror(filename);
close(fd);
return;
}
fprintf(stdout, "file = /dev/%s, name = %s, label = %s, lines = %d\n", filename, info.name, info.label, info.lines);
for (i = 0; i < info.lines; i ++)
display_line_info(fd, i);
fprintf(stdout, "\n");
close(fd);
}
static void display_line_info(int fd, int offset)
{
struct gpioline_info info;
memset(&info, 0, sizeof(struct gpioline_info));
info.line_offset = offset;
if (ioctl(fd, GPIO_GET_LINEINFO_IOCTL, &info) < 0)
return;
fprintf(stdout, " offset = %d, name = %s, consumer = %s, flags = %s %s %s %s %s\n", info.line_offset, info.name, info.consumer,
info.flags & GPIOLINE_FLAG_IS_OUT ? "OUT" : "IN ",
info.flags & GPIOLINE_FLAG_ACTIVE_LOW ? "ACTIVE_LOW " : "ACTIVE_HIGH",
info.flags & GPIOLINE_FLAG_OPEN_DRAIN ? "OPEN_DRAIN" : "",
info.flags & GPIOLINE_FLAG_OPEN_SOURCE ? "OPEN_SOURCE" : "",
info.flags & GPIOLINE_FLAG_KERNEL ? "KERNEL" : "");
}
// ---------------------------------------------------------------------
// ioctl-invert-gpio.c
//
// This is a small example of ioctl() accesses to the new GPIO
// user-space API under Linux to output on a GPIO line the
// complementary value of those read on an input GPIO line.
//
// Copyright 2018 Christophe BLAESS (christophe@blaess.fr)
// License GPL v2.
// ---------------------------------------------------------------------
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <linux/gpio.h>
#include <sys/ioctl.h>
int main(int argc, char *argv[])
{
int input_fd;
int output_fd;
int input_offset;
int output_offset;
struct gpiohandle_request input_request;
struct gpiohandle_request output_request;
struct gpiohandle_data input_values;
struct gpiohandle_data output_values;
if (argc !=5 ) {
fprintf(stderr, "usage: %s <input-device> <input-offset> <output_device> <output-offset>\n",
argv[0]);
exit(EXIT_FAILURE);
}
if (sscanf(argv[2], "%d", &input_offset) != 1) {
fprintf(stderr, "%s: invalid <input-offset> value.\n", argv[0]);
exit(EXIT_FAILURE);
}
if (sscanf(argv[4], "%d", &output_offset) != 1) {
fprintf(stderr, "%s: invalid <output-offset> value.\n", argv[0]);
exit(EXIT_FAILURE);
}
input_fd = open(argv[1], O_RDONLY);
if (input_fd < 0) {
perror(argv[1]);
exit(EXIT_FAILURE);
}
output_fd = open(argv[3], O_RDONLY);
if (output_fd < 0) {
perror(argv[3]);
close(input_fd);
exit(EXIT_FAILURE);
}
memset(&input_request, 0, sizeof(struct gpiohandle_request));
input_request.lineoffsets[0] = input_offset;
input_request.flags = GPIOHANDLE_REQUEST_INPUT;
input_request.lines = 1;
if (ioctl(input_fd, GPIO_GET_LINEHANDLE_IOCTL, &input_request) < 0) {
perror(argv[1]);
close(input_fd);
close(output_fd);
exit(EXIT_FAILURE);
}
memset(&output_request, 0, sizeof(struct gpiohandle_request));
output_request.lineoffsets[0] = output_offset;
output_request.flags = GPIOHANDLE_REQUEST_OUTPUT;
output_request.lines = 1;
if (ioctl(output_fd, GPIO_GET_LINEHANDLE_IOCTL, &output_request) < 0) {
perror(argv[3]);
close(input_fd);
close(output_fd);
exit(EXIT_FAILURE);
}
for (;;) {
if (ioctl(input_request.fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &input_values) < 0) {
perror(argv[1]);
break;
}
output_values.values[0] = (input_values.values[0] == 0) ? 1 : 0;
if (ioctl(output_request.fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, &output_values) < 0) {
perror(argv[3]);
break;
}
}
close(input_fd);
close(output_fd);
return EXIT_FAILURE;
}
// ---------------------------------------------------------------------
// ioctl-poll-gpio.c
//
// This is a small example of ioctl() accesses to the new GPIO
// user-space API under Linux to wait on a input GPIO line for
// some events.
//
// Copyright 2018 Christophe BLAESS (christophe@blaess.fr)
// License GPL v2.
// ---------------------------------------------------------------------
#include <fcntl.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <linux/gpio.h>
#include <sys/ioctl.h>
int main(int argc, char *argv[])
{
int input_fd;
int input_offset;
struct gpioevent_request input_event_request;
struct gpioevent_data input_event_data;
struct pollfd poll_fd;
int ret;
if (argc != 3) {
fprintf(stderr, "usage: %s <input-device> <input-offset>\n",
argv[0]);
exit(EXIT_FAILURE);
}
if (sscanf(argv[2], "%d", &input_offset) != 1) {
fprintf(stderr, "%s: invalid <input-offset> value.\n", argv[0]);
exit(EXIT_FAILURE);
}
input_fd = open(argv[1], O_RDONLY);
if (input_fd < 0) {
perror(argv[1]);
exit(EXIT_FAILURE);
}
memset(&input_event_request, 0, sizeof(struct gpioevent_request));
input_event_request.lineoffset = input_offset;
input_event_request.handleflags = GPIOHANDLE_REQUEST_INPUT;
input_event_request.eventflags = GPIOEVENT_REQUEST_BOTH_EDGES;
if (ioctl(input_fd, GPIO_GET_LINEEVENT_IOCTL, &input_event_request) < 0) {
perror("GPIO_GET_LINEEVENT_IOCTL");
close(input_fd);
exit(EXIT_FAILURE);
}
for (;;) {
poll_fd.fd = input_event_request.fd;
poll_fd.events = POLLIN | POLLPRI;
ret = poll(&poll_fd, 1, 1000);
if (ret < 0) {
perror("poll");
break;
}
if (ret > 0) {
if (read(input_event_request.fd, &input_event_data, sizeof(struct gpioevent_data)) > 0) {
fprintf(stdout, "[%llu.%09llu]", input_event_data.timestamp / 1000000000, input_event_data.timestamp % 1000000000);
if (input_event_data.id & GPIOEVENT_EVENT_RISING_EDGE)
fprintf(stdout, " RISING");
if (input_event_data.id & GPIOEVENT_EVENT_FALLING_EDGE)
fprintf(stdout, " FALLING");
}
}
fprintf(stdout, "\n");
}
close(input_fd);
return EXIT_FAILURE;
}
// ---------------------------------------------------------------------
// ioctl-blink-gpio.c
//
// This is a small example of ioctl() accesses to the new GPIO
// user-space API under Linux to blink an output GPIO line.
//
// Copyright 2018 Christophe BLAESS (christophe@blaess.fr)
// License GPL v2.
// ---------------------------------------------------------------------
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <linux/gpio.h>
#include <sys/ioctl.h>
int main(int argc, char *argv[])
{
int output_fd;
int output_offset;
struct gpiohandle_request output_request;
struct gpiohandle_data output_values;
if (argc != 3) {
fprintf(stderr, "usage: %s <output_device> <output-offset>\n",
argv[0]);
exit(EXIT_FAILURE);
}
if (sscanf(argv[2], "%d", &output_offset) != 1) {
fprintf(stderr, "%s: invalid <output-offset> value.\n", argv[0]);
exit(EXIT_FAILURE);
}
output_fd = open(argv[1], O_RDONLY);
if (output_fd < 0) {
perror(argv[1]);
exit(EXIT_FAILURE);
}
memset(&output_request, 0, sizeof(struct gpiohandle_request));
output_request.lineoffsets[0] = output_offset;
output_request.flags = GPIOHANDLE_REQUEST_OUTPUT;
output_request.lines = 1;
if (ioctl(output_fd, GPIO_GET_LINEHANDLE_IOCTL, &output_request) < 0) {
perror(argv[1]);
close(output_fd);
exit(EXIT_FAILURE);
}
output_values.values[0] = 0;
for (;;) {
output_values.values[0] = 1 - output_values.values[0];
if (ioctl(output_request.fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, &output_values) < 0)
break;
usleep(500000);
}
perror(argv[1]);
close(output_fd);
return EXIT_FAILURE;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment