1 /* Portions of this code have been derived from Weston
2 *
3 * Copyright © 2008-2012 Kristian Høgsberg
4 * Copyright © 2010-2012 Intel Corporation
5 * Copyright © 2010-2011 Benjamin Franzke
6 * Copyright © 2011-2012 Collabora, Ltd.
7 * Copyright © 2010 Red Hat <mjg@redhat.com>
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the next
17 * paragraph) shall be included in all copies or substantial portions of the
18 * Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 */
28
29 #include "ecore_drm_private.h"
30
31 static Eina_Bool logind = EINA_FALSE;
32
33 static Eina_Bool
_ecore_drm_launcher_cb_vt_switch(void * data,int type EINA_UNUSED,void * event)34 _ecore_drm_launcher_cb_vt_switch(void *data, int type EINA_UNUSED, void *event)
35 {
36 Ecore_Drm_Device *dev;
37 Ecore_Event_Key *ev;
38 int keycode;
39 int vt;
40
41 dev = data;
42 ev = event;
43 keycode = ev->keycode - 8;
44
45 if ((ev->modifiers & ECORE_EVENT_MODIFIER_CTRL) &&
46 (ev->modifiers & ECORE_EVENT_MODIFIER_ALT) &&
47 (keycode >= KEY_F1) && (keycode <= KEY_F8))
48 {
49 vt = (keycode - KEY_F1 + 1);
50
51 if (!_ecore_drm_tty_switch(dev, vt))
52 ERR("Failed to activate vt");
53 }
54
55 return ECORE_CALLBACK_PASS_ON;
56 }
57
58 int
_ecore_drm_launcher_device_flags_set(int fd,int flags)59 _ecore_drm_launcher_device_flags_set(int fd, int flags)
60 {
61 int fl;
62
63 fl = fcntl(fd, F_GETFL);
64 if (fl < 0) return -1;
65
66 if (flags & O_NONBLOCK)
67 fl |= O_NONBLOCK;
68
69 if (fcntl(fd, F_SETFL, fl) < 0)
70 return -1;
71
72 fl = fcntl(fd, F_GETFD);
73 if (fl < 0) return -1;
74
75 if (!(flags & O_CLOEXEC))
76 fl &= ~FD_CLOEXEC;
77
78 if (fcntl(fd, F_SETFD, fl) < 0)
79 return -1;
80
81 return fd;
82 }
83
84 EAPI Eina_Bool
ecore_drm_launcher_connect(Ecore_Drm_Device * dev)85 ecore_drm_launcher_connect(Ecore_Drm_Device *dev)
86 {
87 EINA_SAFETY_ON_NULL_RETURN_VAL(dev, EINA_FALSE);
88
89 /* try to connect to logind */
90 if (!(logind = _ecore_drm_logind_connect(dev)))
91 {
92 DBG("Launcher: Logind not supported");
93 if (geteuid() == 0)
94 {
95 DBG("Launcher: Trying to continue with root privileges");
96 if (!ecore_drm_tty_open(dev, NULL))
97 {
98 ERR("Launcher: Could not setup tty");
99 return EINA_FALSE;
100 }
101 }
102 else
103 {
104 ERR("Launcher: Root privileges needed");
105 return EINA_FALSE;
106 }
107 }
108
109 dev->tty.switch_hdlr =
110 ecore_event_handler_add(ECORE_EVENT_KEY_DOWN,
111 _ecore_drm_launcher_cb_vt_switch, dev);
112
113 return EINA_TRUE;
114 }
115
116 EAPI void
ecore_drm_launcher_disconnect(Ecore_Drm_Device * dev)117 ecore_drm_launcher_disconnect(Ecore_Drm_Device *dev)
118 {
119 EINA_SAFETY_ON_NULL_RETURN(dev);
120
121 if (dev->tty.switch_hdlr) ecore_event_handler_del(dev->tty.switch_hdlr);
122 dev->tty.switch_hdlr = NULL;
123
124 if (!logind)
125 {
126 if (!ecore_drm_tty_close(dev))
127 ERR("Launcher: Could not close tty");
128 }
129 else
130 {
131 _ecore_drm_logind_disconnect(dev);
132 }
133 }
134
135 Eina_Bool
_ecore_drm_launcher_device_open(const char * device,Ecore_Drm_Open_Cb callback,void * data,int flags)136 _ecore_drm_launcher_device_open(const char *device, Ecore_Drm_Open_Cb callback, void *data, int flags)
137 {
138 int fd = -1;
139 struct stat s;
140
141 if (logind)
142 {
143 if (!_ecore_drm_logind_device_open(device, callback, data))
144 return EINA_FALSE;
145 }
146 else
147 {
148 fd = open(device, flags | O_CLOEXEC);
149 if (fd < 0) return EINA_FALSE;
150 if (fstat(fd, &s) == -1)
151 {
152 close(fd);
153 fd = -1;
154 return EINA_FALSE;
155 }
156
157 callback(data, fd, EINA_FALSE);
158 }
159
160 return EINA_TRUE;
161 }
162
163 int
_ecore_drm_launcher_device_open_no_pending(const char * device,int flags)164 _ecore_drm_launcher_device_open_no_pending(const char *device, int flags)
165 {
166 int fd = -1;
167 struct stat s;
168
169 if (logind)
170 {
171 fd = _ecore_drm_logind_device_open_no_pending(device);
172 if (fd < 0) return -1;
173 if (_ecore_drm_launcher_device_flags_set(fd, flags | O_CLOEXEC) < 0)
174 {
175 close(fd);
176 _ecore_drm_logind_device_close(device);
177 return -1;
178 }
179 }
180 else
181 {
182 fd = open(device, flags | O_CLOEXEC);
183 if (fd < 0) return fd;
184 if (fstat(fd, &s) == -1)
185 {
186 close(fd);
187 return -1;
188 }
189 }
190
191 return fd;
192 }
193
194 void
_ecore_drm_launcher_device_close(const char * device,int fd)195 _ecore_drm_launcher_device_close(const char *device, int fd)
196 {
197 if ((logind) && (device)) _ecore_drm_logind_device_close(device);
198
199 if (fd < 0) return;
200 close(fd);
201 }
202