4 * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the License);
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
22 #include "core/edbus-handler.h"
23 #include "core/common.h"
24 #include "core/device-notifier.h"
25 #include "core/list.h"
27 #define EDBUS_INIT_RETRY_COUNT 5
28 #define NAME_OWNER_CHANGED "NameOwnerChanged"
29 #define NAME_OWNER_MATCH "type='signal',sender='org.freedesktop.DBus',\
30 path='/org/freedesktop/DBus',interface='org.freedesktop.DBus',\
31 member='NameOwnerChanged',arg0='%s'"
33 /* -1 is a default timeout value, it's converted to 25*1000 internally. */
34 #define DBUS_REPLY_TIMEOUT (-1)
39 E_DBus_Signal_Handler *handler;
42 static struct edbus_object {
44 const char *interface;
46 E_DBus_Interface *iface;
48 { DEVICED_PATH_CORE , DEVICED_INTERFACE_CORE , NULL, NULL },
49 { DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY, NULL, NULL },
50 { DEVICED_PATH_PASS , DEVICED_INTERFACE_PASS , NULL, NULL },
51 { DEVICED_PATH_HALL , DEVICED_INTERFACE_HALL , NULL, NULL },
52 { DEVICED_PATH_POWER , DEVICED_INTERFACE_POWER , NULL, NULL },
53 { DEVICED_PATH_STORAGE, DEVICED_INTERFACE_STORAGE, NULL, NULL },
54 { DEVICED_PATH_HAPTIC , DEVICED_INTERFACE_HAPTIC , NULL, NULL },
55 { DEVICED_PATH_LED , DEVICED_INTERFACE_LED , NULL, NULL },
56 { DEVICED_PATH_MMC , DEVICED_INTERFACE_MMC , NULL, NULL },
57 { DEVICED_PATH_PROCESS, DEVICED_INTERFACE_PROCESS, NULL, NULL },
58 { DEVICED_PATH_KEY , DEVICED_INTERFACE_KEY , NULL, NULL },
59 { DEVICED_PATH_CPU , DEVICED_INTERFACE_CPU , NULL, NULL },
60 { DEVICED_PATH_PMQOS , DEVICED_INTERFACE_PMQOS , NULL, NULL },
61 { DEVICED_PATH_SYSNOTI, DEVICED_INTERFACE_SYSNOTI, NULL, NULL },
62 { DEVICED_PATH_USB , DEVICED_INTERFACE_USB , NULL, NULL },
63 { DEVICED_PATH_USBHOST, DEVICED_INTERFACE_USBHOST, NULL, NULL },
64 { DEVICED_PATH_EXTCON , DEVICED_INTERFACE_EXTCON , NULL, NULL },
65 { DEVICED_PATH_BATTERY, DEVICED_INTERFACE_BATTERY, NULL, NULL },
66 { DEVICED_PATH_BOARD, DEVICED_INTERFACE_BOARD, NULL, NULL },
67 { DEVICED_PATH_TESTMODE, DEVICED_INTERFACE_TESTMODE, NULL, NULL},
68 { DEVICED_PATH_APPS, DEVICED_INTERFACE_APPS, NULL, NULL},
69 { DEVICED_PATH_GPIO, DEVICED_INTERFACE_GPIO, NULL, NULL},
70 { DEVICED_PATH_HDMICEC, DEVICED_INTERFACE_HDMICEC, NULL, NULL},
71 /* Add new object & interface here*/
74 static dd_list *edbus_owner_list;
75 static dd_list *edbus_handler_list;
76 static dd_list *edbus_watch_list;
77 static int edbus_init_val;
78 static DBusConnection *conn;
79 static E_DBus_Connection *edbus_conn;
80 static DBusPendingCall *edbus_request_name;
82 static int register_edbus_interface(struct edbus_object *object)
87 _E("object is invalid value!");
91 object->obj = e_dbus_object_add(edbus_conn, object->path, NULL);
93 _E("fail to add edbus obj");
97 object->iface = e_dbus_interface_new(object->interface);
99 _E("fail to add edbus interface");
103 e_dbus_object_interface_attach(object->obj, object->iface);
108 E_DBus_Interface *get_edbus_interface(const char *path)
112 for (i = 0; i < ARRAY_SIZE(edbus_objects); i++)
113 if (!strcmp(path, edbus_objects[i].path))
114 return edbus_objects[i].iface;
119 pid_t get_edbus_sender_pid(DBusMessage *msg)
122 DBusMessage *send_msg;
123 DBusPendingCall *pending;
124 DBusMessageIter iter;
129 _E("invalid argument!");
133 sender = dbus_message_get_sender(msg);
135 _E("invalid sender!");
139 send_msg = dbus_message_new_method_call(DBUS_SERVICE_DBUS,
142 "GetConnectionUnixProcessID");
144 _E("invalid send msg!");
148 ret = dbus_message_append_args(send_msg, DBUS_TYPE_STRING,
149 &sender, DBUS_TYPE_INVALID);
151 _E("fail to append args!");
152 dbus_message_unref(send_msg);
156 pending = e_dbus_message_send(edbus_conn, send_msg, NULL, -1, NULL);
158 _E("pending is null!");
159 dbus_message_unref(send_msg);
163 dbus_message_unref(send_msg);
165 /* block until reply is received */
166 dbus_pending_call_block(pending);
168 msg = dbus_pending_call_steal_reply(pending);
169 dbus_pending_call_unref(pending);
171 _E("reply msg is null!");
175 dbus_message_iter_init(msg, &iter);
176 dbus_message_iter_get_basic(&iter, &pid);
177 dbus_message_unref(msg);
182 static void unregister_edbus_signal_handle(void)
185 struct edbus_list *entry;
187 DD_LIST_FOREACH(edbus_handler_list, tmp, entry) {
188 e_dbus_signal_handler_del(edbus_conn, entry->handler);
189 DD_LIST_REMOVE(edbus_handler_list, entry);
190 free(entry->signal_name);
195 int register_edbus_signal_handler(const char *path, const char *interface,
196 const char *name, E_DBus_Signal_Cb cb)
199 struct edbus_list *entry;
200 E_DBus_Signal_Handler *handler;
202 DD_LIST_FOREACH(edbus_handler_list, tmp, entry) {
203 if (strncmp(entry->signal_name, name, strlen(name)) == 0)
207 handler = e_dbus_signal_handler_add(edbus_conn, NULL, path,
208 interface, name, cb, NULL);
211 _E("fail to add edbus handler");
215 entry = malloc(sizeof(struct edbus_list));
222 entry->signal_name = strndup(name, strlen(name));
224 if (!entry->signal_name) {
230 entry->handler = handler;
231 DD_LIST_PREPEND(edbus_handler_list, entry);
232 if (!edbus_handler_list) {
233 _E("eina_list_prepend failed");
234 free(entry->signal_name);
241 int broadcast_edbus_signal(const char *path, const char *interface,
242 const char *name, const char *sig, char *param[])
245 DBusMessageIter iter;
248 msg = dbus_message_new_signal(path, interface, name);
250 _E("fail to allocate new %s.%s signal", interface, name);
254 dbus_message_iter_init_append(msg, &iter);
255 r = append_variant(&iter, sig, param);
257 _E("append_variant error(%d)", r);
261 r = dbus_connection_send(conn, msg, NULL);
262 dbus_message_unref(msg);
265 _E("dbus_connection_send error(%s:%s-%s)",
266 path, interface, name);
273 static DBusHandlerResult message_filter(DBusConnection *connection,
274 DBusMessage *message, void *data)
278 const char *iface, *member, *arg = NULL;
282 if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL)
283 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
285 iface = dbus_message_get_interface(message);
286 member = dbus_message_get_member(message);
288 if (strcmp(iface, DBUS_INTERFACE_DBUS))
289 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
291 if (strcmp(member, NAME_OWNER_CHANGED))
292 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
294 ret = dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg,
298 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
301 _D("Argument : %s", arg);
303 DD_LIST_FOREACH(edbus_watch_list, n, watch) {
304 if (strcmp(arg, watch->name)) continue;
307 watch->func(watch->name, watch->id);
309 DD_LIST_REMOVE(edbus_watch_list, watch);
314 /* remove registered sender */
315 snprintf(match, sizeof(match), NAME_OWNER_MATCH, arg);
316 dbus_bus_remove_match(conn, match, NULL);
319 if (DD_LIST_LENGTH(edbus_watch_list) == 0) {
320 dbus_connection_remove_filter(conn, message_filter, NULL);
321 _I("remove message filter, no watcher!");
324 return DBUS_HANDLER_RESULT_HANDLED;
327 int register_edbus_watch(DBusMessage *msg, enum watch_id id, int (*func)(char *name, enum watch_id id))
334 bool matched = false;
337 _E("invalid argument!");
341 sender = dbus_message_get_sender(msg);
343 _E("invalid sender!");
347 /* check the sender&id is already registered */
348 DD_LIST_FOREACH(edbus_watch_list, n, watch) {
349 if (strcmp(sender, watch->name))
351 if (id != watch->id) {
356 _I("%s(%d) is already watched!", watch->name, watch->id);
361 watch = malloc(sizeof(struct watch));
363 _E("Fail to malloc for watch!");
369 watch->name = strndup(sender, strlen(sender));
372 _E("Fail to malloc for watch name");
377 /* Add message filter */
378 if (DD_LIST_LENGTH(edbus_watch_list) == 0) {
379 ret = dbus_connection_add_filter(conn, message_filter, NULL, NULL);
381 _E("fail to add message filter!");
386 _I("success to add message filter!");
389 /* Add watch to watch list */
390 DD_LIST_APPEND(edbus_watch_list, watch);
393 snprintf(match, sizeof(match), NAME_OWNER_MATCH, watch->name);
394 dbus_bus_add_match(conn, match, NULL);
397 _I("%s(%d) is watched by dbus!", watch->name, watch->id);
402 int unregister_edbus_watch(DBusMessage *msg, enum watch_id id)
408 bool matched = false;
411 _E("invalid argument!");
415 sender = dbus_message_get_sender(msg);
417 _E("invalid sender!");
421 DD_LIST_FOREACH(edbus_watch_list, n, watch) {
422 if (strcmp(sender, watch->name))
425 if (id != watch->id) {
429 DD_LIST_REMOVE(edbus_watch_list, watch);
436 snprintf(match, sizeof(match), NAME_OWNER_MATCH, sender);
437 dbus_bus_remove_match(conn, match, NULL);
439 if (DD_LIST_LENGTH(edbus_watch_list) == 0)
440 dbus_connection_remove_filter(conn, message_filter,
447 static void unregister_edbus_watch_all(void)
453 if (DD_LIST_LENGTH(edbus_watch_list) > 0)
454 dbus_connection_remove_filter(conn, message_filter, NULL);
456 DD_LIST_FOREACH(edbus_watch_list, n, watch) {
457 snprintf(match, sizeof(match), NAME_OWNER_MATCH, watch->name);
458 dbus_bus_remove_match(conn, match, NULL);
459 DD_LIST_REMOVE(edbus_watch_list, watch);
465 int register_edbus_method(const char *path, const struct edbus_method *edbus_methods, int size)
467 E_DBus_Interface *iface;
471 iface = get_edbus_interface(path);
474 _E("fail to get edbus interface!");
478 for (i = 0; i < size; i++) {
479 ret = e_dbus_interface_method_add(iface,
480 edbus_methods[i].member,
481 edbus_methods[i].signature,
482 edbus_methods[i].reply_signature,
483 edbus_methods[i].func);
485 _E("fail to add method %s!", edbus_methods[i].member);
493 static void request_name_cb(void *data, DBusMessage *msg, DBusError *error)
500 _D("invalid DBusMessage!");
504 dbus_error_init(&err);
505 r = dbus_message_get_args(msg, &err, DBUS_TYPE_UINT32, &val, DBUS_TYPE_INVALID);
507 _E("no message : [%s:%s]", err.name, err.message);
508 dbus_error_free(&err);
512 _I("Request Name reply : %d", val);
515 static void check_owner_name(void)
519 DBusMessageIter iter;
521 char exe_name[PATH_MAX];
526 DD_LIST_FOREACH(edbus_owner_list, n, entry) {
528 msg = dbus_method_sync_with_reply(E_DBUS_FDO_BUS,
530 E_DBUS_FDO_INTERFACE,
531 "GetConnectionUnixProcessID", "s", pa);
534 _E("invalid DBusMessage!");
538 dbus_error_init(&err);
539 dbus_message_iter_init(msg, &iter);
541 dbus_message_iter_get_basic(&iter, &pid);
542 if (get_cmdline_name(pid, exe_name, PATH_MAX) != 0)
544 _I("%s(%d)", exe_name, pid);
547 dbus_message_unref(msg);
548 dbus_error_free(&err);
552 static void check_owner_list(void)
556 DBusMessageIter array, iter, item, iter_val;
561 pa[0] = DEVICED_BUS_NAME;
562 msg = dbus_method_sync_with_reply(E_DBUS_FDO_BUS,
564 E_DBUS_FDO_INTERFACE,
565 "ListQueuedOwners", "s", pa);
568 _E("invalid DBusMessage!");
572 dbus_error_init(&err);
573 dbus_message_iter_init(msg, &array);
575 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
577 dbus_message_iter_recurse(&array, &item);
578 while (dbus_message_iter_get_arg_type(&item) == DBUS_TYPE_STRING) {
579 dbus_message_iter_get_basic(&item, &name);
580 entry = strndup(name, strlen(name));
581 DD_LIST_APPEND(edbus_owner_list, entry);
582 if (!edbus_owner_list) {
587 dbus_message_iter_next(&item);
591 dbus_message_unref(msg);
592 dbus_error_free(&err);
595 void edbus_init(void *data)
601 dbus_threads_init_default();
602 dbus_error_init(&error);
605 edbus_init_val = e_dbus_init();
608 if (retry == EDBUS_INIT_RETRY_COUNT) {
609 _E("fail to init edbus");
613 } while (retry <= EDBUS_INIT_RETRY_COUNT);
617 conn = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
620 if (retry == EDBUS_INIT_RETRY_COUNT) {
621 _E("fail to get dbus");
625 } while (retry <= EDBUS_INIT_RETRY_COUNT);
629 edbus_conn = e_dbus_connection_setup(conn);
632 if (retry == EDBUS_INIT_RETRY_COUNT) {
633 _E("fail to get edbus");
637 } while (retry <= EDBUS_INIT_RETRY_COUNT);
641 edbus_request_name = e_dbus_request_name(edbus_conn, DEVICED_BUS_NAME,
642 DBUS_NAME_FLAG_REPLACE_EXISTING, request_name_cb, NULL);
643 if (edbus_request_name)
645 if (retry == EDBUS_INIT_RETRY_COUNT) {
646 _E("fail to request edbus name");
650 } while (retry <= EDBUS_INIT_RETRY_COUNT);
652 for (i = 0; i < ARRAY_SIZE(edbus_objects); i++) {
653 ret = register_edbus_interface(&edbus_objects[i]);
655 _E("fail to add obj & interface for %s",
656 edbus_objects[i].interface);
659 _D("add new obj for %s", edbus_objects[i].interface);
666 e_dbus_connection_close(edbus_conn);
668 dbus_connection_set_exit_on_disconnect(conn, FALSE);
673 void edbus_exit(void *data)
675 unregister_edbus_signal_handle();
676 unregister_edbus_watch_all();
677 e_dbus_connection_close(edbus_conn);