Added libevdev node
This commit is contained in:
parent
d3a3217e88
commit
65769a7442
4
Makefile
4
Makefile
|
@ -1,4 +1,4 @@
|
|||
DEPS =
|
||||
DEPS = libevdev
|
||||
CFLAGS = -Wall -Wextra
|
||||
ifdef DEBUG
|
||||
CFLAGS += -Og -gdwarf-2
|
||||
|
@ -10,7 +10,7 @@ CPPFLAGS += $(shell pkg-config --cflags $(DEPS))
|
|||
LDLIBS += $(shell pkg-config --libs $(DEPS))
|
||||
INTERP ?=
|
||||
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)
|
||||
|
||||
|
|
9
main.c
9
main.c
|
@ -1,6 +1,7 @@
|
|||
#include "processing.h"
|
||||
#include "nodes/print.h"
|
||||
#include "nodes/getchar.h"
|
||||
#include "nodes/evdev.h"
|
||||
|
||||
int
|
||||
main(int argc, char ** argv)
|
||||
|
@ -17,15 +18,19 @@ main(int argc, char ** argv)
|
|||
|
||||
GraphNode * input_node = graph_node_new(&nodespec_getchar);
|
||||
GraphNode * output_node = graph_node_new(&nodespec_print);
|
||||
GraphChannel chan;
|
||||
graph_channel_init(&chan, input_node, 0, output_node, 0);
|
||||
GraphNode * evdev_node = graph_node_new(&nodespec_evdev);
|
||||
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(output_node, &state);
|
||||
graph_node_register_io(evdev_node, &state);
|
||||
|
||||
while (true) {
|
||||
process_iteration(&state);
|
||||
}
|
||||
|
||||
graph_node_delete(evdev_node);
|
||||
graph_node_delete(output_node);
|
||||
graph_node_delete(input_node);
|
||||
|
||||
|
|
|
@ -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 = ®ister_io,
|
||||
.name = "evdev",
|
||||
};
|
|
@ -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_ */
|
Loading…
Reference in New Issue