2
* Copyright (c) 2006 Ondrej Palkovsky
3
* Copyright (c) 2008 Martin Decky
4
* Copyright (c) 2008 Pavel Rimsky
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
11
* - Redistributions of source code must retain the above copyright
12
* notice, this list of conditions and the following disclaimer.
13
* - Redistributions in binary form must reproduce the above copyright
14
* notice, this list of conditions and the following disclaimer in the
15
* documentation and/or other materials provided with the distribution.
16
* - The name of the author may not be used to endorse or promote products
17
* derived from this software without specific prior written permission.
19
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
* @defgroup serial Serial console
33
* @brief Serial console services (putc, puts, clear screen, cursor goto,...)
50
#include "../console/screenbuffer.h"
52
#include "serial_console.h"
54
#define MAX_CONTROL 20
56
static void serial_sgr(const unsigned int mode);
57
void serial_putchar(wchar_t ch);
60
static int scr_height;
61
static bool color = true; /** True if producing color output. */
62
static bool utf8 = false; /** True if producing UTF8 output. */
63
static putc_function_t putc_function;
65
/* Allow only 1 connection */
66
static int client_connected = 0;
68
enum sgr_color_index {
91
static int color_map[] = {
92
[COLOR_BLACK] = CI_BLACK,
93
[COLOR_BLUE] = CI_RED,
94
[COLOR_GREEN] = CI_GREEN,
95
[COLOR_CYAN] = CI_CYAN,
97
[COLOR_MAGENTA] = CI_MAGENTA,
98
[COLOR_YELLOW] = CI_BROWN,
99
[COLOR_WHITE] = CI_WHITE
102
void serial_puts(char *str)
105
putc_function(*(str++));
108
void serial_putchar(wchar_t ch)
110
uint8_t buf[STR_BOUNDS(1)];
115
if (ch >= 0 && ch < 128)
116
(*putc_function)((uint8_t) ch);
118
(*putc_function)('?');
123
if (chr_encode(ch, buf, &offs, STR_BOUNDS(1)) == EOK) {
124
for (i = 0; i < offs; i++)
125
(*putc_function)(buf[i]);
127
(*putc_function)('?');
132
void serial_goto(const unsigned int col, const unsigned int row)
134
if ((col > scr_width) || (row > scr_height))
137
char control[MAX_CONTROL];
138
snprintf(control, MAX_CONTROL, "\033[%u;%uf", row + 1, col + 1);
139
serial_puts(control);
142
void serial_clrscr(void)
144
/* Initialize graphic rendition attributes. */
145
serial_sgr(SGR_RESET);
147
serial_sgr(SGR_FGCOLOR + CI_BLACK);
148
serial_sgr(SGR_BGCOLOR + CI_WHITE);
151
serial_puts("\033[2J");
154
void serial_scroll(int i)
157
serial_goto(0, scr_height - 1);
159
serial_puts("\033D");
163
serial_puts("\033M");
167
/** ECMA-48 Set Graphics Rendition. */
168
static void serial_sgr(const unsigned int mode)
170
char control[MAX_CONTROL];
171
snprintf(control, MAX_CONTROL, "\033[%um", mode);
172
serial_puts(control);
175
/** Set scrolling region. */
176
void serial_set_scroll_region(unsigned last_row)
178
char control[MAX_CONTROL];
179
snprintf(control, MAX_CONTROL, "\033[0;%ur", last_row);
180
serial_puts(control);
183
void serial_cursor_disable(void)
185
serial_puts("\033[?25l");
188
void serial_cursor_enable(void)
190
serial_puts("\033[?25h");
193
void serial_console_init(putc_function_t putc_fn, uint32_t w, uint32_t h)
197
putc_function = putc_fn;
200
static void serial_set_style(int style)
202
if (style == STYLE_EMPHASIS) {
204
serial_sgr(SGR_RESET);
205
serial_sgr(SGR_FGCOLOR + CI_RED);
206
serial_sgr(SGR_BGCOLOR + CI_WHITE);
208
serial_sgr(SGR_BOLD);
211
serial_sgr(SGR_RESET);
212
serial_sgr(SGR_FGCOLOR + CI_BLACK);
213
serial_sgr(SGR_BGCOLOR + CI_WHITE);
215
serial_sgr(SGR_NORMAL_INT);
219
static void serial_set_idx(unsigned fgcolor, unsigned bgcolor,
223
serial_sgr(SGR_RESET);
224
serial_sgr(SGR_FGCOLOR + color_map[fgcolor]);
225
serial_sgr(SGR_BGCOLOR + color_map[bgcolor]);
227
if (fgcolor < bgcolor)
228
serial_sgr(SGR_RESET);
230
serial_sgr(SGR_REVERSE);
234
static void serial_set_rgb(uint32_t fgcolor, uint32_t bgcolor)
236
if (fgcolor < bgcolor)
237
serial_sgr(SGR_REVERSE_OFF);
239
serial_sgr(SGR_REVERSE);
242
static void serial_set_attrs(const attrs_t *a)
246
serial_set_style(a->a.s.style);
249
serial_set_rgb(a->a.r.fg_color, a->a.r.bg_color);
252
serial_set_idx(a->a.i.fg_color,
253
a->a.i.bg_color, a->a.i.flags);
260
/** Draw text data to viewport.
262
* @param vport Viewport id
263
* @param data Text data.
264
* @param x Leftmost column of the area.
265
* @param y Topmost row of the area.
266
* @param w Number of rows.
267
* @param h Number of columns.
269
static void draw_text_data(keyfield_t *data, unsigned int x,
270
unsigned int y, unsigned int w, unsigned int h)
278
serial_set_attrs(a0);
280
for (j = 0; j < h; j++) {
281
if (j > 0 && w != scr_width)
284
for (i = 0; i < w; i++) {
285
field = &data[j * w + i];
288
if (!attrs_same(*a0, *a1))
289
serial_set_attrs(a1);
290
serial_putchar(field->character);
300
* Main function of the thread serving client connections.
302
void serial_client_connection(ipc_callid_t iid, ipc_call_t *icall)
307
keyfield_t *interbuf = NULL;
308
size_t intersize = 0;
316
if (client_connected) {
317
ipc_answer_0(iid, ELIMIT);
321
client_connected = 1;
322
ipc_answer_0(iid, EOK);
324
cur_attr.t = at_style;
325
cur_attr.a.s.style = STYLE_NORMAL;
327
/* Clear the terminal, set scrolling region
328
to 0 - height rows. */
331
serial_set_scroll_region(scr_height);
334
callid = async_get_call(&call);
335
switch (IPC_GET_METHOD(call)) {
336
case IPC_M_PHONE_HUNGUP:
337
client_connected = 0;
338
ipc_answer_0(callid, EOK);
340
case IPC_M_SHARE_OUT:
341
/* We accept one area for data interchange */
342
intersize = IPC_GET_ARG2(call);
343
if (intersize >= scr_width * scr_height *
345
receive_comm_area(callid, &call,
351
case FB_DRAW_TEXT_DATA:
352
col = IPC_GET_ARG1(call);
353
row = IPC_GET_ARG2(call);
354
w = IPC_GET_ARG3(call);
355
h = IPC_GET_ARG4(call);
360
if (col + w > scr_width || row + h > scr_height) {
364
draw_text_data(interbuf, col, row, w, h);
366
lastrow = row + h - 1;
370
c = IPC_GET_ARG1(call);
371
col = IPC_GET_ARG2(call);
372
row = IPC_GET_ARG3(call);
373
if ((lastcol != col) || (lastrow != row))
374
serial_goto(col, row);
381
col = IPC_GET_ARG1(call);
382
row = IPC_GET_ARG2(call);
383
serial_goto(col, row);
389
ipc_answer_2(callid, EOK, scr_width, scr_height);
391
case FB_GET_COLOR_CAP:
392
ipc_answer_1(callid, EOK, color ? FB_CCAP_INDEXED :
400
cur_attr.t = at_style;
401
cur_attr.a.s.style = IPC_GET_ARG1(call);
402
cur_attr.a.i.bg_color = IPC_GET_ARG2(call);
403
serial_set_attrs(&cur_attr);
409
cur_attr.a.i.fg_color = IPC_GET_ARG1(call);
410
cur_attr.a.i.bg_color = IPC_GET_ARG2(call);
411
cur_attr.a.i.flags = IPC_GET_ARG3(call);
412
serial_set_attrs(&cur_attr);
416
case FB_SET_RGB_COLOR:
418
cur_attr.a.i.fg_color = IPC_GET_ARG1(call);
419
cur_attr.a.i.bg_color = IPC_GET_ARG2(call);
420
serial_set_attrs(&cur_attr);
425
i = IPC_GET_ARG1(call);
426
if ((i > scr_height) || (i < -scr_height)) {
431
serial_goto(lastcol, lastrow);
434
case FB_CURSOR_VISIBILITY:
435
if(IPC_GET_ARG1(call))
436
serial_cursor_enable();
438
serial_cursor_disable();
441
case FB_SCREEN_YIELD:
442
serial_sgr(SGR_RESET);
443
serial_puts("\033[2J");
445
serial_cursor_enable();
448
case FB_SCREEN_RECLAIM:
450
serial_set_attrs(&cur_attr);
456
ipc_answer_0(callid, retval);