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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since eb13ef8 was eb13ef8, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 6 years ago

Change IPC_GET_* and IPC_SET_* to accept pointer instead of lvalue

  • 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);
375 cons->char_remains_len = str_size(cons->char_remains);
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++) {
[eb13ef8]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.