From: Bartosz Golaszewski <brgl@bgdev.pl>
To: Kent Gibson <warthog618@gmail.com>,
Linus Walleij <linus.walleij@linaro.org>,
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: linux-gpio@vger.kernel.org,
Bartosz Golaszewski <bgolaszewski@baylibre.com>
Subject: [libgpiod][PATCH 2/7] core: provide functions for reading multiple line events at once
Date: Wed, 18 Dec 2019 15:24:44 +0100 [thread overview]
Message-ID: <20191218142449.10957-3-brgl@bgdev.pl> (raw)
In-Reply-To: <20191218142449.10957-1-brgl@bgdev.pl>
From: Bartosz Golaszewski <bgolaszewski@baylibre.com>
The kernel allows us to read multiple (up to 16) line events with
a single read() call, but up to this point libgpiod only supported
reading one event at a time. Add two new functions that allow users
to read more events at the same time.
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
include/gpiod.h | 25 ++++++++++++++++++++
lib/core.c | 61 ++++++++++++++++++++++++++++++++++++++++---------
2 files changed, 75 insertions(+), 11 deletions(-)
diff --git a/include/gpiod.h b/include/gpiod.h
index 0ecb804..b275f4a 100644
--- a/include/gpiod.h
+++ b/include/gpiod.h
@@ -1479,6 +1479,19 @@ int gpiod_line_event_wait_bulk(struct gpiod_line_bulk *bulk,
int gpiod_line_event_read(struct gpiod_line *line,
struct gpiod_line_event *event) GPIOD_API;
+/**
+ * @brief Read up to a certain number of events from the GPIO line.
+ * @param line GPIO line object.
+ * @param events Buffer to which the event data will be copied. Must hold at
+ * least the amount of events specified in num_events.
+ * @param num_events Specifies how many events can be stored in the buffer.
+ * @return On success returns the number of events stored in the buffer, on
+ * failure -1 is returned.
+ */
+int gpiod_line_event_read_multiple(struct gpiod_line *line,
+ struct gpiod_line_event *events,
+ unsigned int num_events) GPIOD_API;
+
/**
* @brief Get the event file descriptor.
* @param line GPIO line object.
@@ -1503,6 +1516,18 @@ int gpiod_line_event_get_fd(struct gpiod_line *line) GPIOD_API;
*/
int gpiod_line_event_read_fd(int fd, struct gpiod_line_event *event) GPIOD_API;
+/**
+ * @brief Read up to a certain number of events directly from a file descriptor.
+ * @param fd File descriptor.
+ * @param events Buffer to which the event data will be copied. Must hold at
+ * least the amount of events specified in num_events.
+ * @param num_events Specifies how many events can be stored in the buffer.
+ * @return On success returns the number of events stored in the buffer, on
+ * failure -1 is returned.
+ */
+int gpiod_line_event_read_fd_multiple(int fd, struct gpiod_line_event *events,
+ unsigned int num_events) GPIOD_API;
+
/**
* @}
*
diff --git a/lib/core.c b/lib/core.c
index 89f5465..8352e18 100644
--- a/lib/core.c
+++ b/lib/core.c
@@ -1009,6 +1009,19 @@ int gpiod_line_event_wait_bulk(struct gpiod_line_bulk *bulk,
int gpiod_line_event_read(struct gpiod_line *line,
struct gpiod_line_event *event)
+{
+ int ret;
+
+ ret = gpiod_line_event_read_multiple(line, event, 1);
+ if (ret < 0)
+ return -1;
+
+ return 0;
+}
+
+int gpiod_line_event_read_multiple(struct gpiod_line *line,
+ struct gpiod_line_event *events,
+ unsigned int num_events)
{
int fd;
@@ -1016,7 +1029,7 @@ int gpiod_line_event_read(struct gpiod_line *line,
if (fd < 0)
return -1;
- return gpiod_line_event_read_fd(fd, event);
+ return gpiod_line_event_read_fd_multiple(fd, events, num_events);
}
int gpiod_line_event_get_fd(struct gpiod_line *line)
@@ -1031,25 +1044,51 @@ int gpiod_line_event_get_fd(struct gpiod_line *line)
int gpiod_line_event_read_fd(int fd, struct gpiod_line_event *event)
{
- struct gpioevent_data evdata;
+ int ret;
+
+ ret = gpiod_line_event_read_fd_multiple(fd, event, 1);
+ if (ret < 0)
+ return -1;
+
+ return 0;
+}
+
+int gpiod_line_event_read_fd_multiple(int fd, struct gpiod_line_event *events,
+ unsigned int num_events)
+{
+ /*
+ * 16 is the maximum number of events the kernel can store in the FIFO
+ * so we can allocate the buffer on the stack.
+ */
+ struct gpioevent_data evdata[16], *curr;
+ struct gpiod_line_event *event;
+ unsigned int events_read, i;
ssize_t rd;
- memset(&evdata, 0, sizeof(evdata));
+ memset(evdata, 0, sizeof(evdata));
- rd = read(fd, &evdata, sizeof(evdata));
+ rd = read(fd, evdata, sizeof(evdata));
if (rd < 0) {
return -1;
- } else if (rd != sizeof(evdata)) {
+ } else if ((unsigned int)rd < sizeof(*evdata)) {
errno = EIO;
return -1;
}
- event->event_type = evdata.id == GPIOEVENT_EVENT_RISING_EDGE
- ? GPIOD_LINE_EVENT_RISING_EDGE
- : GPIOD_LINE_EVENT_FALLING_EDGE;
+ events_read = rd / sizeof(*evdata);
+ if (events_read < num_events)
+ num_events = events_read;
- event->ts.tv_sec = evdata.timestamp / 1000000000ULL;
- event->ts.tv_nsec = evdata.timestamp % 1000000000ULL;
+ for (i = 0; i < num_events; i++) {
+ curr = &evdata[i];
+ event = &events[i];
- return 0;
+ event->event_type = curr->id == GPIOEVENT_EVENT_RISING_EDGE
+ ? GPIOD_LINE_EVENT_RISING_EDGE
+ : GPIOD_LINE_EVENT_FALLING_EDGE;
+ event->ts.tv_sec = curr->timestamp / 1000000000ULL;
+ event->ts.tv_nsec = curr->timestamp % 1000000000ULL;
+ }
+
+ return i;
}
--
2.23.0
next prev parent reply other threads:[~2019-12-18 14:25 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-12-18 14:24 [libgpiod][PATCH 0/7] teach libgpiod to read multiple line events at once Bartosz Golaszewski
2019-12-18 14:24 ` [libgpiod][PATCH 1/7] core: use gpiod_line_event_get_fd() in gpiod_line_event_read() Bartosz Golaszewski
2019-12-18 14:24 ` Bartosz Golaszewski [this message]
2019-12-18 14:24 ` [libgpiod][PATCH 3/7] tests: event: extend test coverage for reading multiple line events at once Bartosz Golaszewski
2019-12-19 13:35 ` Kent Gibson
2019-12-19 13:48 ` Bartosz Golaszewski
2019-12-19 14:05 ` Kent Gibson
2019-12-19 14:07 ` Bartosz Golaszewski
2019-12-19 14:36 ` Kent Gibson
2019-12-19 16:19 ` Bartosz Golaszewski
2019-12-24 12:11 ` Bartosz Golaszewski
2019-12-18 14:24 ` [libgpiod][PATCH 4/7] bindings: cxx: provide a method for reading multiple line events Bartosz Golaszewski
2019-12-18 14:24 ` [libgpiod][PATCH 5/7] bindings: cxx: tests: add a test-case " Bartosz Golaszewski
2019-12-18 14:24 ` [libgpiod][PATCH 6/7] bindings: python: add a method " Bartosz Golaszewski
2019-12-18 14:24 ` [libgpiod][PATCH 7/7] bindings: python: tests: add a test-case " Bartosz Golaszewski
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20191218142449.10957-3-brgl@bgdev.pl \
--to=brgl@bgdev.pl \
--cc=andriy.shevchenko@linux.intel.com \
--cc=bgolaszewski@baylibre.com \
--cc=linus.walleij@linaro.org \
--cc=linux-gpio@vger.kernel.org \
--cc=warthog618@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.