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 30namespace 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 47typedef l4re_event_stream_id_t Event_stream_id; 48typedef l4re_event_absinfo_t Event_absinfo; 49 50class L4_EXPORT Event_stream_bitmap_h 51{ 52protected: 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 78class L4_EXPORT Event_stream_info 79: public l4re_event_stream_info_t, 80 private Event_stream_bitmap_h 81{ 82public: 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 120class L4_EXPORT Event_stream_state 121: public l4re_event_stream_state_t, 122 private Event_stream_bitmap_h 123{ 124public: 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 */ 144class L4_EXPORT Event : 145 public L4::Kobject_t<Event, L4::Icu, L4RE_PROTO_EVENT> 146{ 147public: 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 noexcept 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 184struct 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 */ 197template< typename PAYLOAD = Default_event_payload > 198class L4_EXPORT Event_buffer_t 199{ 200public: 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() noexcept { l4_mb(); time = 0; } 214 }; 215 216private: 217 Event *_current; 218 Event *_begin; 219 Event const *_end; 220 221 void inc() noexcept 222 { 223 ++_current; 224 if (_current == _end) 225 _current = _begin; 226 } 227 228public: 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() noexcept 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) noexcept 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 286typedef Event_buffer_t<Default_event_payload> Event_buffer; 287 288} 289 290 291