Subversion Repositories HelenOS-historic

Rev

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

Rev 1525 Rev 1526
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
 
29
 
30
#include <kbd.h>
30
#include <kbd.h>
31
#include <fb.h>
31
#include <fb.h>
32
#include <ipc/ipc.h>
32
#include <ipc/ipc.h>
33
#include <ipc/fb.h>
33
#include <ipc/fb.h>
34
#include <ipc/services.h>
34
#include <ipc/services.h>
35
#include <errno.h>
35
#include <errno.h>
36
#include <key_buffer.h>
36
#include <key_buffer.h>
37
#include <console.h>
37
#include <console.h>
38
#include <unistd.h>
38
#include <unistd.h>
39
#include <async.h>
39
#include <async.h>
40
#include <libadt/fifo.h>
40
#include <libadt/fifo.h>
41
#include <screenbuffer.h>
41
#include <screenbuffer.h>
42
#include <sys/mman.h>
42
#include <sys/mman.h>
43
 
43
 
44
#include "gcons.h"
44
#include "gcons.h"
45
 
45
 
46
#define MAX_KEYREQUESTS_BUFFERED 32
46
#define MAX_KEYREQUESTS_BUFFERED 32
47
 
47
 
48
#define NAME "CONSOLE"
48
#define NAME "CONSOLE"
49
 
49
 
-
 
50
/** Index of currently used virtual console.
-
 
51
 */
50
int active_console = 0;
52
int active_console = 0;
51
 
53
 
-
 
54
/** Information about framebuffer
-
 
55
 */
52
struct {
56
struct {
53
    int phone;      /**< Framebuffer phone */
57
    int phone;      /**< Framebuffer phone */
54
    ipcarg_t rows;      /**< Framebuffer rows */
58
    ipcarg_t rows;      /**< Framebuffer rows */
55
    ipcarg_t cols;      /**< Framebuffer columns */
59
    ipcarg_t cols;      /**< Framebuffer columns */
56
} fb_info;
60
} fb_info;
57
 
61
 
-
 
62
 
58
typedef struct {
63
typedef struct {
59
    keybuffer_t keybuffer;
64
    keybuffer_t keybuffer;      /**< Buffer for incoming keys. */
60
    FIFO_CREATE_STATIC(keyrequests, ipc_callid_t , MAX_KEYREQUESTS_BUFFERED);
65
    FIFO_CREATE_STATIC(keyrequests, ipc_callid_t , MAX_KEYREQUESTS_BUFFERED);   /**< Buffer for unsatisfied request for keys. */
61
    int keyrequest_counter;
66
    int keyrequest_counter;     /**< Number of requests in buffer. */
62
    int client_phone;
67
    int client_phone;       /**< Phone to connected client. */
63
    int used;
68
    int used;           /**< 1 if this virtual console is connected to some client.*/
64
    screenbuffer_t screenbuffer;
69
    screenbuffer_t screenbuffer;    /**< Screenbuffer for saving screen contents and related settings. */
65
} connection_t;
70
} connection_t;
66
 
71
 
-
 
72
connection_t connections[CONSOLE_COUNT];    /**< Array of data for virtual consoles */
-
 
73
keyfield_t *interbuffer = NULL;         /**< Pointer to memory shared with framebufer used for faster virt. console switching */
67
 
74
 
68
 
75
 
69
connection_t connections[CONSOLE_COUNT];
-
 
70
keyfield_t *interbuffer = NULL;
76
/** Find unused virtual console.
71
   
77
 *
-
 
78
 */
72
static int find_free_connection()
79
static int find_free_connection()
73
{
80
{
74
    int i = 0;
81
    int i = 0;
75
   
82
   
76
    while (i < CONSOLE_COUNT) {
83
    while (i < CONSOLE_COUNT) {
77
        if (connections[i].used == 0)
84
        if (connections[i].used == 0)
78
            return i;
85
            return i;
79
        ++i;
86
        ++i;
80
    }
87
    }
81
    return CONSOLE_COUNT;
88
    return CONSOLE_COUNT;
82
}
89
}
83
 
90
 
-
 
91
/** Find index of virtual console used by client with given phone.
84
 
92
 *
-
 
93
 */
85
static int find_connection(int client_phone)
94
static int find_connection(int client_phone)
86
{
95
{
87
    int i = 0;
96
    int i = 0;
88
   
97
   
89
    while (i < CONSOLE_COUNT) {
98
    while (i < CONSOLE_COUNT) {
90
        if (connections[i].client_phone == client_phone)
99
        if (connections[i].client_phone == client_phone)
91
            return i;
100
            return i;
92
        ++i;
101
        ++i;
93
    }
102
    }
94
    return  CONSOLE_COUNT;
103
    return  CONSOLE_COUNT;
95
}
104
}
96
 
105
 
97
/** Check key and process special keys.
106
/** Check key and process special keys.
98
 *
107
 *
99
 * */
108
 * */
100
static void write_char(int console, char key)
109
static void write_char(int console, char key)
101
{
110
{
102
    screenbuffer_t *scr = &(connections[console].screenbuffer);
111
    screenbuffer_t *scr = &(connections[console].screenbuffer);
103
   
112
   
104
    switch (key) {
113
    switch (key) {
105
        case '\n':
114
        case '\n':
106
            scr->position_y += 1;
115
            scr->position_y += 1;
107
            scr->position_x =  0;
116
            scr->position_x =  0;
108
            break;
117
            break;
109
        case '\r':
118
        case '\r':
110
            break;
119
            break;
111
        case '\t':
120
        case '\t':
112
            scr->position_x += 8;
121
            scr->position_x += 8;
113
            scr->position_x -= scr->position_x % 8;
122
            scr->position_x -= scr->position_x % 8;
114
            break;
123
            break;
115
        case '\b':
124
        case '\b':
116
            if (scr->position_x == 0)
125
            if (scr->position_x == 0)
117
                break;
126
                break;
118
 
127
 
119
            scr->position_x--;
128
            scr->position_x--;
120
 
129
 
121
            if (console == active_console) {
130
            if (console == active_console) {
122
                nsend_call_3(fb_info.phone, FB_PUTCHAR, ' ', scr->position_y, scr->position_x);
131
                nsend_call_3(fb_info.phone, FB_PUTCHAR, ' ', scr->position_y, scr->position_x);
123
            }
132
            }
124
   
133
   
125
            screenbuffer_putchar(scr, ' ');
134
            screenbuffer_putchar(scr, ' ');
126
           
135
           
127
            break;
136
            break;
128
        default:   
137
        default:   
129
            if (console == active_console) {
138
            if (console == active_console) {
130
                nsend_call_3(fb_info.phone, FB_PUTCHAR, key, scr->position_y, scr->position_x);
139
                nsend_call_3(fb_info.phone, FB_PUTCHAR, key, scr->position_y, scr->position_x);
131
            }
140
            }
132
   
141
   
133
            screenbuffer_putchar(scr, key);
142
            screenbuffer_putchar(scr, key);
134
            scr->position_x++;
143
            scr->position_x++;
135
    }
144
    }
136
   
145
   
137
    scr->position_y += (scr->position_x >= scr->size_x);
146
    scr->position_y += (scr->position_x >= scr->size_x);
138
   
147
   
139
    if (scr->position_y >= scr->size_y) {
148
    if (scr->position_y >= scr->size_y) {
140
        scr->position_y = scr->size_y - 1;
149
        scr->position_y = scr->size_y - 1;
141
        screenbuffer_clear_line(scr, scr->top_line++);
150
        screenbuffer_clear_line(scr, scr->top_line++);
142
        if (console == active_console)
151
        if (console == active_console)
143
            nsend_call(fb_info.phone, FB_SCROLL, 1);
152
            nsend_call(fb_info.phone, FB_SCROLL, 1);
144
    }
153
    }
145
   
154
   
146
    scr->position_x = scr->position_x % scr->size_x;
155
    scr->position_x = scr->position_x % scr->size_x;
147
   
156
   
148
    if (console == active_console) 
157
    if (console == active_console) 
149
        send_call_2(fb_info.phone, FB_CURSOR_GOTO, scr->position_y, scr->position_x);
158
        send_call_2(fb_info.phone, FB_CURSOR_GOTO, scr->position_y, scr->position_x);
150
   
159
   
151
}
160
}
152
 
161
 
153
 
162
 
154
/* Handler for keyboard */
163
/** Handler for keyboard */
155
static void keyboard_events(ipc_callid_t iid, ipc_call_t *icall)
164
static void keyboard_events(ipc_callid_t iid, ipc_call_t *icall)
156
{
165
{
157
    ipc_callid_t callid;
166
    ipc_callid_t callid;
158
    ipc_call_t call;
167
    ipc_call_t call;
159
    int retval;
168
    int retval;
160
    int i, j;
169
    int i, j;
161
    char c,d;
170
    char c,d;
162
    connection_t *conn;
171
    connection_t *conn;
163
   
172
   
164
    /* Ignore parameters, the connection is alread opened */
173
    /* Ignore parameters, the connection is alread opened */
165
    while (1) {
174
    while (1) {
166
        callid = async_get_call(&call);
175
        callid = async_get_call(&call);
167
        switch (IPC_GET_METHOD(call)) {
176
        switch (IPC_GET_METHOD(call)) {
168
        case IPC_M_PHONE_HUNGUP:
177
        case IPC_M_PHONE_HUNGUP:
169
            ipc_answer_fast(callid,0,0,0);
178
            ipc_answer_fast(callid,0,0,0);
170
            /* TODO: Handle hangup */
179
            /* TODO: Handle hangup */
171
            return;
180
            return;
172
        case KBD_PUSHCHAR:
181
        case KBD_PUSHCHAR:
173
            /* got key from keyboard driver */
182
            /* got key from keyboard driver */
174
           
183
           
175
            retval = 0;
184
            retval = 0;
176
            c = IPC_GET_ARG1(call);
185
            c = IPC_GET_ARG1(call);
177
            /* switch to another virtual console */
186
            /* switch to another virtual console */
178
           
187
           
179
            conn = &connections[active_console];
188
            conn = &connections[active_console];
180
//          if ((c >= KBD_KEY_F1) && (c < KBD_KEY_F1 + CONSOLE_COUNT)) {
189
//          if ((c >= KBD_KEY_F1) && (c < KBD_KEY_F1 + CONSOLE_COUNT)) {
181
            if ((c >= '0') && (c < '0' + CONSOLE_COUNT)) {
190
            if ((c >= '0') && (c < '0' + CONSOLE_COUNT)) {
182
                if (c == '0') {
191
                if (c == '0') {
183
                    /* switch to kernel console*/
192
                    /* switch to kernel console*/
184
                    nsend_call(fb_info.phone, FB_CURSOR_VISIBILITY, 0);
193
                    nsend_call(fb_info.phone, FB_CURSOR_VISIBILITY, 0);
185
                    nsend_call_2(fb_info.phone, FB_SET_STYLE, DEFAULT_FOREGROUND_COLOR, DEFAULT_BACKGROUND_COLOR);
194
                    nsend_call_2(fb_info.phone, FB_SET_STYLE, DEFAULT_FOREGROUND_COLOR, DEFAULT_BACKGROUND_COLOR);
186
                    nsend_call(fb_info.phone, FB_CLEAR, 0);
195
                    nsend_call(fb_info.phone, FB_CLEAR, 0);
187
                    /* FIXME: restore kernel console */
196
                    /* FIXME: restore kernel console */
188
                     __SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE);
197
                     __SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE);
189
                     break;
198
                     break;
190
                     
199
                     
191
                } else {
200
                } else {
192
                    c = c - '1';
201
                    c = c - '1';
193
                    if (c == active_console)
202
                    if (c == active_console)
194
                        break;
203
                        break;
195
                    active_console = c;
204
                    active_console = c;
196
                    gcons_change_console(c);
205
                    gcons_change_console(c);
197
               
206
               
198
                }
207
                }
199
               
208
               
200
                conn = &connections[active_console];
209
                conn = &connections[active_console];
201
 
210
 
202
                nsend_call(fb_info.phone, FB_CURSOR_VISIBILITY, 0);
211
                nsend_call(fb_info.phone, FB_CURSOR_VISIBILITY, 0);
203
       
212
       
204
                if (interbuffer) {
213
                if (interbuffer) {
205
                    for (i = 0; i < conn->screenbuffer.size_x; i++)
214
                    for (i = 0; i < conn->screenbuffer.size_x; i++)
206
                        for (j = 0; j < conn->screenbuffer.size_y; j++)
215
                        for (j = 0; j < conn->screenbuffer.size_y; j++)
207
                            interbuffer[i + j*conn->screenbuffer.size_x] = *get_field_at(&(conn->screenbuffer),i, j);
216
                            interbuffer[i + j*conn->screenbuffer.size_x] = *get_field_at(&(conn->screenbuffer),i, j);
208
                           
217
                           
209
                    sync_send_2(fb_info.phone, FB_DRAW_TEXT_DATA, 0, 0, NULL, NULL);       
218
                    sync_send_2(fb_info.phone, FB_DRAW_TEXT_DATA, 0, 0, NULL, NULL);       
210
                } else {
219
                } else {
211
                    nsend_call(fb_info.phone, FB_CLEAR, 0);
220
                    nsend_call(fb_info.phone, FB_CLEAR, 0);
212
               
221
               
213
                   
222
                   
214
                    for (i = 0; i < conn->screenbuffer.size_x; i++)
223
                    for (i = 0; i < conn->screenbuffer.size_x; i++)
215
                        for (j = 0; j < conn->screenbuffer.size_y; j++) {
224
                        for (j = 0; j < conn->screenbuffer.size_y; j++) {
216
                            d = get_field_at(&(conn->screenbuffer),i, j)->character;
225
                            d = get_field_at(&(conn->screenbuffer),i, j)->character;
217
                            if (d && d != ' ')
226
                            if (d && d != ' ')
218
                                nsend_call_3(fb_info.phone, FB_PUTCHAR, d, j, i);
227
                                nsend_call_3(fb_info.phone, FB_PUTCHAR, d, j, i);
219
                        }
228
                        }
220
 
229
 
221
                }
230
                }
222
                nsend_call_2(fb_info.phone, FB_CURSOR_GOTO, conn->screenbuffer.position_y, conn->screenbuffer.position_x);
231
                nsend_call_2(fb_info.phone, FB_CURSOR_GOTO, conn->screenbuffer.position_y, conn->screenbuffer.position_x);
223
                nsend_call_2(fb_info.phone, FB_SET_STYLE, conn->screenbuffer.style.fg_color, \
232
                nsend_call_2(fb_info.phone, FB_SET_STYLE, conn->screenbuffer.style.fg_color, \
224
                        conn->screenbuffer.style.bg_color);
233
                        conn->screenbuffer.style.bg_color);
225
                send_call(fb_info.phone, FB_CURSOR_VISIBILITY, 1);
234
                send_call(fb_info.phone, FB_CURSOR_VISIBILITY, 1);
226
 
235
 
227
                break;
236
                break;
228
            }
237
            }
229
           
238
           
230
            /* if client is awaiting key, send it */
239
            /* if client is awaiting key, send it */
231
            if (conn->keyrequest_counter > 0) {    
240
            if (conn->keyrequest_counter > 0) {    
232
                conn->keyrequest_counter--;
241
                conn->keyrequest_counter--;
233
                ipc_answer_fast(fifo_pop(conn->keyrequests), 0, c, 0);
242
                ipc_answer_fast(fifo_pop(conn->keyrequests), 0, c, 0);
234
                break;
243
                break;
235
            }
244
            }
236
           
245
           
237
            /*FIXME: else store key to its buffer */
246
            /*FIXME: else store key to its buffer */
238
            keybuffer_push(&conn->keybuffer, c);
247
            keybuffer_push(&conn->keybuffer, c);
239
           
248
           
240
            break;
249
            break;
241
        default:
250
        default:
242
            retval = ENOENT;
251
            retval = ENOENT;
243
        }      
252
        }      
244
        ipc_answer_fast(callid, retval, 0, 0);
253
        ipc_answer_fast(callid, retval, 0, 0);
245
    }
254
    }
246
}
255
}
247
 
256
 
248
/** Default thread for new connections */
257
/** Default thread for new connections */
249
static void client_connection(ipc_callid_t iid, ipc_call_t *icall)
258
static void client_connection(ipc_callid_t iid, ipc_call_t *icall)
250
{
259
{
251
    ipc_callid_t callid;
260
    ipc_callid_t callid;
252
    ipc_call_t call;
261
    ipc_call_t call;
253
    int consnum;
262
    int consnum;
254
    ipcarg_t arg1, arg2;
263
    ipcarg_t arg1, arg2;
255
 
264
 
256
    if ((consnum = find_free_connection()) == CONSOLE_COUNT) {
265
    if ((consnum = find_free_connection()) == CONSOLE_COUNT) {
257
        ipc_answer_fast(iid,ELIMIT,0,0);
266
        ipc_answer_fast(iid,ELIMIT,0,0);
258
        return;
267
        return;
259
    }
268
    }
260
 
269
 
261
    connections[consnum].used = 1;
270
    connections[consnum].used = 1;
262
    connections[consnum].client_phone = IPC_GET_ARG3(call);
271
    connections[consnum].client_phone = IPC_GET_ARG3(call);
263
    screenbuffer_clear(&(connections[consnum].screenbuffer));
272
    screenbuffer_clear(&(connections[consnum].screenbuffer));
264
   
273
   
265
    /* Accept the connection */
274
    /* Accept the connection */
266
    ipc_answer_fast(iid,0,0,0);
275
    ipc_answer_fast(iid,0,0,0);
267
   
276
   
268
    while (1) {
277
    while (1) {
269
        callid = async_get_call(&call);
278
        callid = async_get_call(&call);
270
        arg1 = arg2 = 0;
279
        arg1 = arg2 = 0;
271
        switch (IPC_GET_METHOD(call)) {
280
        switch (IPC_GET_METHOD(call)) {
272
        case IPC_M_PHONE_HUNGUP:
281
        case IPC_M_PHONE_HUNGUP:
273
            /* TODO */
282
            /* TODO */
274
            ipc_answer_fast(callid, 0,0,0);
283
            ipc_answer_fast(callid, 0,0,0);
275
            return;
284
            return;
276
        case CONSOLE_PUTCHAR:
285
        case CONSOLE_PUTCHAR:
277
            write_char(consnum, IPC_GET_ARG1(call));
286
            write_char(consnum, IPC_GET_ARG1(call));
278
            break;
287
            break;
279
        case CONSOLE_CLEAR:
288
        case CONSOLE_CLEAR:
280
            /* Send message to fb */
289
            /* Send message to fb */
281
            if (consnum == active_console) {
290
            if (consnum == active_console) {
282
                send_call(fb_info.phone, FB_CLEAR, 0);
291
                send_call(fb_info.phone, FB_CLEAR, 0);
283
            }
292
            }
284
           
293
           
285
            screenbuffer_clear(&(connections[consnum].screenbuffer));
294
            screenbuffer_clear(&(connections[consnum].screenbuffer));
286
           
295
           
287
            break;
296
            break;
288
        case CONSOLE_GOTO:
297
        case CONSOLE_GOTO:
289
           
298
           
290
            screenbuffer_goto(&(connections[consnum].screenbuffer), IPC_GET_ARG1(call), IPC_GET_ARG2(call));
299
            screenbuffer_goto(&(connections[consnum].screenbuffer), IPC_GET_ARG1(call), IPC_GET_ARG2(call));
291
           
300
           
292
            break;
301
            break;
293
 
302
 
294
        case CONSOLE_GETSIZE:
303
        case CONSOLE_GETSIZE:
295
            arg1 = fb_info.cols;
304
            arg1 = fb_info.cols;
296
            arg2 = fb_info.rows;
305
            arg2 = fb_info.rows;
297
            break;
306
            break;
298
        case CONSOLE_FLUSH:
307
        case CONSOLE_FLUSH:
299
            sync_send_2(fb_info.phone, FB_FLUSH, 0, 0, NULL, NULL);    
308
            sync_send_2(fb_info.phone, FB_FLUSH, 0, 0, NULL, NULL);    
300
            break;
309
            break;
301
        case CONSOLE_SET_STYLE:
310
        case CONSOLE_SET_STYLE:
302
           
311
           
303
            arg1 = IPC_GET_ARG1(call);
312
            arg1 = IPC_GET_ARG1(call);
304
            arg2 = IPC_GET_ARG2(call);
313
            arg2 = IPC_GET_ARG2(call);
305
            screenbuffer_set_style(&(connections[consnum]),arg1, arg2);
314
            screenbuffer_set_style(&(connections[consnum]),arg1, arg2);
306
            if (consnum == active_console)
315
            if (consnum == active_console)
307
                nsend_call_2(fb_info.phone, FB_SET_STYLE, arg1, arg2);
316
                nsend_call_2(fb_info.phone, FB_SET_STYLE, arg1, arg2);
308
               
317
               
309
            break;
318
            break;
310
        case CONSOLE_GETCHAR:
319
        case CONSOLE_GETCHAR:
311
            if (keybuffer_empty(&(connections[consnum].keybuffer))) {
320
            if (keybuffer_empty(&(connections[consnum].keybuffer))) {
312
                /* buffer is empty -> store request */
321
                /* buffer is empty -> store request */
313
                if (connections[consnum].keyrequest_counter < MAX_KEYREQUESTS_BUFFERED) {      
322
                if (connections[consnum].keyrequest_counter < MAX_KEYREQUESTS_BUFFERED) {      
314
                    fifo_push(connections[consnum].keyrequests, callid);
323
                    fifo_push(connections[consnum].keyrequests, callid);
315
                    connections[consnum].keyrequest_counter++;
324
                    connections[consnum].keyrequest_counter++;
316
                } else {
325
                } else {
317
                    /* no key available and too many requests => fail */
326
                    /* no key available and too many requests => fail */
318
                    ipc_answer_fast(callid, ELIMIT, 0, 0);
327
                    ipc_answer_fast(callid, ELIMIT, 0, 0);
319
                }
328
                }
320
                continue;
329
                continue;
321
            };
330
            };
322
            keybuffer_pop(&(connections[consnum].keybuffer), (char *)&arg1);
331
            keybuffer_pop(&(connections[consnum].keybuffer), (char *)&arg1);
323
           
332
           
324
            break;
333
            break;
325
        }
334
        }
326
        ipc_answer_fast(callid, 0, arg1, arg2);
335
        ipc_answer_fast(callid, 0, arg1, arg2);
327
    }
336
    }
328
}
337
}
329
 
338
 
330
int main(int argc, char *argv[])
339
int main(int argc, char *argv[])
331
{
340
{
332
    ipcarg_t phonehash;
341
    ipcarg_t phonehash;
333
    int kbd_phone, fb_phone;
342
    int kbd_phone, fb_phone;
334
    ipcarg_t retval, arg1 = 0xdead, arg2 = 0xbeef;
343
    ipcarg_t retval, arg1 = 0xdead, arg2 = 0xbeef;
335
    int i;
344
    int i;
336
 
345
 
337
    async_set_client_connection(client_connection);
346
    async_set_client_connection(client_connection);
338
   
347
   
339
    /* Connect to keyboard driver */
348
    /* Connect to keyboard driver */
340
 
349
 
341
    while ((kbd_phone = ipc_connect_me_to(PHONE_NS, SERVICE_KEYBOARD, 0)) < 0) {
350
    while ((kbd_phone = ipc_connect_me_to(PHONE_NS, SERVICE_KEYBOARD, 0)) < 0) {
342
        usleep(10000);
351
        usleep(10000);
343
    };
352
    };
344
   
353
   
345
    if (ipc_connect_to_me(kbd_phone, SERVICE_CONSOLE, 0, &phonehash) != 0) {
354
    if (ipc_connect_to_me(kbd_phone, SERVICE_CONSOLE, 0, &phonehash) != 0) {
346
        return -1;
355
        return -1;
347
    };
356
    };
348
 
357
 
349
    /* Connect to framebuffer driver */
358
    /* Connect to framebuffer driver */
350
   
359
   
351
    while ((fb_info.phone = ipc_connect_me_to(PHONE_NS, SERVICE_VIDEO, 0)) < 0) {
360
    while ((fb_info.phone = ipc_connect_me_to(PHONE_NS, SERVICE_VIDEO, 0)) < 0) {
352
        usleep(10000);
361
        usleep(10000);
353
    }
362
    }
354
 
363
 
355
    /* Initialize gcons */
364
    /* Initialize gcons */
356
    gcons_init(fb_info.phone);
365
    gcons_init(fb_info.phone);
357
    /* Synchronize, the gcons can have something in queue */
366
    /* Synchronize, the gcons can have something in queue */
358
    sync_send_2(fb_info.phone, FB_GET_CSIZE, 0, 0, NULL, NULL);
367
    sync_send_2(fb_info.phone, FB_GET_CSIZE, 0, 0, NULL, NULL);
359
 
368
 
360
   
369
   
361
    ipc_call_sync_2(fb_info.phone, FB_GET_CSIZE, 0, 0, &(fb_info.rows), &(fb_info.cols));
370
    ipc_call_sync_2(fb_info.phone, FB_GET_CSIZE, 0, 0, &(fb_info.rows), &(fb_info.cols));
362
    nsend_call_2(fb_info.phone, FB_SET_STYLE, DEFAULT_FOREGROUND_COLOR, DEFAULT_BACKGROUND_COLOR);
371
    nsend_call_2(fb_info.phone, FB_SET_STYLE, DEFAULT_FOREGROUND_COLOR, DEFAULT_BACKGROUND_COLOR);
363
    nsend_call(fb_info.phone, FB_CLEAR, 0);
372
    nsend_call(fb_info.phone, FB_CLEAR, 0);
364
   
373
   
365
    /* Init virtual consoles */
374
    /* Init virtual consoles */
366
    for (i = 0; i < CONSOLE_COUNT; i++) {
375
    for (i = 0; i < CONSOLE_COUNT; i++) {
367
        connections[i].used = 0;
376
        connections[i].used = 0;
368
        keybuffer_init(&(connections[i].keybuffer));
377
        keybuffer_init(&(connections[i].keybuffer));
369
       
378
       
370
        connections[i].keyrequests.head = connections[i].keyrequests.tail = 0;
379
        connections[i].keyrequests.head = connections[i].keyrequests.tail = 0;
371
        connections[i].keyrequests.items = MAX_KEYREQUESTS_BUFFERED;
380
        connections[i].keyrequests.items = MAX_KEYREQUESTS_BUFFERED;
372
        connections[i].keyrequest_counter = 0;
381
        connections[i].keyrequest_counter = 0;
373
       
382
       
374
        if (screenbuffer_init(&(connections[i].screenbuffer), fb_info.cols, fb_info.rows ) == NULL) {
383
        if (screenbuffer_init(&(connections[i].screenbuffer), fb_info.cols, fb_info.rows ) == NULL) {
375
            /*FIXME: handle error */
384
            /*FIXME: handle error */
376
            return -1;
385
            return -1;
377
        }
386
        }
378
    }
387
    }
379
   
388
   
380
    if ((interbuffer = mmap(NULL, sizeof(keyfield_t) * fb_info.cols * fb_info.rows , PROTO_READ|PROTO_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, 0 ,0 )) != NULL) {
389
    if ((interbuffer = mmap(NULL, sizeof(keyfield_t) * fb_info.cols * fb_info.rows , PROTO_READ|PROTO_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, 0 ,0 )) != NULL) {
381
        if (ipc_call_sync_3(fb_info.phone, IPC_M_AS_AREA_SEND, (ipcarg_t)interbuffer, 0, AS_AREA_READ | AS_AREA_CACHEABLE, NULL, NULL, NULL) != 0) {
390
        if (ipc_call_sync_3(fb_info.phone, IPC_M_AS_AREA_SEND, (ipcarg_t)interbuffer, 0, AS_AREA_READ | AS_AREA_CACHEABLE, NULL, NULL, NULL) != 0) {
382
            munmap(interbuffer, sizeof(keyfield_t) * fb_info.cols * fb_info.rows);
391
            munmap(interbuffer, sizeof(keyfield_t) * fb_info.cols * fb_info.rows);
383
            interbuffer = NULL;
392
            interbuffer = NULL;
384
        }
393
        }
385
    }
394
    }
386
 
395
 
387
    /* FIXME: save kernel console screen */
396
    /* FIXME: save kernel console screen */
388
   
397
   
389
    async_new_connection(phonehash, 0, NULL, keyboard_events);
398
    async_new_connection(phonehash, 0, NULL, keyboard_events);
390
   
399
   
391
    sync_send_2(fb_info.phone, FB_CURSOR_GOTO, 0, 0, NULL, NULL);
400
    sync_send_2(fb_info.phone, FB_CURSOR_GOTO, 0, 0, NULL, NULL);
392
    nsend_call(fb_info.phone, FB_CURSOR_VISIBILITY, 1);
401
    nsend_call(fb_info.phone, FB_CURSOR_VISIBILITY, 1);
393
 
402
 
394
    /* Register at NS */
403
    /* Register at NS */
395
    if (ipc_connect_to_me(PHONE_NS, SERVICE_CONSOLE, 0, &phonehash) != 0) {
404
    if (ipc_connect_to_me(PHONE_NS, SERVICE_CONSOLE, 0, &phonehash) != 0) {
396
        return -1;
405
        return -1;
397
    };
406
    };
398
   
407
   
399
    async_manager();
408
    async_manager();
400
 
409
 
401
    return 0;  
410
    return 0;  
402
}
411
}
403
 
412
 
404
 
413