aboutsummaryrefslogtreecommitdiff
path: root/libseat/backend/noop.c
diff options
context:
space:
mode:
authorSimon Ser <contact@emersion.fr>2021-03-26 10:05:12 +0100
committerKenny Levinsen <kl@kl.wtf>2021-03-26 11:11:26 +0100
commit9a7824b7c3ff5c957632671e91454fc84fbcdda8 (patch)
treecf103f2f5591943b61cb330e129e20de546477ea /libseat/backend/noop.c
parent5ad91ae9dad205331ede6579b2b24b53e02a6287 (diff)
Add no-op session
This is useful for headless testing, for instance with VKMS: modprobe vkms export WLR_DRM_DEVICES=/dev/dri/card1 export WLR_BACKENDS=drm export LIBSEAT_BACKEND=noop sway We don't need any of the VT handling in this case.
Diffstat (limited to 'libseat/backend/noop.c')
-rw-r--r--libseat/backend/noop.c135
1 files changed, 135 insertions, 0 deletions
diff --git a/libseat/backend/noop.c b/libseat/backend/noop.c
new file mode 100644
index 0000000..71d0224
--- /dev/null
+++ b/libseat/backend/noop.c
@@ -0,0 +1,135 @@
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include "backend.h"
+#include "log.h"
+
+struct backend_noop {
+ struct libseat base;
+ struct libseat_seat_listener *seat_listener;
+ void *seat_listener_data;
+
+ bool initial_setup;
+ int sockets[2];
+};
+
+extern const struct seat_impl noop_impl;
+
+static struct backend_noop *backend_noop_from_libseat_backend(struct libseat *base) {
+ assert(base->impl == &noop_impl);
+ return (struct backend_noop *)base;
+}
+
+static void destroy(struct backend_noop *backend) {
+ close(backend->sockets[0]);
+ close(backend->sockets[1]);
+ free(backend);
+}
+
+static int close_seat(struct libseat *base) {
+ struct backend_noop *backend = backend_noop_from_libseat_backend(base);
+ destroy(backend);
+ return 0;
+}
+
+static int disable_seat(struct libseat *base) {
+ (void)base;
+ return 0;
+}
+
+static const char *seat_name(struct libseat *base) {
+ (void)base;
+ return "noop";
+}
+
+static int open_device(struct libseat *base, const char *path, int *fd) {
+ (void)base;
+
+ int tmpfd = open(path, O_RDWR | O_CLOEXEC);
+ if (tmpfd < 0) {
+ log_errorf("Failed to open device: %s", strerror(errno));
+ return -1;
+ }
+
+ *fd = tmpfd;
+ return tmpfd;
+}
+
+static int close_device(struct libseat *base, int device_id) {
+ (void)base;
+ (void)device_id;
+ return 0;
+}
+
+static int switch_session(struct libseat *base, int s) {
+ (void)base;
+ (void)s;
+ log_errorf("No-op backend cannot switch to session %d", s);
+ return -1;
+}
+
+static int get_fd(struct libseat *base) {
+ struct backend_noop *backend = backend_noop_from_libseat_backend(base);
+ return backend->sockets[0];
+}
+
+static int dispatch_background(struct libseat *base, int timeout) {
+ struct backend_noop *backend = backend_noop_from_libseat_backend(base);
+
+ if (backend->initial_setup) {
+ backend->initial_setup = false;
+ backend->seat_listener->enable_seat(&backend->base, backend->seat_listener_data);
+ }
+
+ struct pollfd fd = {
+ .fd = backend->sockets[0],
+ .events = POLLIN,
+ };
+ if (poll(&fd, 1, timeout) < 0) {
+ if (errno == EAGAIN || errno == EINTR) {
+ return 0;
+ } else {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static struct libseat *noop_open_seat(struct libseat_seat_listener *listener, void *data) {
+ struct backend_noop *backend = calloc(1, sizeof(struct backend_noop));
+ if (backend == NULL) {
+ return NULL;
+ }
+
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, backend->sockets) != 0) {
+ log_errorf("socketpair() failed: %s", strerror(errno));
+ free(backend);
+ return NULL;
+ }
+
+ backend->seat_listener = listener;
+ backend->seat_listener_data = data;
+ backend->base.impl = &noop_impl;
+
+ return &backend->base;
+}
+
+const struct seat_impl noop_impl = {
+ .open_seat = noop_open_seat,
+ .disable_seat = disable_seat,
+ .close_seat = close_seat,
+ .seat_name = seat_name,
+ .open_device = open_device,
+ .close_device = close_device,
+ .switch_session = switch_session,
+ .get_fd = get_fd,
+ .dispatch = dispatch_background,
+};