ecore-drm: Add ecore_drm_dbus file for dbus functions
authorChris Michael <cp.michael@samsung.com>
Tue, 15 Jul 2014 13:28:57 +0000 (09:28 -0400)
committerChris Michael <cp.michael@samsung.com>
Tue, 15 Jul 2014 13:44:14 +0000 (09:44 -0400)
Signed-off-by: Chris Michael <cp.michael@samsung.com>
src/lib/ecore_drm/ecore_drm_dbus.c [new file with mode: 0644]

diff --git a/src/lib/ecore_drm/ecore_drm_dbus.c b/src/lib/ecore_drm/ecore_drm_dbus.c
new file mode 100644 (file)
index 0000000..1998602
--- /dev/null
@@ -0,0 +1,819 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "ecore_drm_private.h"
+#include <sys/eventfd.h>
+
+static DBusConnection *conn;
+static DBusPendingCall *dpending;
+static Ecore_Fd_Handler *_dbus_hdlr;
+static Ecore_Fd_Handler *_watch_hdlr;
+static char *dpath;
+static const char *sid;
+
+static void 
+_dbus_session_removed(DBusMessage *msg)
+{
+   const char *n, *o;
+   dbus_bool_t ret;
+
+   ret = dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &n, 
+                               DBUS_TYPE_OBJECT_PATH, &o, DBUS_TYPE_INVALID);
+   if (!ret) return;
+
+   if (!strcmp(n, sid))
+     {
+        ERR("DBus Session Closed");
+//        ecore_main_loop_quit();
+     }
+}
+
+static void 
+_dbus_cb_notify(DBusPendingCall *pending, void *data EINA_UNUSED)
+{
+   DBusMessage *msg;
+   DBusMessageIter iter, s;
+   dbus_bool_t ret;
+   int type = 0;
+
+   dbus_pending_call_unref(dpending);
+   dpending = NULL;
+
+   msg = dbus_pending_call_steal_reply(pending);
+   if (!msg) return;
+
+   type = dbus_message_get_type(msg);
+   if (type != DBUS_MESSAGE_TYPE_METHOD_RETURN) goto err;
+
+   if ((!dbus_message_iter_init(msg, &iter)) || 
+       (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT))
+     goto err;
+
+   dbus_message_iter_recurse(&iter, &s);
+
+   if (dbus_message_iter_get_arg_type(&s) != DBUS_TYPE_BOOLEAN)
+     goto err;
+
+   dbus_message_iter_get_basic(&s, &ret);
+   if (!ret) 
+     {
+        /* TODO: emit active signal to compositor ? */
+     }
+
+err:
+   dbus_message_unref(msg);
+}
+
+static void 
+_dbus_active_get(void)
+{
+   DBusPendingCall *pend;
+   DBusMessage *msg;
+   dbus_bool_t ret;
+   const char *iface, *n;
+
+   msg = 
+     dbus_message_new_method_call("org.freedesktop.login1", dpath, 
+                                  "org.freedesktop.DBus.Properties", "Get");
+   if (!msg) return;
+
+   iface = "org.freedesktop.login1.Session";
+   n = "Active";
+
+   ret = dbus_message_append_args(msg, DBUS_TYPE_STRING, &iface, 
+                                  DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID);
+   if (!ret) goto err;
+
+   ret = dbus_connection_send_with_reply(conn, msg, &pend, -1);
+   if (!ret) goto err;
+
+   ret = dbus_pending_call_set_notify(pend, _dbus_cb_notify, NULL, NULL);
+   if (!ret)
+     {
+        dbus_pending_call_cancel(pend);
+        dbus_pending_call_unref(pend);
+        goto err;
+     }
+
+   if (dpending)
+     {
+        dbus_pending_call_cancel(dpending);
+        dbus_pending_call_unref(dpending);
+     }
+
+   dpending = pend;
+
+   return;
+
+err:
+   dbus_message_unref(msg);
+}
+
+static void 
+_dbus_property_changed(DBusMessage *msg)
+{
+   DBusMessageIter iter, s, ent;
+   const char *iface, *n;
+   dbus_bool_t ret;
+
+   if ((!dbus_message_iter_init(msg, &iter)) || 
+       (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING))
+     return;
+
+   dbus_message_iter_get_basic(&iter, &iface);
+
+   if ((!dbus_message_iter_next(&iter)) || 
+       (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY))
+     return;
+
+   dbus_message_iter_recurse(&iter, &s);
+   while (dbus_message_iter_get_arg_type(&s) == DBUS_TYPE_DICT_ENTRY)
+     {
+        dbus_message_iter_recurse(&s, &ent);
+        if (dbus_message_iter_get_arg_type(&ent) != DBUS_TYPE_STRING)
+          return;
+
+        dbus_message_iter_get_basic(&ent, &n);
+        if (!dbus_message_iter_next(&ent)) return;
+
+        if (!strcmp(n, "Active"))
+          {
+             if (dbus_message_iter_get_arg_type(&ent) == DBUS_TYPE_BOOLEAN)
+               {
+                  dbus_message_iter_get_basic(&ent, &ret);
+                  if (!ret)
+                    {
+                       /* TODO: emit active signal to compositor ? */
+                    }
+                  return;
+               }
+          }
+
+        dbus_message_iter_next(&s);
+     }
+
+   if ((!dbus_message_iter_next(&iter)) || 
+       (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY))
+     return;
+
+   dbus_message_iter_recurse(&iter, &s);
+   while (dbus_message_iter_get_arg_type(&s) == DBUS_TYPE_STRING)
+     {
+        dbus_message_iter_get_basic(&s, &n);
+        if (!strcmp(n, "Active"))
+          {
+             _dbus_active_get();
+             return;
+          }
+
+        dbus_message_iter_next(&s);
+     }
+}
+
+static void 
+_dbus_device_pause_done(uint32_t major, uint32_t minor)
+{
+   DBusMessage *msg;
+   dbus_bool_t ret;
+
+   msg = dbus_message_new_method_call("org.freedesktop.login1", dpath, 
+                                      "org.freedesktop.login1.Session", 
+                                      "PauseDeviceComplete");
+   if (msg)
+     {
+        ret = dbus_message_append_args(msg, DBUS_TYPE_UINT32, &major, 
+                                       DBUS_TYPE_UINT32, &minor, 
+                                       DBUS_TYPE_INVALID);
+        if (ret)
+          dbus_connection_send(conn, msg, NULL);
+
+        dbus_message_unref(msg);
+     }
+}
+
+static void 
+_dbus_device_paused(DBusMessage *msg)
+{
+   dbus_bool_t ret;
+   const char *type;
+   uint32_t maj, min;
+
+   ret = dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &maj, 
+                               DBUS_TYPE_UINT32, &min, 
+                               DBUS_TYPE_STRING, &type, DBUS_TYPE_INVALID);
+   if (!ret) return;
+
+   if (!strcmp(type, "pause"))
+     _dbus_device_pause_done(maj, min);
+
+   if (maj == DRM_MAJOR)
+     {
+        /* TODO: emit active signal to compositor ? */
+     }
+}
+
+static void 
+_dbus_device_resumed(DBusMessage *msg)
+{
+   dbus_bool_t ret;
+   uint32_t maj;
+
+   ret = dbus_message_get_args(msg, NULL, 
+                               DBUS_TYPE_UINT32, &maj, DBUS_TYPE_INVALID);
+   if (!ret) return;
+
+   if (maj == DRM_MAJOR)
+     {
+        /* TODO: emit active signal to compositor ? */
+     }
+}
+
+static void 
+_dbus_device_release(uint32_t major, uint32_t minor)
+{
+   DBusMessage *msg;
+
+   msg = dbus_message_new_method_call("org.freedesktop.login1", dpath, 
+                                      "org.freedesktop.login1.Session", 
+                                      "ReleaseDevice");
+   if (msg)
+     {
+        dbus_bool_t ret;
+
+        ret = dbus_message_append_args(msg, DBUS_TYPE_UINT32, &major, 
+                                       DBUS_TYPE_UINT32, &minor, 
+                                       DBUS_TYPE_INVALID);
+        if (ret) dbus_connection_send(conn, msg, NULL);
+        dbus_message_unref(msg);
+     }
+}
+
+static int 
+_dbus_device_take(uint32_t major, uint32_t minor)
+{
+   DBusMessage *msg, *rep;
+   DBusError err;
+   dbus_bool_t p, ret;
+   int fd = -1;
+
+   msg = dbus_message_new_method_call("org.freedesktop.login1", dpath, 
+                                      "org.freedesktop.login1.Session", 
+                                      "TakeDevice");
+   if (!msg) return -1;
+
+   ret = dbus_message_append_args(msg, DBUS_TYPE_UINT32, &major, 
+                                  DBUS_TYPE_UINT32, &minor, DBUS_TYPE_INVALID);
+   if (!ret) goto err;
+
+   dbus_error_init(&err);
+
+   rep = 
+     dbus_connection_send_with_reply_and_block(conn, msg, -1, &err);
+   if (!rep)
+     {
+        if (dbus_error_has_name(&err, DBUS_ERROR_UNKNOWN_METHOD))
+          ERR("Old Systemd Version detected");
+        else if (dbus_error_is_set(&err))
+          ERR("DBusError: %s %s", err.name, err.message);
+        dbus_error_free(&err);
+        goto err;
+     }
+
+   ret = dbus_message_get_args(rep, &err, DBUS_TYPE_UNIX_FD, &fd, 
+                               DBUS_TYPE_BOOLEAN, &p, DBUS_TYPE_INVALID);
+   if (!ret) 
+     {
+        if (dbus_error_is_set(&err))
+          ERR("DBusError: %s %s", err.name, err.message);
+
+        dbus_error_free(&err);
+        goto err_rep;
+     }
+
+   return fd;
+
+err_rep:
+   dbus_message_unref(rep);
+err:
+   dbus_message_unref(msg);
+   return -1;
+}
+
+static int 
+_dbus_device_open(const char *path)
+{
+   struct stat st;
+   int ret, fl, fd = -1;
+   /* char name[256] = "unknown"; */
+
+   if ((ret = stat(path, &st)) < 0) return -1;
+   if (!S_ISCHR(st.st_mode)) return -1;
+
+   fd = _dbus_device_take(major(st.st_rdev), minor(st.st_rdev));
+   if (fd < 0)
+     {
+        ERR("Failed to take device: %s", path);
+        return -1;
+     }
+
+   if ((fl = fcntl(fd, F_GETFL)) < 0)
+     {
+        ERR("Failed to get file flags: %m");
+        goto flag_err;
+     }
+
+   fl = (O_RDWR | O_NONBLOCK);
+
+   if ((ret = fcntl(fd, F_SETFL, fl)) < 0)
+     {
+        ERR("Failed to set file flags: %m");
+        goto flag_err;
+     }
+
+   if ((fl = fcntl(fd, F_GETFD)) < 0)
+     {
+        ERR("Failed to get file fd: %m");
+        goto flag_err;
+     }
+
+   fl &= ~FD_CLOEXEC;
+
+   if ((ret = fcntl(fd, F_SETFD, fl)) < 0)
+     {
+        ERR("Failed to set file fds: %m");
+        goto flag_err;
+     }
+
+   /* if (ioctl(fd, EVIOCGNAME(sizeof(name)), name) < 0) */
+   /*   { */
+   /*      ERR("Could not get device name: %m"); */
+   /*      goto flag_err; */
+   /*   } */
+   /* else */
+   /*   { */
+   /*      name[sizeof(name) - 1] = '\0'; */
+   /*      DBG("%s Opened", name); */
+   /*   } */
+
+   return fd;
+
+flag_err:
+   _dbus_device_release(major(st.st_rdev), minor(st.st_rdev));
+   return -1;
+}
+
+static DBusHandlerResult 
+_dbus_cb_filter(DBusConnection *conn EINA_UNUSED, DBusMessage *msg, void *data EINA_UNUSED)
+{
+   if (dbus_message_is_signal(msg, DBUS_INTERFACE_LOCAL, "Disconnected"))
+     {
+        ERR("DBus Disconnected");
+     }
+   else if (dbus_message_is_signal(msg, "org.freedesktop.login1.Manager", 
+                                   "SessionRemoved"))
+     _dbus_session_removed(msg);
+   else if (dbus_message_is_signal(msg, "org.freedesktop.DBus.Properties", 
+                                   "PropertiesChanged"))
+     _dbus_property_changed(msg);
+   else if (dbus_message_is_signal(msg, "org.freedesktop.login1.Session", 
+                                   "PauseDevice"))
+     _dbus_device_paused(msg);
+   else if (dbus_message_is_signal(msg, "org.freedesktop.login1.Sesion", 
+                                   "ResumeDevice"))
+     _dbus_device_resumed(msg);
+
+   return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static Eina_Bool 
+_dbus_cb_dispatch(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED)
+{
+   DBusConnection *conn;
+   int ret = 0;
+
+   if (!(conn = data)) return ECORE_CALLBACK_CANCEL;
+
+   do
+     {
+        ret = dbus_connection_dispatch(conn);
+        switch (ret)
+          {
+           case DBUS_DISPATCH_COMPLETE:
+             ret = 0;
+             break;
+           case DBUS_DISPATCH_DATA_REMAINS:
+             ret = -EAGAIN;
+             break;
+           case DBUS_DISPATCH_NEED_MEMORY:
+             ret = -ENOMEM;
+             break;
+           default:
+             ret = -EIO;
+             break;
+          }
+     } while (ret == -EAGAIN);
+
+   return ECORE_CALLBACK_RENEW;
+}
+
+static Eina_Bool
+_dbus_cb_watch(void *data, Ecore_Fd_Handler *hdlr)
+{
+   DBusWatch *watch;
+   uint32_t flags = 0;
+
+   if (!(watch = data)) return ECORE_CALLBACK_RENEW;
+
+   if (dbus_watch_get_enabled(watch))
+     {
+        if (ecore_main_fd_handler_active_get(hdlr, ECORE_FD_READ))
+          flags |= DBUS_WATCH_READABLE;
+        if (ecore_main_fd_handler_active_get(hdlr, ECORE_FD_WRITE))
+          flags |= DBUS_WATCH_WRITABLE;
+        if (ecore_main_fd_handler_active_get(hdlr, ECORE_FD_ERROR))
+          flags |= DBUS_WATCH_ERROR;
+
+        dbus_watch_handle(watch, flags);
+     }
+
+   return ECORE_CALLBACK_RENEW;
+}
+
+static dbus_bool_t 
+_dbus_watch_add(DBusWatch *watch, void *data EINA_UNUSED)
+{
+   uint32_t msk = 0, flags = 0;
+   int fd = -1;
+
+   msk |= ECORE_FD_ERROR;
+   if (dbus_watch_get_enabled(watch))
+     {
+        flags = dbus_watch_get_flags(watch);
+        if (flags & DBUS_WATCH_READABLE)
+          msk |= ECORE_FD_READ;
+        if (flags & DBUS_WATCH_WRITABLE)
+          msk |= ECORE_FD_WRITE;
+     }
+
+   fd = dbus_watch_get_unix_fd(watch);
+
+   _watch_hdlr =
+     ecore_main_fd_handler_add(fd, msk, _dbus_cb_watch, watch, NULL, NULL);
+
+   dbus_watch_set_data(watch, _watch_hdlr, NULL);
+
+   return TRUE;
+}
+
+static void 
+_dbus_watch_del(DBusWatch *watch, void *data EINA_UNUSED)
+{
+   Ecore_Fd_Handler *hdlr;
+
+   if (!(hdlr = dbus_watch_get_data(watch))) return;
+   ecore_main_fd_handler_del(hdlr);
+   _watch_hdlr = NULL;
+}
+
+static void 
+_dbus_watch_toggle(DBusWatch *watch, void *data EINA_UNUSED)
+{
+   uint32_t flags = 0, mask = 0;
+   Ecore_Fd_Handler *hdlr;
+
+   if (!(hdlr = dbus_watch_get_data(watch))) return;
+
+   if (dbus_watch_get_enabled(watch))
+     {
+        flags = dbus_watch_get_flags(watch);
+        if (flags & DBUS_WATCH_READABLE)
+          mask |= ECORE_FD_READ;
+        if (flags & DBUS_WATCH_WRITABLE)
+          mask |= ECORE_FD_WRITE;
+     }
+
+   ecore_main_fd_handler_active_set(hdlr, mask);
+}
+
+static Eina_Bool 
+_dbus_cb_timeout(void *data)
+{
+   DBusTimeout *timeout;
+
+   if (!(timeout = data)) return ECORE_CALLBACK_RENEW;
+
+   if (dbus_timeout_get_enabled(timeout))
+     dbus_timeout_handle(timeout);
+
+   return ECORE_CALLBACK_RENEW;
+}
+
+static dbus_bool_t 
+_dbus_timeout_add(DBusTimeout *timeout, void *data EINA_UNUSED)
+{
+   if (dbus_timeout_get_enabled(timeout))
+     {
+        Ecore_Timer *tmr = NULL;
+        int tme;
+
+        tme = dbus_timeout_get_interval(timeout);
+        if (!(tmr = ecore_timer_loop_add(tme, _dbus_cb_timeout, timeout)))
+          return EINA_FALSE;
+
+        dbus_timeout_set_data(timeout, tmr, NULL);
+     }
+
+   return EINA_TRUE;
+}
+
+static void 
+_dbus_timeout_del(DBusTimeout *timeout, void *data EINA_UNUSED)
+{
+   Ecore_Timer *tmr = NULL;
+
+   if (!(tmr = dbus_timeout_get_data(timeout))) return;
+   ecore_timer_del(tmr);
+}
+
+static void 
+_dbus_timeout_toggle(DBusTimeout *timeout, void *data EINA_UNUSED)
+{
+   Ecore_Timer *tmr = NULL;
+
+   if (!(tmr = dbus_timeout_get_data(timeout))) return;
+
+   if (dbus_timeout_get_enabled(timeout))
+     ecore_timer_thaw(tmr);
+   else
+     ecore_timer_freeze(tmr);
+}
+
+static Eina_Bool 
+_dbus_match_add(DBusConnection *conn, const char *format, ...)
+{
+   DBusError err;
+   va_list lst;
+   char *tmp;
+   int ret;
+
+   va_start(lst, format);
+   ret = vasprintf(&tmp, format, lst);
+   va_end(lst);
+
+   if (ret < 0) return EINA_FALSE;
+
+   dbus_error_init(&err);
+   dbus_bus_add_match(conn, tmp, &err);
+   free(tmp);
+
+   if (dbus_error_is_set(&err))
+     {
+        dbus_error_free(&err);
+        return EINA_FALSE;
+     }
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool 
+_dbus_signal_add(DBusConnection *conn, const char *sender, const char *iface, const char *mem, const char *path)
+{
+   return _dbus_match_add(conn, "type='signal',sender='%s',"
+                          "interface='%s',member='%s',path='%s'", 
+                          sender, iface, mem, path);
+}
+
+static Eina_Bool 
+_dbus_setup(void)
+{
+   int ret = 0;
+   dbus_bool_t res;
+
+   ret = asprintf(&dpath, "/org/freedesktop/login1/session/%s", sid);
+   if (ret < 0) return EINA_FALSE;
+
+   res = dbus_connection_add_filter(conn, _dbus_cb_filter, NULL, NULL);
+   if (!res)
+     {
+        ERR("Could not setup dbus filter: %m\n");
+        goto err;
+     }
+
+   res = _dbus_signal_add(conn, "org.freedesktop.login1", 
+                          "org.freedesktop.login1.Manager", 
+                          "SessionRemoved", "/org/freedesktop/login1");
+   if (!res) goto err;
+
+   res = _dbus_signal_add(conn, "org.freedesktop.login1", 
+                          "org.freedesktop.login1.Session", 
+                          "PauseDevice", dpath);
+   if (!res) goto err;
+
+   res = _dbus_signal_add(conn, "org.freedesktop.login1", 
+                          "org.freedesktop.login1.Session", 
+                          "ResumeDevice", dpath);
+   if (!res) goto err;
+
+   res = _dbus_signal_add(conn, "org.freedesktop.login1", 
+                          "org.freedesktop.DBus.Properties", 
+                          "PropertiesChanged", dpath);
+   if (!res) goto err;
+
+   return EINA_TRUE;
+
+err:
+   free(dpath);
+   return EINA_FALSE;
+}
+
+static Eina_Bool 
+_dbus_control_take(void)
+{
+   DBusError err;
+   DBusMessage *msg, *rep;
+   dbus_bool_t f = EINA_FALSE;
+
+   dbus_error_init(&err);
+
+   msg = 
+     dbus_message_new_method_call("org.freedesktop.login1", dpath, 
+                                  "org.freedesktop.login1.Session", 
+                                  "TakeControl");
+   if (!msg) goto err;
+
+   if (!dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &f, DBUS_TYPE_INVALID))
+     goto msg_err;
+
+   rep = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err);
+   if (!rep)
+     {
+        if (dbus_error_has_name(&err, DBUS_ERROR_UNKNOWN_METHOD))
+          ERR("Old Systemd Version detected\n");
+        goto msg_err;
+     }
+
+   dbus_message_unref(rep);
+   dbus_message_unref(msg);
+   dbus_error_free(&err);
+
+   return EINA_TRUE;
+
+msg_err:
+   dbus_message_unref(msg);
+err:
+   if (dbus_error_is_set(&err))
+     ERR("DBusError: %s %s", err.name, err.message);
+   dbus_error_free(&err);
+   return EINA_FALSE;
+}
+
+static void 
+_dbus_control_release(void)
+{
+   DBusMessage *msg;
+
+   msg = 
+     dbus_message_new_method_call("org.freedesktop.login1", dpath, 
+                                  "org.freedesktop.login1.Session", 
+                                  "ReleaseControl");
+   if (msg)
+     {
+        dbus_connection_send(conn, msg, NULL);
+        dbus_message_unref(msg);
+     }
+}
+
+static Eina_Bool 
+_dbus_bind(DBusConnection *conn)
+{
+   int fd = -1;
+
+   if ((fd = eventfd(0, EFD_CLOEXEC)) < 0)
+     {
+        ERR("Could not create eventfd: %m");
+        return EINA_FALSE;
+     }
+
+   _dbus_hdlr = 
+     ecore_main_fd_handler_add(fd, (ECORE_FD_READ | ECORE_FD_WRITE), 
+                               _dbus_cb_dispatch, conn, NULL, NULL);
+   if (!_dbus_hdlr)
+     {
+        ERR("Failed to create ecore fd handler");
+        goto hdlr_err;
+     }
+
+   if (!dbus_connection_set_watch_functions(conn, _dbus_watch_add, 
+                                            _dbus_watch_del, 
+                                            _dbus_watch_toggle, NULL, NULL))
+     {
+        ERR("Failed to set dbus watch functions: %m");
+        goto watch_err;
+     }
+
+   if (!dbus_connection_set_timeout_functions(conn, _dbus_timeout_add, 
+                                              _dbus_timeout_del, 
+                                              _dbus_timeout_toggle, 
+                                              NULL, NULL))
+     {
+        ERR("Failed to set dbus timeout functions: %m");
+        goto timeout_err;
+     }
+
+   dbus_connection_ref(conn);
+
+   return EINA_TRUE;
+
+timeout_err:
+   dbus_connection_set_watch_functions(conn, NULL, NULL, NULL, NULL, NULL);
+watch_err:
+   ecore_main_fd_handler_del(_dbus_hdlr);
+   _dbus_hdlr = NULL;
+hdlr_err:
+   close(fd);
+   return EINA_FALSE;
+}
+
+static DBusConnection *
+_dbus_open(void)
+{
+   DBusConnection *conn;
+
+   dbus_connection_set_change_sigpipe(EINA_FALSE);
+
+   conn = dbus_bus_get_private(DBUS_BUS_SYSTEM, NULL);
+   if (!conn)
+     {
+        ERR("Failed to get dbus connection: %m");
+        goto conn_err;
+     }
+
+   dbus_connection_set_exit_on_disconnect(conn, EINA_FALSE);
+
+   if (!_dbus_bind(conn))
+     {
+        ERR("Failed to bind dbus: %m");
+        goto bind_err;
+     }
+
+   return conn;
+
+bind_err:
+   dbus_connection_close(conn);
+   dbus_connection_unref(conn);
+conn_err:
+   return NULL;
+}
+
+static void 
+_dbus_close(void)
+{
+   dbus_connection_set_timeout_functions(conn, NULL, NULL, NULL, NULL, NULL);
+   dbus_connection_set_watch_functions(conn, NULL, NULL, NULL, NULL, NULL);
+
+   if (_dbus_hdlr) ecore_main_fd_handler_del(_dbus_hdlr);
+   _dbus_hdlr = NULL;
+
+   dbus_connection_close(conn);
+   dbus_connection_unref(conn);
+}
+
+Eina_Bool 
+_ecore_drm_dbus_init(const char *session)
+{
+   if (conn) return EINA_TRUE;
+
+   /* try to init dbus */
+   if (!(conn = _dbus_open())) return EINA_FALSE;
+
+   sid = eina_stringshare_add(session);
+
+   /* try to setup signal handlers */
+   if (!_dbus_setup()) goto setup_err;
+
+   /* try to take control of the session */
+   if (!_dbus_control_take()) goto setup_err;
+
+   return EINA_TRUE;
+
+setup_err:
+   _dbus_close();
+   eina_stringshare_del(sid);
+   return EINA_FALSE;
+}
+
+void 
+_ecore_drm_dbus_shutdown(void)
+{
+   _dbus_control_release();
+   _dbus_close();
+   eina_stringshare_del(sid);
+   free(dpath);
+}
+
+int 
+_ecore_drm_dbus_device_open(const char *device)
+{
+   return _dbus_device_open(device);
+}