diff --git a/configure.ac b/configure.ac index 6946c0d479..ac8ae99298 100644 --- a/configure.ac +++ b/configure.ac @@ -2861,6 +2861,44 @@ EFL_EVAL_PKGS([ECORE_WAYLAND]) EFL_LIB_END_OPTIONAL([Ecore_Wayland]) #### End of Ecore_Wayland + +#### Eldbus +EFL_LIB_START([Eldbus]) + +### Additional options to configure + +### Default values + +### Checks for programs + +## Compatibility layers +EFL_PLATFORM_DEPEND([ELDBUS], [evil]) + +### Checks for libraries +EFL_INTERNAL_DEPEND_PKG([ELDBUS], [ecore]) +EFL_INTERNAL_DEPEND_PKG([ELDBUS], [eo]) +EFL_INTERNAL_DEPEND_PKG([ELDBUS], [eina]) + +EFL_DEPEND_PKG([ELDBUS], [DBUS], [dbus-1]) + +EFL_EVAL_PKGS([ELDBUS]) + +### Checks for header files + +### Checks for types + +### Checks for structures + +### Checks for compiler characteristics + +### Checks for linker characteristics + +### Checks for library functions + +EFL_LIB_END([Eldbus]) +#### End of Eldbus + + #### Ecore_Drm EFL_LIB_START_OPTIONAL([Ecore_Drm], [test "${want_drm}" = "yes"]) @@ -2877,10 +2915,11 @@ AC_SUBST([SUID_LDFLAGS]) ### Checks for libraries EFL_INTERNAL_DEPEND_PKG([ECORE_DRM], [ecore]) EFL_INTERNAL_DEPEND_PKG([ECORE_DRM], [ecore-input]) +EFL_INTERNAL_DEPEND_PKG([ECORE_DRM], [eldbus]) EFL_INTERNAL_DEPEND_PKG([ECORE_DRM], [eo]) EFL_INTERNAL_DEPEND_PKG([ECORE_DRM], [eina]) -EFL_DEPEND_PKG([ECORE_DRM], [DRM], [libudev >= 148 libdrm >= 2.4 xkbcommon >= 0.3.0 libsystemd-login >= 192 dbus-1 gbm]) +EFL_DEPEND_PKG([ECORE_DRM], [DRM], [libudev >= 148 libdrm >= 2.4 xkbcommon >= 0.3.0 libsystemd-login >= 192 gbm]) EFL_EVAL_PKGS([ECORE_DRM]) @@ -3881,42 +3920,6 @@ if test "x${want_eo_id}" = "xyes" ; then AC_DEFINE([HAVE_EO_ID], [1], [Have eo id]) fi -#### Eldbus -EFL_LIB_START([Eldbus]) - -### Additional options to configure - -### Default values - -### Checks for programs - -## Compatibility layers -EFL_PLATFORM_DEPEND([ELDBUS], [evil]) - -### Checks for libraries -EFL_INTERNAL_DEPEND_PKG([ELDBUS], [ecore]) -EFL_INTERNAL_DEPEND_PKG([ELDBUS], [eo]) -EFL_INTERNAL_DEPEND_PKG([ELDBUS], [eina]) - -EFL_DEPEND_PKG([ELDBUS], [DBUS], [dbus-1]) - -EFL_EVAL_PKGS([ELDBUS]) - -### Checks for header files - -### Checks for types - -### Checks for structures - -### Checks for compiler characteristics - -### Checks for linker characteristics - -### Checks for library functions - -EFL_LIB_END([Eldbus]) -#### End of Eldbus - #### Efreet EFL_LIB_START([Efreet]) diff --git a/src/lib/ecore_drm/ecore_drm_dbus.c b/src/lib/ecore_drm/ecore_drm_dbus.c index 61a0f6ccf9..631a4378c6 100644 --- a/src/lib/ecore_drm/ecore_drm_dbus.c +++ b/src/lib/ecore_drm/ecore_drm_dbus.c @@ -1,840 +1,361 @@ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - #include "ecore_drm_private.h" -#include -static DBusConnection *dconn; -static DBusPendingCall *dpending; -static Ecore_Fd_Handler *_dbus_hdlr; -static Ecore_Fd_Handler *_watch_hdlr; -static char *dpath; -static const char *sid; +static int _dbus_init_count = 0; + +static const char *dsession; +static Eldbus_Connection *dconn; +static Eldbus_Object *dobj; static void -_dbus_session_removed(DBusMessage *msg) +_ecore_drm_dbus_device_pause_done(uint32_t major, uint32_t minor) { - const char *n, *o; - dbus_bool_t ret; + Eldbus_Proxy *proxy; + Eldbus_Message *msg; - 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)) + /* try to get the Session proxy */ + if (!(proxy = eldbus_proxy_get(dobj, "org.freedesktop.login1.Session"))) { - ERR("DBus Session Closed"); -// ecore_main_loop_quit(); + ERR("Could not get eldbus session proxy"); + return; + } + + if (!(msg = eldbus_proxy_method_call_new(proxy, "PauseDeviceComplete"))) + { + ERR("Could not create method call for proxy"); + return; + } + + eldbus_message_arguments_append(msg, "uu", major, minor); + eldbus_proxy_send(proxy, msg, NULL, NULL, -1); +} + +static void +_cb_session_removed(void *ctxt EINA_UNUSED, const Eldbus_Message *msg) +{ + const char *errname, *errmsg; + const char *sid; + + DBG("Session Removed"); + + if (eldbus_message_error_get(msg, &errname, &errmsg)) + { + ERR("Eldbus Message Error: %s %s", errname, errmsg); + return; + } + + if (eldbus_message_arguments_get(msg, "s", &sid)) + { + if (!strcmp(sid, dsession)) + ERR("\tCurrent Session Removed!!"); } } static void -_dbus_cb_notify(DBusPendingCall *pending, void *data EINA_UNUSED) +_cb_device_paused(void *ctxt EINA_UNUSED, const Eldbus_Message *msg) { - 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 paused 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(dconn, 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 paused 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(dconn, msg, NULL); - - dbus_message_unref(msg); - } -} - -static void -_dbus_device_paused(DBusMessage *msg) -{ - dbus_bool_t ret; + const char *errname, *errmsg; 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) + if (eldbus_message_error_get(msg, &errname, &errmsg)) { - /* TODO: emit paused signal to compositor ? */ - DBG("Emit Paused Signal To Compositor"); + ERR("Eldbus Message Error: %s %s", errname, errmsg); + return; + } + + if (eldbus_message_arguments_get(msg, "uus", &maj, &min, &type)) + { + if (!strcmp(type, "pause")) + { + /* TODO: device pause done */ + _ecore_drm_dbus_device_pause_done(maj, min); + } + + /* if (maj == DRM_MAJOR) */ + /* { */ + /* // emit paused to compositor */ + /* } */ } } static void -_dbus_device_resumed(DBusMessage *msg) +_cb_device_resumed(void *ctxt EINA_UNUSED, const Eldbus_Message *msg) { - dbus_bool_t ret; + const char *errname, *errmsg; uint32_t maj; - ret = dbus_message_get_args(msg, NULL, - DBUS_TYPE_UINT32, &maj, DBUS_TYPE_INVALID); - if (!ret) return; - - if (maj == DRM_MAJOR) + if (eldbus_message_error_get(msg, &errname, &errmsg)) { - /* TODO: emit active signal to compositor ? */ - DBG("Emit Active Signal To Compositor"); + ERR("Eldbus Message Error: %s %s", errname, errmsg); + return; + } + + if (eldbus_message_arguments_get(msg, "u", &maj)) + { + /* if (maj == DRM_MAJOR) */ + /* { */ + /* // emit active to compositor */ + /* } */ } } static void -_dbus_device_release(uint32_t major, uint32_t minor) +_cb_properties_changed(void *data EINA_UNUSED, Eldbus_Proxy *proxy EINA_UNUSED, void *event) { - DBusMessage *msg; + Eldbus_Proxy_Event_Property_Changed *ev; + /* const Eina_Value *val; */ - msg = dbus_message_new_method_call("org.freedesktop.login1", dpath, - "org.freedesktop.login1.Session", - "ReleaseDevice"); - if (msg) + ev = event; + /* val = ev->value; */ + + DBG("Properties Changed: %s", ev->name); + + if (!strcmp(ev->name, "Active")) { - 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(dconn, msg, NULL); - dbus_message_unref(msg); + /* TODO: Send 'Active' to login1.Session */ } } -static int -_dbus_device_take(uint32_t major, uint32_t minor) +static Eina_Bool +_ecore_drm_dbus_session_take(const char *session) { - DBusMessage *msg, *rep; - DBusError err; - dbus_bool_t p, ret; - int fd = -1; + Eldbus_Proxy *proxy; - 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(dconn, msg, -1, &err); - if (!rep) + if ((session) && (strcmp(session, dsession))) { - 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; + ERR("Invalid session: %s", session); + return EINA_FALSE; } - ret = dbus_message_get_args(rep, &err, DBUS_TYPE_UNIX_FD, &fd, - DBUS_TYPE_BOOLEAN, &p, DBUS_TYPE_INVALID); - if (!ret) + /* try to get the Session proxy */ + if (!(proxy = eldbus_proxy_get(dobj, "org.freedesktop.login1.Session"))) { - if (dbus_error_is_set(&err)) - ERR("DBusError: %s %s", err.name, err.message); - - dbus_error_free(&err); - goto err_rep; + ERR("Could not get eldbus session proxy"); + return EINA_FALSE; } - return fd; + /* send call to take control */ + if (eldbus_proxy_call(proxy, "TakeControl", NULL, NULL, -1, "b", EINA_FALSE)) + { + ERR("Could not send message to proxy"); + return EINA_FALSE; + } -err_rep: - dbus_message_unref(rep); -err: - dbus_message_unref(msg); - return -1; + return EINA_TRUE; +} + +static Eina_Bool +_ecore_drm_dbus_session_release(const char *session) +{ + Eldbus_Proxy *proxy; + + if ((session) && (strcmp(session, dsession))) + { + ERR("Invalid session: %s", session); + return EINA_FALSE; + } + + /* try to get the Session proxy */ + if (!(proxy = eldbus_proxy_get(dobj, "org.freedesktop.login1.Session"))) + { + ERR("Could not get eldbus session proxy"); + return EINA_FALSE; + } + + /* send call to release control */ + if (!eldbus_proxy_call(proxy, "ReleaseControl", NULL, NULL, -1, "")) + ERR("Could not send ReleaseControl message to proxy"); + + return EINA_TRUE; +} + +static void +_ecore_drm_dbus_device_release(uint32_t major, uint32_t minor) +{ + Eldbus_Proxy *proxy; + Eldbus_Message *msg; + + /* try to get the Session proxy */ + if (!(proxy = eldbus_proxy_get(dobj, "org.freedesktop.login1.Session"))) + { + ERR("Could not get eldbus session proxy"); + return; + } + + if (!(msg = eldbus_proxy_method_call_new(proxy, "ReleaseDevice"))) + { + ERR("Could not create method call for proxy"); + return; + } + + eldbus_message_arguments_append(msg, "uu", major, minor); + + eldbus_proxy_send(proxy, msg, NULL, NULL, -1); } static int -_dbus_device_open(const char *path) +_ecore_drm_dbus_device_take(uint32_t major, uint32_t minor, Eldbus_Message_Cb callback, const void *data) { - struct stat st; - int ret, fl, fd = -1; - /* char name[256] = "unknown"; */ + Eldbus_Proxy *proxy; + Eldbus_Message *msg; - 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) + /* try to get the Session proxy */ + if (!(proxy = eldbus_proxy_get(dobj, "org.freedesktop.login1.Session"))) { - ERR("Failed to take device: %s", path); + ERR("Could not get eldbus session proxy"); return -1; } - if ((fl = fcntl(fd, F_GETFL)) < 0) + if (!(msg = eldbus_proxy_method_call_new(proxy, "TakeDevice"))) { - ERR("Failed to get file flags: %m"); - goto flag_err; + ERR("Could not create method call for proxy"); + return -1; } - fl = (O_RDWR | O_NONBLOCK); + eldbus_message_arguments_append(msg, "uu", major, minor); + eldbus_proxy_send(proxy, msg, callback, data, -1); - 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: - close(fd); - _dbus_device_release(major(st.st_rdev), minor(st.st_rdev)); - return -1; -} - -static void -_dbus_device_close(const char *path) -{ - struct stat st; - int ret; - - if ((ret = stat(path, &st)) < 0) return; - if (!S_ISCHR(st.st_mode)) return; - - _dbus_device_release(major(st.st_rdev), minor(st.st_rdev)); -} - -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(dconn, _dbus_cb_filter, NULL, NULL); - if (!res) - { - ERR("Could not setup dbus filter: %m\n"); - goto err; - } - - res = _dbus_signal_add(dconn, "org.freedesktop.login1", - "org.freedesktop.login1.Manager", - "SessionRemoved", "/org/freedesktop/login1"); - if (!res) goto err; - - res = _dbus_signal_add(dconn, "org.freedesktop.login1", - "org.freedesktop.login1.Session", - "PauseDevice", dpath); - if (!res) goto err; - - res = _dbus_signal_add(dconn, "org.freedesktop.login1", - "org.freedesktop.login1.Session", - "ResumeDevice", dpath); - if (!res) goto err; - - res = _dbus_signal_add(dconn, "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(dconn, 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(dconn, 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(dconn, NULL, NULL, NULL, NULL, NULL); - dbus_connection_set_watch_functions(dconn, NULL, NULL, NULL, NULL, NULL); - - if (_dbus_hdlr) ecore_main_fd_handler_del(_dbus_hdlr); - _dbus_hdlr = NULL; - - dbus_connection_close(dconn); - dbus_connection_unref(dconn); -} - -Eina_Bool -_ecore_drm_dbus_init(const char *session) -{ - if (dconn) return EINA_TRUE; - - /* try to init dbus */ - if (!(dconn = _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); + return 1; } int -_ecore_drm_dbus_device_open(const char *device) +_ecore_drm_dbus_init(const char *session) { - return _dbus_device_open(device); + Eldbus_Proxy *proxy; + int ret = 0; + char *dpath; + + if (++_dbus_init_count != 1) return _dbus_init_count; + + if (!session) return --_dbus_init_count; + + /* try to init eldbus */ + if (!eldbus_init()) + { + ERR("Could not init eldbus library"); + return --_dbus_init_count; + } + + dsession = eina_stringshare_add(session); + + /* try to get the dbus connection */ + if (!(dconn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM))) + { + ERR("Failed to get eldbus system connection"); + goto conn_err; + } + + /* assemble dbus path */ + ret = asprintf(&dpath, "/org/freedesktop/login1/session/%s", session); + if (ret < 0) + { + ERR("Could not assemble dbus path"); + goto path_err; + } + + /* try to get the eldbus object */ + if (!(dobj = eldbus_object_get(dconn, "org.freedesktop.login1", dpath))) + { + ERR("Could not get eldbus object: %s", dpath); + goto obj_err; + } + + /* try to get the Manager proxy */ + if (!(proxy = eldbus_proxy_get(dobj, "org.freedesktop.login1.Manager"))) + { + ERR("Could not get eldbus proxy"); + goto proxy_err; + } + + eldbus_proxy_signal_handler_add(proxy, "SessionRemoved", + _cb_session_removed, NULL); + + /* try to get the Session proxy */ + if (!(proxy = eldbus_proxy_get(dobj, "org.freedesktop.login1.Session"))) + { + ERR("Could not get eldbus proxy"); + goto proxy_err; + } + + eldbus_proxy_signal_handler_add(proxy, "PauseDevice", + _cb_device_paused, NULL); + eldbus_proxy_signal_handler_add(proxy, "ResumeDevice", + _cb_device_resumed, NULL); + + /* try to get the Properties proxy */ + if (!(proxy = eldbus_proxy_get(dobj, "org.freedesktop.DBus.Properties"))) + { + ERR("Could not get eldbus proxy"); + goto proxy_err; + } + + eldbus_proxy_properties_monitor(proxy, EINA_TRUE); + eldbus_proxy_event_callback_add(proxy, ELDBUS_PROXY_EVENT_PROPERTY_CHANGED, + _cb_properties_changed, NULL); + + if (!_ecore_drm_dbus_session_take(dsession)) + { + ERR("Failed to take control of session"); + goto session_err; + } + + return _dbus_init_count; + +session_err: + eldbus_proxy_event_callback_del(proxy, ELDBUS_PROXY_EVENT_PROPERTY_CHANGED, + _cb_properties_changed, NULL); +proxy_err: + eldbus_object_unref(dobj); +obj_err: + free(dpath); +path_err: + eldbus_connection_unref(dconn); +conn_err: + eina_stringshare_del(dsession); + eldbus_shutdown(); + return --_dbus_init_count; } -void +int +_ecore_drm_dbus_shutdown(void) +{ + if (--_dbus_init_count != 0) return _dbus_init_count; + + /* release control of the session */ + _ecore_drm_dbus_session_release(dsession); + + /* release dbus object */ + if (dobj) eldbus_object_unref(dobj); + + /* release the dbus connection */ + if (dconn) eldbus_connection_unref(dconn); + + eina_stringshare_del(dsession); + + /* shutdown eldbus library */ + eldbus_shutdown(); + + return _dbus_init_count; +} + +void +_ecore_drm_dbus_device_open(const char *device, Eldbus_Message_Cb callback, const void *data) +{ + struct stat st; + + if (stat(device, &st) < 0) return; + if (!S_ISCHR(st.st_mode)) return; + + _ecore_drm_dbus_device_take(major(st.st_rdev), minor(st.st_rdev), callback, data); +} + +void _ecore_drm_dbus_device_close(const char *device) { - _dbus_device_close(device); + struct stat st; + + if (stat(device, &st) < 0) return; + if (!S_ISCHR(st.st_mode)) return; + + _ecore_drm_dbus_device_release(major(st.st_rdev), minor(st.st_rdev)); } diff --git a/src/lib/ecore_drm/ecore_drm_evdev.c b/src/lib/ecore_drm/ecore_drm_evdev.c index 7ecc1756c1..e78ef179d2 100644 --- a/src/lib/ecore_drm/ecore_drm_evdev.c +++ b/src/lib/ecore_drm/ecore_drm_evdev.c @@ -70,7 +70,7 @@ _device_configure(Ecore_Drm_Evdev *edev) if ((edev->caps & (EVDEV_MOTION_ABS | EVDEV_MOTION_REL)) && (edev->caps & EVDEV_BUTTON)) { - DBG("Input device %s is a pointer", edev->name); + DBG("\tInput device %s is a pointer", edev->name); edev->seat_caps |= EVDEV_SEAT_POINTER; /* FIXME: make this configurable */ @@ -81,7 +81,7 @@ _device_configure(Ecore_Drm_Evdev *edev) if (edev->caps & EVDEV_KEYBOARD) { - DBG("Input device %s is a keyboard", edev->name); + DBG("\tInput device %s is a keyboard", edev->name); edev->seat_caps |= EVDEV_SEAT_KEYBOARD; _device_keyboard_setup(edev); ret = EINA_TRUE; @@ -89,7 +89,7 @@ _device_configure(Ecore_Drm_Evdev *edev) if (edev->caps & EVDEV_TOUCH) { - DBG("Input device %s is a touchpad", edev->name); + DBG("\tInput device %s is a touchpad", edev->name); edev->seat_caps |= EVDEV_SEAT_TOUCH; ret = EINA_TRUE; } @@ -786,7 +786,7 @@ _ecore_drm_evdev_device_create(Ecore_Drm_Seat *seat, const char *path, int fd) if (!_device_configure(edev)) { - ERR("Could not configure input device: %s", name); + ERR("\tCould not configure input device: %s", name); _ecore_drm_evdev_device_destroy(edev); return NULL; } @@ -798,7 +798,7 @@ _ecore_drm_evdev_device_create(Ecore_Drm_Seat *seat, const char *path, int fd) _cb_device_data, edev, NULL, NULL); if (!edev->hdlr) { - ERR("Could not create fd handler"); + ERR("\tCould not create fd handler"); _ecore_drm_evdev_device_destroy(edev); return NULL; } diff --git a/src/lib/ecore_drm/ecore_drm_inputs.c b/src/lib/ecore_drm/ecore_drm_inputs.c index 0320fdcc08..0774b8fc34 100644 --- a/src/lib/ecore_drm/ecore_drm_inputs.c +++ b/src/lib/ecore_drm/ecore_drm_inputs.c @@ -4,7 +4,121 @@ #include "ecore_drm_private.h" +typedef struct _Ecore_Drm_Device_Open_Data Ecore_Drm_Device_Open_Data; +struct _Ecore_Drm_Device_Open_Data +{ + Ecore_Drm_Seat *seat; + const char *node; +}; + /* local functions */ +static int +_device_flags_set(int fd) +{ + int ret, fl; + /* char name[256] = "unknown"; */ + + if (fd < 0) + { + ERR("Failed to take device"); + 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: + close(fd); + return -1; +} + +static void +_cb_device_opened(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED) +{ + Ecore_Drm_Device_Open_Data *d; + Ecore_Drm_Evdev *edev; + Eina_Bool b = EINA_FALSE; + const char *errname, *errmsg; + int fd = -1; + + if (eldbus_message_error_get(msg, &errname, &errmsg)) + { + ERR("Eldbus Message Error: %s %s", errname, errmsg); + return; + } + + if (!(d = data)) return; + + DBG("Device Opened: %s", d->node); + + /* DBUS_TYPE_UNIX_FD == 'h' */ + if (!eldbus_message_arguments_get(msg, "hb", &fd, &b)) + { + ERR("\tCould not get UNIX_FD from eldbus message: %d %d", fd, b); + goto cleanup; + } + + if (!(fd = _device_flags_set(fd))) + { + ERR("\tCould not set fd flags"); + goto release; + } + + if (!(edev = _ecore_drm_evdev_device_create(d->seat, d->node, fd))) + { + ERR("\tCould not create evdev device: %s", d->node); + goto release; + } + + d->seat->devices = eina_list_append(d->seat->devices, edev); + + goto cleanup; + +release: + _ecore_drm_dbus_device_close(d->node); +cleanup: + eina_stringshare_del(d->node); + free(d); +} + static Ecore_Drm_Seat * _seat_get(Ecore_Drm_Input *input, const char *seat) { @@ -30,12 +144,11 @@ _seat_get(Ecore_Drm_Input *input, const char *seat) static Eina_Bool _device_add(Ecore_Drm_Input *input, struct udev_device *device) { - Ecore_Drm_Evdev *edev; + Ecore_Drm_Device_Open_Data *data; Ecore_Drm_Seat *seat; const char *dev_seat, *wl_seat; const char *node; char n[PATH_MAX]; - int fd = -1; if (!(dev_seat = udev_device_get_property_value(device, "ID_SEAT"))) dev_seat = "seat0"; @@ -51,25 +164,13 @@ _device_add(Ecore_Drm_Input *input, struct udev_device *device) node = udev_device_get_devnode(device); strcpy(n, node); - fd = _ecore_drm_dbus_device_open(n); - if (fd < 0) - { - ERR("FAILED TO OPEN %s: %m", n); - return EINA_FALSE; - } + if (!(data = calloc(1, sizeof(Ecore_Drm_Device_Open_Data)))) + return EINA_FALSE; - /* DBG("Opened Restricted Input: %s %d", node, fd); */ + data->seat = seat; + data->node = eina_stringshare_add(n); - if (!(edev = _ecore_drm_evdev_device_create(seat, node, fd))) - { - ERR("Could not create evdev device: %s", node); - close(fd); - return EINA_FALSE; - } - - seat->devices = eina_list_append(seat->devices, edev); - - /* TODO: finish */ + _ecore_drm_dbus_device_open(n, _cb_device_opened, data); return EINA_TRUE; } @@ -106,8 +207,6 @@ _cb_input_event(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED) struct udev_device *udevice; const char *act; - DBG("Input Event"); - if (!(input = data)) return EINA_FALSE; if (!(udevice = udev_monitor_receive_device(input->monitor))) @@ -119,17 +218,13 @@ _cb_input_event(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED) goto err; if (!strcmp(act, "add")) - { - DBG("\tDevice Added"); - _device_add(input, udevice); - } + _device_add(input, udevice); else if (!strcmp(act, "remove")) { const char *node; node = udev_device_get_devnode(udevice); - DBG("\tDevice Removed: %s", node); _device_remove(input, node); } diff --git a/src/lib/ecore_drm/ecore_drm_private.h b/src/lib/ecore_drm/ecore_drm_private.h index 34484cc516..68f3afabf2 100644 --- a/src/lib/ecore_drm/ecore_drm_private.h +++ b/src/lib/ecore_drm/ecore_drm_private.h @@ -1,6 +1,10 @@ #ifndef _ECORE_DRM_PRIVATE_H # define _ECORE_DRM_PRIVATE_H +# ifdef HAVE_CONFIG_H +# include "config.h" +# endif + # include "Ecore.h" # include "ecore_private.h" # include "Ecore_Input.h" @@ -18,7 +22,6 @@ # include # include //# include -# include # include # include @@ -34,6 +37,7 @@ /* # include */ /* # endif */ +# include # include # define NUM_FRAME_BUFFERS 2 @@ -227,9 +231,9 @@ struct _Ecore_Drm_Sprite unsigned int formats[]; }; -Eina_Bool _ecore_drm_dbus_init(const char *session); -void _ecore_drm_dbus_shutdown(void); -int _ecore_drm_dbus_device_open(const char *device); +int _ecore_drm_dbus_init(const char *session); +int _ecore_drm_dbus_shutdown(void); +void _ecore_drm_dbus_device_open(const char *device, Eldbus_Message_Cb callback, const void *data); void _ecore_drm_dbus_device_close(const char *device); Ecore_Drm_Evdev *_ecore_drm_evdev_device_create(Ecore_Drm_Seat *seat, const char *path, int fd);