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_loop {
47 struct wl_display *wl_display;
48 struct wl_event_loop *wl_loop;
51 tdm_event_loop_source *backend_source;
54 typedef struct _tdm_event_loop_source_base
56 struct wl_event_source *wl_source;
57 } tdm_event_loop_source_base;
59 typedef struct _tdm_event_loop_source_fd
61 tdm_event_loop_source_base base;
62 tdm_private_display *private_display;
63 tdm_event_loop_fd_handler func;
65 } tdm_event_loop_source_fd;
67 typedef struct _tdm_event_loop_source_timer
69 tdm_event_loop_source_base base;
70 tdm_private_display *private_display;
71 tdm_event_loop_timer_handler func;
73 } tdm_event_loop_source_timer;
76 _tdm_event_loop_main_fd_handler(int fd, tdm_event_loop_mask mask, void *user_data)
78 tdm_private_display *private_display = (tdm_private_display*)user_data;
79 tdm_private_loop *private_loop;
80 tdm_func_display *func_display;
82 TDM_RETURN_VAL_IF_FAIL(private_display != NULL, TDM_ERROR_OPERATION_FAILED);
83 TDM_RETURN_VAL_IF_FAIL(private_display->private_loop != NULL, TDM_ERROR_OPERATION_FAILED);
85 private_loop = private_display->private_loop;
88 TDM_INFO("backend fd(%d) event happens", private_loop->backend_fd);
90 func_display = &private_display->func_display;
91 if (!func_display->display_handle_events)
92 return TDM_ERROR_NONE;
94 return func_display->display_handle_events(private_display->bdata);
98 tdm_event_loop_init(tdm_private_display *private_display)
100 tdm_private_loop *private_loop;
102 if (private_display->private_loop)
103 return TDM_ERROR_NONE;
105 private_loop = calloc(1, sizeof *private_loop);
107 TDM_ERR("alloc failed");
108 return TDM_ERROR_OUT_OF_MEMORY;
111 private_loop->backend_fd = -1;
113 private_loop->wl_display = wl_display_create();
114 if (!private_loop->wl_display) {
115 TDM_ERR("creating a wayland display failed");
117 return TDM_ERROR_OUT_OF_MEMORY;
120 private_loop->wl_loop = wl_display_get_event_loop(private_loop->wl_display);
121 if (!private_loop->wl_loop) {
122 TDM_ERR("no event loop");
123 wl_display_destroy(private_loop->wl_display);
125 return TDM_ERROR_OUT_OF_MEMORY;
128 TDM_INFO("event loop fd(%d)", wl_event_loop_get_fd(private_loop->wl_loop));
130 private_display->private_loop = private_loop;
132 return TDM_ERROR_NONE;
136 tdm_event_loop_deinit(tdm_private_display *private_display)
138 if (!private_display->private_loop)
141 if (private_display->private_loop->backend_source)
142 tdm_event_loop_source_remove(private_display->private_loop->backend_source);
144 if (private_display->private_loop->wl_display)
145 wl_display_destroy(private_display->private_loop->wl_display);
147 free(private_display->private_loop);
148 private_display->private_loop = NULL;
152 tdm_event_loop_create_backend_source(tdm_private_display *private_display)
154 tdm_private_loop *private_loop = private_display->private_loop;
155 tdm_func_display *func_display;
159 TDM_RETURN_IF_FAIL(private_loop != NULL);
161 func_display = &private_display->func_display;
162 if (!func_display->display_get_fd) {
163 TDM_INFO("TDM backend module won't offer a display fd");
167 ret = func_display->display_get_fd(private_display->bdata, &fd);
169 TDM_WRN("TDM backend module returns fd(%d)", fd);
173 if (!func_display->display_handle_events) {
174 TDM_ERR("no display_handle_events function");
178 private_loop->backend_source =
179 tdm_event_loop_add_fd_handler(private_display, fd,
180 TDM_EVENT_LOOP_READABLE,
181 _tdm_event_loop_main_fd_handler,
182 private_display, &ret);
183 if (!private_loop->backend_source) {
184 TDM_ERR("no backend fd(%d) source", fd);
188 private_loop->backend_fd = fd;
190 TDM_INFO("backend fd(%d) source created", private_loop->backend_fd);
194 tdm_event_loop_get_fd(tdm_private_display *private_display)
196 tdm_private_loop *private_loop = private_display->private_loop;
198 TDM_RETURN_VAL_IF_FAIL(private_loop->wl_loop != NULL, -1);
200 return wl_event_loop_get_fd(private_loop->wl_loop);
204 tdm_event_loop_dispatch(tdm_private_display *private_display)
206 tdm_private_loop *private_loop = private_display->private_loop;
208 TDM_RETURN_VAL_IF_FAIL(private_loop->wl_loop != NULL, TDM_ERROR_OPERATION_FAILED);
210 if (tdm_debug_thread)
211 TDM_INFO("dispatch");
213 /* Don't set timeout to -1. It can make deadblock by two mutex locks.
214 * If need to set -1, use poll() and call tdm_event_loop_dispatch() after
217 if (wl_event_loop_dispatch(private_loop->wl_loop, 0) < 0)
218 TDM_ERR("dispatch failed");
220 return TDM_ERROR_NONE;
224 tdm_event_loop_add_socket(tdm_private_display *private_display, const char *name)
226 tdm_private_loop *private_loop = private_display->private_loop;
228 TDM_RETURN_VAL_IF_FAIL(private_loop->wl_display != NULL, TDM_ERROR_OPERATION_FAILED);
230 if (wl_display_add_socket(private_loop->wl_display, name) < 0) {
231 TDM_ERR("add socket(\"%s\") failed", name);
232 return TDM_ERROR_OPERATION_FAILED;
235 return TDM_ERROR_NONE;
239 _tdm_event_loop_fd_func(int fd, uint32_t wl_mask, void *data)
241 tdm_event_loop_source_fd *fd_source = (tdm_event_loop_source_fd*)data;
242 tdm_event_loop_mask mask = 0;
244 TDM_RETURN_VAL_IF_FAIL(fd_source, 1);
245 TDM_RETURN_VAL_IF_FAIL(fd_source->func, 1);
247 if (wl_mask & WL_EVENT_READABLE)
248 mask |= TDM_EVENT_LOOP_READABLE;
249 if (wl_mask & WL_EVENT_WRITABLE)
250 mask |= TDM_EVENT_LOOP_WRITABLE;
251 if (wl_mask & WL_EVENT_HANGUP)
252 mask |= TDM_EVENT_LOOP_HANGUP;
253 if (wl_mask & WL_EVENT_ERROR)
254 mask |= TDM_EVENT_LOOP_ERROR;
256 fd_source->func(fd, mask, fd_source->user_data);
261 EXTERN tdm_event_loop_source*
262 tdm_event_loop_add_fd_handler(tdm_display *dpy, int fd, tdm_event_loop_mask mask,
263 tdm_event_loop_fd_handler func, void *user_data,
266 tdm_private_display *private_display;
267 tdm_private_loop *private_loop;
268 tdm_event_loop_source_fd *fd_source;
269 uint32_t wl_mask = 0;
272 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(dpy, TDM_ERROR_INVALID_PARAMETER, NULL);
273 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(fd >= 0, TDM_ERROR_INVALID_PARAMETER, NULL);
274 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(func, TDM_ERROR_INVALID_PARAMETER, NULL);
276 private_display = (tdm_private_display*)dpy;
277 private_loop = private_display->private_loop;
278 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_loop, TDM_ERROR_INVALID_PARAMETER, NULL);
279 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_loop->wl_loop, TDM_ERROR_INVALID_PARAMETER, NULL);
281 fd_source = calloc(1, sizeof(tdm_event_loop_source_fd));
282 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(fd_source, TDM_ERROR_OUT_OF_MEMORY, NULL);
284 if (mask & TDM_EVENT_LOOP_READABLE)
285 wl_mask |= WL_EVENT_READABLE;
286 if (mask & TDM_EVENT_LOOP_WRITABLE)
287 wl_mask |= WL_EVENT_WRITABLE;
289 fd_source->base.wl_source =
290 wl_event_loop_add_fd(private_loop->wl_loop,
291 fd, wl_mask, _tdm_event_loop_fd_func, fd_source);
292 if (!fd_source->base.wl_source) {
294 *error = TDM_ERROR_OUT_OF_MEMORY;
299 fd_source->private_display = private_display;
300 fd_source->func = func;
301 fd_source->user_data = user_data;
304 *error = TDM_ERROR_NONE;
306 return (tdm_event_loop_source*)fd_source;
310 tdm_event_loop_source_fd_update(tdm_event_loop_source *source, tdm_event_loop_mask mask)
312 tdm_event_loop_source_fd *fd_source = source;
313 uint32_t wl_mask = 0;
315 TDM_RETURN_VAL_IF_FAIL(fd_source, TDM_ERROR_INVALID_PARAMETER);
317 if (mask & TDM_EVENT_LOOP_READABLE)
318 wl_mask |= WL_EVENT_READABLE;
319 if (mask & TDM_EVENT_LOOP_WRITABLE)
320 wl_mask |= WL_EVENT_WRITABLE;
322 if (wl_event_source_fd_update(fd_source->base.wl_source, wl_mask) < 0) {
323 TDM_ERR("source update failed: %m");
324 return TDM_ERROR_OPERATION_FAILED;
327 return TDM_ERROR_NONE;
331 _tdm_event_loop_timer_func(void *data)
333 tdm_event_loop_source_timer *timer_source = (tdm_event_loop_source_timer*)data;
335 TDM_RETURN_VAL_IF_FAIL(timer_source, 1);
336 TDM_RETURN_VAL_IF_FAIL(timer_source->func, 1);
338 timer_source->func(timer_source->user_data);
343 EXTERN tdm_event_loop_source*
344 tdm_event_loop_add_timer_handler(tdm_display *dpy, tdm_event_loop_timer_handler func,
345 void *user_data, tdm_error *error)
347 tdm_private_display *private_display;
348 tdm_private_loop *private_loop;
349 tdm_event_loop_source_timer *timer_source;
352 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(dpy, TDM_ERROR_INVALID_PARAMETER, NULL);
353 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(func, TDM_ERROR_INVALID_PARAMETER, NULL);
355 private_display = (tdm_private_display*)dpy;
356 private_loop = private_display->private_loop;
357 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_loop, TDM_ERROR_INVALID_PARAMETER, NULL);
358 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_loop->wl_loop, TDM_ERROR_INVALID_PARAMETER, NULL);
360 timer_source = calloc(1, sizeof(tdm_event_loop_source_timer));
361 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(timer_source, TDM_ERROR_OUT_OF_MEMORY, NULL);
363 timer_source->base.wl_source =
364 wl_event_loop_add_timer(private_loop->wl_loop,
365 _tdm_event_loop_timer_func, timer_source);
366 if (!timer_source->base.wl_source) {
368 *error = TDM_ERROR_OUT_OF_MEMORY;
373 timer_source->private_display = private_display;
374 timer_source->func = func;
375 timer_source->user_data = user_data;
378 *error = TDM_ERROR_NONE;
380 return (tdm_event_loop_source*)timer_source;
384 tdm_event_loop_source_timer_update(tdm_event_loop_source *source, int ms_delay)
386 tdm_event_loop_source_timer *timer_source = source;
388 TDM_RETURN_VAL_IF_FAIL(timer_source, TDM_ERROR_INVALID_PARAMETER);
390 if (wl_event_source_timer_update(timer_source->base.wl_source, ms_delay) < 0) {
391 TDM_ERR("source update failed: %m");
392 return TDM_ERROR_OPERATION_FAILED;
395 return TDM_ERROR_NONE;
399 tdm_event_loop_source_remove(tdm_event_loop_source *source)
401 tdm_event_loop_source_base *base = (tdm_event_loop_source_base*)source;
406 wl_event_source_remove(base->wl_source);