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