]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4con/server/src/server.cc
842893f2e19f7a00cb2d2e13bda27e35c8369460
[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
16 #include <l4/sys/capability>
17 #include <l4/sys/factory>
18 #include <l4/sys/typeinfo_svr>
19 #include <l4/cxx/ipc_server>
20 #include <l4/cxx/iostream>
21 #include <l4/cxx/l4iostream>
22 #include <l4/cxx/minmax>
23
24 #include <l4/re/protocols>
25
26 #include <cstdio>
27 #include <l4/l4con/l4con.h>
28 #include <l4/input/libinput.h>
29
30 #include <l4/re/util/video/goos_svr>
31 #include <l4/re/util/video/goos_fb>
32 #include <l4/re/util/event_svr>
33 #include <l4/re/util/event_buffer>
34 #include <l4/re/util/cap_alloc>
35
36 #include "object_registry_gc"
37 #include "main.h"
38 #include "l4con.h"
39 #include "gmode.h"
40 #include "srv.h"
41 #include "vc.h"
42
43 // ---------------------------------------------------------------
44 //
45 static L4::Cap<void> rcv_cap()
46 {
47   static L4::Cap<void> _rcv_cap = L4Re::Util::cap_alloc.alloc<void>();
48   return _rcv_cap;
49 }
50
51 // XXX: why is this in the L4Re::Util namespace ???
52 static L4Re::Util::Object_registry_gc
53                               con_registry(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::Server_object,
59            public l4con_vc
60 {
61 public:
62   explicit Vc();
63   ~Vc();
64   int dispatch(l4_umword_t obj, L4::Ipc_iostream &ios);
65
66   void setup_info(l4con_vc *vc);
67   void reg_fbds(l4_cap_idx_t c);
68   void send_event(l4input *ev);
69   int create_event();
70
71   long close();
72   long pslim_fill(L4::Ipc_iostream &ios);
73   long pslim_copy(L4::Ipc_iostream &ios);
74   long puts(L4::Ipc_iostream &ios);
75   long puts_scale(L4::Ipc_iostream &ios);
76   long get_font_size(L4::Ipc_iostream &ios);
77
78   virtual int refresh(int x, int y, int w, int h);
79
80   long vc_dispatch(L4::Ipc_iostream &ios);
81
82   static L4::Cap<void> rcv_cap() { return ::rcv_cap(); }
83 private:
84   L4Re::Util::Event_buffer evbuf;
85 };
86
87 Vc::Vc()
88 {
89 }
90
91 int
92 Vc::refresh(int x, int y, int w, int h)
93 {
94   l4con_pslim_rect_t r;
95   r.x = x;
96   r.y = y;
97   r.w = w;
98   r.h = h;
99   return con_vc_direct_update_component(this, &r);
100 }
101
102 int
103 Vc::create_event()
104 {
105   long r;
106
107   L4Re::Util::Auto_cap<L4Re::Dataspace>::Cap b
108     = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
109   if (!b.is_valid())
110     return -L4_ENOMEM;
111
112   if ((r = L4Re::Env::env()->mem_alloc()->alloc(L4_PAGESIZE, b.get())) < 0)
113     return r;
114
115   if ((r = evbuf.attach(b.get(), L4Re::Env::env()->rm())) < 0)
116     return r;
117
118   memset(evbuf.buf(), 0, b.get()->size());
119
120   _ds  = b.release();
121
122   return 0;
123 }
124
125 long
126 Vc::close()
127 {
128   return con_vc_close_component(this);
129 }
130
131 Vc::~Vc()
132 {
133   con_vc_close_component(this);
134 }
135
136 long
137 Vc::pslim_fill(L4::Ipc_iostream &ios)
138 {
139   l4con_pslim_rect_t r;
140   l4con_pslim_color_t c;
141   int x, y, w, h;
142
143   ios >> x >> y >> w >> h >> c;
144
145   r.x = x;
146   r.y = y;
147   r.w = w;
148   r.h = h;
149
150   return con_vc_pslim_fill_component(this, &r, c);
151 }
152
153 long
154 Vc::pslim_copy(L4::Ipc_iostream &ios)
155 {
156   l4con_pslim_rect_t r;
157   int x, y, w, h;
158   l4_int16_t dx, dy;
159
160   ios >> x >> y >> w >> h >> dx >> dy;
161
162   r.x = x;
163   r.y = y;
164   r.w = w;
165   r.h = h;
166
167   return con_vc_pslim_copy_component(this, &r, dx, dy);
168 }
169
170 long
171 Vc::puts(L4::Ipc_iostream &ios)
172 {
173   char buf[150];
174   char *s = 0;
175   unsigned long len;
176   short x;
177   short y;
178   l4con_pslim_color_t fg_color;
179   l4con_pslim_color_t bg_color;
180
181   ios >> x >> y >> fg_color >> bg_color
182       >> L4::ipc_buf_in(s, len);
183
184   len = cxx::min<unsigned long>(len, sizeof(buf));
185   memcpy(buf, s, len);
186
187   return con_vc_puts_component(this, buf, len, x, y, fg_color, bg_color);
188 }
189
190 long
191 Vc::puts_scale(L4::Ipc_iostream &ios)
192 {
193   char buf[150];
194   char *s = 0;
195   unsigned long len;
196   short x, y, scale_x, scale_y;
197   l4con_pslim_color_t fg_color;
198   l4con_pslim_color_t bg_color;
199
200   ios >> x >> y >> fg_color >> bg_color >> scale_x >> scale_y
201       >> L4::ipc_buf_in(s, len);
202
203   len = cxx::min<unsigned long>(len, sizeof(buf));
204   memcpy(buf, s, len);
205
206   return con_vc_puts_scale_component(this, buf, len, x, y, fg_color, bg_color,
207                                      scale_x, scale_y);
208 }
209
210 long
211 Vc::get_font_size(L4::Ipc_iostream &ios)
212 {
213   int w = FONT_XRES, h = FONT_YRES;
214   ios << w << h;
215   return L4_EOK;
216 }
217
218 long
219 Vc::vc_dispatch(L4::Ipc_iostream &ios)
220 {
221   l4_msgtag_t tag;
222   ios >> tag;
223
224   if (tag.label() != L4con::Protocol)
225     return -L4_EBADPROTO;
226
227   L4::Opcode op;
228   ios >> op;
229
230   switch (op)
231     {
232     case L4con::L4con_::Close:
233       return close();
234     case L4con::L4con_::Pslim_fill:
235       return pslim_fill(ios);
236     case L4con::L4con_::Puts:
237       return puts(ios);
238     case L4con::L4con_::Puts_scale:
239       return puts_scale(ios);
240     case L4con::L4con_::Get_font_size:
241       return get_font_size(ios);
242     default:
243       return -L4_ENOSYS;
244     }
245 }
246
247 int
248 Vc::dispatch(l4_umword_t obj, L4::Ipc_iostream &ios)
249 {
250   l4_msgtag_t tag;
251   ios >> tag;
252   switch (tag.label())
253     {
254     case L4::Meta::Protocol:
255       return L4::Util::handle_meta_request<L4con>(ios);
256     case L4Re::Protocol::Goos:
257       return L4Re::Util::Video::Goos_svr::dispatch(obj, ios);
258     case L4Re::Protocol::Event:
259     case L4_PROTO_IRQ:
260       return L4Re::Util::Event_svr<Vc>::dispatch(obj, ios);
261     case L4con::Protocol:
262       return vc_dispatch(ios);
263     default:
264       return -L4_EBADPROTO;
265     }
266 }
267
268 extern "C" l4con_vc *alloc_vc()
269 { return new Vc(); }
270
271 extern "C" void create_event(struct l4con_vc *vc)
272 { ((Vc *)vc)->create_event(); }
273
274 void
275 Vc::setup_info(l4con_vc *vc)
276 {
277   _screen_info.pixel_info           = *(L4Re::Video::Pixel_info *)&fb_info.pixel_info;
278   _screen_info.width                = vc->client_xres;
279   _screen_info.height               = vc->client_yres;
280   _screen_info.flags                = 0;
281   _screen_info.num_static_views     = 1;
282   _screen_info.num_static_buffers   = 1;
283
284   init_infos();
285
286   _view_info.buffer_offset          = 0;
287   _view_info.bytes_per_line         = vc->bytes_per_line;
288 }
289
290 void
291 Vc::send_event(l4input *ev)
292 {
293   evbuf.put(*reinterpret_cast<L4Re::Event_buffer::Event const*>(ev));
294   _irq.trigger();
295 }
296
297 extern "C" void fill_out_info(l4con_vc *vc)
298 { ((Vc *)vc)->setup_info(vc); }
299
300 extern "C" void send_event_client(struct l4con_vc *vc, l4input *ev)
301 {
302   if (!ev->time)
303     printf("WARNING: Emiting invalid event!\n");
304
305   if (vc_mode & CON_IN)
306     ((Vc *)vc)->send_event(ev);
307 }
308
309 extern "C" void register_fb_ds(struct l4con_vc *vc)
310 { ((Vc *)vc)->reg_fbds(vc->vfb_ds); }
311
312
313 void
314 Vc::reg_fbds(l4_cap_idx_t c)
315 {
316   L4::Cap<L4Re::Dataspace> t(c);
317   _fb_ds = t;
318 }
319
320 class Controller : public L4::Server_object
321 {
322 public:
323   int dispatch(l4_umword_t obj, L4::Ipc_iostream &ios);
324 };
325
326 int
327 Controller::dispatch(l4_umword_t, L4::Ipc_iostream &ios)
328 {
329   l4_msgtag_t tag;
330   ios >> tag;
331
332   switch (tag.label())
333     {
334     case L4::Meta::Protocol:
335       return L4::Util::handle_meta_request<L4::Factory>(ios);
336     case L4::Factory::Protocol:
337       break;
338     default:
339       return -L4_EBADPROTO;
340     }
341
342   if (!L4::kobject_typeid<L4con>()->
343         has_proto(L4::Ipc::read<L4::Factory::Proto>(ios)))
344     return -L4_ENODEV;
345
346   int connum = con_if_open_component(CON_VFB);
347   if (connum < 0)
348     return -L4_ENOMEM;
349
350   con_registry.register_obj_with_gc((Vc *)vc[connum], 0);
351
352   //con_registry.ref_cnt_add((Vc *)vc[connum], -1);
353   ios << ((Vc *)vc[connum])->obj_cap();
354   return L4_EOK;
355 }
356
357 // ---------------------------------------------------------------
358
359 class My_timeout_hooks
360 {
361 public:
362   static l4_cpu_time_t next_timeout(l4_cpu_time_t old)
363   { return old + REQUEST_TIMEOUT_DELTA; }
364
365   static l4_cpu_time_t current_time()
366   { return l4re_kip()->clock; }
367
368   static void work()
369   {
370     periodic_work();
371     con_registry.gc_run(500);
372   }
373
374   void setup_wait(L4::Ipc_istream &istr, L4::Ipc_svr::Reply_mode)
375   {
376     istr.reset();
377     istr << L4::Small_buf(rcv_cap().cap(), L4_RCV_ITEM_LOCAL_ID);
378     l4_utcb_br_u(istr.utcb())->bdr = 0;
379   }
380
381   static int timeout_br() { return 8; }
382 };
383
384 class My_hooks :
385   public L4::Ipc_svr::Ignore_errors,
386   public L4::Ipc_svr::Timed_work<My_timeout_hooks>
387 {};
388
389 static L4::Server<My_hooks> con_server(l4_utcb());
390
391 int server_loop(void)
392 {
393   static Controller ctrl;
394
395   if (!con_registry.register_obj(&ctrl, "con"))
396     {
397       printf("Service registration failed.\n");
398       return 1;
399     }
400
401   printf("Ready. Waiting for clients\n");
402   con_server.loop(con_registry);
403   return 0;
404 }