Subversion Repositories HelenOS-historic

Rev

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

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