linux/tools/gpio/gpio-watch.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * gpio-watch - monitor unrequested lines for property changes using the
   4 *              character device
   5 *
   6 * Copyright (C) 2019 BayLibre SAS
   7 * Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>
   8 */
   9
  10#include <ctype.h>
  11#include <errno.h>
  12#include <fcntl.h>
  13#include <inttypes.h>
  14#include <linux/gpio.h>
  15#include <poll.h>
  16#include <stdbool.h>
  17#include <stdio.h>
  18#include <stdlib.h>
  19#include <string.h>
  20#include <sys/ioctl.h>
  21#include <unistd.h>
  22
  23int main(int argc, char **argv)
  24{
  25        struct gpio_v2_line_info_changed chg;
  26        struct gpio_v2_line_info req;
  27        struct pollfd pfd;
  28        int fd, i, j, ret;
  29        char *event, *end;
  30        ssize_t rd;
  31
  32        if (argc < 3)
  33                goto err_usage;
  34
  35        fd = open(argv[1], O_RDWR | O_CLOEXEC);
  36        if (fd < 0) {
  37                perror("unable to open gpiochip");
  38                return EXIT_FAILURE;
  39        }
  40
  41        for (i = 0, j = 2; i < argc - 2; i++, j++) {
  42                memset(&req, 0, sizeof(req));
  43
  44                req.offset = strtoul(argv[j], &end, 0);
  45                if (*end != '\0')
  46                        goto err_usage;
  47
  48                ret = ioctl(fd, GPIO_V2_GET_LINEINFO_WATCH_IOCTL, &req);
  49                if (ret) {
  50                        perror("unable to set up line watch");
  51                        return EXIT_FAILURE;
  52                }
  53        }
  54
  55        pfd.fd = fd;
  56        pfd.events = POLLIN | POLLPRI;
  57
  58        for (;;) {
  59                ret = poll(&pfd, 1, 5000);
  60                if (ret < 0) {
  61                        perror("error polling the linechanged fd");
  62                        return EXIT_FAILURE;
  63                } else if (ret > 0) {
  64                        memset(&chg, 0, sizeof(chg));
  65                        rd = read(pfd.fd, &chg, sizeof(chg));
  66                        if (rd < 0 || rd != sizeof(chg)) {
  67                                if (rd != sizeof(chg))
  68                                        errno = EIO;
  69
  70                                perror("error reading line change event");
  71                                return EXIT_FAILURE;
  72                        }
  73
  74                        switch (chg.event_type) {
  75                        case GPIO_V2_LINE_CHANGED_REQUESTED:
  76                                event = "requested";
  77                                break;
  78                        case GPIO_V2_LINE_CHANGED_RELEASED:
  79                                event = "released";
  80                                break;
  81                        case GPIO_V2_LINE_CHANGED_CONFIG:
  82                                event = "config changed";
  83                                break;
  84                        default:
  85                                fprintf(stderr,
  86                                        "invalid event type received from the kernel\n");
  87                                return EXIT_FAILURE;
  88                        }
  89
  90                        printf("line %u: %s at %" PRIu64 "\n",
  91                               chg.info.offset, event, (uint64_t)chg.timestamp_ns);
  92                }
  93        }
  94
  95        return 0;
  96
  97err_usage:
  98        printf("%s: <gpiochip> <line0> <line1> ...\n", argv[0]);
  99        return EXIT_FAILURE;
 100}
 101