Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * gpio-watch - monitor unrequested lines for property changes using the
0004  *              character device
0005  *
0006  * Copyright (C) 2019 BayLibre SAS
0007  * Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>
0008  */
0009 
0010 #include <ctype.h>
0011 #include <errno.h>
0012 #include <fcntl.h>
0013 #include <inttypes.h>
0014 #include <linux/gpio.h>
0015 #include <poll.h>
0016 #include <stdbool.h>
0017 #include <stdio.h>
0018 #include <stdlib.h>
0019 #include <string.h>
0020 #include <sys/ioctl.h>
0021 #include <unistd.h>
0022 
0023 int main(int argc, char **argv)
0024 {
0025     struct gpio_v2_line_info_changed chg;
0026     struct gpio_v2_line_info req;
0027     struct pollfd pfd;
0028     int fd, i, j, ret;
0029     char *event, *end;
0030     ssize_t rd;
0031 
0032     if (argc < 3)
0033         goto err_usage;
0034 
0035     fd = open(argv[1], O_RDWR | O_CLOEXEC);
0036     if (fd < 0) {
0037         perror("unable to open gpiochip");
0038         return EXIT_FAILURE;
0039     }
0040 
0041     for (i = 0, j = 2; i < argc - 2; i++, j++) {
0042         memset(&req, 0, sizeof(req));
0043 
0044         req.offset = strtoul(argv[j], &end, 0);
0045         if (*end != '\0')
0046             goto err_usage;
0047 
0048         ret = ioctl(fd, GPIO_V2_GET_LINEINFO_WATCH_IOCTL, &req);
0049         if (ret) {
0050             perror("unable to set up line watch");
0051             return EXIT_FAILURE;
0052         }
0053     }
0054 
0055     pfd.fd = fd;
0056     pfd.events = POLLIN | POLLPRI;
0057 
0058     for (;;) {
0059         ret = poll(&pfd, 1, 5000);
0060         if (ret < 0) {
0061             perror("error polling the linechanged fd");
0062             return EXIT_FAILURE;
0063         } else if (ret > 0) {
0064             memset(&chg, 0, sizeof(chg));
0065             rd = read(pfd.fd, &chg, sizeof(chg));
0066             if (rd < 0 || rd != sizeof(chg)) {
0067                 if (rd != sizeof(chg))
0068                     errno = EIO;
0069 
0070                 perror("error reading line change event");
0071                 return EXIT_FAILURE;
0072             }
0073 
0074             switch (chg.event_type) {
0075             case GPIO_V2_LINE_CHANGED_REQUESTED:
0076                 event = "requested";
0077                 break;
0078             case GPIO_V2_LINE_CHANGED_RELEASED:
0079                 event = "released";
0080                 break;
0081             case GPIO_V2_LINE_CHANGED_CONFIG:
0082                 event = "config changed";
0083                 break;
0084             default:
0085                 fprintf(stderr,
0086                     "invalid event type received from the kernel\n");
0087                 return EXIT_FAILURE;
0088             }
0089 
0090             printf("line %u: %s at %" PRIu64 "\n",
0091                    chg.info.offset, event, (uint64_t)chg.timestamp_ns);
0092         }
0093     }
0094 
0095     return 0;
0096 
0097 err_usage:
0098     printf("%s: <gpiochip> <line0> <line1> ...\n", argv[0]);
0099     return EXIT_FAILURE;
0100 }