]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/mag/include/server/input_driver
Inital import
[l4.git] / l4 / pkg / mag / include / server / input_driver
1 // vi:ft=cpp
2 /*
3  * (c) 2010 Technische Universität Dresden
4  * This file is part of TUD:OS and distributed under the terms of the
5  * GNU General Public License 2.
6  * Please see the COPYING-GPL-2 file for details.
7  */
8 #pragma once
9
10 #include <l4/mag/server/user_state>
11 #include <l4/mag/server/plugin>
12
13 #include <l4/re/event_enums.h>
14
15 namespace Mag_server {
16
17 template<int Max_axis>
18 class Motion_merger
19 {
20 private:
21   unsigned long _changed;
22   int _v[Max_axis];
23
24   enum Type
25   {
26     T_none = 0,
27     T_abs  = 1,
28     T_rel  = 2,
29   };
30
31   Type axis_inf(unsigned char axis) const
32   { return Type((_changed >> (2*axis)) & 3); }
33
34   void set_axis_inf(unsigned char axis, Type t)
35   { _changed |= ((unsigned long)t) << (axis*2); }
36
37 public:
38   Motion_merger() : _changed(0) {}
39
40   void reset() { _changed = 0; }
41
42
43
44   bool handle(User_state::Event const &e)
45   {
46     if (!(e.payload.type == L4RE_EV_REL || e.payload.type == L4RE_EV_ABS))
47       return false;
48
49     if (e.payload.code >= Max_axis)
50       return false;
51
52     unsigned char ax = e.payload.code;
53
54     if (axis_inf(ax) == T_none && e.payload.type == L4RE_EV_REL)
55       {
56         _v[ax] = 0;
57         set_axis_inf(ax, T_rel);
58       }
59
60     switch (e.payload.type)
61       {
62       case L4RE_EV_REL:
63         _v[ax] += e.payload.value;
64         break;
65       case L4RE_EV_ABS:
66         _v[ax] = e.payload.value;
67         set_axis_inf(ax, T_abs);
68         break;
69       }
70
71     return true;
72   }
73
74   bool set_event(unsigned char axis, User_state::Event *e)
75   {
76     unsigned i = axis_inf(axis);
77     if (!i)
78       return false;
79
80     if (i & T_abs)
81       e->payload.type = L4RE_EV_ABS;
82     else
83       e->payload.type = L4RE_EV_REL;
84
85     e->payload.code = axis;
86     e->payload.value = _v[axis];
87
88     return true;
89   }
90
91   template< typename I, typename T >
92   I merge(I const &s, I const &e, T *last_time)
93   {
94     for (I i = s; i != e; ++i)
95       if (handle(*i))
96         {
97           *last_time = i->time;
98           i->free();
99         }
100       else
101         return i;
102
103     return e;
104   }
105
106   template< typename E, typename I, typename F >
107   void process(I const &s, I const &end, F const &f)
108   {
109     for (I e = s; e != end; ++e)
110       {
111         E me;
112         me.payload.stream_id = e->payload.stream_id;
113         e = merge(e, end, &me.time);
114
115         for (unsigned i = 0; i < Max_axis; ++i)
116           if (set_event(i, &me))
117             f(me);
118
119         if (e != end)
120           {
121             reset();
122             f(*e);
123           }
124         else
125           break;
126         e->free();
127       }
128   }
129 };
130
131 class Motion_fwd
132 {
133 public:
134   template< /*typename E,*/ typename I, typename F >
135   void process(I const &s, I const &end, F const &f)
136   {
137     for (I e = s; e != end; ++e)
138       {
139         f(*e);
140         e->free();
141       }
142   }
143 };
144
145 class Input_driver : public Plugin
146 {
147 protected:
148   Core_api *_core;
149
150 private:
151   Input_driver *_next_active;
152
153 public:
154   explicit Input_driver(char const *name)
155   : Plugin(name), _core(0), _next_active(0)
156   {}
157
158   char const *type() const { return "input-driver"; }
159   Input_driver *next_active() const { return _next_active; }
160   virtual void poll_events() = 0;
161   virtual int probe() = 0;
162
163   void start(Core_api *core)
164   {
165     _core = core;
166     if (probe() == 0)
167       {
168         _next_active = core->input_drivers();
169         core->add_input_driver(this);
170       }
171   }
172
173   virtual ~Input_driver() {}
174 };
175
176 }