1 /**************************************************************************
5 Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved.
7 Contact: Eunchul Kim <chulspro.kim@samsung.com>,
8 JinYoung Jeon <jy0.jeon@samsung.com>,
9 Taeheon Kim <th908.kim@samsung.com>,
10 YoungJun Cho <yj44.cho@samsung.com>,
11 SooChan Lim <sc1.lim@samsung.com>,
12 Boram Park <sc1.lim@samsung.com>
14 Permission is hereby granted, free of charge, to any person obtaining a
15 copy of this software and associated documentation files (the
16 "Software"), to deal in the Software without restriction, including
17 without limitation the rights to use, copy, modify, merge, publish,
18 distribute, sub license, and/or sell copies of the Software, and to
19 permit persons to whom the Software is furnished to do so, subject to
20 the following conditions:
22 The above copyright notice and this permission notice (including the
23 next paragraph) shall be included in all copies or substantial portions
26 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
27 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
29 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
30 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
31 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
32 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 **************************************************************************/
41 #include "tdm_private.h"
44 #include <wayland-server-core.h>
46 struct _tdm_private_event {
47 struct wl_display *wl_display;
48 struct wl_event_loop *event_loop;
51 tdm_event_source *backend_source;
53 struct wl_display *wl_display2;
54 struct wl_event_loop *event_loop2;
57 typedef struct _tdm_event_source_base
59 struct wl_event_source *wl_source;
60 } tdm_event_source_base;
62 typedef struct _tdm_event_source_fd
64 tdm_event_source_base base;
65 tdm_private_display *private_display;
66 tdm_event_fd_handler func;
68 } tdm_event_source_fd;
70 typedef struct _tdm_event_source_timer
72 tdm_event_source_base base;
73 tdm_private_display *private_display;
74 tdm_event_timer_handler func;
76 } tdm_event_source_timer;
79 _tdm_event_main_fd_handler(int fd, tdm_event_mask mask, void *user_data)
81 tdm_private_display *private_display = (tdm_private_display*)user_data;
82 tdm_private_event *private_event;
83 tdm_func_display *func_display;
85 TDM_RETURN_VAL_IF_FAIL(private_display != NULL, TDM_ERROR_OPERATION_FAILED);
86 TDM_RETURN_VAL_IF_FAIL(private_display->private_event != NULL, TDM_ERROR_OPERATION_FAILED);
88 private_event = private_display->private_event;
91 TDM_INFO("backend fd(%d) event happens", private_event->backend_fd);
93 func_display = &private_display->func_display;
94 if (!func_display->display_handle_events)
95 return TDM_ERROR_NONE;
97 return func_display->display_handle_events(private_display->bdata);
101 tdm_event_init(tdm_private_display *private_display)
103 tdm_private_event *private_event;
105 if (private_display->private_event)
106 return TDM_ERROR_NONE;
108 private_event = calloc(1, sizeof *private_event);
109 if (!private_event) {
110 TDM_ERR("alloc failed");
111 return TDM_ERROR_OUT_OF_MEMORY;
114 private_event->backend_fd = -1;
116 private_event->wl_display = wl_display_create();
117 if (!private_event->wl_display) {
118 TDM_ERR("creating a wayland display failed");
120 return TDM_ERROR_OUT_OF_MEMORY;
123 private_event->event_loop = wl_display_get_event_loop(private_event->wl_display);
124 if (!private_event->event_loop) {
125 TDM_ERR("no event loop");
126 wl_display_destroy(private_event->wl_display);
128 return TDM_ERROR_OUT_OF_MEMORY;
131 TDM_INFO("event loop fd(%d)", wl_event_loop_get_fd(private_event->event_loop));
133 private_event->wl_display2 = wl_display_create();
134 if (!private_event->wl_display2) {
135 TDM_ERR("creating a wayland display2 failed");
136 return TDM_ERROR_OUT_OF_MEMORY;
139 private_event->event_loop2 = wl_display_get_event_loop(private_event->wl_display2);
140 if (!private_event->event_loop2) {
141 TDM_ERR("no event loop2");
142 wl_display_destroy(private_event->wl_display2);
143 private_event->wl_display2 = NULL;
144 return TDM_ERROR_OUT_OF_MEMORY;
147 private_display->private_event = private_event;
149 return TDM_ERROR_NONE;
153 tdm_event_deinit(tdm_private_display *private_display)
155 if (!private_display->private_event)
158 if (private_display->private_event->backend_source)
159 tdm_event_source_remove(private_display->private_event->backend_source);
161 if (private_display->private_event->wl_display)
162 wl_display_destroy(private_display->private_event->wl_display);
164 free(private_display->private_event);
165 private_display->private_event = NULL;
169 tdm_event_create_backend_source(tdm_private_display *private_display)
171 tdm_private_event *private_event = private_display->private_event;
172 tdm_func_display *func_display;
176 TDM_RETURN_IF_FAIL(private_event != NULL);
178 func_display = &private_display->func_display;
179 if (!func_display->display_get_fd) {
180 TDM_INFO("TDM backend module won't offer a display fd");
184 ret = func_display->display_get_fd(private_display->bdata, &fd);
186 TDM_WRN("TDM backend module returns fd(%d)", fd);
190 if (!func_display->display_handle_events) {
191 TDM_ERR("no display_handle_events function");
195 private_event->backend_source =
196 tdm_event_add_fd_handler(private_display, fd, TDM_EVENT_READABLE,
197 _tdm_event_main_fd_handler, private_display,
199 if (!private_event->backend_source) {
200 TDM_ERR("no backend fd(%d) source", fd);
204 private_event->backend_fd = fd;
206 TDM_INFO("backend fd(%d) source created", private_event->backend_fd);
210 tdm_event_get_fd(tdm_private_display *private_display)
212 tdm_private_event *private_event = private_display->private_event;
214 TDM_RETURN_VAL_IF_FAIL(private_event->event_loop != NULL, -1);
216 return wl_event_loop_get_fd(private_event->event_loop);
220 tdm_event_dispatch(tdm_private_display *private_display)
222 tdm_private_event *private_event = private_display->private_event;
224 TDM_RETURN_VAL_IF_FAIL(private_event->event_loop != NULL, TDM_ERROR_OPERATION_FAILED);
226 if (tdm_debug_thread)
227 TDM_INFO("dispatch");
229 /* Don't set timeout to -1. It can make deadblock by two mutex locks.
230 * If need to set -1, use poll() and call tdm_event_dispatch() after
233 if (wl_event_loop_dispatch(private_event->event_loop, 0) < 0)
234 TDM_ERR("dispatch failed");
236 return TDM_ERROR_NONE;
240 tdm_event_add_socket(tdm_private_display *private_display, const char *name)
242 tdm_private_event *private_event = private_display->private_event;
244 TDM_RETURN_VAL_IF_FAIL(private_event->wl_display != NULL, TDM_ERROR_OPERATION_FAILED);
246 if (wl_display_add_socket(private_event->wl_display, name) < 0) {
247 TDM_ERR("add socket(\"%s\") failed", name);
248 return TDM_ERROR_OPERATION_FAILED;
251 return TDM_ERROR_NONE;
255 _tdm_event_loop_fd_func(int fd, uint32_t wl_mask, void *data)
257 tdm_event_source_fd *fd_source = (tdm_event_source_fd*)data;
258 tdm_event_mask mask = 0;
260 TDM_RETURN_VAL_IF_FAIL(fd_source, 1);
261 TDM_RETURN_VAL_IF_FAIL(fd_source->func, 1);
263 if (wl_mask & WL_EVENT_READABLE)
264 mask |= TDM_EVENT_READABLE;
265 if (wl_mask & WL_EVENT_WRITABLE)
266 mask |= TDM_EVENT_WRITABLE;
267 if (wl_mask & WL_EVENT_HANGUP)
268 mask |= TDM_EVENT_HANGUP;
269 if (wl_mask & WL_EVENT_ERROR)
270 mask |= TDM_EVENT_ERROR;
272 fd_source->func(fd, mask, fd_source->user_data);
277 EXTERN tdm_event_source*
278 tdm_event_add_fd_handler(tdm_display *dpy, int fd, tdm_event_mask mask,
279 tdm_event_fd_handler func, void *user_data,
282 tdm_private_display *private_display;
283 tdm_private_event *private_event;
284 tdm_event_source_fd *fd_source;
285 uint32_t wl_mask = 0;
288 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(dpy, TDM_ERROR_INVALID_PARAMETER, NULL);
289 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(fd >= 0, TDM_ERROR_INVALID_PARAMETER, NULL);
290 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(func, TDM_ERROR_INVALID_PARAMETER, NULL);
292 private_display = (tdm_private_display*)dpy;
293 private_event = private_display->private_event;
294 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_event, TDM_ERROR_INVALID_PARAMETER, NULL);
295 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_event->event_loop, TDM_ERROR_INVALID_PARAMETER, NULL);
297 fd_source = calloc(1, sizeof(tdm_event_source_fd));
298 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(fd_source, TDM_ERROR_OUT_OF_MEMORY, NULL);
300 if (mask & TDM_EVENT_READABLE)
301 wl_mask |= WL_EVENT_READABLE;
302 if (mask & TDM_EVENT_WRITABLE)
303 wl_mask |= WL_EVENT_WRITABLE;
305 fd_source->base.wl_source =
306 wl_event_loop_add_fd(private_event->event_loop,
307 fd, wl_mask, _tdm_event_loop_fd_func, fd_source);
308 if (!fd_source->base.wl_source) {
310 *error = TDM_ERROR_OUT_OF_MEMORY;
315 fd_source->private_display = private_display;
316 fd_source->func = func;
317 fd_source->user_data = user_data;
320 *error = TDM_ERROR_NONE;
322 return (tdm_event_source*)fd_source;
326 tdm_event_source_fd_update(tdm_event_source *source, tdm_event_mask mask)
328 tdm_event_source_fd *fd_source = source;
329 uint32_t wl_mask = 0;
331 TDM_RETURN_VAL_IF_FAIL(fd_source, TDM_ERROR_INVALID_PARAMETER);
333 if (mask & TDM_EVENT_READABLE)
334 wl_mask |= WL_EVENT_READABLE;
335 if (mask & TDM_EVENT_WRITABLE)
336 wl_mask |= WL_EVENT_WRITABLE;
338 if (wl_event_source_fd_update(fd_source->base.wl_source, wl_mask) < 0) {
339 TDM_ERR("source update failed: %m");
340 return TDM_ERROR_OPERATION_FAILED;
343 return TDM_ERROR_NONE;
347 _tdm_event_loop_timer_func(void *data)
349 tdm_event_source_timer *timer_source = (tdm_event_source_timer*)data;
351 TDM_RETURN_VAL_IF_FAIL(timer_source, 1);
352 TDM_RETURN_VAL_IF_FAIL(timer_source->func, 1);
354 timer_source->func(timer_source->user_data);
359 EXTERN tdm_event_source*
360 tdm_event_add_timer_handler(tdm_display *dpy, tdm_event_timer_handler func,
361 void *user_data, tdm_error *error)
363 tdm_private_display *private_display;
364 tdm_private_event *private_event;
365 tdm_event_source_timer *timer_source;
368 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(dpy, TDM_ERROR_INVALID_PARAMETER, NULL);
369 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(func, TDM_ERROR_INVALID_PARAMETER, NULL);
371 private_display = (tdm_private_display*)dpy;
372 private_event = private_display->private_event;
373 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_event, TDM_ERROR_INVALID_PARAMETER, NULL);
374 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_event->event_loop, TDM_ERROR_INVALID_PARAMETER, NULL);
376 timer_source = calloc(1, sizeof(tdm_event_source_timer));
377 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(timer_source, TDM_ERROR_OUT_OF_MEMORY, NULL);
379 timer_source->base.wl_source =
380 wl_event_loop_add_timer(private_event->event_loop,
381 _tdm_event_loop_timer_func, timer_source);
382 if (!timer_source->base.wl_source) {
384 *error = TDM_ERROR_OUT_OF_MEMORY;
389 timer_source->private_display = private_display;
390 timer_source->func = func;
391 timer_source->user_data = user_data;
394 *error = TDM_ERROR_NONE;
396 return (tdm_event_source*)timer_source;
400 tdm_event_source_timer_update(tdm_event_source *source, int ms_delay)
402 tdm_event_source_timer *timer_source = source;
404 TDM_RETURN_VAL_IF_FAIL(timer_source, TDM_ERROR_INVALID_PARAMETER);
406 if (wl_event_source_timer_update(timer_source->base.wl_source, ms_delay) < 0) {
407 TDM_ERR("source update failed: %m");
408 return TDM_ERROR_OPERATION_FAILED;
411 return TDM_ERROR_NONE;
415 tdm_event_source_remove(tdm_event_source *source)
417 tdm_event_source_base *base = (tdm_event_source_base*)source;
422 wl_event_source_remove(base->wl_source);