]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/mag/include/server/hid_report
update
[l4.git] / l4 / pkg / mag / include / server / hid_report
1 // vi:ft=cpp
2 /*
3  * (c) 2011 Alexander Warg <warg@os.inf.tu-dresden.de>
4  *     economic rights: Technische Universität Dresden (Germany)
5  *
6  * This file is part of TUD:OS and distributed under the terms of the
7  * GNU General Public License 2.
8  * Please see the COPYING-GPL-2 file for details.
9  */
10
11 #pragma once
12
13 #include <l4/mag/server/valuator>
14
15 namespace Mag_server {
16
17 class Axis_info
18 {
19 public:
20   int value;
21   int min;
22   int max;
23   int fuzz;
24   int flat;
25   int resolution;
26   int delta;
27   int mode;
28 };
29
30 class Axis_info_vector
31 {
32 public:
33   Axis_info_vector() : _i(0), _size(0) {}
34   explicit Axis_info_vector(unsigned size)
35   : _i(new Axis_info*[size]), _size(size)
36   {
37     for (unsigned i = 0; i < _size; ++i)
38       _i[i] = 0;
39   }
40
41   ~Axis_info_vector()
42   {
43     if (!_i)
44       return;
45
46     for (unsigned i = 0; i < _size; ++i)
47       if (_i[i])
48         delete _i[i];
49
50     delete [] _i;
51   }
52
53
54   unsigned size() const { return _size; }
55   Axis_info const *get(unsigned idx) const
56   {
57     if (idx < _size)
58       return _i[idx];
59     return 0;
60   }
61
62   Axis_info *get(unsigned idx)
63   {
64     if (idx < _size )
65       return _i[idx];
66     return 0;
67   }
68
69   Axis_info *create(unsigned idx)
70   {
71     if (idx >= _size)
72       return 0;
73
74     if (_i[idx])
75       delete _i[idx];
76
77     _i[idx] = new Axis_info();
78     return _i[idx];
79   }
80
81   bool set(unsigned idx, Axis_info *info)
82   {
83     if (idx >= _size)
84       {
85         delete info;
86         return 0;
87       }
88
89     if (_i[idx])
90       delete _i[idx];
91
92     _i[idx] = info;
93     return true;
94   }
95
96 private:
97   Axis_info **_i;
98   unsigned _size;
99
100   Axis_info_vector(Axis_info_vector const &);
101 };
102
103 class Hid_report
104 {
105 public:
106   struct Key_event
107   {
108     int code;
109     int value;
110   };
111
112   Hid_report(l4_umword_t device_id, unsigned rels, unsigned abss, unsigned mscs,
113              unsigned sws, unsigned mts);
114
115   ~Hid_report();
116
117   bool get(unsigned char type, unsigned code, int &val) const;
118   void set(unsigned char type, unsigned code, int val);
119
120   bool mt_get(unsigned id, unsigned code, int &val) const;
121
122   void mt_set(unsigned code, int val);
123   bool submit_mt();
124
125   Mag_server::Valuator<int> const *get_vals(unsigned char type) const;
126   Mag_server::Valuator<int> *get_vals(unsigned char type);
127   Mag_server::Valuator<int> const *get_mt_vals(unsigned id) const;
128
129   bool add_key(int code, int value);
130   Key_event const *get_key_event(unsigned idx) const;
131   Key_event const *find_key_event(int code) const;
132   void remove_key_event(int code);
133
134   void sync(long long time) { _time = time; }
135   long long time() const { return _time; }
136   void clear();
137   l4_umword_t device_id() const { return _device_id; }
138
139   Axis_info_vector const *abs_infos() const
140   { return _abs_info; }
141
142   Axis_info_vector *abs_infos()
143   { return _abs_info; }
144
145   void set_abs_info(Axis_info_vector *i)
146   { _abs_info = i; }
147
148 private:
149   enum
150   {
151     Type_offset = 2,
152     Num_types   = 4,
153
154     Mt_val_offset = 0x2f,
155     Num_mt_vals   = 13,
156
157     Num_key_events = 5,
158   };
159
160   long long _time;
161   l4_umword_t const _device_id;
162
163   unsigned _kevs;
164   Key_event _kev[Num_key_events];
165
166   Valuator<int> _vals[Num_types];
167   unsigned _mts;
168   Valuator<int> *_mt;
169
170   Axis_info_vector *_abs_info;
171 };
172
173 struct Axis_xfrm_noop
174 {
175   void operator () (unsigned, int &) const {}
176 };
177
178
179 template<typename SINK, typename XFRM>
180 bool post_hid_report(Hid_report const *e, SINK &sink, XFRM const &xfrm_abs)
181 {
182   bool events = false;
183   bool trigger = false;
184
185   typename SINK::Event ne;
186   ne.time = e->time();
187   ne.payload.stream_id = e->device_id();
188
189   ne.payload.type = 2;
190   Valuator<int> const *v = e->get_vals(2);
191   for (unsigned i = 0; v && i < v->size(); ++i)
192     {
193       Value<int> val = v->get(i);
194       if (!val.valid())
195         continue;
196
197       ne.payload.code = i;
198       ne.payload.value = val.val();
199
200       trigger |= sink.put(ne);
201       events = true;
202     }
203
204   v = e->get_vals(3);
205   ne.payload.type = 3;
206   for (unsigned i = 0; v && i < v->size(); ++i)
207     {
208       Value<int> val = v->get(i);
209       if (!val.valid())
210         continue;
211
212       ne.payload.code = i;
213       ne.payload.value = val.val();
214       xfrm_abs(i, ne.payload.value);
215       trigger |= sink.put(ne);
216       events = true;
217     }
218
219   ne.payload.type = 1;
220   for (unsigned i = 0;; ++i)
221     {
222       Hid_report::Key_event const *ke = e->get_key_event(i);
223       if (!ke)
224         break;
225
226       ne.payload.code = ke->code;
227       ne.payload.value = ke->value;
228       trigger |= sink.put(ne);
229       events = true;
230     }
231
232   for (unsigned mt = 0; mt < 10; ++mt)
233     {
234       Valuator<int> const *m = e->get_mt_vals(mt);
235       if (!m)
236         continue;
237
238       bool mt_ev = false;
239       ne.payload.type = 3;
240       unsigned mt_offset = m->offset();
241       for (unsigned i = 0; i < m->size(); ++i)
242         {
243           Value<int> v = m->get(i + mt_offset);
244           if (!v.valid())
245             continue;
246
247           ne.payload.code = i + mt_offset;
248           ne.payload.value = v.val();
249           xfrm_abs(i + mt_offset, ne.payload.value);
250           trigger |= sink.put(ne);
251           events = true;
252           mt_ev = true;
253         }
254
255       if (mt_ev)
256         {
257           ne.payload.type = 0;
258           ne.payload.code = 2;
259           ne.payload.value = 0;
260           trigger |= sink.put(ne);
261         }
262     }
263
264   if (events)
265     {
266       ne.payload.type = 0;
267       ne.payload.code = 0;
268       ne.payload.value = 0;
269       trigger |= sink.put(ne);
270     }
271   return trigger;
272 }
273
274
275 }