summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathanael Sensfelder <SpamShield0@MultiAgentSystems.org>2019-12-27 17:06:53 +0100
committerNathanael Sensfelder <SpamShield0@MultiAgentSystems.org>2019-12-27 17:06:53 +0100
commit60283fb1407fcd1de0586c960ed8d106f59483e9 (patch)
tree306d3daa5c409b0449b4151fa8939f88ddc84884 /src/device/physical/physical_device.c
parent4a9df9b604cec6ee4b4a6f01ef940443583f7573 (diff)
Got a clue about the pesky "SYN" messages.
I must not have read libevdev's documentation well enough. Hopefully this new approach will work better. The risk would be that the conversion takes too long and properly handling all events leads to an increasing lag between the physical and the virtual device. I should probably add an option to let users indicate they would prefer dropping missed events.
Diffstat (limited to 'src/device/physical/physical_device.c')
-rw-r--r--src/device/physical/physical_device.c231
1 files changed, 231 insertions, 0 deletions
diff --git a/src/device/physical/physical_device.c b/src/device/physical/physical_device.c
new file mode 100644
index 0000000..7023791
--- /dev/null
+++ b/src/device/physical/physical_device.c
@@ -0,0 +1,231 @@
+/**** POSIX *******************************************************************/
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+
+/**** LIBEVDEV ****************************************************************/
+#include <libevdev/libevdev.h>
+
+/**** RELABSD *****************************************************************/
+#include <relabsd/debug.h>
+
+/******************************************************************************/
+/**** LOCAL FUNCTIONS *********************************************************/
+/******************************************************************************/
+/*
+ * Ensures that the input device has enabled the EV_REL axes mentioned
+ * in the configuration file.
+ *
+ * Returns -1 on (fatal) error,
+ * 0 all configured axes are accounted for.
+ */
+static int check_for_axes
+(
+ const struct libevdev * const dev,
+ const struct relabsd_config * const conf
+)
+{
+ int i, device_is_valid;
+ unsigned int rel_code;
+
+ device_is_valid = 1;
+
+ for (i = RELABSD_VALID_AXES_COUNT; i --> 0;)
+ {
+ if (conf->axis[i].enabled)
+ {
+ rel_code = relabsd_axis_to_rel((enum relabsd_axis) i);
+
+ if (!libevdev_has_event_code(dev, EV_REL, rel_code))
+ {
+ RELABSD_FATAL
+ (
+ "Input device has no relative %s axis, yet the configuration "
+ "file asks to convert it.",
+ relabsd_axis_to_name((enum relabsd_axis) i)
+ );
+
+ device_is_valid = 0;
+ }
+ }
+ }
+
+ return (device_is_valid - 1);
+}
+
+/*
+ * Ensures that the input device is compatible with the config file.
+ *
+ * Returns -1 on (fatal) error,
+ * 0 is the device is compatible.
+ */
+static int device_is_compatible
+(
+ const struct libevdev * const dev,
+ const struct relabsd_config * const conf
+)
+{
+
+
+ return 0;
+}
+
+/******************************************************************************/
+/**** EXPORTED FUNCTIONS ******************************************************/
+/******************************************************************************/
+int relabsd_physical_device_compatibility_test
+(
+ const struct relabsd_physical_device device [const restrict static 1],
+ const struct relabsd_parameters parameters [const restrict static 0],
+ const int verbose
+)
+{
+ if (!libevdev_has_event_type(device->libevdev, EV_REL))
+ {
+ RELABSD_S_FATAL("The physical device has no relative axes.");
+
+ return -1;
+ }
+
+ if
+ (
+ (parameters != (const struct relabsd_parameters *) NULL)
+ && (check_for_axes(device->libevdev, parameters, verbose) < 0)
+ )
+ {
+ RELABSD_S_FATAL
+ (
+ "Issue with the physical device's axes (or lack thereof), or their"
+ " compatibility with the requested configuration."
+ );
+
+ return -2;
+ }
+
+ return 0;
+}
+
+int relabsd_physical_device_open
+(
+ const char filename [const restrict static 1],
+ struct relabsd_physical_device device [const restrict static 1]
+)
+{
+ int err;
+
+ RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "Opening physical device...");
+
+ errno = 0;
+ device->file = open(filename, O_RDONLY);
+ device->is_late = 0;
+
+ if (device->file == -1)
+ {
+ RELABSD_FATAL
+ (
+ "Could not open physical device '%s' in read only mode: %s.",
+ filename,
+ strerror(errno)
+ );
+
+ return -1;
+ }
+
+ err = libevdev_new_from_fd(device->file, &(device->libevdev));
+
+ if (err != 0)
+ {
+ RELABSD_FATAL
+ (
+ "libevdev could not open physical device '%s': %s.",
+ filename,
+ strerror(-err)
+ );
+
+ close(device->file);
+
+ return -1;
+ }
+
+ return 0;
+}
+
+void relabsd_physical_device_close
+(
+ const struct relabsd_physical_device device [const restrict static 1]
+)
+{
+ RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "Closing input device...");
+
+ libevdev_free(device->libevdev);
+
+ errno = 0;
+
+ if (close(device->file) == -1)
+ {
+ RELABSD_ERROR
+ (
+ "Could not properly close the input device: %s.",
+ strerror(errno)
+ );
+ }
+}
+
+int relabsd_physical_device_read
+(
+ const struct relabsd_physical_device device [const restrict static 1],
+ unsigned int input_type [const restrict static 1],
+ unsigned int input_code [const restrict static 1],
+ int input_value [const restrict static 1]
+)
+{
+ int returned_code;
+ struct input_event event;
+
+ returned_code =
+ libevdev_next_event
+ (
+ device->libevdev,
+ device->is_late ? LIBEVDEV_READ_FLAG_SYNC : LIBEVDEV_READ_FLAG_NORMAL,
+ &event
+ );
+
+ switch (returned_code)
+ {
+ case LIBEVDEV_READ_STATUS_SUCCESS:
+ RELABSD_DEBUG
+ (
+ RELABSD_DEBUG_REAL_EVENTS,
+ "Valid event received: {type = %s; code = %s; value = %d}.",
+ libevdev_event_type_get_name(event.type),
+ libevdev_event_code_get_name(event.type, event.code),
+ event.value
+ );
+
+ *input_type = event.type;
+ *input_code = event.code;
+ *input_value = event.value;
+
+ return 1;
+
+ case LIBEVDEV_READ_STATUS_SYNC:
+ /* There are old events waiting to be read. */
+ device->is_late = 1;
+
+ return 0;
+
+ case -EAGAIN:
+ device->is_late = 0;
+
+ return -1;
+ }
+}
+
+int relabsd_physical_device_is_late
+(
+ const struct relabsd_physical_device device [const restrict static 1]
+)
+{
+ return device->is_late;
+}