source: mainline/uspace/srv/fb/serial_console.c@ 4527fb5

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

Define wchar_t in userspace. Use it in fb and console.

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