| summaryrefslogtreecommitdiff |
diff options
| author | Nathanael Sensfelder <SpamShield0@MultiAgentSystems.org> | 2015-09-01 22:48:51 +0200 |
|---|---|---|
| committer | Nathanael Sensfelder <SpamShield0@MultiAgentSystems.org> | 2015-09-01 22:48:51 +0200 |
| commit | 1af58bb8886673ac115f019094853fa763e79187 (patch) | |
| tree | c2ab030898e74288f82c557287272546a990e932 | |
Initial commit.
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | CMakeLists.txt | 16 | ||||
| -rw-r--r-- | LICENSE | 24 | ||||
| -rw-r--r-- | conf/space_navigator.conf | 8 | ||||
| -rw-r--r-- | src/CMakeLists.txt | 10 | ||||
| -rw-r--r-- | src/axis.c | 99 | ||||
| -rw-r--r-- | src/axis.h | 23 | ||||
| -rw-r--r-- | src/config.c | 256 | ||||
| -rw-r--r-- | src/config.h | 49 | ||||
| -rw-r--r-- | src/error.h | 123 | ||||
| -rw-r--r-- | src/input.c | 150 | ||||
| -rw-r--r-- | src/input.h | 28 | ||||
| -rw-r--r-- | src/main.c | 110 | ||||
| -rw-r--r-- | src/pervasive.h | 13 | ||||
| -rw-r--r-- | src/relabsd_device.c | 137 | ||||
| -rw-r--r-- | src/relabsd_device.h | 31 |
16 files changed, 1078 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..a1ca449 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 2.8 FATAL_ERROR) + +project("relabsd") + +include(FindPkgConfig) + +add_subdirectory(src) + +# ${SRC_FILES} is recursively defined in the subdirectories. +# Each subdirectory only adds the source files that are present at its level. + +add_executable(relabsd ${SRC_FILES}) + +pkg_search_module(LIBEVDEV REQUIRED libevdev) +include_directories(${LIBEVDEV_INCLUDE_DIRS}) +target_link_libraries(relabsd ${LIBEVDEV_LIBRARIES}) @@ -0,0 +1,24 @@ +Copyright (c) 2015, Nathanael Sensfelder +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the <organization> nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL NATHANAEL SENSFELDER BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/conf/space_navigator.conf b/conf/space_navigator.conf new file mode 100644 index 0000000..07a5ae0 --- /dev/null +++ b/conf/space_navigator.conf @@ -0,0 +1,8 @@ +# 3DConnexion SpaceNavigator +# AXIS MIN MAX FUZZ FLAT RESOLUTION +X -350 350 1 1 1 +Y -350 350 1 1 1 +Z -350 350 1 1 1 +RX -350 350 1 1 1 +RY -350 350 1 1 1 +RZ -350 350 1 1 1 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..98af72c --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,10 @@ +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 new file mode 100644 index 0000000..1ba09f0 --- /dev/null +++ b/src/axis.c @@ -0,0 +1,99 @@ +#include <libevdev/libevdev.h> + +#include "pervasive.h" + +#include "axis.h" + +enum relabsd_axis relabsd_axis_name_to_enum (char * const name) +{ + if (_IS_PREFIX("X", name)) + { + return RELABSD_X; + } + else if (_IS_PREFIX("Y", name)) + { + return RELABSD_Y; + } + else if (_IS_PREFIX("Z", name)) + { + return RELABSD_Z; + } + else if (_IS_PREFIX("RX", name)) + { + return RELABSD_RX; + } + else if (_IS_PREFIX("RY", name)) + { + return RELABSD_RY; + } + else if (_IS_PREFIX("RZ", name)) + { + return RELABSD_RZ; + } + + return RELABSD_UNKNOWN; +} + +char * relabsd_axis_enum_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_UNKNOWN: + 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; + + default: + return RELABSD_UNKNOWN; + } +} diff --git a/src/axis.h b/src/axis.h new file mode 100644 index 0000000..6d4f7f5 --- /dev/null +++ b/src/axis.h @@ -0,0 +1,23 @@ +#ifndef RELABSD_AXIS_H +#define RELABSD_AXIS_H + +enum relabsd_axis +{ + RELABSD_X, + RELABSD_Y, + RELABSD_Z, + RELABSD_RX, + RELABSD_RY, + RELABSD_RZ, + RELABSD_UNKNOWN +}; + +enum relabsd_axis relabsd_axis_name_to_enum (char * const name); +char * relabsd_axis_enum_to_name (enum relabsd_axis const e); +enum relabsd_axis relabsd_axis_convert_evdev_rel +( + unsigned int const rel_code, + unsigned int * const abs_code +); + +#endif diff --git a/src/config.c b/src/config.c new file mode 100644 index 0000000..1699811 --- /dev/null +++ b/src/config.c @@ -0,0 +1,256 @@ +#include <errno.h> +#include <string.h> + +#include "error.h" +#include "pervasive.h" +#include "axis.h" +#include "config.h" + +static int reach_next_line_or_eof (FILE * const f) +{ + char c; + c = getc(f); + + while ((c != '\n') && c != EOF) + { + c = getc(f); + } + + if (c == EOF) + { + return -1; + } + + return 0; +} + +static int all_axis_are_configured (const int * const axis_is_configured) +{ + int i; + + for (i = 0; i < 6; ++i) + { + if (axis_is_configured[i] == 0) + { + _FATAL + ( + "[CONFIG] Axis '%s' is not configured.", + relabsd_axis_enum_to_name((enum relabsd_axis) i) + ); + + return -1; + } + } + + return 0; +} + +static int parse_axis_configuration_line +( + struct relabsd_config * const conf, + FILE * const f, + int * const axis_is_configured, + char * const buffer +) +{ + int valc; + enum relabsd_axis axis; + + axis = relabsd_axis_name_to_enum(buffer); + + if (axis == RELABSD_UNKNOWN) + { + _FATAL + ( + "[CONFIG] Unknown axis '%s'.", + buffer + ); + + 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) + ); + + if (valc == EOF) + { + _FATAL + ( + "[CONFIG] Unexpected end of file while reading axis '%s'.", + buffer + ); + + return -1; + } + else if (valc < 5) + { + _FATAL + ( + "[CONFIG] Invalid parameter count for axis '%s'.", + buffer + ); + + return -1; + } + + axis_is_configured[axis] = 1; + return 0; +} + +static int read_config_file +( + struct relabsd_config * const conf, + char * const filename +) +{ + FILE * f; + int axis_is_configured[6]; + char buffer[3]; + int test; + + buffer[2] = '\0'; + + memset(axis_is_configured, 0, 6 * sizeof(int)); + + f = fopen(filename, "r"); + + if (f == (FILE *) NULL) + { + _FATAL + ( + "[CONFIG] Could not open file: %s.", + strerror(errno) + ); + + return -1; + } + + errno = 0; + + while ((test = fscanf(f, "%2s", buffer)) > 0) + { + if (_IS_PREFIX("#", buffer)) + { + if (reach_next_line_or_eof(f) < 0) + { + break; + } + } + else + { + if + ( + parse_axis_configuration_line + ( + conf, + f, + axis_is_configured, + buffer + ) + < 0 + ) + { + break; + } + + if (reach_next_line_or_eof(f) < 0) + { + break; + } + } + } + + if (test < 0 && errno != 0) + { + _FATAL + ( + "[CONFIG] Error while reading file: %s, last read '%s'.", + strerror(errno), + buffer + ); + + fclose(f); + + return -1; + } + + fclose(f); + + if (all_axis_are_configured(axis_is_configured) < 0) + { + return -1; + } + + return 0; +} + +int relabsd_config_parse +( + struct relabsd_config * const conf, + int const argc, + char ** const argv +) +{ + if ((argc < 3) || (argc > 4)) + { + _FATAL + ( + "Usage: %s input_device config_file [<relabsd_device_name>]", + argv[0] + ); + + return -1; + } + + if (argc == 3) + { + conf->device_name = "relabsd device"; + } + else + { + conf->device_name = argv[3]; + } + + conf->input_file = argv[1]; + + if (read_config_file(conf, argv[2]) < 0) + { + return -1; + } + + return 0; +} + +int relabsd_config_allows +( + const struct relabsd_config * const conf, + enum relabsd_axis const axis, + int const value +) +{ + return 1; +}; + +void relabsd_config_get_absinfo +( + const struct relabsd_config * const conf, + enum relabsd_axis const axis, + struct input_absinfo * const absinfo +) +{ + absinfo->value = (__s32) 0; + absinfo->minimum = (__s32) conf->axis[axis].min; + absinfo->maximum = (__s32) conf->axis[axis].max; + absinfo->fuzz = (__s32) conf->axis[axis].fuzz; + absinfo->flat = (__s32) conf->axis[axis].flat; + absinfo->resolution = (__s32) conf->axis[axis].resolution; +} diff --git a/src/config.h b/src/config.h new file mode 100644 index 0000000..ffdfebb --- /dev/null +++ b/src/config.h @@ -0,0 +1,49 @@ +#ifndef RELABSD_CONFIG_H +#define RELABSD_CONFIG_H + +#include <libevdev/libevdev.h> + +#include "axis.h" + +struct relabsd_config_axis +{ + int min; + int max; + int fuzz; + int flat; + int resolution; +}; + +/* + * There are 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; + struct relabsd_config_axis axis[6]; +}; + +int relabsd_config_parse +( + struct relabsd_config * const conf, + int const argc, + char ** const argv +); + +int relabsd_config_allows +( + const struct relabsd_config * const conf, + enum relabsd_axis const axis, + int const value +); + +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/src/error.h b/src/error.h new file mode 100644 index 0000000..aa85e63 --- /dev/null +++ b/src/error.h @@ -0,0 +1,123 @@ +#ifndef RELABSD_ERROR_H +#define RELABSD_ERROR_H + +#include <stdio.h> + +#include "config.h" +#include "pervasive.h" + +#define _HIGHEST_DEBUG_LVL 100 + +#define _DEBUG_LVL _HIGHEST_DEBUG_LVL +#define _ENABLE_WARNINGS_OUTPUT 1 +#define _ENABLE_RUNTIME_ERRORS_OUTPUT 1 +#define _ENABLE_PROGRAMMING_ERRORS_OUTPUT 1 +#define _ENABLE_FATAL_ERROR_OUTPUT 1 +#define _ENABLE_ERROR_LOCATION 0 + +#if _ENABLE_ERROR_LOCATION + #define _LOCATION "[" __FILE__ "][" _TO_STRING(__LINE__) "]" +#else + #define _LOCATION "" +#endif + +#define _PRINT_STDERR(symbol, str, ...)\ + fprintf(stderr, "[" symbol "]" _LOCATION " " str "\n", __VA_ARGS__); + +#define _DEBUG(level, str, ...)\ + _ISOLATE\ + (\ + if (level < _DEBUG_LVL)\ + {\ + _PRINT_STDERR("D", str, __VA_ARGS__);\ + }\ + ) + + +#define _WARNING(str, ...)\ + _ISOLATE\ + (\ + if (_ENABLE_WARNINGS_OUTPUT)\ + {\ + _PRINT_STDERR("W", str, __VA_ARGS__);\ + }\ + ) + +#define _ERROR(str, ...)\ + _ISOLATE\ + (\ + if (_ENABLE_RUNTIME_ERRORS_OUTPUT)\ + {\ + _PRINT_STDERR("E", str, __VA_ARGS__);\ + }\ + ) + +#define _PROG_ERROR(str, ...)\ + _ISOLATE\ + (\ + if (_ENABLE_PROGRAMMING_ERRORS_OUTPUT)\ + {\ + _PRINT_STDERR("P", str, __VA_ARGS__);\ + }\ + ) + +#define _FATAL(str, ...)\ + _ISOLATE\ + (\ + if (_ENABLE_FATAL_ERROR_OUTPUT)\ + {\ + _PRINT_STDERR("F", str, __VA_ARGS__);\ + }\ + ) + +/* For outputs without dynamic content (static). ******************************/ + +#define _PRINT_S_STDERR(symbol, str)\ + fprintf(stderr, "[" symbol "]" _LOCATION " " str "\n"); + +#define _S_DEBUG(level, str)\ + _ISOLATE\ + (\ + if (level < _DEBUG_LVL)\ + {\ + _PRINT_S_STDERR("D", str);\ + }\ + ) + +#define _S_WARNING(str)\ + _ISOLATE\ + (\ + if (_ENABLE_WARNINGS_OUTPUT)\ + {\ + _PRINT_S_STDERR("W", str);\ + }\ + ) + +#define _S_ERROR(str)\ + _ISOLATE\ + (\ + if (_ENABLE_RUNTIME_ERRORS_OUTPUT)\ + {\ + _PRINT_S_STDERR("E", str);\ + }\ + ) + +#define _S_PROG_ERROR(str)\ + _ISOLATE\ + (\ + if (_ENABLE_PROGRAMMING_ERRORS_OUTPUT)\ + {\ + _PRINT_S_STDERR("P", str);\ + }\ + ) + +#define _S_FATAL(str)\ + _ISOLATE\ + (\ + if (_ENABLE_FATAL_ERROR_OUTPUT)\ + {\ + _PRINT_S_STDERR("F", str);\ + }\ + ) + +#endif diff --git a/src/input.c b/src/input.c new file mode 100644 index 0000000..eb7b013 --- /dev/null +++ b/src/input.c @@ -0,0 +1,150 @@ +#include <fcntl.h> +#include <errno.h> +#include <string.h> + +#include <libevdev/libevdev.h> + +#include "error.h" + +#include "input.h" + +static int check_for_axis +( + const struct libevdev * const dev, + const char * axis_name, + const unsigned int axis_id +) +{ + if (!libevdev_has_event_code(dev, EV_REL, axis_id)) + { + _FATAL("Input device has no %s axis.", axis_name); + + return -1; + } + + return 0; +} + +static int device_is_compatible (const struct libevdev * const dev) +{ + if (!libevdev_has_event_type(dev, EV_REL)) + { + _S_FATAL("Input device has no relative axis."); + + return -1; + } + + if + ( + (check_for_axis(dev, "X", REL_X) < 0) + | (check_for_axis(dev, "Y", REL_Y) < 0) + | (check_for_axis(dev, "Z", REL_Z) < 0) + | (check_for_axis(dev, "RX", REL_RX) < 0) + | (check_for_axis(dev, "RY", REL_RY) < 0) + | (check_for_axis(dev, "RZ", REL_RZ) < 0) + ) + { + return -1; + } + + return 0; +} + +int relabsd_input_open +( + struct relabsd_input * const input, + const char * const filename +) +{ + input->fd = open(filename, O_RDONLY); + + if (input->fd < 0) + { + _FATAL + ( + "Could not open device %s in read only mode:", + filename, + strerror(errno) + ); + + return -1; + } + + if + ( + libevdev_new_from_fd(input->fd, &(input->dev)) < 0 + ) + { + _FATAL + ( + "libevdev could not open %s:", + filename, + strerror(errno) + ); + + close(input->fd); + + return -1; + } + + if (device_is_compatible(input->dev) < 0) + { + _FATAL("%s is not compatible with relabsd.", filename); + + return -1; + } + + return 0; +} + +void relabsd_input_close (const struct relabsd_input * const input) +{ + libevdev_free(input->dev); + close(input->fd); +} + +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 rc; + struct input_event event; + + rc = + libevdev_next_event + ( + input->dev, + (LIBEVDEV_READ_FLAG_NORMAL | LIBEVDEV_READ_FLAG_BLOCKING), + &event + ); + + /*if (rc == LIBEVDEV_READ_STATUS_SYNC) + { + handle_syn_dropped(input->dev); + } + else*/ if (rc != LIBEVDEV_READ_STATUS_SUCCESS) + { + _WARNING("[INPUT] Could not get next event: %s.", strerror(-rc)); + + return -1; + } + + _DEBUG + ( + 90, + "[INPUT] 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 0; +} diff --git a/src/input.h b/src/input.h new file mode 100644 index 0000000..03b5c5a --- /dev/null +++ b/src/input.h @@ -0,0 +1,28 @@ +#ifndef RELABSD_INPUT_H +#define RELABSD_INPUT_H + +#include <libevdev/libevdev.h> + +struct relabsd_input +{ + struct libevdev * dev; + int fd; +}; + +int relabsd_input_open +( + struct relabsd_input * const input, + const char * const filename +); + +void relabsd_input_close (const struct relabsd_input * const input); + +int relabsd_input_read +( + const struct relabsd_input * const input, + unsigned int * const input_type, + unsigned int * const input_code, + int * const input_value +); + +#endif diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..b60a074 --- /dev/null +++ b/src/main.c @@ -0,0 +1,110 @@ +#include <fcntl.h> +#include <errno.h> +#include <string.h> +#include <unistd.h> +#include <signal.h> + +#include "pervasive.h" +#include "error.h" +#include "config.h" +#include "input.h" +#include "relabsd_device.h" + +static int RELABSD_RUN = 1; + +static void interrupt (int signal_id) +{ + RELABSD_RUN = 0; + + _S_WARNING("Interrupted, will exit at the next input device event."); +} + +static void convert_input +( + const struct relabsd_config * const conf, + const struct relabsd_input * const input, + const struct relabsd_device * const dev +) +{ + 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) + { + 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); + } + } + else + { + relabsd_device_write_evdev_event + ( + dev, + input_type, + input_code, + value + ); + } + } +} + +int main (int argc, char ** argv) +{ + struct relabsd_config conf; + struct relabsd_input input; + struct relabsd_device dev; + + if (signal(SIGINT, interrupt) == SIG_ERR) + { + _S_FATAL("Unable to set the SIGINT signal handler."); + + return -1; + } + + if (relabsd_config_parse(&conf, argc, argv) < 0) + { + return -2; + } + + if (relabsd_input_open(&input, conf.input_file) < 0) + { + return -3; + } + + if (relabsd_device_create(&dev, &conf) < 0) + { + return -4; + } + + _S_DEBUG(10, "Converting inputs..."); + + convert_input(&conf, &input, &dev); + + _S_DEBUG(10, "Terminating..."); + + relabsd_device_destroy(&dev); + relabsd_input_close(&input); + + return 0; +} diff --git a/src/pervasive.h b/src/pervasive.h new file mode 100644 index 0000000..8a8449a --- /dev/null +++ b/src/pervasive.h @@ -0,0 +1,13 @@ +#ifndef RELABSD_PERVASIVE_H +#define RELABSD_PERVASIVE_H + +#include <string.h> + +#define __TO_STRING(x) #x +#define _TO_STRING(x) __TO_STRING(x) + +#define _ISOLATE(a) do {a} while (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 new file mode 100644 index 0000000..7d2b761 --- /dev/null +++ b/src/relabsd_device.c @@ -0,0 +1,137 @@ +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <fcntl.h> + +#include "error.h" +#include "axis.h" +#include "config.h" + +#include "relabsd_device.h" + +/* LIBEVDEV_UINPUT_OPEN_MANAGED is not defined on my machine. */ +#ifndef LIBEVDEV_UINPUT_OPEN_MANAGED + #warning "libevdev did not define LIBEVDEV_UINPUT_OPEN_MANAGED, "\ + "using value '-2' instead." + #define LIBEVDEV_UINPUT_OPEN_MANAGED -2 +#endif + +static void replace_rel_axis +( + struct relabsd_device * const dev, + const struct relabsd_config * const config, + struct input_absinfo * const absinfo, + unsigned int rel_code +) +{ + enum relabsd_axis rad_code; + unsigned int abs_code; + + rad_code = relabsd_axis_convert_evdev_rel(rel_code, &abs_code); + + relabsd_config_get_absinfo(config, rad_code, absinfo); + libevdev_disable_event_code(dev->dev, EV_REL, rel_code); + libevdev_enable_event_code(dev->dev, EV_ABS, abs_code, absinfo); +} + +int relabsd_device_create +( + struct relabsd_device * const dev, + const struct relabsd_config * const config +) +{ + struct input_absinfo absinfo; + int fd; + + fd = open(config->input_file, O_RDONLY); + + if (fd < 0) + { + _FATAL + ( + "Could not open device %s in read only mode:", + config->input_file, + strerror(errno) + ); + + return -1; + } + + if + ( + libevdev_new_from_fd(fd, &(dev->dev)) < 0 + ) + { + _FATAL + ( + "libevdev could not open %s:", + config->input_file, + strerror(errno) + ); + + close(fd); + + return -1; + } + + libevdev_set_name(dev->dev, config->device_name); + + libevdev_enable_event_type(dev->dev, EV_ABS); + + replace_rel_axis(dev, config, &absinfo, REL_X); + replace_rel_axis(dev, config, &absinfo, REL_Y); + replace_rel_axis(dev, config, &absinfo, REL_Z); + replace_rel_axis(dev, config, &absinfo, REL_RX); + replace_rel_axis(dev, config, &absinfo, REL_RY); + replace_rel_axis(dev, config, &absinfo, REL_RZ); + + if + ( + libevdev_uinput_create_from_device + ( + dev->dev, + LIBEVDEV_UINPUT_OPEN_MANAGED, + &(dev->uidev) + ) + < 0 + ) + { + _FATAL("Could not create relabsd device: %s.", strerror(errno)); + + libevdev_free(dev->dev); + + close(fd); + + return -1; + } + + close(fd); + + return 0; +} + +void relabsd_device_destroy (const struct relabsd_device * const dev) +{ + libevdev_uinput_destroy(dev->uidev); + libevdev_free(dev->dev); +} + +int relabsd_device_write_evdev_event +( + const struct relabsd_device * const dev, + unsigned int const type, + unsigned int const code, + int const value +) +{ + if + ( + (libevdev_uinput_write_event(dev->uidev, type, code, value) == 0) + && (libevdev_uinput_write_event(dev->uidev, EV_SYN, SYN_REPORT, 0) == 0) + ) + { + return 0; + } + + return -1; +} diff --git a/src/relabsd_device.h b/src/relabsd_device.h new file mode 100644 index 0000000..35a4830 --- /dev/null +++ b/src/relabsd_device.h @@ -0,0 +1,31 @@ +#ifndef RELABSD_RELABSD_DEVICE_H +#define RELABSD_RELABSD_DEVICE_H + +#include <libevdev/libevdev.h> + +#include "config.h" +#include "input.h" + +struct relabsd_device +{ + struct libevdev * dev; + struct libevdev_uinput * uidev; +}; + +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); + +int relabsd_device_write_evdev_event +( + const struct relabsd_device * const dev, + unsigned int const type, + unsigned int const code, + int const value +); + +#endif |


