blob: 2c9128cf485b0051edf8a0d321eb1dfe0ac19cb3 [file] [log] [blame]
Jasper St. Pierre72dea062015-09-23 10:46:47 -07001/*
2 * Copyright © 2012 Benjamin Franzke
3 * Copyright © 2013 Intel Corporation
4 *
5 * Permission to use, copy, modify, distribute, and sell this software and
6 * its documentation for any purpose is hereby granted without fee, provided
7 * that the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of the copyright holders not be used in
10 * advertising or publicity pertaining to distribution of the software
11 * without specific, written prior permission. The copyright holders make
12 * no representations about the suitability of this software for any
13 * purpose. It is provided "as is" without express or implied warranty.
14 *
15 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
16 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
19 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
20 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 */
23
24#include "config.h"
25
Jussi Kukkonen649bbce2016-07-19 14:16:27 +030026#include <stdint.h>
Jasper St. Pierre72dea062015-09-23 10:46:47 -070027#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30
31#include <errno.h>
32#include <signal.h>
33#include <sys/socket.h>
34#include <sys/types.h>
35#include <sys/stat.h>
36#include <sys/uio.h>
37#include <sys/ioctl.h>
38#include <fcntl.h>
39#include <unistd.h>
40#include <linux/vt.h>
41#include <linux/kd.h>
42#include <linux/major.h>
43
44#include "compositor.h"
45#include "weston-launch.h"
46#include "launcher-impl.h"
47
48#define DRM_MAJOR 226
49
50#ifndef KDSKBMUTE
51#define KDSKBMUTE 0x4B51
52#endif
53
54#ifdef HAVE_LIBDRM
55
56#include <xf86drm.h>
57
Jasper St. Pierre72dea062015-09-23 10:46:47 -070058#else
59
60static inline int
61drmDropMaster(int drm_fd)
62{
63 return 0;
64}
65
66static inline int
67drmSetMaster(int drm_fd)
68{
69 return 0;
70}
71
Jasper St. Pierre72dea062015-09-23 10:46:47 -070072#endif
73
74
75union cmsg_data { unsigned char b[4]; int fd; };
76
77struct launcher_weston_launch {
78 struct weston_launcher base;
79 struct weston_compositor *compositor;
80 struct wl_event_loop *loop;
81 int fd;
82 struct wl_event_source *source;
83
84 int kb_mode, tty, drm_fd;
Jasper St. Pierre72dea062015-09-23 10:46:47 -070085};
86
87static int
88launcher_weston_launch_open(struct weston_launcher *launcher_base,
89 const char *path, int flags)
90{
91 struct launcher_weston_launch *launcher = wl_container_of(launcher_base, launcher, base);
92 int n, ret;
93 struct msghdr msg;
94 struct cmsghdr *cmsg;
95 struct iovec iov;
96 union cmsg_data *data;
97 char control[CMSG_SPACE(sizeof data->fd)];
98 ssize_t len;
99 struct weston_launcher_open *message;
100
101 n = sizeof(*message) + strlen(path) + 1;
102 message = malloc(n);
103 if (!message)
104 return -1;
105
106 message->header.opcode = WESTON_LAUNCHER_OPEN;
107 message->flags = flags;
108 strcpy(message->path, path);
109
110 do {
111 len = send(launcher->fd, message, n, 0);
112 } while (len < 0 && errno == EINTR);
113 free(message);
114
115 memset(&msg, 0, sizeof msg);
116 iov.iov_base = &ret;
117 iov.iov_len = sizeof ret;
118 msg.msg_iov = &iov;
119 msg.msg_iovlen = 1;
120 msg.msg_control = control;
121 msg.msg_controllen = sizeof control;
122
123 do {
124 len = recvmsg(launcher->fd, &msg, MSG_CMSG_CLOEXEC);
125 } while (len < 0 && errno == EINTR);
126
127 if (len != sizeof ret ||
128 ret < 0)
129 return -1;
130
131 cmsg = CMSG_FIRSTHDR(&msg);
132 if (!cmsg ||
133 cmsg->cmsg_level != SOL_SOCKET ||
134 cmsg->cmsg_type != SCM_RIGHTS) {
135 fprintf(stderr, "invalid control message\n");
136 return -1;
137 }
138
139 data = (union cmsg_data *) CMSG_DATA(cmsg);
140 if (data->fd == -1) {
141 fprintf(stderr, "missing drm fd in socket request\n");
142 return -1;
143 }
144
145 return data->fd;
146}
147
148static void
149launcher_weston_launch_close(struct weston_launcher *launcher_base, int fd)
150{
151 close(fd);
152}
153
154static void
155launcher_weston_launch_restore(struct weston_launcher *launcher_base)
156{
157 struct launcher_weston_launch *launcher = wl_container_of(launcher_base, launcher, base);
158 struct vt_mode mode = { 0 };
159
160 if (ioctl(launcher->tty, KDSKBMUTE, 0) &&
161 ioctl(launcher->tty, KDSKBMODE, launcher->kb_mode))
162 weston_log("failed to restore kb mode: %m\n");
163
164 if (ioctl(launcher->tty, KDSETMODE, KD_TEXT))
165 weston_log("failed to set KD_TEXT mode on tty: %m\n");
166
167 /* We have to drop master before we switch the VT back in
168 * VT_AUTO, so we don't risk switching to a VT with another
169 * display server, that will then fail to set drm master. */
170 drmDropMaster(launcher->drm_fd);
171
172 mode.mode = VT_AUTO;
173 if (ioctl(launcher->tty, VT_SETMODE, &mode) < 0)
174 weston_log("could not reset vt handling\n");
175}
176
177static int
178launcher_weston_launch_data(int fd, uint32_t mask, void *data)
179{
180 struct launcher_weston_launch *launcher = data;
181 int len, ret;
182
183 if (mask & (WL_EVENT_HANGUP | WL_EVENT_ERROR)) {
184 weston_log("launcher socket closed, exiting\n");
185 /* Normally the weston-launch will reset the tty, but
186 * in this case it died or something, so do it here so
187 * we don't end up with a stuck vt. */
188 launcher_weston_launch_restore(&launcher->base);
189 exit(-1);
190 }
191
192 do {
193 len = recv(launcher->fd, &ret, sizeof ret, 0);
194 } while (len < 0 && errno == EINTR);
195
196 switch (ret) {
197 case WESTON_LAUNCHER_ACTIVATE:
198 launcher->compositor->session_active = 1;
199 wl_signal_emit(&launcher->compositor->session_signal,
200 launcher->compositor);
201 break;
202 case WESTON_LAUNCHER_DEACTIVATE:
203 launcher->compositor->session_active = 0;
204 wl_signal_emit(&launcher->compositor->session_signal,
205 launcher->compositor);
206 break;
207 default:
208 weston_log("unexpected event from weston-launch\n");
209 break;
210 }
211
212 return 1;
213}
214
215static int
216launcher_weston_launch_activate_vt(struct weston_launcher *launcher_base, int vt)
217{
218 struct launcher_weston_launch *launcher = wl_container_of(launcher_base, launcher, base);
219 return ioctl(launcher->tty, VT_ACTIVATE, vt);
220}
221
222static int
223launcher_weston_launch_connect(struct weston_launcher **out, struct weston_compositor *compositor,
224 int tty, const char *seat_id, bool sync_drm)
225{
226 struct launcher_weston_launch *launcher;
227 struct wl_event_loop *loop;
228
229 launcher = malloc(sizeof *launcher);
230 if (launcher == NULL)
231 return -ENOMEM;
232
233 launcher->base.iface = &launcher_weston_launch_iface;
234 * (struct launcher_weston_launch **) out = launcher;
235 launcher->compositor = compositor;
236 launcher->drm_fd = -1;
Derek Foremane7d868a2015-09-24 14:30:38 -0500237 launcher->fd = weston_environment_get_fd("WESTON_LAUNCHER_SOCK");
Jasper St. Pierre72dea062015-09-23 10:46:47 -0700238 if (launcher->fd != -1) {
239 launcher->tty = weston_environment_get_fd("WESTON_TTY_FD");
240 /* We don't get a chance to read out the original kb
241 * mode for the tty, so just hard code K_UNICODE here
242 * in case we have to clean if weston-launch dies. */
243 launcher->kb_mode = K_UNICODE;
244
245 loop = wl_display_get_event_loop(compositor->wl_display);
246 launcher->source = wl_event_loop_add_fd(loop, launcher->fd,
247 WL_EVENT_READABLE,
248 launcher_weston_launch_data,
249 launcher);
250 if (launcher->source == NULL) {
251 free(launcher);
252 return -ENOMEM;
253 }
254
255 return 0;
256 } else {
257 return -1;
258 }
259}
260
261static void
262launcher_weston_launch_destroy(struct weston_launcher *launcher_base)
263{
264 struct launcher_weston_launch *launcher = wl_container_of(launcher_base, launcher, base);
265
266 if (launcher->fd != -1) {
267 close(launcher->fd);
268 wl_event_source_remove(launcher->source);
269 } else {
270 launcher_weston_launch_restore(&launcher->base);
Jasper St. Pierre72dea062015-09-23 10:46:47 -0700271 }
272
273 if (launcher->tty >= 0)
274 close(launcher->tty);
275
276 free(launcher);
277}
278
Giulio Camuffoa32986e2016-12-05 14:50:36 +0100279static int
280launcher_weston_launch_get_vt(struct weston_launcher *base)
281{
282 struct launcher_weston_launch *launcher = wl_container_of(base, launcher, base);
283 struct stat s;
284 if (fstat(launcher->tty, &s) < 0)
285 return -1;
286
287 return minor(s.st_rdev);
288}
289
Jasper St. Pierre72dea062015-09-23 10:46:47 -0700290struct launcher_interface launcher_weston_launch_iface = {
291 launcher_weston_launch_connect,
292 launcher_weston_launch_destroy,
293 launcher_weston_launch_open,
294 launcher_weston_launch_close,
295 launcher_weston_launch_activate_vt,
296 launcher_weston_launch_restore,
Giulio Camuffoa32986e2016-12-05 14:50:36 +0100297 launcher_weston_launch_get_vt,
Jasper St. Pierre72dea062015-09-23 10:46:47 -0700298};