summaryrefslogtreecommitdiff
blob: 47b78a235f906a16ea0cac2bd23dcd940d1e3a7f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#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 unused_mandatory_parameter)
{
   RELABSD_RUN = 0;

   _S_WARNING("Interrupted, will exit at the next input device event.");
}

static void handle_relative_axis_event
(
   struct relabsd_config * const conf,
   const struct relabsd_device * const dev,
   unsigned int const input_type,
   unsigned int const input_code,
   int value
)
{
   unsigned int abs_code;
   enum relabsd_axis rad_code;

   rad_code = relabsd_axis_convert_evdev_rel(input_code, &abs_code);

   switch (relabsd_config_filter(conf, rad_code, &value))
   {
      case -1:
         /* 'conf' doesn't want the event to be transmitted. */
         break;

      case 0:
         /* 'conf' wants the event to be transmitted as is. */
         relabsd_device_write_evdev_event(dev, input_type, input_code, value);
         break;

      case 1:
         /* 'conf' allows the value to be emitted */
         relabsd_device_write_evdev_event(dev, EV_ABS, abs_code, value);
         break;
   }
}

static void convert_input
(
   struct relabsd_config * const conf,
   const struct relabsd_input * const input,
   const struct relabsd_device * const dev
)
{
   unsigned int input_type, input_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)
      {
         /* 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, input_type, input_code, value);
      }
   }
}

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 (set_signal_handlers() < 0)
   {
      return -1;
   }

   if (relabsd_config_parse(&conf, argc, argv) < 0)
   {
      return -2;
   }

   if (relabsd_input_open(&input, &conf) < 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;
}