summaryrefslogtreecommitdiff
path: root/events.c
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2012-02-22 23:27:15 +0100
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2012-04-16 23:40:56 +0200
commit211507d598b67e6e274275ab472d5e81ec1afcec (patch)
tree47d4ba219c740b85dd563e312083f2787016d0ec /events.c
parent4dd4dcb4f594c872df222390031975d06adc7e71 (diff)
Factor event handling code out into events.c
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Diffstat (limited to 'events.c')
-rw-r--r--events.c175
1 files changed, 175 insertions, 0 deletions
diff --git a/events.c b/events.c
new file mode 100644
index 0000000..461e641
--- /dev/null
+++ b/events.c
@@ -0,0 +1,175 @@
+/*
+ * OMAP3 generic events handling
+ *
+ * Copyright (C) 2010-2012 Ideas on board SPRL
+ *
+ * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#define _BSD_SOURCE
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/select.h>
+
+#include "isp/list.h"
+#include "isp/omap3isp.h"
+#include "isp/tools.h"
+
+#include "events.h"
+
+#define SELECT_TIMEOUT 2000 /* in milliseconds */
+
+struct event_fd {
+ struct list_entry list;
+
+ int fd;
+ enum omap3_isp_event_type type;
+ void (*callback)(void *priv);
+ void *priv;
+};
+
+void events_watch_fd(struct events *events, int fd,
+ enum omap3_isp_event_type type,
+ void(*callback)(void *), void *priv)
+{
+ struct event_fd *event;
+
+ event = malloc(sizeof *event);
+ if (event == NULL)
+ return;
+
+ event->fd = fd;
+ event->type = type;
+ event->callback = callback;
+ event->priv = priv;
+
+ switch (event->type) {
+ case OMAP3_ISP_EVENT_READ:
+ FD_SET(fd, &events->rfds);
+ break;
+ case OMAP3_ISP_EVENT_WRITE:
+ FD_SET(fd, &events->wfds);
+ break;
+ }
+
+ events->maxfd = max(events->maxfd, fd);
+
+ list_append(&event->list, &events->events);
+}
+
+void events_unwatch_fd(struct events *events, int fd)
+{
+ struct event_fd *event = NULL;
+ struct event_fd *entry;
+ int maxfd = 0;
+
+ list_for_each_entry(entry, &events->events, list) {
+ if (entry->fd == fd)
+ event = entry;
+ else
+ maxfd = max(maxfd, entry->fd);
+ }
+
+ if (event == NULL)
+ return;
+
+ switch (event->type) {
+ case OMAP3_ISP_EVENT_READ:
+ FD_CLR(fd, &events->rfds);
+ break;
+ case OMAP3_ISP_EVENT_WRITE:
+ FD_CLR(fd, &events->wfds);
+ break;
+ }
+
+ events->maxfd = maxfd;
+
+ list_remove(&event->list);
+ free(event);
+}
+
+static void events_dispatch(struct events *events, const fd_set *rfds,
+ const fd_set *wfds)
+{
+ struct event_fd *event;
+
+ list_for_each_entry(event, &events->events, list) {
+ if (event->type == OMAP3_ISP_EVENT_READ &&
+ FD_ISSET(event->fd, rfds))
+ event->callback(event->priv);
+ if (event->type == OMAP3_ISP_EVENT_WRITE &&
+ FD_ISSET(event->fd, wfds))
+ event->callback(event->priv);
+ }
+}
+
+bool events_loop(struct events *events)
+{
+ while (!events->done) {
+ struct timeval timeout;
+ fd_set rfds;
+ fd_set wfds;
+ int ret;
+
+ timeout.tv_sec = SELECT_TIMEOUT / 1000;
+ timeout.tv_usec = (SELECT_TIMEOUT % 1000) * 1000;
+ rfds = events->rfds;
+ wfds = events->wfds;
+
+ ret = select(events->maxfd + 1, &rfds, &wfds, NULL, &timeout);
+ if (ret < 0) {
+ /* EINTR means that a signal has been received, continue
+ * to the next iteration in that case.
+ */
+ if (errno == EINTR)
+ continue;
+
+ printf("error: select failed with %d\n", errno);
+ break;
+ }
+ if (ret == 0) {
+ /* select() should never time out as the ISP is supposed
+ * to capture images continuously. A timeout is thus
+ * considered as a fatal error.
+ */
+ printf("error: select timeout\n");
+ break;
+ }
+
+ events_dispatch(events, &rfds, &wfds);
+ }
+
+ return !events->done;
+}
+
+void events_stop(struct events *events)
+{
+ events->done = true;
+}
+
+void events_init(struct events *events)
+{
+ memset(events, 0, sizeof *events);
+
+ FD_ZERO(&events->rfds);
+ FD_ZERO(&events->wfds);
+ events->maxfd = 0;
+ list_init(&events->events);
+}