śr., 4 gru 2019 o 23:42 Andy Shevchenko <andy.shevchenko@xxxxxxxxx> napisał(a): > > On Wed, Dec 4, 2019 at 7:19 PM Bartosz Golaszewski <brgl@xxxxxxxx> wrote: > > Add a simple program that allows to test the new LINECHANGED_FD ioctl(). > > > --- a/tools/gpio/.gitignore > > +++ b/tools/gpio/.gitignore > > @@ -1,4 +1,5 @@ > > gpio-event-mon > > gpio-hammer > > lsgpio > > +gpio-watch > > Perhaps keep it sorted? > Sure I can do this. > > +++ 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@xxxxxxxxxxxx> > > + */ > > + > > +#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; > > +} > > strtoul() will do the same. > > char *p; > unsigned long dummy; // do we need it? > dummy = strtoul(..., &p); > return *p == '\0'; Yeah strtoul does allow for error checking. I'll change this in v3. > > > +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]); > > Oh, why not to call strtoul() directly? > > > + > > + ret = ioctl(fd, GPIO_GET_LINEINFO_WATCH_IOCTL, &req); > > + if (ret) { > > + perror("unable to set up line watch"); > > Don't you need to unwatch previously added ones? Nah, we're exiting anyway, the fd will be released. > > > + return EXIT_FAILURE; > > + } > > + } > > > + 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; > > + } > > Shouldn't we handle the -EINTR? Indeed we should. Will fix. Bart > > > + } > > + } > > + > > + return 0; > > > -- > With Best Regards, > Andy Shevchenko