L4Re - L4 Runtime Environment
event
1 // vi:set ft=cpp: -*- Mode: C++ -*-
2 /*
3  * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
4  * Alexander Warg <warg@os.inf.tu-dresden.de>
5  * economic rights: Technische Universit√§t Dresden (Germany)
6  *
7  * This file is part of TUD:OS and distributed under the terms of the
8  * GNU General Public License 2.
9  * Please see the COPYING-GPL-2 file for details.
10  *
11  * As a special exception, you may use this file as part of a free software
12  * library without restriction. Specifically, if other files instantiate
13  * templates or use macros or inline functions from this file, or you compile
14  * this file and link it with other files to produce an executable, this
15  * file does not by itself cause the resulting executable to be covered by
16  * the GNU General Public License. This exception does not however
17  * invalidate any other reasons why the executable file might be covered by
18  * the GNU General Public License.
19  */
20 
21 #pragma once
22 
23 #include <l4/sys/capability>
24 #include <l4/sys/irq>
25 #include <l4/sys/cxx/ipc_iface>
26 #include <l4/sys/cxx/ipc_array>
27 #include <l4/re/dataspace>
28 #include <l4/re/event.h>
29 
30 namespace L4Re {
31 
32 /**
33  * \defgroup api_l4re_event Event API
34  * \ingroup api_l4re
35  * \brief Event interface.
36  */
37 
38 typedef l4re_event_stream_id_t Event_stream_id;
39 typedef l4re_event_absinfo_t Event_absinfo;
40 
41 class L4_EXPORT Event_stream_bitmap_h
42 {
43 protected:
44  static unsigned __get_idx(unsigned idx)
45  { return idx / (sizeof(unsigned long)*8); }
46 
47  static unsigned long __get_mask(unsigned idx)
48  { return 1ul << (idx % (sizeof(unsigned long)*8)); }
49 
50  static bool __get_bit(unsigned long const *bm, unsigned max, unsigned idx)
51  {
52  if (idx <= max)
53  return bm[__get_idx(idx)] & __get_mask(idx);
54  return false;
55  }
56 
57  static void __set_bit(unsigned long *bm, unsigned max, unsigned idx, bool v)
58  {
59  if (idx > max)
60  return;
61 
62  if (v)
63  bm[__get_idx(idx)] |= __get_mask(idx);
64  else
65  bm[__get_idx(idx)] &= ~__get_mask(idx);
66  }
67 };
68 
69 class L4_EXPORT Event_stream_info
70 : public l4re_event_stream_info_t,
71  private Event_stream_bitmap_h
72 {
73 public:
74  bool get_propbit(unsigned idx) const
75  { return __get_bit(propbits, L4RE_EVENT_PROP_MAX, idx); }
76 
77  void set_propbit(unsigned idx, bool v)
78  { __set_bit(propbits, L4RE_EVENT_PROP_MAX, idx, v); }
79 
80  bool get_evbit(unsigned idx) const
81  { return __get_bit(evbits, L4RE_EVENT_EV_MAX, idx); }
82 
83  void set_evbit(unsigned idx, bool v)
84  { __set_bit(evbits, L4RE_EVENT_EV_MAX, idx, v); }
85 
86  bool get_keybit(unsigned idx) const
87  { return __get_bit(keybits, L4RE_EVENT_KEY_MAX, idx); }
88 
89  void set_keybit(unsigned idx, bool v)
90  { __set_bit(keybits, L4RE_EVENT_KEY_MAX, idx, v); }
91 
92  bool get_relbit(unsigned idx) const
93  { return __get_bit(relbits, L4RE_EVENT_REL_MAX, idx); }
94 
95  void set_relbit(unsigned idx, bool v)
96  { __set_bit(relbits, L4RE_EVENT_REL_MAX, idx, v); }
97 
98  bool get_absbit(unsigned idx) const
99  { return __get_bit(absbits, L4RE_EVENT_ABS_MAX, idx); }
100 
101  void set_absbit(unsigned idx, bool v)
102  { __set_bit(absbits, L4RE_EVENT_ABS_MAX, idx, v); }
103 
104  bool get_swbit(unsigned idx) const
105  { return __get_bit(swbits, L4RE_EVENT_SW_MAX, idx); }
106 
107  void set_swbit(unsigned idx, bool v)
108  { __set_bit(swbits, L4RE_EVENT_SW_MAX, idx, v); }
109 };
110 
111 class L4_EXPORT Event_stream_state
112 : public l4re_event_stream_state_t,
113  private Event_stream_bitmap_h
114 {
115 public:
116  bool get_keybit(unsigned idx) const
117  { return __get_bit(keybits, L4RE_EVENT_KEY_MAX, idx); }
118 
119  void set_keybit(unsigned idx, bool v)
120  { __set_bit(keybits, L4RE_EVENT_KEY_MAX, idx, v); }
121 
122  bool get_swbit(unsigned idx) const
123  { return __get_bit(swbits, L4RE_EVENT_SW_MAX, idx); }
124 
125  void set_swbit(unsigned idx, bool v)
126  { __set_bit(swbits, L4RE_EVENT_SW_MAX, idx, v); }
127 };
128 
129 /**
130  * \brief Event class.
131  * \ingroup api_l4re_event
132  */
133 class L4_EXPORT Event :
134  public L4::Kobject_t<Event, L4::Icu, L4RE_PROTO_EVENT>
135 {
136 public:
137  /**
138  * \brief Get event signal buffer.
139  *
140  * \retval ds Event buffer.
141  *
142  * \return 0 on success, negative error code otherwise.
143  */
144  L4_RPC(long, get_buffer, (L4::Ipc::Out<L4::Cap<Dataspace> > ds));
145  L4_RPC(long, get_num_streams, ());
146  L4_RPC(long, get_stream_info, (int idx, Event_stream_info *info));
147  L4_RPC(long, get_stream_info_for_id, (l4_umword_t stream_id, Event_stream_info *info));
148  L4_RPC_NF(long, get_axis_info, (l4_umword_t stream_id,
149  L4::Ipc::Array<unsigned const, unsigned long> axes,
150  L4::Ipc::Array<Event_absinfo, unsigned long> &info));
151 
152  long get_axis_info(l4_umword_t stream_id, unsigned naxes,
153  unsigned const *axis, Event_absinfo *info) const throw()
154  {
155  L4::Ipc::Array<Event_absinfo, unsigned long> i(naxes, info);
156  return get_axis_info_t::call(c(), stream_id,
157  L4::Ipc::Array<unsigned const, unsigned long>(naxes, axis), i);
158  }
159 
160  L4_RPC(long, get_stream_state_for_id, (l4_umword_t stream_id,
161  Event_stream_state *state));
162 
163  typedef L4::Typeid::Rpcs<
164  get_buffer_t,
165  get_num_streams_t,
166  get_stream_info_t,
167  get_stream_info_for_id_t,
168  get_axis_info_t,
169  get_stream_state_for_id_t
170  > Rpcs;
171 };
172 
173 struct L4_EXPORT Default_event_payload
174 {
175  unsigned short type; /**< Type of event */
176  unsigned short code; /**< Code of event */
177  int value; /**< Value of event */
178  l4_umword_t stream_id; /**< Stream ID */
179 };
180 
181 
182 /**
183  * \brief Event buffer class.
184  * \ingroup api_l4re_event
185  */
186 template< typename PAYLOAD = Default_event_payload >
187 class L4_EXPORT Event_buffer_t
188 {
189 public:
190 
191  /**
192  * \brief Event structure used in buffer.
193  */
194  struct Event
195  {
196  long long time; /**< Event time stamp */
197  PAYLOAD payload;
198 
199  /**
200  * \brief Free the entry.
201  */
202  void free() throw() { l4_mb(); time = 0; }
203  };
204 
205 private:
206  Event *_current;
207  Event *_begin;
208  Event const *_end;
209 
210  void inc() throw()
211  {
212  ++_current;
213  if (_current == _end)
214  _current = _begin;
215  }
216 
217 public:
218 
219  Event_buffer_t() : _current(0), _begin(0), _end(0) {}
220 
221  void reset()
222  {
223  for (Event *i = _begin; i != _end; ++i)
224  i->time = 0;
225  _current = _begin;
226  }
227 
228  /**
229  * \brief Initialize event buffer.
230  *
231  * \param buffer Pointer to buffer.
232  * \param size Size of buffer in bytes.
233  */
234  Event_buffer_t(void *buffer, l4_addr_t size)
235  : _current((Event*)buffer), _begin(_current),
236  _end(_begin + size / sizeof(Event))
237  { reset(); }
238 
239  /**
240  * \brief Next event in buffer.
241  *
242  * \return 0 if no event available, event otherwise.
243  */
244  Event *next() throw()
245  {
246  Event *c = _current;
247  if (c->time)
248  {
249  inc();
250  return c;
251  }
252  return 0;
253  }
254 
255  /**
256  * \brief Put event into buffer at current position.
257  *
258  * \param ev Event to put into the buffer.
259  * \return false if buffer is full and entry could not be added.
260  */
261  bool put(Event const &ev) throw()
262  {
263  Event *c = _current;
264  if (c->time)
265  return false;
266 
267  inc();
268  c->payload = ev.payload;
269  l4_wmb();
270  c->time = ev.time;
271  return true;
272  }
273 };
274 
275 typedef Event_buffer_t<Default_event_payload> Event_buffer;
276 
277 }
278 
279