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