1 /**************************************************************************
3 xserver-xorg-module-lazyload
5 Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
7 Contact: Sung-Jin Park <sj76.park@samsung.com>
8 Sangjin LEE <lsj119@samsung.com>
10 Permission is hereby granted, free of charge, to any person obtaining a
11 copy of this software and associated documentation files (the
12 "Software"), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sub license, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial portions
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
25 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 **************************************************************************/
39 #include <dbus/dbus.h>
44 #include "module_lazyload_main.h"
45 #include "module_lazyload_dbus.h"
48 #define REP_MSG_SIZE 8192
51 #define RECONNECT_TIME 500
52 #define DISPATCH_TIME 50
54 typedef struct _ModuleLazyloadDbusInfo
58 ModuleLazyloadDbusMethod *methods;
61 } ModuleLazyloadDbusInfo;
63 static ModuleLazyloadDbusInfo server_info;
65 static CARD32 _moduleLazyloadDbusTimeout (OsTimerPtr timer, CARD32 time, pointer arg);
66 static Bool _moduleLazyloadDbusInit (ModuleLazyloadDbusInfo *info);
67 static void _moduleLazyloadDbusDeinit (ModuleLazyloadDbusInfo *info);
70 _moduleLazyloadDbusReplyMessage (ModuleLazyloadDbusInfo *info, DBusMessage *msg, char *reply)
72 DBusMessage *reply_msg = NULL;
75 XDBG_RETURN_VAL_IF_FAIL (info->conn != NULL, FALSE);
77 reply_msg = dbus_message_new_method_return (msg);
78 XDBG_RETURN_VAL_IF_FAIL (reply_msg != NULL, FALSE);
80 dbus_message_iter_init_append (reply_msg, &iter);
81 if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &reply))
83 XDBG_ERROR (MLAZY, "[SERVER] out of memory\n");
84 dbus_message_unref (reply_msg);
88 if (!dbus_connection_send (info->conn, reply_msg, NULL))
90 XDBG_ERROR (MLAZY, "[SERVER] failed: send reply\n");
91 dbus_message_unref (reply_msg);
95 XDBG_DEBUG (MLAZY, "[SERVER] send reply\n");
97 dbus_connection_flush (info->conn);
98 dbus_message_unref (reply_msg);
104 _moduleLazyloadDbusProcessMessage (ModuleLazyloadDbusInfo *info, DBusMessage *msg)
106 ModuleLazyloadDbusMethod **prev;
108 char err_buf[REP_MSG_SIZE] = {0,};
109 char *argv[ARGV_NUM] = {0,};
113 snprintf (err_buf, REP_MSG_SIZE, "error message!\n");
115 dbus_error_init (&err);
117 XDBG_DEBUG (MLAZY, "[SERVER] Process a message (%s.%s)\n",
118 dbus_message_get_interface (msg), dbus_message_get_member (msg));
120 XDBG_RETURN_IF_FAIL (info->conn != NULL);
122 for (prev = &info->methods; *prev; prev = &(*prev)->next)
124 ModuleLazyloadDbusMethod *method = *prev;
126 if (!strcmp (dbus_message_get_member (msg), method->name))
128 DBusMessageIter iter;
129 char reply[REP_MSG_SIZE] = {0,};
133 if (!dbus_message_iter_init (msg, &iter))
135 XDBG_ERROR (MLAZY, "[SERVER] Message has no arguments!\n");
136 snprintf (err_buf, REP_MSG_SIZE, "Message has no arguments!\n");
144 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
146 XDBG_ERROR (MLAZY, "[SERVER] Argument is not string!\n");
147 snprintf (err_buf, REP_MSG_SIZE, "Argument is not string!\n");
151 dbus_message_iter_get_basic (&iter, &p);
155 XDBG_ERROR (MLAZY, "[SERVER] Can't get string!\n");
156 snprintf (err_buf, REP_MSG_SIZE, "Can't get string!\n");
160 argv[argc] = strdup (p);
162 } while (dbus_message_iter_has_next (&iter) &&
163 dbus_message_iter_next (&iter) &&
166 len = REP_MSG_SIZE - 1;
169 method->func (method->data, argc, argv, reply, &len);
171 _moduleLazyloadDbusReplyMessage (info, msg, reply);
173 for (i = 0; i < ARGV_NUM; i++)
176 dbus_error_free (&err);
185 _moduleLazyloadDbusReplyMessage (info, msg, err_buf);
187 for (i = 0; i < ARGV_NUM; i++)
190 dbus_error_free (&err);
194 _moduleLazyloadDbusWakeupHandler (pointer data, int error, pointer pRead)
196 ModuleLazyloadDbusInfo *info = (ModuleLazyloadDbusInfo*)data;
198 if (!info || !info->conn || info->fd < 0)
201 if (FD_ISSET(info->fd, (fd_set*)pRead))
204 dbus_connection_read_write_dispatch (info->conn, 0);
205 } while (info->conn &&
206 dbus_connection_get_is_connected (info->conn) &&
207 dbus_connection_get_dispatch_status (info->conn) ==
208 DBUS_DISPATCH_DATA_REMAINS);
210 /* DON'T use info->conn from here. info->conn becomes NULL by
211 * dbus_connection_read_write_dispatch(_moduleLazyloadDbusMsgFilter)
216 static DBusHandlerResult
217 _moduleLazyloadDbusMsgHandler (DBusConnection *connection, DBusMessage *msg, void *data)
219 ModuleLazyloadDbusInfo *info = (ModuleLazyloadDbusInfo*)data;
221 if (!info || !info->conn || !msg)
222 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
224 XDBG_DEBUG (MLAZY, "[SERVER] Got a message (%s.%s)\n",
225 dbus_message_get_interface (msg), dbus_message_get_member (msg));
227 if (!dbus_message_is_method_call (msg, LAZYLOAD_DBUS_INTERFACE, LAZYLOAD_DBUS_METHOD))
228 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
230 _moduleLazyloadDbusProcessMessage (info, msg);
232 return DBUS_HANDLER_RESULT_HANDLED;
235 static DBusHandlerResult
236 _moduleLazyloadDbusMsgFilter (DBusConnection *conn, DBusMessage *msg, void *data)
238 ModuleLazyloadDbusInfo *info = (ModuleLazyloadDbusInfo*)data;
241 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
243 if (dbus_message_is_signal (msg, DBUS_INTERFACE_LOCAL, "Disconnected"))
245 XDBG_DEBUG (MLAZY, "[SERVER] disconnected by signal\n");
246 _moduleLazyloadDbusDeinit (info);
249 TimerFree(info->timer);
250 info->timer = TimerSet(NULL, 0, 1, _moduleLazyloadDbusTimeout, info);
252 return DBUS_HANDLER_RESULT_HANDLED;
255 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
259 _moduleLazyloadDbusTimeout (OsTimerPtr timer, CARD32 time, pointer arg)
261 ModuleLazyloadDbusInfo *info = (ModuleLazyloadDbusInfo*)arg;
266 XDBG_DEBUG (MLAZY, "[SERVER] timeout\n");
268 if (_moduleLazyloadDbusInit (info))
270 TimerFree (info->timer);
275 return RECONNECT_TIME;
279 _moduleLazyloadDbusInit (ModuleLazyloadDbusInfo *info)
281 DBusObjectPathVTable vtable = {.message_function = _moduleLazyloadDbusMsgHandler, };
285 dbus_error_init (&err);
287 XDBG_RETURN_VAL_IF_FAIL (info->conn == NULL, FALSE);
289 info->conn = dbus_bus_get (DBUS_BUS_SYSTEM, &err);
290 if (dbus_error_is_set (&err))
292 XDBG_ERROR (MLAZY, "[SERVER] failed: connection (%s)\n", err.message);
297 XDBG_ERROR (MLAZY, "[SERVER] failed: connection NULL\n");
301 ret = dbus_bus_request_name (info->conn, LAZYLOAD_DBUS_SERVER,
302 DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
303 if (dbus_error_is_set (&err))
305 XDBG_ERROR (MLAZY, "[SERVER] failed: request name (%s)\n", err.message);
308 if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
310 XDBG_ERROR (MLAZY, "[SERVER] failed: Not Primary Owner (%d)\n", ret);
314 snprintf (info->rule, sizeof (info->rule), "type='method_call',interface='%s'",
315 LAZYLOAD_DBUS_INTERFACE);
317 /* blocks until we get a reply. */
318 dbus_bus_add_match (info->conn, info->rule, &err);
319 if (dbus_error_is_set (&err))
321 XDBG_ERROR (MLAZY, "[SERVER] failed: add match (%s)\n", err.message);
325 if (!dbus_connection_register_object_path (info->conn,
326 LAZYLOAD_DBUS_PATH, &vtable,
329 XDBG_ERROR (MLAZY, "[SERVER] failed: register object path\n");
333 dbus_connection_set_exit_on_disconnect (info->conn, FALSE);
335 if (!dbus_connection_add_filter (info->conn, _moduleLazyloadDbusMsgFilter, info, NULL))
337 XDBG_ERROR (MLAZY, "[SERVER] failed: add filter (%s)\n", err.message);
341 if (!dbus_connection_get_unix_fd (info->conn, &info->fd) || info->fd < 0)
343 XDBG_ERROR (MLAZY, "[SERVER] failed: get fd\n");
347 AddGeneralSocket (info->fd);
348 RegisterBlockAndWakeupHandlers ((BlockHandlerProcPtr)NoopDDA,
349 _moduleLazyloadDbusWakeupHandler, info);
351 XDBG_INFO (MLAZY, "[SERVER] connected\n");
353 dbus_error_free (&err);
358 dbus_connection_remove_filter (info->conn, _moduleLazyloadDbusMsgFilter, info);
360 dbus_connection_unregister_object_path (info->conn, LAZYLOAD_DBUS_PATH);
362 dbus_bus_remove_match (info->conn, info->rule, &err);
363 dbus_error_free (&err);
365 dbus_bus_release_name (info->conn, LAZYLOAD_DBUS_SERVER, &err);
366 dbus_error_free (&err);
368 dbus_connection_close (info->conn);
370 dbus_error_free (&err);
378 _moduleLazyloadDbusDeinit (ModuleLazyloadDbusInfo *info)
382 TimerFree (info->timer);
389 dbus_error_init (&err);
390 dbus_connection_remove_filter (info->conn, _moduleLazyloadDbusMsgFilter, info);
391 dbus_connection_unregister_object_path (info->conn, LAZYLOAD_DBUS_PATH);
392 dbus_bus_remove_match (info->conn, info->rule, &err);
393 dbus_error_free (&err);
394 dbus_bus_release_name (info->conn, LAZYLOAD_DBUS_SERVER, &err);
395 dbus_error_free (&err);
396 dbus_connection_unref (info->conn);
400 RemoveBlockAndWakeupHandlers ((BlockHandlerProcPtr)NoopDDA,
401 _moduleLazyloadDbusWakeupHandler, info);
404 RemoveGeneralSocket (info->fd);
408 XDBG_INFO (MLAZY, "[SERVER] disconnected\n");
412 moduleLazyloadDbusConnect (void)
414 XDBG_DEBUG (MLAZY, "[SERVER] connecting\n");
416 memset (&server_info, 0, sizeof(server_info));
419 server_info.timer = TimerSet (NULL, 0, 1, _moduleLazyloadDbusTimeout, &server_info);
425 moduleLazyloadDbusDisconnect (void)
427 XDBG_DEBUG (MLAZY, "[SERVER] disconnecting\n");
429 _moduleLazyloadDbusDeinit (&server_info);
433 moduleLazyloadDbusAddMethod (ModuleLazyloadDbusMethod *method)
435 ModuleLazyloadDbusMethod **prev;
437 for (prev = &server_info.methods; *prev; prev = &(*prev)->next);
446 moduleLazyloadDbusRemoveMethod (ModuleLazyloadDbusMethod *method)
448 ModuleLazyloadDbusMethod **prev;
450 for (prev = &server_info.methods; *prev; prev = &(*prev)->next)
453 *prev = method->next;