mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2024-12-29 17:22:07 +00:00
tools: gpio: implement gpio-watch
Add a simple program that allows to test the new LINECHANGED_FD ioctl(). Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
This commit is contained in:
parent
51c1064e82
commit
33f0c47b8f
1
tools/gpio/.gitignore
vendored
1
tools/gpio/.gitignore
vendored
@ -1,4 +1,5 @@
|
|||||||
gpio-event-mon
|
gpio-event-mon
|
||||||
gpio-hammer
|
gpio-hammer
|
||||||
|
gpio-watch
|
||||||
lsgpio
|
lsgpio
|
||||||
include/linux/gpio.h
|
include/linux/gpio.h
|
||||||
|
@ -2,3 +2,4 @@ gpio-utils-y += gpio-utils.o
|
|||||||
lsgpio-y += lsgpio.o gpio-utils.o
|
lsgpio-y += lsgpio.o gpio-utils.o
|
||||||
gpio-hammer-y += gpio-hammer.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-event-mon-y += gpio-event-mon.o gpio-utils.o
|
||||||
|
gpio-watch-y += gpio-watch.o
|
||||||
|
@ -18,7 +18,7 @@ MAKEFLAGS += -r
|
|||||||
|
|
||||||
override CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include
|
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_PROGRAMS := $(patsubst %,$(OUTPUT)%,$(ALL_TARGETS))
|
||||||
|
|
||||||
all: $(ALL_PROGRAMS)
|
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)
|
$(OUTPUT)gpio-event-mon: $(GPIO_EVENT_MON_IN)
|
||||||
$(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
|
$(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:
|
clean:
|
||||||
rm -f $(ALL_PROGRAMS)
|
rm -f $(ALL_PROGRAMS)
|
||||||
rm -f $(OUTPUT)include/linux/gpio.h
|
rm -f $(OUTPUT)include/linux/gpio.h
|
||||||
|
99
tools/gpio/gpio-watch.c
Normal file
99
tools/gpio/gpio-watch.c
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
// 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>
|
||||||
|
|
||||||
|
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, *end;
|
||||||
|
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++) {
|
||||||
|
memset(&req, 0, sizeof(req));
|
||||||
|
|
||||||
|
req.line_offset = strtoul(argv[j], &end, 0);
|
||||||
|
if (*end != '\0')
|
||||||
|
goto err_usage;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user