forked from enlightenment/efl
ecore-drm: Add ecore_drm_dbus file for dbus functions
Signed-off-by: Chris Michael <cp.michael@samsung.com>
This commit is contained in:
parent
61070f779f
commit
be325af372
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue