summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathanael Sensfelder <SpamShield0@MultiAgentSystems.org>2019-12-27 20:14:49 +0100
committerNathanael Sensfelder <SpamShield0@MultiAgentSystems.org>2019-12-27 20:14:49 +0100
commitb9952b4938da95de07bff748cfd6d2c7e8471796 (patch)
tree3c34b7d8327f41515ec939e3e188767d5d641cca
parent60283fb1407fcd1de0586c960ed8d106f59483e9 (diff)
Remembering what was happening in this program...
*Maybe* I should document it more. Who knows... I do seem to get one feature request every two years, and pretty much forget all about it inbetween.
-rw-r--r--src/device/physical/physical_device.c40
-rw-r--r--src/device/virtual/virtual_device.c253
2 files changed, 199 insertions, 94 deletions
diff --git a/src/device/physical/physical_device.c b/src/device/physical/physical_device.c
index 7023791..4582c2d 100644
--- a/src/device/physical/physical_device.c
+++ b/src/device/physical/physical_device.c
@@ -187,12 +187,28 @@ int relabsd_physical_device_read
libevdev_next_event
(
device->libevdev,
- device->is_late ? LIBEVDEV_READ_FLAG_SYNC : LIBEVDEV_READ_FLAG_NORMAL,
+ (
+ (
+ /*
+ * If we were already late, reading in NORMAL mode discards all
+ * the outdated input events, whereas reading in SYNC mode goes
+ * through them in order.
+ * TODO: add an option to allow users to drop events when late.
+ */
+ device->is_late ?
+ LIBEVDEV_READ_FLAG_SYNC
+ : LIBEVDEV_READ_FLAG_NORMAL
+ )
+ /* "The fd is not in O_NONBLOCK and a read may block." */
+ | LIBEVDEV_READ_FLAG_BLOCKING
+ )
+ ,
&event
);
switch (returned_code)
{
+ /* Read an actual input. */
case LIBEVDEV_READ_STATUS_SUCCESS:
RELABSD_DEBUG
(
@@ -207,14 +223,28 @@ int relabsd_physical_device_read
*input_code = event.code;
*input_value = event.value;
- return 1;
+ return 0;
+ /* Code indicating that we are late. */
case LIBEVDEV_READ_STATUS_SYNC:
- /* There are old events waiting to be read. */
+ /* There are old input events waiting to be read. */
device->is_late = 1;
+ /*
+ * From the documentation, the event we just read was an EV_SYN one,
+ * so we don't actually have any input event in hand.
+ */
+
+ /* FIXME: Really make sure this cannot recurse a second time. */
+ return
+ relabsd_physical_device_read
+ (
+ device,
+ input_type,
+ input_code,
+ input_value
+ );
- return 0;
-
+ /* No event to read. */
case -EAGAIN:
device->is_late = 0;
diff --git a/src/device/virtual/virtual_device.c b/src/device/virtual/virtual_device.c
index 19d1097..0c5eab4 100644
--- a/src/device/virtual/virtual_device.c
+++ b/src/device/virtual/virtual_device.c
@@ -1,25 +1,57 @@
+/**** POSIX *******************************************************************/
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+/**** LIBEVDEV ****************************************************************/
+#include <libevdev/libevdev.h>
+#include <libevdev/libevdev-uinput.h>
+
+/**** RELABSD *****************************************************************/
+#include <relabsd/config/parameters.h>
+
+#include <relabsd/debug.h>
+
+#include <relabsd/device/axis.h>
+#include <relabsd/device/virtual_device.h>
+
+/******************************************************************************/
+/**** LOCAL FUNCTIONS *********************************************************/
+/******************************************************************************/
static void replace_rel_axes
(
- struct relabsd_virtual_device * const dev,
- const struct relabsd_config * const config
+ const struct relabsd_parameters parameters [const restrict static 1],
+ const struct relabsd_virtual_device device [const restrict static 1]
)
{
int i;
- struct input_absinfo absinfo;
- unsigned int abs_code, rel_code;
-
- for (i = RELABSD_VALID_AXES_COUNT; i --> 0;)
+ for (i = 0; i < RELABSD_VALID_AXES_COUNT; i++)
{
if (config->axis[i].enabled)
{
- rel_code = relabsd_axis_to_rel((enum relabsd_axis) i);
- abs_code = relabsd_axis_to_abs((enum relabsd_axis) i);
+ struct input_absinfo absinfo;
+
relabsd_config_get_absinfo(config, (enum relabsd_axis) i, &absinfo);
- libevdev_disable_event_code(dev->dev, EV_REL, rel_code);
- libevdev_enable_event_code(dev->dev, EV_ABS, abs_code, &absinfo);
+
+ /* TODO: report failure? 0 on success, -1 otherwise, no cause given. */
+ (void) libevdev_disable_event_code
+ (
+ device->libevdev,
+ EV_REL,
+ relabsd_axis_to_rel((enum relabsd_axis) i);
+ );
+
+ (void) libevdev_enable_event_code
+ (
+ device->libevdev,
+ EV_ABS,
+ relabsd_axis_to_abs((enum relabsd_axis) i);
+ &absinfo
+ );
}
}
@@ -27,8 +59,8 @@ static void replace_rel_axes
static int rename_device
(
- struct libevdev * const dev,
- const struct relabsd_config * const config
+ const struct relabsd_parameters parameters [const restrict static 1],
+ const struct relabsd_virtual_device device [const restrict static 1]
)
{
size_t new_name_size;
@@ -38,22 +70,20 @@ static int rename_device
/* +2: One for the \0, one for the space between prefix and 'real_name'. */
new_name_size = strlen(RELABSD_DEVICE_PREFIX) + 2;
- if (config->device_name == (char *) NULL)
+ real_name = relabsd_parameters_get_device_name(parameters);
+
+ if (real_name == (const char *) NULL)
{
- /* XXX
+ /*
* "The name is never NULL but it may be the empty string."
* I'm assuming that since they use the term 'string', it is \0
* terminated.
*/
real_name = libevdev_get_name(dev);
}
- else
- {
- real_name = config->device_name;
- }
new_name_size += strlen(real_name);
-
+ errno = 0;
new_name = (char *) calloc(new_name_size, sizeof(char));
if (new_name == (char *) NULL)
@@ -71,6 +101,8 @@ static int rename_device
return -1;
}
+ errno = 0;
+
if
(
snprintf
@@ -101,156 +133,197 @@ static int rename_device
/* This frees whatever came from 'libevdev_get_name'. */
libevdev_set_name(dev, new_name);
+
+ /* FIXME: not entirely sure I should be the one to free it. */
free((void *) new_name);
return 0;
}
-int relabsd_virtual_device_create
+/******************************************************************************/
+/**** EXPORTED FUNCTIONS ******************************************************/
+/******************************************************************************/
+int relabsd_virtual_device_create_from
(
- struct relabsd_virtual_device * const dev,
- const struct relabsd_config * const config
+ const struct relabsd_parameters parameters [const restrict static 1],
+ struct relabsd_virtual_device device [const restrict static 1]
)
{
- int fd;
+ struct libevdev * physical_device_libevdev;
+ int physical_device_file;
RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "Creating virtual device...");
- fd = open(config->input_file, O_RDONLY);
+ errno = 0;
+ physical_device_file =
+ open
+ (
+ relabsd_parameters_get_physical_device_file_name(parameters),
+ O_RDONLY
+ );
- if (fd < 0)
+ if (physical_device_file == -1)
{
RELABSD_FATAL
(
- "Could not open device '%s' in read only mode: %s.",
- config->input_file,
+ "Could not open physical device '%s' in read only mode: %s.",
+ relabsd_parameters_get_physical_device_file_name(parameters),
strerror(errno)
);
return -1;
}
- if (libevdev_new_from_fd(fd, &(dev->dev)) < 0)
+ err = libevdev_new_from_fd(physical_device_file, &physical_device_libevdev);
+
+ if (err != 0)
{
RELABSD_FATAL
(
- "libevdev could not open '%s': '%s'.",
- config->input_file,
- strerror(errno)
+ "libevdev could not open physical device '%s': %s.",
+ relabsd_parameters_get_physical_device_file_name(parameters),
+ strerror(-err)
);
- close(fd);
+ (void) close(device->file);
return -1;
}
- if (rename_device(dev->dev, config) < 0)
- {
- libevdev_free(dev->dev);
- close(fd);
+ /* Not exactly fatal, is it? */
+ (void) rename_device(parameters, physical_device_libevdev);
- return -1;
- }
+ libevdev_enable_event_type(physical_device_libevdev, EV_ABS);
- libevdev_enable_event_type(dev->dev, EV_ABS);
+ replace_rel_axes(parameters, physical_device_libevdev);
- replace_rel_axes(dev, config);
- if
- (
- libevdev_uinput_create_from_device
- (
- dev->dev,
+ err =
+ libevdev_uinput_create_from_device
+ (
+ physical_device_libevdev,
/* See top of the file. */
RELABSD_UINPUT_OPEN_MANAGED,
- &(dev->uidev)
- )
- < 0
- )
+ &(device->uinput_device)
+ );
+
+ if (err != 0)
{
- RELABSD_FATAL("Could not create relabsd device: %s.", strerror(errno));
+ RELABSD_FATAL("Could not create uinput device: %s.", strerror(-err));
- libevdev_free(dev->dev);
+ libevdev_free(physical_device_libevdev);
- close(fd);
+ (void) close(physical_device_file);
return -1;
}
- close(fd);
+ /* For future modifications. */
+ device->libevdev = physical_device_libevdev;
+
+ /*
+ * We only need the physical device's (now modified) profile, not to actually
+ * read from it.
+ */
+ errno = 0;
+
+ if (close(physical_device_file) == -1)
+ {
+ RELABSD_ERROR("Could not close physical device: %s". strerror(errno));
+ }
+
+ RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "Created virtual device.");
return 0;
}
-void relabsd_virtual_device_destroy (const struct relabsd_virtual_device * const dev)
+void relabsd_virtual_device_destroy
+(
+ const struct relabsd_virtual_device device [const restrict static 1]
+)
{
RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "Destroying virtual device...");
- libevdev_uinput_destroy(dev->uidev);
- libevdev_free(dev->dev);
+ libevdev_uinput_destroy(device->uinput_device);
+ libevdev_free(device->libevdev);
+
+ RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "Destroyed virtual device.");
}
int relabsd_virtual_device_write_evdev_event
(
- const struct relabsd_virtual_device * const dev,
+ const struct relabsd_virtual_device device [const restrict static 1],
unsigned int const type,
unsigned int const code,
int const value
)
{
+ int err;
+
RELABSD_DEBUG
(
RELABSD_DEBUG_VIRTUAL_EVENTS,
"Sending event: {type = %s; code = %s; value = %d}.",
- libevdev_event_type_get_name(type),
- libevdev_event_code_get_name(type, code),
- value
+ libevdev_event_type_get_name(type),
+ libevdev_event_code_get_name(type, code),
+ value
);
/*
- * We'll also send the 'EV_SYN' events when we receive them from the input
+ * "It is the caller's responsibility that any event sequence is terminated
+ * with an EV_SYN/SYN_REPORT/0 event. Otherwise, listeners on the device node
+ * will not see the events until the next EV_SYN event is posted."
+ * We'll simply send the 'EV_SYN' events when we read them from the physical
* device.
- * OPTIMIZE: prevent 'EV_SYN' from being sent if we haven't sent any new
- * values. (It might not be worth it though)
*/
- if (libevdev_uinput_write_event(dev->uidev, type, code, value) == 0)
+ err = libevdev_uinput_write_event(device->uinput_device, type, code, value);
+
+ if (err != 0)
{
- /* FIXME:
- * Why does activating the timeout trigger the EV_KEYS event to not be
- * followed by EV_SYN?
- */
- if (type == EV_KEY)
- {
- libevdev_uinput_write_event
- (
- dev->uidev,
- EV_SYN,
- SYN_REPORT,
- 0
- );
- }
+ RELABSD_ERROR
+ (
+ "Unable to generate event {type = %s; code = %s; value = %d}: %s.",
+ libevdev_event_type_get_name(type),
+ libevdev_event_code_get_name(type, code),
+ value,
+ strerror(-err)
+ );
- return 0;
+ return -1;
}
- return -1;
+ /*
+ * TODO: check if this is needed.
+ if (type == EV_KEY)
+ {
+ libevdev_uinput_write_event
+ (
+ dev->uidev,
+ EV_SYN,
+ SYN_REPORT,
+ 0
+ );
+ }
+ */
+
+ return 0;
}
void relabsd_virtual_device_set_axes_to_zero
(
- const struct relabsd_virtual_device * const dev,
- const struct relabsd_config * const config
+ const struct relabsd_parameters parameters [const restrict static 1],
+ const struct relabsd_virtual_device device [const restrict static 1]
)
{
int i;
for (i = 0; i < RELABSD_VALID_AXES_COUNT; ++i)
{
- if (config->axis[i].enabled)
+ if (parameters->axis[i].enabled)
{
relabsd_virtual_device_write_evdev_event
(
- dev,
+ device,
EV_ABS,
relabsd_axis_to_abs((enum relabsd_axis) i),
0
@@ -261,12 +334,14 @@ void relabsd_virtual_device_set_axes_to_zero
/*
* Also send a SYN event when the axes have been modified.
*/
- libevdev_uinput_write_event
+ i =
+ libevdev_uinput_write_event(device->uinput_device, EV_SYN, SYN_REPORT, 0);
+
+ RELABSD_ERROR
(
- dev->uidev,
- EV_SYN,
- SYN_REPORT,
- 0
+ "Unable to generate event {type = EV_SYN; code = SYN_REPORT; value = 0}:"
+ " %s.",
+ strerror(-i)
);
}