source: mainline/uspace/srv/console/console.c@ d2cc7e1

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since d2cc7e1 was d2cc7e1, checked in by Jiri Svoboda <jirik.svoboda@…>, 16 years ago

Buffer console output with line granularity. Makes esp. msim/ski console faster. EGA-fb needs fixing.

  • Property mode set to 100644
File size: 17.5 KB
RevLine 
[51c1b003]1/*
[df4ed85]2 * Copyright (c) 2006 Josef Cejka
[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
[ce5bcb4]30 * @{
31 */
32/** @file
33 */
34
[3209923]35#include <libc.h>
[79460ae]36#include <fb.h>
[51c1b003]37#include <ipc/ipc.h>
[24ff4df]38#include <kbd.h>
[f89979b]39#include <kbd/keycode.h>
[79460ae]40#include <ipc/fb.h>
[51c1b003]41#include <ipc/services.h>
42#include <errno.h>
[79460ae]43#include <key_buffer.h>
[d3e6935]44#include <ipc/console.h>
[eaf34f7]45#include <unistd.h>
46#include <async.h>
[cf28036c]47#include <libadt/fifo.h>
[3993b3d]48#include <screenbuffer.h>
[2def788]49#include <sys/mman.h>
[271b540]50#include <stdio.h>
[3ad953c]51#include <sysinfo.h>
[79460ae]52
[9805cde]53#include "console.h"
[e1c4849]54#include "gcons.h"
55
[cf28036c]56#define MAX_KEYREQUESTS_BUFFERED 32
[51c1b003]57
[271b540]58#define NAME "console"
[51c1b003]59
[e87e18f]60/** Index of currently used virtual console.
61 */
[390a678]62int active_console = 0;
[3ad953c]63int prev_console = 0;
[eaf34f7]64
[e87e18f]65/** Information about framebuffer
66 */
[3993b3d]67struct {
68 int phone; /**< Framebuffer phone */
[bb51e9a8]69 ipcarg_t rows; /**< Framebuffer rows */
70 ipcarg_t cols; /**< Framebuffer columns */
[3993b3d]71} fb_info;
72
[79460ae]73typedef struct {
[e87e18f]74 keybuffer_t keybuffer; /**< Buffer for incoming keys. */
[00bb6965]75 /** Buffer for unsatisfied request for keys. */
76 FIFO_CREATE_STATIC(keyrequests, ipc_callid_t,
77 MAX_KEYREQUESTS_BUFFERED);
[e87e18f]78 int keyrequest_counter; /**< Number of requests in buffer. */
79 int client_phone; /**< Phone to connected client. */
[00bb6965]80 int used; /**< 1 if this virtual console is
81 * connected to some client.*/
82 screenbuffer_t screenbuffer; /**< Screenbuffer for saving screen
83 * contents and related settings. */
[79460ae]84} connection_t;
85
[00bb6965]86static connection_t connections[CONSOLE_COUNT]; /**< Array of data for virtual
87 * consoles */
88static keyfield_t *interbuffer = NULL; /**< Pointer to memory shared
89 * with framebufer used for
90 * faster virtual console
[c738d65]91 * switching */
[d2cc7e1]92/** Size of fb_buf. */
93#define FB_BUF_SIZE 256
94
95/** Buffer for sending characters to FB driver. */
96static char fb_buf[FB_BUF_SIZE];
97
98/* Properties of fb_buf data. */
99static int fb_buf_row; /**< Row where fb_buf data belong. */
100static int fb_buf_col; /**< Column where fb_buf data start. */
101static int fb_console; /**< VC to which fb_buf data belong. */
102int fb_bi = 0; /**< Number of valid chars in fb_buf. */
103
104/** Size of cwrite_buf. */
105#define CWRITE_BUF_SIZE 256
106
107/** Buffer for receiving data via the CONSOLE_WRITE call from the client. */
108static char cwrite_buf[CWRITE_BUF_SIZE];
[429acb9]109
[bb51e9a8]110
[e87e18f]111/** Find unused virtual console.
112 *
113 */
[d32af35]114static int find_free_connection(void)
[79460ae]115{
[c738d65]116 int i;
[79460ae]117
[c738d65]118 for (i = 0; i < CONSOLE_COUNT; i++) {
[d32af35]119 if (!connections[i].used)
[79460ae]120 return i;
121 }
[d32af35]122 return -1;
[79460ae]123}
124
[429acb9]125static void clrscr(void)
126{
[0cc4313]127 async_msg_0(fb_info.phone, FB_CLEAR);
[429acb9]128}
129
[8c6337d]130static void curs_visibility(bool visible)
[429acb9]131{
[8c6337d]132 async_msg_1(fb_info.phone, FB_CURSOR_VISIBILITY, visible);
133}
134
135static void curs_hide_sync(void)
136{
137 ipc_call_sync_1_0(fb_info.phone, FB_CURSOR_VISIBILITY, false);
[429acb9]138}
139
140static void curs_goto(int row, int col)
141{
[085bd54]142 async_msg_2(fb_info.phone, FB_CURSOR_GOTO, row, col);
[429acb9]143}
144
[9805cde]145static void set_style(int style)
[429acb9]146{
[9805cde]147 async_msg_1(fb_info.phone, FB_SET_STYLE, style);
[429acb9]148}
149
[9805cde]150static void set_color(int fgcolor, int bgcolor, int flags)
[429acb9]151{
[9805cde]152 async_msg_3(fb_info.phone, FB_SET_COLOR, fgcolor, bgcolor, flags);
153}
154
155static void set_rgb_color(int fgcolor, int bgcolor)
156{
157 async_msg_2(fb_info.phone, FB_SET_RGB_COLOR, fgcolor, bgcolor);
158}
159
160static void set_attrs(attrs_t *attrs)
161{
162 switch (attrs->t) {
163 case at_style:
164 set_style(attrs->a.s.style);
165 break;
166
167 case at_idx:
168 set_color(attrs->a.i.fg_color, attrs->a.i.bg_color,
169 attrs->a.i.flags);
170 break;
171
172 case at_rgb:
173 set_rgb_color(attrs->a.r.fg_color, attrs->a.r.bg_color);
174 break;
175 }
[429acb9]176}
177
[d2cc7e1]178/** Write a character vector to FB driver via IPC. */
179static ssize_t fb_write(const char *buf, size_t nbyte, int row, int col)
180{
181 ipcarg_t rc;
182 ipc_call_t answer;
183 aid_t req;
184
185 async_serialize_start();
186
187 req = async_send_2(fb_info.phone, FB_WRITE, row, col, &answer);
188 rc = ipc_data_write_start(fb_info.phone, (void *) buf, nbyte);
189
190 if (rc != EOK) {
191 async_wait_for(req, NULL);
192 async_serialize_end();
193 return (ssize_t) rc;
194 }
195
196 async_wait_for(req, &rc);
197 async_serialize_end();
198
199 if (rc == EOK)
200 return (ssize_t) IPC_GET_ARG1(answer);
201 else
202 return -1;
203}
204
205/** Flush buffered characters to FB. */
206static void fb_buf_flush(void)
207{
208 screenbuffer_t *scr;
209 int i;
210
211 scr = &(connections[fb_console].screenbuffer);
212
213 if (fb_bi > 0) {
214 if (fb_write(fb_buf, fb_bi, fb_buf_row, fb_buf_col) < 0) {
215 /* Try falling back to char-by-char. */
216 for (i = 0; i < fb_bi; i++) {
217 async_msg_3(fb_info.phone, FB_PUTCHAR, fb_buf[i],
218 fb_buf_row, fb_buf_col + i);
219 }
220 }
221 fb_bi = 0;
222 }
223}
224
225/** Print a character to the active VC with buffering. */
[429acb9]226static void prtchr(char c, int row, int col)
227{
[d2cc7e1]228 if (fb_bi >= FB_BUF_SIZE)
229 fb_buf_flush();
230
231 if (fb_bi == 0) {
232 fb_buf_row = row;
233 fb_buf_col = col;
234 fb_console = active_console;
235 }
236
237 fb_buf[fb_bi++] = c;
[429acb9]238}
239
[10569b1]240/** Check key and process special keys.
241 *
[96858e8]242 *
243 */
[10569b1]244static void write_char(int console, char key)
245{
[d2cc7e1]246 bool flush_cursor = false;
[10569b1]247 screenbuffer_t *scr = &(connections[console].screenbuffer);
[d2cc7e1]248
[10569b1]249 switch (key) {
[00bb6965]250 case '\n':
[d2cc7e1]251 fb_buf_flush();
252 flush_cursor = true;
[c738d65]253 scr->position_y++;
254 scr->position_x = 0;
[00bb6965]255 break;
256 case '\r':
[d2cc7e1]257 fb_buf_flush();
[00bb6965]258 break;
259 case '\t':
[d2cc7e1]260 fb_buf_flush();
[00bb6965]261 scr->position_x += 8;
262 scr->position_x -= scr->position_x % 8;
263 break;
264 case '\b':
[d2cc7e1]265 fb_buf_flush();
[00bb6965]266 if (scr->position_x == 0)
[10569b1]267 break;
[00bb6965]268 scr->position_x--;
269 if (console == active_console)
270 prtchr(' ', scr->position_y, scr->position_x);
271 screenbuffer_putchar(scr, ' ');
272 break;
273 default:
274 if (console == active_console)
275 prtchr(key, scr->position_y, scr->position_x);
[10569b1]276
[00bb6965]277 screenbuffer_putchar(scr, key);
278 scr->position_x++;
[10569b1]279 }
[d2cc7e1]280
281 if (scr->position_x >= scr->size_x) {
282 fb_buf_flush();
283 flush_cursor = true;
284 scr->position_y++;
285 }
[10569b1]286
287 if (scr->position_y >= scr->size_y) {
288 scr->position_y = scr->size_y - 1;
[c891ed39]289 screenbuffer_clear_line(scr, scr->top_line);
[c738d65]290 scr->top_line = (scr->top_line + 1) % scr->size_y;
[b1f51f0]291 if (console == active_console)
[0cc4313]292 async_msg_1(fb_info.phone, FB_SCROLL, 1);
[10569b1]293 }
[d2cc7e1]294
[10569b1]295 scr->position_x = scr->position_x % scr->size_x;
[d2cc7e1]296
297 if (console == active_console && flush_cursor)
[429acb9]298 curs_goto(scr->position_y, scr->position_x);
[10569b1]299}
300
[429acb9]301/** Switch to new console */
302static void change_console(int newcons)
303{
304 connection_t *conn;
[bd02038]305 int i, j, rc;
[6d5005c]306 keyfield_t *field;
[9805cde]307 attrs_t *attrs;
[76fca31]308
[429acb9]309 if (newcons == active_console)
310 return;
[d2cc7e1]311
312 fb_buf_flush();
313
[a7d2d78]314 if (newcons == KERNEL_CONSOLE) {
[1f83244]315 async_serialize_start();
[8c6337d]316 curs_hide_sync();
[76fca31]317 gcons_in_kernel();
[1f83244]318 async_serialize_end();
[76fca31]319
[3ad953c]320 if (__SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE)) {
321 prev_console = active_console;
[76fca31]322 active_console = KERNEL_CONSOLE;
[3ad953c]323 } else
[8c6337d]324 newcons = active_console;
[01f5e17]325 }
[6d5005c]326
[76fca31]327 if (newcons != KERNEL_CONSOLE) {
328 async_serialize_start();
329
330 if (active_console == KERNEL_CONSOLE)
331 gcons_redraw_console();
332
333 active_console = newcons;
334 gcons_change_console(newcons);
335 conn = &connections[active_console];
336
[9805cde]337 set_attrs(&conn->screenbuffer.attrs);
[8c6337d]338 curs_visibility(false);
[76fca31]339 if (interbuffer) {
340 for (i = 0; i < conn->screenbuffer.size_x; i++)
341 for (j = 0; j < conn->screenbuffer.size_y; j++) {
342 unsigned int size_x;
343
344 size_x = conn->screenbuffer.size_x;
345 interbuffer[i + j * size_x] =
346 *get_field_at(&conn->screenbuffer, i, j);
347 }
348 /* This call can preempt, but we are already at the end */
[3ad953c]349 rc = async_req_0_0(fb_info.phone, FB_DRAW_TEXT_DATA);
[76fca31]350 }
351
352 if ((!interbuffer) || (rc != 0)) {
[9805cde]353 set_attrs(&conn->screenbuffer.attrs);
[76fca31]354 clrscr();
[9805cde]355 attrs = &conn->screenbuffer.attrs;
[76fca31]356
[3ad953c]357 for (j = 0; j < conn->screenbuffer.size_y; j++)
[76fca31]358 for (i = 0; i < conn->screenbuffer.size_x; i++) {
359 field = get_field_at(&conn->screenbuffer, i, j);
[9805cde]360 if (!attrs_same(*attrs, field->attrs))
361 set_attrs(&field->attrs);
362 attrs = &field->attrs;
[76fca31]363 if ((field->character == ' ') &&
[9805cde]364 (attrs_same(field->attrs,
365 conn->screenbuffer.attrs)))
[76fca31]366 continue;
[9805cde]367
[76fca31]368 prtchr(field->character, j, i);
369 }
370 }
371
372 curs_goto(conn->screenbuffer.position_y,
373 conn->screenbuffer.position_x);
374 curs_visibility(conn->screenbuffer.is_cursor_visible);
375
376 async_serialize_end();
[429acb9]377 }
378}
[10569b1]379
[e87e18f]380/** Handler for keyboard */
[eaf34f7]381static void keyboard_events(ipc_callid_t iid, ipc_call_t *icall)
[51c1b003]382{
[eaf34f7]383 ipc_callid_t callid;
[51c1b003]384 ipc_call_t call;
[eaf34f7]385 int retval;
[fa09449]386 kbd_event_t ev;
[c1d2c9d]387 connection_t *conn;
[1f83244]388 int newcon;
[bb51e9a8]389
[eaf34f7]390 /* Ignore parameters, the connection is alread opened */
391 while (1) {
392 callid = async_get_call(&call);
393 switch (IPC_GET_METHOD(call)) {
394 case IPC_M_PHONE_HUNGUP:
395 /* TODO: Handle hangup */
396 return;
[1f83244]397 case KBD_MS_LEFT:
398 newcon = gcons_mouse_btn(IPC_GET_ARG1(call));
399 if (newcon != -1)
400 change_console(newcon);
[501a8ba]401 retval = 0;
[1f83244]402 break;
[830ac99]403 case KBD_MS_MOVE:
[00bb6965]404 gcons_mouse_move(IPC_GET_ARG1(call),
[01f5e17]405 IPC_GET_ARG2(call));
[501a8ba]406 retval = 0;
[830ac99]407 break;
[fa09449]408 case KBD_EVENT:
409 /* Got event from keyboard driver. */
[eaf34f7]410 retval = 0;
[fa09449]411 ev.type = IPC_GET_ARG1(call);
412 ev.key = IPC_GET_ARG2(call);
413 ev.mods = IPC_GET_ARG3(call);
414 ev.c = IPC_GET_ARG4(call);
415
[eaf34f7]416 /* switch to another virtual console */
[cf28036c]417
[c1d2c9d]418 conn = &connections[active_console];
[fa09449]419
[f89979b]420 if ((ev.key >= KC_F1) && (ev.key < KC_F1 +
[fa09449]421 CONSOLE_COUNT)) {
[f89979b]422 if (ev.key == KC_F12)
[a7d2d78]423 change_console(KERNEL_CONSOLE);
[429acb9]424 else
[f89979b]425 change_console(ev.key - KC_F1);
[eaf34f7]426 break;
427 }
[cf28036c]428
429 /* if client is awaiting key, send it */
[c1d2c9d]430 if (conn->keyrequest_counter > 0) {
431 conn->keyrequest_counter--;
[fa09449]432 ipc_answer_4(fifo_pop(conn->keyrequests), EOK,
433 ev.type, ev.key, ev.mods, ev.c);
[cf28036c]434 break;
435 }
[fa09449]436
437 keybuffer_push(&conn->keybuffer, &ev);
[501a8ba]438 retval = 0;
[fa09449]439
[eaf34f7]440 break;
441 default:
[1029d3d3]442 retval = ENOENT;
[085bd54]443 }
[b74959bd]444 ipc_answer_0(callid, retval);
[eaf34f7]445 }
446}
447
[d2cc7e1]448/** Handle CONSOLE_WRITE call. */
449static void cons_write(int consnum, ipc_callid_t rid, ipc_call_t *request)
450{
451 ipc_callid_t callid;
452 size_t len;
453 size_t i;
454
455 if (!ipc_data_write_receive(&callid, &len)) {
456 ipc_answer_0(callid, EINVAL);
457 ipc_answer_0(rid, EINVAL);
458 }
459
460 if (len > CWRITE_BUF_SIZE)
461 len = CWRITE_BUF_SIZE;
462
463 (void) ipc_data_write_finalize(callid, cwrite_buf, len);
464
465 for (i = 0; i < len; i++) {
466 write_char(consnum, cwrite_buf[i]);
467 }
468
469 gcons_notify_char(consnum);
470 ipc_answer_1(rid, EOK, len);
471}
472
[eaf34f7]473/** Default thread for new connections */
[b1f51f0]474static void client_connection(ipc_callid_t iid, ipc_call_t *icall)
[eaf34f7]475{
[51c1b003]476 ipc_callid_t callid;
[eaf34f7]477 ipc_call_t call;
478 int consnum;
[fa09449]479 ipcarg_t arg1, arg2, arg3, arg4;
[e9073f2]480 connection_t *conn;
[3ad953c]481
[d32af35]482 if ((consnum = find_free_connection()) == -1) {
[b74959bd]483 ipc_answer_0(iid, ELIMIT);
[eaf34f7]484 return;
485 }
[e9073f2]486 conn = &connections[consnum];
[085bd54]487 conn->used = 1;
[a7d2d78]488
[085bd54]489 async_serialize_start();
[a7d2d78]490 gcons_notify_connect(consnum);
[38c706cc]491 conn->client_phone = IPC_GET_ARG5(*icall);
[e9073f2]492 screenbuffer_clear(&conn->screenbuffer);
[10569b1]493
[eaf34f7]494 /* Accept the connection */
[b74959bd]495 ipc_answer_0(iid, EOK);
[3ad953c]496
[eaf34f7]497 while (1) {
[085bd54]498 async_serialize_end();
[eaf34f7]499 callid = async_get_call(&call);
[085bd54]500 async_serialize_start();
[3ad953c]501
[96858e8]502 arg1 = 0;
503 arg2 = 0;
[fa09449]504 arg3 = 0;
505 arg4 = 0;
506
[eaf34f7]507 switch (IPC_GET_METHOD(call)) {
508 case IPC_M_PHONE_HUNGUP:
[e9073f2]509 gcons_notify_disconnect(consnum);
[085bd54]510
[e9073f2]511 /* Answer all pending requests */
[3ad953c]512 while (conn->keyrequest_counter > 0) {
[e9073f2]513 conn->keyrequest_counter--;
[b74959bd]514 ipc_answer_0(fifo_pop(conn->keyrequests),
515 ENOENT);
[e9073f2]516 break;
517 }
[0d11fc1c]518 conn->used = 0;
[eaf34f7]519 return;
520 case CONSOLE_PUTCHAR:
[10569b1]521 write_char(consnum, IPC_GET_ARG1(call));
[d6cc453]522 gcons_notify_char(consnum);
[ad123964]523 break;
[d2cc7e1]524 case CONSOLE_WRITE:
525 cons_write(consnum, callid, &call);
526 continue;
[ad123964]527 case CONSOLE_CLEAR:
[3993b3d]528 /* Send message to fb */
529 if (consnum == active_console) {
[0cc4313]530 async_msg_0(fb_info.phone, FB_CLEAR);
[3993b3d]531 }
532
[e9073f2]533 screenbuffer_clear(&conn->screenbuffer);
[3993b3d]534
[eaf34f7]535 break;
[ad123964]536 case CONSOLE_GOTO:
[d2cc7e1]537 fb_buf_flush();
[00bb6965]538 screenbuffer_goto(&conn->screenbuffer,
[01f5e17]539 IPC_GET_ARG2(call), IPC_GET_ARG1(call));
[6118e5f6]540 if (consnum == active_console)
[00bb6965]541 curs_goto(IPC_GET_ARG1(call),
[01f5e17]542 IPC_GET_ARG2(call));
[ad123964]543 break;
[3756912]544 case CONSOLE_GETSIZE:
[d6cc453]545 arg1 = fb_info.rows;
546 arg2 = fb_info.cols;
[3756912]547 break;
[0c6984e]548 case CONSOLE_FLUSH:
[d2cc7e1]549 fb_buf_flush();
[a3d2939]550 if (consnum == active_console)
[0cc4313]551 async_req_0_0(fb_info.phone, FB_FLUSH);
[a9bd960c]552 break;
553 case CONSOLE_SET_STYLE:
[d2cc7e1]554 fb_buf_flush();
[9805cde]555 arg1 = IPC_GET_ARG1(call);
556 screenbuffer_set_style(&conn->screenbuffer, arg1);
557 if (consnum == active_console)
558 set_style(arg1);
559 break;
560 case CONSOLE_SET_COLOR:
[d2cc7e1]561 fb_buf_flush();
[9805cde]562 arg1 = IPC_GET_ARG1(call);
563 arg2 = IPC_GET_ARG2(call);
564 arg3 = IPC_GET_ARG3(call);
565 screenbuffer_set_color(&conn->screenbuffer, arg1,
566 arg2, arg3);
567 if (consnum == active_console)
568 set_color(arg1, arg2, arg3);
569 break;
570 case CONSOLE_SET_RGB_COLOR:
[d2cc7e1]571 fb_buf_flush();
[a9bd960c]572 arg1 = IPC_GET_ARG1(call);
573 arg2 = IPC_GET_ARG2(call);
[9805cde]574 screenbuffer_set_rgb_color(&conn->screenbuffer, arg1,
[01f5e17]575 arg2);
[a9bd960c]576 if (consnum == active_console)
[9805cde]577 set_rgb_color(arg1, arg2);
[0c6984e]578 break;
[a8b2b5b2]579 case CONSOLE_CURSOR_VISIBILITY:
[d2cc7e1]580 fb_buf_flush();
[a8b2b5b2]581 arg1 = IPC_GET_ARG1(call);
[e9073f2]582 conn->screenbuffer.is_cursor_visible = arg1;
[a8b2b5b2]583 if (consnum == active_console)
584 curs_visibility(arg1);
585 break;
[fa09449]586 case CONSOLE_GETKEY:
[e9073f2]587 if (keybuffer_empty(&conn->keybuffer)) {
[cf28036c]588 /* buffer is empty -> store request */
[00bb6965]589 if (conn->keyrequest_counter <
590 MAX_KEYREQUESTS_BUFFERED) {
[e9073f2]591 fifo_push(conn->keyrequests, callid);
592 conn->keyrequest_counter++;
[cf28036c]593 } else {
[00bb6965]594 /*
595 * No key available and too many
596 * requests => fail.
597 */
[b74959bd]598 ipc_answer_0(callid, ELIMIT);
[cf28036c]599 }
600 continue;
[00bb6965]601 }
[fa09449]602 kbd_event_t ev;
603 keybuffer_pop(&conn->keybuffer, &ev);
604 arg1 = ev.type;
605 arg2 = ev.key;
606 arg3 = ev.mods;
607 arg4 = ev.c;
[eaf34f7]608 break;
609 }
[fa09449]610 ipc_answer_4(callid, EOK, arg1, arg2, arg3, arg4);
[eaf34f7]611 }
612}
613
[3ad953c]614static void interrupt_received(ipc_callid_t callid, ipc_call_t *call)
615{
616 change_console(prev_console);
617}
618
[eaf34f7]619int main(int argc, char *argv[])
620{
[271b540]621 printf(NAME ": HelenOS Console service\n");
622
[eaf34f7]623 ipcarg_t phonehash;
[501a8ba]624 int kbd_phone;
[7447572]625 size_t ib_size;
[79460ae]626 int i;
[3ad953c]627
[da0c91e7]628 async_set_client_connection(client_connection);
[51c1b003]629
630 /* Connect to keyboard driver */
[4904de8]631 kbd_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_KEYBOARD, 0, 0);
632 if (kbd_phone < 0) {
633 printf(NAME ": Failed to connect to keyboard service\n");
634 return -1;
[00bb6965]635 }
[51c1b003]636
[4904de8]637 if (ipc_connect_to_me(kbd_phone, SERVICE_CONSOLE, 0, 0, &phonehash) != 0) {
638 printf(NAME ": Failed to create callback from keyboard service\n");
[51c1b003]639 return -1;
[4904de8]640 }
641
[290c0db]642 async_new_connection(phonehash, 0, NULL, keyboard_events);
643
[51c1b003]644 /* Connect to framebuffer driver */
[4904de8]645 fb_info.phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VIDEO, 0, 0);
646 if (fb_info.phone < 0) {
647 printf(NAME ": Failed to connect to video service\n");
648 return -1;
[3993b3d]649 }
[429acb9]650
[516ff92]651 /* Disable kernel output to the console */
652 __SYSCALL0(SYS_DEBUG_DISABLE_CONSOLE);
653
[e1c4849]654 /* Initialize gcons */
655 gcons_init(fb_info.phone);
656 /* Synchronize, the gcons can have something in queue */
[0cc4313]657 async_req_0_0(fb_info.phone, FB_FLUSH);
[3993b3d]658
[0cc4313]659 async_req_0_2(fb_info.phone, FB_GET_CSIZE, &fb_info.rows,
[01f5e17]660 &fb_info.cols);
[9805cde]661 set_rgb_color(DEFAULT_FOREGROUND, DEFAULT_BACKGROUND);
[429acb9]662 clrscr();
[3993b3d]663
664 /* Init virtual consoles */
[79460ae]665 for (i = 0; i < CONSOLE_COUNT; i++) {
666 connections[i].used = 0;
[01f5e17]667 keybuffer_init(&connections[i].keybuffer);
[cf28036c]668
[01f5e17]669 connections[i].keyrequests.head = 0;
670 connections[i].keyrequests.tail = 0;
[cf28036c]671 connections[i].keyrequests.items = MAX_KEYREQUESTS_BUFFERED;
672 connections[i].keyrequest_counter = 0;
[3993b3d]673
[01f5e17]674 if (screenbuffer_init(&connections[i].screenbuffer,
675 fb_info.cols, fb_info.rows) == NULL) {
[c738d65]676 /* FIXME: handle error */
[3993b3d]677 return -1;
678 }
[79460ae]679 }
[d32af35]680 connections[KERNEL_CONSOLE].used = 1;
[7447572]681
682 /* Set up shared memory buffer. */
683 ib_size = sizeof(keyfield_t) * fb_info.cols * fb_info.rows;
684 interbuffer = as_get_mappable_page(ib_size);
685
686 if (as_area_create(interbuffer, ib_size, AS_AREA_READ |
687 AS_AREA_WRITE | AS_AREA_CACHEABLE) != interbuffer) {
688 interbuffer = NULL;
689 }
690
691 if (interbuffer) {
[215e375]692 if (ipc_share_out_start(fb_info.phone, interbuffer,
[27d293a]693 AS_AREA_READ) != EOK) {
[7447572]694 as_area_destroy(interbuffer);
[390a678]695 interbuffer = NULL;
696 }
697 }
[3ad953c]698
[c738d65]699 curs_goto(0, 0);
[01f5e17]700 curs_visibility(
701 connections[active_console].screenbuffer.is_cursor_visible);
[3ad953c]702
[b1f51f0]703 /* Register at NS */
[271b540]704 if (ipc_connect_to_me(PHONE_NS, SERVICE_CONSOLE, 0, 0, &phonehash) != 0)
[51c1b003]705 return -1;
706
[3ad953c]707 /* Receive kernel notifications */
[84afc7b]708// if (sysinfo_value("kconsole.present")) {
709// int inr = sysinfo_value("kconsole.inr");
710// if (ipc_register_irq(inr, device_assign_devno(), 0, NULL) != EOK)
711// printf(NAME ": Error registering kconsole notifications\n");
712//
713// async_set_interrupt_received(interrupt_received);
714// }
[3ad953c]715
[271b540]716 // FIXME: avoid connectiong to itself, keep using klog
717 // printf(NAME ": Accepting connections\n");
[eaf34f7]718 async_manager();
[3ad953c]719
720 return 0;
[51c1b003]721}
[516ff92]722
[ce5bcb4]723/** @}
724 */
Note: See TracBrowser for help on using the repository browser.