ioctl-invert-gpio.c 2.57 KB
Newer Older
Christophe Blaess's avatar
Christophe Blaess committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
// ---------------------------------------------------------------------
// 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);
102
	close(output_request.fd);
Christophe Blaess's avatar
Christophe Blaess committed
103 104 105 106
	close(output_fd);
	return EXIT_FAILURE;
}