summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathanael Sensfelder <SpamShield0@MultiAgentSystems.org>2015-09-02 10:57:48 +0200
committerNathanael Sensfelder <SpamShield0@MultiAgentSystems.org>2015-09-02 10:57:48 +0200
commit265053e2a4394b20d82aa1170ec3a9901f437d81 (patch)
tree022440b6bc0d1ad36e36429573ec17e589fb791c
parentd9656cc86505b6f2bba57e04a4c99430a945a70d (diff)
Adds some comments, as well as minor code improvements.
-rw-r--r--src/axis.c7
-rw-r--r--src/axis.h21
-rw-r--r--src/config.c224
-rw-r--r--src/config.h31
-rw-r--r--src/input.c24
-rw-r--r--src/input.h16
-rw-r--r--src/main.c79
-rw-r--r--src/pervasive.h1
-rw-r--r--src/relabsd_device.c18
-rw-r--r--src/relabsd_device.h22
10 files changed, 357 insertions, 86 deletions
diff --git a/src/axis.c b/src/axis.c
index 1ba09f0..d883f42 100644
--- a/src/axis.c
+++ b/src/axis.c
@@ -4,7 +4,12 @@
#include "axis.h"
-enum relabsd_axis relabsd_axis_name_to_enum (char * const name)
+/*
+ * Implementation note: _IS_PREFIX, as its name implies, is checking for a
+ * prefix, not an equal value. This could cause issues if there were axes
+ * with name prefixed by another axis name.
+ */
+enum relabsd_axis relabsd_axis_name_to_enum (const char * const name)
{
if (_IS_PREFIX("X", name))
{
diff --git a/src/axis.h b/src/axis.h
index 6d4f7f5..d2200de 100644
--- a/src/axis.h
+++ b/src/axis.h
@@ -12,8 +12,27 @@ enum relabsd_axis
RELABSD_UNKNOWN
};
-enum relabsd_axis relabsd_axis_name_to_enum (char * const name);
+/*
+ * Returns the relabsd_axis whose name is 'name', according to the configuration
+ * file syntax.
+ * RELABSD_UNKNOWN is returned for any name that didn't match any other
+ * possibility.
+ **/
+enum relabsd_axis relabsd_axis_name_to_enum (const char * const name);
+
+/*
+ * Gives an string representation of an relabsd_axis.
+ * "??" is returned for RELABSD_UNKNOWN.
+ * Returned values should be coherent with the configuration file syntax.
+ **/
char * relabsd_axis_enum_to_name (enum relabsd_axis const e);
+
+/*
+ * Gives the relabsd_axis and EV_ABS event code equivalent to an EV_REL event
+ * code.
+ * If the returned relabsd_axis is RELABSD_UNKNOWN, no value is inserted into
+ * 'abs_code'.
+ **/
enum relabsd_axis relabsd_axis_convert_evdev_rel
(
unsigned int const rel_code,
diff --git a/src/config.c b/src/config.c
index 1699811..2c860b9 100644
--- a/src/config.c
+++ b/src/config.c
@@ -6,9 +6,30 @@
#include "axis.h"
#include "config.h"
+/*
+ * "errno is never set to zero by any system call or library function."
+ * This file makes use of this, by setting it to zero and checking if
+ * it was modified after calling an function (I'm guessing this is common
+ * practice, but I think it's worth explaining).
+ * Following the principle of least astonishment, if a function sets errno to
+ * zero, it will not return before setting it back either to its previous
+ * value or to a arbitrary nonzero value.
+ */
+
+/*
+ * Returns -1 on error,
+ * 0 on EOF,
+ * 1 on newline.
+ */
static int reach_next_line_or_eof (FILE * const f)
{
+ int prev_errno;
char c;
+
+ prev_errno = errno;
+
+ errno = 0;
+
c = getc(f);
while ((c != '\n') && c != EOF)
@@ -16,15 +37,28 @@ static int reach_next_line_or_eof (FILE * const f)
c = getc(f);
}
- if (c == EOF)
+ if (errno != 0)
{
+ errno = prev_errno;
+
return -1;
}
- return 0;
+ errno = prev_errno;
+
+ if (c == EOF)
+ {
+ return 0;
+ }
+
+ return 1;
}
-static int all_axis_are_configured (const int * const axis_is_configured)
+/*
+ * Returns -1 on if an axis has not been configured,
+ * 0 otherwise.
+ */
+static int all_axes_are_configured (const int * const axis_is_configured)
{
int i;
@@ -45,15 +79,21 @@ static int all_axis_are_configured (const int * const axis_is_configured)
return 0;
}
+/*
+ * Returns -1 on (fatal) error,
+ * 0 on succes.
+ * On failure, 'axis_is_configured' is untouched.
+ * On success, the corresponding 'axis_is_configured' is set to 1.
+ */
static int parse_axis_configuration_line
(
struct relabsd_config * const conf,
FILE * const f,
int * const axis_is_configured,
- char * const buffer
+ const char * const buffer
)
{
- int valc;
+ int valc, prev_errno;
enum relabsd_axis axis;
axis = relabsd_axis_name_to_enum(buffer);
@@ -69,25 +109,42 @@ static int parse_axis_configuration_line
return -1;
}
- valc =
- fscanf
- (
- f,
- "%d %d %d %d %d",
- &(conf->axis[axis].min),
- &(conf->axis[axis].max),
- &(conf->axis[axis].fuzz),
- &(conf->axis[axis].flat),
- &(conf->axis[axis].resolution)
- );
+ prev_errno = errno;
+ errno = 0;
+
+ valc =
+ fscanf
+ (
+ f,
+ "%d %d %d %d %d",
+ &(conf->axis[axis].min),
+ &(conf->axis[axis].max),
+ &(conf->axis[axis].fuzz),
+ &(conf->axis[axis].flat),
+ &(conf->axis[axis].resolution)
+ );
if (valc == EOF)
{
- _FATAL
- (
- "[CONFIG] Unexpected end of file while reading axis '%s'.",
- buffer
- );
+ if (errno == 0)
+ {
+ _FATAL
+ (
+ "[CONFIG] Unexpected end of file while reading axis '%s'.",
+ buffer
+ );
+ }
+ else
+ {
+ _FATAL
+ (
+ "[CONFIG] An error occured while reading axis '%s': %s.",
+ buffer,
+ strerror(errno)
+ );
+ }
+
+ errno = prev_errno;
return -1;
}
@@ -99,13 +156,57 @@ static int parse_axis_configuration_line
buffer
);
+ errno = prev_errno;
+
return -1;
}
+ errno = prev_errno;
+
axis_is_configured[axis] = 1;
+
return 0;
}
+/*
+ * Returns -1 on (fatal) error,
+ * 0 on EOF,
+ * 1 on newline.
+ */
+static int read_config_line
+(
+ struct relabsd_config * const conf,
+ FILE * const f,
+ int * const axis_is_configured,
+ const char * const prefix
+)
+{
+ if (!_IS_PREFIX("#", prefix))
+ {
+ if
+ (
+ parse_axis_configuration_line
+ (
+ conf,
+ f,
+ axis_is_configured,
+ prefix
+ )
+ < 0
+ )
+ {
+ /* Fatal error. */
+ return -1;
+ }
+ }
+
+ return reach_next_line_or_eof(f);
+}
+
+/*
+ * Returns -1 on (fatal) error,
+ * 0 on success.
+ */
static int read_config_file
(
struct relabsd_config * const conf,
@@ -115,11 +216,11 @@ static int read_config_file
FILE * f;
int axis_is_configured[6];
char buffer[3];
- int test;
+ int continue_reading, prev_errno;
buffer[2] = '\0';
- memset(axis_is_configured, 0, 6 * sizeof(int));
+ memset(axis_is_configured, 0, (6 * sizeof(int)));
f = fopen(filename, "r");
@@ -134,43 +235,37 @@ static int read_config_file
return -1;
}
+ prev_errno = errno;
errno = 0;
- while ((test = fscanf(f, "%2s", buffer)) > 0)
+ continue_reading = 1;
+
+ while ((continue_reading == 1) && (fscanf(f, "%2s", buffer) != EOF))
{
- if (_IS_PREFIX("#", buffer))
- {
- if (reach_next_line_or_eof(f) < 0)
- {
- break;
- }
- }
- else
+ switch (read_config_line(conf, f, axis_is_configured, buffer))
{
- if
- (
- parse_axis_configuration_line
- (
- conf,
- f,
- axis_is_configured,
- buffer
- )
- < 0
- )
- {
+ case 1:
+ /* Everything is going well. */
break;
- }
- if (reach_next_line_or_eof(f) < 0)
- {
+ case 0:
+ /* EOF reached. */
+ continue_reading = 0;
break;
- }
+
+ case -1:
+ /* A fatal error occured. */
+ errno = prev_errno;
+
+ fclose(f);
+ return -1;
}
}
- if (test < 0 && errno != 0)
+ if (errno != 0)
{
+ /* An error happened in the while loop condition. */
+
_FATAL
(
"[CONFIG] Error while reading file: %s, last read '%s'.",
@@ -178,14 +273,18 @@ static int read_config_file
buffer
);
+ errno = prev_errno;
+
fclose(f);
return -1;
}
+ errno = prev_errno;
+
fclose(f);
- if (all_axis_are_configured(axis_is_configured) < 0)
+ if (all_axes_are_configured(axis_is_configured) < 0)
{
return -1;
}
@@ -193,11 +292,14 @@ static int read_config_file
return 0;
}
-int relabsd_config_parse
+/*
+ * Returns -1 on (fatal) error,
+ * 0 on valid usage.
+ */
+static int check_usage
(
- struct relabsd_config * const conf,
int const argc,
- char ** const argv
+ char * const * const argv
)
{
if ((argc < 3) || (argc > 4))
@@ -211,6 +313,21 @@ int relabsd_config_parse
return -1;
}
+ return 0;
+}
+
+int relabsd_config_parse
+(
+ struct relabsd_config * const conf,
+ int const argc,
+ char * const * const argv
+)
+{
+ if (check_usage(argc, argv) < 0)
+ {
+ return -1;
+ }
+
if (argc == 3)
{
conf->device_name = "relabsd device";
@@ -237,6 +354,7 @@ int relabsd_config_allows
int const value
)
{
+ /* TODO */
return 1;
};
diff --git a/src/config.h b/src/config.h
index ffdfebb..558ea98 100644
--- a/src/config.h
+++ b/src/config.h
@@ -15,23 +15,41 @@ struct relabsd_config_axis
};
/*
- * There are no relabsd_config_free function so be careful about using dynamic
+ * There is no relabsd_config_free function, so be careful about using dynamic
* memory for input_file or device_name.
*/
struct relabsd_config
{
- char * input_file;
- char * device_name;
+ const char * input_file;
+ const char * device_name;
struct relabsd_config_axis axis[6];
};
+/*
+ * Parses the invocation parameters and the config file into 'conf'.
+ *
+ * Returns -1 on (fatal) error,
+ * 0 on successfully parsed config.
+ *
+ * 'conf' does not need to be initialized, as the function will only write to
+ * it.
+ * As one would expect, argc is the number of elements in argv.
+ */
int relabsd_config_parse
(
struct relabsd_config * const conf,
int const argc,
- char ** const argv
+ char * const * const argv
);
+/*
+ * This function aims at preventing us from emitting values that are incoherent
+ * with our REV_ABS axis configuration, such as the axis' minimum or maximum
+ * values.
+ *
+ * Returns 1 if 'conf' allows the axis to have this value,
+ * 0 otherwise.
+ */
int relabsd_config_allows
(
const struct relabsd_config * const conf,
@@ -39,6 +57,11 @@ int relabsd_config_allows
int const value
);
+/*
+ * Copies all the ABS event parameters of 'axis' into 'absinfo'.
+ * 'absinfo' does not need to be initialized, as the function will only write to
+ * it.
+ */
void relabsd_config_get_absinfo
(
const struct relabsd_config * const conf,
diff --git a/src/input.c b/src/input.c
index eb7b013..aafb9a3 100644
--- a/src/input.c
+++ b/src/input.c
@@ -8,6 +8,12 @@
#include "input.h"
+/*
+ * Ensures that the input device has enabled an given EV_REL axis.
+ *
+ * Returns -1 on (fatal) error,
+ * 0 is the axis is enabled.
+ */
static int check_for_axis
(
const struct libevdev * const dev,
@@ -25,6 +31,12 @@ static int check_for_axis
return 0;
}
+/*
+ * Ensures that the input defice is at least 6DOF.
+ *
+ * Returns -1 on (fatal) error,
+ * 0 is the device is compatible.
+ */
static int device_is_compatible (const struct libevdev * const dev)
{
if (!libevdev_has_event_type(dev, EV_REL))
@@ -44,6 +56,10 @@ static int device_is_compatible (const struct libevdev * const dev)
| (check_for_axis(dev, "RZ", REL_RZ) < 0)
)
{
+ /*
+ * Note the '|' instead of '||': we want to inform the user of all the
+ * axes we require.
+ */
return -1;
}
@@ -122,11 +138,15 @@ int relabsd_input_read
&event
);
- /*if (rc == LIBEVDEV_READ_STATUS_SYNC)
+ /* TODO: Look into LIBEVDEV_READ_STATUS_SYNC, handle it. */
+ /*
+ if (rc == LIBEVDEV_READ_STATUS_SYNC)
{
handle_syn_dropped(input->dev);
}
- else*/ if (rc != LIBEVDEV_READ_STATUS_SUCCESS)
+ else
+ */
+ if (rc != LIBEVDEV_READ_STATUS_SUCCESS)
{
_WARNING("[INPUT] Could not get next event: %s.", strerror(-rc));
diff --git a/src/input.h b/src/input.h
index 03b5c5a..4a23c27 100644
--- a/src/input.h
+++ b/src/input.h
@@ -9,6 +9,14 @@ struct relabsd_input
int fd;
};
+/*
+ * Returns -1 on (fatal) error,
+ * 0 on success.
+ *
+ * 'input' does not need to be initialized, as the function will to that for
+ * you (on success).
+ * On success, 'input' will need to be closed.
+ */
int relabsd_input_open
(
struct relabsd_input * const input,
@@ -17,6 +25,14 @@ int relabsd_input_open
void relabsd_input_close (const struct relabsd_input * const input);
+/*
+ * Returns -1 on (warning) error,
+ * 0 on successful read.
+ *
+ * The 'input_*' parameters do not need to be initialized, as the function will
+ * do that for you (on success).
+ * Requires 'input' to be open.
+ */
int relabsd_input_read
(
const struct relabsd_input * const input,
diff --git a/src/main.c b/src/main.c
index b60a074..2dc42db 100644
--- a/src/main.c
+++ b/src/main.c
@@ -19,6 +19,44 @@ static void interrupt (int signal_id)
_S_WARNING("Interrupted, will exit at the next input device event.");
}
+static void handle_relative_axis_event
+(
+ const struct relabsd_config * const conf,
+ const struct relabsd_device * const dev,
+ unsigned int const input_type,
+ unsigned int const input_code,
+ int const value
+)
+{
+ unsigned int abs_code;
+ enum relabsd_axis rad_code;
+
+ rad_code = relabsd_axis_convert_evdev_rel(input_code, &abs_code);
+
+ if (rad_code == RELABSD_UNKNOWN)
+ {
+ /*
+ * EV_REL events that do not concern an axis that was explicitly
+ * configured are retransmitted as is.
+ */
+ relabsd_device_write_evdev_event
+ (
+ dev,
+ input_type,
+ input_code,
+ value
+ );
+ }
+ else if (relabsd_config_allows(conf, rad_code, value))
+ {
+ /*
+ * This filters out events which are inconsistent with 'conf', such as
+ * values higher than the axis' configured maximum.
+ */
+ relabsd_device_write_evdev_event(dev, EV_ABS, abs_code, value);
+ }
+}
+
static void convert_input
(
const struct relabsd_config * const conf,
@@ -27,37 +65,28 @@ static void convert_input
)
{
unsigned int input_type, input_code, abs_code;
- enum relabsd_axis rad_code;
int value;
while (RELABSD_RUN == 1)
{
if (relabsd_input_read(input, &input_type, &input_code, &value) < 0)
{
+ /*
+ * The next event should not be retransmitted, or some kind of error
+ * happened.
+ */
+ /* TODO: error handling. */
continue;
}
if (input_type == EV_REL)
{
- rad_code = relabsd_axis_convert_evdev_rel(input_code, &abs_code);
-
- if (rad_code == RELABSD_UNKNOWN)
- {
- relabsd_device_write_evdev_event
- (
- dev,
- input_type,
- input_code,
- value
- );
- }
- else if (relabsd_config_allows(conf, rad_code, value))
- {
- relabsd_device_write_evdev_event(dev, EV_ABS, abs_code, value);
- }
+ /* We might have to convert the event. */
+ handle_relative_axis_event(conf, dev, input_type, input_code, value);
}
else
{
+ /* Any other event is retransmitted as is. */
relabsd_device_write_evdev_event
(
dev,
@@ -69,16 +98,26 @@ static void convert_input
}
}
+static int set_signal_handlers ()
+{
+ if (signal(SIGINT, interrupt) == SIG_ERR)
+ {
+ _S_FATAL("Unable to set the SIGINT signal handler.");
+
+ return -1;
+ }
+
+ return 0;
+}
+
int main (int argc, char ** argv)
{
struct relabsd_config conf;
struct relabsd_input input;
struct relabsd_device dev;
- if (signal(SIGINT, interrupt) == SIG_ERR)
+ if (set_signal_handlers() < 0)
{
- _S_FATAL("Unable to set the SIGINT signal handler.");
-
return -1;
}
diff --git a/src/pervasive.h b/src/pervasive.h
index 8a8449a..ee04b08 100644
--- a/src/pervasive.h
+++ b/src/pervasive.h
@@ -8,6 +8,7 @@
#define _ISOLATE(a) do {a} while (0)
+/* strncmp stops at '\0' and strlen does not count '\0'. */
#define _IS_PREFIX(a, b) (strncmp(a, b, strlen(a)) == 0)
#endif
diff --git a/src/relabsd_device.c b/src/relabsd_device.c
index 7d2b761..ced74d8 100644
--- a/src/relabsd_device.c
+++ b/src/relabsd_device.c
@@ -9,11 +9,17 @@
#include "relabsd_device.h"
-/* LIBEVDEV_UINPUT_OPEN_MANAGED is not defined on my machine. */
+/*
+ LIBEVDEV_UINPUT_OPEN_MANAGED is not defined on my machines.
+ It is not my place to define it, so I'll avoid the issue by defining my own
+ constant.
+*/
#ifndef LIBEVDEV_UINPUT_OPEN_MANAGED
- #warning "libevdev did not define LIBEVDEV_UINPUT_OPEN_MANAGED, "\
- "using value '-2' instead."
- #define LIBEVDEV_UINPUT_OPEN_MANAGED -2
+ #pragma message "[WARNING] libevdev did not define "\
+ "LIBEVDEV_UINPUT_OPEN_MANAGED, using value '-2' instead."
+ #define RELABSD_UINPUT_OPEN_MANAGED -2
+#else
+ #define RELABSD_UINPUT_OPEN_MANAGED LIBEVDEV_UINPUT_OPEN_MANAGED
#endif
static void replace_rel_axis
@@ -90,7 +96,8 @@ int relabsd_device_create
libevdev_uinput_create_from_device
(
dev->dev,
- LIBEVDEV_UINPUT_OPEN_MANAGED,
+ /* See top of the file. */
+ RELABSD_UINPUT_OPEN_MANAGED,
&(dev->uidev)
)
< 0
@@ -124,6 +131,7 @@ int relabsd_device_write_evdev_event
int const value
)
{
+ /* OPTIMIZE: Should we really send 'EV_SYN' after every event? */
if
(
(libevdev_uinput_write_event(dev->uidev, type, code, value) == 0)
diff --git a/src/relabsd_device.h b/src/relabsd_device.h
index 35a4830..b3f2d51 100644
--- a/src/relabsd_device.h
+++ b/src/relabsd_device.h
@@ -12,6 +12,21 @@ struct relabsd_device
struct libevdev_uinput * uidev;
};
+/*
+ * - Clones the (real) input device.
+ * - Adds ABS event support to the clone.
+ * - Adds the ABS axis described in 'config' to the clone (overwriting if
+ * needed).
+ * - Disables the associated REL events from the clone.
+ *
+ * Returns -1 on (fatal) error,
+ * 0 on success.
+ *
+ * 'dev' does not need to be initialized, as the function will to that for you
+ * (on success).
+ * On success, 'dev' will need to be closed.
+ * This opens the (real) input device in read only mode to copy its properties.
+ */
int relabsd_device_create
(
struct relabsd_device * const dev,
@@ -20,6 +35,13 @@ int relabsd_device_create
void relabsd_device_destroy (const struct relabsd_device * const dev);
+/*
+ * Write an event to 'dev'. At this time, every event written to 'dev' is
+ * followed by an EV_SYN event.
+ *
+ * Returns 0 if both the event and the EV_SYN were successful,
+ * -1 if either failed.
+ */
int relabsd_device_write_evdev_event
(
const struct relabsd_device * const dev,