root/tools/gpio/gpio-event-mon.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. monitor_device
  2. print_usage
  3. main

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * gpio-event-mon - monitor GPIO line events from userspace
   4  *
   5  * Copyright (C) 2016 Linus Walleij
   6  *
   7  * Usage:
   8  *      gpio-event-mon -n <device-name> -o <offset>
   9  */
  10 
  11 #include <unistd.h>
  12 #include <stdlib.h>
  13 #include <stdbool.h>
  14 #include <stdint.h>
  15 #include <stdio.h>
  16 #include <dirent.h>
  17 #include <errno.h>
  18 #include <string.h>
  19 #include <poll.h>
  20 #include <fcntl.h>
  21 #include <getopt.h>
  22 #include <inttypes.h>
  23 #include <sys/ioctl.h>
  24 #include <sys/types.h>
  25 #include <linux/gpio.h>
  26 
  27 int monitor_device(const char *device_name,
  28                    unsigned int line,
  29                    uint32_t handleflags,
  30                    uint32_t eventflags,
  31                    unsigned int loops)
  32 {
  33         struct gpioevent_request req;
  34         struct gpiohandle_data data;
  35         char *chrdev_name;
  36         int fd;
  37         int ret;
  38         int i = 0;
  39 
  40         ret = asprintf(&chrdev_name, "/dev/%s", device_name);
  41         if (ret < 0)
  42                 return -ENOMEM;
  43 
  44         fd = open(chrdev_name, 0);
  45         if (fd == -1) {
  46                 ret = -errno;
  47                 fprintf(stderr, "Failed to open %s\n", chrdev_name);
  48                 goto exit_close_error;
  49         }
  50 
  51         req.lineoffset = line;
  52         req.handleflags = handleflags;
  53         req.eventflags = eventflags;
  54         strcpy(req.consumer_label, "gpio-event-mon");
  55 
  56         ret = ioctl(fd, GPIO_GET_LINEEVENT_IOCTL, &req);
  57         if (ret == -1) {
  58                 ret = -errno;
  59                 fprintf(stderr, "Failed to issue GET EVENT "
  60                         "IOCTL (%d)\n",
  61                         ret);
  62                 goto exit_close_error;
  63         }
  64 
  65         /* Read initial states */
  66         ret = ioctl(req.fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data);
  67         if (ret == -1) {
  68                 ret = -errno;
  69                 fprintf(stderr, "Failed to issue GPIOHANDLE GET LINE "
  70                         "VALUES IOCTL (%d)\n",
  71                         ret);
  72                 goto exit_close_error;
  73         }
  74 
  75         fprintf(stdout, "Monitoring line %d on %s\n", line, device_name);
  76         fprintf(stdout, "Initial line value: %d\n", data.values[0]);
  77 
  78         while (1) {
  79                 struct gpioevent_data event;
  80 
  81                 ret = read(req.fd, &event, sizeof(event));
  82                 if (ret == -1) {
  83                         if (errno == -EAGAIN) {
  84                                 fprintf(stderr, "nothing available\n");
  85                                 continue;
  86                         } else {
  87                                 ret = -errno;
  88                                 fprintf(stderr, "Failed to read event (%d)\n",
  89                                         ret);
  90                                 break;
  91                         }
  92                 }
  93 
  94                 if (ret != sizeof(event)) {
  95                         fprintf(stderr, "Reading event failed\n");
  96                         ret = -EIO;
  97                         break;
  98                 }
  99                 fprintf(stdout, "GPIO EVENT %llu: ", event.timestamp);
 100                 switch (event.id) {
 101                 case GPIOEVENT_EVENT_RISING_EDGE:
 102                         fprintf(stdout, "rising edge");
 103                         break;
 104                 case GPIOEVENT_EVENT_FALLING_EDGE:
 105                         fprintf(stdout, "falling edge");
 106                         break;
 107                 default:
 108                         fprintf(stdout, "unknown event");
 109                 }
 110                 fprintf(stdout, "\n");
 111 
 112                 i++;
 113                 if (i == loops)
 114                         break;
 115         }
 116 
 117 exit_close_error:
 118         if (close(fd) == -1)
 119                 perror("Failed to close GPIO character device file");
 120         free(chrdev_name);
 121         return ret;
 122 }
 123 
 124 void print_usage(void)
 125 {
 126         fprintf(stderr, "Usage: gpio-event-mon [options]...\n"
 127                 "Listen to events on GPIO lines, 0->1 1->0\n"
 128                 "  -n <name>  Listen on GPIOs on a named device (must be stated)\n"
 129                 "  -o <n>     Offset to monitor\n"
 130                 "  -d         Set line as open drain\n"
 131                 "  -s         Set line as open source\n"
 132                 "  -r         Listen for rising edges\n"
 133                 "  -f         Listen for falling edges\n"
 134                 " [-c <n>]    Do <n> loops (optional, infinite loop if not stated)\n"
 135                 "  -?         This helptext\n"
 136                 "\n"
 137                 "Example:\n"
 138                 "gpio-event-mon -n gpiochip0 -o 4 -r -f\n"
 139         );
 140 }
 141 
 142 int main(int argc, char **argv)
 143 {
 144         const char *device_name = NULL;
 145         unsigned int line = -1;
 146         unsigned int loops = 0;
 147         uint32_t handleflags = GPIOHANDLE_REQUEST_INPUT;
 148         uint32_t eventflags = 0;
 149         int c;
 150 
 151         while ((c = getopt(argc, argv, "c:n:o:dsrf?")) != -1) {
 152                 switch (c) {
 153                 case 'c':
 154                         loops = strtoul(optarg, NULL, 10);
 155                         break;
 156                 case 'n':
 157                         device_name = optarg;
 158                         break;
 159                 case 'o':
 160                         line = strtoul(optarg, NULL, 10);
 161                         break;
 162                 case 'd':
 163                         handleflags |= GPIOHANDLE_REQUEST_OPEN_DRAIN;
 164                         break;
 165                 case 's':
 166                         handleflags |= GPIOHANDLE_REQUEST_OPEN_SOURCE;
 167                         break;
 168                 case 'r':
 169                         eventflags |= GPIOEVENT_REQUEST_RISING_EDGE;
 170                         break;
 171                 case 'f':
 172                         eventflags |= GPIOEVENT_REQUEST_FALLING_EDGE;
 173                         break;
 174                 case '?':
 175                         print_usage();
 176                         return -1;
 177                 }
 178         }
 179 
 180         if (!device_name || line == -1) {
 181                 print_usage();
 182                 return -1;
 183         }
 184         if (!eventflags) {
 185                 printf("No flags specified, listening on both rising and "
 186                        "falling edges\n");
 187                 eventflags = GPIOEVENT_REQUEST_BOTH_EDGES;
 188         }
 189         return monitor_device(device_name, line, handleflags,
 190                               eventflags, loops);
 191 }

/* [<][>][^][v][top][bottom][index][help] */