mirror of
https://gitlab.freedesktop.org/wayland/weston.git
synced 2026-05-02 23:38:05 +02:00
launcher: Split out launcher implementations into three distinct ones
We now have a launcher interface and distinct implementations for logind, weston-launch, and direct DRM, each in their own files. This helps up clean up the spaghetti code into something that's hopefully a bit more understood. There should be no functional changes here. Reviewed-by: Derek Foreman <derekf@osg.samsung.com> update: Dropped redundant free() in weston_launcher_destroy()
This commit is contained in:
parent
30bcf35ceb
commit
72dea06d79
7 changed files with 806 additions and 602 deletions
|
|
@ -127,9 +127,11 @@ noinst_LTLIBRARIES += \
|
|||
libsession-helper.la
|
||||
|
||||
libsession_helper_la_SOURCES = \
|
||||
src/weston-launch.h \
|
||||
src/launcher-util.c \
|
||||
src/launcher-util.h
|
||||
src/launcher-util.h \
|
||||
src/weston-launch.h \
|
||||
src/launcher-weston-launch.c \
|
||||
src/launcher-direct.c
|
||||
libsession_helper_la_CFLAGS = $(AM_CFLAGS) $(LIBDRM_CFLAGS) $(PIXMAN_CFLAGS) $(COMPOSITOR_CFLAGS)
|
||||
libsession_helper_la_LIBADD = $(LIBDRM_LIBS)
|
||||
|
||||
|
|
@ -138,7 +140,6 @@ if HAVE_SYSTEMD_LOGIN
|
|||
libsession_helper_la_SOURCES += \
|
||||
src/dbus.h \
|
||||
src/dbus.c \
|
||||
src/launcher-logind.h \
|
||||
src/launcher-logind.c
|
||||
libsession_helper_la_CFLAGS += $(SYSTEMD_LOGIN_CFLAGS) $(DBUS_CFLAGS)
|
||||
libsession_helper_la_LIBADD += $(SYSTEMD_LOGIN_LIBS) $(DBUS_LIBS)
|
||||
|
|
|
|||
315
src/launcher-direct.c
Normal file
315
src/launcher-direct.c
Normal file
|
|
@ -0,0 +1,315 @@
|
|||
/*
|
||||
* Copyright © 2012 Benjamin Franzke
|
||||
* Copyright © 2013 Intel Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of the copyright holders not be used in
|
||||
* advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. The copyright holders make
|
||||
* no representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "compositor.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/vt.h>
|
||||
#include <linux/kd.h>
|
||||
#include <linux/major.h>
|
||||
|
||||
#include "launcher-impl.h"
|
||||
|
||||
#define DRM_MAJOR 226
|
||||
|
||||
#ifndef KDSKBMUTE
|
||||
#define KDSKBMUTE 0x4B51
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBDRM
|
||||
|
||||
#include <xf86drm.h>
|
||||
|
||||
static inline int
|
||||
is_drm_master(int drm_fd)
|
||||
{
|
||||
drm_magic_t magic;
|
||||
|
||||
return drmGetMagic(drm_fd, &magic) == 0 &&
|
||||
drmAuthMagic(drm_fd, magic) == 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline int
|
||||
drmDropMaster(int drm_fd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
drmSetMaster(int drm_fd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
is_drm_master(int drm_fd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
struct launcher_direct {
|
||||
struct weston_launcher base;
|
||||
struct weston_compositor *compositor;
|
||||
int kb_mode, tty, drm_fd;
|
||||
struct wl_event_source *vt_source;
|
||||
};
|
||||
|
||||
static int
|
||||
vt_handler(int signal_number, void *data)
|
||||
{
|
||||
struct launcher_direct *launcher = data;
|
||||
struct weston_compositor *compositor = launcher->compositor;
|
||||
|
||||
if (compositor->session_active) {
|
||||
compositor->session_active = 0;
|
||||
wl_signal_emit(&compositor->session_signal, compositor);
|
||||
drmDropMaster(launcher->drm_fd);
|
||||
ioctl(launcher->tty, VT_RELDISP, 1);
|
||||
} else {
|
||||
ioctl(launcher->tty, VT_RELDISP, VT_ACKACQ);
|
||||
drmSetMaster(launcher->drm_fd);
|
||||
compositor->session_active = 1;
|
||||
wl_signal_emit(&compositor->session_signal, compositor);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
setup_tty(struct launcher_direct *launcher, int tty)
|
||||
{
|
||||
struct wl_event_loop *loop;
|
||||
struct vt_mode mode = { 0 };
|
||||
struct stat buf;
|
||||
char tty_device[32] ="<stdin>";
|
||||
int ret, kd_mode;
|
||||
|
||||
if (tty == 0) {
|
||||
launcher->tty = dup(tty);
|
||||
if (launcher->tty == -1) {
|
||||
weston_log("couldn't dup stdin: %m\n");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
snprintf(tty_device, sizeof tty_device, "/dev/tty%d", tty);
|
||||
launcher->tty = open(tty_device, O_RDWR | O_CLOEXEC);
|
||||
if (launcher->tty == -1) {
|
||||
weston_log("couldn't open tty %s: %m\n", tty_device);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (fstat(launcher->tty, &buf) == -1 ||
|
||||
major(buf.st_rdev) != TTY_MAJOR || minor(buf.st_rdev) == 0) {
|
||||
weston_log("%s not a vt\n", tty_device);
|
||||
weston_log("if running weston from ssh, "
|
||||
"use --tty to specify a tty\n");
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
ret = ioctl(launcher->tty, KDGETMODE, &kd_mode);
|
||||
if (ret) {
|
||||
weston_log("failed to get VT mode: %m\n");
|
||||
return -1;
|
||||
}
|
||||
if (kd_mode != KD_TEXT) {
|
||||
weston_log("%s is already in graphics mode, "
|
||||
"is another display server running?\n", tty_device);
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
ioctl(launcher->tty, VT_ACTIVATE, minor(buf.st_rdev));
|
||||
ioctl(launcher->tty, VT_WAITACTIVE, minor(buf.st_rdev));
|
||||
|
||||
if (ioctl(launcher->tty, KDGKBMODE, &launcher->kb_mode)) {
|
||||
weston_log("failed to read keyboard mode: %m\n");
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
if (ioctl(launcher->tty, KDSKBMUTE, 1) &&
|
||||
ioctl(launcher->tty, KDSKBMODE, K_OFF)) {
|
||||
weston_log("failed to set K_OFF keyboard mode: %m\n");
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
ret = ioctl(launcher->tty, KDSETMODE, KD_GRAPHICS);
|
||||
if (ret) {
|
||||
weston_log("failed to set KD_GRAPHICS mode on tty: %m\n");
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
/*
|
||||
* SIGRTMIN is used as global VT-acquire+release signal. Note that
|
||||
* SIGRT* must be tested on runtime, as their exact values are not
|
||||
* known at compile-time. POSIX requires 32 of them to be available.
|
||||
*/
|
||||
if (SIGRTMIN > SIGRTMAX) {
|
||||
weston_log("not enough RT signals available: %u-%u\n",
|
||||
SIGRTMIN, SIGRTMAX);
|
||||
ret = -EINVAL;
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
mode.mode = VT_PROCESS;
|
||||
mode.relsig = SIGRTMIN;
|
||||
mode.acqsig = SIGRTMIN;
|
||||
if (ioctl(launcher->tty, VT_SETMODE, &mode) < 0) {
|
||||
weston_log("failed to take control of vt handling\n");
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
loop = wl_display_get_event_loop(launcher->compositor->wl_display);
|
||||
launcher->vt_source =
|
||||
wl_event_loop_add_signal(loop, SIGRTMIN, vt_handler, launcher);
|
||||
if (!launcher->vt_source)
|
||||
goto err_close;
|
||||
|
||||
return 0;
|
||||
|
||||
err_close:
|
||||
close(launcher->tty);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
launcher_direct_open(struct weston_launcher *launcher_base, const char *path, int flags)
|
||||
{
|
||||
struct launcher_direct *launcher = wl_container_of(launcher_base, launcher, base);
|
||||
struct stat s;
|
||||
int fd;
|
||||
|
||||
fd = open(path, flags | O_CLOEXEC);
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
|
||||
if (fstat(fd, &s) == -1) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (major(s.st_rdev) == DRM_MAJOR) {
|
||||
launcher->drm_fd = fd;
|
||||
if (!is_drm_master(fd)) {
|
||||
weston_log("drm fd not master\n");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static void
|
||||
launcher_direct_close(struct weston_launcher *launcher_base, int fd)
|
||||
{
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static void
|
||||
launcher_direct_restore(struct weston_launcher *launcher_base)
|
||||
{
|
||||
struct launcher_direct *launcher = wl_container_of(launcher_base, launcher, base);
|
||||
struct vt_mode mode = { 0 };
|
||||
|
||||
if (ioctl(launcher->tty, KDSKBMUTE, 0) &&
|
||||
ioctl(launcher->tty, KDSKBMODE, launcher->kb_mode))
|
||||
weston_log("failed to restore kb mode: %m\n");
|
||||
|
||||
if (ioctl(launcher->tty, KDSETMODE, KD_TEXT))
|
||||
weston_log("failed to set KD_TEXT mode on tty: %m\n");
|
||||
|
||||
/* We have to drop master before we switch the VT back in
|
||||
* VT_AUTO, so we don't risk switching to a VT with another
|
||||
* display server, that will then fail to set drm master. */
|
||||
drmDropMaster(launcher->drm_fd);
|
||||
|
||||
mode.mode = VT_AUTO;
|
||||
if (ioctl(launcher->tty, VT_SETMODE, &mode) < 0)
|
||||
weston_log("could not reset vt handling\n");
|
||||
}
|
||||
|
||||
static int
|
||||
launcher_direct_activate_vt(struct weston_launcher *launcher_base, int vt)
|
||||
{
|
||||
struct launcher_direct *launcher = wl_container_of(launcher_base, launcher, base);
|
||||
return ioctl(launcher->tty, VT_ACTIVATE, vt);
|
||||
}
|
||||
|
||||
static int
|
||||
launcher_direct_connect(struct weston_launcher **out, struct weston_compositor *compositor,
|
||||
int tty, const char *seat_id, bool sync_drm)
|
||||
{
|
||||
struct launcher_direct *launcher;
|
||||
|
||||
if (geteuid() != 0)
|
||||
return -EINVAL;
|
||||
|
||||
launcher = zalloc(sizeof(*launcher));
|
||||
if (launcher == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
launcher->base.iface = &launcher_direct_iface;
|
||||
launcher->compositor = compositor;
|
||||
|
||||
if (setup_tty(launcher, tty) == -1) {
|
||||
free(launcher);
|
||||
return -1;
|
||||
}
|
||||
|
||||
* (struct launcher_direct **) out = launcher;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
launcher_direct_destroy(struct weston_launcher *launcher_base)
|
||||
{
|
||||
struct launcher_direct *launcher = wl_container_of(launcher_base, launcher, base);
|
||||
|
||||
launcher_direct_restore(&launcher->base);
|
||||
wl_event_source_remove(launcher->vt_source);
|
||||
|
||||
if (launcher->tty >= 0)
|
||||
close(launcher->tty);
|
||||
|
||||
free(launcher);
|
||||
}
|
||||
|
||||
struct launcher_interface launcher_direct_iface = {
|
||||
launcher_direct_connect,
|
||||
launcher_direct_destroy,
|
||||
launcher_direct_open,
|
||||
launcher_direct_close,
|
||||
launcher_direct_activate_vt,
|
||||
launcher_direct_restore,
|
||||
};
|
||||
45
src/launcher-impl.h
Normal file
45
src/launcher-impl.h
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright © 2015 Jasper St. Pierre
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of the copyright holders not be used in
|
||||
* advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. The copyright holders make
|
||||
* no representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "compositor.h"
|
||||
|
||||
struct weston_launcher;
|
||||
|
||||
struct launcher_interface {
|
||||
int (* connect) (struct weston_launcher **launcher_out, struct weston_compositor *compositor,
|
||||
int tty, const char *seat_id, bool sync_drm);
|
||||
void (* destroy) (struct weston_launcher *launcher);
|
||||
int (* open) (struct weston_launcher *launcher, const char *path, int flags);
|
||||
void (* close) (struct weston_launcher *launcher, int fd);
|
||||
int (* activate_vt) (struct weston_launcher *launcher, int vt);
|
||||
void (* restore) (struct weston_launcher *launcher);
|
||||
};
|
||||
|
||||
struct weston_launcher {
|
||||
struct launcher_interface *iface;
|
||||
};
|
||||
|
||||
extern struct launcher_interface launcher_logind_iface;
|
||||
extern struct launcher_interface launcher_weston_launch_iface;
|
||||
extern struct launcher_interface launcher_direct_iface;
|
||||
|
|
@ -44,7 +44,7 @@
|
|||
|
||||
#include "compositor.h"
|
||||
#include "dbus.h"
|
||||
#include "launcher-logind.h"
|
||||
#include "launcher-impl.h"
|
||||
|
||||
#define DRM_MAJOR 226
|
||||
|
||||
|
|
@ -52,7 +52,8 @@
|
|||
#define KDSKBMUTE 0x4B51
|
||||
#endif
|
||||
|
||||
struct weston_logind {
|
||||
struct launcher_logind {
|
||||
struct weston_launcher base;
|
||||
struct weston_compositor *compositor;
|
||||
bool sync_drm;
|
||||
char *seat;
|
||||
|
|
@ -70,7 +71,7 @@ struct weston_logind {
|
|||
};
|
||||
|
||||
static int
|
||||
weston_logind_take_device(struct weston_logind *wl, uint32_t major,
|
||||
launcher_logind_take_device(struct launcher_logind *wl, uint32_t major,
|
||||
uint32_t minor, bool *paused_out)
|
||||
{
|
||||
DBusMessage *m, *reply;
|
||||
|
|
@ -122,7 +123,7 @@ err_unref:
|
|||
}
|
||||
|
||||
static void
|
||||
weston_logind_release_device(struct weston_logind *wl, uint32_t major,
|
||||
launcher_logind_release_device(struct launcher_logind *wl, uint32_t major,
|
||||
uint32_t minor)
|
||||
{
|
||||
DBusMessage *m;
|
||||
|
|
@ -144,7 +145,7 @@ weston_logind_release_device(struct weston_logind *wl, uint32_t major,
|
|||
}
|
||||
|
||||
static void
|
||||
weston_logind_pause_device_complete(struct weston_logind *wl, uint32_t major,
|
||||
launcher_logind_pause_device_complete(struct launcher_logind *wl, uint32_t major,
|
||||
uint32_t minor)
|
||||
{
|
||||
DBusMessage *m;
|
||||
|
|
@ -165,10 +166,10 @@ weston_logind_pause_device_complete(struct weston_logind *wl, uint32_t major,
|
|||
}
|
||||
}
|
||||
|
||||
WL_EXPORT int
|
||||
weston_logind_open(struct weston_logind *wl, const char *path,
|
||||
int flags)
|
||||
static int
|
||||
launcher_logind_open(struct weston_launcher *launcher, const char *path, int flags)
|
||||
{
|
||||
struct launcher_logind *wl = wl_container_of(launcher, wl, base);
|
||||
struct stat st;
|
||||
int fl, r, fd;
|
||||
|
||||
|
|
@ -180,7 +181,7 @@ weston_logind_open(struct weston_logind *wl, const char *path,
|
|||
return -1;
|
||||
}
|
||||
|
||||
fd = weston_logind_take_device(wl, major(st.st_rdev),
|
||||
fd = launcher_logind_take_device(wl, major(st.st_rdev),
|
||||
minor(st.st_rdev), NULL);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
|
@ -210,15 +211,16 @@ weston_logind_open(struct weston_logind *wl, const char *path,
|
|||
|
||||
err_close:
|
||||
close(fd);
|
||||
weston_logind_release_device(wl, major(st.st_rdev),
|
||||
launcher_logind_release_device(wl, major(st.st_rdev),
|
||||
minor(st.st_rdev));
|
||||
errno = -r;
|
||||
return -1;
|
||||
}
|
||||
|
||||
WL_EXPORT void
|
||||
weston_logind_close(struct weston_logind *wl, int fd)
|
||||
static void
|
||||
launcher_logind_close(struct weston_launcher *launcher, int fd)
|
||||
{
|
||||
struct launcher_logind *wl = wl_container_of(launcher, wl, base);
|
||||
struct stat st;
|
||||
int r;
|
||||
|
||||
|
|
@ -233,13 +235,14 @@ weston_logind_close(struct weston_logind *wl, int fd)
|
|||
return;
|
||||
}
|
||||
|
||||
weston_logind_release_device(wl, major(st.st_rdev),
|
||||
launcher_logind_release_device(wl, major(st.st_rdev),
|
||||
minor(st.st_rdev));
|
||||
}
|
||||
|
||||
WL_EXPORT void
|
||||
weston_logind_restore(struct weston_logind *wl)
|
||||
static void
|
||||
launcher_logind_restore(struct weston_launcher *launcher)
|
||||
{
|
||||
struct launcher_logind *wl = wl_container_of(launcher, wl, base);
|
||||
struct vt_mode mode = { 0 };
|
||||
|
||||
ioctl(wl->vt, KDSETMODE, KD_TEXT);
|
||||
|
|
@ -249,9 +252,10 @@ weston_logind_restore(struct weston_logind *wl)
|
|||
ioctl(wl->vt, VT_SETMODE, &mode);
|
||||
}
|
||||
|
||||
WL_EXPORT int
|
||||
weston_logind_activate_vt(struct weston_logind *wl, int vt)
|
||||
static int
|
||||
launcher_logind_activate_vt(struct weston_launcher *launcher, int vt)
|
||||
{
|
||||
struct launcher_logind *wl = wl_container_of(launcher, wl, base);
|
||||
int r;
|
||||
|
||||
r = ioctl(wl->vt, VT_ACTIVATE, vt);
|
||||
|
|
@ -262,7 +266,7 @@ weston_logind_activate_vt(struct weston_logind *wl, int vt)
|
|||
}
|
||||
|
||||
static void
|
||||
weston_logind_set_active(struct weston_logind *wl, bool active)
|
||||
launcher_logind_set_active(struct launcher_logind *wl, bool active)
|
||||
{
|
||||
if (!wl->compositor->session_active == !active)
|
||||
return;
|
||||
|
|
@ -274,7 +278,7 @@ weston_logind_set_active(struct weston_logind *wl, bool active)
|
|||
}
|
||||
|
||||
static void
|
||||
parse_active(struct weston_logind *wl, DBusMessage *m, DBusMessageIter *iter)
|
||||
parse_active(struct launcher_logind *wl, DBusMessage *m, DBusMessageIter *iter)
|
||||
{
|
||||
DBusMessageIter sub;
|
||||
dbus_bool_t b;
|
||||
|
|
@ -293,13 +297,13 @@ parse_active(struct weston_logind *wl, DBusMessage *m, DBusMessageIter *iter)
|
|||
* wake-up the compositor once the master-device is up and running. For
|
||||
* other backends, we immediately forward the Active-change event. */
|
||||
if (!wl->sync_drm || !b)
|
||||
weston_logind_set_active(wl, b);
|
||||
launcher_logind_set_active(wl, b);
|
||||
}
|
||||
|
||||
static void
|
||||
get_active_cb(DBusPendingCall *pending, void *data)
|
||||
{
|
||||
struct weston_logind *wl = data;
|
||||
struct launcher_logind *wl = data;
|
||||
DBusMessageIter iter;
|
||||
DBusMessage *m;
|
||||
int type;
|
||||
|
|
@ -320,7 +324,7 @@ get_active_cb(DBusPendingCall *pending, void *data)
|
|||
}
|
||||
|
||||
static void
|
||||
weston_logind_get_active(struct weston_logind *wl)
|
||||
launcher_logind_get_active(struct launcher_logind *wl)
|
||||
{
|
||||
DBusPendingCall *pending;
|
||||
DBusMessage *m;
|
||||
|
|
@ -366,15 +370,15 @@ err_unref:
|
|||
}
|
||||
|
||||
static void
|
||||
disconnected_dbus(struct weston_logind *wl)
|
||||
disconnected_dbus(struct launcher_logind *wl)
|
||||
{
|
||||
weston_log("logind: dbus connection lost, exiting..\n");
|
||||
weston_logind_restore(wl);
|
||||
launcher_logind_restore(&wl->base);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
static void
|
||||
session_removed(struct weston_logind *wl, DBusMessage *m)
|
||||
session_removed(struct launcher_logind *wl, DBusMessage *m)
|
||||
{
|
||||
const char *name, *obj;
|
||||
bool r;
|
||||
|
|
@ -390,13 +394,13 @@ session_removed(struct weston_logind *wl, DBusMessage *m)
|
|||
|
||||
if (!strcmp(name, wl->sid)) {
|
||||
weston_log("logind: our session got closed, exiting..\n");
|
||||
weston_logind_restore(wl);
|
||||
launcher_logind_restore(&wl->base);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
property_changed(struct weston_logind *wl, DBusMessage *m)
|
||||
property_changed(struct launcher_logind *wl, DBusMessage *m)
|
||||
{
|
||||
DBusMessageIter iter, sub, entry;
|
||||
const char *interface, *name;
|
||||
|
|
@ -441,7 +445,7 @@ property_changed(struct weston_logind *wl, DBusMessage *m)
|
|||
dbus_message_iter_get_basic(&sub, &name);
|
||||
|
||||
if (!strcmp(name, "Active")) {
|
||||
weston_logind_get_active(wl);
|
||||
launcher_logind_get_active(wl);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -455,7 +459,7 @@ error:
|
|||
}
|
||||
|
||||
static void
|
||||
device_paused(struct weston_logind *wl, DBusMessage *m)
|
||||
device_paused(struct launcher_logind *wl, DBusMessage *m)
|
||||
{
|
||||
bool r;
|
||||
const char *type;
|
||||
|
|
@ -480,14 +484,14 @@ device_paused(struct weston_logind *wl, DBusMessage *m)
|
|||
* If it's our main DRM device, tell the compositor to go asleep. */
|
||||
|
||||
if (!strcmp(type, "pause"))
|
||||
weston_logind_pause_device_complete(wl, major, minor);
|
||||
launcher_logind_pause_device_complete(wl, major, minor);
|
||||
|
||||
if (wl->sync_drm && major == DRM_MAJOR)
|
||||
weston_logind_set_active(wl, false);
|
||||
launcher_logind_set_active(wl, false);
|
||||
}
|
||||
|
||||
static void
|
||||
device_resumed(struct weston_logind *wl, DBusMessage *m)
|
||||
device_resumed(struct launcher_logind *wl, DBusMessage *m)
|
||||
{
|
||||
bool r;
|
||||
uint32_t major;
|
||||
|
|
@ -509,13 +513,13 @@ device_resumed(struct weston_logind *wl, DBusMessage *m)
|
|||
* notify the compositor to wake up. */
|
||||
|
||||
if (wl->sync_drm && major == DRM_MAJOR)
|
||||
weston_logind_set_active(wl, true);
|
||||
launcher_logind_set_active(wl, true);
|
||||
}
|
||||
|
||||
static DBusHandlerResult
|
||||
filter_dbus(DBusConnection *c, DBusMessage *m, void *data)
|
||||
{
|
||||
struct weston_logind *wl = data;
|
||||
struct launcher_logind *wl = data;
|
||||
|
||||
if (dbus_message_is_signal(m, DBUS_INTERFACE_LOCAL, "Disconnected")) {
|
||||
disconnected_dbus(wl);
|
||||
|
|
@ -537,7 +541,7 @@ filter_dbus(DBusConnection *c, DBusMessage *m, void *data)
|
|||
}
|
||||
|
||||
static int
|
||||
weston_logind_setup_dbus(struct weston_logind *wl)
|
||||
launcher_logind_setup_dbus(struct launcher_logind *wl)
|
||||
{
|
||||
bool b;
|
||||
int r;
|
||||
|
|
@ -603,14 +607,14 @@ err_spath:
|
|||
}
|
||||
|
||||
static void
|
||||
weston_logind_destroy_dbus(struct weston_logind *wl)
|
||||
launcher_logind_destroy_dbus(struct launcher_logind *wl)
|
||||
{
|
||||
/* don't remove any dbus-match as the connection is closed, anyway */
|
||||
free(wl->spath);
|
||||
}
|
||||
|
||||
static int
|
||||
weston_logind_take_control(struct weston_logind *wl)
|
||||
launcher_logind_take_control(struct launcher_logind *wl)
|
||||
{
|
||||
DBusError err;
|
||||
DBusMessage *m, *reply;
|
||||
|
|
@ -659,7 +663,7 @@ err_unref:
|
|||
}
|
||||
|
||||
static void
|
||||
weston_logind_release_control(struct weston_logind *wl)
|
||||
launcher_logind_release_control(struct launcher_logind *wl)
|
||||
{
|
||||
DBusMessage *m;
|
||||
|
||||
|
|
@ -676,7 +680,7 @@ weston_logind_release_control(struct weston_logind *wl)
|
|||
static int
|
||||
signal_event(int fd, uint32_t mask, void *data)
|
||||
{
|
||||
struct weston_logind *wl = data;
|
||||
struct launcher_logind *wl = data;
|
||||
struct signalfd_siginfo sig;
|
||||
|
||||
if (read(fd, &sig, sizeof sig) != sizeof sig) {
|
||||
|
|
@ -693,7 +697,7 @@ signal_event(int fd, uint32_t mask, void *data)
|
|||
}
|
||||
|
||||
static int
|
||||
weston_logind_setup_vt(struct weston_logind *wl)
|
||||
launcher_logind_setup_vt(struct launcher_logind *wl)
|
||||
{
|
||||
struct stat st;
|
||||
char buf[64];
|
||||
|
|
@ -816,20 +820,42 @@ err_close:
|
|||
}
|
||||
|
||||
static void
|
||||
weston_logind_destroy_vt(struct weston_logind *wl)
|
||||
launcher_logind_destroy_vt(struct launcher_logind *wl)
|
||||
{
|
||||
weston_logind_restore(wl);
|
||||
launcher_logind_restore(&wl->base);
|
||||
wl_event_source_remove(wl->sfd_source);
|
||||
close(wl->sfd);
|
||||
close(wl->vt);
|
||||
}
|
||||
|
||||
WL_EXPORT int
|
||||
weston_logind_connect(struct weston_logind **out,
|
||||
struct weston_compositor *compositor,
|
||||
const char *seat_id, int tty, bool sync_drm)
|
||||
static int
|
||||
weston_sd_session_get_vt(const char *sid, unsigned int *out)
|
||||
{
|
||||
struct weston_logind *wl;
|
||||
#ifdef HAVE_SYSTEMD_LOGIN_209
|
||||
return sd_session_get_vt(sid, out);
|
||||
#else
|
||||
int r;
|
||||
char *tty;
|
||||
|
||||
r = sd_session_get_tty(sid, &tty);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sscanf(tty, "tty%u", out);
|
||||
free(tty);
|
||||
|
||||
if (r != 1)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
launcher_logind_connect(struct weston_launcher **out, struct weston_compositor *compositor,
|
||||
int tty, const char *seat_id, bool sync_drm)
|
||||
{
|
||||
struct launcher_logind *wl;
|
||||
struct wl_event_loop *loop;
|
||||
char *t;
|
||||
int r;
|
||||
|
|
@ -840,6 +866,7 @@ weston_logind_connect(struct weston_logind **out,
|
|||
goto err_out;
|
||||
}
|
||||
|
||||
wl->base.iface = &launcher_logind_iface;
|
||||
wl->compositor = compositor;
|
||||
wl->sync_drm = sync_drm;
|
||||
|
||||
|
|
@ -888,26 +915,26 @@ weston_logind_connect(struct weston_logind **out,
|
|||
goto err_session;
|
||||
}
|
||||
|
||||
r = weston_logind_setup_dbus(wl);
|
||||
r = launcher_logind_setup_dbus(wl);
|
||||
if (r < 0)
|
||||
goto err_dbus;
|
||||
|
||||
r = weston_logind_take_control(wl);
|
||||
r = launcher_logind_take_control(wl);
|
||||
if (r < 0)
|
||||
goto err_dbus_cleanup;
|
||||
|
||||
r = weston_logind_setup_vt(wl);
|
||||
r = launcher_logind_setup_vt(wl);
|
||||
if (r < 0)
|
||||
goto err_control;
|
||||
|
||||
weston_log("logind: session control granted\n");
|
||||
*out = wl;
|
||||
* (struct launcher_logind **) out = wl;
|
||||
return 0;
|
||||
|
||||
err_control:
|
||||
weston_logind_release_control(wl);
|
||||
launcher_logind_release_control(wl);
|
||||
err_dbus_cleanup:
|
||||
weston_logind_destroy_dbus(wl);
|
||||
launcher_logind_destroy_dbus(wl);
|
||||
err_dbus:
|
||||
weston_dbus_close(wl->dbus, wl->dbus_ctx);
|
||||
err_session:
|
||||
|
|
@ -922,19 +949,30 @@ err_out:
|
|||
return -1;
|
||||
}
|
||||
|
||||
WL_EXPORT void
|
||||
weston_logind_destroy(struct weston_logind *wl)
|
||||
static void
|
||||
launcher_logind_destroy(struct weston_launcher *launcher)
|
||||
{
|
||||
struct launcher_logind *wl = wl_container_of(launcher, wl, base);
|
||||
|
||||
if (wl->pending_active) {
|
||||
dbus_pending_call_cancel(wl->pending_active);
|
||||
dbus_pending_call_unref(wl->pending_active);
|
||||
}
|
||||
|
||||
weston_logind_destroy_vt(wl);
|
||||
weston_logind_release_control(wl);
|
||||
weston_logind_destroy_dbus(wl);
|
||||
launcher_logind_destroy_vt(wl);
|
||||
launcher_logind_release_control(wl);
|
||||
launcher_logind_destroy_dbus(wl);
|
||||
weston_dbus_close(wl->dbus, wl->dbus_ctx);
|
||||
free(wl->sid);
|
||||
free(wl->seat);
|
||||
free(wl);
|
||||
}
|
||||
|
||||
struct launcher_interface launcher_logind_iface = {
|
||||
launcher_logind_connect,
|
||||
launcher_logind_destroy,
|
||||
launcher_logind_open,
|
||||
launcher_logind_close,
|
||||
launcher_logind_activate_vt,
|
||||
launcher_logind_restore,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,123 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2013 David Herrmann
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial
|
||||
* portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "compositor.h"
|
||||
|
||||
struct weston_logind;
|
||||
|
||||
#if defined(HAVE_SYSTEMD_LOGIN) && defined(HAVE_DBUS)
|
||||
|
||||
#include <systemd/sd-login.h>
|
||||
|
||||
int
|
||||
weston_logind_open(struct weston_logind *wl, const char *path,
|
||||
int flags);
|
||||
|
||||
void
|
||||
weston_logind_close(struct weston_logind *wl, int fd);
|
||||
|
||||
void
|
||||
weston_logind_restore(struct weston_logind *wl);
|
||||
|
||||
int
|
||||
weston_logind_activate_vt(struct weston_logind *wl, int vt);
|
||||
|
||||
int
|
||||
weston_logind_connect(struct weston_logind **out,
|
||||
struct weston_compositor *compositor,
|
||||
const char *seat_id, int tty, bool sync_drm);
|
||||
|
||||
void
|
||||
weston_logind_destroy(struct weston_logind *wl);
|
||||
|
||||
static inline int
|
||||
weston_sd_session_get_vt(const char *sid, unsigned int *out)
|
||||
{
|
||||
#ifdef HAVE_SYSTEMD_LOGIN_209
|
||||
return sd_session_get_vt(sid, out);
|
||||
#else
|
||||
int r;
|
||||
char *tty;
|
||||
|
||||
r = sd_session_get_tty(sid, &tty);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sscanf(tty, "tty%u", out);
|
||||
free(tty);
|
||||
|
||||
if (r != 1)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#else /* defined(HAVE_SYSTEMD_LOGIN) && defined(HAVE_DBUS) */
|
||||
|
||||
static inline int
|
||||
weston_logind_open(struct weston_logind *wl, const char *path,
|
||||
int flags)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline void
|
||||
weston_logind_close(struct weston_logind *wl, int fd)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
weston_logind_restore(struct weston_logind *wl)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int
|
||||
weston_logind_activate_vt(struct weston_logind *wl, int vt)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int
|
||||
weston_logind_connect(struct weston_logind **out,
|
||||
struct weston_compositor *compositor,
|
||||
const char *seat_id, int tty, bool sync_drm)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline void
|
||||
weston_logind_destroy(struct weston_logind *wl)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* defined(HAVE_SYSTEMD_LOGIN) && defined(HAVE_DBUS) */
|
||||
|
|
@ -26,440 +26,66 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/vt.h>
|
||||
#include <linux/kd.h>
|
||||
#include <linux/major.h>
|
||||
|
||||
#include "compositor.h"
|
||||
|
||||
#include "launcher-util.h"
|
||||
#include "launcher-logind.h"
|
||||
#include "weston-launch.h"
|
||||
#include "launcher-impl.h"
|
||||
|
||||
#define DRM_MAJOR 226
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef KDSKBMUTE
|
||||
#define KDSKBMUTE 0x4B51
|
||||
static struct launcher_interface *ifaces[] = {
|
||||
#ifdef HAVE_SYSTEMD_LOGIN
|
||||
&launcher_logind_iface,
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBDRM
|
||||
|
||||
#include <xf86drm.h>
|
||||
|
||||
static inline int
|
||||
is_drm_master(int drm_fd)
|
||||
{
|
||||
drm_magic_t magic;
|
||||
|
||||
return drmGetMagic(drm_fd, &magic) == 0 &&
|
||||
drmAuthMagic(drm_fd, magic) == 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline int
|
||||
drmDropMaster(int drm_fd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
drmSetMaster(int drm_fd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
is_drm_master(int drm_fd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
union cmsg_data { unsigned char b[4]; int fd; };
|
||||
|
||||
struct weston_launcher {
|
||||
struct weston_compositor *compositor;
|
||||
struct weston_logind *logind;
|
||||
struct wl_event_loop *loop;
|
||||
int fd;
|
||||
struct wl_event_source *source;
|
||||
|
||||
int kb_mode, tty, drm_fd;
|
||||
struct wl_event_source *vt_source;
|
||||
&launcher_weston_launch_iface,
|
||||
&launcher_direct_iface,
|
||||
NULL,
|
||||
};
|
||||
|
||||
int
|
||||
weston_launcher_open(struct weston_launcher *launcher,
|
||||
const char *path, int flags)
|
||||
{
|
||||
int n, fd, ret = -1;
|
||||
struct msghdr msg;
|
||||
struct cmsghdr *cmsg;
|
||||
struct iovec iov;
|
||||
union cmsg_data *data;
|
||||
char control[CMSG_SPACE(sizeof data->fd)];
|
||||
ssize_t len;
|
||||
struct weston_launcher_open *message;
|
||||
struct stat s;
|
||||
|
||||
/* We really don't want to be leaking fds to child processes so
|
||||
* we force this flag here. If someone comes up with a legitimate
|
||||
* reason to not CLOEXEC they'll need to unset the flag manually.
|
||||
*/
|
||||
flags |= O_CLOEXEC;
|
||||
|
||||
if (launcher->logind)
|
||||
return weston_logind_open(launcher->logind, path, flags);
|
||||
|
||||
if (launcher->fd == -1) {
|
||||
fd = open(path, flags);
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
|
||||
if (fstat(fd, &s) == -1) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (major(s.st_rdev) == DRM_MAJOR) {
|
||||
launcher->drm_fd = fd;
|
||||
if (!is_drm_master(fd)) {
|
||||
weston_log("drm fd not master\n");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
n = sizeof(*message) + strlen(path) + 1;
|
||||
message = malloc(n);
|
||||
if (!message)
|
||||
return -1;
|
||||
|
||||
message->header.opcode = WESTON_LAUNCHER_OPEN;
|
||||
message->flags = flags;
|
||||
strcpy(message->path, path);
|
||||
|
||||
do {
|
||||
len = send(launcher->fd, message, n, 0);
|
||||
} while (len < 0 && errno == EINTR);
|
||||
free(message);
|
||||
|
||||
memset(&msg, 0, sizeof msg);
|
||||
iov.iov_base = &ret;
|
||||
iov.iov_len = sizeof ret;
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_control = control;
|
||||
msg.msg_controllen = sizeof control;
|
||||
|
||||
do {
|
||||
len = recvmsg(launcher->fd, &msg, MSG_CMSG_CLOEXEC);
|
||||
} while (len < 0 && errno == EINTR);
|
||||
|
||||
if (len != sizeof ret ||
|
||||
ret < 0)
|
||||
return -1;
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
if (!cmsg ||
|
||||
cmsg->cmsg_level != SOL_SOCKET ||
|
||||
cmsg->cmsg_type != SCM_RIGHTS) {
|
||||
fprintf(stderr, "invalid control message\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
data = (union cmsg_data *) CMSG_DATA(cmsg);
|
||||
if (data->fd == -1) {
|
||||
fprintf(stderr, "missing drm fd in socket request\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return data->fd;
|
||||
}
|
||||
|
||||
void
|
||||
weston_launcher_close(struct weston_launcher *launcher, int fd)
|
||||
{
|
||||
if (launcher->logind)
|
||||
weston_logind_close(launcher->logind, fd);
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void
|
||||
weston_launcher_restore(struct weston_launcher *launcher)
|
||||
{
|
||||
struct vt_mode mode = { 0 };
|
||||
|
||||
if (launcher->logind)
|
||||
return weston_logind_restore(launcher->logind);
|
||||
|
||||
if (ioctl(launcher->tty, KDSKBMUTE, 0) &&
|
||||
ioctl(launcher->tty, KDSKBMODE, launcher->kb_mode))
|
||||
weston_log("failed to restore kb mode: %m\n");
|
||||
|
||||
if (ioctl(launcher->tty, KDSETMODE, KD_TEXT))
|
||||
weston_log("failed to set KD_TEXT mode on tty: %m\n");
|
||||
|
||||
/* We have to drop master before we switch the VT back in
|
||||
* VT_AUTO, so we don't risk switching to a VT with another
|
||||
* display server, that will then fail to set drm master. */
|
||||
drmDropMaster(launcher->drm_fd);
|
||||
|
||||
mode.mode = VT_AUTO;
|
||||
if (ioctl(launcher->tty, VT_SETMODE, &mode) < 0)
|
||||
weston_log("could not reset vt handling\n");
|
||||
}
|
||||
|
||||
static int
|
||||
weston_launcher_data(int fd, uint32_t mask, void *data)
|
||||
{
|
||||
struct weston_launcher *launcher = data;
|
||||
int len, ret;
|
||||
|
||||
if (mask & (WL_EVENT_HANGUP | WL_EVENT_ERROR)) {
|
||||
weston_log("launcher socket closed, exiting\n");
|
||||
/* Normally the weston-launch will reset the tty, but
|
||||
* in this case it died or something, so do it here so
|
||||
* we don't end up with a stuck vt. */
|
||||
weston_launcher_restore(launcher);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
do {
|
||||
len = recv(launcher->fd, &ret, sizeof ret, 0);
|
||||
} while (len < 0 && errno == EINTR);
|
||||
|
||||
switch (ret) {
|
||||
case WESTON_LAUNCHER_ACTIVATE:
|
||||
launcher->compositor->session_active = 1;
|
||||
wl_signal_emit(&launcher->compositor->session_signal,
|
||||
launcher->compositor);
|
||||
break;
|
||||
case WESTON_LAUNCHER_DEACTIVATE:
|
||||
launcher->compositor->session_active = 0;
|
||||
wl_signal_emit(&launcher->compositor->session_signal,
|
||||
launcher->compositor);
|
||||
break;
|
||||
default:
|
||||
weston_log("unexpected event from weston-launch\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
vt_handler(int signal_number, void *data)
|
||||
{
|
||||
struct weston_launcher *launcher = data;
|
||||
struct weston_compositor *compositor = launcher->compositor;
|
||||
|
||||
if (compositor->session_active) {
|
||||
compositor->session_active = 0;
|
||||
wl_signal_emit(&compositor->session_signal, compositor);
|
||||
drmDropMaster(launcher->drm_fd);
|
||||
ioctl(launcher->tty, VT_RELDISP, 1);
|
||||
} else {
|
||||
ioctl(launcher->tty, VT_RELDISP, VT_ACKACQ);
|
||||
drmSetMaster(launcher->drm_fd);
|
||||
compositor->session_active = 1;
|
||||
wl_signal_emit(&compositor->session_signal, compositor);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
setup_tty(struct weston_launcher *launcher, int tty)
|
||||
{
|
||||
struct wl_event_loop *loop;
|
||||
struct vt_mode mode = { 0 };
|
||||
struct stat buf;
|
||||
char tty_device[32] ="<stdin>";
|
||||
int ret, kd_mode;
|
||||
|
||||
if (tty == 0) {
|
||||
launcher->tty = dup(tty);
|
||||
if (launcher->tty == -1) {
|
||||
weston_log("couldn't dup stdin: %m\n");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
snprintf(tty_device, sizeof tty_device, "/dev/tty%d", tty);
|
||||
launcher->tty = open(tty_device, O_RDWR | O_CLOEXEC);
|
||||
if (launcher->tty == -1) {
|
||||
weston_log("couldn't open tty %s: %m\n", tty_device);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (fstat(launcher->tty, &buf) == -1 ||
|
||||
major(buf.st_rdev) != TTY_MAJOR || minor(buf.st_rdev) == 0) {
|
||||
weston_log("%s not a vt\n", tty_device);
|
||||
weston_log("if running weston from ssh, "
|
||||
"use --tty to specify a tty\n");
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
ret = ioctl(launcher->tty, KDGETMODE, &kd_mode);
|
||||
if (ret) {
|
||||
weston_log("failed to get VT mode: %m\n");
|
||||
return -1;
|
||||
}
|
||||
if (kd_mode != KD_TEXT) {
|
||||
weston_log("%s is already in graphics mode, "
|
||||
"is another display server running?\n", tty_device);
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
ioctl(launcher->tty, VT_ACTIVATE, minor(buf.st_rdev));
|
||||
ioctl(launcher->tty, VT_WAITACTIVE, minor(buf.st_rdev));
|
||||
|
||||
if (ioctl(launcher->tty, KDGKBMODE, &launcher->kb_mode)) {
|
||||
weston_log("failed to read keyboard mode: %m\n");
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
if (ioctl(launcher->tty, KDSKBMUTE, 1) &&
|
||||
ioctl(launcher->tty, KDSKBMODE, K_OFF)) {
|
||||
weston_log("failed to set K_OFF keyboard mode: %m\n");
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
ret = ioctl(launcher->tty, KDSETMODE, KD_GRAPHICS);
|
||||
if (ret) {
|
||||
weston_log("failed to set KD_GRAPHICS mode on tty: %m\n");
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
/*
|
||||
* SIGRTMIN is used as global VT-acquire+release signal. Note that
|
||||
* SIGRT* must be tested on runtime, as their exact values are not
|
||||
* known at compile-time. POSIX requires 32 of them to be available.
|
||||
*/
|
||||
if (SIGRTMIN > SIGRTMAX) {
|
||||
weston_log("not enough RT signals available: %u-%u\n",
|
||||
SIGRTMIN, SIGRTMAX);
|
||||
ret = -EINVAL;
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
mode.mode = VT_PROCESS;
|
||||
mode.relsig = SIGRTMIN;
|
||||
mode.acqsig = SIGRTMIN;
|
||||
if (ioctl(launcher->tty, VT_SETMODE, &mode) < 0) {
|
||||
weston_log("failed to take control of vt handling\n");
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
loop = wl_display_get_event_loop(launcher->compositor->wl_display);
|
||||
launcher->vt_source =
|
||||
wl_event_loop_add_signal(loop, SIGRTMIN, vt_handler, launcher);
|
||||
if (!launcher->vt_source)
|
||||
goto err_close;
|
||||
|
||||
return 0;
|
||||
|
||||
err_close:
|
||||
close(launcher->tty);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
weston_launcher_activate_vt(struct weston_launcher *launcher, int vt)
|
||||
{
|
||||
if (launcher->logind)
|
||||
return weston_logind_activate_vt(launcher->logind, vt);
|
||||
|
||||
return ioctl(launcher->tty, VT_ACTIVATE, vt);
|
||||
}
|
||||
|
||||
struct weston_launcher *
|
||||
WL_EXPORT struct weston_launcher *
|
||||
weston_launcher_connect(struct weston_compositor *compositor, int tty,
|
||||
const char *seat_id, bool sync_drm)
|
||||
{
|
||||
struct weston_launcher *launcher;
|
||||
struct wl_event_loop *loop;
|
||||
int r;
|
||||
struct launcher_interface **it;
|
||||
|
||||
launcher = malloc(sizeof *launcher);
|
||||
if (launcher == NULL)
|
||||
return NULL;
|
||||
for (it = ifaces; *it != NULL; it++) {
|
||||
struct launcher_interface *iface = *it;
|
||||
struct weston_launcher *launcher;
|
||||
|
||||
launcher->logind = NULL;
|
||||
launcher->compositor = compositor;
|
||||
launcher->drm_fd = -1;
|
||||
launcher->fd = weston_environment_get_fd("WESTON_LAUNCHER_SOCK");
|
||||
if (launcher->fd != -1) {
|
||||
launcher->tty = weston_environment_get_fd("WESTON_TTY_FD");
|
||||
/* We don't get a chance to read out the original kb
|
||||
* mode for the tty, so just hard code K_UNICODE here
|
||||
* in case we have to clean if weston-launch dies. */
|
||||
launcher->kb_mode = K_UNICODE;
|
||||
|
||||
loop = wl_display_get_event_loop(compositor->wl_display);
|
||||
launcher->source = wl_event_loop_add_fd(loop, launcher->fd,
|
||||
WL_EVENT_READABLE,
|
||||
weston_launcher_data,
|
||||
launcher);
|
||||
if (launcher->source == NULL) {
|
||||
free(launcher);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
r = weston_logind_connect(&launcher->logind, compositor,
|
||||
seat_id, tty, sync_drm);
|
||||
if (r < 0) {
|
||||
launcher->logind = NULL;
|
||||
if (geteuid() == 0) {
|
||||
if (setup_tty(launcher, tty) == -1) {
|
||||
free(launcher);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
free(launcher);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (iface->connect(&launcher, compositor, tty, seat_id, sync_drm) == 0)
|
||||
return launcher;
|
||||
}
|
||||
|
||||
return launcher;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
WL_EXPORT void
|
||||
weston_launcher_destroy(struct weston_launcher *launcher)
|
||||
{
|
||||
if (launcher->logind) {
|
||||
weston_logind_destroy(launcher->logind);
|
||||
} else if (launcher->fd != -1) {
|
||||
close(launcher->fd);
|
||||
wl_event_source_remove(launcher->source);
|
||||
} else {
|
||||
weston_launcher_restore(launcher);
|
||||
wl_event_source_remove(launcher->vt_source);
|
||||
}
|
||||
|
||||
if (launcher->tty >= 0)
|
||||
close(launcher->tty);
|
||||
|
||||
free(launcher);
|
||||
launcher->iface->destroy(launcher);
|
||||
}
|
||||
|
||||
WL_EXPORT int
|
||||
weston_launcher_open(struct weston_launcher *launcher,
|
||||
const char *path, int flags)
|
||||
{
|
||||
return launcher->iface->open(launcher, path, flags);
|
||||
}
|
||||
|
||||
WL_EXPORT void
|
||||
weston_launcher_close(struct weston_launcher *launcher, int fd)
|
||||
{
|
||||
launcher->iface->close(launcher, fd);
|
||||
}
|
||||
|
||||
WL_EXPORT int
|
||||
weston_launcher_activate_vt(struct weston_launcher *launcher, int vt)
|
||||
{
|
||||
return launcher->iface->activate_vt(launcher, vt);
|
||||
}
|
||||
|
||||
WL_EXPORT void
|
||||
weston_launcher_restore(struct weston_launcher *launcher)
|
||||
{
|
||||
launcher->iface->restore(launcher);
|
||||
}
|
||||
|
|
|
|||
302
src/launcher-weston-launch.c
Normal file
302
src/launcher-weston-launch.c
Normal file
|
|
@ -0,0 +1,302 @@
|
|||
/*
|
||||
* Copyright © 2012 Benjamin Franzke
|
||||
* Copyright © 2013 Intel Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of the copyright holders not be used in
|
||||
* advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. The copyright holders make
|
||||
* no representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/vt.h>
|
||||
#include <linux/kd.h>
|
||||
#include <linux/major.h>
|
||||
|
||||
#include "compositor.h"
|
||||
#include "weston-launch.h"
|
||||
#include "launcher-impl.h"
|
||||
|
||||
#define DRM_MAJOR 226
|
||||
|
||||
#ifndef KDSKBMUTE
|
||||
#define KDSKBMUTE 0x4B51
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBDRM
|
||||
|
||||
#include <xf86drm.h>
|
||||
|
||||
static inline int
|
||||
is_drm_master(int drm_fd)
|
||||
{
|
||||
drm_magic_t magic;
|
||||
|
||||
return drmGetMagic(drm_fd, &magic) == 0 &&
|
||||
drmAuthMagic(drm_fd, magic) == 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline int
|
||||
drmDropMaster(int drm_fd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
drmSetMaster(int drm_fd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
is_drm_master(int drm_fd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
union cmsg_data { unsigned char b[4]; int fd; };
|
||||
|
||||
struct launcher_weston_launch {
|
||||
struct weston_launcher base;
|
||||
struct weston_compositor *compositor;
|
||||
struct wl_event_loop *loop;
|
||||
int fd;
|
||||
struct wl_event_source *source;
|
||||
|
||||
int kb_mode, tty, drm_fd;
|
||||
struct wl_event_source *vt_source;
|
||||
};
|
||||
|
||||
static int
|
||||
launcher_weston_launch_open(struct weston_launcher *launcher_base,
|
||||
const char *path, int flags)
|
||||
{
|
||||
struct launcher_weston_launch *launcher = wl_container_of(launcher_base, launcher, base);
|
||||
int n, ret;
|
||||
struct msghdr msg;
|
||||
struct cmsghdr *cmsg;
|
||||
struct iovec iov;
|
||||
union cmsg_data *data;
|
||||
char control[CMSG_SPACE(sizeof data->fd)];
|
||||
ssize_t len;
|
||||
struct weston_launcher_open *message;
|
||||
|
||||
n = sizeof(*message) + strlen(path) + 1;
|
||||
message = malloc(n);
|
||||
if (!message)
|
||||
return -1;
|
||||
|
||||
message->header.opcode = WESTON_LAUNCHER_OPEN;
|
||||
message->flags = flags;
|
||||
strcpy(message->path, path);
|
||||
|
||||
do {
|
||||
len = send(launcher->fd, message, n, 0);
|
||||
} while (len < 0 && errno == EINTR);
|
||||
free(message);
|
||||
|
||||
memset(&msg, 0, sizeof msg);
|
||||
iov.iov_base = &ret;
|
||||
iov.iov_len = sizeof ret;
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_control = control;
|
||||
msg.msg_controllen = sizeof control;
|
||||
|
||||
do {
|
||||
len = recvmsg(launcher->fd, &msg, MSG_CMSG_CLOEXEC);
|
||||
} while (len < 0 && errno == EINTR);
|
||||
|
||||
if (len != sizeof ret ||
|
||||
ret < 0)
|
||||
return -1;
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
if (!cmsg ||
|
||||
cmsg->cmsg_level != SOL_SOCKET ||
|
||||
cmsg->cmsg_type != SCM_RIGHTS) {
|
||||
fprintf(stderr, "invalid control message\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
data = (union cmsg_data *) CMSG_DATA(cmsg);
|
||||
if (data->fd == -1) {
|
||||
fprintf(stderr, "missing drm fd in socket request\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return data->fd;
|
||||
}
|
||||
|
||||
static void
|
||||
launcher_weston_launch_close(struct weston_launcher *launcher_base, int fd)
|
||||
{
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static void
|
||||
launcher_weston_launch_restore(struct weston_launcher *launcher_base)
|
||||
{
|
||||
struct launcher_weston_launch *launcher = wl_container_of(launcher_base, launcher, base);
|
||||
struct vt_mode mode = { 0 };
|
||||
|
||||
if (ioctl(launcher->tty, KDSKBMUTE, 0) &&
|
||||
ioctl(launcher->tty, KDSKBMODE, launcher->kb_mode))
|
||||
weston_log("failed to restore kb mode: %m\n");
|
||||
|
||||
if (ioctl(launcher->tty, KDSETMODE, KD_TEXT))
|
||||
weston_log("failed to set KD_TEXT mode on tty: %m\n");
|
||||
|
||||
/* We have to drop master before we switch the VT back in
|
||||
* VT_AUTO, so we don't risk switching to a VT with another
|
||||
* display server, that will then fail to set drm master. */
|
||||
drmDropMaster(launcher->drm_fd);
|
||||
|
||||
mode.mode = VT_AUTO;
|
||||
if (ioctl(launcher->tty, VT_SETMODE, &mode) < 0)
|
||||
weston_log("could not reset vt handling\n");
|
||||
}
|
||||
|
||||
static int
|
||||
launcher_weston_launch_data(int fd, uint32_t mask, void *data)
|
||||
{
|
||||
struct launcher_weston_launch *launcher = data;
|
||||
int len, ret;
|
||||
|
||||
if (mask & (WL_EVENT_HANGUP | WL_EVENT_ERROR)) {
|
||||
weston_log("launcher socket closed, exiting\n");
|
||||
/* Normally the weston-launch will reset the tty, but
|
||||
* in this case it died or something, so do it here so
|
||||
* we don't end up with a stuck vt. */
|
||||
launcher_weston_launch_restore(&launcher->base);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
do {
|
||||
len = recv(launcher->fd, &ret, sizeof ret, 0);
|
||||
} while (len < 0 && errno == EINTR);
|
||||
|
||||
switch (ret) {
|
||||
case WESTON_LAUNCHER_ACTIVATE:
|
||||
launcher->compositor->session_active = 1;
|
||||
wl_signal_emit(&launcher->compositor->session_signal,
|
||||
launcher->compositor);
|
||||
break;
|
||||
case WESTON_LAUNCHER_DEACTIVATE:
|
||||
launcher->compositor->session_active = 0;
|
||||
wl_signal_emit(&launcher->compositor->session_signal,
|
||||
launcher->compositor);
|
||||
break;
|
||||
default:
|
||||
weston_log("unexpected event from weston-launch\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
launcher_weston_launch_activate_vt(struct weston_launcher *launcher_base, int vt)
|
||||
{
|
||||
struct launcher_weston_launch *launcher = wl_container_of(launcher_base, launcher, base);
|
||||
return ioctl(launcher->tty, VT_ACTIVATE, vt);
|
||||
}
|
||||
|
||||
static int
|
||||
launcher_weston_launch_connect(struct weston_launcher **out, struct weston_compositor *compositor,
|
||||
int tty, const char *seat_id, bool sync_drm)
|
||||
{
|
||||
struct launcher_weston_launch *launcher;
|
||||
struct wl_event_loop *loop;
|
||||
|
||||
launcher = malloc(sizeof *launcher);
|
||||
if (launcher == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
launcher->base.iface = &launcher_weston_launch_iface;
|
||||
* (struct launcher_weston_launch **) out = launcher;
|
||||
launcher->compositor = compositor;
|
||||
launcher->drm_fd = -1;
|
||||
launcher->fd = weston_environment_get_fd("WESTON_LAUNCH_SOCK");
|
||||
if (launcher->fd != -1) {
|
||||
launcher->tty = weston_environment_get_fd("WESTON_TTY_FD");
|
||||
/* We don't get a chance to read out the original kb
|
||||
* mode for the tty, so just hard code K_UNICODE here
|
||||
* in case we have to clean if weston-launch dies. */
|
||||
launcher->kb_mode = K_UNICODE;
|
||||
|
||||
loop = wl_display_get_event_loop(compositor->wl_display);
|
||||
launcher->source = wl_event_loop_add_fd(loop, launcher->fd,
|
||||
WL_EVENT_READABLE,
|
||||
launcher_weston_launch_data,
|
||||
launcher);
|
||||
if (launcher->source == NULL) {
|
||||
free(launcher);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
launcher_weston_launch_destroy(struct weston_launcher *launcher_base)
|
||||
{
|
||||
struct launcher_weston_launch *launcher = wl_container_of(launcher_base, launcher, base);
|
||||
|
||||
if (launcher->fd != -1) {
|
||||
close(launcher->fd);
|
||||
wl_event_source_remove(launcher->source);
|
||||
} else {
|
||||
launcher_weston_launch_restore(&launcher->base);
|
||||
wl_event_source_remove(launcher->vt_source);
|
||||
}
|
||||
|
||||
if (launcher->tty >= 0)
|
||||
close(launcher->tty);
|
||||
|
||||
free(launcher);
|
||||
}
|
||||
|
||||
struct launcher_interface launcher_weston_launch_iface = {
|
||||
launcher_weston_launch_connect,
|
||||
launcher_weston_launch_destroy,
|
||||
launcher_weston_launch_open,
|
||||
launcher_weston_launch_close,
|
||||
launcher_weston_launch_activate_vt,
|
||||
launcher_weston_launch_restore,
|
||||
};
|
||||
Loading…
Add table
Reference in a new issue