Subversion Repositories HelenOS

Rev

Rev 3675 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3675 Rev 4377
Line 36... Line 36...
36
 
36
 
37
/** @file
37
/** @file
38
 */
38
 */
39
 
39
 
40
#include <stdio.h>
40
#include <stdio.h>
-
 
41
#include <ipc/ipc.h>
-
 
42
#include <async.h>
-
 
43
#include <ipc/fb.h>
-
 
44
#include <bool.h>
-
 
45
#include <errno.h>
-
 
46
#include <console/color.h>
-
 
47
#include <console/style.h>
41
 
48
 
-
 
49
#include "../console/screenbuffer.h"
-
 
50
#include "main.h"
42
#include "serial_console.h"
51
#include "serial_console.h"
43
 
52
 
44
#define MAX_CONTROL 20
53
#define MAX_CONTROL 20
45
 
54
 
-
 
55
static void serial_sgr(const unsigned int mode);
-
 
56
void serial_putchar(wchar_t ch);
-
 
57
 
46
static uint32_t width;
58
static int scr_width;
47
static uint32_t height;
59
static int scr_height;
-
 
60
static bool color = true;   /** True if producing color output. */
-
 
61
static bool utf8 = false;   /** True if producing UTF8 output. */
48
static putc_function_t putc_function;
62
static putc_function_t putc_function;
49
 
63
 
-
 
64
/* Allow only 1 connection */
-
 
65
static int client_connected = 0;
-
 
66
 
-
 
67
enum sgr_color_index {
-
 
68
    CI_BLACK    = 0,
-
 
69
    CI_RED      = 1,
-
 
70
    CI_GREEN    = 2,
-
 
71
    CI_BROWN    = 3,
-
 
72
    CI_BLUE     = 4,
-
 
73
    CI_MAGENTA  = 5,
-
 
74
    CI_CYAN     = 6,
-
 
75
    CI_WHITE    = 7,
-
 
76
};
-
 
77
 
-
 
78
enum sgr_command {
-
 
79
    SGR_RESET   = 0,
-
 
80
    SGR_BOLD    = 1,
-
 
81
    SGR_BLINK   = 5,
-
 
82
    SGR_REVERSE = 7,
-
 
83
    SGR_NORMAL_INT  = 22,
-
 
84
    SGR_BLINK_OFF   = 25,
-
 
85
    SGR_REVERSE_OFF = 27,
-
 
86
    SGR_FGCOLOR = 30,
-
 
87
    SGR_BGCOLOR = 40
-
 
88
};
-
 
89
 
-
 
90
static int color_map[] = {
-
 
91
    [COLOR_BLACK]   = CI_BLACK,
-
 
92
    [COLOR_BLUE]    = CI_RED,
-
 
93
    [COLOR_GREEN]   = CI_GREEN,
-
 
94
    [COLOR_CYAN]    = CI_CYAN,
-
 
95
    [COLOR_RED] = CI_RED,
-
 
96
    [COLOR_MAGENTA] = CI_MAGENTA,
-
 
97
    [COLOR_YELLOW]  = CI_BROWN,
-
 
98
    [COLOR_WHITE]   = CI_WHITE
-
 
99
};
-
 
100
 
50
void serial_puts(char *str)
101
void serial_puts(char *str)
51
{
102
{
52
    while (*str)
103
    while (*str)
53
        putc_function(*(str++));
104
        putc_function(*(str++));
54
}
105
}
55
 
106
 
-
 
107
void serial_putchar(wchar_t ch)
-
 
108
{
-
 
109
    uint8_t buf[STR_BOUNDS(1)];
-
 
110
    size_t offs;
-
 
111
    size_t i;
-
 
112
 
-
 
113
    if (utf8 != true) {
-
 
114
        if (ch >= 0 && ch < 128)
-
 
115
            (*putc_function)((uint8_t) ch);
-
 
116
        else
-
 
117
            (*putc_function)('?');
-
 
118
        return;
-
 
119
    }
-
 
120
 
-
 
121
    offs = 0;
-
 
122
    if (chr_encode(ch, buf, &offs, STR_BOUNDS(1)) == EOK) {
-
 
123
        for (i = 0; i < offs; i++)
-
 
124
            (*putc_function)(buf[i]);
-
 
125
    } else {
-
 
126
        (*putc_function)('?');
-
 
127
    }
-
 
128
 
-
 
129
}
-
 
130
 
56
void serial_goto(const unsigned int row, const unsigned int col)
131
void serial_goto(const unsigned int row, const unsigned int col)
57
{
132
{
58
    if ((row > height) || (col > width))
133
    if ((row > scr_height) || (col > scr_width))
59
        return;
134
        return;
60
   
135
   
61
    char control[20];
136
    char control[MAX_CONTROL];
62
    snprintf(control, 20, "\033[%u;%uf", row + 1, col + 1);
137
    snprintf(control, MAX_CONTROL, "\033[%u;%uf", row + 1, col + 1);
63
    serial_puts(control);
138
    serial_puts(control);
64
}
139
}
65
 
140
 
66
void serial_clrscr(void)
141
void serial_clrscr(void)
67
{
142
{
-
 
143
    /* Initialize graphic rendition attributes. */
-
 
144
    serial_sgr(SGR_RESET);
-
 
145
    if (color) {
-
 
146
        serial_sgr(SGR_FGCOLOR + CI_BLACK);
-
 
147
        serial_sgr(SGR_BGCOLOR + CI_WHITE);
-
 
148
    }
-
 
149
 
68
    serial_puts("\033[2J");
150
    serial_puts("\033[2J");
69
}
151
}
70
 
152
 
71
void serial_scroll(int i)
153
void serial_scroll(int i)
72
{
154
{
73
    if (i > 0) {
155
    if (i > 0) {
74
        serial_goto(height - 1, 0);
156
        serial_goto(scr_height - 1, 0);
75
        while (i--)
157
        while (i--)
76
            serial_puts("\033D");
158
            serial_puts("\033D");
77
    } else if (i < 0) {
159
    } else if (i < 0) {
78
        serial_goto(0, 0);
160
        serial_goto(0, 0);
79
        while (i++)
161
        while (i++)
80
            serial_puts("\033M");
162
            serial_puts("\033M");
81
    }
163
    }
82
}
164
}
83
 
165
 
-
 
166
/** ECMA-48 Set Graphics Rendition. */
84
void serial_set_style(const unsigned int mode)
167
static void serial_sgr(const unsigned int mode)
85
{
168
{
86
    char control[MAX_CONTROL];
169
    char control[MAX_CONTROL];
87
    snprintf(control, MAX_CONTROL, "\033[%um", mode);
170
    snprintf(control, MAX_CONTROL, "\033[%um", mode);
88
    serial_puts(control);
171
    serial_puts(control);
89
}
172
}
90
 
173
 
-
 
174
/** Set scrolling region. */
-
 
175
void serial_set_scroll_region(unsigned last_row)
-
 
176
{
-
 
177
    char control[MAX_CONTROL];
-
 
178
    snprintf(control, MAX_CONTROL, "\033[0;%ur", last_row);
-
 
179
    serial_puts(control);
-
 
180
}
-
 
181
 
91
void serial_cursor_disable(void)
182
void serial_cursor_disable(void)
92
{
183
{
93
    serial_puts("\033[?25l");
184
    serial_puts("\033[?25l");
94
}
185
}
95
 
186
 
Line 98... Line 189...
98
    serial_puts("\033[?25h");
189
    serial_puts("\033[?25h");
99
}
190
}
100
 
191
 
101
void serial_console_init(putc_function_t putc_fn, uint32_t w, uint32_t h)
192
void serial_console_init(putc_function_t putc_fn, uint32_t w, uint32_t h)
102
{
193
{
103
    width = w;
194
    scr_width = w;
104
    height = h;
195
    scr_height = h;
105
    putc_function = putc_fn;
196
    putc_function = putc_fn;
106
}
197
}
107
 
198
 
-
 
199
static void serial_set_style(int style)
-
 
200
{
-
 
201
    if (style == STYLE_EMPHASIS) {
-
 
202
        if (color) {
-
 
203
            serial_sgr(SGR_RESET);
-
 
204
            serial_sgr(SGR_FGCOLOR + CI_RED);
-
 
205
            serial_sgr(SGR_BGCOLOR + CI_WHITE);
-
 
206
        }
-
 
207
        serial_sgr(SGR_BOLD);
-
 
208
    } else {
-
 
209
        if (color) {
-
 
210
            serial_sgr(SGR_RESET);
-
 
211
            serial_sgr(SGR_FGCOLOR + CI_BLACK);
-
 
212
            serial_sgr(SGR_BGCOLOR + CI_WHITE);
-
 
213
        }
-
 
214
        serial_sgr(SGR_NORMAL_INT);
-
 
215
    }
-
 
216
}
-
 
217
 
-
 
218
static void serial_set_idx(unsigned fgcolor, unsigned bgcolor,
-
 
219
    unsigned flags)
-
 
220
{
-
 
221
    if (color) {
-
 
222
        serial_sgr(SGR_RESET);
-
 
223
        serial_sgr(SGR_FGCOLOR + color_map[fgcolor]);
-
 
224
        serial_sgr(SGR_BGCOLOR + color_map[bgcolor]);
-
 
225
    } else {
-
 
226
        if (fgcolor < bgcolor)
-
 
227
            serial_sgr(SGR_RESET);
-
 
228
        else
-
 
229
            serial_sgr(SGR_REVERSE);
-
 
230
    }  
-
 
231
}
-
 
232
 
-
 
233
static void serial_set_rgb(uint32_t fgcolor, uint32_t bgcolor)
-
 
234
{
-
 
235
    if (fgcolor < bgcolor)
-
 
236
        serial_sgr(SGR_REVERSE_OFF);
-
 
237
    else
-
 
238
        serial_sgr(SGR_REVERSE);   
-
 
239
}
-
 
240
 
-
 
241
static void serial_set_attrs(const attrs_t *a)
-
 
242
{
-
 
243
    switch (a->t) {
-
 
244
    case at_style: serial_set_style(a->a.s.style); break;
-
 
245
    case at_rgb: serial_set_rgb(a->a.r.fg_color, a->a.r.bg_color); break;
-
 
246
    case at_idx: serial_set_idx(a->a.i.fg_color,
-
 
247
        a->a.i.bg_color, a->a.i.flags); break;
-
 
248
    default: break;
-
 
249
    }
-
 
250
}
-
 
251
 
-
 
252
/** Draw text data to viewport.
-
 
253
 *
-
 
254
 * @param vport Viewport id
-
 
255
 * @param data  Text data.
-
 
256
 * @param x Leftmost column of the area.
-
 
257
 * @param y Topmost row of the area.
-
 
258
 * @param w Number of rows.
-
 
259
 * @param h Number of columns.
-
 
260
 */
-
 
261
static void draw_text_data(keyfield_t *data, unsigned int x,
-
 
262
    unsigned int y, unsigned int w, unsigned int h)
-
 
263
{
-
 
264
    unsigned int i, j;
-
 
265
    keyfield_t *field;
-
 
266
    attrs_t *a0, *a1;
-
 
267
 
-
 
268
    serial_goto(y, x);
-
 
269
    a0 = &data[0].attrs;
-
 
270
    serial_set_attrs(a0);
-
 
271
 
-
 
272
    for (j = 0; j < h; j++) {
-
 
273
        if (j > 0 && w != scr_width)
-
 
274
            serial_goto(y, x);
-
 
275
 
-
 
276
        for (i = 0; i < w; i++) {
-
 
277
            field = &data[j * w + i];
-
 
278
 
-
 
279
            a1 = &field->attrs;
-
 
280
            if (!attrs_same(*a0, *a1))
-
 
281
                serial_set_attrs(a1);
-
 
282
            serial_putchar(field->character);
-
 
283
            a0 = a1;
-
 
284
        }
-
 
285
    }
-
 
286
}
-
 
287
 
-
 
288
int lastcol = 0;
-
 
289
int lastrow = 0;
-
 
290
 
-
 
291
/**
-
 
292
 * Main function of the thread serving client connections.
-
 
293
 */
-
 
294
void serial_client_connection(ipc_callid_t iid, ipc_call_t *icall)
-
 
295
{
-
 
296
    int retval;
-
 
297
    ipc_callid_t callid;
-
 
298
    ipc_call_t call;
-
 
299
    keyfield_t *interbuf = NULL;
-
 
300
    size_t intersize = 0;
-
 
301
 
-
 
302
    wchar_t c;
-
 
303
    int col, row, w, h;
-
 
304
    int i;
-
 
305
 
-
 
306
    attrs_t cur_attr;
-
 
307
   
-
 
308
    if (client_connected) {
-
 
309
        ipc_answer_0(iid, ELIMIT);
-
 
310
        return;
-
 
311
    }
-
 
312
   
-
 
313
    client_connected = 1;
-
 
314
    ipc_answer_0(iid, EOK);
-
 
315
 
-
 
316
    cur_attr.t = at_style;
-
 
317
    cur_attr.a.s.style = STYLE_NORMAL;
-
 
318
   
-
 
319
    /* Clear the terminal, set scrolling region
-
 
320
       to 0 - height rows. */
-
 
321
    serial_clrscr();
-
 
322
    serial_goto(0, 0);
-
 
323
    serial_set_scroll_region(scr_height);
-
 
324
   
-
 
325
    while (true) {
-
 
326
        callid = async_get_call(&call);
-
 
327
        switch (IPC_GET_METHOD(call)) {
-
 
328
        case IPC_M_PHONE_HUNGUP:
-
 
329
            client_connected = 0;
-
 
330
            ipc_answer_0(callid, EOK);
-
 
331
            return;
-
 
332
        case IPC_M_SHARE_OUT:
-
 
333
            /* We accept one area for data interchange */
-
 
334
            intersize = IPC_GET_ARG2(call);
-
 
335
            if (intersize >= scr_width * scr_height *
-
 
336
                sizeof(*interbuf)) {
-
 
337
                receive_comm_area(callid, &call,
-
 
338
                    (void *) &interbuf);
-
 
339
                continue;
-
 
340
            }
-
 
341
            retval = EINVAL;
-
 
342
            break;
-
 
343
        case FB_DRAW_TEXT_DATA:
-
 
344
            col = IPC_GET_ARG1(call);
-
 
345
            row = IPC_GET_ARG2(call);
-
 
346
            w = IPC_GET_ARG3(call);
-
 
347
            h = IPC_GET_ARG4(call);
-
 
348
            if (!interbuf) {
-
 
349
                retval = EINVAL;
-
 
350
                break;
-
 
351
            }
-
 
352
            if (col + w > scr_width || row + h > scr_height) {
-
 
353
                retval = EINVAL;
-
 
354
                break;
-
 
355
            }
-
 
356
            draw_text_data(interbuf, col, row, w, h);
-
 
357
            lastrow = row + h - 1;
-
 
358
            lastcol = col + w;
-
 
359
            retval = 0;
-
 
360
            break;
-
 
361
        case FB_PUTCHAR:
-
 
362
            c = IPC_GET_ARG1(call);
-
 
363
            row = IPC_GET_ARG2(call);
-
 
364
            col = IPC_GET_ARG3(call);
-
 
365
            if ((lastcol != col) || (lastrow != row))
-
 
366
                serial_goto(row, col);
-
 
367
            lastcol = col + 1;
-
 
368
            lastrow = row;
-
 
369
            serial_putchar(c);
-
 
370
            retval = 0;
-
 
371
            break;
-
 
372
        case FB_CURSOR_GOTO:
-
 
373
            row = IPC_GET_ARG1(call);
-
 
374
            col = IPC_GET_ARG2(call);
-
 
375
            serial_goto(row, col);
-
 
376
            lastrow = row;
-
 
377
            lastcol = col;
-
 
378
            retval = 0;
-
 
379
            break;
-
 
380
        case FB_GET_CSIZE:
-
 
381
            ipc_answer_2(callid, EOK, scr_height, scr_width);
-
 
382
            continue;
-
 
383
        case FB_CLEAR:
-
 
384
            serial_clrscr();
-
 
385
            retval = 0;
-
 
386
            break;
-
 
387
        case FB_SET_STYLE:
-
 
388
            cur_attr.t = at_style;
-
 
389
            cur_attr.a.s.style = IPC_GET_ARG1(call);
-
 
390
            cur_attr.a.i.bg_color = IPC_GET_ARG2(call);
-
 
391
            serial_set_attrs(&cur_attr);
-
 
392
 
-
 
393
            retval = 0;
-
 
394
            break;
-
 
395
        case FB_SET_COLOR:
-
 
396
            cur_attr.t = at_idx;
-
 
397
            cur_attr.a.i.fg_color = IPC_GET_ARG1(call);
-
 
398
            cur_attr.a.i.bg_color = IPC_GET_ARG2(call);
-
 
399
            cur_attr.a.i.flags = IPC_GET_ARG3(call);
-
 
400
            serial_set_attrs(&cur_attr);
-
 
401
 
-
 
402
            retval = 0;
-
 
403
            break;
-
 
404
        case FB_SET_RGB_COLOR:
-
 
405
            cur_attr.t = at_rgb;
-
 
406
            cur_attr.a.i.fg_color = IPC_GET_ARG1(call);
-
 
407
            cur_attr.a.i.bg_color = IPC_GET_ARG2(call);
-
 
408
            serial_set_attrs(&cur_attr);
-
 
409
 
-
 
410
            retval = 0;
-
 
411
            break;
-
 
412
        case FB_SCROLL:
-
 
413
            i = IPC_GET_ARG1(call);
-
 
414
            if ((i > scr_height) || (i < -scr_height)) {
-
 
415
                retval = EINVAL;
-
 
416
                break;
-
 
417
            }
-
 
418
            serial_scroll(i);
-
 
419
            serial_goto(lastrow, lastcol);
-
 
420
            retval = 0;
-
 
421
            break;
-
 
422
        case FB_CURSOR_VISIBILITY:
-
 
423
            if(IPC_GET_ARG1(call))
-
 
424
                serial_cursor_enable();
-
 
425
            else
-
 
426
                serial_cursor_disable();
-
 
427
            retval = 0;
-
 
428
            break;
-
 
429
        case FB_SCREEN_YIELD:
-
 
430
            serial_sgr(SGR_RESET);
-
 
431
            serial_puts("\033[2J");
-
 
432
            serial_goto(0, 0);
-
 
433
            serial_cursor_enable();
-
 
434
            retval = 0;
-
 
435
            break;
-
 
436
        case FB_SCREEN_RECLAIM:
-
 
437
            serial_clrscr();
-
 
438
            serial_set_attrs(&cur_attr);
-
 
439
            retval = 0;
-
 
440
            break;
-
 
441
        default:
-
 
442
            retval = ENOENT;
-
 
443
        }
-
 
444
        ipc_answer_0(callid, retval);
-
 
445
    }
-
 
446
}
-
 
447
 
108
/**
448
/**
109
 * @}
449
 * @}
110
 */
450
 */