| summaryrefslogtreecommitdiff |
diff options
| author | Nathanael Sensfelder <SpamShield0@MultiAgentSystems.org> | 2019-12-27 20:14:49 +0100 |
|---|---|---|
| committer | Nathanael Sensfelder <SpamShield0@MultiAgentSystems.org> | 2019-12-27 20:14:49 +0100 |
| commit | b9952b4938da95de07bff748cfd6d2c7e8471796 (patch) | |
| tree | 3c34b7d8327f41515ec939e3e188767d5d641cca | |
| parent | 60283fb1407fcd1de0586c960ed8d106f59483e9 (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.c | 40 | ||||
| -rw-r--r-- | src/device/virtual/virtual_device.c | 253 |
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) ); } |


