Added libevdev node

This commit is contained in:
Vftdan 2024-08-14 14:47:12 +02:00
parent d3a3217e88
commit 65769a7442
4 changed files with 146 additions and 4 deletions

View File

@ -1,4 +1,4 @@
DEPS = DEPS = libevdev
CFLAGS = -Wall -Wextra CFLAGS = -Wall -Wextra
ifdef DEBUG ifdef DEBUG
CFLAGS += -Og -gdwarf-2 CFLAGS += -Og -gdwarf-2
@ -10,7 +10,7 @@ CPPFLAGS += $(shell pkg-config --cflags $(DEPS))
LDLIBS += $(shell pkg-config --libs $(DEPS)) LDLIBS += $(shell pkg-config --libs $(DEPS))
INTERP ?= INTERP ?=
MAIN = main MAIN = main
OBJS = main.o events.o processing.o graph.o nodes/getchar.o nodes/print.o OBJS = main.o events.o processing.o graph.o nodes/getchar.o nodes/print.o nodes/evdev.o
all: $(MAIN) all: $(MAIN)

9
main.c
View File

@ -1,6 +1,7 @@
#include "processing.h" #include "processing.h"
#include "nodes/print.h" #include "nodes/print.h"
#include "nodes/getchar.h" #include "nodes/getchar.h"
#include "nodes/evdev.h"
int int
main(int argc, char ** argv) main(int argc, char ** argv)
@ -17,15 +18,19 @@ main(int argc, char ** argv)
GraphNode * input_node = graph_node_new(&nodespec_getchar); GraphNode * input_node = graph_node_new(&nodespec_getchar);
GraphNode * output_node = graph_node_new(&nodespec_print); GraphNode * output_node = graph_node_new(&nodespec_print);
GraphChannel chan; GraphNode * evdev_node = graph_node_new(&nodespec_evdev);
graph_channel_init(&chan, input_node, 0, output_node, 0); GraphChannel chan[2];
graph_channel_init(&chan[0], input_node, 0, output_node, 0);
graph_channel_init(&chan[1], evdev_node, 0, output_node, 1);
graph_node_register_io(input_node, &state); graph_node_register_io(input_node, &state);
graph_node_register_io(output_node, &state); graph_node_register_io(output_node, &state);
graph_node_register_io(evdev_node, &state);
while (true) { while (true) {
process_iteration(&state); process_iteration(&state);
} }
graph_node_delete(evdev_node);
graph_node_delete(output_node); graph_node_delete(output_node);
graph_node_delete(input_node); graph_node_delete(input_node);

129
nodes/evdev.c Normal file
View File

@ -0,0 +1,129 @@
#include <libevdev/libevdev.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include "evdev.h"
#include "../processing.h"
typedef struct {
GraphNode as_GraphNode;
IOHandling subscription;
struct libevdev *dev;
int fd;
} EvdevGraphNode;
static void
handle_io(EventPositionBase * self, int fd, bool is_output)
{
(void) is_output;
(void) fd;
EvdevGraphNode * node = DOWNCAST(EvdevGraphNode, GraphNode, DOWNCAST(GraphNode, EventPositionBase, self));
int err = 0;
AbsoluteTime realtime;
clock_gettime(CLOCK_REALTIME, &realtime.absolute);
AbsoluteTime monotime = get_current_time();
RelativeTime realtime_adj = absolute_time_sub_absolute(realtime, monotime);
while (!err) {
struct input_event buf;
err = libevdev_next_event(node->dev, LIBEVDEV_READ_FLAG_NORMAL, &buf);
if (err) {
if (err == -EAGAIN || err == 1) {
break;
}
node->subscription.enabled = false;
if (err < 0) {
errno = -err;
perror("Failed to read evdev event");
}
break;
}
realtime.absolute.tv_sec = buf.time.tv_sec;
realtime.absolute.tv_nsec = buf.time.tv_usec * (long) 1000;
monotime = absolute_time_sub_relative(realtime, realtime_adj);
EventData data = {
.code = {
.ns = 1,
.value = (((int32_t) buf.type) << 16) | buf.code,
},
.ttl = 100,
.priority = 10,
.payload = buf.value,
.modifiers = EMPTY_MODIFIER_SET,
.time = monotime,
};
for (size_t i = 0; i < node->as_GraphNode.outputs.length; ++i) {
EventNode *ev = event_create(&data);
if (!ev) {
perror("Failed to create event");
break;
}
ev->position = &node->as_GraphNode.outputs.elements[i]->as_EventPositionBase;
}
}
}
static GraphNode *
create(GraphNodeSpecification * spec)
{
EvdevGraphNode * node = calloc(1, sizeof(EvdevGraphNode));
if (!node) {
return NULL;
}
int fd = open("/dev/input/event7", O_RDONLY | O_NONBLOCK);
int err;
if ((err = libevdev_new_from_fd(fd, &node->dev)) < 0) {
errno = -err;
free(node);
return NULL;
}
*node = (EvdevGraphNode) {
.as_GraphNode = {
.as_EventPositionBase = {
.handle_event = NULL,
.waiting_new_event = false,
},
.specification = spec,
.inputs = EMPTY_GRAPH_CHANNEL_LIST,
.outputs = EMPTY_GRAPH_CHANNEL_LIST,
},
.subscription = {
.self = &node->as_GraphNode.as_EventPositionBase,
.handle_io = handle_io,
.enabled = true,
},
.dev = node->dev,
.fd = fd,
};
return &node->as_GraphNode;
}
static void destroy
(GraphNodeSpecification * self, GraphNode * target)
{
(void) self;
EvdevGraphNode * node = DOWNCAST(EvdevGraphNode, GraphNode, target);
if (node->dev) {
libevdev_free(node->dev);
node->dev = NULL;
close(node->fd);
}
free(target);
}
static void
register_io(GraphNodeSpecification * self, GraphNode * target, ProcessingState * state)
{
(void) self;
EvdevGraphNode * node = DOWNCAST(EvdevGraphNode, GraphNode, target);
io_subscription_list_add(&state->wait_input, node->fd, &node->subscription);
}
GraphNodeSpecification nodespec_evdev = (GraphNodeSpecification) {
.create = &create,
.destroy = &destroy,
.register_io = &register_io,
.name = "evdev",
};

8
nodes/evdev.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef NODES_EVDEV_H_
#define NODES_EVDEV_H_
#include "../graph.h"
extern GraphNodeSpecification nodespec_evdev;
#endif /* end of include guard: NODES_EVDEV_H_ */