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

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

Use errno_t in all uspace and kernel code.

Change type of every variable, parameter and return value that holds an
<errno.h> constant to either errno_t (the usual case), or sys_errno_t
(some places in kernel). This is for the purpose of self-documentation,
as well as for type-checking with a bit of type definition hackery.

Although this is a massive commit, it is a simple text replacement, and thus
is very easy to verify. Simply do the following:

`
git checkout <this commit's hash>
git reset HEAD
git add .
tools/srepl '\berrno_t\b' int
git add .
tools/srepl '\bsys_errno_t\b' sysarg_t
git reset
git diff
`

While this doesn't ensure that the replacements are correct, it does ensure
that the commit doesn't do anything except those replacements. Since errno_t
is typedef'd to int in the usual case (and sys_errno_t to sysarg_t), even if
incorrect, this commit cannot change behavior.

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