summaryrefslogtreecommitdiff
path: root/src/lib/ecore_drm
diff options
context:
space:
mode:
authorChris Michael <cp.michael@samsung.com>2015-01-22 12:38:29 -0500
committerChris Michael <cp.michael@samsung.com>2015-01-26 08:37:08 -0500
commitc7d557cf4e1cf2b5d4278141363c02ec01d98dfc (patch)
tree1f76a417186018c22076d8b175f086d379648163 /src/lib/ecore_drm
parente6970f4f8b13177c64f7020e26d46a65a527a126 (diff)
ecore-drm: Fix various issues with logind code
Summary: This fixes a few issues with the logind code such as: Getting the VT from systemd (if available), Properly setup the VT using proper 'open' flags, adding a 'restore' function to reset the tty properly, and handle take/release session. @fix Signed-off-by: Chris Michael <cp.michael@samsung.com>
Diffstat (limited to 'src/lib/ecore_drm')
-rw-r--r--src/lib/ecore_drm/ecore_drm_logind.c236
1 files changed, 207 insertions, 29 deletions
diff --git a/src/lib/ecore_drm/ecore_drm_logind.c b/src/lib/ecore_drm/ecore_drm_logind.c
index 9a8d7f1357..dfc5402373 100644
--- a/src/lib/ecore_drm/ecore_drm_logind.c
+++ b/src/lib/ecore_drm/ecore_drm_logind.c
@@ -1,32 +1,154 @@
1#include <sys/stat.h>
2#include <sys/ioctl.h>
3#include <linux/vt.h>
4#include <linux/kd.h>
5#include <linux/major.h>
6#include "ecore_drm_private.h" 1#include "ecore_drm_private.h"
7#include "ecore_drm_logind.h"
8 2
9#ifndef KDSKBMUTE 3#ifndef KDSKBMUTE
10# define KDSKBMUTE 0x4B51 4# define KDSKBMUTE 0x4B51
11#endif 5#endif
12 6
13static Ecore_Event_Handler *active_hdl; 7static Ecore_Event_Handler *active_hdlr;
14static char *sid;
15 8
16static Eina_Bool 9#ifdef HAVE_SYSTEMD
10static inline Eina_Bool
11_ecore_drm_logind_vt_get(Ecore_Drm_Device *dev)
12{
13 int ret;
14 char *tty;
15
16 ret = sd_session_get_tty(dev->session, &tty);
17 if (ret < 0)
18 {
19 ERR("Could not get systemd tty: %m");
20 return EINA_FALSE;
21 }
22
23 ret = sscanf(tty, "tty%u", &dev->vt);
24 free(tty);
25
26 if (ret != 1) return EINA_FALSE;
27
28 return EINA_TRUE;
29}
30#endif
31
32static Eina_Bool
33_ecore_drm_logind_vt_setup(Ecore_Drm_Device *dev)
34{
35 struct stat st;
36 char buff[64];
37 struct vt_mode vtmode = { 0 };
38
39 snprintf(buff, sizeof(buff), "/dev/tty%d", dev->vt);
40 buff[sizeof(buff) - 1] = 0;
41
42 dev->tty.fd = open(buff, (O_RDWR | O_CLOEXEC | O_NONBLOCK));
43 if (dev->tty.fd < 0)
44 {
45 ERR("Could not open VT %s %m", buff);
46 return EINA_FALSE;
47 }
48
49 if ((fstat(dev->tty.fd, &st) == -1) ||
50 (major(st.st_rdev) != TTY_MAJOR) ||
51 (minor(st.st_rdev) <= 0) || (minor(st.st_rdev) >= 64))
52 {
53 ERR("TTY %s is not a virtual terminal", buff);
54 goto stat_err;
55 }
56
57 if (ioctl(dev->tty.fd, KDGKBMODE, &dev->tty.kbd_mode) < 0)
58 {
59 ERR("Could not read keyboard mode of %s: %m", buff);
60 dev->tty.kbd_mode = K_UNICODE;
61 }
62 else if (dev->tty.kbd_mode == K_OFF)
63 dev->tty.kbd_mode = K_UNICODE;
64
65 if ((ioctl(dev->tty.fd, KDSKBMUTE, 1) < 0) &&
66 (ioctl(dev->tty.fd, KDSKBMODE, K_OFF) < 0))
67 {
68 ERR("Could not set K_OFF keyboard mode on %s: %m", buff);
69 goto stat_err;
70 }
71
72 if (ioctl(dev->tty.fd, KDSETMODE, KD_GRAPHICS) < 0)
73 {
74 ERR("Could not set KD_GRAPHICS mode on %s: %m", buff);
75 goto kbdmode_err;
76 }
77
78 vtmode.mode = VT_PROCESS;
79 vtmode.waitv =0 ;
80 vtmode.relsig = SIGUSR1;
81 vtmode.acqsig = SIGUSR2;
82
83 if (ioctl(dev->tty.fd, VT_SETMODE, &vtmode) < 0)
84 {
85 ERR("Could not take over virtual terminal: %m");
86 goto mode_err;
87 }
88
89 return EINA_TRUE;
90
91mode_err:
92 ioctl(dev->tty.fd, KDSETMODE, KD_TEXT);
93kbdmode_err:
94 ioctl(dev->tty.fd, KDSKBMUTE, 0);
95 ioctl(dev->tty.fd, KDSKBMODE, dev->tty.kbd_mode);
96stat_err:
97 close(dev->tty.fd);
98 return EINA_FALSE;
99}
100
101static void
102_ecore_drm_logind_vt_destroy(Ecore_Drm_Device *dev)
103{
104 _ecore_drm_logind_restore(dev);
105 close(dev->tty.fd);
106}
107
108static Eina_Bool
109_ecore_drm_logind_cb_vt_signal(void *data, int type EINA_UNUSED, void *event)
110{
111 Ecore_Drm_Device *dev;
112 Ecore_Event_Signal_User *ev;
113 siginfo_t sig;
114
115 ev = event;
116 sig = ev->data;
117
118 if (sig.si_code != SI_KERNEL) return ECORE_CALLBACK_RENEW;
119 if (!(dev = data)) return ECORE_CALLBACK_RENEW;
120
121 switch (ev->number)
122 {
123 case 1:
124 _ecore_drm_event_activate_send(EINA_FALSE);
125 ioctl(dev->tty.fd, VT_RELDISP, 1);
126 break;
127 case 2:
128 ioctl(dev->tty.fd, VT_RELDISP, VT_ACKACQ);
129 _ecore_drm_event_activate_send(EINA_TRUE);
130 break;
131 default:
132 break;
133 }
134
135 return ECORE_CALLBACK_RENEW;
136}
137
138static Eina_Bool
17_ecore_drm_logind_cb_activate(void *data, int type EINA_UNUSED, void *event) 139_ecore_drm_logind_cb_activate(void *data, int type EINA_UNUSED, void *event)
18{ 140{
19 Ecore_Drm_Event_Activate *e; 141 Ecore_Drm_Event_Activate *ev;
20 Ecore_Drm_Device *dev; 142 Ecore_Drm_Device *dev;
21 Ecore_Drm_Output *output; 143 Ecore_Drm_Output *output;
22 Eina_List *l; 144 Eina_List *l;
23 145
24 if ((!event) || (!data)) return ECORE_CALLBACK_RENEW; 146 if ((!event) || (!data)) return ECORE_CALLBACK_RENEW;
25 147
26 e = event; 148 ev = event;
27 dev = data; 149 dev = data;
28 150
29 if (e->active) 151 if (ev->active)
30 { 152 {
31 /* set output mode */ 153 /* set output mode */
32 EINA_LIST_FOREACH(dev->outputs, l, output) 154 EINA_LIST_FOREACH(dev->outputs, l, output)
@@ -48,38 +170,94 @@ _ecore_drm_logind_cb_activate(void *data, int type EINA_UNUSED, void *event)
48 return ECORE_CALLBACK_PASS_ON; 170 return ECORE_CALLBACK_PASS_ON;
49} 171}
50 172
51Eina_Bool 173Eina_Bool
52_ecore_drm_logind_connect(Ecore_Drm_Device *dev) 174_ecore_drm_logind_connect(Ecore_Drm_Device *dev)
53{ 175{
54#ifdef HAVE_SYSTEMD 176#ifdef HAVE_SYSTEMD
55 /* get sd-login properties we need */ 177 char *seat;
56 if (sd_pid_get_session(getpid(), &sid) < 0) return EINA_FALSE; 178
57#endif 179 /* get session id */
180 if (sd_pid_get_session(getpid(), &dev->session) < 0)
181 {
182 ERR("Could not get systemd session: %m");
183 return EINA_FALSE;
184 }
58 185
59 /* try to init dbus */ 186 if (sd_session_get_seat(dev->session, &seat) < 0)
60 if (!_ecore_drm_dbus_init(sid)) 187 {
188 ERR("Could not get systemd seat: %m");
189 free(seat);
190 return EINA_FALSE;
191 }
192 else if (strcmp(dev->seat, seat))
61 { 193 {
62 free(sid); 194 ERR("Session seat '%s' differs from device seat '%s'", seat, dev->seat);
195 free(seat);
63 return EINA_FALSE; 196 return EINA_FALSE;
64 } 197 }
65 198
66 active_hdl = 199 free(seat);
67 ecore_event_handler_add(ECORE_DRM_EVENT_ACTIVATE, 200
68 _ecore_drm_logind_cb_activate, dev); 201 if (!_ecore_drm_logind_vt_get(dev)) return EINA_FALSE;
202#endif
203
204 if (!_ecore_drm_dbus_init(dev)) return EINA_FALSE;
205
206 /* take control of session */
207 if (!_ecore_drm_dbus_session_take(dev->session))
208 {
209 ERR("Could not take control of session");
210 goto take_err;
211 }
212
213 /* setup vt */
214 if (!_ecore_drm_logind_vt_setup(dev))
215 {
216 ERR("Could not setup vt '%d'", dev->vt);
217 goto vt_err;
218 }
219
220 /* setup handler for vt signals */
221 dev->tty.event_hdlr =
222 ecore_event_handler_add(ECORE_EVENT_SIGNAL_USER,
223 _ecore_drm_logind_cb_vt_signal, dev);
224
225 active_hdlr =
226 ecore_event_handler_add(ECORE_DRM_EVENT_ACTIVATE,
227 _ecore_drm_logind_cb_activate, dev);
69 228
70 return EINA_TRUE; 229 return EINA_TRUE;
230
231vt_err:
232 _ecore_drm_dbus_session_release(dev->session);
233take_err:
234 _ecore_drm_dbus_shutdown();
235 return EINA_FALSE;
71} 236}
72 237
73void 238void
74_ecore_drm_logind_disconnect(Ecore_Drm_Device *dev EINA_UNUSED) 239_ecore_drm_logind_disconnect(Ecore_Drm_Device *dev)
75{ 240{
241 if (active_hdlr) ecore_event_handler_del(active_hdlr);
242 active_hdlr = NULL;
243
244 _ecore_drm_logind_vt_destroy(dev);
245 _ecore_drm_dbus_session_release(dev->session);
76 _ecore_drm_dbus_shutdown(); 246 _ecore_drm_dbus_shutdown();
247}
77 248
78 if (active_hdl) 249void
79 { 250_ecore_drm_logind_restore(Ecore_Drm_Device *dev)
80 ecore_event_handler_del(active_hdl); 251{
81 active_hdl = NULL; 252 struct vt_mode vtmode = { 0 };
82 } 253
254 if ((!dev) || (dev->tty.fd < 0)) return;
255
256 ioctl(dev->tty.fd, KDSETMODE, KD_TEXT);
257 ioctl(dev->tty.fd, KDSKBMUTE, 0);
258 ioctl(dev->tty.fd, KDSKBMODE, dev->tty.kbd_mode);
259 vtmode.mode = VT_AUTO;
260 ioctl(dev->tty.fd, VT_SETMODE, &vtmode);
83} 261}
84 262
85Eina_Bool 263Eina_Bool