source: mainline/uspace/srv/hid/console/console.c@ beb9336

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

Factor out input protocol client code.

  • Property mode set to 100644
File size: 16.1 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/console.h>
40#include <ipc/vfs.h>
[51c1b003]41#include <errno.h>
[30db06c]42#include <str_error.h>
[15f3c3f]43#include <loc.h>
[7c014d1]44#include <event.h>
[111d2d6]45#include <io/kbd_event.h>
[7c014d1]46#include <io/keycode.h>
[6d5e378]47#include <io/chargrid.h>
48#include <io/console.h>
49#include <io/output.h>
[7c014d1]50#include <align.h>
51#include <malloc.h>
52#include <as.h>
[1e4cada]53#include <fibril_synch.h>
[9805cde]54#include "console.h"
[369a5f8]55
[1313ee9]56#define NAME "console"
57#define NAMESPACE "term"
[79ae36dd]58
[6d5e378]59#define UTF8_CHAR_BUFFER_SIZE (STR_BOUNDS(1) + 1)
[a58bc8b]60
[79460ae]61typedef struct {
[6d5e378]62 atomic_t refcnt; /**< Connection reference count */
63 prodcons_t input_pc; /**< Incoming keyboard events */
64
65 /**
66 * Not yet sent bytes of last char event.
67 */
68 char char_remains[UTF8_CHAR_BUFFER_SIZE];
69 size_t char_remains_len; /**< Number of not yet sent bytes. */
[7c014d1]70
[6d5e378]71 fibril_mutex_t mtx; /**< Lock protecting mutable fields */
[7c014d1]72
[6d5e378]73 size_t index; /**< Console index */
74 service_id_t dsid; /**< Service handle */
[7c014d1]75
[6d5e378]76 sysarg_t cols; /**< Number of columns */
77 sysarg_t rows; /**< Number of rows */
78 console_caps_t ccaps; /**< Console capabilities */
[7c014d1]79
[6d5e378]80 chargrid_t *frontbuf; /**< Front buffer */
81 frontbuf_handle_t fbid; /**< Front buffer handle */
[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
[7c014d1]116static void cons_update(console_t *cons)
[9805cde]117{
[7c014d1]118 fibril_mutex_lock(&switch_mtx);
119 fibril_mutex_lock(&cons->mtx);
120
121 if ((cons == active_console) && (active_console != kernel_console)) {
[6d5e378]122 output_update(output_sess, cons->fbid);
123 output_cursor_update(output_sess, cons->fbid);
[7c014d1]124 }
125
126 fibril_mutex_unlock(&cons->mtx);
127 fibril_mutex_unlock(&switch_mtx);
[9805cde]128}
129
[7c014d1]130static void cons_update_cursor(console_t *cons)
[9805cde]131{
[7c014d1]132 fibril_mutex_lock(&switch_mtx);
133 fibril_mutex_lock(&cons->mtx);
134
135 if ((cons == active_console) && (active_console != kernel_console))
[6d5e378]136 output_cursor_update(output_sess, cons->fbid);
[7c014d1]137
138 fibril_mutex_unlock(&cons->mtx);
139 fibril_mutex_unlock(&switch_mtx);
[429acb9]140}
141
[7c014d1]142static void cons_clear(console_t *cons)
[50cfa6c]143{
[7c014d1]144 fibril_mutex_lock(&cons->mtx);
[6d5e378]145 chargrid_clear(cons->frontbuf);
[7c014d1]146 fibril_mutex_unlock(&cons->mtx);
[9f1362d4]147
[7c014d1]148 cons_update(cons);
[50cfa6c]149}
150
[6d5e378]151static void cons_damage(console_t *cons)
[d2cc7e1]152{
[7c014d1]153 fibril_mutex_lock(&switch_mtx);
154 fibril_mutex_lock(&cons->mtx);
155
156 if ((cons == active_console) && (active_console != kernel_console)) {
[6d5e378]157 output_damage(output_sess, cons->fbid, 0, 0, cons->cols,
[7c014d1]158 cons->rows);
[6d5e378]159 output_cursor_update(output_sess, cons->fbid);
[dc033a1]160 }
[7c014d1]161
162 fibril_mutex_unlock(&cons->mtx);
163 fibril_mutex_unlock(&switch_mtx);
[d2cc7e1]164}
165
[7c014d1]166static void cons_switch(console_t *cons)
[d2cc7e1]167{
[7c014d1]168 fibril_mutex_lock(&switch_mtx);
169
170 if (cons == active_console) {
171 fibril_mutex_unlock(&switch_mtx);
172 return;
173 }
174
175 if (cons == kernel_console) {
[6d5e378]176 output_yield(output_sess);
[7c014d1]177 if (!console_kcon()) {
[6d5e378]178 output_claim(output_sess);
[7c014d1]179 fibril_mutex_unlock(&switch_mtx);
180 return;
181 }
[d2cc7e1]182 }
[7c014d1]183
184 if (active_console == kernel_console)
[6d5e378]185 output_claim(output_sess);
[7c014d1]186
187 prev_console = active_console;
188 active_console = cons;
189
190 fibril_mutex_unlock(&switch_mtx);
191
[6d5e378]192 cons_damage(cons);
[d2cc7e1]193}
194
[024fcc5]195static console_t *cons_get_active_uspace(void)
196{
197 fibril_mutex_lock(&switch_mtx);
[6d5e378]198
[024fcc5]199 console_t *active_uspace = active_console;
[6d5e378]200 if (active_uspace == kernel_console)
[024fcc5]201 active_uspace = prev_console;
[7c014d1]202
[6d5e378]203 assert(active_uspace != kernel_console);
[7c014d1]204
[6d5e378]205 fibril_mutex_unlock(&switch_mtx);
[7c014d1]206
[6d5e378]207 return active_uspace;
[429acb9]208}
[10569b1]209
[111d2d6]210static int input_ev_key(input_t *input, kbd_event_type_t type, keycode_t key,
211 keymod_t mods, wchar_t c)
[51c1b003]212{
[111d2d6]213 if ((key >= KC_F1) && (key < KC_F1 + CONSOLE_COUNT) &&
214 ((mods & KM_CTRL) == 0)) {
215 cons_switch(&consoles[key - KC_F1]);
216 } else {
217 /* Got key press/release event */
218 kbd_event_t *event =
219 (kbd_event_t *) malloc(sizeof(kbd_event_t));
220 if (event == NULL) {
221 return ENOMEM;
[79ae36dd]222 }
223
[111d2d6]224 link_initialize(&event->link);
225 event->type = type;
226 event->key = key;
227 event->mods = mods;
228 event->c = c;
[7c014d1]229
[111d2d6]230 /*
231 * Kernel console does not read events
232 * from us, so we will redirect them
233 * to the (last) active userspace console
234 * if necessary.
235 */
236 console_t *target_console = cons_get_active_uspace();
237
238 prodcons_produce(&target_console->input_pc,
239 &event->link);
[7c014d1]240 }
[111d2d6]241
242 return EOK;
243}
244
245static int input_ev_move(input_t *input, int dx, int dy)
246{
247 return EOK;
248}
249
250static int input_ev_abs_move(input_t *input, unsigned x , unsigned y,
251 unsigned max_x, unsigned max_y)
252{
253 return EOK;
254}
255
256static int input_ev_button(input_t *input, int bnum, int bpress)
257{
258 return EOK;
[7c014d1]259}
[1875a0c]260
[7c014d1]261/** Process a character from the client (TTY emulation). */
262static void cons_write_char(console_t *cons, wchar_t ch)
263{
264 sysarg_t updated = 0;
265
266 fibril_mutex_lock(&cons->mtx);
267
268 switch (ch) {
269 case '\n':
[6d5e378]270 updated = chargrid_newline(cons->frontbuf);
[7c014d1]271 break;
272 case '\r':
273 break;
274 case '\t':
[6d5e378]275 updated = chargrid_tabstop(cons->frontbuf, 8);
[7c014d1]276 break;
277 case '\b':
[6d5e378]278 updated = chargrid_backspace(cons->frontbuf);
[7c014d1]279 break;
280 default:
[6d5e378]281 updated = chargrid_putchar(cons->frontbuf, ch, true);
[9f51afc]282 }
[7c014d1]283
284 fibril_mutex_unlock(&cons->mtx);
285
286 if (updated > 1)
287 cons_update(cons);
288}
289
290static void cons_set_cursor(console_t *cons, sysarg_t col, sysarg_t row)
291{
292 fibril_mutex_lock(&cons->mtx);
[6d5e378]293 chargrid_set_cursor(cons->frontbuf, col, row);
[7c014d1]294 fibril_mutex_unlock(&cons->mtx);
295
296 cons_update_cursor(cons);
297}
298
299static void cons_set_cursor_visibility(console_t *cons, bool visible)
300{
301 fibril_mutex_lock(&cons->mtx);
[6d5e378]302 chargrid_set_cursor_visibility(cons->frontbuf, visible);
[7c014d1]303 fibril_mutex_unlock(&cons->mtx);
304
305 cons_update_cursor(cons);
306}
307
308static void cons_get_cursor(console_t *cons, ipc_callid_t iid, ipc_call_t *icall)
309{
310 sysarg_t col;
311 sysarg_t row;
312
313 fibril_mutex_lock(&cons->mtx);
[6d5e378]314 chargrid_get_cursor(cons->frontbuf, &col, &row);
[7c014d1]315 fibril_mutex_unlock(&cons->mtx);
316
317 async_answer_2(iid, EOK, col, row);
[9f51afc]318}
319
[7c014d1]320static void cons_write(console_t *cons, ipc_callid_t iid, ipc_call_t *icall)
[d2cc7e1]321{
[472c09d]322 void *buf;
[171f9a1]323 size_t size;
[eda925a]324 int rc = async_data_write_accept(&buf, false, 0, 0, 0, &size);
[1601f3c]325
[472c09d]326 if (rc != EOK) {
[7c014d1]327 async_answer_0(iid, rc);
[424cd43]328 return;
329 }
[1601f3c]330
[424cd43]331 size_t off = 0;
[7c014d1]332 while (off < size)
333 cons_write_char(cons, str_decode(buf, &off, size));
[424cd43]334
[7c014d1]335 async_answer_1(iid, EOK, size);
[424cd43]336 free(buf);
337}
338
[7c014d1]339static void cons_read(console_t *cons, ipc_callid_t iid, ipc_call_t *icall)
[424cd43]340{
341 ipc_callid_t callid;
342 size_t size;
[0da4e41]343 if (!async_data_read_receive(&callid, &size)) {
[ffa2c8ef]344 async_answer_0(callid, EINVAL);
[7c014d1]345 async_answer_0(iid, EINVAL);
[424cd43]346 return;
347 }
348
349 char *buf = (char *) malloc(size);
350 if (buf == NULL) {
[ffa2c8ef]351 async_answer_0(callid, ENOMEM);
[7c014d1]352 async_answer_0(iid, ENOMEM);
[424cd43]353 return;
354 }
355
356 size_t pos = 0;
[e435537]357
[a58bc8b]358 /*
359 * Read input from keyboard and copy it to the buffer.
360 * We need to handle situation when wchar is split by 2 following
361 * reads.
362 */
[7c014d1]363 while (pos < size) {
[a58bc8b]364 /* Copy to the buffer remaining characters. */
365 while ((pos < size) && (cons->char_remains_len > 0)) {
366 buf[pos] = cons->char_remains[0];
[424cd43]367 pos++;
[e435537]368
[a58bc8b]369 /* Unshift the array. */
[e435537]370 for (size_t i = 1; i < cons->char_remains_len; i++)
[a58bc8b]371 cons->char_remains[i - 1] = cons->char_remains[i];
[e435537]372
[a58bc8b]373 cons->char_remains_len--;
374 }
[e435537]375
[a58bc8b]376 /* Still not enough? Then get another key from the queue. */
377 if (pos < size) {
378 link_t *link = prodcons_consume(&cons->input_pc);
379 kbd_event_t *event = list_get_instance(link, kbd_event_t, link);
[e435537]380
[a58bc8b]381 /* Accept key presses of printable chars only. */
382 if ((event->type == KEY_PRESS) && (event->c != 0)) {
383 wchar_t tmp[2] = { event->c, 0 };
384 wstr_to_str(cons->char_remains, UTF8_CHAR_BUFFER_SIZE, tmp);
385 cons->char_remains_len = str_size(cons->char_remains);
386 }
[e435537]387
[a58bc8b]388 free(event);
[424cd43]389 }
390 }
391
[7c014d1]392 (void) async_data_read_finalize(callid, buf, size);
393 async_answer_1(iid, EOK, size);
394 free(buf);
[424cd43]395}
396
[7c014d1]397static void cons_set_style(console_t *cons, console_style_t style)
[424cd43]398{
[7c014d1]399 fibril_mutex_lock(&cons->mtx);
[6d5e378]400 chargrid_set_style(cons->frontbuf, style);
[7c014d1]401 fibril_mutex_unlock(&cons->mtx);
402}
403
404static void cons_set_color(console_t *cons, console_color_t bgcolor,
405 console_color_t fgcolor, console_color_attr_t attr)
406{
407 fibril_mutex_lock(&cons->mtx);
[6d5e378]408 chargrid_set_color(cons->frontbuf, bgcolor, fgcolor, attr);
[7c014d1]409 fibril_mutex_unlock(&cons->mtx);
410}
411
412static void cons_set_rgb_color(console_t *cons, pixel_t bgcolor,
413 pixel_t fgcolor)
414{
415 fibril_mutex_lock(&cons->mtx);
[6d5e378]416 chargrid_set_rgb_color(cons->frontbuf, bgcolor, fgcolor);
[7c014d1]417 fibril_mutex_unlock(&cons->mtx);
418}
419
420static void cons_get_event(console_t *cons, ipc_callid_t iid, ipc_call_t *icall)
421{
422 link_t *link = prodcons_consume(&cons->input_pc);
423 kbd_event_t *event = list_get_instance(link, kbd_event_t, link);
[9f1362d4]424
[7c014d1]425 async_answer_4(iid, EOK, event->type, event->key, event->mods, event->c);
426 free(event);
[d2cc7e1]427}
428
[9934f7d]429static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
[eaf34f7]430{
[424cd43]431 console_t *cons = NULL;
[3ad953c]432
[7c014d1]433 for (size_t i = 0; i < CONSOLE_COUNT; i++) {
[424cd43]434 if (i == KERNEL_CONSOLE)
435 continue;
436
[7c014d1]437 if (consoles[i].dsid == (service_id_t) IPC_GET_ARG1(*icall)) {
[424cd43]438 cons = &consoles[i];
439 break;
440 }
441 }
442
443 if (cons == NULL) {
[ffa2c8ef]444 async_answer_0(iid, ENOENT);
[eaf34f7]445 return;
446 }
[424cd43]447
[6d5e378]448 if (atomic_postinc(&cons->refcnt) == 0)
[7c014d1]449 cons_set_cursor_visibility(cons, true);
[10569b1]450
[eaf34f7]451 /* Accept the connection */
[ffa2c8ef]452 async_answer_0(iid, EOK);
[3ad953c]453
[1601f3c]454 while (true) {
[7c014d1]455 ipc_call_t call;
456 ipc_callid_t callid = async_get_call(&call);
[1601f3c]457
[6d5e378]458 if (!IPC_GET_IMETHOD(call))
[eaf34f7]459 return;
[79ae36dd]460
461 switch (IPC_GET_IMETHOD(call)) {
[4198f9c3]462 case VFS_OUT_READ:
[424cd43]463 cons_read(cons, callid, &call);
[7c014d1]464 break;
[4198f9c3]465 case VFS_OUT_WRITE:
[424cd43]466 cons_write(cons, callid, &call);
[7c014d1]467 break;
[4198f9c3]468 case VFS_OUT_SYNC:
[7c014d1]469 cons_update(cons);
470 async_answer_0(callid, EOK);
[424cd43]471 break;
[ad123964]472 case CONSOLE_CLEAR:
[7c014d1]473 cons_clear(cons);
474 async_answer_0(callid, EOK);
[eaf34f7]475 break;
[ad123964]476 case CONSOLE_GOTO:
[7c014d1]477 cons_set_cursor(cons, IPC_GET_ARG1(call), IPC_GET_ARG2(call));
478 async_answer_0(callid, EOK);
[ad123964]479 break;
[19528516]480 case CONSOLE_GET_POS:
[7c014d1]481 cons_get_cursor(cons, callid, &call);
[19528516]482 break;
[424cd43]483 case CONSOLE_GET_SIZE:
[7c014d1]484 async_answer_2(callid, EOK, cons->cols, cons->rows);
[a9bd960c]485 break;
[50cfa6c]486 case CONSOLE_GET_COLOR_CAP:
[7c014d1]487 async_answer_1(callid, EOK, cons->ccaps);
[50cfa6c]488 break;
[a9bd960c]489 case CONSOLE_SET_STYLE:
[7c014d1]490 cons_set_style(cons, IPC_GET_ARG1(call));
491 async_answer_0(callid, EOK);
[9805cde]492 break;
493 case CONSOLE_SET_COLOR:
[7c014d1]494 cons_set_color(cons, IPC_GET_ARG1(call), IPC_GET_ARG2(call),
495 IPC_GET_ARG3(call));
496 async_answer_0(callid, EOK);
[9805cde]497 break;
498 case CONSOLE_SET_RGB_COLOR:
[7c014d1]499 cons_set_rgb_color(cons, IPC_GET_ARG1(call), IPC_GET_ARG2(call));
500 async_answer_0(callid, EOK);
[0c6984e]501 break;
[a8b2b5b2]502 case CONSOLE_CURSOR_VISIBILITY:
[7c014d1]503 cons_set_cursor_visibility(cons, IPC_GET_ARG1(call));
504 async_answer_0(callid, EOK);
[a8b2b5b2]505 break;
[424cd43]506 case CONSOLE_GET_EVENT:
507 cons_get_event(cons, callid, &call);
[7c014d1]508 break;
509 default:
510 async_answer_0(callid, EINVAL);
[eaf34f7]511 }
512 }
513}
514
[111d2d6]515static int input_connect(const char *svc)
[eaf34f7]516{
[a40dea3]517 async_sess_t *sess;
[7c014d1]518 service_id_t dsid;
[9f1362d4]519
[7c014d1]520 int rc = loc_service_get_id(svc, &dsid, 0);
[111d2d6]521 if (rc != EOK) {
522 printf("%s: Input service %s not found\n", NAME, svc);
523 return rc;
524 }
525
526 sess = loc_service_connect(EXCHANGE_ATOMIC, dsid, 0);
527 if (sess == NULL) {
528 printf("%s: Unable to connect to input service %s\n", NAME,
529 svc);
530 return EIO;
531 }
[7c014d1]532
[111d2d6]533 rc = input_open(sess, &input_ev_ops, NULL, &input);
[700af62]534 if (rc != EOK) {
[a40dea3]535 async_hangup(sess);
[111d2d6]536 printf("%s: Unable to communicate with service %s (%s)\n",
[7c014d1]537 NAME, svc, str_error(rc));
[111d2d6]538 return rc;
[4904de8]539 }
[9f1362d4]540
[111d2d6]541 return EOK;
[700af62]542}
543
[7c014d1]544static void interrupt_received(ipc_callid_t callid, ipc_call_t *call)
545{
546 cons_switch(prev_console);
547}
548
[6d5e378]549static async_sess_t *output_connect(const char *svc)
[700af62]550{
[7c014d1]551 async_sess_t *sess;
552 service_id_t dsid;
553
554 int rc = loc_service_get_id(svc, &dsid, 0);
555 if (rc == EOK) {
556 sess = loc_service_connect(EXCHANGE_SERIALIZE, dsid, 0);
557 if (sess == NULL) {
[6d5e378]558 printf("%s: Unable to connect to output service %s\n",
[7c014d1]559 NAME, svc);
560 return NULL;
561 }
562 } else
563 return NULL;
564
565 return sess;
566}
567
[6d5e378]568static bool console_srv_init(char *input_svc, char *output_svc)
[7c014d1]569{
[111d2d6]570 int rc;
571
[7c014d1]572 /* Connect to input service */
[111d2d6]573 rc = input_connect(input_svc);
574 if (rc != EOK)
[700af62]575 return false;
[79ae36dd]576
[6d5e378]577 /* Connect to output service */
578 output_sess = output_connect(output_svc);
579 if (output_sess == NULL)
[79ae36dd]580 return false;
[9f1362d4]581
[15f3c3f]582 /* Register server */
[f302586]583 async_set_client_connection(client_connection);
[111d2d6]584 rc = loc_server_register(NAME);
[2f90b46]585 if (rc != EOK) {
[7c014d1]586 printf("%s: Unable to register server (%s)\n", NAME,
587 str_error(rc));
[424cd43]588 return false;
589 }
[516ff92]590
[6d5e378]591 output_get_dimensions(output_sess, &cols, &rows);
592 output_set_style(output_sess, STYLE_NORMAL);
[7c014d1]593
594 console_caps_t ccaps;
[6d5e378]595 output_get_caps(output_sess, &ccaps);
[3ad953c]596
[424cd43]597 /* Inititalize consoles */
[7c014d1]598 for (size_t i = 0; i < CONSOLE_COUNT; i++) {
599 consoles[i].index = i;
600 atomic_set(&consoles[i].refcnt, 0);
601 fibril_mutex_initialize(&consoles[i].mtx);
[d03da17]602 prodcons_initialize(&consoles[i].input_pc);
[a58bc8b]603 consoles[i].char_remains_len = 0;
[7c014d1]604
[6d5e378]605 if (i == KERNEL_CONSOLE)
[7c014d1]606 continue;
607
608 consoles[i].cols = cols;
609 consoles[i].rows = rows;
610 consoles[i].ccaps = ccaps;
611 consoles[i].frontbuf =
[6d5e378]612 chargrid_create(cols, rows, CHARGRID_FLAG_SHARED);
[7c014d1]613
614 if (consoles[i].frontbuf == NULL) {
615 printf("%s: Unable to allocate frontbuffer %zu\n", NAME, i);
616 return false;
617 }
618
[6d5e378]619 consoles[i].fbid = output_frontbuf_create(output_sess,
620 consoles[i].frontbuf);
[7c014d1]621 if (consoles[i].fbid == 0) {
622 printf("%s: Unable to create frontbuffer %zu\n", NAME, i);
623 return false;
624 }
625
626 char vc[LOC_NAME_MAXLEN + 1];
627 snprintf(vc, LOC_NAME_MAXLEN, "%s/vc%zu", NAMESPACE, i);
628
629 if (loc_service_register(vc, &consoles[i].dsid) != EOK) {
630 printf("%s: Unable to register device %s\n", NAME, vc);
631 return false;
[424cd43]632 }
633 }
634
[6d5e378]635 cons_damage(active_console);
636
[3ad953c]637 /* Receive kernel notifications */
[007e6efa]638 async_set_interrupt_received(interrupt_received);
[7c014d1]639 rc = event_subscribe(EVENT_KCONSOLE, 0);
640 if (rc != EOK)
641 printf("%s: Failed to register kconsole notifications (%s)\n",
642 NAME, str_error(rc));
[1601f3c]643
[424cd43]644 return true;
645}
646
[6d5e378]647static void usage(char *name)
[47a350f]648{
[6d5e378]649 printf("Usage: %s <input_dev> <output_dev>\n", name);
[47a350f]650}
651
[424cd43]652int main(int argc, char *argv[])
653{
[7c014d1]654 if (argc < 3) {
[6d5e378]655 usage(argv[0]);
[47a350f]656 return -1;
657 }
658
[7c014d1]659 printf("%s: HelenOS Console service\n", NAME);
[424cd43]660
[7c014d1]661 if (!console_srv_init(argv[1], argv[2]))
[424cd43]662 return -1;
[79ae36dd]663
[7c014d1]664 printf("%s: Accepting connections\n", NAME);
665 task_retval(0);
[eaf34f7]666 async_manager();
[3ad953c]667
[6d5e378]668 /* Never reached */
[3ad953c]669 return 0;
[51c1b003]670}
[516ff92]671
[ce5bcb4]672/** @}
673 */
Note: See TracBrowser for help on using the repository browser.