Merge branch 'devs/devilhorns/ecore_drm'

This branch fixes several issues with ecore_drm:

In particular, it address the issue of not properly restoring the tty
on shutdown, saves the current tty keyboard mode and properly restores
that on shutdown, we now get the VT from systemd (if available) and
properly setup the VT.

@fix
This commit is contained in:
Chris Michael 2015-01-26 09:16:44 -05:00
commit a5063a0c9b
11 changed files with 366 additions and 297 deletions

View File

@ -17,14 +17,13 @@ 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_launcher.c \
lib/ecore_drm/ecore_drm_dbus.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
lib/ecore_drm/ecore_drm_logind.c
endif
lib_ecore_drm_libecore_drm_la_CPPFLAGS = \

View File

@ -373,7 +373,6 @@ _gfd_events_from_fdh(Ecore_Fd_Handler *fdh)
if (fdh->flags & ECORE_FD_ERROR) events |= G_IO_ERR;
return events;
}
#endif
static inline int
@ -386,16 +385,16 @@ _ecore_main_fdh_poll_add(Ecore_Fd_Handler *fdh)
r = _ecore_epoll_add(_ecore_get_epoll_fd(), fdh->fd,
_ecore_poll_events_from_fdh(fdh), fdh);
}
#ifdef USE_G_MAIN_LOOP
else
{
#ifdef USE_G_MAIN_LOOP
fdh->gfd.fd = fdh->fd;
fdh->gfd.events = _gfd_events_from_fdh(fdh);
fdh->gfd.revents = 0;
DBG("adding gpoll on %d %08x", fdh->fd, fdh->gfd.events);
g_source_add_poll(ecore_glib_source, &fdh->gfd);
#endif
}
#endif
return r;
}
@ -425,16 +424,16 @@ _ecore_main_fdh_poll_del(Ecore_Fd_Handler *fdh)
}
}
}
#ifdef USE_G_MAIN_LOOP
else
{
#ifdef USE_G_MAIN_LOOP
fdh->gfd.fd = fdh->fd;
fdh->gfd.events = _gfd_events_from_fdh(fdh);
fdh->gfd.revents = 0;
DBG("removing gpoll on %d %08x", fdh->fd, fdh->gfd.events);
g_source_remove_poll(ecore_glib_source, &fdh->gfd);
#endif
}
#endif
}
static inline int
@ -452,15 +451,15 @@ _ecore_main_fdh_poll_modify(Ecore_Fd_Handler *fdh)
DBG("modifing epoll on %d to %08x", fdh->fd, ev.events);
r = epoll_ctl(efd, EPOLL_CTL_MOD, fdh->fd, &ev);
}
#ifdef USE_G_MAIN_LOOP
else
{
#ifdef USE_G_MAIN_LOOP
fdh->gfd.fd = fdh->fd;
fdh->gfd.events = _gfd_events_from_fdh(fdh);
fdh->gfd.revents = 0;
DBG("modifing gpoll on %d to %08x", fdh->fd, fdh->gfd.events);
#endif
}
#endif
return r;
}
@ -476,7 +475,7 @@ _ecore_main_fdh_epoll_mark_active(void)
if (ret < 0)
{
if (errno == EINTR) return -1;
ERR("epoll_wait failed %d", errno);
ERR("epoll_wait failed on fd: %d %s", efd, strerror(errno));
return -1;
}

View File

@ -66,7 +66,9 @@ typedef struct _Ecore_Drm_Fb
struct _Ecore_Drm_Device
{
int id;
unsigned int vt;
const char *seat;
char *session;
struct
{
@ -94,6 +96,7 @@ struct _Ecore_Drm_Device
struct
{
int fd;
int kbd_mode;
const char *name;
Ecore_Event_Handler *event_hdlr;
Ecore_Event_Handler *switch_hdlr;

View File

@ -2,7 +2,6 @@
static int _dbus_init_count = 0;
static const char *dsession;
static Eldbus_Connection *dconn;
static Eldbus_Object *dobj;
@ -30,11 +29,14 @@ _ecore_drm_dbus_device_pause_done(uint32_t major, uint32_t minor)
}
static void
_cb_session_removed(void *ctxt EINA_UNUSED, const Eldbus_Message *msg)
_cb_session_removed(void *data, const Eldbus_Message *msg)
{
Ecore_Drm_Device *dev;
const char *errname, *errmsg;
const char *sid;
if (!(dev = data)) return;
if (eldbus_message_error_get(msg, &errname, &errmsg))
{
ERR("Eldbus Message Error: %s %s", errname, errmsg);
@ -43,8 +45,11 @@ _cb_session_removed(void *ctxt EINA_UNUSED, const Eldbus_Message *msg)
if (eldbus_message_arguments_get(msg, "s", &sid))
{
if (!strcmp(sid, dsession))
ERR("\tCurrent Session Removed!!");
if (!strcmp(sid, dev->session))
{
WRN("\tCurrent Session Removed!!");
_ecore_drm_logind_restore(dev);
}
}
}
@ -116,19 +121,13 @@ _cb_properties_changed(void *data EINA_UNUSED, Eldbus_Proxy *proxy EINA_UNUSED,
}
}
static Eina_Bool
_ecore_drm_dbus_session_take(const char *session)
Eina_Bool
_ecore_drm_dbus_session_take(void)
{
Eldbus_Proxy *proxy;
Eldbus_Message *msg, *reply;
const char *errname, *errmsg;
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")))
{
@ -155,19 +154,13 @@ _ecore_drm_dbus_session_take(const char *session)
return EINA_TRUE;
}
static Eina_Bool
_ecore_drm_dbus_session_release(const char *session)
Eina_Bool
_ecore_drm_dbus_session_release(void)
{
Eldbus_Proxy *proxy;
Eldbus_Message *msg, *reply;
const char *errname, *errmsg;
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")))
{
@ -300,7 +293,7 @@ _ecore_drm_dbus_device_take_no_pending(uint32_t major, uint32_t minor, Eina_Bool
}
int
_ecore_drm_dbus_init(const char *session)
_ecore_drm_dbus_init(Ecore_Drm_Device *dev)
{
Eldbus_Proxy *proxy;
int ret = 0;
@ -308,7 +301,7 @@ _ecore_drm_dbus_init(const char *session)
if (++_dbus_init_count != 1) return _dbus_init_count;
if (!session) return --_dbus_init_count;
if (!dev->session) return --_dbus_init_count;
/* try to init eldbus */
if (!eldbus_init())
@ -317,8 +310,6 @@ _ecore_drm_dbus_init(const char *session)
return --_dbus_init_count;
}
dsession = eina_stringshare_add(session);
/* try to get the dbus connection */
if (!(dconn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM)))
{
@ -327,7 +318,7 @@ _ecore_drm_dbus_init(const char *session)
}
/* assemble dbus path */
ret = asprintf(&dpath, "/org/freedesktop/login1/session/%s", session);
ret = asprintf(&dpath, "/org/freedesktop/login1/session/%s", dev->session);
if (ret < 0)
{
ERR("Could not assemble dbus path");
@ -349,7 +340,7 @@ _ecore_drm_dbus_init(const char *session)
}
eldbus_proxy_signal_handler_add(proxy, "SessionRemoved",
_cb_session_removed, NULL);
_cb_session_removed, dev);
/* try to get the Session proxy */
if (!(proxy = eldbus_proxy_get(dobj, "org.freedesktop.login1.Session")))
@ -374,17 +365,8 @@ _ecore_drm_dbus_init(const char *session)
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:
@ -392,7 +374,6 @@ obj_err:
path_err:
eldbus_connection_unref(dconn);
conn_err:
eina_stringshare_del(dsession);
eldbus_shutdown();
return --_dbus_init_count;
}
@ -402,17 +383,12 @@ _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();

View File

@ -185,8 +185,10 @@ cont:
dev->seat = eeze_udev_syspath_get_property(device, "ID_SEAT");
if (!dev->seat) dev->seat = eina_stringshare_add("seat0");
dev->vt = 0;
dev->format = 0;
dev->use_hw_accel = EINA_FALSE;
dev->session = NULL;
DBG("Using Drm Device: %s", dev->drm.name);
}
@ -231,6 +233,9 @@ ecore_drm_device_free(Ecore_Drm_Device *dev)
/* free device seat */
if (dev->seat) eina_stringshare_del(dev->seat);
/* free session */
free(dev->session);
/* free structure */
free(dev);
}
@ -255,7 +260,8 @@ ecore_drm_device_open(Ecore_Drm_Device *dev)
if ((!dev) || (!dev->drm.name)) return EINA_FALSE;
/* DRM device node is needed immediately to keep going. */
dev->drm.fd = _ecore_drm_launcher_device_open_no_pending(dev->drm.name, O_RDWR);
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);

View File

@ -1,9 +1,8 @@
#include "ecore_drm_private.h"
#include "ecore_drm_logind.h"
static Eina_Bool logind = EINA_FALSE;
static Eina_Bool
static Eina_Bool
_ecore_drm_launcher_cb_vt_switch(void *data, int type EINA_UNUSED, void *event)
{
Ecore_Drm_Device *dev;
@ -28,143 +27,8 @@ _ecore_drm_launcher_cb_vt_switch(void *data, int type EINA_UNUSED, void *event)
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_ecore_drm_launcher_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)
{
if (!logind)
{
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);
/* drop drm master */
ecore_drm_device_master_drop(dev);
_ecore_drm_event_activate_send(EINA_FALSE);
}
/* issue ioctl to release vt */
if (!ecore_drm_tty_release(dev))
ERR("Could not release VT: %m");
}
else if (ev->number == 2)
{
if (!logind)
{
Ecore_Drm_Output *output;
Ecore_Drm_Input *input;
Eina_List *l;
/* set drm master */
if (!ecore_drm_device_master_set(dev))
ERR("Could not set drm master: %m");
/* 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);
if (ecore_drm_tty_acquire(dev))
_ecore_drm_event_activate_send(EINA_TRUE);
else
ERR("Could not acquire VT: %m");
}
else
{
if (!ecore_drm_tty_acquire(dev))
ERR("Could not acquire VT: %m");
}
}
return ECORE_CALLBACK_RENEW;
}
EAPI Eina_Bool
ecore_drm_launcher_connect(Ecore_Drm_Device *dev)
{
if (!(logind = _ecore_drm_logind_connect(dev)))
{
DBG("Launcher: Not Support logind\n");
if (geteuid() == 0)
DBG("Launcher: Try to keep going with root privilege\n");
else
{
ERR("Launcher: Need Root Privilege or logind\n");
return EINA_FALSE;
}
}
if (!ecore_drm_tty_open(dev, NULL))
{
ERR("Launcher: failed to open tty\n");
return EINA_FALSE;
}
/* setup handler for signals */
dev->tty.event_hdlr =
ecore_event_handler_add(ECORE_EVENT_SIGNAL_USER,
_ecore_drm_launcher_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_launcher_cb_vt_switch, dev);
DBG("Launcher: Success Connect\n");
return EINA_TRUE;
}
EAPI void
ecore_drm_launcher_disconnect(Ecore_Drm_Device *dev)
{
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 (!ecore_drm_tty_close(dev))
ERR("Launcher: failed to close tty\n");
if (logind)
{
logind = EINA_FALSE;
_ecore_drm_logind_disconnect(dev);
}
}
static int
_device_flags_set(int fd, int flags)
int
_ecore_drm_launcher_device_flags_set(int fd, int flags)
{
int fl;
@ -189,6 +53,54 @@ _device_flags_set(int fd, int flags)
return fd;
}
EAPI Eina_Bool
ecore_drm_launcher_connect(Ecore_Drm_Device *dev)
{
/* try to connect to logind */
if (!(logind = _ecore_drm_logind_connect(dev)))
{
DBG("Launcher: Logind not supported");
if (geteuid() == 0)
{
DBG("Launcher: Trying to continue with root privileges");
if (!ecore_drm_tty_open(dev, NULL))
{
ERR("Launcher: Could not setup tty");
return EINA_FALSE;
}
}
else
{
ERR("Launcher: Root privileges needed");
return EINA_FALSE;
}
}
dev->tty.switch_hdlr =
ecore_event_handler_add(ECORE_EVENT_KEY_DOWN,
_ecore_drm_launcher_cb_vt_switch, dev);
return EINA_TRUE;
}
EAPI void
ecore_drm_launcher_disconnect(Ecore_Drm_Device *dev)
{
if (dev->tty.switch_hdlr) ecore_event_handler_del(dev->tty.switch_hdlr);
dev->tty.switch_hdlr = NULL;
if (!logind)
{
if (!ecore_drm_tty_close(dev))
ERR("Launcher: Could not close tty");
}
else
{
_ecore_drm_logind_disconnect(dev);
logind = EINA_FALSE;
}
}
Eina_Bool
_ecore_drm_launcher_device_open(const char *device, Ecore_Drm_Open_Cb callback, void *data, int flags)
{
@ -226,7 +138,7 @@ _ecore_drm_launcher_device_open_no_pending(const char *device, int flags)
if (logind)
{
fd = _ecore_drm_logind_device_open_no_pending(device);
if ((fd = _device_flags_set(fd, flags)) == -1)
if ((fd = _ecore_drm_launcher_device_flags_set(fd, flags)) < 0)
{
_ecore_drm_logind_device_close(device);
return -1;

View File

@ -1,32 +1,154 @@
#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 Ecore_Event_Handler *active_hdl;
static char *sid;
static Ecore_Event_Handler *active_hdlr;
static Eina_Bool
#ifdef HAVE_SYSTEMD
static inline Eina_Bool
_ecore_drm_logind_vt_get(Ecore_Drm_Device *dev)
{
int ret;
char *tty;
ret = sd_session_get_tty(dev->session, &tty);
if (ret < 0)
{
ERR("Could not get systemd tty: %m");
return EINA_FALSE;
}
ret = sscanf(tty, "tty%u", &dev->vt);
free(tty);
if (ret != 1) return EINA_FALSE;
return EINA_TRUE;
}
#endif
static Eina_Bool
_ecore_drm_logind_vt_setup(Ecore_Drm_Device *dev)
{
struct stat st;
char buff[64];
struct vt_mode vtmode = { 0 };
snprintf(buff, sizeof(buff), "/dev/tty%d", dev->vt);
buff[sizeof(buff) - 1] = 0;
dev->tty.fd = open(buff, (O_RDWR | O_CLOEXEC | O_NONBLOCK));
if (dev->tty.fd < 0)
{
ERR("Could not open VT %s %m", buff);
return EINA_FALSE;
}
if ((fstat(dev->tty.fd, &st) == -1) ||
(major(st.st_rdev) != TTY_MAJOR) ||
(minor(st.st_rdev) <= 0) || (minor(st.st_rdev) >= 64))
{
ERR("TTY %s is not a virtual terminal", buff);
goto stat_err;
}
if (ioctl(dev->tty.fd, KDGKBMODE, &dev->tty.kbd_mode) < 0)
{
ERR("Could not read keyboard mode of %s: %m", buff);
dev->tty.kbd_mode = K_UNICODE;
}
else if (dev->tty.kbd_mode == K_OFF)
dev->tty.kbd_mode = K_UNICODE;
if ((ioctl(dev->tty.fd, KDSKBMUTE, 1) < 0) &&
(ioctl(dev->tty.fd, KDSKBMODE, K_OFF) < 0))
{
ERR("Could not set K_OFF keyboard mode on %s: %m", buff);
goto stat_err;
}
if (ioctl(dev->tty.fd, KDSETMODE, KD_GRAPHICS) < 0)
{
ERR("Could not set KD_GRAPHICS mode on %s: %m", buff);
goto kbdmode_err;
}
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 take over virtual terminal: %m");
goto mode_err;
}
return EINA_TRUE;
mode_err:
ioctl(dev->tty.fd, KDSETMODE, KD_TEXT);
kbdmode_err:
ioctl(dev->tty.fd, KDSKBMUTE, 0);
ioctl(dev->tty.fd, KDSKBMODE, dev->tty.kbd_mode);
stat_err:
close(dev->tty.fd);
return EINA_FALSE;
}
static void
_ecore_drm_logind_vt_destroy(Ecore_Drm_Device *dev)
{
_ecore_drm_logind_restore(dev);
close(dev->tty.fd);
}
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 sig;
ev = event;
sig = ev->data;
if (sig.si_code != SI_KERNEL) return ECORE_CALLBACK_RENEW;
if (!(dev = data)) return ECORE_CALLBACK_RENEW;
switch (ev->number)
{
case 1:
_ecore_drm_event_activate_send(EINA_FALSE);
ioctl(dev->tty.fd, VT_RELDISP, 1);
break;
case 2:
ioctl(dev->tty.fd, VT_RELDISP, VT_ACKACQ);
_ecore_drm_event_activate_send(EINA_TRUE);
break;
default:
break;
}
return ECORE_CALLBACK_RENEW;
}
static Eina_Bool
_ecore_drm_logind_cb_activate(void *data, int type EINA_UNUSED, void *event)
{
Ecore_Drm_Event_Activate *e;
Ecore_Drm_Event_Activate *ev;
Ecore_Drm_Device *dev;
Ecore_Drm_Output *output;
Eina_List *l;
if ((!event) || (!data)) return ECORE_CALLBACK_RENEW;
e = event;
ev = event;
dev = data;
if (e->active)
if (ev->active)
{
/* set output mode */
EINA_LIST_FOREACH(dev->outputs, l, output)
@ -48,38 +170,94 @@ _ecore_drm_logind_cb_activate(void *data, int type EINA_UNUSED, void *event)
return ECORE_CALLBACK_PASS_ON;
}
Eina_Bool
Eina_Bool
_ecore_drm_logind_connect(Ecore_Drm_Device *dev)
{
#ifdef HAVE_SYSTEMD
/* get sd-login properties we need */
if (sd_pid_get_session(getpid(), &sid) < 0) return EINA_FALSE;
#endif
char *seat;
/* try to init dbus */
if (!_ecore_drm_dbus_init(sid))
/* get session id */
if (sd_pid_get_session(getpid(), &dev->session) < 0)
{
free(sid);
ERR("Could not get systemd session: %m");
return EINA_FALSE;
}
active_hdl =
ecore_event_handler_add(ECORE_DRM_EVENT_ACTIVATE,
_ecore_drm_logind_cb_activate, dev);
if (sd_session_get_seat(dev->session, &seat) < 0)
{
ERR("Could not get systemd seat: %m");
free(seat);
return EINA_FALSE;
}
else if (strcmp(dev->seat, seat))
{
ERR("Session seat '%s' differs from device seat '%s'", seat, dev->seat);
free(seat);
return EINA_FALSE;
}
free(seat);
if (!_ecore_drm_logind_vt_get(dev)) return EINA_FALSE;
#endif
if (!_ecore_drm_dbus_init(dev)) return EINA_FALSE;
/* take control of session */
if (!_ecore_drm_dbus_session_take())
{
ERR("Could not take control of session");
goto take_err;
}
/* setup vt */
if (!_ecore_drm_logind_vt_setup(dev))
{
ERR("Could not setup vt '%d'", dev->vt);
goto vt_err;
}
/* setup handler for vt signals */
dev->tty.event_hdlr =
ecore_event_handler_add(ECORE_EVENT_SIGNAL_USER,
_ecore_drm_logind_cb_vt_signal, dev);
active_hdlr =
ecore_event_handler_add(ECORE_DRM_EVENT_ACTIVATE,
_ecore_drm_logind_cb_activate, dev);
return EINA_TRUE;
vt_err:
_ecore_drm_dbus_session_release();
take_err:
_ecore_drm_dbus_shutdown();
return EINA_FALSE;
}
void
_ecore_drm_logind_disconnect(Ecore_Drm_Device *dev EINA_UNUSED)
void
_ecore_drm_logind_disconnect(Ecore_Drm_Device *dev)
{
_ecore_drm_dbus_shutdown();
if (active_hdlr) ecore_event_handler_del(active_hdlr);
active_hdlr = NULL;
if (active_hdl)
{
ecore_event_handler_del(active_hdl);
active_hdl = NULL;
}
_ecore_drm_logind_vt_destroy(dev);
_ecore_drm_dbus_session_release();
_ecore_drm_dbus_shutdown();
}
void
_ecore_drm_logind_restore(Ecore_Drm_Device *dev)
{
struct vt_mode vtmode = { 0 };
if ((!dev) || (dev->tty.fd < 0)) return;
ioctl(dev->tty.fd, KDSETMODE, KD_TEXT);
ioctl(dev->tty.fd, KDSKBMUTE, 0);
ioctl(dev->tty.fd, KDSKBMODE, dev->tty.kbd_mode);
vtmode.mode = VT_AUTO;
ioctl(dev->tty.fd, VT_SETMODE, &vtmode);
}
Eina_Bool

View File

@ -1,55 +0,0 @@
#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

View File

@ -19,6 +19,9 @@
# include <sys/stat.h>
# include <sys/ioctl.h>
# include <linux/vt.h>
# include <linux/kd.h>
# include <linux/major.h>
# include <linux/input.h>
# include <libinput.h>
# include <xkbcommon/xkbcommon.h>
@ -27,6 +30,10 @@
# include <xf86drmMode.h>
# include <drm_fourcc.h>
# ifdef HAVE_SYSTEMD_LOGIN
# include <systemd/sd-login.h>
# endif
# include <Eeze.h>
# include <Eldbus.h>
# include <Ecore_Drm.h>
@ -231,6 +238,7 @@ void _ecore_drm_event_activate_send(Eina_Bool active);
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);
int _ecore_drm_launcher_device_flags_set(int fd, int flags);
Eina_Bool _ecore_drm_tty_switch(Ecore_Drm_Device *dev, int activate_vt);
@ -245,4 +253,19 @@ void _ecore_drm_output_fb_release(Ecore_Drm_Output *output, Ecore_Drm_Fb *fb);
void _ecore_drm_output_repaint_start(Ecore_Drm_Output *output);
void _ecore_drm_output_frame_finish(Ecore_Drm_Output *output);
Eina_Bool _ecore_drm_logind_connect(Ecore_Drm_Device *dev);
void _ecore_drm_logind_disconnect(Ecore_Drm_Device *dev);
void _ecore_drm_logind_restore(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(Ecore_Drm_Device *dev);
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);
Eina_Bool _ecore_drm_dbus_session_take(void);
Eina_Bool _ecore_drm_dbus_session_release(void);
#endif

View File

@ -1,12 +1,4 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "ecore_drm_private.h"
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/vt.h>
#include <linux/kd.h>
#ifndef KDSKBMUTE
# define KDSKBMUTE 0x4B51
@ -14,6 +6,35 @@
static int kbd_mode = 0;
static Eina_Bool
_ecore_drm_tty_cb_vt_signal(void *data, int type EINA_UNUSED, void *event)
{
Ecore_Drm_Device *dev;
Ecore_Event_Signal_User *ev;
siginfo_t sig;
ev = event;
sig = ev->data;
if (sig.si_code != SI_KERNEL) return ECORE_CALLBACK_RENEW;
if (!(dev = data)) return ECORE_CALLBACK_RENEW;
switch (ev->number)
{
case 1:
ecore_drm_device_master_drop(dev);
ioctl(dev->tty.fd, VT_RELDISP, 1);
break;
case 2:
ioctl(dev->tty.fd, VT_RELDISP, VT_ACKACQ);
ecore_drm_device_master_set(dev);
break;
default:
break;
}
return ECORE_CALLBACK_RENEW;
}
Eina_Bool
_ecore_drm_tty_switch(Ecore_Drm_Device *dev, int activate_vt)
{
@ -29,7 +50,8 @@ _ecore_drm_tty_setup(Ecore_Drm_Device *dev)
int kmode;
struct vt_mode vtmode = { 0 };
if (fstat(dev->tty.fd, &st) == -1)
if ((fstat(dev->tty.fd, &st) == -1) ||
(major(st.st_rdev) != TTY_MAJOR) || (minor(st.st_rdev) == 0))
{
ERR("Failed to get stats for tty: %m");
return EINA_FALSE;
@ -41,6 +63,12 @@ _ecore_drm_tty_setup(Ecore_Drm_Device *dev)
return EINA_FALSE;
}
if (kmode != KD_TEXT)
{
WRN("Virtual Terminal already in KD_GRAPHICS mode");
return EINA_FALSE;
}
if (ioctl(dev->tty.fd, VT_ACTIVATE, minor(st.st_rdev)) < 0)
{
ERR("Failed to activate vt: %m");
@ -66,13 +94,10 @@ _ecore_drm_tty_setup(Ecore_Drm_Device *dev)
return EINA_FALSE;
}
if (kmode != KD_GRAPHICS)
if (ioctl(dev->tty.fd, KDSETMODE, KD_GRAPHICS))
{
if (ioctl(dev->tty.fd, KDSETMODE, KD_GRAPHICS))
{
ERR("Could not set graphics mode: %m");
goto err_kmode;
}
ERR("Could not set graphics mode: %m");
goto err_kmode;
}
vtmode.mode = VT_PROCESS;
@ -136,7 +161,7 @@ ecore_drm_tty_open(Ecore_Drm_Device *dev, const char *name)
{
DBG("Trying to Open Tty: %s", tty);
dev->tty.fd = open(tty, O_RDWR | O_NOCTTY);
dev->tty.fd = open(tty, (O_RDWR | O_CLOEXEC)); //O_RDWR | O_NOCTTY);
if (dev->tty.fd < 0)
{
DBG("Failed to Open Tty: %m");
@ -149,7 +174,6 @@ ecore_drm_tty_open(Ecore_Drm_Device *dev, const char *name)
/* save tty name */
dev->tty.name = eina_stringshare_add(tty);
/* FIXME */
if (!_ecore_drm_tty_setup(dev))
{
close(dev->tty.fd);
@ -162,6 +186,10 @@ ecore_drm_tty_open(Ecore_Drm_Device *dev, const char *name)
return EINA_FALSE;
}
dev->tty.event_hdlr =
ecore_event_handler_add(ECORE_EVENT_SIGNAL_USER,
_ecore_drm_tty_cb_vt_signal, dev);
/* set current tty into env */
setenv("ECORE_DRM_TTY", tty, 1);

View File

@ -526,8 +526,8 @@ input_err:
sprite_err:
ecore_drm_device_close(dev);
dev_open_err:
ecore_drm_device_free(dev);
ecore_drm_launcher_disconnect(dev);
ecore_drm_device_free(dev);
launcher_err:
dev_err:
ecore_drm_shutdown();
@ -543,8 +543,8 @@ _ecore_evas_drm_shutdown(void)
/* NB: No need to free outputs here. Is done in device free */
ecore_drm_sprites_destroy(dev);
ecore_drm_device_close(dev);
ecore_drm_device_free(dev);
ecore_drm_launcher_disconnect(dev);
ecore_drm_device_free(dev);
ecore_drm_shutdown();
ecore_event_evas_shutdown();