Subversion Repositories HelenOS

Rev

Rev 4542 | Rev 4584 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4542 Rev 4571
1
/*
1
/*
2
 * Copyright (c) 2006 Josef Cejka
2
 * Copyright (c) 2006 Josef Cejka
3
 * All rights reserved.
3
 * All rights reserved.
4
 *
4
 *
5
 * Redistribution and use in source and binary forms, with or without
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
6
 * modification, are permitted provided that the following conditions
7
 * are met:
7
 * are met:
8
 *
8
 *
9
 * - Redistributions of source code must retain the above copyright
9
 * - Redistributions of source code must retain the above copyright
10
 *   notice, this list of conditions and the following disclaimer.
10
 *   notice, this list of conditions and the following disclaimer.
11
 * - Redistributions in binary form must reproduce the above copyright
11
 * - Redistributions in binary form must reproduce the above copyright
12
 *   notice, this list of conditions and the following disclaimer in the
12
 *   notice, this list of conditions and the following disclaimer in the
13
 *   documentation and/or other materials provided with the distribution.
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
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.
15
 *   derived from this software without specific prior written permission.
16
 *
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
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
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
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
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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
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.
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 */
27
 */
28
 
28
 
29
/** @addtogroup console
29
/** @addtogroup console
30
 * @{
30
 * @{
31
 */
31
 */
32
/** @file
32
/** @file
33
 */
33
 */
34
 
34
 
35
#include <libc.h>
35
#include <libc.h>
36
#include <fb.h>
36
#include <fb.h>
37
#include <ipc/ipc.h>
37
#include <ipc/ipc.h>
38
#include <kbd.h>
38
#include <kbd.h>
39
#include <io/keycode.h>
39
#include <io/keycode.h>
40
#include <ipc/fb.h>
40
#include <ipc/fb.h>
41
#include <ipc/services.h>
41
#include <ipc/services.h>
42
#include <errno.h>
42
#include <errno.h>
43
#include <keybuffer.h>
43
#include <keybuffer.h>
44
#include <ipc/console.h>
44
#include <ipc/console.h>
45
#include <unistd.h>
45
#include <unistd.h>
46
#include <async.h>
46
#include <async.h>
47
#include <adt/fifo.h>
47
#include <adt/fifo.h>
48
#include <sys/mman.h>
48
#include <sys/mman.h>
49
#include <stdio.h>
49
#include <stdio.h>
50
#include <string.h>
50
#include <string.h>
51
#include <sysinfo.h>
51
#include <sysinfo.h>
52
#include <event.h>
52
#include <event.h>
53
#include <devmap.h>
53
#include <devmap.h>
54
#include <assert.h>
-
 
55
#include <fibril_sync.h>
54
#include <fibril_sync.h>
56
 
55
 
57
#include "console.h"
56
#include "console.h"
58
#include "gcons.h"
57
#include "gcons.h"
59
#include "screenbuffer.h"
58
#include "screenbuffer.h"
60
 
59
 
61
#define NAME  "console"
60
#define NAME  "console"
62
 
61
 
63
#define MAX_DEVICE_NAME  32
62
#define MAX_DEVICE_NAME  32
64
 
63
 
65
/** Phone to the keyboard driver. */
64
/** Phone to the keyboard driver. */
66
static int kbd_phone;
65
static int kbd_phone;
67
 
66
 
68
/** Information about framebuffer */
67
/** Information about framebuffer */
69
struct {
68
struct {
70
    int phone;      /**< Framebuffer phone */
69
    int phone;      /**< Framebuffer phone */
71
    ipcarg_t cols;  /**< Framebuffer columns */
70
    ipcarg_t cols;  /**< Framebuffer columns */
72
    ipcarg_t rows;  /**< Framebuffer rows */
71
    ipcarg_t rows;  /**< Framebuffer rows */
73
} fb_info;
72
} fb_info;
74
 
73
 
75
typedef struct {
74
typedef struct {
76
    size_t index;             /**< Console index */
75
    size_t index;             /**< Console index */
77
    size_t refcount;          /**< Connection reference count */
76
    size_t refcount;          /**< Connection reference count */
78
    dev_handle_t dev_handle;  /**< Device handle */
77
    dev_handle_t dev_handle;  /**< Device handle */
79
    keybuffer_t keybuffer;    /**< Buffer for incoming keys. */
78
    keybuffer_t keybuffer;    /**< Buffer for incoming keys. */
80
    screenbuffer_t scr;       /**< Screenbuffer for saving screen
79
    screenbuffer_t scr;       /**< Screenbuffer for saving screen
81
                                   contents and related settings. */
80
                                   contents and related settings. */
82
} console_t;
81
} console_t;
83
 
82
 
84
/** Array of data for virtual consoles */
83
/** Array of data for virtual consoles */
85
static console_t consoles[CONSOLE_COUNT];
84
static console_t consoles[CONSOLE_COUNT];
86
 
85
 
87
static console_t *active_console = &consoles[0];
86
static console_t *active_console = &consoles[0];
88
static console_t *prev_console = &consoles[0];
87
static console_t *prev_console = &consoles[0];
89
static console_t *kernel_console = &consoles[KERNEL_CONSOLE];
88
static console_t *kernel_console = &consoles[KERNEL_CONSOLE];
90
 
89
 
91
/** Pointer to memory shared with framebufer used for
90
/** Pointer to memory shared with framebufer used for
92
    faster virtual console switching */
91
    faster virtual console switching */
93
static keyfield_t *interbuffer = NULL;
92
static keyfield_t *interbuffer = NULL;
94
 
93
 
95
/** Information on row-span yet unsent to FB driver. */
94
/** Information on row-span yet unsent to FB driver. */
96
struct {
95
struct {
97
    size_t col;  /**< Leftmost column of the span. */
96
    size_t col;  /**< Leftmost column of the span. */
98
    size_t row;  /**< Row where the span lies. */
97
    size_t row;  /**< Row where the span lies. */
99
    size_t cnt;  /**< Width of the span. */
98
    size_t cnt;  /**< Width of the span. */
100
} fb_pending;
99
} fb_pending;
101
 
100
 
102
/** Pending input structure. */
-
 
103
typedef struct {
-
 
104
    link_t link;
-
 
105
    console_t *cons;      /**< Console waiting for input */
-
 
106
    ipc_callid_t rid;     /**< Call ID waiting for input */
-
 
107
    ipc_callid_t callid;  /**< Call ID waiting for IPC_DATA_READ */
-
 
108
   
-
 
109
    size_t pos;           /**< Position of the last stored data */
-
 
110
    size_t size;          /**< Size of ther buffer */
-
 
111
    char *data;           /**< Already stored data */
-
 
112
} pending_input_t;
-
 
113
 
-
 
114
LIST_INITIALIZE(pending_input);
-
 
115
 
-
 
116
static FIBRIL_MUTEX_INITIALIZE(input_mutex);
101
static FIBRIL_MUTEX_INITIALIZE(input_mutex);
117
static FIBRIL_CONDVAR_INITIALIZE(input_cv);
102
static FIBRIL_CONDVAR_INITIALIZE(input_cv);
118
static input_flag = false;
-
 
119
 
-
 
120
/** Process pending input requests */
-
 
121
static void process_pending_input(void)
-
 
122
{
-
 
123
    link_t *cur;
-
 
124
   
-
 
125
loop:
-
 
126
    fibril_mutex_lock(&input_mutex);
-
 
127
    while (!input_flag)
-
 
128
        fibril_condvar_wait(&input_cv, &input_mutex);
-
 
129
rescan:
-
 
130
    for (cur = pending_input.next; cur != &pending_input; cur = cur->next) {
-
 
131
        pending_input_t *pr = list_get_instance(cur, pending_input_t, link);
-
 
132
       
-
 
133
        console_event_t ev;
-
 
134
        if (keybuffer_pop(&pr->cons->keybuffer, &ev)) {
-
 
135
           
-
 
136
            if (pr->data != NULL) {
-
 
137
                if (ev.type == KEY_PRESS) {
-
 
138
                    pr->data[pr->pos] = ev.c;
-
 
139
                    pr->pos++;
-
 
140
                }
-
 
141
            } else {
-
 
142
                ipc_answer_4(pr->rid, EOK, ev.type, ev.key, ev.mods, ev.c);
-
 
143
                list_remove(cur);
-
 
144
                free(pr);
-
 
145
                goto rescan;
-
 
146
            }
-
 
147
        }
-
 
148
       
-
 
149
        if ((pr->data != NULL) && (pr->pos == pr->size)) {
-
 
150
            (void) ipc_data_read_finalize(pr->callid, pr->data, pr->size);
-
 
151
            ipc_answer_1(pr->rid, EOK, pr->size);
-
 
152
 
-
 
153
            free(pr->data);
-
 
154
            list_remove(cur);
-
 
155
            free(pr);
-
 
156
            goto rescan;
-
 
157
        }
-
 
158
    }
-
 
159
    input_flag = false;
-
 
160
    fibril_mutex_unlock(&input_mutex);
-
 
161
    goto loop;
-
 
162
}
-
 
163
 
103
 
164
static void curs_visibility(bool visible)
104
static void curs_visibility(bool visible)
165
{
105
{
166
    async_msg_1(fb_info.phone, FB_CURSOR_VISIBILITY, visible);
106
    async_msg_1(fb_info.phone, FB_CURSOR_VISIBILITY, visible);
167
}
107
}
168
 
108
 
169
static void curs_hide_sync(void)
109
static void curs_hide_sync(void)
170
{
110
{
171
    ipc_call_sync_1_0(fb_info.phone, FB_CURSOR_VISIBILITY, false);
111
    ipc_call_sync_1_0(fb_info.phone, FB_CURSOR_VISIBILITY, false);
172
}
112
}
173
 
113
 
174
static void curs_goto(size_t x, size_t y)
114
static void curs_goto(size_t x, size_t y)
175
{
115
{
176
    async_msg_2(fb_info.phone, FB_CURSOR_GOTO, x, y);
116
    async_msg_2(fb_info.phone, FB_CURSOR_GOTO, x, y);
177
}
117
}
178
 
118
 
179
static void screen_clear(void)
119
static void screen_clear(void)
180
{
120
{
181
    async_msg_0(fb_info.phone, FB_CLEAR);
121
    async_msg_0(fb_info.phone, FB_CLEAR);
182
}
122
}
183
 
123
 
184
static void screen_yield(void)
124
static void screen_yield(void)
185
{
125
{
186
    ipc_call_sync_0_0(fb_info.phone, FB_SCREEN_YIELD);
126
    ipc_call_sync_0_0(fb_info.phone, FB_SCREEN_YIELD);
187
}
127
}
188
 
128
 
189
static void screen_reclaim(void)
129
static void screen_reclaim(void)
190
{
130
{
191
    ipc_call_sync_0_0(fb_info.phone, FB_SCREEN_RECLAIM);
131
    ipc_call_sync_0_0(fb_info.phone, FB_SCREEN_RECLAIM);
192
}
132
}
193
 
133
 
194
static void kbd_yield(void)
134
static void kbd_yield(void)
195
{
135
{
196
    ipc_call_sync_0_0(kbd_phone, KBD_YIELD);
136
    ipc_call_sync_0_0(kbd_phone, KBD_YIELD);
197
}
137
}
198
 
138
 
199
static void kbd_reclaim(void)
139
static void kbd_reclaim(void)
200
{
140
{
201
    ipc_call_sync_0_0(kbd_phone, KBD_RECLAIM);
141
    ipc_call_sync_0_0(kbd_phone, KBD_RECLAIM);
202
}
142
}
203
 
143
 
204
static void set_style(int style)
144
static void set_style(int style)
205
{
145
{
206
    async_msg_1(fb_info.phone, FB_SET_STYLE, style);
146
    async_msg_1(fb_info.phone, FB_SET_STYLE, style);
207
}
147
}
208
 
148
 
209
static void set_color(int fgcolor, int bgcolor, int flags)
149
static void set_color(int fgcolor, int bgcolor, int flags)
210
{
150
{
211
    async_msg_3(fb_info.phone, FB_SET_COLOR, fgcolor, bgcolor, flags);
151
    async_msg_3(fb_info.phone, FB_SET_COLOR, fgcolor, bgcolor, flags);
212
}
152
}
213
 
153
 
214
static void set_rgb_color(int fgcolor, int bgcolor)
154
static void set_rgb_color(int fgcolor, int bgcolor)
215
{
155
{
216
    async_msg_2(fb_info.phone, FB_SET_RGB_COLOR, fgcolor, bgcolor);
156
    async_msg_2(fb_info.phone, FB_SET_RGB_COLOR, fgcolor, bgcolor);
217
}
157
}
218
 
158
 
219
static void set_attrs(attrs_t *attrs)
159
static void set_attrs(attrs_t *attrs)
220
{
160
{
221
    switch (attrs->t) {
161
    switch (attrs->t) {
222
    case at_style:
162
    case at_style:
223
        set_style(attrs->a.s.style);
163
        set_style(attrs->a.s.style);
224
        break;
164
        break;
225
    case at_idx:
165
    case at_idx:
226
        set_color(attrs->a.i.fg_color, attrs->a.i.bg_color,
166
        set_color(attrs->a.i.fg_color, attrs->a.i.bg_color,
227
            attrs->a.i.flags);
167
            attrs->a.i.flags);
228
        break;
168
        break;
229
    case at_rgb:
169
    case at_rgb:
230
        set_rgb_color(attrs->a.r.fg_color, attrs->a.r.bg_color);
170
        set_rgb_color(attrs->a.r.fg_color, attrs->a.r.bg_color);
231
        break;
171
        break;
232
    }
172
    }
233
}
173
}
234
 
174
 
235
/** Send an area of screenbuffer to the FB driver. */
175
/** Send an area of screenbuffer to the FB driver. */
236
static void fb_update_area(console_t *cons, ipcarg_t x0, ipcarg_t y0, ipcarg_t width, ipcarg_t height)
176
static void fb_update_area(console_t *cons, ipcarg_t x0, ipcarg_t y0, ipcarg_t width, ipcarg_t height)
237
{
177
{
238
    if (interbuffer) {
178
    if (interbuffer) {
239
        ipcarg_t x;
179
        ipcarg_t x;
240
        ipcarg_t y;
180
        ipcarg_t y;
241
       
181
       
242
        for (y = 0; y < height; y++) {
182
        for (y = 0; y < height; y++) {
243
            for (x = 0; x < width; x++) {
183
            for (x = 0; x < width; x++) {
244
                interbuffer[y * width + x] =
184
                interbuffer[y * width + x] =
245
                    *get_field_at(&cons->scr, x0 + x, y0 + y);
185
                    *get_field_at(&cons->scr, x0 + x, y0 + y);
246
            }
186
            }
247
        }
187
        }
248
       
188
       
249
        async_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
189
        async_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
250
            x0, y0, width, height);
190
            x0, y0, width, height);
251
    }
191
    }
252
}
192
}
253
 
193
 
254
/** Flush pending cells to FB. */
194
/** Flush pending cells to FB. */
255
static void fb_pending_flush(void)
195
static void fb_pending_flush(void)
256
{
196
{
257
    if (fb_pending.cnt > 0) {
197
    if (fb_pending.cnt > 0) {
258
        fb_update_area(active_console, fb_pending.col,
198
        fb_update_area(active_console, fb_pending.col,
259
            fb_pending.row, fb_pending.cnt, 1);
199
            fb_pending.row, fb_pending.cnt, 1);
260
        fb_pending.cnt = 0;
200
        fb_pending.cnt = 0;
261
    }
201
    }
262
}
202
}
263
 
203
 
264
/** Mark a character cell as changed.
204
/** Mark a character cell as changed.
265
 *
205
 *
266
 * This adds the cell to the pending rowspan if possible. Otherwise
206
 * This adds the cell to the pending rowspan if possible. Otherwise
267
 * the old span is flushed first.
207
 * the old span is flushed first.
268
 *
208
 *
269
 */
209
 */
270
static void cell_mark_changed(size_t col, size_t row)
210
static void cell_mark_changed(size_t col, size_t row)
271
{
211
{
272
    if (fb_pending.cnt != 0) {
212
    if (fb_pending.cnt != 0) {
273
        if ((col != fb_pending.col + fb_pending.cnt)
213
        if ((col != fb_pending.col + fb_pending.cnt)
274
            || (row != fb_pending.row)) {
214
            || (row != fb_pending.row)) {
275
            fb_pending_flush();
215
            fb_pending_flush();
276
        }
216
        }
277
    }
217
    }
278
   
218
   
279
    if (fb_pending.cnt == 0) {
219
    if (fb_pending.cnt == 0) {
280
        fb_pending.col = col;
220
        fb_pending.col = col;
281
        fb_pending.row = row;
221
        fb_pending.row = row;
282
    }
222
    }
283
   
223
   
284
    fb_pending.cnt++;
224
    fb_pending.cnt++;
285
}
225
}
286
 
226
 
287
/** Print a character to the active VC with buffering. */
227
/** Print a character to the active VC with buffering. */
288
static void fb_putchar(wchar_t c, ipcarg_t col, ipcarg_t row)
228
static void fb_putchar(wchar_t c, ipcarg_t col, ipcarg_t row)
289
{
229
{
290
    async_msg_3(fb_info.phone, FB_PUTCHAR, c, col, row);
230
    async_msg_3(fb_info.phone, FB_PUTCHAR, c, col, row);
291
}
231
}
292
 
232
 
293
/** Process a character from the client (TTY emulation). */
233
/** Process a character from the client (TTY emulation). */
294
static void write_char(console_t *cons, wchar_t ch)
234
static void write_char(console_t *cons, wchar_t ch)
295
{
235
{
296
    bool flush_cursor = false;
236
    bool flush_cursor = false;
297
 
237
 
298
    switch (ch) {
238
    switch (ch) {
299
    case '\n':
239
    case '\n':
300
        fb_pending_flush();
240
        fb_pending_flush();
301
        flush_cursor = true;
241
        flush_cursor = true;
302
        cons->scr.position_y++;
242
        cons->scr.position_y++;
303
        cons->scr.position_x = 0;
243
        cons->scr.position_x = 0;
304
        break;
244
        break;
305
    case '\r':
245
    case '\r':
306
        break;
246
        break;
307
    case '\t':
247
    case '\t':
308
        cons->scr.position_x += 8;
248
        cons->scr.position_x += 8;
309
        cons->scr.position_x -= cons->scr.position_x % 8;
249
        cons->scr.position_x -= cons->scr.position_x % 8;
310
        break;
250
        break;
311
    case '\b':
251
    case '\b':
312
        if (cons->scr.position_x == 0)
252
        if (cons->scr.position_x == 0)
313
            break;
253
            break;
314
        cons->scr.position_x--;
254
        cons->scr.position_x--;
315
        if (cons == active_console)
255
        if (cons == active_console)
316
            cell_mark_changed(cons->scr.position_x, cons->scr.position_y);
256
            cell_mark_changed(cons->scr.position_x, cons->scr.position_y);
317
        screenbuffer_putchar(&cons->scr, ' ');
257
        screenbuffer_putchar(&cons->scr, ' ');
318
        break;
258
        break;
319
    default:
259
    default:
320
        if (cons == active_console)
260
        if (cons == active_console)
321
            cell_mark_changed(cons->scr.position_x, cons->scr.position_y);
261
            cell_mark_changed(cons->scr.position_x, cons->scr.position_y);
322
       
262
       
323
        screenbuffer_putchar(&cons->scr, ch);
263
        screenbuffer_putchar(&cons->scr, ch);
324
        cons->scr.position_x++;
264
        cons->scr.position_x++;
325
    }
265
    }
326
   
266
   
327
    if (cons->scr.position_x >= cons->scr.size_x) {
267
    if (cons->scr.position_x >= cons->scr.size_x) {
328
        flush_cursor = true;
268
        flush_cursor = true;
329
        cons->scr.position_y++;
269
        cons->scr.position_y++;
330
    }
270
    }
331
   
271
   
332
    if (cons->scr.position_y >= cons->scr.size_y) {
272
    if (cons->scr.position_y >= cons->scr.size_y) {
333
        fb_pending_flush();
273
        fb_pending_flush();
334
        cons->scr.position_y = cons->scr.size_y - 1;
274
        cons->scr.position_y = cons->scr.size_y - 1;
335
        screenbuffer_clear_line(&cons->scr, cons->scr.top_line);
275
        screenbuffer_clear_line(&cons->scr, cons->scr.top_line);
336
        cons->scr.top_line = (cons->scr.top_line + 1) % cons->scr.size_y;
276
        cons->scr.top_line = (cons->scr.top_line + 1) % cons->scr.size_y;
337
       
277
       
338
        if (cons == active_console)
278
        if (cons == active_console)
339
            async_msg_1(fb_info.phone, FB_SCROLL, 1);
279
            async_msg_1(fb_info.phone, FB_SCROLL, 1);
340
    }
280
    }
341
 
281
 
342
    if (cons == active_console && flush_cursor)
282
    if (cons == active_console && flush_cursor)
343
        curs_goto(cons->scr.position_x, cons->scr.position_y);
283
        curs_goto(cons->scr.position_x, cons->scr.position_y);
344
    cons->scr.position_x = cons->scr.position_x % cons->scr.size_x;
284
    cons->scr.position_x = cons->scr.position_x % cons->scr.size_x;
345
}
285
}
346
 
286
 
347
/** Switch to new console */
287
/** Switch to new console */
348
static void change_console(console_t *cons)
288
static void change_console(console_t *cons)
349
{
289
{
350
    if (cons == active_console)
290
    if (cons == active_console)
351
        return;
291
        return;
352
   
292
   
353
    fb_pending_flush();
293
    fb_pending_flush();
354
   
294
   
355
    if (cons == kernel_console) {
295
    if (cons == kernel_console) {
356
        async_serialize_start();
296
        async_serialize_start();
357
        curs_hide_sync();
297
        curs_hide_sync();
358
        gcons_in_kernel();
298
        gcons_in_kernel();
359
        screen_yield();
299
        screen_yield();
360
        kbd_yield();
300
        kbd_yield();
361
        async_serialize_end();
301
        async_serialize_end();
362
       
302
       
363
        if (__SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE)) {
303
        if (__SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE)) {
364
            prev_console = active_console;
304
            prev_console = active_console;
365
            active_console = kernel_console;
305
            active_console = kernel_console;
366
        } else
306
        } else
367
            cons = active_console;
307
            cons = active_console;
368
    }
308
    }
369
   
309
   
370
    if (cons != kernel_console) {
310
    if (cons != kernel_console) {
371
        size_t x;
311
        size_t x;
372
        size_t y;
312
        size_t y;
373
        int rc = 0;
313
        int rc = 0;
374
       
314
       
375
        async_serialize_start();
315
        async_serialize_start();
376
       
316
       
377
        if (active_console == kernel_console) {
317
        if (active_console == kernel_console) {
378
            screen_reclaim();
318
            screen_reclaim();
379
            kbd_reclaim();
319
            kbd_reclaim();
380
            gcons_redraw_console();
320
            gcons_redraw_console();
381
        }
321
        }
382
       
322
       
383
        active_console = cons;
323
        active_console = cons;
384
        gcons_change_console(cons->index);
324
        gcons_change_console(cons->index);
385
       
325
       
386
        set_attrs(&cons->scr.attrs);
326
        set_attrs(&cons->scr.attrs);
387
        curs_visibility(false);
327
        curs_visibility(false);
388
        if (interbuffer) {
328
        if (interbuffer) {
389
            for (y = 0; y < cons->scr.size_y; y++) {
329
            for (y = 0; y < cons->scr.size_y; y++) {
390
                for (x = 0; x < cons->scr.size_x; x++) {
330
                for (x = 0; x < cons->scr.size_x; x++) {
391
                    interbuffer[y * cons->scr.size_x + x] =
331
                    interbuffer[y * cons->scr.size_x + x] =
392
                        *get_field_at(&cons->scr, x, y);
332
                        *get_field_at(&cons->scr, x, y);
393
                }
333
                }
394
            }
334
            }
395
           
335
           
396
            /* This call can preempt, but we are already at the end */
336
            /* This call can preempt, but we are already at the end */
397
            rc = async_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
337
            rc = async_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
398
                0, 0, cons->scr.size_x,
338
                0, 0, cons->scr.size_x,
399
                cons->scr.size_y);
339
                cons->scr.size_y);
400
        }
340
        }
401
       
341
       
402
        if ((!interbuffer) || (rc != 0)) {
342
        if ((!interbuffer) || (rc != 0)) {
403
            set_attrs(&cons->scr.attrs);
343
            set_attrs(&cons->scr.attrs);
404
            screen_clear();
344
            screen_clear();
405
           
345
           
406
            for (y = 0; y < cons->scr.size_y; y++)
346
            for (y = 0; y < cons->scr.size_y; y++)
407
                for (x = 0; x < cons->scr.size_x; x++) {
347
                for (x = 0; x < cons->scr.size_x; x++) {
408
                    keyfield_t *field = get_field_at(&cons->scr, x, y);
348
                    keyfield_t *field = get_field_at(&cons->scr, x, y);
409
                   
349
                   
410
                    if (!attrs_same(cons->scr.attrs, field->attrs))
350
                    if (!attrs_same(cons->scr.attrs, field->attrs))
411
                        set_attrs(&field->attrs);
351
                        set_attrs(&field->attrs);
412
                   
352
                   
413
                    cons->scr.attrs = field->attrs;
353
                    cons->scr.attrs = field->attrs;
414
                    if ((field->character == ' ') &&
354
                    if ((field->character == ' ') &&
415
                        (attrs_same(field->attrs, cons->scr.attrs)))
355
                        (attrs_same(field->attrs, cons->scr.attrs)))
416
                        continue;
356
                        continue;
417
                   
357
                   
418
                    fb_putchar(field->character, x, y);
358
                    fb_putchar(field->character, x, y);
419
                }
359
                }
420
        }
360
        }
421
       
361
       
422
        curs_goto(cons->scr.position_x, cons->scr.position_y);
362
        curs_goto(cons->scr.position_x, cons->scr.position_y);
423
        curs_visibility(cons->scr.is_cursor_visible);
363
        curs_visibility(cons->scr.is_cursor_visible);
424
       
364
       
425
        async_serialize_end();
365
        async_serialize_end();
426
    }
366
    }
427
}
367
}
428
 
368
 
429
/** Handler for keyboard */
369
/** Handler for keyboard */
430
static void keyboard_events(ipc_callid_t iid, ipc_call_t *icall)
370
static void keyboard_events(ipc_callid_t iid, ipc_call_t *icall)
431
{
371
{
432
    /* Ignore parameters, the connection is already opened */
372
    /* Ignore parameters, the connection is already opened */
433
    while (true) {
373
    while (true) {
434
       
374
       
435
        ipc_call_t call;
375
        ipc_call_t call;
436
        ipc_callid_t callid = async_get_call(&call);
376
        ipc_callid_t callid = async_get_call(&call);
437
       
377
       
438
        int retval;
378
        int retval;
439
        console_event_t ev;
379
        console_event_t ev;
440
       
380
       
441
        switch (IPC_GET_METHOD(call)) {
381
        switch (IPC_GET_METHOD(call)) {
442
        case IPC_M_PHONE_HUNGUP:
382
        case IPC_M_PHONE_HUNGUP:
443
            /* TODO: Handle hangup */
383
            /* TODO: Handle hangup */
444
            return;
384
            return;
445
        case KBD_EVENT:
385
        case KBD_EVENT:
446
            /* Got event from keyboard driver. */
386
            /* Got event from keyboard driver. */
447
            retval = 0;
387
            retval = 0;
448
            ev.type = IPC_GET_ARG1(call);
388
            ev.type = IPC_GET_ARG1(call);
449
            ev.key = IPC_GET_ARG2(call);
389
            ev.key = IPC_GET_ARG2(call);
450
            ev.mods = IPC_GET_ARG3(call);
390
            ev.mods = IPC_GET_ARG3(call);
451
            ev.c = IPC_GET_ARG4(call);
391
            ev.c = IPC_GET_ARG4(call);
452
           
392
           
453
            if ((ev.key >= KC_F1) && (ev.key < KC_F1 +
393
            if ((ev.key >= KC_F1) && (ev.key < KC_F1 +
454
                CONSOLE_COUNT) && ((ev.mods & KM_CTRL) == 0)) {
394
                CONSOLE_COUNT) && ((ev.mods & KM_CTRL) == 0)) {
455
                if (ev.key == KC_F1 + KERNEL_CONSOLE)
395
                if (ev.key == KC_F1 + KERNEL_CONSOLE)
456
                    change_console(kernel_console);
396
                    change_console(kernel_console);
457
                else
397
                else
458
                    change_console(&consoles[ev.key - KC_F1]);
398
                    change_console(&consoles[ev.key - KC_F1]);
459
                break;
399
                break;
460
            }
400
            }
461
           
401
           
462
            fibril_mutex_lock(&input_mutex);
402
            fibril_mutex_lock(&input_mutex);
463
            keybuffer_push(&active_console->keybuffer, &ev);
403
            keybuffer_push(&active_console->keybuffer, &ev);
464
            input_flag = true;
-
 
465
            fibril_condvar_signal(&input_cv);
404
            fibril_condvar_broadcast(&input_cv);
466
            fibril_mutex_unlock(&input_mutex);
405
            fibril_mutex_unlock(&input_mutex);
467
            break;
406
            break;
468
        default:
407
        default:
469
            retval = ENOENT;
408
            retval = ENOENT;
470
        }
409
        }
471
        ipc_answer_0(callid, retval);
410
        ipc_answer_0(callid, retval);
472
    }
411
    }
473
}
412
}
474
 
413
 
475
static void cons_write(console_t *cons, ipc_callid_t rid, ipc_call_t *request)
414
static void cons_write(console_t *cons, ipc_callid_t rid, ipc_call_t *request)
476
{
415
{
477
    ipc_callid_t callid;
416
    ipc_callid_t callid;
478
    size_t size;
417
    size_t size;
479
    if (!ipc_data_write_receive(&callid, &size)) {
418
    if (!ipc_data_write_receive(&callid, &size)) {
480
        ipc_answer_0(callid, EINVAL);
419
        ipc_answer_0(callid, EINVAL);
481
        ipc_answer_0(rid, EINVAL);
420
        ipc_answer_0(rid, EINVAL);
482
        return;
421
        return;
483
    }
422
    }
484
   
423
   
485
    char *buf = (char *) malloc(size);
424
    char *buf = (char *) malloc(size);
486
    if (buf == NULL) {
425
    if (buf == NULL) {
487
        ipc_answer_0(callid, ENOMEM);
426
        ipc_answer_0(callid, ENOMEM);
488
        ipc_answer_0(rid, ENOMEM);
427
        ipc_answer_0(rid, ENOMEM);
489
        return;
428
        return;
490
    }
429
    }
491
   
430
   
492
    (void) ipc_data_write_finalize(callid, buf, size);
431
    (void) ipc_data_write_finalize(callid, buf, size);
493
   
432
   
494
    async_serialize_start();
433
    async_serialize_start();
495
   
434
   
496
    size_t off = 0;
435
    size_t off = 0;
497
    while (off < size) {
436
    while (off < size) {
498
        wchar_t ch = str_decode(buf, &off, size);
437
        wchar_t ch = str_decode(buf, &off, size);
499
        write_char(cons, ch);
438
        write_char(cons, ch);
500
    }
439
    }
501
   
440
   
502
    async_serialize_end();
441
    async_serialize_end();
503
   
442
   
504
    gcons_notify_char(cons->index);
443
    gcons_notify_char(cons->index);
505
    ipc_answer_1(rid, EOK, size);
444
    ipc_answer_1(rid, EOK, size);
506
   
445
   
507
    free(buf);
446
    free(buf);
508
}
447
}
509
 
448
 
510
static void cons_read(console_t *cons, ipc_callid_t rid, ipc_call_t *request)
449
static void cons_read(console_t *cons, ipc_callid_t rid, ipc_call_t *request)
511
{
450
{
512
    ipc_callid_t callid;
451
    ipc_callid_t callid;
513
    size_t size;
452
    size_t size;
514
    if (!ipc_data_read_receive(&callid, &size)) {
453
    if (!ipc_data_read_receive(&callid, &size)) {
515
        ipc_answer_0(callid, EINVAL);
454
        ipc_answer_0(callid, EINVAL);
516
        ipc_answer_0(rid, EINVAL);
455
        ipc_answer_0(rid, EINVAL);
517
        return;
456
        return;
518
    }
457
    }
519
   
458
   
520
    char *buf = (char *) malloc(size);
459
    char *buf = (char *) malloc(size);
521
    if (buf == NULL) {
460
    if (buf == NULL) {
522
        ipc_answer_0(callid, ENOMEM);
461
        ipc_answer_0(callid, ENOMEM);
523
        ipc_answer_0(rid, ENOMEM);
462
        ipc_answer_0(rid, ENOMEM);
524
        return;
463
        return;
525
    }
464
    }
526
   
465
   
527
    size_t pos = 0;
466
    size_t pos = 0;
528
    console_event_t ev;
467
    console_event_t ev;
529
    fibril_mutex_lock(&input_mutex);
468
    fibril_mutex_lock(&input_mutex);
-
 
469
recheck:
530
    while ((keybuffer_pop(&cons->keybuffer, &ev)) && (pos < size)) {
470
    while ((keybuffer_pop(&cons->keybuffer, &ev)) && (pos < size)) {
531
        if (ev.type == KEY_PRESS) {
471
        if (ev.type == KEY_PRESS) {
532
            buf[pos] = ev.c;
472
            buf[pos] = ev.c;
533
            pos++;
473
            pos++;
534
        }
474
        }
535
    }
475
    }
536
   
476
   
537
    if (pos == size) {
477
    if (pos == size) {
538
        (void) ipc_data_read_finalize(callid, buf, size);
478
        (void) ipc_data_read_finalize(callid, buf, size);
539
        ipc_answer_1(rid, EOK, size);
479
        ipc_answer_1(rid, EOK, size);
540
        free(buf);
480
        free(buf);
541
    } else {
481
    } else {
542
        pending_input_t *pr = (pending_input_t *) malloc(sizeof(pending_input_t));
-
 
543
        if (!pr) {
-
 
544
            fibril_mutex_unlock(&input_mutex);
482
        fibril_condvar_wait(&input_cv, &input_mutex);
545
            ipc_answer_0(callid, ENOMEM);
-
 
546
            ipc_answer_0(rid, ENOMEM);
-
 
547
            free(buf);
483
        goto recheck;
548
            return;
-
 
549
        }
-
 
550
       
-
 
551
        pr->cons = cons;
-
 
552
        pr->rid = rid;
-
 
553
        pr->callid = callid;
-
 
554
        pr->pos = pos;
-
 
555
        pr->size = size;
-
 
556
        pr->data = buf;
-
 
557
        list_append(&pr->link, &pending_input);
-
 
558
    }
484
    }
559
    fibril_mutex_unlock(&input_mutex);
485
    fibril_mutex_unlock(&input_mutex);
560
}
486
}
561
 
487
 
562
static void cons_get_event(console_t *cons, ipc_callid_t rid, ipc_call_t *request)
488
static void cons_get_event(console_t *cons, ipc_callid_t rid, ipc_call_t *request)
563
{
489
{
564
    console_event_t ev;
490
    console_event_t ev;
565
 
491
 
566
    fibril_mutex_lock(&input_mutex);
492
    fibril_mutex_lock(&input_mutex);
-
 
493
recheck:
567
    if (keybuffer_pop(&cons->keybuffer, &ev)) {
494
    if (keybuffer_pop(&cons->keybuffer, &ev)) {
568
        ipc_answer_4(rid, EOK, ev.type, ev.key, ev.mods, ev.c);
495
        ipc_answer_4(rid, EOK, ev.type, ev.key, ev.mods, ev.c);
569
    } else {
496
    } else {
570
        pending_input_t *pr = (pending_input_t *) malloc(sizeof(pending_input_t));
-
 
571
        if (!pr) {
-
 
572
            fibril_mutex_unlock(&input_mutex);
497
        fibril_condvar_wait(&input_cv, &input_mutex);
573
            ipc_answer_0(rid, ENOMEM);
-
 
574
            return;
498
        goto recheck;
575
        }
-
 
576
       
-
 
577
        pr->cons = cons;
-
 
578
        pr->rid = rid;
-
 
579
        pr->callid = 0;
-
 
580
        pr->data = NULL;
-
 
581
        list_append(&pr->link, &pending_input);
-
 
582
    }
499
    }
583
    fibril_mutex_unlock(&input_mutex);
500
    fibril_mutex_unlock(&input_mutex);
584
}
501
}
585
 
502
 
586
/** Default thread for new connections */
503
/** Default thread for new connections */
587
static void client_connection(ipc_callid_t iid, ipc_call_t *icall)
504
static void client_connection(ipc_callid_t iid, ipc_call_t *icall)
588
{
505
{
589
    console_t *cons = NULL;
506
    console_t *cons = NULL;
590
   
507
   
591
    size_t i;
508
    size_t i;
592
    for (i = 0; i < CONSOLE_COUNT; i++) {
509
    for (i = 0; i < CONSOLE_COUNT; i++) {
593
        if (i == KERNEL_CONSOLE)
510
        if (i == KERNEL_CONSOLE)
594
            continue;
511
            continue;
595
       
512
       
596
        if (consoles[i].dev_handle == (dev_handle_t) IPC_GET_ARG1(*icall)) {
513
        if (consoles[i].dev_handle == (dev_handle_t) IPC_GET_ARG1(*icall)) {
597
            cons = &consoles[i];
514
            cons = &consoles[i];
598
            break;
515
            break;
599
        }
516
        }
600
    }
517
    }
601
   
518
   
602
    if (cons == NULL) {
519
    if (cons == NULL) {
603
        ipc_answer_0(iid, ENOENT);
520
        ipc_answer_0(iid, ENOENT);
604
        return;
521
        return;
605
    }
522
    }
606
   
523
   
607
    ipc_callid_t callid;
524
    ipc_callid_t callid;
608
    ipc_call_t call;
525
    ipc_call_t call;
609
    ipcarg_t arg1;
526
    ipcarg_t arg1;
610
    ipcarg_t arg2;
527
    ipcarg_t arg2;
611
    ipcarg_t arg3;
528
    ipcarg_t arg3;
612
   
529
   
613
    async_serialize_start();
530
    async_serialize_start();
614
    if (cons->refcount == 0)
531
    if (cons->refcount == 0)
615
        gcons_notify_connect(cons->index);
532
        gcons_notify_connect(cons->index);
616
   
533
   
617
    cons->refcount++;
534
    cons->refcount++;
618
   
535
   
619
    /* Accept the connection */
536
    /* Accept the connection */
620
    ipc_answer_0(iid, EOK);
537
    ipc_answer_0(iid, EOK);
621
   
538
   
622
    while (true) {
539
    while (true) {
623
        async_serialize_end();
540
        async_serialize_end();
624
        callid = async_get_call(&call);
541
        callid = async_get_call(&call);
625
        async_serialize_start();
542
        async_serialize_start();
626
       
543
       
627
        arg1 = 0;
544
        arg1 = 0;
628
        arg2 = 0;
545
        arg2 = 0;
629
        arg3 = 0;
546
        arg3 = 0;
630
       
547
       
631
        switch (IPC_GET_METHOD(call)) {
548
        switch (IPC_GET_METHOD(call)) {
632
        case IPC_M_PHONE_HUNGUP:
549
        case IPC_M_PHONE_HUNGUP:
633
            cons->refcount--;
550
            cons->refcount--;
634
            if (cons->refcount == 0)
551
            if (cons->refcount == 0)
635
                gcons_notify_disconnect(cons->index);
552
                gcons_notify_disconnect(cons->index);
636
            return;
553
            return;
637
        case VFS_READ:
554
        case VFS_READ:
638
            async_serialize_end();
555
            async_serialize_end();
639
            cons_read(cons, callid, &call);
556
            cons_read(cons, callid, &call);
640
            async_serialize_start();
557
            async_serialize_start();
641
            continue;
558
            continue;
642
        case VFS_WRITE:
559
        case VFS_WRITE:
643
            async_serialize_end();
560
            async_serialize_end();
644
            cons_write(cons, callid, &call);
561
            cons_write(cons, callid, &call);
645
            async_serialize_start();
562
            async_serialize_start();
646
            continue;
563
            continue;
647
        case VFS_SYNC:
564
        case VFS_SYNC:
648
            fb_pending_flush();
565
            fb_pending_flush();
649
            if (cons == active_console) {
566
            if (cons == active_console) {
650
                async_req_0_0(fb_info.phone, FB_FLUSH);
567
                async_req_0_0(fb_info.phone, FB_FLUSH);
651
               
568
               
652
                curs_goto(cons->scr.position_x, cons->scr.position_y);
569
                curs_goto(cons->scr.position_x, cons->scr.position_y);
653
            }
570
            }
654
            break;
571
            break;
655
        case CONSOLE_CLEAR:
572
        case CONSOLE_CLEAR:
656
            /* Send message to fb */
573
            /* Send message to fb */
657
            if (cons == active_console)
574
            if (cons == active_console)
658
                async_msg_0(fb_info.phone, FB_CLEAR);
575
                async_msg_0(fb_info.phone, FB_CLEAR);
659
           
576
           
660
            screenbuffer_clear(&cons->scr);
577
            screenbuffer_clear(&cons->scr);
661
           
578
           
662
            break;
579
            break;
663
        case CONSOLE_GOTO:
580
        case CONSOLE_GOTO:
664
            screenbuffer_goto(&cons->scr,
581
            screenbuffer_goto(&cons->scr,
665
                IPC_GET_ARG1(call), IPC_GET_ARG2(call));
582
                IPC_GET_ARG1(call), IPC_GET_ARG2(call));
666
            if (cons == active_console)
583
            if (cons == active_console)
667
                curs_goto(IPC_GET_ARG1(call),
584
                curs_goto(IPC_GET_ARG1(call),
668
                    IPC_GET_ARG2(call));
585
                    IPC_GET_ARG2(call));
669
            break;
586
            break;
670
        case CONSOLE_GET_SIZE:
587
        case CONSOLE_GET_SIZE:
671
            arg1 = fb_info.cols;
588
            arg1 = fb_info.cols;
672
            arg2 = fb_info.rows;
589
            arg2 = fb_info.rows;
673
            break;
590
            break;
674
        case CONSOLE_SET_STYLE:
591
        case CONSOLE_SET_STYLE:
675
            fb_pending_flush();
592
            fb_pending_flush();
676
            arg1 = IPC_GET_ARG1(call);
593
            arg1 = IPC_GET_ARG1(call);
677
            screenbuffer_set_style(&cons->scr, arg1);
594
            screenbuffer_set_style(&cons->scr, arg1);
678
            if (cons == active_console)
595
            if (cons == active_console)
679
                set_style(arg1);
596
                set_style(arg1);
680
            break;
597
            break;
681
        case CONSOLE_SET_COLOR:
598
        case CONSOLE_SET_COLOR:
682
            fb_pending_flush();
599
            fb_pending_flush();
683
            arg1 = IPC_GET_ARG1(call);
600
            arg1 = IPC_GET_ARG1(call);
684
            arg2 = IPC_GET_ARG2(call);
601
            arg2 = IPC_GET_ARG2(call);
685
            arg3 = IPC_GET_ARG3(call);
602
            arg3 = IPC_GET_ARG3(call);
686
            screenbuffer_set_color(&cons->scr, arg1, arg2, arg3);
603
            screenbuffer_set_color(&cons->scr, arg1, arg2, arg3);
687
            if (cons == active_console)
604
            if (cons == active_console)
688
                set_color(arg1, arg2, arg3);
605
                set_color(arg1, arg2, arg3);
689
            break;
606
            break;
690
        case CONSOLE_SET_RGB_COLOR:
607
        case CONSOLE_SET_RGB_COLOR:
691
            fb_pending_flush();
608
            fb_pending_flush();
692
            arg1 = IPC_GET_ARG1(call);
609
            arg1 = IPC_GET_ARG1(call);
693
            arg2 = IPC_GET_ARG2(call);
610
            arg2 = IPC_GET_ARG2(call);
694
            screenbuffer_set_rgb_color(&cons->scr, arg1, arg2);
611
            screenbuffer_set_rgb_color(&cons->scr, arg1, arg2);
695
            if (cons == active_console)
612
            if (cons == active_console)
696
                set_rgb_color(arg1, arg2);
613
                set_rgb_color(arg1, arg2);
697
            break;
614
            break;
698
        case CONSOLE_CURSOR_VISIBILITY:
615
        case CONSOLE_CURSOR_VISIBILITY:
699
            fb_pending_flush();
616
            fb_pending_flush();
700
            arg1 = IPC_GET_ARG1(call);
617
            arg1 = IPC_GET_ARG1(call);
701
            cons->scr.is_cursor_visible = arg1;
618
            cons->scr.is_cursor_visible = arg1;
702
            if (cons == active_console)
619
            if (cons == active_console)
703
                curs_visibility(arg1);
620
                curs_visibility(arg1);
704
            break;
621
            break;
705
        case CONSOLE_GET_EVENT:
622
        case CONSOLE_GET_EVENT:
706
            async_serialize_end();
623
            async_serialize_end();
707
            cons_get_event(cons, callid, &call);
624
            cons_get_event(cons, callid, &call);
708
            async_serialize_start();
625
            async_serialize_start();
709
            continue;
626
            continue;
710
        case CONSOLE_KCON_ENABLE:
627
        case CONSOLE_KCON_ENABLE:
711
            change_console(kernel_console);
628
            change_console(kernel_console);
712
            break;
629
            break;
713
        }
630
        }
714
        ipc_answer_3(callid, EOK, arg1, arg2, arg3);
631
        ipc_answer_3(callid, EOK, arg1, arg2, arg3);
715
    }
632
    }
716
}
633
}
717
 
634
 
718
static void interrupt_received(ipc_callid_t callid, ipc_call_t *call)
635
static void interrupt_received(ipc_callid_t callid, ipc_call_t *call)
719
{
636
{
720
    change_console(prev_console);
637
    change_console(prev_console);
721
}
638
}
722
 
639
 
723
static bool console_init(void)
640
static bool console_init(void)
724
{
641
{
725
    /* Connect to keyboard driver */
642
    /* Connect to keyboard driver */
726
    kbd_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_KEYBOARD, 0, 0);
643
    kbd_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_KEYBOARD, 0, 0);
727
    if (kbd_phone < 0) {
644
    if (kbd_phone < 0) {
728
        printf(NAME ": Failed to connect to keyboard service\n");
645
        printf(NAME ": Failed to connect to keyboard service\n");
729
        return false;
646
        return false;
730
    }
647
    }
731
   
648
   
732
    ipcarg_t phonehash;
649
    ipcarg_t phonehash;
733
    if (ipc_connect_to_me(kbd_phone, SERVICE_CONSOLE, 0, 0, &phonehash) != 0) {
650
    if (ipc_connect_to_me(kbd_phone, SERVICE_CONSOLE, 0, 0, &phonehash) != 0) {
734
        printf(NAME ": Failed to create callback from keyboard service\n");
651
        printf(NAME ": Failed to create callback from keyboard service\n");
735
        return false;
652
        return false;
736
    }
653
    }
737
   
654
   
738
    async_new_connection(phonehash, 0, NULL, keyboard_events);
655
    async_new_connection(phonehash, 0, NULL, keyboard_events);
739
 
656
 
740
    fid_t fid = fibril_create(process_pending_input, NULL);
-
 
741
    if (!fid) {
-
 
742
        printf(NAME ": Failed to create fibril for handling pending "
-
 
743
            "input\n");
-
 
744
        return -1;
-
 
745
    }
-
 
746
    fibril_add_ready(fid);
-
 
747
   
-
 
748
    /* Connect to framebuffer driver */
657
    /* Connect to framebuffer driver */
749
    fb_info.phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VIDEO, 0, 0);
658
    fb_info.phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VIDEO, 0, 0);
750
    if (fb_info.phone < 0) {
659
    if (fb_info.phone < 0) {
751
        printf(NAME ": Failed to connect to video service\n");
660
        printf(NAME ": Failed to connect to video service\n");
752
        return -1;
661
        return -1;
753
    }
662
    }
754
   
663
   
755
    /* Register driver */
664
    /* Register driver */
756
    int rc = devmap_driver_register(NAME, client_connection);
665
    int rc = devmap_driver_register(NAME, client_connection);
757
    if (rc < 0) {
666
    if (rc < 0) {
758
        printf(NAME ": Unable to register driver (%d)\n", rc);
667
        printf(NAME ": Unable to register driver (%d)\n", rc);
759
        return false;
668
        return false;
760
    }
669
    }
761
   
670
   
762
    /* Initialize gcons */
671
    /* Initialize gcons */
763
    gcons_init(fb_info.phone);
672
    gcons_init(fb_info.phone);
764
   
673
   
765
    /* Synchronize, the gcons could put something in queue */
674
    /* Synchronize, the gcons could put something in queue */
766
    async_req_0_0(fb_info.phone, FB_FLUSH);
675
    async_req_0_0(fb_info.phone, FB_FLUSH);
767
    async_req_0_2(fb_info.phone, FB_GET_CSIZE, &fb_info.cols, &fb_info.rows);
676
    async_req_0_2(fb_info.phone, FB_GET_CSIZE, &fb_info.cols, &fb_info.rows);
768
   
677
   
769
    /* Set up shared memory buffer. */
678
    /* Set up shared memory buffer. */
770
    size_t ib_size = sizeof(keyfield_t) * fb_info.cols * fb_info.rows;
679
    size_t ib_size = sizeof(keyfield_t) * fb_info.cols * fb_info.rows;
771
    interbuffer = as_get_mappable_page(ib_size);
680
    interbuffer = as_get_mappable_page(ib_size);
772
   
681
   
773
    if (as_area_create(interbuffer, ib_size, AS_AREA_READ |
682
    if (as_area_create(interbuffer, ib_size, AS_AREA_READ |
774
        AS_AREA_WRITE | AS_AREA_CACHEABLE) != interbuffer)
683
        AS_AREA_WRITE | AS_AREA_CACHEABLE) != interbuffer)
775
        interbuffer = NULL;
684
        interbuffer = NULL;
776
   
685
   
777
    if (interbuffer) {
686
    if (interbuffer) {
778
        if (ipc_share_out_start(fb_info.phone, interbuffer,
687
        if (ipc_share_out_start(fb_info.phone, interbuffer,
779
            AS_AREA_READ) != EOK) {
688
            AS_AREA_READ) != EOK) {
780
            as_area_destroy(interbuffer);
689
            as_area_destroy(interbuffer);
781
            interbuffer = NULL;
690
            interbuffer = NULL;
782
        }
691
        }
783
    }
692
    }
784
   
693
   
785
    fb_pending.cnt = 0;
694
    fb_pending.cnt = 0;
786
   
695
   
787
    /* Inititalize consoles */
696
    /* Inititalize consoles */
788
    size_t i;
697
    size_t i;
789
    for (i = 0; i < CONSOLE_COUNT; i++) {
698
    for (i = 0; i < CONSOLE_COUNT; i++) {
790
        if (i != KERNEL_CONSOLE) {
699
        if (i != KERNEL_CONSOLE) {
791
            if (screenbuffer_init(&consoles[i].scr,
700
            if (screenbuffer_init(&consoles[i].scr,
792
                fb_info.cols, fb_info.rows) == NULL) {
701
                fb_info.cols, fb_info.rows) == NULL) {
793
                printf(NAME ": Unable to allocate screen buffer %u\n", i);
702
                printf(NAME ": Unable to allocate screen buffer %u\n", i);
794
                return false;
703
                return false;
795
            }
704
            }
796
            screenbuffer_clear(&consoles[i].scr);
705
            screenbuffer_clear(&consoles[i].scr);
797
            keybuffer_init(&consoles[i].keybuffer);
706
            keybuffer_init(&consoles[i].keybuffer);
798
            consoles[i].index = i;
707
            consoles[i].index = i;
799
            consoles[i].refcount = 0;
708
            consoles[i].refcount = 0;
800
           
709
           
801
            char vc[MAX_DEVICE_NAME];
710
            char vc[MAX_DEVICE_NAME];
802
            snprintf(vc, MAX_DEVICE_NAME, "vc%u", i);
711
            snprintf(vc, MAX_DEVICE_NAME, "vc%u", i);
803
           
712
           
804
            if (devmap_device_register(vc, &consoles[i].dev_handle) != EOK) {
713
            if (devmap_device_register(vc, &consoles[i].dev_handle) != EOK) {
805
                devmap_hangup_phone(DEVMAP_DRIVER);
714
                devmap_hangup_phone(DEVMAP_DRIVER);
806
                printf(NAME ": Unable to register device %s\n", vc);
715
                printf(NAME ": Unable to register device %s\n", vc);
807
                return false;
716
                return false;
808
            }
717
            }
809
        }
718
        }
810
    }
719
    }
811
   
720
   
812
    /* Disable kernel output to the console */
721
    /* Disable kernel output to the console */
813
    __SYSCALL0(SYS_DEBUG_DISABLE_CONSOLE);
722
    __SYSCALL0(SYS_DEBUG_DISABLE_CONSOLE);
814
   
723
   
815
    /* Initialize the screen */
724
    /* Initialize the screen */
816
    async_serialize_start();
725
    async_serialize_start();
817
    gcons_redraw_console();
726
    gcons_redraw_console();
818
    set_rgb_color(DEFAULT_FOREGROUND, DEFAULT_BACKGROUND);
727
    set_rgb_color(DEFAULT_FOREGROUND, DEFAULT_BACKGROUND);
819
    screen_clear();
728
    screen_clear();
820
    curs_goto(0, 0);
729
    curs_goto(0, 0);
821
    curs_visibility(active_console->scr.is_cursor_visible);
730
    curs_visibility(active_console->scr.is_cursor_visible);
822
    async_serialize_end();
731
    async_serialize_end();
823
   
732
   
824
    /* Receive kernel notifications */
733
    /* Receive kernel notifications */
825
    if (event_subscribe(EVENT_KCONSOLE, 0) != EOK)
734
    if (event_subscribe(EVENT_KCONSOLE, 0) != EOK)
826
        printf(NAME ": Error registering kconsole notifications\n");
735
        printf(NAME ": Error registering kconsole notifications\n");
827
   
736
   
828
    async_set_interrupt_received(interrupt_received);
737
    async_set_interrupt_received(interrupt_received);
829
   
738
   
830
    return true;
739
    return true;
831
}
740
}
832
 
741
 
833
int main(int argc, char *argv[])
742
int main(int argc, char *argv[])
834
{
743
{
835
    printf(NAME ": HelenOS Console service\n");
744
    printf(NAME ": HelenOS Console service\n");
836
   
745
   
837
    if (!console_init())
746
    if (!console_init())
838
        return -1;
747
        return -1;
839
   
748
   
840
    printf(NAME ": Accepting connections\n");
749
    printf(NAME ": Accepting connections\n");
841
    async_manager();
750
    async_manager();
842
   
751
   
843
    return 0;
752
    return 0;
844
}
753
}
845
 
754
 
846
/** @}
755
/** @}
847
 */
756
 */
848
 
757