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  * Event API.
36  *
37  * On top of a shared L4Re::Dataspace (and optionally using L4::Triggerable),
38  * the event API implements asynchronous event transmission from an event
39  * provider (server) to an event receiver (client). Events are put into an
40  * Event_buffer_t residing on the shared L4Re::Dataspace.
41  *
42  * This interface is not usually used directly. Instead use
43  * L4Re::Util::Event_t for clients. An example server portion is implemented
44  * in L4Re::Util::Event_svr.
45  */
46 
47 typedef l4re_event_stream_id_t Event_stream_id;
48 typedef l4re_event_absinfo_t Event_absinfo;
49 
50 class L4_EXPORT Event_stream_bitmap_h
51 {
52 protected:
53  static unsigned __get_idx(unsigned idx)
54  { return idx / (sizeof(unsigned long)*8); }
55 
56  static unsigned long __get_mask(unsigned idx)
57  { return 1ul << (idx % (sizeof(unsigned long)*8)); }
58 
59  static bool __get_bit(unsigned long const *bm, unsigned max, unsigned idx)
60  {
61  if (idx <= max)
62  return bm[__get_idx(idx)] & __get_mask(idx);
63  return false;
64  }
65 
66  static void __set_bit(unsigned long *bm, unsigned max, unsigned idx, bool v)
67  {
68  if (idx > max)
69  return;
70 
71  if (v)
72  bm[__get_idx(idx)] |= __get_mask(idx);
73  else
74  bm[__get_idx(idx)] &= ~__get_mask(idx);
75  }
76 };
77 
78 class L4_EXPORT Event_stream_info
79 : public l4re_event_stream_info_t,
80  private Event_stream_bitmap_h
81 {
82 public:
83  bool get_propbit(unsigned idx) const
84  { return __get_bit(propbits, L4RE_EVENT_PROP_MAX, idx); }
85 
86  void set_propbit(unsigned idx, bool v)
87  { __set_bit(propbits, L4RE_EVENT_PROP_MAX, idx, v); }
88 
89  bool get_evbit(unsigned idx) const
90  { return __get_bit(evbits, L4RE_EVENT_EV_MAX, idx); }
91 
92  void set_evbit(unsigned idx, bool v)
93  { __set_bit(evbits, L4RE_EVENT_EV_MAX, idx, v); }
94 
95  bool get_keybit(unsigned idx) const
96  { return __get_bit(keybits, L4RE_EVENT_KEY_MAX, idx); }
97 
98  void set_keybit(unsigned idx, bool v)
99  { __set_bit(keybits, L4RE_EVENT_KEY_MAX, idx, v); }
100 
101  bool get_relbit(unsigned idx) const
102  { return __get_bit(relbits, L4RE_EVENT_REL_MAX, idx); }
103 
104  void set_relbit(unsigned idx, bool v)
105  { __set_bit(relbits, L4RE_EVENT_REL_MAX, idx, v); }
106 
107  bool get_absbit(unsigned idx) const
108  { return __get_bit(absbits, L4RE_EVENT_ABS_MAX, idx); }
109 
110  void set_absbit(unsigned idx, bool v)
111  { __set_bit(absbits, L4RE_EVENT_ABS_MAX, idx, v); }
112 
113  bool get_swbit(unsigned idx) const
114  { return __get_bit(swbits, L4RE_EVENT_SW_MAX, idx); }
115 
116  void set_swbit(unsigned idx, bool v)
117  { __set_bit(swbits, L4RE_EVENT_SW_MAX, idx, v); }
118 };
119 
120 class L4_EXPORT Event_stream_state
121 : public l4re_event_stream_state_t,
122  private Event_stream_bitmap_h
123 {
124 public:
125  bool get_keybit(unsigned idx) const
126  { return __get_bit(keybits, L4RE_EVENT_KEY_MAX, idx); }
127 
128  void set_keybit(unsigned idx, bool v)
129  { __set_bit(keybits, L4RE_EVENT_KEY_MAX, idx, v); }
130 
131  bool get_swbit(unsigned idx) const
132  { return __get_bit(swbits, L4RE_EVENT_SW_MAX, idx); }
133 
134  void set_swbit(unsigned idx, bool v)
135  { __set_bit(swbits, L4RE_EVENT_SW_MAX, idx, v); }
136 };
137 
138 /**
139  * \brief Event class.
140  * \ingroup api_l4re_event
141  *
142  * \see \link api_l4re_event L4Re Event API \endlink
143  */
144 class L4_EXPORT Event :
145  public L4::Kobject_t<Event, L4::Icu, L4RE_PROTO_EVENT>
146 {
147 public:
148  /**
149  * \brief Get event signal buffer.
150  *
151  * \retval ds Event buffer.
152  *
153  * \return 0 on success, negative error code otherwise.
154  */
155  L4_RPC(long, get_buffer, (L4::Ipc::Out<L4::Cap<Dataspace> > ds));
156  L4_RPC(long, get_num_streams, ());
157  L4_RPC(long, get_stream_info, (int idx, Event_stream_info *info));
158  L4_RPC(long, get_stream_info_for_id, (l4_umword_t stream_id, Event_stream_info *info));
159  L4_RPC_NF(long, get_axis_info, (l4_umword_t stream_id,
160  L4::Ipc::Array<unsigned const, unsigned long> axes,
161  L4::Ipc::Array<Event_absinfo, unsigned long> &info));
162 
163  long get_axis_info(l4_umword_t stream_id, unsigned naxes,
164  unsigned const *axis, Event_absinfo *info) const throw()
165  {
166  L4::Ipc::Array<Event_absinfo, unsigned long> i(naxes, info);
167  return get_axis_info_t::call(c(), stream_id,
168  L4::Ipc::Array<unsigned const, unsigned long>(naxes, axis), i);
169  }
170 
171  L4_RPC(long, get_stream_state_for_id, (l4_umword_t stream_id,
172  Event_stream_state *state));
173 
174  typedef L4::Typeid::Rpcs<
175  get_buffer_t,
176  get_num_streams_t,
177  get_stream_info_t,
178  get_stream_info_for_id_t,
179  get_axis_info_t,
180  get_stream_state_for_id_t
181  > Rpcs;
182 };
183 
184 struct L4_EXPORT Default_event_payload
185 {
186  unsigned short type; /**< Type of event */
187  unsigned short code; /**< Code of event */
188  int value; /**< Value of event */
189  l4_umword_t stream_id; /**< Stream ID */
190 };
191 
192 
193 /**
194  * \brief Event buffer class.
195  * \ingroup api_l4re_event
196  */
197 template< typename PAYLOAD = Default_event_payload >
198 class L4_EXPORT Event_buffer_t
199 {
200 public:
201 
202  /**
203  * \brief Event structure used in buffer.
204  */
205  struct Event
206  {
207  long long time; /**< Event time stamp */
208  PAYLOAD payload;
209 
210  /**
211  * \brief Free the entry.
212  */
213  void free() throw() { l4_mb(); time = 0; }
214  };
215 
216 private:
217  Event *_current;
218  Event *_begin;
219  Event const *_end;
220 
221  void inc() throw()
222  {
223  ++_current;
224  if (_current == _end)
225  _current = _begin;
226  }
227 
228 public:
229 
230  Event_buffer_t() : _current(0), _begin(0), _end(0) {}
231 
232  void reset()
233  {
234  for (Event *i = _begin; i != _end; ++i)
235  i->time = 0;
236  _current = _begin;
237  }
238 
239  /**
240  * \brief Initialize event buffer.
241  *
242  * \param buffer Pointer to buffer.
243  * \param size Size of buffer in bytes.
244  */
245  Event_buffer_t(void *buffer, l4_addr_t size)
246  : _current((Event*)buffer), _begin(_current),
247  _end(_begin + size / sizeof(Event))
248  { reset(); }
249 
250  /**
251  * \brief Next event in buffer.
252  *
253  * \return 0 if no event available, event otherwise.
254  */
255  Event *next() throw()
256  {
257  Event *c = _current;
258  if (c->time)
259  {
260  inc();
261  return c;
262  }
263  return 0;
264  }
265 
266  /**
267  * \brief Put event into buffer at current position.
268  *
269  * \param ev Event to put into the buffer.
270  * \return false if buffer is full and entry could not be added.
271  */
272  bool put(Event const &ev) throw()
273  {
274  Event *c = _current;
275  if (c->time)
276  return false;
277 
278  inc();
279  c->payload = ev.payload;
280  l4_wmb();
281  c->time = ev.time;
282  return true;
283  }
284 };
285 
286 typedef Event_buffer_t<Default_event_payload> Event_buffer;
287 
288 }
289 
290