101 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * gpio-watch - monitor unrequested lines for property changes using the4 * character device5 *6 * Copyright (C) 2019 BayLibre SAS7 * 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