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.
*/
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;
+
/**
* @}
*
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;
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)
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;
}