]> git.itanic.dy.fi Git - log-plotter/blob - event.c
data.c: Implement initial support for handling multiple data channels
[log-plotter] / event.c
1 #include <errno.h>
2 #include <sys/epoll.h>
3
4 #include "event.h"
5 #include "trace.h"
6
7 static int epoll_fd = -1;
8
9 static int init_event_handler(void)
10 {
11         epoll_fd = epoll_create(1);
12         if (epoll_fd < 0) {
13                 pr_err("Failed to create epoll socket: %m\n");
14                 return -1;
15         }
16
17         return 0;
18 }
19
20 int register_event_handler(struct eventhandler_entry *handler)
21 {
22         struct epoll_event ev;
23         int ret = 0;
24
25         if (epoll_fd < 0)
26                 ret = init_event_handler();
27
28         if (ret < 0)
29                 return ret;
30
31         if (handler->fd < 0) {
32                 pr_err("Invalid file descriptor of %d for handler %s\n",
33                         handler->fd, handler->name);
34                 return -1;
35         }
36
37         if (!handler->handle_event) {
38                 pr_err("Handler %s missing callback function\n", handler->name);
39                 return -1;
40         }
41
42         pr_debug("Registering handler for \"%s\", fd=%d\n",
43                 handler->name, handler->fd);
44
45         ev.data.fd = handler->fd;
46         ev.data.ptr = handler;
47         ev.events = handler->events;
48         ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, handler->fd, &ev);
49         if (ret) {
50                 pr_err("Failed to add epoll_fd: %m\n");
51                 return -1;
52         }
53
54         return 0;
55 }
56
57 int poll_events(int timeout_ms)
58 {
59         struct epoll_event event;
60         struct eventhandler_entry *handler;
61         int ret;
62
63         ret = epoll_wait(epoll_fd, &event, 1, timeout_ms);
64
65         if (ret == -1) {
66                 if (errno != EINTR) {
67                         pr_err("epoll_wait: %m\n");
68                         return -1;
69                 }
70
71                 /*
72                  * If epoll_wait() was interrupted, better start
73                  * everything again from the beginning
74                  */
75                 return 0;
76         }
77
78         if (ret == 0) {
79                 pr_info("Timed out\n");
80                 goto out;
81         }
82
83         handler = event.data.ptr;
84
85         if (!handler || !handler->handle_event) {
86                 pr_err("Corrupted event handler for fd %d\n",
87                         event.data.fd);
88                 goto out;
89         }
90
91         pr_debug("Running handler %s to handle events from fd %d\n",
92                 handler->name, handler->fd);
93         handler->handle_event(handler);
94
95 out:
96         return ret;
97 }
98