weston/libweston/launcher-libseat.c
Marius Vlad c19cf3d684 libweston: Enable logging for libseat launcher
The built-in backend of libseat requires users to enable a logging
level in order for libseat to start writing out log messages.  For that
to happen we split out the info and error log level messages into the
compositor's log scope, while debug level messages go into a dedicated
scope.

With that, this patch brings in a new scope, called libseat-debug, which
users need to explicity create a subscription for it as to retrieve/have
access to debug message coming out of libseat. Note that by default we
have a subscription for the log-scope so any errors/info from libseat
would be displayed to the user.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2022-03-10 17:13:16 +02:00

312 lines
7.3 KiB
C

/*
* Copyright © 2020 Kenny Levinsen
*
* 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 <fcntl.h>
#include <signal.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <libseat.h>
#include <libweston/libweston.h>
#include <libweston/weston-log.h>
#include "weston-log-internal.h"
#include "backend.h"
#include "dbus.h"
#include "launcher-impl.h"
struct launcher_libseat_device {
struct wl_list link;
int fd;
int device_id;
dev_t fsdev;
};
struct launcher_libseat {
struct weston_launcher base;
struct weston_compositor *compositor;
struct libseat *seat;
struct wl_event_source *seat_ctx;
struct wl_list devices;
};
/* debug messages go into a dedicated libseat-debug scope, while info and err
* log level messages go into the log_scope, which the compositor has a
* subscription by default*/
static struct weston_log_scope *libseat_debug_scope = NULL;
static struct launcher_libseat_device *
find_device_by_fd(struct launcher_libseat *wl, int fd)
{
struct launcher_libseat_device *dev;
wl_list_for_each(dev, &wl->devices, link) {
if (dev->fd == fd) {
return dev;
}
}
return NULL;
}
static void
handle_enable_seat(struct libseat *seat, void *data)
{
struct launcher_libseat *wl = data;
if (wl->compositor->session_active)
return;
wl->compositor->session_active = true;
wl_signal_emit(&wl->compositor->session_signal,
wl->compositor);
}
static void
handle_disable_seat(struct libseat *seat, void *data)
{
struct launcher_libseat *wl = data;
if (!wl->compositor->session_active)
return;
wl->compositor->session_active = false;
wl_signal_emit(&wl->compositor->session_signal,
wl->compositor);
libseat_disable_seat(wl->seat);
}
static struct libseat_seat_listener seat_listener = {
.enable_seat = handle_enable_seat,
.disable_seat = handle_disable_seat,
};
static int
seat_open_device(struct weston_launcher *launcher, const char *path, int flags)
{
struct launcher_libseat *wl = wl_container_of(launcher, wl, base);
struct launcher_libseat_device *dev;
struct stat st;
dev = zalloc(sizeof(struct launcher_libseat_device));
if (dev == NULL) {
goto err_alloc;
}
dev->device_id = libseat_open_device(wl->seat, path, &dev->fd);
if (dev->device_id == -1) {
goto err_open;
}
if (fstat(dev->fd, &st) == -1) {
goto err_fd;
}
dev->fsdev = st.st_rdev;
wl_list_insert(&wl->devices, &dev->link);
return dev->fd;
err_fd:
libseat_close_device(wl->seat, dev->device_id);
close(dev->fd);
err_open:
free(dev);
err_alloc:
return -1;
}
static void
seat_close_device(struct weston_launcher *launcher, int fd)
{
struct launcher_libseat *wl = wl_container_of(launcher, wl, base);
struct launcher_libseat_device *dev;
dev = find_device_by_fd(wl, fd);
if (dev == NULL) {
weston_log("libseat: No device with fd %d found\n", fd);
close(fd);
return;
}
if (libseat_close_device(wl->seat, dev->device_id) == -1) {
weston_log("libseat: Could not close device %d",
dev->device_id);
}
wl_list_remove(&dev->link);
free(dev);
close(fd);
}
static int
seat_switch_session(struct weston_launcher *launcher, int vt)
{
struct launcher_libseat *wl = wl_container_of(launcher, wl, base);
return libseat_switch_session(wl->seat, vt);
}
static int
libseat_event(int fd, uint32_t mask, void *data)
{
struct libseat *seat = data;
if (libseat_dispatch(seat, 0) == -1) {
weston_log("libseat: dispatch failed: %s\n", strerror(errno));
exit(-1);
}
return 1;
}
static void
log_libseat_info_err(const char *fmt, va_list ap)
{
/* these all have been set-up by the compositor and use the 'log' scope */
weston_vlog(fmt, ap);
weston_log_continue("\n");
}
static void
log_libseat_debug(const char *fmt, va_list ap)
{
int len_va;
char *str;
const char *oom = "Out of memory";
if (!weston_log_scope_is_enabled(libseat_debug_scope))
return;
len_va = vasprintf(&str, fmt, ap);
if (len_va >= 0) {
weston_log_scope_printf(libseat_debug_scope, "%s\n", str);
free(str);
} else {
weston_log_scope_printf(libseat_debug_scope, "%s\n", oom);
}
}
static void log_libseat(enum libseat_log_level level,
const char *fmt, va_list ap)
{
if (level == LIBSEAT_LOG_LEVEL_DEBUG) {
log_libseat_debug(fmt, ap);
return;
}
log_libseat_info_err(fmt, ap);
}
static int
seat_open(struct weston_launcher **out, struct weston_compositor *compositor,
const char *seat_id, bool sync_drm)
{
struct launcher_libseat *wl;
struct wl_event_loop *event_loop;
wl = zalloc(sizeof(*wl));
if (wl == NULL) {
goto err_out;
}
wl->base.iface = &launcher_libseat_iface;
wl->compositor = compositor;
wl_list_init(&wl->devices);
libseat_debug_scope = compositor->libseat_debug;
assert(libseat_debug_scope);
libseat_set_log_handler(log_libseat);
/* includes (all) other log levels available <= LOG_LEVEL_DEBUG */
libseat_set_log_level(LIBSEAT_LOG_LEVEL_DEBUG);
wl->seat = libseat_open_seat(&seat_listener, wl);
if (wl->seat == NULL) {
weston_log("libseat: could not open seat\n");
goto err_seat;
}
event_loop = wl_display_get_event_loop(compositor->wl_display);
wl->seat_ctx = wl_event_loop_add_fd(event_loop,
libseat_get_fd(wl->seat), WL_EVENT_READABLE,
libseat_event, wl->seat);
if (wl->seat_ctx == NULL) {
weston_log("libseat: could not register connection to event loop\n");
goto err_session;
}
if (libseat_dispatch(wl->seat, 0) == -1) {
weston_log("libseat: dispatch failed\n");
goto err_session;
}
weston_log("libseat: session control granted\n");
*out = &wl->base;
return 0;
err_session:
libseat_close_seat(wl->seat);
err_seat:
free(wl);
err_out:
return -1;
}
static void
seat_close(struct weston_launcher *launcher)
{
struct launcher_libseat *wl = wl_container_of(launcher, wl, base);
libseat_debug_scope = NULL;
libseat_set_log_handler(NULL);
if (wl->seat != NULL) {
libseat_close_seat(wl->seat);
}
wl_event_source_remove(wl->seat_ctx);
free(wl);
}
static int
seat_get_vt(struct weston_launcher *launcher)
{
return -ENOSYS;
}
const struct launcher_interface launcher_libseat_iface = {
.name = "libseat",
.connect = seat_open,
.destroy = seat_close,
.open = seat_open_device,
.close = seat_close_device,
.activate_vt = seat_switch_session,
.get_vt = seat_get_vt,
};