--- /dev/null
+From b10ab1a86f35ab793ba6efb49224d9ecdd1b7dbd Mon Sep 17 00:00:00 2001
+From: Seunghun Lee <shiin.lee@samsung.com>
+Date: Tue, 9 Dec 2014 09:36:42 -0500
+Subject: ecore-drm: added drm launcher that is allow to determine whether to
+ launch with logind or root privilege.
+
+Summary:
+- allow to launch drm backend without systemd-logind with root privilege.
+- allow to open drm device node via logind, not directly open it, in case exist systemd-logind.
+- fixes issue that couldn't switch session, because ecore-drm couldn't drop master to drm device with no permission. (allow to switch session appropriate.)
+
+Reviewers: gwanglim, devilhorns
+
+Subscribers: torori, cedric
+
+Differential Revision: https://phab.enlightenment.org/D1704
+
+diff --git a/configure.ac b/configure.ac
+index e09213d..5911192 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -673,13 +673,18 @@ fi
+ AM_CONDITIONAL([HAVE_SYSTEMD_USER_SESSION], [test "x${have_systemd_user_session}" = "xyes"])
+ AC_SUBST([USER_SESSION_DIR])
+
+-
+ if test "x${have_systemd_pkg}" = "xauto" -o "x${have_systemd_pkg}" = "xyes"; then
+ PKG_CHECK_MODULES([SYSTEMD], [libsystemd-daemon >= 192 libsystemd-journal >= 192],
+ [have_systemd_pkg="yes"],
+ [have_systemd_pkg="no"])
+ fi
+
++PKG_CHECK_MODULES(SYSTEMD_LOGIN, [libsystemd-login >= 198],
++ [have_systemd_login=yes], [have_systemd_login=no])
++AS_IF([test "x$have_systemd_login" = "xyes"],
++ [AC_DEFINE([HAVE_SYSTEMD_LOGIN], [1], [Have systemd-login])])
++AM_CONDITIONAL(HAVE_SYSTEMD_LOGIN, test "x$have_systemd_login" = "xyes")
++
+ # check for systemd library if requested
+ if test "x${want_systemd}" = "xyes" -a "x${have_systemd_pkg}" = "xno"; then
+ AC_MSG_ERROR([Systemd dependencie requested but not found])
+@@ -3072,7 +3077,7 @@ EFL_INTERNAL_DEPEND_PKG([ECORE_DRM], [eeze])
+ EFL_INTERNAL_DEPEND_PKG([ECORE_DRM], [eo])
+ EFL_INTERNAL_DEPEND_PKG([ECORE_DRM], [eina])
+
+-EFL_DEPEND_PKG([ECORE_DRM], [DRM], [libdrm >= 2.4 xkbcommon >= 0.3.0 libsystemd-login >= 192 gbm])
++EFL_DEPEND_PKG([ECORE_DRM], [DRM], [libdrm >= 2.4 xkbcommon >= 0.3.0 gbm])
+
+ EFL_EVAL_PKGS([ECORE_DRM])
+
+diff --git a/src/Makefile_Ecore_Drm.am b/src/Makefile_Ecore_Drm.am
+index 8867f37..b558277 100644
+--- a/src/Makefile_Ecore_Drm.am
++++ b/src/Makefile_Ecore_Drm.am
+@@ -16,10 +16,17 @@ lib/ecore_drm/ecore_drm_inputs.c \
+ lib/ecore_drm/ecore_drm_output.c \
+ lib/ecore_drm/ecore_drm_tty.c \
+ lib/ecore_drm/ecore_drm_device.c \
+-lib/ecore_drm/ecore_drm_dbus.c \
++lib/ecore_drm/ecore_drm_launcher.c \
+ lib/ecore_drm/ecore_drm.c \
++lib/ecore_drm/ecore_drm_logind.h \
+ lib/ecore_drm/ecore_drm_private.h
+
++if HAVE_SYSTEMD_LOGIN
++lib_ecore_drm_libecore_drm_la_SOURCES += \
++lib/ecore_drm/ecore_drm_logind.c \
++lib/ecore_drm/ecore_drm_dbus.c
++endif
++
+ lib_ecore_drm_libecore_drm_la_CPPFLAGS = \
+ -I$(top_builddir)/src/lib/efl \
+ @ECORE_DRM_CFLAGS@ \
+diff --git a/src/lib/ecore_drm/Ecore_Drm.h b/src/lib/ecore_drm/Ecore_Drm.h
+index 80efaf5..3238a20 100644
+--- a/src/lib/ecore_drm/Ecore_Drm.h
++++ b/src/lib/ecore_drm/Ecore_Drm.h
+@@ -194,4 +194,6 @@ EAPI Eina_Bool ecore_drm_sprites_crtc_supported(Ecore_Drm_Output *output, unsign
+ EAPI Ecore_Drm_Fb *ecore_drm_fb_create(Ecore_Drm_Device *dev, int width, int height);
+ EAPI void ecore_drm_fb_destroy(Ecore_Drm_Fb *fb);
+
++EAPI Eina_Bool ecore_drm_launcher_connect(Ecore_Drm_Device *dev);
++EAPI void ecore_drm_launcher_disconnect(Ecore_Drm_Device *dev);
+ #endif
+diff --git a/src/lib/ecore_drm/ecore_drm.c b/src/lib/ecore_drm/ecore_drm.c
+index c341c19..6413270 100644
+--- a/src/lib/ecore_drm/ecore_drm.c
++++ b/src/lib/ecore_drm/ecore_drm.c
+@@ -6,7 +6,6 @@
+
+ /* local variables */
+ static int _ecore_drm_init_count = 0;
+-static char *sid;
+
+ /* external variables */
+ int _ecore_drm_log_dom = -1;
+@@ -65,12 +64,6 @@ ecore_drm_init(void)
+ if (!eina_log_domain_level_check(_ecore_drm_log_dom, EINA_LOG_LEVEL_DBG))
+ eina_log_domain_level_set("ecore_drm", EINA_LOG_LEVEL_DBG);
+
+- /* get sd-login properties we need */
+- if (sd_pid_get_session(getpid(), &sid) < 0) goto sd_err;
+-
+- /* try to init dbus */
+- if (!_ecore_drm_dbus_init(sid)) goto dbus_err;
+-
+ /* try to init eeze */
+ if (!eeze_init()) goto eeze_err;
+
+@@ -78,10 +71,6 @@ ecore_drm_init(void)
+ return _ecore_drm_init_count;
+
+ eeze_err:
+- _ecore_drm_dbus_shutdown();
+-dbus_err:
+- free(sid);
+-sd_err:
+ eina_log_domain_unregister(_ecore_drm_log_dom);
+ _ecore_drm_log_dom = -1;
+ log_err:
+@@ -115,9 +104,6 @@ ecore_drm_shutdown(void)
+ /* close eeze */
+ eeze_shutdown();
+
+- /* cleanup dbus */
+- _ecore_drm_dbus_shutdown();
+-
+ /* shutdown ecore_event */
+ ecore_event_shutdown();
+
+@@ -131,8 +117,6 @@ ecore_drm_shutdown(void)
+ /* shutdown eina */
+ eina_shutdown();
+
+- free(sid);
+-
+ /* return init count */
+ return _ecore_drm_init_count;
+ }
+diff --git a/src/lib/ecore_drm/ecore_drm_dbus.c b/src/lib/ecore_drm/ecore_drm_dbus.c
+index 222b5e9..bfac33f 100644
+--- a/src/lib/ecore_drm/ecore_drm_dbus.c
++++ b/src/lib/ecore_drm/ecore_drm_dbus.c
+@@ -175,7 +175,7 @@ _ecore_drm_dbus_session_release(const char *session)
+ return EINA_TRUE;
+ }
+
+-static void
++void
+ _ecore_drm_dbus_device_release(uint32_t major, uint32_t minor)
+ {
+ Eldbus_Proxy *proxy;
+@@ -199,11 +199,35 @@ _ecore_drm_dbus_device_release(uint32_t major, uint32_t minor)
+ eldbus_proxy_send(proxy, msg, NULL, NULL, -1);
+ }
+
+-static int
+-_ecore_drm_dbus_device_take(uint32_t major, uint32_t minor, Eldbus_Message_Cb callback, const void *data)
++static void
++_cb_device_taken(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
++{
++ const char *errname, *errmsg;
++ Ecore_Drm_Open_Cb callback = NULL;
++ Eina_Bool b = EINA_FALSE;
++ int fd = -1;
++
++ if (eldbus_message_error_get(msg, &errname, &errmsg))
++ {
++ ERR("Eldbus Message Error: %s %s", errname, errmsg);
++ goto eldbus_err;
++ }
++
++ /* 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);
++
++eldbus_err:
++ callback = (Ecore_Drm_Open_Cb)eldbus_pending_data_del(pending, "callback");
++ if (callback) callback(data, fd, b);
++}
++
++int
++_ecore_drm_dbus_device_take(uint32_t major, uint32_t minor, Ecore_Drm_Open_Cb callback, void *data)
+ {
+ Eldbus_Proxy *proxy;
+ Eldbus_Message *msg;
++ Eldbus_Pending *pending;
+
+ /* try to get the Session proxy */
+ if (!(proxy = eldbus_proxy_get(dobj, "org.freedesktop.login1.Session")))
+@@ -219,11 +243,45 @@ _ecore_drm_dbus_device_take(uint32_t major, uint32_t minor, Eldbus_Message_Cb ca
+ }
+
+ eldbus_message_arguments_append(msg, "uu", major, minor);
+- eldbus_proxy_send(proxy, msg, callback, data, -1);
++ pending = eldbus_proxy_send(proxy, msg, _cb_device_taken, data, -1);
++ if (callback) eldbus_pending_data_set(pending, "callback", callback);
+
+ return 1;
+ }
+
++int
++_ecore_drm_dbus_device_take_no_pending(uint32_t major, uint32_t minor, Eina_Bool *paused_out, double timeout)
++{
++ Eldbus_Proxy *proxy;
++ Eldbus_Message *msg, *reply;
++ Eina_Bool b;
++ int fd;
++
++ /* try to get the Session proxy */
++ if (!(proxy = eldbus_proxy_get(dobj, "org.freedesktop.login1.Session")))
++ {
++ ERR("Could not get eldbus session proxy");
++ return -1;
++ }
++
++ if (!(msg = eldbus_proxy_method_call_new(proxy, "TakeDevice")))
++ {
++ ERR("Could not create method call for proxy");
++ return -1;
++ }
++
++ if (!eldbus_message_arguments_append(msg, "uu", major, minor))
++ return -1;
++
++ reply = eldbus_proxy_send_and_block(proxy, msg, timeout);
++
++ if (!eldbus_message_arguments_get(reply, "hb", &fd, &b))
++ return -1;
++
++ if (paused_out) *paused_out = b;
++ return fd;
++}
++
+ int
+ _ecore_drm_dbus_init(const char *session)
+ {
+@@ -343,25 +401,3 @@ _ecore_drm_dbus_shutdown(void)
+
+ 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)
+-{
+- 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_device.c b/src/lib/ecore_drm/ecore_drm_device.c
+index e8ca052..957c439e 100644
+--- a/src/lib/ecore_drm/ecore_drm_device.c
++++ b/src/lib/ecore_drm/ecore_drm_device.c
+@@ -254,7 +254,8 @@ ecore_drm_device_open(Ecore_Drm_Device *dev)
+ /* check for valid device */
+ if ((!dev) || (!dev->drm.name)) return EINA_FALSE;
+
+- dev->drm.fd = open(dev->drm.name, O_RDWR | O_CLOEXEC);
++ /* DRM device node is needed immediately to keep going. */
++ dev->drm.fd = _ecore_drm_launcher_device_open_no_pending(dev->drm.name, O_RDWR);
+ if (dev->drm.fd < 0) return EINA_FALSE;
+
+ DBG("Opened Device %s : %d", dev->drm.name, dev->drm.fd);
+@@ -319,7 +320,7 @@ ecore_drm_device_close(Ecore_Drm_Device *dev)
+ if (dev->drm.hdlr) ecore_main_fd_handler_del(dev->drm.hdlr);
+ dev->drm.hdlr = NULL;
+
+- close(dev->drm.fd);
++ _ecore_drm_launcher_device_close(dev->drm.name, dev->drm.fd);
+
+ /* reset device fd */
+ dev->drm.fd = -1;
+diff --git a/src/lib/ecore_drm/ecore_drm_inputs.c b/src/lib/ecore_drm/ecore_drm_inputs.c
+index f03af36..a1ca008 100644
+--- a/src/lib/ecore_drm/ecore_drm_inputs.c
++++ b/src/lib/ecore_drm/ecore_drm_inputs.c
+@@ -57,29 +57,18 @@ flag_err:
+ }
+
+ static void
+-_cb_device_opened(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
++_cb_device_opened(void *data, int fd, Eina_Bool paused 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 (!(d = data)) return;
+
+- if (eldbus_message_error_get(msg, &errname, &errmsg))
+- {
+- ERR("Eldbus Message Error: %s %s", errname, errmsg);
+- ERR("\tFailed to open device: %s", d->node);
+- return;
+- }
+-
+- /* DBG("Input Device Opened: %s", d->node); */
+-
+- /* DBUS_TYPE_UNIX_FD == 'h' */
+- if (!eldbus_message_arguments_get(msg, "hb", &fd, &b))
++ if (fd < 0)
+ {
+ ERR("\tCould not get UNIX_FD from eldbus message: %d %d", fd, b);
++ ERR("\tFailed to open device: %s", d->node);
+ goto cleanup;
+ }
+
+@@ -100,7 +89,7 @@ _cb_device_opened(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending
+ goto cleanup;
+
+ release:
+- _ecore_drm_dbus_device_close(d->node);
++ _ecore_drm_launcher_device_close(d->node, fd);
+ cleanup:
+ eina_stringshare_del(d->node);
+ free(d);
+@@ -162,7 +151,8 @@ _device_add(Ecore_Drm_Input *input, const char *device)
+
+ DBG("\tDevice Path: %s", data->node);
+
+- _ecore_drm_dbus_device_open(data->node, _cb_device_opened, data);
++ if (!_ecore_drm_launcher_device_open(data->node, _cb_device_opened, data, O_RDWR | O_NONBLOCK))
++ goto dev_err;
+
+ return EINA_TRUE;
+
+@@ -311,7 +301,7 @@ ecore_drm_inputs_destroy(Ecore_Drm_Device *dev)
+
+ EINA_LIST_FREE(seat->devices, edev)
+ {
+- _ecore_drm_dbus_device_close(edev->path);
++ _ecore_drm_launcher_device_close(edev->path, edev->fd);
+ _ecore_drm_evdev_device_destroy(edev);
+ }
+ }
+diff --git a/src/lib/ecore_drm/ecore_drm_launcher.c b/src/lib/ecore_drm/ecore_drm_launcher.c
+new file mode 100644
+index 0000000..e2d64d5
+--- /dev/null
++++ b/src/lib/ecore_drm/ecore_drm_launcher.c
+@@ -0,0 +1,139 @@
++#include "ecore_drm_private.h"
++#include "ecore_drm_logind.h"
++
++static Eina_Bool logind = EINA_FALSE;
++
++EAPI Eina_Bool
++ecore_drm_launcher_connect(Ecore_Drm_Device *dev)
++{
++ if (!(logind = _ecore_drm_logind_connect(dev)))
++ {
++ DBG("Launcher: Not Support loignd\n");
++ if (geteuid() == 0)
++ {
++ DBG("Launcher: Try to keep going with root privilege\n");
++ if (!ecore_drm_tty_open(dev, NULL))
++ {
++ ERR("Launcher: failed to open tty with root privilege\n");
++ return EINA_FALSE;
++ }
++ }
++ else
++ {
++ ERR("Launcher: Need Root Privilege or logind\n");
++ return EINA_FALSE;
++ }
++ }
++ DBG("Launcher: Success Connect\n");
++
++ return EINA_TRUE;
++}
++
++EAPI void
++ecore_drm_launcher_disconnect(Ecore_Drm_Device *dev)
++{
++ if (logind)
++ {
++ logind = EINA_FALSE;
++ _ecore_drm_logind_disconnect(dev);
++ }
++ else
++ {
++ ecore_drm_tty_close(dev);
++ }
++}
++
++static int
++_device_flags_set(int fd, int flags)
++{
++ int fl;
++
++ fl = fcntl(fd, F_GETFL);
++ if (fl < 0)
++ return -1;
++
++ if (flags & O_NONBLOCK)
++ fl |= O_NONBLOCK;
++
++ if (fcntl(fd, F_SETFL, fl) < 0)
++ return -1;
++
++ fl = fcntl(fd, F_GETFD);
++ if (fl < 0)
++ return -1;
++
++ if (!(flags & O_CLOEXEC))
++ fl &= ~FD_CLOEXEC;
++
++ if (fcntl(fd, F_SETFD, fl) < 0)
++ return -1;
++
++ return fd;
++}
++
++Eina_Bool
++_ecore_drm_launcher_device_open(const char *device, Ecore_Drm_Open_Cb callback, void *data, int flags)
++{
++ int fd = -1;
++ struct stat s;
++
++ if (logind)
++ {
++ if (!_ecore_drm_logind_device_open(device, callback, data))
++ return EINA_FALSE;
++ }
++ else
++ {
++ fd = open(device, flags | O_CLOEXEC);
++ if (fd < 0) return EINA_FALSE;
++ if (fstat(fd, &s) == -1)
++ {
++ close(fd);
++ fd = -1;
++ return EINA_FALSE;
++ }
++
++ callback(data, fd, EINA_FALSE);
++ }
++
++ return EINA_TRUE;
++}
++
++int
++_ecore_drm_launcher_device_open_no_pending(const char *device, int flags)
++{
++ int fd = -1;
++ struct stat s;
++
++ if (logind)
++ {
++ fd = _ecore_drm_logind_device_open_no_pending(device);
++ if ((fd = _device_flags_set(fd, flags)) == -1)
++ {
++ _ecore_drm_logind_device_close(device);
++ return -1;
++ }
++ }
++ else
++ {
++ fd = open(device, flags, flags | O_CLOEXEC);
++ if (fd < 0) return fd;
++ if (fstat(fd, &s) == -1)
++ {
++ close(fd);
++ return -1;
++ }
++ }
++
++ DBG("Device opened %s", device);
++ return fd;
++}
++
++void
++_ecore_drm_launcher_device_close(const char *device, int fd)
++{
++ if (logind)
++ return _ecore_drm_logind_device_close(device);
++
++ close(fd);
++}
+diff --git a/src/lib/ecore_drm/ecore_drm_logind.c b/src/lib/ecore_drm/ecore_drm_logind.c
+new file mode 100644
+index 0000000..a3c6c1e
+--- /dev/null
++++ b/src/lib/ecore_drm/ecore_drm_logind.c
+@@ -0,0 +1,310 @@
++#include <sys/stat.h>
++#include <sys/ioctl.h>
++#include <linux/vt.h>
++#include <linux/kd.h>
++#include <linux/major.h>
++#include "ecore_drm_private.h"
++#include "ecore_drm_logind.h"
++
++#ifndef KDSKBMUTE
++# define KDSKBMUTE 0x4B51
++#endif
++
++static char *sid;
++
++static Eina_Bool
++_ecore_drm_logind_cb_vt_switch(void *data, int type EINA_UNUSED, void *event)
++{
++ Ecore_Drm_Device *dev;
++ Ecore_Event_Key *ev;
++ int keycode;
++ int vt;
++
++ dev = data;
++ ev = event;
++ keycode = ev->keycode - 8;
++
++ if ((ev->modifiers & ECORE_EVENT_MODIFIER_CTRL) &&
++ (ev->modifiers & ECORE_EVENT_MODIFIER_ALT) &&
++ (keycode >= KEY_F1) && (keycode <= KEY_F8))
++ {
++ vt = (keycode - KEY_F1 + 1);
++
++ if (ioctl(dev->tty.fd, VT_ACTIVATE, vt) < 0)
++ ERR("Failed to activate vt: %m");
++ }
++
++ return ECORE_CALLBACK_PASS_ON;
++}
++
++static Eina_Bool
++_ecore_drm_logind_cb_vt_signal(void *data, int type EINA_UNUSED, void *event)
++{
++ Ecore_Drm_Device *dev;
++ Ecore_Event_Signal_User *ev;
++ siginfo_t sigdata;
++
++ dev = data;
++ ev = event;
++
++ sigdata = ev->data;
++ if (sigdata.si_code != SI_KERNEL) return ECORE_CALLBACK_RENEW;
++
++ if (ev->number == 1)
++ {
++ Ecore_Drm_Input *input;
++ Ecore_Drm_Output *output;
++ Ecore_Drm_Sprite *sprite;
++ Eina_List *l;
++
++ /* disable inputs (suspends) */
++ EINA_LIST_FOREACH(dev->inputs, l, input)
++ ecore_drm_inputs_disable(input);
++
++ /* disable hardware cursor */
++ EINA_LIST_FOREACH(dev->outputs, l, output)
++ ecore_drm_output_cursor_size_set(output, 0, 0, 0);
++
++ /* disable sprites */
++ EINA_LIST_FOREACH(dev->sprites, l, sprite)
++ ecore_drm_sprites_fb_set(sprite, 0, 0);
++
++ if (!ecore_drm_tty_release(dev))
++ ERR("Could not release VT: %m");
++ }
++ else if (ev->number == 2)
++ {
++ if (ecore_drm_tty_acquire(dev))
++ {
++ Ecore_Drm_Output *output;
++ Ecore_Drm_Input *input;
++ Eina_List *l;
++
++ /* set output mode */
++ EINA_LIST_FOREACH(dev->outputs, l, output)
++ ecore_drm_output_enable(output);
++
++ /* enable inputs */
++ EINA_LIST_FOREACH(dev->inputs, l, input)
++ ecore_drm_inputs_enable(input);
++ }
++ else
++ ERR("Could not acquire VT: %m");
++ }
++
++ return ECORE_CALLBACK_PASS_ON;
++}
++
++static Eina_Bool
++_ecore_drm_logind_tty_setup(Ecore_Drm_Device *dev)
++{
++ struct stat st;
++ int kmode;
++ struct vt_mode vtmode = { 0 };
++
++ if (fstat(dev->tty.fd, &st) == -1)
++ {
++ ERR("Failed to get stats for tty: %m");
++ return EINA_FALSE;
++ }
++
++ if (ioctl(dev->tty.fd, KDGETMODE, &kmode))
++ {
++ ERR("Could not get tty mode: %m");
++ return EINA_FALSE;
++ }
++
++ if (ioctl(dev->tty.fd, VT_ACTIVATE, minor(st.st_rdev)) < 0)
++ {
++ ERR("Failed to activate vt: %m");
++ return EINA_FALSE;
++ }
++
++ if (ioctl(dev->tty.fd, VT_WAITACTIVE, minor(st.st_rdev)) < 0)
++ {
++ ERR("Failed to wait active: %m");
++ return EINA_FALSE;
++ }
++
++ /* NB: Don't set this. This Turns OFF keyboard on the VT */
++ /* if (ioctl(dev->tty.fd, KDSKBMUTE, 1) && */
++ /* ioctl(dev->tty.fd, KDSKBMODE, K_OFF)) */
++ /* { */
++ /* ERR("Could not set K_OFF keyboard mode: %m"); */
++ /* return EINA_FALSE; */
++ /* } */
++
++ if (kmode != KD_GRAPHICS)
++ {
++ if (ioctl(dev->tty.fd, KDSETMODE, KD_GRAPHICS))
++ {
++ ERR("Could not set graphics mode: %m");
++ goto err_kmode;
++ }
++ }
++
++ vtmode.mode = VT_PROCESS;
++ vtmode.waitv = 0;
++ vtmode.relsig = SIGUSR1;
++ vtmode.acqsig = SIGUSR2;
++ if (ioctl(dev->tty.fd, VT_SETMODE, &vtmode) < 0)
++ {
++ ERR("Could not set Terminal Mode: %m");
++ goto err_setmode;
++ }
++
++ return EINA_TRUE;
++err_setmode:
++ ioctl(dev->tty.fd, KDSETMODE, KD_TEXT);
++err_kmode:
++ return EINA_FALSE;
++}
++
++
++static Eina_Bool
++_ecore_drm_logind_vt_open(Ecore_Drm_Device *dev, const char *name)
++{
++ char tty[32] = "<stdin>";
++
++ /* check for valid device */
++ if ((!dev) || (!dev->drm.name)) return EINA_FALSE;
++
++ /* assign default tty fd of -1 */
++ dev->tty.fd = -1;
++
++ if (!name)
++ {
++ char *env;
++
++ if ((env = getenv("ECORE_DRM_TTY")))
++ snprintf(tty, sizeof(tty), "%s", env);
++ else
++ dev->tty.fd = dup(STDIN_FILENO);
++ }
++ else
++ snprintf(tty, sizeof(tty), "%s", name);
++
++ if (dev->tty.fd < 0)
++ {
++ DBG("Trying to Open Tty: %s", tty);
++
++ dev->tty.fd = open(tty, O_RDWR | O_NOCTTY);
++ if (dev->tty.fd < 0)
++ {
++ DBG("Failed to Open Tty: %m");
++ return EINA_FALSE;
++ }
++ }
++
++ /* save tty name */
++ dev->tty.name = eina_stringshare_add(tty);
++
++ /* FIXME */
++ if (!_ecore_drm_logind_tty_setup(dev))
++ {
++ close(dev->tty.fd);
++ dev->tty.fd = -1;
++ return EINA_FALSE;
++ }
++
++ /* setup handler for signals */
++ dev->tty.event_hdlr =
++ ecore_event_handler_add(ECORE_EVENT_SIGNAL_USER,
++ _ecore_drm_logind_cb_vt_signal, dev);
++
++ /* setup handler for key event of vt switch */
++ dev->tty.switch_hdlr =
++ ecore_event_handler_add(ECORE_EVENT_KEY_DOWN,
++ _ecore_drm_logind_cb_vt_switch, dev);
++
++ /* set current tty into env */
++ setenv("ECORE_DRM_TTY", tty, 1);
++
++ return EINA_TRUE;
++}
++
++static void
++_ecore_drm_logind_vt_close(Ecore_Drm_Device *dev)
++{
++ struct vt_mode mode = { 0 };
++
++ ioctl(dev->tty.fd, KDSETMODE, KD_TEXT);
++ mode.mode = VT_AUTO;
++ ioctl(dev->tty.fd, VT_SETMODE, &mode);
++
++ if (dev->tty.event_hdlr) ecore_event_handler_del(dev->tty.event_hdlr);
++ dev->tty.event_hdlr = NULL;
++
++ if (dev->tty.switch_hdlr) ecore_event_handler_del(dev->tty.switch_hdlr);
++ dev->tty.switch_hdlr = NULL;
++
++ if (dev->tty.name) eina_stringshare_del(dev->tty.name);
++ dev->tty.name = NULL;
++
++ unsetenv("ECORE_DRM_TTY");
++}
++
++Eina_Bool
++_ecore_drm_logind_connect(Ecore_Drm_Device *dev)
++{
++ /* get sd-login properties we need */
++ if (sd_pid_get_session(getpid(), &sid) < 0) return EINA_FALSE;
++
++ /* try to init dbus */
++ if (!_ecore_drm_dbus_init(sid))
++ {
++ free(sid);
++ return EINA_FALSE;
++ }
++
++ if (!_ecore_drm_logind_vt_open(dev, NULL))
++ {
++ free(sid);
++ return EINA_FALSE;
++ }
++
++ return EINA_TRUE;
++}
++
++void
++_ecore_drm_logind_disconnect(Ecore_Drm_Device *dev)
++{
++ _ecore_drm_logind_vt_close(dev);
++ _ecore_drm_dbus_shutdown();
++}
++
++Eina_Bool
++_ecore_drm_logind_device_open(const char *device, Ecore_Drm_Open_Cb callback, void *data)
++{
++ struct stat st;
++
++ if (stat(device, &st) < 0) return EINA_FALSE;
++ if (!S_ISCHR(st.st_mode)) return EINA_FALSE;
++
++ if (_ecore_drm_dbus_device_take(major(st.st_rdev), minor(st.st_rdev), callback, data) < 0)
++ return EINA_FALSE;
++
++ return EINA_TRUE;
++}
++
++int
++_ecore_drm_logind_device_open_no_pending(const char *device)
++{
++ struct stat st;
++
++ if (stat(device, &st) < 0) return EINA_FALSE;
++ if (!S_ISCHR(st.st_mode)) return EINA_FALSE;
++
++ return _ecore_drm_dbus_device_take_no_pending(major(st.st_rdev), minor(st.st_rdev), NULL, -1);
++}
++
++void
++_ecore_drm_logind_device_close(const char *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_logind.h b/src/lib/ecore_drm/ecore_drm_logind.h
+new file mode 100644
+index 0000000..4315722
+--- /dev/null
++++ b/src/lib/ecore_drm/ecore_drm_logind.h
+@@ -0,0 +1,55 @@
++#ifndef _ECORE_DRM_LOGIN_H_
++# define _ECORE_DRM_LOGIN_H_
++
++# ifdef HAVE_CONFIG_H
++# include "config.h"
++# endif
++
++#ifdef HAVE_SYSTEMD_LOGIN
++# include <systemd/sd-login.h>
++
++Eina_Bool _ecore_drm_logind_connect(Ecore_Drm_Device *dev);
++void _ecore_drm_logind_disconnect(Ecore_Drm_Device *dev);
++Eina_Bool _ecore_drm_logind_device_open(const char *device, Ecore_Drm_Open_Cb callback, void *data);
++int _ecore_drm_logind_device_open_no_pending(const char *device);
++void _ecore_drm_logind_device_close(const char *device);
++
++int _ecore_drm_dbus_init(const char *session);
++int _ecore_drm_dbus_shutdown(void);
++int _ecore_drm_dbus_device_take(uint32_t major, uint32_t minor, Ecore_Drm_Open_Cb callback, void *data);
++int _ecore_drm_dbus_device_take_no_pending(uint32_t major, uint32_t minor, Eina_Bool *paused_out, double timeout);
++void _ecore_drm_dbus_device_release(uint32_t major, uint32_t minor);
++
++#else
++static inline Eina_Bool
++_ecore_drm_logind_connect(Ecore_Drm_Device *dev EINA_UNUSED)
++{
++ return EINA_FALSE;
++}
++
++static inline void
++_ecore_drm_logind_disconnect(Ecore_Drm_Device *dev EINA_UNUSED)
++{
++ return;
++}
++
++static inline Eina_Bool
++_ecore_drm_logind_device_open(const char *device EINA_UNUSED, Ecore_Drm_Open_Cb callback EINA_UNUSED, void *data EINA_UNUSED)
++{
++ return EINA_FALSE;
++}
++
++static inline int
++_ecore_drm_logind_device_open_no_pending(const char *device EINA_UNUSED)
++{
++ return -1;
++}
++
++static inline void
++_ecore_drm_logind_device_close(const char *device EINA_UNUSED)
++{
++ return;
++}
++#endif
++
++#endif
+diff --git a/src/lib/ecore_drm/ecore_drm_private.h b/src/lib/ecore_drm/ecore_drm_private.h
+index fe769a4..7a3c0a0 100644
+--- a/src/lib/ecore_drm/ecore_drm_private.h
++++ b/src/lib/ecore_drm/ecore_drm_private.h
+@@ -21,7 +21,6 @@
+
+ # include <linux/input.h>
+ //# include <libinput.h>
+-# include <systemd/sd-login.h>
+ # include <xkbcommon/xkbcommon.h>
+
+ # include <xf86drm.h>
+@@ -228,10 +227,11 @@ struct _Ecore_Drm_Sprite
+ unsigned int formats[];
+ };
+
+-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);
++typedef void (*Ecore_Drm_Open_Cb)(void *data, int fd, Eina_Bool b);
++
++Eina_Bool _ecore_drm_launcher_device_open(const char *device, Ecore_Drm_Open_Cb callback, void *data, int flags);
++int _ecore_drm_launcher_device_open_no_pending(const char *device, int flags);
++void _ecore_drm_launcher_device_close(const char *device, int fd);
+
+ Ecore_Drm_Evdev *_ecore_drm_evdev_device_create(Ecore_Drm_Seat *seat, const char *path, int fd);
+ void _ecore_drm_evdev_device_destroy(Ecore_Drm_Evdev *evdev);
+diff --git a/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c b/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c
+index ce6ce84..776939e 100644
+--- a/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c
++++ b/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c
+@@ -474,6 +474,12 @@ _ecore_evas_drm_init(const char *device)
+ goto dev_err;
+ }
+
++ if (!ecore_drm_launcher_connect(dev))
++ {
++ ERR("Could not connect DRM launcher");
++ goto launcher_err;
++ }
++
+ /* try to open the graphics card */
+ if (!ecore_drm_device_open(dev))
+ {
+@@ -481,13 +487,6 @@ _ecore_evas_drm_init(const char *device)
+ goto dev_open_err;
+ }
+
+- /* try to open the tty */
+- if (!ecore_drm_tty_open(dev, NULL))
+- {
+- ERR("Could not open tty: %m");
+- goto tty_open_err;
+- }
+-
+ /* try to create sprites */
+ if (!ecore_drm_sprites_create(dev))
+ {
+@@ -516,11 +515,11 @@ _ecore_evas_drm_init(const char *device)
+ output_err:
+ ecore_drm_sprites_destroy(dev);
+ sprite_err:
+- ecore_drm_tty_close(dev);
+-tty_open_err:
+ ecore_drm_device_close(dev);
+ dev_open_err:
+ ecore_drm_device_free(dev);
++ ecore_drm_launcher_disconnect(dev);
++launcher_err:
+ dev_err:
+ ecore_drm_shutdown();
+ return --_ecore_evas_init_count;
+@@ -534,9 +533,9 @@ _ecore_evas_drm_shutdown(void)
+ ecore_drm_sprites_destroy(dev);
+ /* NB: No need to free outputs here. Is done in device free */
+ ecore_drm_inputs_destroy(dev);
+- ecore_drm_tty_close(dev);
+ ecore_drm_device_close(dev);
+ ecore_drm_device_free(dev);
++ ecore_drm_launcher_disconnect(dev);
+ ecore_drm_shutdown();
+
+ ecore_event_evas_shutdown();
+--
+cgit v0.10.1
+