source: mainline/uspace/srv/hid/console/console.c@ 1433ecda

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

Fix cstyle: make ccheck-fix and commit only files where all the changes are good.

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