gpiomon: new options
authorBartosz Golaszewski <bartekgola@gmail.com>
Tue, 17 Jan 2017 15:51:11 +0000 (16:51 +0100)
committerBartosz Golaszewski <bartekgola@gmail.com>
Tue, 17 Jan 2017 15:55:19 +0000 (16:55 +0100)
Add new options to gpiomon:
  - allow to specify the number of events after which the program
    should exit
  - allow to silence the output
  - allow to only monitor certain types of events

Signed-off-by: Bartosz Golaszewski <bartekgola@gmail.com>
src/tools/gpiomon.c

index ff78b6d48a675d4c96940677bd3ee3d100b90abb..c8157cc02d538c98e481aada9a3dcf74503585c2 100644 (file)
 #include <signal.h>
 
 static const struct option longopts[] = {
-       { "help",       no_argument,    NULL,   'h' },
-       { "version",    no_argument,    NULL,   'v' },
-       { "active-low", no_argument,    NULL,   'l' },
+       { "help",               no_argument,            NULL,   'h' },
+       { "version",            no_argument,            NULL,   'v' },
+       { "active-low",         no_argument,            NULL,   'l' },
+       { "num-events",         required_argument,      NULL,   'n' },
+       { "silent",             no_argument,            NULL,   's' },
+       { "rising-edge",        no_argument,            NULL,   'r' },
+       { "falling-edge",       no_argument,            NULL,   'f' },
        { 0 },
 };
 
-static const char *const shortopts = "+hvl";
+static const char *const shortopts = "+hvln:rf";
 
 static void print_help(void)
 {
@@ -34,6 +38,10 @@ static void print_help(void)
        printf("  -h, --help:\t\tdisplay this message and exit\n");
        printf("  -v, --version:\tdisplay the version and exit\n");
        printf("  -l, --active-low:\tset the line active state to low\n");
+       printf("  -n, --num-events=NUM:\texit after processing NUM events\n");
+       printf("  -s, --silent:\t\tdon't print event info\n");
+       printf("  -r, --rising-edge:\tonly process rising edge events\n");
+       printf("  -f, --falling-edge:\tonly process falling edge events\n");
 }
 
 static volatile bool do_run = true;
@@ -43,26 +51,44 @@ static void sighandler(int signum UNUSED)
        do_run = false;
 }
 
-static int event_callback(int type, const struct timespec *ts,
-                         void *data UNUSED)
+struct callback_data {
+       unsigned int num_events_wanted;
+       unsigned int num_events_done;
+       bool silent;
+       bool watch_rising;
+       bool watch_falling;
+};
+
+static int event_callback(int type, const struct timespec *ts, void *data)
 {
+       struct callback_data *cbdata = data;
        const char *evname = NULL;
 
        switch (type) {
        case GPIOD_EVENT_CB_RISING_EDGE:
-               evname = " RISING EDGE";
+               if (cbdata->watch_rising) {
+                       evname = " RISING EDGE";
+                       cbdata->num_events_done++;
+               }
                break;
        case GPIOD_EVENT_CB_FALLING_EDGE:
-               evname = "FALLING_EDGE";
+               if (cbdata->watch_falling) {
+                       evname = "FALLING_EDGE";
+                       cbdata->num_events_done++;
+               }
                break;
        default:
                break;
        }
 
-       if (evname)
+       if (evname && !cbdata->silent)
                printf("GPIO EVENT: %s [%8ld.%09ld]\n",
                       evname, ts->tv_sec, ts->tv_nsec);
 
+       if (cbdata->num_events_wanted &&
+           cbdata->num_events_done >= cbdata->num_events_wanted)
+               do_run = false;
+
        if (!do_run)
                return GPIOD_EVENT_CB_STOP;
 
@@ -71,6 +97,7 @@ static int event_callback(int type, const struct timespec *ts,
 
 int main(int argc, char **argv)
 {
+       struct callback_data cbdata;
        bool active_low = false;
        struct timespec timeout;
        int optc, opti, status;
@@ -79,6 +106,8 @@ int main(int argc, char **argv)
 
        set_progname(argv[0]);
 
+       memset(&cbdata, 0, sizeof(cbdata));
+
        for (;;) {
                optc = getopt_long(argc, argv, shortopts, longopts, &opti);
                if (optc < 0)
@@ -94,6 +123,20 @@ int main(int argc, char **argv)
                case 'l':
                        active_low = true;
                        break;
+               case 'n':
+                       cbdata.num_events_wanted = strtoul(optarg, &end, 10);
+                       if (*end != '\0')
+                               die("invalid number: %s", optarg);
+                       break;
+               case 's':
+                       cbdata.silent = true;
+                       break;
+               case 'r':
+                       cbdata.watch_rising = true;
+                       break;
+               case 'f':
+                       cbdata.watch_falling = true;
+                       break;
                case '?':
                        die("try %s --help", get_progname());
                default:
@@ -101,6 +144,9 @@ int main(int argc, char **argv)
                }
        }
 
+       if (!cbdata.watch_rising && !cbdata.watch_falling)
+               cbdata.watch_rising = cbdata.watch_falling = true;
+
        argc -= optind;
        argv += optind;
 
@@ -122,7 +168,7 @@ int main(int argc, char **argv)
        signal(SIGTERM, sighandler);
 
        status = gpiod_simple_event_loop("gpiomon", device, offset, active_low,
-                                        &timeout, event_callback, NULL);
+                                        &timeout, event_callback, &cbdata);
        if (status < 0)
                die_perror("error waiting for events");