From 390576c3839ee7abb845e27b7267de45495e6b2f Mon Sep 17 00:00:00 2001 From: Nathanael Sensfelder Date: Mon, 23 Dec 2019 15:44:19 +0100 Subject: Starting to turn relabsd into a proper daemon... --- CMakeLists.txt | 4 +- include/relabsd/client.h | 0 include/relabsd/config.h | 0 include/relabsd/config/config_file.h | 100 ++++ include/relabsd/config/parameters.h | 0 include/relabsd/debug.h | 145 ++++++ include/relabsd/device/axis.h | 78 +++ include/relabsd/device/physical_device.h | 50 ++ include/relabsd/device/virtual_device.h | 71 +++ include/relabsd/server.h | 0 include/relabsd/util/macro.h | 6 + include/relabsd/util/string.h | 18 + src/CMakeLists.txt | 10 - src/axis.c | 285 ----------- src/axis.h | 61 --- src/client.c | 189 +++++++ src/config.c | 821 ------------------------------- src/config.h | 100 ---- src/config/config_file.c | 821 +++++++++++++++++++++++++++++++ src/config/parameters.c | 287 +++++++++++ src/device/axis/axis_name.c | 302 ++++++++++++ src/device/physical_device.c | 276 +++++++++++ src/device/virtual_device.c | 272 ++++++++++ src/error.h | 141 ------ src/input.c | 276 ----------- src/input.h | 53 -- src/main.c | 171 +------ src/pervasive.h | 16 - src/relabsd_device.c | 298 ----------- src/relabsd_device.h | 64 --- src/server/daemon.c | 126 +++++ src/server/main_loop.c | 165 +++++++ src/server/server.c | 113 +++++ src/util/string.c | 36 ++ 34 files changed, 3084 insertions(+), 2271 deletions(-) create mode 100644 include/relabsd/client.h create mode 100644 include/relabsd/config.h create mode 100644 include/relabsd/config/config_file.h create mode 100644 include/relabsd/config/parameters.h create mode 100644 include/relabsd/debug.h create mode 100644 include/relabsd/device/axis.h create mode 100644 include/relabsd/device/physical_device.h create mode 100644 include/relabsd/device/virtual_device.h create mode 100644 include/relabsd/server.h create mode 100644 include/relabsd/util/macro.h create mode 100644 include/relabsd/util/string.h delete mode 100644 src/CMakeLists.txt delete mode 100644 src/axis.c delete mode 100644 src/axis.h create mode 100644 src/client.c delete mode 100644 src/config.c delete mode 100644 src/config.h create mode 100644 src/config/config_file.c create mode 100644 src/config/parameters.c create mode 100644 src/device/axis/axis_name.c create mode 100644 src/device/physical_device.c create mode 100644 src/device/virtual_device.c delete mode 100644 src/error.h delete mode 100644 src/input.c delete mode 100644 src/input.h delete mode 100644 src/pervasive.h delete mode 100644 src/relabsd_device.c delete mode 100644 src/relabsd_device.h create mode 100644 src/server/daemon.c create mode 100644 src/server/main_loop.c create mode 100644 src/server/server.c create mode 100644 src/util/string.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 0697bcb..f5da0f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,9 +7,11 @@ include(FindPkgConfig) # ${SRC_FILES} is recursively defined in the subdirectories. # Each subdirectory adds only the source files that are present at its level. -add_subdirectory(src) +file(GLOB_RECURSE SRC_FILES src/ true *.c) add_executable(relabsd ${SRC_FILES}) +include_directories(include/) + # Language parameters. enable_language(C) target_compile_features(relabsd PUBLIC c_variadic_macros) diff --git a/include/relabsd/client.h b/include/relabsd/client.h new file mode 100644 index 0000000..e69de29 diff --git a/include/relabsd/config.h b/include/relabsd/config.h new file mode 100644 index 0000000..e69de29 diff --git a/include/relabsd/config/config_file.h b/include/relabsd/config/config_file.h new file mode 100644 index 0000000..3aa1a13 --- /dev/null +++ b/include/relabsd/config/config_file.h @@ -0,0 +1,100 @@ +#ifndef RELABSD_CONFIG_H +#define RELABSD_CONFIG_H + +#include + +#include "axis.h" + +/* Maximum length for a axis code. */ +#define RELABSD_CONF_AXIS_CODE_SIZE 2 + +/* Number of options that can be configured. */ +#define RELABSD_OPTIONS_COUNT 3 + +enum relabsd_option +{ + RELABSD_DIRECT_OPTION, + RELABSD_REAL_FUZZ_OPTION, + RELABSD_FRAMED_OPTION +}; + +struct relabsd_config_axis +{ +/* relabsd axis properties */ + int enabled; + int previous_value; + int option[RELABSD_OPTIONS_COUNT]; + +/* Absolute axis properties */ + int min; + int max; + int fuzz; + int flat; + int resolution; +}; + +/* + * There is no relabsd_config_free function, so be careful about using dynamic + * memory for input_file or device_name. + */ +struct relabsd_config +{ + const char * input_file; + const char * device_name; + struct timeval timeout; + int enable_timeout; + struct relabsd_config_axis axis[RELABSD_VALID_AXES_COUNT]; +}; + +/* + * 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 * 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 value to be emitted, + * 0 if 'conf' wants the event to be transmitted as is. + * -1 if 'conf' doesn't want the event to be transmitted. + * + * If the return value is 0, this function will not have altered the value at + * 'value'. Otherwise, this function can have altered it to match its + * requirements. + * If the return value is either 0 or -1, the 'previous_value' of the axis + * has been updated. + */ +int relabsd_config_filter +( + struct relabsd_config * const conf, + enum relabsd_axis const axis, + 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, + enum relabsd_axis const axis, + struct input_absinfo * const absinfo +); + +#endif diff --git a/include/relabsd/config/parameters.h b/include/relabsd/config/parameters.h new file mode 100644 index 0000000..e69de29 diff --git a/include/relabsd/debug.h b/include/relabsd/debug.h new file mode 100644 index 0000000..025c312 --- /dev/null +++ b/include/relabsd/debug.h @@ -0,0 +1,145 @@ +#pragma once + +#include + +#include + +#ifndef RELABSD_DEBUG_PROGRAM_FLOW + #define RELABSD_DEBUG_PROGRAM_FLOW 0 +#endif + +#ifndef RELABSD_DEBUG_CONFIG + #define RELABSD_DEBUG_CONFIG 0 +#endif + +#ifndef RELABSD_DEBUG_REAL_EVENTS + #define RELABSD_DEBUG_REAL_EVENTS 0 +#endif + +#ifndef RELABSD_DEBUG_VIRTUAL_EVENTS + #define RELABSD_DEBUG_VIRTUAL_EVENTS 0 +#endif + +#ifndef RELABSD_ENABLE_WARNINGS_OUTPUT +#define RELABSD_ENABLE_WARNINGS_OUTPUT 1 +#endif +#ifndef RELABSD_ENABLE_RUNTIME_ERRORS_OUTPUT +#define RELABSD_ENABLE_RUNTIME_ERRORS_OUTPUT 1 +#endif +#ifndef RELABSD_ENABLE_PROGRAMMING_ERRORS_OUTPUT +#define RELABSD_ENABLE_PROGRAMMING_ERRORS_OUTPUT 1 +#endif +#ifndef RELABSD_ENABLE_FATAL_ERROR_OUTPUT +#define RELABSD_ENABLE_FATAL_ERROR_OUTPUT 1 +#endif + +#ifdef RELABSD_ENABLE_ERROR_LOCATION + #define RELABSD_LOCATION "[" __FILE__ "][" RELABSD_TO_STRING(__LINE__) "]" +#else + #define RELABSD_LOCATION "" +#endif + +#define RELABSD_PRINT_STDERR(symbol, str, ...)\ + fprintf(stderr, "[" symbol "]" RELABSD_LOCATION " " str "\n", __VA_ARGS__); + +/* + * Given that we use preprocessor contants as flags, we can expect the compilers + * to remove the test condition for disabled flags. No need to be shy about + * allowing many debug options. + */ + +#define RELABSD_DEBUG(flag, str, ...)\ + RELABSD_ISOLATE\ + (\ + if (flag)\ + {\ + RELABSD_PRINT_STDERR("D", str, __VA_ARGS__);\ + }\ + ) + + +#define RELABSD_WARNING(str, ...)\ + RELABSD_ISOLATE\ + (\ + if (RELABSD_ENABLE_WARNINGS_OUTPUT)\ + {\ + RELABSD_PRINT_STDERR("W", str, __VA_ARGS__);\ + }\ + ) + +#define RELABSD_ERROR(str, ...)\ + RELABSD_ISOLATE\ + (\ + if (RELABSD_ENABLE_RUNTIME_ERRORS_OUTPUT)\ + {\ + RELABSD_PRINT_STDERR("E", str, __VA_ARGS__);\ + }\ + ) + +#define RELABSD_PROG_ERROR(str, ...)\ + RELABSD_ISOLATE\ + (\ + if (RELABSD_ENABLE_PROGRAMMING_ERRORS_OUTPUT)\ + {\ + RELABSD_PRINT_STDERR("P", str, __VA_ARGS__);\ + }\ + ) + +#define RELABSD_FATAL(str, ...)\ + RELABSD_ISOLATE\ + (\ + if (RELABSD_ENABLE_FATAL_ERROR_OUTPUT)\ + {\ + RELABSD_PRINT_STDERR("F", str, __VA_ARGS__);\ + }\ + ) + +/* For outputs without dynamic content (static). ******************************/ + +#define RELABSD_PRINT_S_STDERR(symbol, str)\ + fprintf(stderr, "[" symbol "]" RELABSD_LOCATION " " str "\n"); + +#define RELABSD_S_DEBUG(flag, str)\ + RELABSD_ISOLATE\ + (\ + if (flag)\ + {\ + RELABSD_PRINT_S_STDERR("D", str);\ + }\ + ) + +#define RELABSD_S_WARNING(str)\ + RELABSD_ISOLATE\ + (\ + if (RELABSD_ENABLE_WARNINGS_OUTPUT)\ + {\ + RELABSD_PRINT_S_STDERR("W", str);\ + }\ + ) + +#define RELABSD_S_ERROR(str)\ + RELABSD_ISOLATE\ + (\ + if (RELABSD_ENABLE_RUNTIME_ERRORS_OUTPUT)\ + {\ + RELABSD_PRINT_S_STDERR("E", str);\ + }\ + ) + +#define RELABSD_S_PROG_ERROR(str)\ + RELABSD_ISOLATE\ + (\ + if (RELABSD_ENABLE_PROGRAMMING_ERRORS_OUTPUT)\ + {\ + RELABSD_PRINT_S_STDERR("P", str);\ + }\ + ) + +#define RELABSD_S_FATAL(str)\ + RELABSD_ISOLATE\ + (\ + if (RELABSD_ENABLE_FATAL_ERROR_OUTPUT)\ + {\ + RELABSD_PRINT_S_STDERR("F", str);\ + }\ + ) diff --git a/include/relabsd/device/axis.h b/include/relabsd/device/axis.h new file mode 100644 index 0000000..3829b51 --- /dev/null +++ b/include/relabsd/device/axis.h @@ -0,0 +1,78 @@ +#pragma once + +/* Number of axes that can be configured. */ +#define RELABSD_AXIS_AXES_COUNT 8 + +enum relabsd_axis_name +{ + RELABSD_X, + RELABSD_Y, + RELABSD_Z, + RELABSD_RX, + RELABSD_RY, + RELABSD_RZ, + RELABSD_WHEEL, + RELABSD_MISC, + RELABSD_UNKNOWN +}; + +struct relabsd_axis +{ + int min; + int max; + int fuzz; + int flat; + int resolution; + int flags; +}; + +/* + * 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_name relabsd_axis_name_and_evdev_abs_from_evdev_rel +( + const unsigned int rel_code, + unsigned int abs_code [const restrict static 1] +); + +/* + * Returns the EV_REL/EV_ABS equivalent of 'e'. + * There is no equivalent for RELABSD_UNKNOWN, so 'e' is forbidden from + * taking this value. + */ +unsigned int relabsd_axis_name_to_evdev_rel (const enum relabsd_axis_name e); +unsigned int relabsd_axis_name_to_evdev_abs (const enum relabsd_axis_name e); + +/* + * Returns the relabsd_axis equivalent of a EV_REL/EV_ABS code. + */ +enum relabsd_axis_name relabsd_axis_name_from_evdev_rel +( + const unsigned int rel +); + +enum relabsd_axis_name relabsd_axis_name_from_evdev_abs +( + const unsigned int abs +); + +/* + * 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_name relabsd_axis_parse_name +( + const char name [const restrict static 1] +); + +/* + * Gives an string representation of an relabsd_axis. + * "??" is returned for RELABSD_UNKNOWN. + * Returned values should be coherent with the configuration file syntax. + */ +const char * relabsd_axis_name_to_string (const enum relabsd_axis_name e); diff --git a/include/relabsd/device/physical_device.h b/include/relabsd/device/physical_device.h new file mode 100644 index 0000000..17866f7 --- /dev/null +++ b/include/relabsd/device/physical_device.h @@ -0,0 +1,50 @@ +#pragma once + +#include + +struct relabsd_input +{ + struct libevdev * dev; + int fd; + int timed_out; +}; + +/* + * 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, + const struct relabsd_config * const conf +); + +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, + unsigned int * const input_type, + unsigned int * const input_code, + int * const input_value +); + +int relabsd_input_wait_for_next_event +( + const struct relabsd_input * const input, + const struct relabsd_config * const config +); + +#endif diff --git a/include/relabsd/device/virtual_device.h b/include/relabsd/device/virtual_device.h new file mode 100644 index 0000000..d398c7f --- /dev/null +++ b/include/relabsd/device/virtual_device.h @@ -0,0 +1,71 @@ +#pragma once + +#include +#include + +/* + 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 + #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 + +struct relabsd_device +{ + struct libevdev * dev; + 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, + const struct relabsd_config * const config +); + +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, + unsigned int const type, + unsigned int const code, + int const value +); + +/* + * Send an event for each enabled axis, setting it to zero. + * An EV_SYN event is sent afterwards. + */ +void relabsd_device_set_axes_to_zero +( + const struct relabsd_device * const dev, + const struct relabsd_config * const config +); diff --git a/include/relabsd/server.h b/include/relabsd/server.h new file mode 100644 index 0000000..e69de29 diff --git a/include/relabsd/util/macro.h b/include/relabsd/util/macro.h new file mode 100644 index 0000000..b9adb5e --- /dev/null +++ b/include/relabsd/util/macro.h @@ -0,0 +1,6 @@ +#pragma once + +#define RELABSD_ISOLATE(a) do {a} while (0) + +#define RELABSD__TO_STRING(x) #x +#define RELABSD_TO_STRING(x) RELABSD__TO_STRING(x) diff --git a/include/relabsd/util/string.h b/include/relabsd/util/string.h new file mode 100644 index 0000000..d632720 --- /dev/null +++ b/include/relabsd/util/string.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +#include + +/* strncmp stops at '\0' and strlen does not count '\0'. */ +#define RELABSD_IS_PREFIX(a, b) (strncmp(a, b, strlen(a)) == 0) + +#define RELABSD_STRING_EQUALS(a, b) (strcmp(a, b) == 0) + +int relabsd_util_parse_int +( + const char string [const restrict static 1], + const int min, + const int max, + int output [const restrict static 1] +); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt deleted file mode 100644 index 98af72c..0000000 --- a/src/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -set( - SRC_FILES ${SRC_FILES} - ${CMAKE_CURRENT_SOURCE_DIR}/main.c - ${CMAKE_CURRENT_SOURCE_DIR}/config.c - ${CMAKE_CURRENT_SOURCE_DIR}/input.c - ${CMAKE_CURRENT_SOURCE_DIR}/axis.c - ${CMAKE_CURRENT_SOURCE_DIR}/relabsd_device.c -) - -set(SRC_FILES ${SRC_FILES} PARENT_SCOPE) diff --git a/src/axis.c b/src/axis.c deleted file mode 100644 index c4729ba..0000000 --- a/src/axis.c +++ /dev/null @@ -1,285 +0,0 @@ -#include - -#include "pervasive.h" - -#include "axis.h" -#include "error.h" - -enum relabsd_axis relabsd_axis_from_name (const char * const name) -{ - if (RELABSD_STRING_EQUALS("X", name)) - { - return RELABSD_X; - } - else if (RELABSD_STRING_EQUALS("Y", name)) - { - return RELABSD_Y; - } - else if (RELABSD_STRING_EQUALS("Z", name)) - { - return RELABSD_Z; - } - else if (RELABSD_STRING_EQUALS("RX", name)) - { - return RELABSD_RX; - } - else if (RELABSD_STRING_EQUALS("RY", name)) - { - return RELABSD_RY; - } - else if (RELABSD_STRING_EQUALS("RZ", name)) - { - return RELABSD_RZ; - } - else if (RELABSD_STRING_EQUALS("WL", name)) - { - return RELABSD_WHEEL; - } - else if (RELABSD_STRING_EQUALS("MC", name)) - { - return RELABSD_MISC; - } - - return RELABSD_UNKNOWN; -} - -char * relabsd_axis_to_name (enum relabsd_axis const e) -{ - switch (e) - { - case RELABSD_X: - return "X"; - - case RELABSD_Y: - return "Y"; - - case RELABSD_Z: - return "Z"; - - case RELABSD_RX: - return "RX"; - - case RELABSD_RY: - return "RY"; - - case RELABSD_RZ: - return "RZ"; - - case RELABSD_WHEEL: - return "WL"; - - case RELABSD_MISC: - return "MC"; - - case RELABSD_UNKNOWN: - return "??"; - - default: - break; - } - - RELABSD_S_PROG_ERROR("relabsd_axis_to_name is missing at least 1 case."); - - return ".."; -} - -enum relabsd_axis relabsd_axis_convert_evdev_rel -( - unsigned int const rel_code, - unsigned int * const abs_code -) -{ - switch (rel_code) - { - case REL_X: - *abs_code = ABS_X; - return RELABSD_X; - - case REL_Y: - *abs_code = ABS_Y; - return RELABSD_Y; - - case REL_Z: - *abs_code = ABS_Z; - return RELABSD_Z; - - case REL_RX: - *abs_code = ABS_RX; - return RELABSD_RX; - - case REL_RY: - *abs_code = ABS_RY; - return RELABSD_RY; - - case REL_RZ: - *abs_code = ABS_RZ; - return RELABSD_RZ; - - case REL_WHEEL: - *abs_code = ABS_WHEEL; - return RELABSD_WHEEL; - - case REL_MISC: - *abs_code = ABS_MISC; - return RELABSD_MISC; - - default: - return RELABSD_UNKNOWN; - } -} - -unsigned int relabsd_axis_to_rel (enum relabsd_axis const e) -{ - switch (e) - { - case RELABSD_X: - return REL_X; - - case RELABSD_Y: - return REL_Y; - - case RELABSD_Z: - return REL_Z; - - case RELABSD_RX: - return REL_RX; - - case RELABSD_RY: - return REL_RY; - - case RELABSD_RZ: - return REL_RZ; - - case RELABSD_WHEEL: - return REL_WHEEL; - - case RELABSD_MISC: - return REL_MISC; - - case RELABSD_UNKNOWN: - RELABSD_S_PROG_ERROR - ( - "relabsd_axis_to_rel(RELABSD_UNKNOWN) is forbidden." - ); - return REL_MAX; - - default: - break; - } - - RELABSD_S_PROG_ERROR("relabsd_axis_to_rel is missing at least 1 case."); - - return REL_MAX; -} - -unsigned int relabsd_axis_to_abs (enum relabsd_axis const e) -{ - switch (e) - { - case RELABSD_X: - return ABS_X; - - case RELABSD_Y: - return ABS_Y; - - case RELABSD_Z: - return ABS_Z; - - case RELABSD_RX: - return ABS_RX; - - case RELABSD_RY: - return ABS_RY; - - case RELABSD_RZ: - return ABS_RZ; - - case RELABSD_WHEEL: - return ABS_WHEEL; - - case RELABSD_MISC: - return ABS_MISC; - - case RELABSD_UNKNOWN: - RELABSD_S_PROG_ERROR - ( - "relabsd_axis_to_abs(RELABSD_UNKNOWN) is forbidden." - ); - return ABS_MAX; - - default: - break; - } - - RELABSD_S_PROG_ERROR("relabsd_axis_to_abs is missing at least 1 case."); - - return REL_MAX; -} - -/* - * Returns the relabsd_axis equivalent of a EV_REL/EV_ABS code. - */ -enum relabsd_axis relabsd_axis_from_rel (unsigned int const rel) -{ - switch (rel) - { - case REL_X: - return RELABSD_X; - - case REL_Y: - return RELABSD_Y; - - case REL_Z: - return RELABSD_Z; - - case REL_RX: - return RELABSD_RX; - - case REL_RY: - return RELABSD_RY; - - case REL_RZ: - return RELABSD_RZ; - - case REL_WHEEL: - return RELABSD_WHEEL; - - case REL_MISC: - return RELABSD_MISC; - - default: - return RELABSD_UNKNOWN; - } -} -enum relabsd_axis relabsd_axis_from_abs (unsigned int const abs) -{ - switch (abs) - { - case ABS_X: - return RELABSD_X; - - case ABS_Y: - return RELABSD_Y; - - case ABS_Z: - return RELABSD_Z; - - case ABS_RX: - return RELABSD_RX; - - case ABS_RY: - return RELABSD_RY; - - case ABS_RZ: - return RELABSD_RZ; - - case ABS_WHEEL: - return RELABSD_WHEEL; - - case ABS_MISC: - return RELABSD_MISC; - - default: - return RELABSD_UNKNOWN; - } -} diff --git a/src/axis.h b/src/axis.h deleted file mode 100644 index 2c4ea72..0000000 --- a/src/axis.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef RELABSD_AXIS_H -#define RELABSD_AXIS_H - -/* Number of axes that can be configured. */ -#define RELABSD_VALID_AXES_COUNT 8 - -enum relabsd_axis -{ - RELABSD_X, - RELABSD_Y, - RELABSD_Z, - RELABSD_RX, - RELABSD_RY, - RELABSD_RZ, - RELABSD_WHEEL, - RELABSD_MISC, - RELABSD_UNKNOWN -}; - - -/* - * 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, - unsigned int * const abs_code -); - -/* - * Returns the EV_REL/EV_ABS equivalent of 'e'. - * There is no equivalent for RELABSD_UNKNOWN, so 'e' is forbidden from - * taking this value. - */ -unsigned int relabsd_axis_to_rel (enum relabsd_axis const e); -unsigned int relabsd_axis_to_abs (enum relabsd_axis const e); - -/* - * Returns the relabsd_axis equivalent of a EV_REL/EV_ABS code. - */ -enum relabsd_axis relabsd_axis_from_rel (unsigned int const rel); -enum relabsd_axis relabsd_axis_from_abs (unsigned int const abs); - -/* - * 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_from_name (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_to_name (enum relabsd_axis const e); -#endif diff --git a/src/client.c b/src/client.c new file mode 100644 index 0000000..d03a768 --- /dev/null +++ b/src/client.c @@ -0,0 +1,189 @@ +/**** POSIX *******************************************************************/ +#include +#include +#include +#include +#include + +#include +#include + +/**** RELABSD *****************************************************************/ +#include +#include +#include + +#include + +/******************************************************************************/ +/**** LOCAL FUNCTIONS *********************************************************/ +/******************************************************************************/ +static int open_socket +( + FILE * s [const restrict static 1], + const char socket_name [const restrict static 1] +) +{ + const int old_errno = errno; + int fd; + struct sockaddr_un addr; + + RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "Opening socket to server..."); + + errno = 0; + + if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) + { + RELABSD_FATAL + ( + "Unable to create socket: %s.", + strerror(errno) + ); + + errno = old_errno; + + return -1; + } + + errno = old_errno; + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, socket_name, (sizeof(addr.sun_path) - 1)); + + errno = 0; + + if (connect(fd, ((struct sockaddr*) &addr), sizeof(addr)) == -1) + { + RELABSD_FATAL + ( + "Unable to connect to address: %s.", + strerror(errno) + ); + + errno = old_errno; + + close(fd); + + return -1; + } + + errno = 0; + + *s = fdopen(fd, "w+"); + + if (*s == ((FILE *) NULL)) + { + RELABSD_FATAL + ( + "Unable to open socket as a file: %s.", + strerror(errno) + ); + + errno = old_errno; + + close(fd); + + return -1; + } + + errno = old_errno; + + RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "Opened socket to server."); + + return 0; +} + +static int send_commands +( + const int argc, + const char * argv [const restrict static argc], + FILE socket [const restrict static 1] +) +{ + int i, j; + + RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "Sending commands to server..."); + + for (i = 3; i < argc;) + { + + if (fputs(argv[i], socket) == EOF) + { + // TODO: error + } + + for + ( + j = relabsd_parameters_argument_count_for(argv[i]), + i++; + ((j > 0) && (i < argc)); + j++, i-- + ) + { + if (fputc(' ', socket) == EOF) + { + // TODO: error + } + if (fputs(argv[i], socket) == EOF) + { + // TODO: error + } + } + + if (fputc('\0', socket) == EOF) + { + // TODO: error + } + } + + if (fputc('\0', socket) == EOF) + { + } + + RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "Sent commands to server."); + + return 0; +} + +static int receive_reply +( + FILE socket [const restrict static 1] +) +{ + return 0; +} + +/******************************************************************************/ +/**** EXPORTED FUNCTIONS ******************************************************/ +/******************************************************************************/ +int relabsd_client +( + const int argc, + const char * argv [const restrict static argc], + struct relabsd_parameters params [const restrict static 1] +) +{ + FILE * socket; + + RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "Started client mode."); + + if (open_socket(&socket, relabsd_parameters_get_node(params)) < 0) + { + return -1; + } + + if (send_commands(argc, argv, socket) < 0) + { + return -2; + } + + if (receive_reply(socket) < 0) + { + return -3; + } + + RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "Completed client mode."); + + return 0; +} diff --git a/src/config.c b/src/config.c deleted file mode 100644 index ad060a5..0000000 --- a/src/config.c +++ /dev/null @@ -1,821 +0,0 @@ -#include -#include -#include -#include -#include - -#include - -#include "error.h" -#include "pervasive.h" -#include "axis.h" -#include "config.h" - -#ifndef RELABSD_OPTION_MAX_SIZE - #define RELABSD_OPTION_MAX_SIZE 64 -#endif -/* - * "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 (fatal) 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 = (char) getc(f); - - while ((c != '\n') && c != EOF) - { - c = (char) getc(f); - } - - if (errno != 0) - { - RELABSD_FATAL - ( - "[CONFIG] Error while attempting to reach EOF or next line: %s.", - strerror(errno) - ); - - errno = prev_errno; - - return -1; - } - - errno = prev_errno; - - if (c == EOF) - { - return 0; - } - - return 1; -} - -/* - * Returns -1 if the option was discarded (an error has been reported), - * 0 if the option was successfully parsed. - * - * ('length' - 1) is the number of relevant characters in 'name'. - * 'name' must support 'length' characters. - * name[length] will be set to \0, so it does not need to be when calling - * this function. - */ -static int parse_option -( - struct relabsd_config * const conf, - enum relabsd_axis const axis, - char * const name, - int const length -) -{ - name[length] = '\0'; - - if (strcmp(name, "direct") == 0) - { - conf->axis[axis].option[RELABSD_DIRECT_OPTION] = 1; - - RELABSD_DEBUG - ( - RELABSD_DEBUG_CONFIG, - "Axis '%s' enabled option 'direct'.", - relabsd_axis_to_name(axis) - ); - - if (conf->axis[axis].option[RELABSD_FRAMED_OPTION]) - { - RELABSD_WARNING - ( - "[CONFIG] Axis '%s': using option 'direct' discards option" - "'framed'.", - relabsd_axis_to_name(axis) - ); - } - } - else if (strcmp(name, "real_fuzz") == 0) - { - conf->axis[axis].option[RELABSD_REAL_FUZZ_OPTION] = 1; - - RELABSD_DEBUG - ( - RELABSD_DEBUG_CONFIG, - "Axis '%s' enabled option 'real_fuzz'.", - relabsd_axis_to_name(axis) - ); - } - else if (strcmp(name, "framed") == 0) - { - conf->axis[axis].option[RELABSD_FRAMED_OPTION] = 1; - - RELABSD_DEBUG - ( - RELABSD_DEBUG_CONFIG, - "Axis '%s' enabled option 'framed'.", - relabsd_axis_to_name(axis) - ); - - if (conf->axis[axis].option[RELABSD_DIRECT_OPTION]) - { - RELABSD_WARNING - ( - "[CONFIG] Axis '%s': using option 'direct' discards option" - "'framed'.", - relabsd_axis_to_name(axis) - ); - } - } - else - { - RELABSD_ERROR - ( - "[CONFIG] Unknown option '%s' for axis '%s'.", - name, - relabsd_axis_to_name(axis) - ); - - return -1; - } - - return 0; -} - -/* - * Returns -1 on error, - * 0 on EOF, - * 1 on newline. - */ -static int read_axis_options -( - struct relabsd_config * const conf, - FILE * const f, - enum relabsd_axis const axis -) -{ - char option[(RELABSD_OPTION_MAX_SIZE + 1)]; - int i, prev_errno; - char c; - - option[RELABSD_OPTION_MAX_SIZE] = '\0'; - - prev_errno = errno; - - errno = 0; - - memset(conf->axis[axis].option, 0, RELABSD_OPTIONS_COUNT * sizeof(int)); - - i = 0; - - while (i <= RELABSD_OPTION_MAX_SIZE) - { - c = (char) getc(f); - - if ((errno != 0) && (c == EOF)) - { - RELABSD_FATAL - ( - "[CONFIG] Reading error while parsing option name (axis '%s'): %s.", - relabsd_axis_to_name(axis), - strerror(errno) - ); - - errno = prev_errno; - - return -1; - } - - switch (c) - { - case ' ': - case '\t': - break; - - case ',': - /* We parsed a new option and there is a least another. */ - parse_option(conf, axis, option, i); - - i = 0; - - break; - - case '\n': - parse_option(conf, axis, option, i); - errno = prev_errno; - - return 1; - - case EOF: - parse_option(conf, axis, option, i); - errno = prev_errno; - - return 0; - - default: - option[i] = c; - i++; - - break; - } - } - - RELABSD_FATAL - ( - "[CONFIG] Option name '%s[...]' (axis '%s') is too long (%d chars max).", - option, - relabsd_axis_to_name(axis), - RELABSD_OPTION_MAX_SIZE - ); - - return -1; -} - -static int parse_timeout_option -( - struct relabsd_config * const conf, - const char * const param -) -{ - int timeout_msec; - const int prev_errno = errno; - - conf->enable_timeout = 1; - - errno = 0; - - timeout_msec = atoi(param); - - if (timeout_msec <= 0) - { - RELABSD_FATAL - ( - "Illegal value for timeout \"%d\": accepted range is [1, %d].", - timeout_msec, - INT_MAX - ); - - return -1; - } - - memset((void *) &(conf->timeout), 0, sizeof(struct timeval)); - - conf->timeout.tv_sec = (time_t) (timeout_msec / 1000); - - conf->timeout.tv_usec = - ( - ((suseconds_t) timeout_msec) - * ((suseconds_t) 1000) - ); - - return 0; -} - -/* - * Returns -1 on (fatal) error, - * 0 on succes. - */ -static int parse_axis_configuration_line -( - struct relabsd_config * const conf, - FILE * const f, - const char * const buffer -) -{ - int valc, prev_errno; - enum relabsd_axis axis; - - axis = relabsd_axis_from_name(buffer); - - if (axis == RELABSD_UNKNOWN) - { - RELABSD_FATAL - ( - "[CONFIG] Unknown axis '%s'.", - buffer - ); - - return -1; - } - - 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) - { - if (errno == 0) - { - RELABSD_FATAL - ( - "[CONFIG] Unexpected end of file while reading axis '%s'.", - buffer - ); - } - else - { - RELABSD_FATAL - ( - "[CONFIG] An error occured while reading axis '%s': %s.", - buffer, - strerror(errno) - ); - } - - errno = prev_errno; - - return -1; - } - else if (valc < 5) - { - RELABSD_FATAL - ( - "[CONFIG] Invalid parameter count for axis '%s'.", - buffer - ); - - errno = prev_errno; - - return -1; - } - - RELABSD_DEBUG - ( - RELABSD_DEBUG_CONFIG, - "Axis '%s': {min = %d; max = %d; fuzz = %d; flat = %d; resolution = %d}", - buffer, - conf->axis[axis].min, - conf->axis[axis].max, - conf->axis[axis].fuzz, - conf->axis[axis].flat, - conf->axis[axis].resolution - ); - - errno = prev_errno; - - conf->axis[axis].enabled = 1; - conf->axis[axis].previous_value = 0; - - return read_axis_options(conf, f, axis); -} - -/* - * Returns -1 on (fatal) error, - * 0 on EOF, - * 1 on newline. - */ -static int read_config_line -( - struct relabsd_config * const conf, - FILE * const f, - const char * const prefix -) -{ - if (!RELABSD_IS_PREFIX("#", prefix)) - { - return parse_axis_configuration_line(conf, f, prefix); - } - - 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, - char * const filename -) -{ - FILE * f; - char buffer[(RELABSD_CONF_AXIS_CODE_SIZE + 1)]; - int continue_reading, prev_errno; - - buffer[RELABSD_CONF_AXIS_CODE_SIZE] = '\0'; - - f = fopen(filename, "r"); - - if (f == (FILE *) NULL) - { - RELABSD_FATAL - ( - "[CONFIG] Could not open file: %s.", - strerror(errno) - ); - - return -1; - } - - - prev_errno = errno; - errno = 0; - - continue_reading = 1; - - while - ( - (continue_reading == 1) - && - ( - fscanf - ( - f, - "%" RELABSD_TO_STRING(RELABSD_CONF_AXIS_CODE_SIZE) "s", - buffer - ) - != EOF - ) - ) - { - switch (read_config_line(conf, f, buffer)) - { - case 1: - /* Everything is going well. */ - break; - - case 0: - /* EOF reached. */ - continue_reading = 0; - break; - - case -1: - /* A fatal error occured. */ - errno = prev_errno; - - fclose(f); - return -1; - } - } - - if (errno != 0) - { - /* An error happened in the while loop condition. */ - RELABSD_FATAL - ( - "[CONFIG] Error while reading file: %s, last read '%s'.", - strerror(errno), - buffer - ); - - errno = prev_errno; - - fclose(f); - - return -1; - } - - errno = prev_errno; - - fclose(f); - - return 0; -} - -static void print_usage -( - const char * const exec -) -{ - RELABSD_FATAL - ( - "USAGE: %s input_device config_file [