source: mainline/uspace/srv/hid/console/console.c@ 1d2f85e

Last change on this file since 1d2f85e was 08e103d4, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

Use clearer naming for string length functions

This and the following commit change the names of functions, as well as
their documentation, to use unambiguous terms "bytes" and "code points"
instead of ambiguous terms "size", "length", and "characters".

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