lkml.org 
[lkml]   [2019]   [Dec]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v2 11/11] tools: gpio: implement gpio-watch
    Date
    From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

    Add a simple program that allows to test the new LINECHANGED_FD ioctl().

    Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
    ---
    tools/gpio/.gitignore | 1 +
    tools/gpio/Build | 1 +
    tools/gpio/Makefile | 11 +++-
    tools/gpio/gpio-watch.c | 112 ++++++++++++++++++++++++++++++++++++++++
    4 files changed, 124 insertions(+), 1 deletion(-)
    create mode 100644 tools/gpio/gpio-watch.c

    diff --git a/tools/gpio/.gitignore b/tools/gpio/.gitignore
    index a94c0e83b209..fffd32969d62 100644
    --- a/tools/gpio/.gitignore
    +++ b/tools/gpio/.gitignore
    @@ -1,4 +1,5 @@
    gpio-event-mon
    gpio-hammer
    lsgpio
    +gpio-watch
    include/linux/gpio.h
    diff --git a/tools/gpio/Build b/tools/gpio/Build
    index 4141f35837db..67c7b7f6a717 100644
    --- a/tools/gpio/Build
    +++ b/tools/gpio/Build
    @@ -2,3 +2,4 @@ gpio-utils-y += gpio-utils.o
    lsgpio-y += lsgpio.o gpio-utils.o
    gpio-hammer-y += gpio-hammer.o gpio-utils.o
    gpio-event-mon-y += gpio-event-mon.o gpio-utils.o
    +gpio-watch-y += gpio-watch.o
    diff --git a/tools/gpio/Makefile b/tools/gpio/Makefile
    index 6080de58861f..842287e42c83 100644
    --- a/tools/gpio/Makefile
    +++ b/tools/gpio/Makefile
    @@ -18,7 +18,7 @@ MAKEFLAGS += -r

    override CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include

    -ALL_TARGETS := lsgpio gpio-hammer gpio-event-mon
    +ALL_TARGETS := lsgpio gpio-hammer gpio-event-mon gpio-watch
    ALL_PROGRAMS := $(patsubst %,$(OUTPUT)%,$(ALL_TARGETS))

    all: $(ALL_PROGRAMS)
    @@ -66,6 +66,15 @@ $(GPIO_EVENT_MON_IN): prepare FORCE $(OUTPUT)gpio-utils-in.o
    $(OUTPUT)gpio-event-mon: $(GPIO_EVENT_MON_IN)
    $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@

    +#
    +# gpio-watch
    +#
    +GPIO_WATCH_IN := $(OUTPUT)gpio-watch-in.o
    +$(GPIO_WATCH_IN): prepare FORCE
    + $(Q)$(MAKE) $(build)=gpio-watch
    +$(OUTPUT)gpio-watch: $(GPIO_WATCH_IN)
    + $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
    +
    clean:
    rm -f $(ALL_PROGRAMS)
    rm -f $(OUTPUT)include/linux/gpio.h
    diff --git a/tools/gpio/gpio-watch.c b/tools/gpio/gpio-watch.c
    new file mode 100644
    index 000000000000..69aee43655ae
    --- /dev/null
    +++ b/tools/gpio/gpio-watch.c
    @@ -0,0 +1,112 @@
    +// SPDX-License-Identifier: GPL-2.0-only
    +/*
    + * gpio-watch - monitor unrequested lines for property changes using the
    + * character device
    + *
    + * Copyright (C) 2019 BayLibre SAS
    + * Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>
    + */
    +
    +#include <ctype.h>
    +#include <errno.h>
    +#include <fcntl.h>
    +#include <linux/gpio.h>
    +#include <poll.h>
    +#include <stdbool.h>
    +#include <stdio.h>
    +#include <stdlib.h>
    +#include <string.h>
    +#include <sys/ioctl.h>
    +#include <unistd.h>
    +
    +static bool isnumber(const char *str)
    +{
    + size_t sz = strlen(str);
    + int i;
    +
    + for (i = 0; i < sz; i++) {
    + if (!isdigit(str[i]))
    + return false;
    + }
    +
    + return true;
    +}
    +
    +int main(int argc, char **argv)
    +{
    + struct gpioline_info_changed chg;
    + struct gpioline_info req;
    + struct pollfd pfd;
    + int fd, i, j, ret;
    + char *event;
    + ssize_t rd;
    +
    + if (argc < 3)
    + goto err_usage;
    +
    + fd = open(argv[1], O_RDWR | O_CLOEXEC);
    + if (fd < 0) {
    + perror("unable to open gpiochip");
    + return EXIT_FAILURE;
    + }
    +
    + for (i = 0, j = 2; i < argc - 2; i++, j++) {
    + if (!isnumber(argv[j]))
    + goto err_usage;
    +
    + memset(&req, 0, sizeof(req));
    + req.line_offset = atoi(argv[j]);
    +
    + ret = ioctl(fd, GPIO_GET_LINEINFO_WATCH_IOCTL, &req);
    + if (ret) {
    + perror("unable to set up line watch");
    + return EXIT_FAILURE;
    + }
    + }
    +
    + pfd.fd = fd;
    + pfd.events = POLLIN | POLLPRI;
    +
    + for (;;) {
    + ret = poll(&pfd, 1, 5000);
    + if (ret < 0) {
    + perror("error polling the linechanged fd");
    + return EXIT_FAILURE;
    + } else if (ret > 0) {
    + memset(&chg, 0, sizeof(chg));
    + rd = read(pfd.fd, &chg, sizeof(chg));
    + if (rd < 0 || rd != sizeof(chg)) {
    + if (rd != sizeof(chg))
    + errno = EIO;
    +
    + perror("error reading line change event");
    + return EXIT_FAILURE;
    + }
    +
    + switch (chg.event_type) {
    + case GPIOLINE_CHANGED_REQUESTED:
    + event = "requested";
    + break;
    + case GPIOLINE_CHANGED_RELEASED:
    + event = "released";
    + break;
    + case GPIOLINE_CHANGED_CONFIG:
    + event = "config changed";
    + break;
    + default:
    + fprintf(stderr,
    + "invalid event type received from the kernel\n");
    + return EXIT_FAILURE;
    + }
    +
    + printf("line %u: %s at %llu\n",
    + chg.info.line_offset, event, chg.timestamp);
    + }
    + }
    +
    + return 0;
    +
    +err_usage:
    + printf("%s: <gpiochip> <line0> <line1> ...\n", argv[0]);
    + return EXIT_FAILURE;
    +}
    --
    2.23.0
    \
     
     \ /
      Last update: 2019-12-04 17:00    [W:3.036 / U:0.240 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site