]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4con/server/src/server.cc
Update
[l4.git] / l4 / pkg / l4con / server / src / server.cc
1 /*
2  * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
3  *               Alexander Warg <warg@os.inf.tu-dresden.de>,
4  *               Torsten Frenzel <frenzel@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
12 #include <l4/re/env>
13 #include <l4/re/namespace>
14 #include <l4/re/util/cap_alloc>
15 #include <l4/re/util/br_manager>
16
17 #include <l4/sys/capability>
18 #include <l4/sys/factory>
19 #include <l4/cxx/ipc_timeout_queue>
20 #include <l4/sys/cxx/ipc_epiface>
21 #include <l4/cxx/minmax>
22
23 #include <cstdio>
24 #include <l4/l4con/l4con.h>
25 #include <l4/input/libinput.h>
26
27 #include <l4/re/util/video/goos_svr>
28 #include <l4/re/util/video/goos_fb>
29 #include <l4/re/util/event_svr>
30 #include <l4/re/util/event_buffer>
31 #include <l4/re/util/cap_alloc>
32 #include <l4/re/console>
33
34 #include "object_registry_gc"
35 #include "main.h"
36 #include "l4con.h"
37 #include "gmode.h"
38 #include "srv.h"
39 #include "vc.h"
40
41 // XXX: why is this in the L4Re::Util namespace ???
42 struct My_hooks :
43   L4::Ipc_svr::Ignore_errors,
44   L4::Ipc_svr::Timeout_queue_hooks<My_hooks, L4Re::Util::Br_manager>
45 {
46   static l4_cpu_time_t now()
47   { return l4_kip_clock(l4re_kip()); }
48 };
49
50 static L4::Server<My_hooks> con_server(l4_utcb());
51 static L4Re::Util::Object_registry_gc
52                               con_registry(&con_server,
53                                            L4Re::Env::env()->main_thread(),
54                                            L4Re::Env::env()->factory());
55
56 class Vc : public L4Re::Util::Video::Goos_svr,
57            public L4Re::Util::Event_svr<Vc>,
58            public L4::Epiface_t<Vc, L4con>,
59            public l4con_vc
60 {
61 public:
62   using L4Re::Util::Video::Goos_svr::op_info;
63   using L4Re::Util::Event_svr<Vc>::op_info;
64
65   explicit Vc();
66   ~Vc();
67
68   void setup_info(l4con_vc *vc);
69   void reg_fbds(l4_cap_idx_t c);
70   void send_event(l4input *ev);
71   int create_event();
72
73   long close();
74
75   long op_close(L4con::Rights)
76   { return close(); }
77
78   long op_pslim_fill(L4con::Rights, int x, int y, int w, int h,
79                      l4con_pslim_color_t color)
80   {
81     l4con_pslim_rect_t r(x, y, w, h);
82     return con_vc_pslim_fill_component(this, &r, color);
83   }
84
85   long op_pslim_copy(L4con::Rights, int x, int y, int w, int h,
86                      l4_int16_t dx, l4_int16_t dy)
87   {
88     l4con_pslim_rect_t r(x, y, w, h);
89     return con_vc_pslim_copy_component(this, &r, dx, dy);
90   }
91
92   long op_puts(L4con::Rights, short x, short y, l4con_pslim_color_t fg_color,
93                l4con_pslim_color_t bg_color,
94                L4::Ipc::Array_in_buf<char, unsigned long> const &text)
95   {
96       return con_vc_puts_component(this, text.data, text.length, x, y,
97                                    fg_color, bg_color);
98   }
99
100   long op_puts_scale(L4con::Rights, short x, short y, l4con_pslim_color_t fg_color,
101                      l4con_pslim_color_t bg_color, short scale_x, short scale_y,
102                      L4::Ipc::Array_in_buf<char, unsigned long> const &text)
103   {
104       return con_vc_puts_scale_component(this, text.data, text.length, x, y,
105                                          fg_color, bg_color, scale_x, scale_y);
106   }
107
108   long op_get_font_size(L4con::Rights, short &w, short &h)
109   {
110     w = FONT_XRES;
111     h = FONT_YRES;
112     return L4_EOK;
113   }
114
115
116   virtual int refresh(int x, int y, int w, int h);
117
118   void reset_event_buffer() { evbuf.reset(); }
119 private:
120   L4Re::Util::Event_buffer evbuf;
121 };
122
123 Vc::Vc()
124 {
125 }
126
127 int
128 Vc::refresh(int x, int y, int w, int h)
129 {
130   l4con_pslim_rect_t r;
131   r.x = x;
132   r.y = y;
133   r.w = w;
134   r.h = h;
135   return con_vc_direct_update_component(this, &r);
136 }
137
138 int
139 Vc::create_event()
140 {
141   long r;
142
143   L4Re::Util::Auto_cap<L4Re::Dataspace>::Cap b
144     = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
145   if (!b.is_valid())
146     return -L4_ENOMEM;
147
148   if ((r = L4Re::Env::env()->mem_alloc()->alloc(L4_PAGESIZE, b.get())) < 0)
149     return r;
150
151   if ((r = evbuf.attach(b.get(), L4Re::Env::env()->rm())) < 0)
152     return r;
153
154   memset(evbuf.buf(), 0, b.get()->size());
155
156   _ds  = b.release();
157
158   return 0;
159 }
160
161 long
162 Vc::close()
163 {
164   return con_vc_close_component(this);
165 }
166
167 Vc::~Vc()
168 {
169   con_vc_close_component(this);
170 }
171
172
173 extern "C" l4con_vc *alloc_vc()
174 { return new Vc(); }
175
176 extern "C" void create_event(struct l4con_vc *vc)
177 { ((Vc *)vc)->create_event(); }
178
179 void
180 Vc::setup_info(l4con_vc *vc)
181 {
182   _screen_info.pixel_info           = *(L4Re::Video::Pixel_info *)&fb_info.pixel_info;
183   _screen_info.width                = vc->client_xres;
184   _screen_info.height               = vc->client_yres;
185   _screen_info.flags                = 0;
186   _screen_info.num_static_views     = 1;
187   _screen_info.num_static_buffers   = 1;
188
189   init_infos();
190
191   _view_info.buffer_offset          = 0;
192   _view_info.bytes_per_line         = vc->bytes_per_line;
193 }
194
195 void
196 Vc::send_event(l4input *ev)
197 {
198   evbuf.put(*reinterpret_cast<L4Re::Event_buffer::Event const*>(ev));
199   static_assert(sizeof(L4Re::Event_buffer::Event) == sizeof(*ev),
200                 "Size mismatch");
201   _irq.trigger();
202 }
203
204 extern "C" void fill_out_info(l4con_vc *vc)
205 { ((Vc *)vc)->setup_info(vc); }
206
207 extern "C" void send_event_client(struct l4con_vc *vc, l4input *ev)
208 {
209   if (!ev->time)
210     printf("WARNING: Emiting invalid event!\n");
211
212   if (vc_mode & CON_IN)
213     ((Vc *)vc)->send_event(ev);
214 }
215
216 extern "C" void register_fb_ds(struct l4con_vc *vc)
217 { ((Vc *)vc)->reg_fbds(vc->vfb_ds); }
218
219
220 void
221 Vc::reg_fbds(l4_cap_idx_t c)
222 {
223   L4::Cap<L4Re::Dataspace> t(c);
224   _fb_ds = t;
225 }
226
227 class Controller : public L4::Epiface_t<Controller, L4::Factory>
228 {
229 public:
230   long op_create(L4::Factory::Rights, L4::Ipc::Cap<void> &obj,
231                  long type, L4::Ipc::Varg_list<> &&)
232   {
233     if (!L4::kobject_typeid<L4con>()->has_proto(type))
234       return -L4_ENODEV;
235
236     int connum = con_if_open_component(CON_VFB);
237     if (connum < 0)
238       return -L4_ENOMEM;
239
240     con_registry.register_obj_with_gc((Vc *)vc[connum], 0);
241
242     obj = L4::Ipc::make_cap(((Vc *)vc[connum])->obj_cap(), L4_CAP_FPAGE_RWSD);
243     return L4_EOK;
244   }
245 };
246
247 // ---------------------------------------------------------------
248 struct Periodic : L4::Ipc_svr::Timeout_queue::Timeout
249 {
250   void expired()
251   {
252     periodic_work();
253     con_registry.gc_run(500);
254     con_server.queue.add(this, timeout() + REQUEST_TIMEOUT_DELTA);
255   }
256 };
257
258 static Periodic periodic;
259
260 int server_loop(void)
261 {
262   static Controller ctrl;
263   con_server.queue.add(&periodic,
264                        l4_kip_clock(l4re_kip()) + REQUEST_TIMEOUT_DELTA);
265
266   if (!con_registry.register_obj(&ctrl, "con"))
267     {
268       printf("Service registration failed.\n");
269       return 1;
270     }
271
272   printf("Ready. Waiting for clients\n");
273   con_server.loop<L4::Runtime_error, L4Re::Util::Object_registry_gc &>(con_registry);
274   return 0;
275 }