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/re/event_enums.h>
24#include <l4/re/event>
25#include <l4/re/event-sys.h>
26#include <l4/re/util/icu_svr>
27#include <l4/cxx/minmax>
28
29#include <l4/sys/cxx/ipc_legacy>
30
31namespace L4Re { namespace Util {
32
33/**
34 * Convenience wrapper for implementing an event server.
35 *
36 * \see L4Re::Event, L4Re::Util::Event_t
37 */
38template< typename SVR >
39class Event_svr : public Icu_cap_array_svr<SVR>
40{
41private:
42  typedef Icu_cap_array_svr<SVR> Icu_svr;
43
44protected:
45  L4::Cap<L4Re::Dataspace> _ds;
46  typename Icu_svr::Irq _irq;
47
48public:
49  Event_svr() : Icu_svr(1, &_irq) {}
50
51  L4_RPC_LEGACY_DISPATCH(L4Re::Event);
52  L4_RPC_LEGACY_USING(Icu_svr);
53
54  /// Handle L4Re::Event protocol
55  long op_get_buffer(L4Re::Event::Rights, L4::Ipc::Cap<L4Re::Dataspace> &ds)
56  {
57    static_cast<SVR*>(this)->reset_event_buffer();
58    ds = L4::Ipc::Cap<L4Re::Dataspace>(_ds, L4_CAP_FPAGE_RW);
59    return 0;
60  }
61
62  long op_get_num_streams(L4Re::Event::Rights)
63  { return static_cast<SVR*>(this)->get_num_streams(); }
64
65  long op_get_stream_info(L4Re::Event::Rights, int idx, Event_stream_info &info)
66  { return static_cast<SVR*>(this)->get_stream_info(idx, &info); }
67
68  long op_get_stream_info_for_id(L4Re::Event::Rights, l4_umword_t id,
69                                 Event_stream_info &info)
70  { return static_cast<SVR*>(this)->get_stream_info_for_id(id, &info); }
71
72  long op_get_axis_info(L4Re::Event::Rights, l4_umword_t id,
73                        L4::Ipc::Array_in_buf<unsigned, unsigned long> const &axes,
74                        L4::Ipc::Array_ref<Event_absinfo, unsigned long> &info)
75  {
76    unsigned naxes = cxx::min<unsigned>(L4RE_ABS_MAX, axes.length);
77
78    info.length = 0;
79
80    Event_absinfo _info[naxes];
81    int r = static_cast<SVR*>(this)->get_axis_info(id, naxes, axes.data, _info);
82    if (r < 0)
83      return r;
84
85    for (unsigned i = 0; i < naxes; ++i)
86      info.data[i] = _info[i];
87
88    info.length = naxes;
89    return r;
90  }
91
92  long op_get_stream_state_for_id(L4Re::Event::Rights, l4_umword_t stream_id,
93                                  Event_stream_state &state)
94  { return static_cast<SVR*>(this)->get_stream_state_for_id(stream_id, &state); }
95
96  int get_num_streams() const { return 0; }
97  int get_stream_info(int, L4Re::Event_stream_info *)
98  { return -L4_EINVAL; }
99  int get_stream_info_for_id(l4_umword_t, L4Re::Event_stream_info *)
100  { return -L4_EINVAL; }
101  int get_axis_info(l4_umword_t, unsigned /*naxes*/, unsigned const * /*axes*/,
102                    L4Re::Event_absinfo *)
103  { return -L4_EINVAL; }
104  int get_stream_state_for_id(l4_umword_t, L4Re::Event_stream_state *)
105  { return -L4_EINVAL; }
106};
107
108}}
109