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.
21 #include "core/data.h"
22 #include "core/edbus-handler.h"
23 #include "core/common.h"
24 #include "core/devices.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'"
37 E_DBus_Signal_Handler *handler;
40 static struct edbus_object {
42 const char *interface;
44 E_DBus_Interface *iface;
46 { DEVICED_PATH_CORE , DEVICED_INTERFACE_CORE , NULL, NULL },
47 { DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY, NULL, NULL },
48 { DEVICED_PATH_STORAGE, DEVICED_INTERFACE_STORAGE, NULL, NULL },
49 /* Add new object & interface here*/
52 static Eina_List *edbus_handler_list;
53 static Eina_List *edbus_watch_list;
54 static int edbus_init_val;
55 static DBusConnection *conn;
56 static E_DBus_Connection *edbus_conn;
57 static DBusPendingCall *edbus_request_name;
59 static int register_edbus_interface(struct edbus_object *object)
64 _E("object is invalid value!");
68 object->obj = e_dbus_object_add(edbus_conn, object->path, NULL);
70 _E("fail to add edbus obj");
74 object->iface = e_dbus_interface_new(object->interface);
76 _E("fail to add edbus interface");
80 e_dbus_object_interface_attach(object->obj, object->iface);
85 E_DBus_Interface *get_edbus_interface(const char *path)
89 for (i = 0; i < ARRAY_SIZE(edbus_objects); i++)
90 if (!strcmp(path, edbus_objects[i].path))
91 return edbus_objects[i].iface;
96 pid_t get_edbus_sender_pid(DBusMessage *msg)
99 DBusMessage *send_msg;
100 DBusPendingCall *pending;
101 DBusMessageIter iter;
106 _E("invalid argument!");
110 sender = dbus_message_get_sender(msg);
112 _E("invalid sender!");
116 send_msg = dbus_message_new_method_call(DBUS_SERVICE_DBUS,
119 "GetConnectionUnixProcessID");
121 _E("invalid send msg!");
125 ret = dbus_message_append_args(send_msg, DBUS_TYPE_STRING,
126 &sender, DBUS_TYPE_INVALID);
128 _E("fail to append args!");
129 dbus_message_unref(send_msg);
133 pending = e_dbus_message_send(edbus_conn, send_msg, NULL, -1, NULL);
135 _E("pending is null!");
136 dbus_message_unref(send_msg);
140 dbus_message_unref(send_msg);
142 /* block until reply is received */
143 dbus_pending_call_block(pending);
145 msg = dbus_pending_call_steal_reply(pending);
146 dbus_pending_call_unref(pending);
148 _E("reply msg is null!");
152 dbus_message_iter_init(msg, &iter);
153 dbus_message_iter_get_basic(&iter, &pid);
154 dbus_message_unref(msg);
159 static void unregister_edbus_signal_handle(void)
163 struct edbus_list *entry;
165 EINA_LIST_FOREACH_SAFE(edbus_handler_list, tmp, tmp_next, entry) {
167 e_dbus_signal_handler_del(edbus_conn, entry->handler);
168 edbus_handler_list = eina_list_remove(edbus_handler_list, entry);
169 free(entry->signal_name);
175 int register_edbus_signal_handler(const char *path, const char *interface,
176 const char *name, E_DBus_Signal_Cb cb)
179 struct edbus_list *entry;
180 E_DBus_Signal_Handler *handler;
182 EINA_LIST_FOREACH(edbus_handler_list, tmp, entry) {
183 if (entry != NULL && strncmp(entry->signal_name, name, strlen(name)) == 0)
187 handler = e_dbus_signal_handler_add(edbus_conn, NULL, path,
188 interface, name, cb, NULL);
191 _E("fail to add edbus handler");
195 _E("add edbus service: %s", name);
197 entry = malloc(sizeof(struct edbus_list));
204 entry->signal_name = strndup(name, strlen(name));
206 if (!entry->signal_name) {
212 entry->handler = handler;
213 edbus_handler_list = eina_list_prepend(edbus_handler_list, entry);
214 if (!edbus_handler_list) {
215 _E("eina_list_prepend failed");
216 free(entry->signal_name);
223 int broadcast_edbus_signal(const char *path, const char *interface,
224 const char *name, int type, void *value)
227 DBusMessageIter iter;
229 char sig[2] = {type, '\0'};
231 signal = dbus_message_new_signal(path, interface, name);
233 _E("fail to allocate new %s.%s signal", interface, name);
237 dbus_message_append_args(signal, type, value, DBUS_TYPE_INVALID);
239 e_dbus_message_send(edbus_conn, signal, NULL, -1, NULL);
241 dbus_message_unref(signal);
245 static DBusHandlerResult message_filter(DBusConnection *connection,
246 DBusMessage *message, void *data)
250 const char *iface, *member, *watch, *arg = NULL;
253 if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL)
254 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
256 iface = dbus_message_get_interface(message);
257 member = dbus_message_get_member(message);
259 if (strcmp(iface, DBUS_INTERFACE_DBUS))
260 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
262 if (strcmp(member, NAME_OWNER_CHANGED))
263 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
265 ret = dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg,
269 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
272 _D("Argument : %s", arg);
274 EINA_LIST_FOREACH(edbus_watch_list, l, watch) {
275 if (strcmp(arg, watch)) continue;
277 /* notify 'process terminated' to device notifiers */
278 device_notify(DEVICE_NOTIFIER_PROCESS_TERMINATED, watch);
280 /* remove registered sender */
281 snprintf(match, sizeof(match), NAME_OWNER_MATCH, watch);
282 dbus_bus_remove_match(conn, match, NULL);
283 EINA_LIST_REMOVE(edbus_watch_list, watch);
288 if (eina_list_count(edbus_watch_list) == 0) {
289 dbus_connection_remove_filter(conn, message_filter, NULL);
290 _I("remove message filter, no watcher!");
293 return DBUS_HANDLER_RESULT_HANDLED;
296 int register_edbus_watch(DBusMessage *msg)
299 const char *sender, *watch;
304 _E("invalid argument!");
308 sender = dbus_message_get_sender(msg);
310 _E("invalid sender!");
314 /* check the sender is already registered */
315 EINA_LIST_FOREACH(edbus_watch_list, l, watch) {
316 if (strcmp(sender, watch)) continue;
318 _I("%s is already watched!", watch);
322 watch = strndup(sender, strlen(sender));
328 /* Add message filter */
329 if (eina_list_count(edbus_watch_list) == 0) {
330 ret = dbus_connection_add_filter(conn, message_filter, NULL, NULL);
332 _E("fail to add message filter!");
336 _I("success to add message filter!");
339 /* Add sender to watch list */
340 EINA_LIST_APPEND(edbus_watch_list, watch);
342 snprintf(match, sizeof(match), NAME_OWNER_MATCH, watch);
343 dbus_bus_add_match(conn, match, NULL);
345 _I("%s is watched by dbus!", watch);
348 static unregister_edbus_watch_all(void)
352 struct edbus_list *watch;
354 EINA_LIST_FOREACH_SAFE(edbus_watch_list, n, next, watch) {
355 snprintf(match, sizeof(match), NAME_OWNER_MATCH, watch);
356 dbus_bus_remove_match(conn, match, NULL);
357 EINA_LIST_REMOVE(edbus_watch_list, watch);
362 static void edbus_init(void *data)
364 int retry = EDBUS_INIT_RETRY_COUNT;
368 edbus_init_val = e_dbus_init();
372 _E("fail to init edbus");
377 retry = EDBUS_INIT_RETRY_COUNT;
379 edbus_conn = e_dbus_bus_get(DBUS_BUS_SYSTEM);
383 _E("fail to get edbus");
384 goto err_dbus_shutdown;
388 retry = EDBUS_INIT_RETRY_COUNT;
390 edbus_request_name = e_dbus_request_name(edbus_conn, BUS_NAME, 0, NULL, NULL);
391 if (edbus_request_name)
394 _E("fail to request edbus name");
399 for (i = 0; i < ARRAY_SIZE(edbus_objects); i++) {
400 r = register_edbus_interface(&edbus_objects[i]);
402 _E("fail to add obj & interface for %s",
403 edbus_objects[i].interface);
405 _I("add new obj for %s", edbus_objects[i].interface);
410 e_dbus_connection_close(edbus_conn);
416 static void edbus_exit(void *data)
418 unregister_edbus_signal_handle();
419 dbus_connection_remove_filter(conn, message_filter, NULL);
420 unregister_edbus_watch_all();
421 e_dbus_connection_close(edbus_conn);
425 const struct device_ops edbus_device_ops = {