| summaryrefslogtreecommitdiff | 
diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/axis.c | 7 | ||||
| -rw-r--r-- | src/axis.h | 21 | ||||
| -rw-r--r-- | src/config.c | 224 | ||||
| -rw-r--r-- | src/config.h | 31 | ||||
| -rw-r--r-- | src/input.c | 24 | ||||
| -rw-r--r-- | src/input.h | 16 | ||||
| -rw-r--r-- | src/main.c | 79 | ||||
| -rw-r--r-- | src/pervasive.h | 1 | ||||
| -rw-r--r-- | src/relabsd_device.c | 18 | ||||
| -rw-r--r-- | src/relabsd_device.h | 22 | 
10 files changed, 357 insertions, 86 deletions
| @@ -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))     { @@ -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, @@ -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, | 


