diff --git a/src/Makefile_Ecore_Drm.am b/src/Makefile_Ecore_Drm.am index 8ed601b794..61a15556b9 100644 --- a/src/Makefile_Ecore_Drm.am +++ b/src/Makefile_Ecore_Drm.am @@ -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 = \ diff --git a/src/lib/ecore/ecore_main.c b/src/lib/ecore/ecore_main.c index d7d6a42f7c..de84e61a7f 100644 --- a/src/lib/ecore/ecore_main.c +++ b/src/lib/ecore/ecore_main.c @@ -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; } diff --git a/src/lib/ecore_drm/Ecore_Drm.h b/src/lib/ecore_drm/Ecore_Drm.h index 7a652735cf..286aa20e58 100644 --- a/src/lib/ecore_drm/Ecore_Drm.h +++ b/src/lib/ecore_drm/Ecore_Drm.h @@ -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; diff --git a/src/lib/ecore_drm/ecore_drm_dbus.c b/src/lib/ecore_drm/ecore_drm_dbus.c index 292879eee1..2e745ebbac 100644 --- a/src/lib/ecore_drm/ecore_drm_dbus.c +++ b/src/lib/ecore_drm/ecore_drm_dbus.c @@ -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(); diff --git a/src/lib/ecore_drm/ecore_drm_device.c b/src/lib/ecore_drm/ecore_drm_device.c index 957c439e03..5d0c0bcfe2 100644 --- a/src/lib/ecore_drm/ecore_drm_device.c +++ b/src/lib/ecore_drm/ecore_drm_device.c @@ -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); diff --git a/src/lib/ecore_drm/ecore_drm_launcher.c b/src/lib/ecore_drm/ecore_drm_launcher.c index 41f2fe1b50..860cc84666 100644 --- a/src/lib/ecore_drm/ecore_drm_launcher.c +++ b/src/lib/ecore_drm/ecore_drm_launcher.c @@ -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; diff --git a/src/lib/ecore_drm/ecore_drm_logind.c b/src/lib/ecore_drm/ecore_drm_logind.c index 9a8d7f1357..7e7fa89797 100644 --- a/src/lib/ecore_drm/ecore_drm_logind.c +++ b/src/lib/ecore_drm/ecore_drm_logind.c @@ -1,32 +1,154 @@ -#include -#include -#include -#include -#include #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 diff --git a/src/lib/ecore_drm/ecore_drm_logind.h b/src/lib/ecore_drm/ecore_drm_logind.h deleted file mode 100644 index fe72b73294..0000000000 --- a/src/lib/ecore_drm/ecore_drm_logind.h +++ /dev/null @@ -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 - -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 2a1bac94fc..444b1c06e8 100644 --- a/src/lib/ecore_drm/ecore_drm_private.h +++ b/src/lib/ecore_drm/ecore_drm_private.h @@ -19,6 +19,9 @@ # include # include +# include +# include +# include # include # include # include @@ -27,6 +30,10 @@ # include # include +# ifdef HAVE_SYSTEMD_LOGIN +# include +# endif + # include # include # include @@ -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 diff --git a/src/lib/ecore_drm/ecore_drm_tty.c b/src/lib/ecore_drm/ecore_drm_tty.c index fe338f52fa..f88d9f1278 100644 --- a/src/lib/ecore_drm/ecore_drm_tty.c +++ b/src/lib/ecore_drm/ecore_drm_tty.c @@ -1,12 +1,4 @@ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - #include "ecore_drm_private.h" -#include -#include -#include -#include #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); 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 40ec670550..8ff1d394d7 100644 --- a/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c +++ b/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c @@ -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();