source: mainline/uspace/srv/fb/serial_console.c@ fe24a52

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since fe24a52 was b27eb71, checked in by Jiri Svoboda <jirik.svoboda@…>, 16 years ago

Make ega-fb and serial-fb aware of UCS.

  • Property mode set to 100644
File size: 9.4 KB
Line 
1/*
2 * Copyright (c) 2006 Ondrej Palkovsky
3 * Copyright (c) 2008 Martin Decky
4 * Copyright (c) 2008 Pavel Rimsky
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
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.
18 *
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.
29 */
30
31/**
32 * @defgroup serial Serial console
33 * @brief Serial console services (putc, puts, clear screen, cursor goto,...)
34 * @{
35 */
36
37/** @file
38 */
39
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>
48
49#include "../console/screenbuffer.h"
50#include "main.h"
51#include "serial_console.h"
52
53#define MAX_CONTROL 20
54
55static void serial_sgr(const unsigned int mode);
56void serial_putchar(wchar_t ch);
57
58static int scr_width;
59static int scr_height;
60static bool color = true; /** True if producing color output. */
61static bool utf8 = false; /** True if producing UTF8 output. */
62static putc_function_t putc_function;
63
64/* Allow only 1 connection */
65static int client_connected = 0;
66
67enum 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
78enum 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
90static 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
101void serial_puts(char *str)
102{
103 while (*str)
104 putc_function(*(str++));
105}
106
107void 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
131void serial_goto(const unsigned int row, const unsigned int col)
132{
133 if ((row > scr_height) || (col > scr_width))
134 return;
135
136 char control[MAX_CONTROL];
137 snprintf(control, MAX_CONTROL, "\033[%u;%uf", row + 1, col + 1);
138 serial_puts(control);
139}
140
141void serial_clrscr(void)
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
150 serial_puts("\033[2J");
151}
152
153void serial_scroll(int i)
154{
155 if (i > 0) {
156 serial_goto(scr_height - 1, 0);
157 while (i--)
158 serial_puts("\033D");
159 } else if (i < 0) {
160 serial_goto(0, 0);
161 while (i++)
162 serial_puts("\033M");
163 }
164}
165
166/** ECMA-48 Set Graphics Rendition. */
167static void serial_sgr(const unsigned int mode)
168{
169 char control[MAX_CONTROL];
170 snprintf(control, MAX_CONTROL, "\033[%um", mode);
171 serial_puts(control);
172}
173
174/** Set scrolling region. */
175void 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
182void serial_cursor_disable(void)
183{
184 serial_puts("\033[?25l");
185}
186
187void serial_cursor_enable(void)
188{
189 serial_puts("\033[?25h");
190}
191
192void serial_console_init(putc_function_t putc_fn, uint32_t w, uint32_t h)
193{
194 scr_width = w;
195 scr_height = h;
196 putc_function = putc_fn;
197}
198
199static 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
218static 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
233static 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
241static 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 */
261static 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 unsigned int col = x + i;
278 unsigned int row = y + j;
279
280 field = &data[j * w + i];
281
282 a1 = &field->attrs;
283 if (!attrs_same(*a0, *a1))
284 serial_set_attrs(a1);
285 serial_putchar(field->character);
286 a0 = a1;
287 }
288 }
289}
290
291int lastcol = 0;
292int lastrow = 0;
293
294/**
295 * Main function of the thread serving client connections.
296 */
297void serial_client_connection(ipc_callid_t iid, ipc_call_t *icall)
298{
299 int retval;
300 ipc_callid_t callid;
301 ipc_call_t call;
302 keyfield_t *interbuf = NULL;
303 size_t intersize = 0;
304
305 wchar_t c;
306 int col, row, w, h;
307 int fgcolor;
308 int bgcolor;
309 int flags;
310 int style;
311 int i;
312
313
314 if (client_connected) {
315 ipc_answer_0(iid, ELIMIT);
316 return;
317 }
318
319 client_connected = 1;
320 ipc_answer_0(iid, EOK);
321
322 /* Clear the terminal, set scrolling region
323 to 0 - height rows. */
324 serial_clrscr();
325 serial_goto(0, 0);
326 serial_set_scroll_region(scr_height);
327
328 while (true) {
329 callid = async_get_call(&call);
330 switch (IPC_GET_METHOD(call)) {
331 case IPC_M_PHONE_HUNGUP:
332 client_connected = 0;
333 ipc_answer_0(callid, EOK);
334 return;
335 case IPC_M_SHARE_OUT:
336 /* We accept one area for data interchange */
337 intersize = IPC_GET_ARG2(call);
338 if (intersize >= scr_width * scr_height *
339 sizeof(*interbuf)) {
340 receive_comm_area(callid, &call,
341 (void *) &interbuf);
342 continue;
343 }
344 retval = EINVAL;
345 break;
346 case FB_DRAW_TEXT_DATA:
347 col = IPC_GET_ARG1(call);
348 row = IPC_GET_ARG2(call);
349 w = IPC_GET_ARG3(call);
350 h = IPC_GET_ARG4(call);
351 if (!interbuf) {
352 retval = EINVAL;
353 break;
354 }
355 if (col + w > scr_width || row + h > scr_height) {
356 retval = EINVAL;
357 break;
358 }
359 draw_text_data(interbuf, col, row, w, h);
360 lastrow = row + h - 1;
361 lastcol = col + w;
362 retval = 0;
363 break;
364 case FB_PUTCHAR:
365 c = IPC_GET_ARG1(call);
366 row = IPC_GET_ARG2(call);
367 col = IPC_GET_ARG3(call);
368 if ((lastcol != col) || (lastrow != row))
369 serial_goto(row, col);
370 lastcol = col + 1;
371 lastrow = row;
372 serial_putchar(c);
373 retval = 0;
374 break;
375 case FB_CURSOR_GOTO:
376 row = IPC_GET_ARG1(call);
377 col = IPC_GET_ARG2(call);
378 serial_goto(row, col);
379 lastrow = row;
380 lastcol = col;
381 retval = 0;
382 break;
383 case FB_GET_CSIZE:
384 ipc_answer_2(callid, EOK, scr_height, scr_width);
385 continue;
386 case FB_CLEAR:
387 serial_clrscr();
388 retval = 0;
389 break;
390 case FB_SET_STYLE:
391 style = IPC_GET_ARG1(call);
392 serial_set_style(style);
393 retval = 0;
394 break;
395 case FB_SET_COLOR:
396 fgcolor = IPC_GET_ARG1(call);
397 bgcolor = IPC_GET_ARG2(call);
398 flags = IPC_GET_ARG3(call);
399
400 serial_set_idx(fgcolor, bgcolor, flags);
401 retval = 0;
402 break;
403 case FB_SET_RGB_COLOR:
404 fgcolor = IPC_GET_ARG1(call);
405 bgcolor = IPC_GET_ARG2(call);
406
407 serial_set_rgb(fgcolor, bgcolor);
408 retval = 0;
409 break;
410 case FB_SCROLL:
411 i = IPC_GET_ARG1(call);
412 if ((i > scr_height) || (i < -scr_height)) {
413 retval = EINVAL;
414 break;
415 }
416 serial_scroll(i);
417 serial_goto(lastrow, lastcol);
418 retval = 0;
419 break;
420 case FB_CURSOR_VISIBILITY:
421 if(IPC_GET_ARG1(call))
422 serial_cursor_enable();
423 else
424 serial_cursor_disable();
425 retval = 0;
426 break;
427 default:
428 retval = ENOENT;
429 }
430 ipc_answer_0(callid, retval);
431 }
432}
433
434/**
435 * @}
436 */
Note: See TracBrowser for help on using the repository browser.