forked from enlightenment/efl
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
This commit is contained in:
parent
05006e6463
commit
b10ab1a86f
|
@ -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])
|
||||
|
||||
|
|
|
@ -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@ \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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));
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue