Add README for the adventurous, allow evdev override from getenv().
[profile/ivi/wayland.git] / event-loop.c
1 #include <stddef.h>
2 #include <stdio.h>
3 #include <errno.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <sys/socket.h>
7 #include <sys/un.h>
8 #include <sys/epoll.h>
9 #include <unistd.h>
10 #include "wayland.h"
11
12 struct wl_event_loop {
13         int epoll_fd;
14         wl_event_loop_idle_func_t idle_func;
15         void *idle_data;
16 };
17
18 struct wl_event_source {
19         int fd;
20         wl_event_loop_fd_func_t func;
21         void *data;
22 };
23
24 struct wl_event_source *
25 wl_event_loop_add_fd(struct wl_event_loop *loop,
26                      int fd, uint32_t mask,
27                      wl_event_loop_fd_func_t func,
28                      void *data)
29 {
30         struct wl_event_source *source;
31         struct epoll_event ep;
32
33         source = malloc(sizeof *source);
34         if (source == NULL)
35                 return NULL;
36
37         source->fd = fd;
38         source->func = func;
39         source->data = data;
40
41         ep.events = 0;
42         if (mask & WL_EVENT_READABLE)
43                 ep.events |= EPOLLIN;
44         if (mask & WL_EVENT_WRITEABLE)
45                 ep.events |= EPOLLOUT;
46         ep.data.ptr = source;
47
48         if (epoll_ctl(loop->epoll_fd, EPOLL_CTL_ADD, fd, &ep) < 0) {
49                 free(source);
50                 return NULL;
51         }
52
53         return source;
54 }
55
56 struct wl_event_source idle_source;
57
58 int
59 wl_event_loop_remove_source(struct wl_event_loop *loop,
60                             struct wl_event_source *source)
61 {
62         int fd;
63
64         if (source == &idle_source) {
65                 loop->idle_func = NULL;
66                 return 0;
67         } else {
68                 fd = source->fd;
69                 free(source);
70                 return epoll_ctl(loop->epoll_fd,
71                                  EPOLL_CTL_DEL, fd, NULL);
72         };
73 }
74
75 int
76 wl_event_loop_update_source(struct wl_event_loop *loop,
77                             struct wl_event_source *source,
78                             uint32_t mask)
79 {
80         struct epoll_event ep;
81
82         ep.events = 0;
83         if (mask & WL_EVENT_READABLE)
84                 ep.events |= EPOLLIN;
85         if (mask & WL_EVENT_WRITEABLE)
86                 ep.events |= EPOLLOUT;
87         ep.data.ptr = source;
88
89         return epoll_ctl(loop->epoll_fd,
90                          EPOLL_CTL_MOD, source->fd, &ep);
91 }
92
93 struct wl_event_loop *
94 wl_event_loop_create(void)
95 {
96         struct wl_event_loop *loop;
97
98         loop = malloc(sizeof *loop);
99         if (loop == NULL)
100                 return NULL;
101
102         loop->epoll_fd = epoll_create(16);
103         if (loop->epoll_fd < 0) {
104                 free(loop);
105                 return NULL;
106         }
107
108         return loop;
109 }
110
111 void
112 wl_event_loop_destroy(struct wl_event_loop *loop)
113 {
114         close(loop->epoll_fd);
115         free(loop);
116 }
117
118 struct wl_event_source *
119 wl_event_loop_add_idle(struct wl_event_loop *loop,
120                        wl_event_loop_idle_func_t func,
121                        void *data)
122 {
123         loop->idle_func = func;
124         loop->idle_data = data;
125
126         return &idle_source;
127 }
128
129 #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
130
131 int
132 wl_event_loop_wait(struct wl_event_loop *loop)
133 {
134         struct epoll_event ep[32];
135         struct wl_event_source *source;
136         int i, count, timeout;
137         uint32_t mask;
138
139         if (loop->idle_func)
140                 timeout = 0;
141         else
142                 timeout = -1;
143
144         count = epoll_wait(loop->epoll_fd, ep, ARRAY_LENGTH(ep), timeout);
145         if (count < 0)
146                 return -1;
147
148         for (i = 0; i < count; i++) {
149                 source = ep[i].data.ptr;
150                 mask = 0;
151                 if (ep[i].events & EPOLLIN)
152                         mask |= WL_EVENT_READABLE;
153                 if (ep[i].events & EPOLLOUT)
154                         mask |= WL_EVENT_WRITEABLE;
155
156                 source->func(source->fd, mask, source->data);
157         }
158
159         if (count == 0 && loop->idle_func != NULL) {
160                 loop->idle_func(loop->idle_data);
161                 loop->idle_func = NULL;
162         }
163         
164         return 0;
165 }