source: mainline/uspace/srv/fb/serial_console.c@ 7e15496

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

Remove garbage.

  • Property mode set to 100644
File size: 8.3 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_goto(const unsigned int row, const unsigned int col)
106{
107 if ((row > scr_height) || (col > scr_width))
108 return;
109
110 char control[MAX_CONTROL];
111 snprintf(control, MAX_CONTROL, "\033[%u;%uf", row + 1, col + 1);
112 serial_puts(control);
113}
114
115void serial_clrscr(void)
116{
117 /* Initialize graphic rendition attributes. */
118 serial_sgr(SGR_RESET);
119 if (color) {
120 serial_sgr(SGR_FGCOLOR + CI_BLACK);
121 serial_sgr(SGR_BGCOLOR + CI_WHITE);
122 }
123
124 serial_puts("\033[2J");
125}
126
127void serial_scroll(int i)
128{
129 if (i > 0) {
130 serial_goto(scr_height - 1, 0);
131 while (i--)
132 serial_puts("\033D");
133 } else if (i < 0) {
134 serial_goto(0, 0);
135 while (i++)
136 serial_puts("\033M");
137 }
138}
139
140/** ECMA-48 Set Graphics Rendition. */
141static void serial_sgr(const unsigned int mode)
142{
143 char control[MAX_CONTROL];
144 snprintf(control, MAX_CONTROL, "\033[%um", mode);
145 serial_puts(control);
146}
147
148/** Set scrolling region. */
149void serial_set_scroll_region(unsigned last_row)
150{
151 char control[MAX_CONTROL];
152 snprintf(control, MAX_CONTROL, "\033[0;%ur", last_row);
153 serial_puts(control);
154}
155
156void serial_cursor_disable(void)
157{
158 serial_puts("\033[?25l");
159}
160
161void serial_cursor_enable(void)
162{
163 serial_puts("\033[?25h");
164}
165
166void serial_console_init(putc_function_t putc_fn, uint32_t w, uint32_t h)
167{
168 scr_width = w;
169 scr_height = h;
170 putc_function = putc_fn;
171}
172
173static void serial_set_style(int style)
174{
175 if (style == STYLE_EMPHASIS) {
176 if (color) {
177 serial_sgr(SGR_RESET);
178 serial_sgr(SGR_FGCOLOR + CI_RED);
179 serial_sgr(SGR_BGCOLOR + CI_WHITE);
180 }
181 serial_sgr(SGR_BOLD);
182 } else {
183 if (color) {
184 serial_sgr(SGR_RESET);
185 serial_sgr(SGR_FGCOLOR + CI_BLACK);
186 serial_sgr(SGR_BGCOLOR + CI_WHITE);
187 }
188 serial_sgr(SGR_NORMAL_INT);
189 }
190}
191
192static void serial_set_idx(unsigned fgcolor, unsigned bgcolor,
193 unsigned flags)
194{
195 if (color) {
196 serial_sgr(SGR_RESET);
197 serial_sgr(SGR_FGCOLOR + color_map[fgcolor]);
198 serial_sgr(SGR_BGCOLOR + color_map[bgcolor]);
199 } else {
200 if (fgcolor < bgcolor)
201 serial_sgr(SGR_RESET);
202 else
203 serial_sgr(SGR_REVERSE);
204 }
205}
206
207static void serial_set_rgb(uint32_t fgcolor, uint32_t bgcolor)
208{
209 if (fgcolor < bgcolor)
210 serial_sgr(SGR_REVERSE_OFF);
211 else
212 serial_sgr(SGR_REVERSE);
213}
214
215static void serial_set_attrs(const attrs_t *a)
216{
217 switch (a->t) {
218 case at_style: serial_set_style(a->a.s.style); break;
219 case at_rgb: serial_set_rgb(a->a.r.fg_color, a->a.r.bg_color); break;
220 case at_idx: serial_set_idx(a->a.i.fg_color,
221 a->a.i.bg_color, a->a.i.flags); break;
222 default: break;
223 }
224}
225
226static void draw_text_data(keyfield_t *data)
227{
228 int i, j;
229 attrs_t *a0, *a1;
230
231 serial_goto(0, 0);
232 a0 = &data[0].attrs;
233 serial_set_attrs(a0);
234
235 for (i = 0; i < scr_height; i++) {
236 for (j = 0; j < scr_width; j++) {
237 a1 = &data[i * scr_width + j].attrs;
238 if (!attrs_same(*a0, *a1))
239 serial_set_attrs(a1);
240 (*putc_function)(data[i * scr_width + j].character);
241 a0 = a1;
242 }
243 }
244}
245
246/**
247 * Main function of the thread serving client connections.
248 */
249void serial_client_connection(ipc_callid_t iid, ipc_call_t *icall)
250{
251 int retval;
252 ipc_callid_t callid;
253 ipc_call_t call;
254 keyfield_t *interbuf = NULL;
255 size_t intersize = 0;
256
257 char c;
258 int lastcol = 0;
259 int lastrow = 0;
260 int newcol;
261 int newrow;
262 int fgcolor;
263 int bgcolor;
264 int flags;
265 int style;
266 int i;
267
268
269 if (client_connected) {
270 ipc_answer_0(iid, ELIMIT);
271 return;
272 }
273
274 client_connected = 1;
275 ipc_answer_0(iid, EOK);
276
277 /* Clear the terminal, set scrolling region
278 to 0 - height rows. */
279 serial_clrscr();
280 serial_goto(0, 0);
281 serial_set_scroll_region(scr_height);
282
283 while (true) {
284 callid = async_get_call(&call);
285 switch (IPC_GET_METHOD(call)) {
286 case IPC_M_PHONE_HUNGUP:
287 client_connected = 0;
288 ipc_answer_0(callid, EOK);
289 return;
290 case IPC_M_SHARE_OUT:
291 /* We accept one area for data interchange */
292 intersize = IPC_GET_ARG2(call);
293 if (intersize >= scr_width * scr_height *
294 sizeof(*interbuf)) {
295 receive_comm_area(callid, &call,
296 (void *) &interbuf);
297 continue;
298 }
299 retval = EINVAL;
300 break;
301 case FB_DRAW_TEXT_DATA:
302 if (!interbuf) {
303 retval = EINVAL;
304 break;
305 }
306 draw_text_data(interbuf);
307 retval = 0;
308 break;
309 case FB_PUTCHAR:
310 c = IPC_GET_ARG1(call);
311 newrow = IPC_GET_ARG2(call);
312 newcol = IPC_GET_ARG3(call);
313 if ((lastcol != newcol) || (lastrow != newrow))
314 serial_goto(newrow, newcol);
315 lastcol = newcol + 1;
316 lastrow = newrow;
317 (*putc_function)(c);
318 retval = 0;
319 break;
320 case FB_CURSOR_GOTO:
321 newrow = IPC_GET_ARG1(call);
322 newcol = IPC_GET_ARG2(call);
323 serial_goto(newrow, newcol);
324 lastrow = newrow;
325 lastcol = newcol;
326 retval = 0;
327 break;
328 case FB_GET_CSIZE:
329 ipc_answer_2(callid, EOK, scr_height, scr_width);
330 continue;
331 case FB_CLEAR:
332 serial_clrscr();
333 retval = 0;
334 break;
335 case FB_SET_STYLE:
336 style = IPC_GET_ARG1(call);
337 serial_set_style(style);
338 retval = 0;
339 break;
340 case FB_SET_COLOR:
341 fgcolor = IPC_GET_ARG1(call);
342 bgcolor = IPC_GET_ARG2(call);
343 flags = IPC_GET_ARG3(call);
344
345 serial_set_idx(fgcolor, bgcolor, flags);
346 retval = 0;
347 break;
348 case FB_SET_RGB_COLOR:
349 fgcolor = IPC_GET_ARG1(call);
350 bgcolor = IPC_GET_ARG2(call);
351
352 serial_set_rgb(fgcolor, bgcolor);
353 retval = 0;
354 break;
355 case FB_SCROLL:
356 i = IPC_GET_ARG1(call);
357 if ((i > scr_height) || (i < -scr_height)) {
358 retval = EINVAL;
359 break;
360 }
361 serial_scroll(i);
362 serial_goto(lastrow, lastcol);
363 retval = 0;
364 break;
365 case FB_CURSOR_VISIBILITY:
366 if(IPC_GET_ARG1(call))
367 serial_cursor_enable();
368 else
369 serial_cursor_disable();
370 retval = 0;
371 break;
372 default:
373 retval = ENOENT;
374 }
375 ipc_answer_0(callid, retval);
376 }
377}
378
379/**
380 * @}
381 */
Note: See TracBrowser for help on using the repository browser.