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/data.h"
23 #include "core/edbus-handler.h"
24 #include "core/common.h"
25 #include "core/device-notifier.h"
26 #include "core/list.h"
28 #define EDBUS_INIT_RETRY_COUNT 5
29 #define NAME_OWNER_CHANGED "NameOwnerChanged"
30 #define NAME_OWNER_MATCH "type='signal',sender='org.freedesktop.DBus',\
31 path='/org/freedesktop/DBus',interface='org.freedesktop.DBus',\
32 member='NameOwnerChanged',arg0='%s'"
34 /* -1 is a default timeout value, it's converted to 25*1000 internally. */
35 #define DBUS_REPLY_TIMEOUT (-1)
40 E_DBus_Signal_Handler *handler;
43 static struct edbus_object {
45 const char *interface;
47 E_DBus_Interface *iface;
49 { DEVICED_PATH_CORE , DEVICED_INTERFACE_CORE , NULL, NULL },
50 { DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY, NULL, NULL },
51 { DEVICED_PATH_PASS , DEVICED_INTERFACE_PASS , NULL, NULL },
52 { DEVICED_PATH_HALL , DEVICED_INTERFACE_HALL , NULL, NULL },
53 { DEVICED_PATH_POWER , DEVICED_INTERFACE_POWER , NULL, NULL },
54 { DEVICED_PATH_STORAGE, DEVICED_INTERFACE_STORAGE, NULL, NULL },
55 { DEVICED_PATH_HAPTIC , DEVICED_INTERFACE_HAPTIC , NULL, NULL },
56 { DEVICED_PATH_LED , DEVICED_INTERFACE_LED , NULL, NULL },
57 { DEVICED_PATH_MMC , DEVICED_INTERFACE_MMC , NULL, NULL },
58 { DEVICED_PATH_PROCESS, DEVICED_INTERFACE_PROCESS, NULL, NULL },
59 { DEVICED_PATH_KEY , DEVICED_INTERFACE_KEY , NULL, NULL },
60 { DEVICED_PATH_CPU , DEVICED_INTERFACE_CPU , NULL, NULL },
61 { DEVICED_PATH_PMQOS , DEVICED_INTERFACE_PMQOS , NULL, NULL },
62 { DEVICED_PATH_SYSNOTI, DEVICED_INTERFACE_SYSNOTI, 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 /* Add new object & interface here*/
71 static dd_list *edbus_handler_list;
72 static dd_list *edbus_watch_list;
73 static int edbus_init_val;
74 static DBusConnection *conn;
75 static E_DBus_Connection *edbus_conn;
76 static DBusPendingCall *edbus_request_name;
78 static int register_edbus_interface(struct edbus_object *object)
83 _E("object is invalid value!");
87 object->obj = e_dbus_object_add(edbus_conn, object->path, NULL);
89 _E("fail to add edbus obj");
93 object->iface = e_dbus_interface_new(object->interface);
95 _E("fail to add edbus interface");
99 e_dbus_object_interface_attach(object->obj, object->iface);
104 E_DBus_Interface *get_edbus_interface(const char *path)
108 for (i = 0; i < ARRAY_SIZE(edbus_objects); i++)
109 if (!strcmp(path, edbus_objects[i].path))
110 return edbus_objects[i].iface;
115 pid_t get_edbus_sender_pid(DBusMessage *msg)
118 DBusMessage *send_msg;
119 DBusPendingCall *pending;
120 DBusMessageIter iter;
125 _E("invalid argument!");
129 sender = dbus_message_get_sender(msg);
131 _E("invalid sender!");
135 send_msg = dbus_message_new_method_call(DBUS_SERVICE_DBUS,
138 "GetConnectionUnixProcessID");
140 _E("invalid send msg!");
144 ret = dbus_message_append_args(send_msg, DBUS_TYPE_STRING,
145 &sender, DBUS_TYPE_INVALID);
147 _E("fail to append args!");
148 dbus_message_unref(send_msg);
152 pending = e_dbus_message_send(edbus_conn, send_msg, NULL, -1, NULL);
154 _E("pending is null!");
155 dbus_message_unref(send_msg);
159 dbus_message_unref(send_msg);
161 /* block until reply is received */
162 dbus_pending_call_block(pending);
164 msg = dbus_pending_call_steal_reply(pending);
165 dbus_pending_call_unref(pending);
167 _E("reply msg is null!");
171 dbus_message_iter_init(msg, &iter);
172 dbus_message_iter_get_basic(&iter, &pid);
173 dbus_message_unref(msg);
178 static void unregister_edbus_signal_handle(void)
181 struct edbus_list *entry;
183 DD_LIST_FOREACH(edbus_handler_list, tmp, entry) {
184 e_dbus_signal_handler_del(edbus_conn, entry->handler);
185 DD_LIST_REMOVE(edbus_handler_list, entry);
186 free(entry->signal_name);
191 int register_edbus_signal_handler(const char *path, const char *interface,
192 const char *name, E_DBus_Signal_Cb cb)
195 struct edbus_list *entry;
196 E_DBus_Signal_Handler *handler;
198 DD_LIST_FOREACH(edbus_handler_list, tmp, entry) {
199 if (strncmp(entry->signal_name, name, strlen(name)) == 0)
203 handler = e_dbus_signal_handler_add(edbus_conn, NULL, path,
204 interface, name, cb, NULL);
207 _E("fail to add edbus handler");
211 entry = malloc(sizeof(struct edbus_list));
218 entry->signal_name = strndup(name, strlen(name));
220 if (!entry->signal_name) {
226 entry->handler = handler;
227 DD_LIST_PREPEND(edbus_handler_list, entry);
228 if (!edbus_handler_list) {
229 _E("eina_list_prepend failed");
230 free(entry->signal_name);
237 int broadcast_edbus_signal(const char *path, const char *interface,
238 const char *name, const char *sig, char *param[])
241 DBusMessageIter iter;
244 msg = dbus_message_new_signal(path, interface, name);
246 _E("fail to allocate new %s.%s signal", interface, name);
250 dbus_message_iter_init_append(msg, &iter);
251 r = append_variant(&iter, sig, param);
253 _E("append_variant error(%d)", r);
257 e_dbus_message_send(edbus_conn, msg, NULL, -1, NULL);
259 dbus_message_unref(msg);
263 static DBusHandlerResult message_filter(DBusConnection *connection,
264 DBusMessage *message, void *data)
268 const char *iface, *member, *arg = NULL;
272 if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL)
273 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
275 iface = dbus_message_get_interface(message);
276 member = dbus_message_get_member(message);
278 if (strcmp(iface, DBUS_INTERFACE_DBUS))
279 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
281 if (strcmp(member, NAME_OWNER_CHANGED))
282 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
284 ret = dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg,
288 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
291 _D("Argument : %s", arg);
293 DD_LIST_FOREACH(edbus_watch_list, n, watch) {
294 if (strcmp(arg, watch->name)) continue;
297 watch->func(watch->name, watch->id);
299 DD_LIST_REMOVE(edbus_watch_list, watch);
304 /* remove registered sender */
305 snprintf(match, sizeof(match), NAME_OWNER_MATCH, arg);
306 dbus_bus_remove_match(conn, match, NULL);
309 if (DD_LIST_LENGTH(edbus_watch_list) == 0) {
310 dbus_connection_remove_filter(conn, message_filter, NULL);
311 _I("remove message filter, no watcher!");
314 return DBUS_HANDLER_RESULT_HANDLED;
317 int register_edbus_watch(DBusMessage *msg, enum watch_id id, int (*func)(char *name, enum watch_id id))
324 bool matched = false;
327 _E("invalid argument!");
331 sender = dbus_message_get_sender(msg);
333 _E("invalid sender!");
337 /* check the sender&id is already registered */
338 DD_LIST_FOREACH(edbus_watch_list, n, watch) {
339 if (strcmp(sender, watch->name))
341 if (id != watch->id) {
346 _I("%s(%d) is already watched!", watch->name, watch->id);
351 watch = malloc(sizeof(struct watch));
353 _E("Fail to malloc for watch!");
359 watch->name = strndup(sender, strlen(sender));
362 _E("Fail to malloc for watch name");
367 /* Add message filter */
368 if (DD_LIST_LENGTH(edbus_watch_list) == 0) {
369 ret = dbus_connection_add_filter(conn, message_filter, NULL, NULL);
371 _E("fail to add message filter!");
376 _I("success to add message filter!");
379 /* Add watch to watch list */
380 DD_LIST_APPEND(edbus_watch_list, watch);
383 snprintf(match, sizeof(match), NAME_OWNER_MATCH, watch->name);
384 dbus_bus_add_match(conn, match, NULL);
387 _I("%s(%d) is watched by dbus!", watch->name, watch->id);
392 int unregister_edbus_watch(DBusMessage *msg, enum watch_id id)
398 bool matched = false;
401 _E("invalid argument!");
405 sender = dbus_message_get_sender(msg);
407 _E("invalid sender!");
411 DD_LIST_FOREACH(edbus_watch_list, n, watch) {
412 if (strcmp(sender, watch->name))
415 if (id != watch->id) {
419 DD_LIST_REMOVE(edbus_watch_list, watch);
426 snprintf(match, sizeof(match), NAME_OWNER_MATCH, sender);
427 dbus_bus_remove_match(conn, match, NULL);
429 if (DD_LIST_LENGTH(edbus_watch_list) == 0)
430 dbus_connection_remove_filter(conn, message_filter,
437 static void unregister_edbus_watch_all(void)
443 if (DD_LIST_LENGTH(edbus_watch_list) > 0)
444 dbus_connection_remove_filter(conn, message_filter, NULL);
446 DD_LIST_FOREACH(edbus_watch_list, n, watch) {
447 snprintf(match, sizeof(match), NAME_OWNER_MATCH, watch->name);
448 dbus_bus_remove_match(conn, match, NULL);
449 DD_LIST_REMOVE(edbus_watch_list, watch);
455 int register_edbus_method(const char *path, const struct edbus_method *edbus_methods, int size)
457 E_DBus_Interface *iface;
461 iface = get_edbus_interface(path);
464 _E("fail to get edbus interface!");
468 for (i = 0; i < size; i++) {
469 ret = e_dbus_interface_method_add(iface,
470 edbus_methods[i].member,
471 edbus_methods[i].signature,
472 edbus_methods[i].reply_signature,
473 edbus_methods[i].func);
475 _E("fail to add method %s!", edbus_methods[i].member);
483 static void request_name_cb(void *data, DBusMessage *msg, DBusError *error)
490 _D("invalid DBusMessage!");
494 dbus_error_init(&err);
495 r = dbus_message_get_args(msg, &err, DBUS_TYPE_UINT32, &val, DBUS_TYPE_INVALID);
497 _E("no message : [%s:%s]", err.name, err.message);
498 dbus_error_free(&err);
502 _I("Request Name reply : %d", val);
505 void edbus_init(void *data)
511 dbus_threads_init_default();
512 dbus_error_init(&error);
515 edbus_init_val = e_dbus_init();
518 if (retry == EDBUS_INIT_RETRY_COUNT) {
519 _E("fail to init edbus");
523 } while (retry <= EDBUS_INIT_RETRY_COUNT);
527 conn = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
530 if (retry == EDBUS_INIT_RETRY_COUNT) {
531 _E("fail to get dbus");
535 } while (retry <= EDBUS_INIT_RETRY_COUNT);
539 edbus_conn = e_dbus_connection_setup(conn);
542 if (retry == EDBUS_INIT_RETRY_COUNT) {
543 _E("fail to get edbus");
547 } while (retry <= EDBUS_INIT_RETRY_COUNT);
551 edbus_request_name = e_dbus_request_name(edbus_conn, DEVICED_BUS_NAME,
552 DBUS_NAME_FLAG_REPLACE_EXISTING, request_name_cb, NULL);
553 if (edbus_request_name)
555 if (retry == EDBUS_INIT_RETRY_COUNT) {
556 _E("fail to request edbus name");
560 } while (retry <= EDBUS_INIT_RETRY_COUNT);
562 for (i = 0; i < ARRAY_SIZE(edbus_objects); i++) {
563 ret = register_edbus_interface(&edbus_objects[i]);
565 _E("fail to add obj & interface for %s",
566 edbus_objects[i].interface);
569 _D("add new obj for %s", edbus_objects[i].interface);
574 e_dbus_connection_close(edbus_conn);
576 dbus_connection_set_exit_on_disconnect(conn, FALSE);
581 void edbus_exit(void *data)
583 unregister_edbus_signal_handle();
584 unregister_edbus_watch_all();
585 e_dbus_connection_close(edbus_conn);