source: mainline/uspace/srv/hid/console/console.c@ 5d94b16c

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 5d94b16c was 5d94b16c, checked in by Jiri Svoboda <jiri@…>, 13 years ago

Factor out server side of console IPC protocol.

  • Property mode set to 100644
File size: 16.6 KB
RevLine 
[51c1b003]1/*
[7c014d1]2 * Copyright (c) 2011 Martin Decky
[51c1b003]3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
[ce5bcb4]28
[231a60a]29/** @addtogroup console
[1601f3c]30 * @{
[ce5bcb4]31 */
32/** @file
33 */
34
[7c014d1]35#include <async.h>
36#include <stdio.h>
37#include <adt/prodcons.h>
[111d2d6]38#include <io/input.h>
[7c014d1]39#include <ipc/vfs.h>
[51c1b003]40#include <errno.h>
[30db06c]41#include <str_error.h>
[15f3c3f]42#include <loc.h>
[7c014d1]43#include <event.h>
[5d94b16c]44#include <io/con_srv.h>
[111d2d6]45#include <io/kbd_event.h>
[7c014d1]46#include <io/keycode.h>
[6d5e378]47#include <io/chargrid.h>
48#include <io/output.h>
[7c014d1]49#include <align.h>
50#include <malloc.h>
51#include <as.h>
[1e4cada]52#include <fibril_synch.h>
[9805cde]53#include "console.h"
[369a5f8]54
[1313ee9]55#define NAME "console"
56#define NAMESPACE "term"
[79ae36dd]57
[6d5e378]58#define UTF8_CHAR_BUFFER_SIZE (STR_BOUNDS(1) + 1)
[a58bc8b]59
[79460ae]60typedef struct {
[6d5e378]61 atomic_t refcnt; /**< Connection reference count */
62 prodcons_t input_pc; /**< Incoming keyboard events */
63
64 /**
65 * Not yet sent bytes of last char event.
66 */
67 char char_remains[UTF8_CHAR_BUFFER_SIZE];
68 size_t char_remains_len; /**< Number of not yet sent bytes. */
[7c014d1]69
[6d5e378]70 fibril_mutex_t mtx; /**< Lock protecting mutable fields */
[7c014d1]71
[6d5e378]72 size_t index; /**< Console index */
73 service_id_t dsid; /**< Service handle */
[7c014d1]74
[6d5e378]75 sysarg_t cols; /**< Number of columns */
76 sysarg_t rows; /**< Number of rows */
77 console_caps_t ccaps; /**< Console capabilities */
[7c014d1]78
[6d5e378]79 chargrid_t *frontbuf; /**< Front buffer */
80 frontbuf_handle_t fbid; /**< Front buffer handle */
[5d94b16c]81 con_srvs_t srvs; /**< Console service setup */
[424cd43]82} console_t;
[79460ae]83
[111d2d6]84/** Input server proxy */
85static input_t *input;
[7c014d1]86
[6d5e378]87/** Session to the output server */
88static async_sess_t *output_sess;
[7c014d1]89
[6d5e378]90/** Output dimensions */
91static sysarg_t cols;
92static sysarg_t rows;
[7c014d1]93
[1601f3c]94/** Array of data for virtual consoles */
[424cd43]95static console_t consoles[CONSOLE_COUNT];
96
[7c014d1]97/** Mutex for console switching */
98static FIBRIL_MUTEX_INITIALIZE(switch_mtx);
99
[424cd43]100static console_t *prev_console = &consoles[0];
[7c014d1]101static console_t *active_console = &consoles[0];
[424cd43]102static console_t *kernel_console = &consoles[KERNEL_CONSOLE];
[1601f3c]103
[111d2d6]104static int input_ev_key(input_t *, kbd_event_type_t, keycode_t, keymod_t, wchar_t);
105static int input_ev_move(input_t *, int, int);
106static int input_ev_abs_move(input_t *, unsigned, unsigned, unsigned, unsigned);
107static int input_ev_button(input_t *, int, int);
108
109static input_ev_ops_t input_ev_ops = {
110 .key = input_ev_key,
111 .move = input_ev_move,
112 .abs_move = input_ev_abs_move,
113 .button = input_ev_button
114};
115
[5d94b16c]116static int cons_open(con_srvs_t *, con_srv_t *);
117static int cons_close(con_srv_t *);
118static int cons_read(con_srv_t *, void *, size_t);
119static int cons_write(con_srv_t *, void *, size_t);
120static void cons_sync(con_srv_t *);
121static void cons_clear(con_srv_t *);
122static void cons_set_pos(con_srv_t *, sysarg_t col, sysarg_t row);
123static int cons_get_pos(con_srv_t *, sysarg_t *, sysarg_t *);
124static int cons_get_size(con_srv_t *, sysarg_t *, sysarg_t *);
125static int cons_get_color_cap(con_srv_t *, console_caps_t *);
126static void cons_set_style(con_srv_t *, console_style_t);
127static void cons_set_color(con_srv_t *, console_color_t, console_color_t,
128 console_color_attr_t);
129static void cons_set_rgb_color(con_srv_t *, pixel_t, pixel_t);
130static void cons_set_cursor_visibility(con_srv_t *, bool);
131static int cons_get_event(con_srv_t *, kbd_event_t *);
132
133static con_ops_t con_ops = {
134 .open = cons_open,
135 .close = cons_close,
136 .read = cons_read,
137 .write = cons_write,
138 .sync = cons_sync,
139 .clear = cons_clear,
140 .set_pos = cons_set_pos,
141 .get_pos = cons_get_pos,
142 .get_size = cons_get_size,
143 .get_color_cap = cons_get_color_cap,
144 .set_style = cons_set_style,
145 .set_color = cons_set_color,
146 .set_rgb_color = cons_set_rgb_color,
147 .set_cursor_visibility = cons_set_cursor_visibility,
148 .get_event = cons_get_event
149};
150
151static console_t *srv_to_console(con_srv_t *srv)
152{
153 return srv->srvs->sarg;
154}
155
[7c014d1]156static void cons_update(console_t *cons)
[9805cde]157{
[7c014d1]158 fibril_mutex_lock(&switch_mtx);
159 fibril_mutex_lock(&cons->mtx);
160
161 if ((cons == active_console) && (active_console != kernel_console)) {
[6d5e378]162 output_update(output_sess, cons->fbid);
163 output_cursor_update(output_sess, cons->fbid);
[7c014d1]164 }
165
166 fibril_mutex_unlock(&cons->mtx);
167 fibril_mutex_unlock(&switch_mtx);
[9805cde]168}
169
[7c014d1]170static void cons_update_cursor(console_t *cons)
[9805cde]171{
[7c014d1]172 fibril_mutex_lock(&switch_mtx);
173 fibril_mutex_lock(&cons->mtx);
174
175 if ((cons == active_console) && (active_console != kernel_console))
[6d5e378]176 output_cursor_update(output_sess, cons->fbid);
[7c014d1]177
178 fibril_mutex_unlock(&cons->mtx);
179 fibril_mutex_unlock(&switch_mtx);
[429acb9]180}
181
[6d5e378]182static void cons_damage(console_t *cons)
[d2cc7e1]183{
[7c014d1]184 fibril_mutex_lock(&switch_mtx);
185 fibril_mutex_lock(&cons->mtx);
186
187 if ((cons == active_console) && (active_console != kernel_console)) {
[6d5e378]188 output_damage(output_sess, cons->fbid, 0, 0, cons->cols,
[7c014d1]189 cons->rows);
[6d5e378]190 output_cursor_update(output_sess, cons->fbid);
[dc033a1]191 }
[7c014d1]192
193 fibril_mutex_unlock(&cons->mtx);
194 fibril_mutex_unlock(&switch_mtx);
[d2cc7e1]195}
196
[7c014d1]197static void cons_switch(console_t *cons)
[d2cc7e1]198{
[7c014d1]199 fibril_mutex_lock(&switch_mtx);
200
201 if (cons == active_console) {
202 fibril_mutex_unlock(&switch_mtx);
203 return;
204 }
205
206 if (cons == kernel_console) {
[6d5e378]207 output_yield(output_sess);
[7c014d1]208 if (!console_kcon()) {
[6d5e378]209 output_claim(output_sess);
[7c014d1]210 fibril_mutex_unlock(&switch_mtx);
211 return;
212 }
[d2cc7e1]213 }
[7c014d1]214
215 if (active_console == kernel_console)
[6d5e378]216 output_claim(output_sess);
[7c014d1]217
218 prev_console = active_console;
219 active_console = cons;
220
221 fibril_mutex_unlock(&switch_mtx);
222
[6d5e378]223 cons_damage(cons);
[d2cc7e1]224}
225
[024fcc5]226static console_t *cons_get_active_uspace(void)
227{
228 fibril_mutex_lock(&switch_mtx);
[6d5e378]229
[024fcc5]230 console_t *active_uspace = active_console;
[6d5e378]231 if (active_uspace == kernel_console)
[024fcc5]232 active_uspace = prev_console;
[7c014d1]233
[6d5e378]234 assert(active_uspace != kernel_console);
[7c014d1]235
[6d5e378]236 fibril_mutex_unlock(&switch_mtx);
[7c014d1]237
[6d5e378]238 return active_uspace;
[429acb9]239}
[10569b1]240
[111d2d6]241static int input_ev_key(input_t *input, kbd_event_type_t type, keycode_t key,
242 keymod_t mods, wchar_t c)
[51c1b003]243{
[111d2d6]244 if ((key >= KC_F1) && (key < KC_F1 + CONSOLE_COUNT) &&
245 ((mods & KM_CTRL) == 0)) {
246 cons_switch(&consoles[key - KC_F1]);
247 } else {
248 /* Got key press/release event */
249 kbd_event_t *event =
250 (kbd_event_t *) malloc(sizeof(kbd_event_t));
251 if (event == NULL) {
252 return ENOMEM;
[79ae36dd]253 }
254
[111d2d6]255 link_initialize(&event->link);
256 event->type = type;
257 event->key = key;
258 event->mods = mods;
259 event->c = c;
[7c014d1]260
[111d2d6]261 /*
262 * Kernel console does not read events
263 * from us, so we will redirect them
264 * to the (last) active userspace console
265 * if necessary.
266 */
267 console_t *target_console = cons_get_active_uspace();
268
269 prodcons_produce(&target_console->input_pc,
270 &event->link);
[7c014d1]271 }
[111d2d6]272
273 return EOK;
274}
275
276static int input_ev_move(input_t *input, int dx, int dy)
277{
278 return EOK;
279}
280
281static int input_ev_abs_move(input_t *input, unsigned x , unsigned y,
282 unsigned max_x, unsigned max_y)
283{
284 return EOK;
285}
286
287static int input_ev_button(input_t *input, int bnum, int bpress)
288{
289 return EOK;
[7c014d1]290}
[1875a0c]291
[7c014d1]292/** Process a character from the client (TTY emulation). */
293static void cons_write_char(console_t *cons, wchar_t ch)
294{
295 sysarg_t updated = 0;
296
297 fibril_mutex_lock(&cons->mtx);
298
299 switch (ch) {
300 case '\n':
[6d5e378]301 updated = chargrid_newline(cons->frontbuf);
[7c014d1]302 break;
303 case '\r':
304 break;
305 case '\t':
[6d5e378]306 updated = chargrid_tabstop(cons->frontbuf, 8);
[7c014d1]307 break;
308 case '\b':
[6d5e378]309 updated = chargrid_backspace(cons->frontbuf);
[7c014d1]310 break;
311 default:
[6d5e378]312 updated = chargrid_putchar(cons->frontbuf, ch, true);
[9f51afc]313 }
[7c014d1]314
315 fibril_mutex_unlock(&cons->mtx);
316
317 if (updated > 1)
318 cons_update(cons);
319}
320
[5d94b16c]321static void cons_set_cursor_vis(console_t *cons, bool visible)
[7c014d1]322{
323 fibril_mutex_lock(&cons->mtx);
[6d5e378]324 chargrid_set_cursor_visibility(cons->frontbuf, visible);
[7c014d1]325 fibril_mutex_unlock(&cons->mtx);
326
327 cons_update_cursor(cons);
328}
329
[5d94b16c]330static int cons_open(con_srvs_t *srvs, con_srv_t *srv)
[7c014d1]331{
[5d94b16c]332 return EOK;
[9f51afc]333}
334
[5d94b16c]335static int cons_close(con_srv_t *srv)
[d2cc7e1]336{
[5d94b16c]337 return EOK;
[424cd43]338}
339
[5d94b16c]340static int cons_read(con_srv_t *srv, void *buf, size_t size)
[424cd43]341{
[5d94b16c]342 uint8_t *bbuf = buf;
343 console_t *cons = srv_to_console(srv);
[424cd43]344 size_t pos = 0;
[e435537]345
[a58bc8b]346 /*
347 * Read input from keyboard and copy it to the buffer.
348 * We need to handle situation when wchar is split by 2 following
349 * reads.
350 */
[7c014d1]351 while (pos < size) {
[a58bc8b]352 /* Copy to the buffer remaining characters. */
353 while ((pos < size) && (cons->char_remains_len > 0)) {
[5d94b16c]354 bbuf[pos] = cons->char_remains[0];
[424cd43]355 pos++;
[e435537]356
[a58bc8b]357 /* Unshift the array. */
[e435537]358 for (size_t i = 1; i < cons->char_remains_len; i++)
[a58bc8b]359 cons->char_remains[i - 1] = cons->char_remains[i];
[e435537]360
[a58bc8b]361 cons->char_remains_len--;
362 }
[e435537]363
[a58bc8b]364 /* Still not enough? Then get another key from the queue. */
365 if (pos < size) {
366 link_t *link = prodcons_consume(&cons->input_pc);
367 kbd_event_t *event = list_get_instance(link, kbd_event_t, link);
[e435537]368
[a58bc8b]369 /* Accept key presses of printable chars only. */
370 if ((event->type == KEY_PRESS) && (event->c != 0)) {
371 wchar_t tmp[2] = { event->c, 0 };
372 wstr_to_str(cons->char_remains, UTF8_CHAR_BUFFER_SIZE, tmp);
373 cons->char_remains_len = str_size(cons->char_remains);
374 }
[e435537]375
[a58bc8b]376 free(event);
[424cd43]377 }
378 }
[5d94b16c]379
380 return size;
381}
382
383static int cons_write(con_srv_t *srv, void *data, size_t size)
384{
385 console_t *cons = srv_to_console(srv);
386
387 size_t off = 0;
388 while (off < size)
389 cons_write_char(cons, str_decode(data, &off, size));
390 return size;
391}
392
393static void cons_sync(con_srv_t *srv)
394{
395 console_t *cons = srv_to_console(srv);
[424cd43]396
[5d94b16c]397 cons_update(cons);
[424cd43]398}
399
[5d94b16c]400static void cons_clear(con_srv_t *srv)
[424cd43]401{
[5d94b16c]402 console_t *cons = srv_to_console(srv);
403
404 fibril_mutex_lock(&cons->mtx);
405 chargrid_clear(cons->frontbuf);
406 fibril_mutex_unlock(&cons->mtx);
407
408 cons_update(cons);
409}
410
411static void cons_set_pos(con_srv_t *srv, sysarg_t col, sysarg_t row)
412{
413 console_t *cons = srv_to_console(srv);
414
415 fibril_mutex_lock(&cons->mtx);
416 chargrid_set_cursor(cons->frontbuf, col, row);
417 fibril_mutex_unlock(&cons->mtx);
418
419 cons_update_cursor(cons);
420}
421
422static int cons_get_pos(con_srv_t *srv, sysarg_t *col, sysarg_t *row)
423{
424 console_t *cons = srv_to_console(srv);
425
426 fibril_mutex_lock(&cons->mtx);
427 chargrid_get_cursor(cons->frontbuf, col, row);
428 fibril_mutex_unlock(&cons->mtx);
429
430 return EOK;
431}
432
433static int cons_get_size(con_srv_t *srv, sysarg_t *cols, sysarg_t *rows)
434{
435 console_t *cons = srv_to_console(srv);
436
437 fibril_mutex_lock(&cons->mtx);
438 *cols = cons->cols;
439 *rows = cons->rows;
440 fibril_mutex_unlock(&cons->mtx);
441
442 return EOK;
443}
444
445static int cons_get_color_cap(con_srv_t *srv, console_caps_t *ccaps)
446{
447 console_t *cons = srv_to_console(srv);
448
449 fibril_mutex_lock(&cons->mtx);
450 *ccaps = cons->ccaps;
451 fibril_mutex_unlock(&cons->mtx);
452
453 return EOK;
454}
455
456static void cons_set_style(con_srv_t *srv, console_style_t style)
457{
458 console_t *cons = srv_to_console(srv);
459
[7c014d1]460 fibril_mutex_lock(&cons->mtx);
[6d5e378]461 chargrid_set_style(cons->frontbuf, style);
[7c014d1]462 fibril_mutex_unlock(&cons->mtx);
463}
464
[5d94b16c]465static void cons_set_color(con_srv_t *srv, console_color_t bgcolor,
[7c014d1]466 console_color_t fgcolor, console_color_attr_t attr)
467{
[5d94b16c]468 console_t *cons = srv_to_console(srv);
469
[7c014d1]470 fibril_mutex_lock(&cons->mtx);
[6d5e378]471 chargrid_set_color(cons->frontbuf, bgcolor, fgcolor, attr);
[7c014d1]472 fibril_mutex_unlock(&cons->mtx);
473}
474
[5d94b16c]475static void cons_set_rgb_color(con_srv_t *srv, pixel_t bgcolor,
[7c014d1]476 pixel_t fgcolor)
477{
[5d94b16c]478 console_t *cons = srv_to_console(srv);
479
[7c014d1]480 fibril_mutex_lock(&cons->mtx);
[6d5e378]481 chargrid_set_rgb_color(cons->frontbuf, bgcolor, fgcolor);
[7c014d1]482 fibril_mutex_unlock(&cons->mtx);
483}
484
[5d94b16c]485static void cons_set_cursor_visibility(con_srv_t *srv, bool visible)
486{
487 console_t *cons = srv_to_console(srv);
488
489 cons_set_cursor_vis(cons, visible);
490}
491
492static int cons_get_event(con_srv_t *srv, kbd_event_t *event)
[7c014d1]493{
[5d94b16c]494 console_t *cons = srv_to_console(srv);
[7c014d1]495 link_t *link = prodcons_consume(&cons->input_pc);
[5d94b16c]496 kbd_event_t *kevent = list_get_instance(link, kbd_event_t, link);
[9f1362d4]497
[5d94b16c]498 *event = *kevent;
499 free(kevent);
500 return EOK;
[d2cc7e1]501}
502
[9934f7d]503static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
[eaf34f7]504{
[424cd43]505 console_t *cons = NULL;
[3ad953c]506
[7c014d1]507 for (size_t i = 0; i < CONSOLE_COUNT; i++) {
[424cd43]508 if (i == KERNEL_CONSOLE)
509 continue;
510
[7c014d1]511 if (consoles[i].dsid == (service_id_t) IPC_GET_ARG1(*icall)) {
[424cd43]512 cons = &consoles[i];
513 break;
514 }
515 }
516
517 if (cons == NULL) {
[ffa2c8ef]518 async_answer_0(iid, ENOENT);
[eaf34f7]519 return;
520 }
[424cd43]521
[6d5e378]522 if (atomic_postinc(&cons->refcnt) == 0)
[5d94b16c]523 cons_set_cursor_vis(cons, true);
[3ad953c]524
[5d94b16c]525 con_conn(iid, icall, &cons->srvs);
[eaf34f7]526}
527
[5d94b16c]528
[111d2d6]529static int input_connect(const char *svc)
[eaf34f7]530{
[a40dea3]531 async_sess_t *sess;
[7c014d1]532 service_id_t dsid;
[9f1362d4]533
[7c014d1]534 int rc = loc_service_get_id(svc, &dsid, 0);
[111d2d6]535 if (rc != EOK) {
536 printf("%s: Input service %s not found\n", NAME, svc);
537 return rc;
538 }
539
540 sess = loc_service_connect(EXCHANGE_ATOMIC, dsid, 0);
541 if (sess == NULL) {
542 printf("%s: Unable to connect to input service %s\n", NAME,
543 svc);
544 return EIO;
545 }
[7c014d1]546
[111d2d6]547 rc = input_open(sess, &input_ev_ops, NULL, &input);
[700af62]548 if (rc != EOK) {
[a40dea3]549 async_hangup(sess);
[111d2d6]550 printf("%s: Unable to communicate with service %s (%s)\n",
[7c014d1]551 NAME, svc, str_error(rc));
[111d2d6]552 return rc;
[4904de8]553 }
[9f1362d4]554
[111d2d6]555 return EOK;
[700af62]556}
557
[7c014d1]558static void interrupt_received(ipc_callid_t callid, ipc_call_t *call)
559{
560 cons_switch(prev_console);
561}
562
[6d5e378]563static async_sess_t *output_connect(const char *svc)
[700af62]564{
[7c014d1]565 async_sess_t *sess;
566 service_id_t dsid;
567
568 int rc = loc_service_get_id(svc, &dsid, 0);
569 if (rc == EOK) {
570 sess = loc_service_connect(EXCHANGE_SERIALIZE, dsid, 0);
571 if (sess == NULL) {
[6d5e378]572 printf("%s: Unable to connect to output service %s\n",
[7c014d1]573 NAME, svc);
574 return NULL;
575 }
576 } else
577 return NULL;
578
579 return sess;
580}
581
[6d5e378]582static bool console_srv_init(char *input_svc, char *output_svc)
[7c014d1]583{
[111d2d6]584 int rc;
585
[7c014d1]586 /* Connect to input service */
[111d2d6]587 rc = input_connect(input_svc);
588 if (rc != EOK)
[700af62]589 return false;
[79ae36dd]590
[6d5e378]591 /* Connect to output service */
592 output_sess = output_connect(output_svc);
593 if (output_sess == NULL)
[79ae36dd]594 return false;
[9f1362d4]595
[15f3c3f]596 /* Register server */
[f302586]597 async_set_client_connection(client_connection);
[111d2d6]598 rc = loc_server_register(NAME);
[2f90b46]599 if (rc != EOK) {
[7c014d1]600 printf("%s: Unable to register server (%s)\n", NAME,
601 str_error(rc));
[424cd43]602 return false;
603 }
[516ff92]604
[6d5e378]605 output_get_dimensions(output_sess, &cols, &rows);
606 output_set_style(output_sess, STYLE_NORMAL);
[7c014d1]607
608 console_caps_t ccaps;
[6d5e378]609 output_get_caps(output_sess, &ccaps);
[3ad953c]610
[424cd43]611 /* Inititalize consoles */
[7c014d1]612 for (size_t i = 0; i < CONSOLE_COUNT; i++) {
613 consoles[i].index = i;
614 atomic_set(&consoles[i].refcnt, 0);
615 fibril_mutex_initialize(&consoles[i].mtx);
[d03da17]616 prodcons_initialize(&consoles[i].input_pc);
[a58bc8b]617 consoles[i].char_remains_len = 0;
[7c014d1]618
[6d5e378]619 if (i == KERNEL_CONSOLE)
[7c014d1]620 continue;
621
622 consoles[i].cols = cols;
623 consoles[i].rows = rows;
624 consoles[i].ccaps = ccaps;
625 consoles[i].frontbuf =
[6d5e378]626 chargrid_create(cols, rows, CHARGRID_FLAG_SHARED);
[7c014d1]627
628 if (consoles[i].frontbuf == NULL) {
629 printf("%s: Unable to allocate frontbuffer %zu\n", NAME, i);
630 return false;
631 }
632
[6d5e378]633 consoles[i].fbid = output_frontbuf_create(output_sess,
634 consoles[i].frontbuf);
[7c014d1]635 if (consoles[i].fbid == 0) {
636 printf("%s: Unable to create frontbuffer %zu\n", NAME, i);
637 return false;
638 }
639
[5d94b16c]640 con_srvs_init(&consoles[i].srvs);
641 consoles[i].srvs.ops = &con_ops;
642 consoles[i].srvs.sarg = &consoles[i];
643
[7c014d1]644 char vc[LOC_NAME_MAXLEN + 1];
645 snprintf(vc, LOC_NAME_MAXLEN, "%s/vc%zu", NAMESPACE, i);
646
647 if (loc_service_register(vc, &consoles[i].dsid) != EOK) {
648 printf("%s: Unable to register device %s\n", NAME, vc);
649 return false;
[424cd43]650 }
651 }
652
[6d5e378]653 cons_damage(active_console);
654
[3ad953c]655 /* Receive kernel notifications */
[007e6efa]656 async_set_interrupt_received(interrupt_received);
[7c014d1]657 rc = event_subscribe(EVENT_KCONSOLE, 0);
658 if (rc != EOK)
659 printf("%s: Failed to register kconsole notifications (%s)\n",
660 NAME, str_error(rc));
[1601f3c]661
[424cd43]662 return true;
663}
664
[6d5e378]665static void usage(char *name)
[47a350f]666{
[6d5e378]667 printf("Usage: %s <input_dev> <output_dev>\n", name);
[47a350f]668}
669
[424cd43]670int main(int argc, char *argv[])
671{
[7c014d1]672 if (argc < 3) {
[6d5e378]673 usage(argv[0]);
[47a350f]674 return -1;
675 }
676
[7c014d1]677 printf("%s: HelenOS Console service\n", NAME);
[424cd43]678
[7c014d1]679 if (!console_srv_init(argv[1], argv[2]))
[424cd43]680 return -1;
[79ae36dd]681
[7c014d1]682 printf("%s: Accepting connections\n", NAME);
683 task_retval(0);
[eaf34f7]684 async_manager();
[3ad953c]685
[6d5e378]686 /* Never reached */
[3ad953c]687 return 0;
[51c1b003]688}
[516ff92]689
[ce5bcb4]690/** @}
691 */
Note: See TracBrowser for help on using the repository browser.