source: mainline/uspace/lib/libc/generic/console.c@ 433131d

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 433131d was 566f4cfb, checked in by Martin Decky <martin@…>, 16 years ago

use buffering for klog output (this can be used to avoid the ugly usleeps while starting tasks)
unify and cleanup console.c and related files

  • Property mode set to 100644
File size: 5.8 KB
Line 
1/*
2 * Copyright (c) 2006 Josef Cejka
3 * Copyright (c) 2006 Jakub Vana
4 * Copyright (c) 2008 Jiri Svoboda
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/** @addtogroup libc
32 * @{
33 */
34/** @file
35 */
36
37#include <libc.h>
38#include <async.h>
39#include <io/stream.h>
40#include <ipc/console.h>
41#include <ipc/services.h>
42#include <errno.h>
43#include <string.h>
44#include <console.h>
45
46static int console_phone = -1;
47
48/** Size of cbuffer. */
49#define CBUFFER_SIZE 256
50
51/** Buffer for writing characters to the console. */
52static char cbuffer[CBUFFER_SIZE];
53
54/** Pointer to end of cbuffer. */
55static char *cbuffer_end = cbuffer + CBUFFER_SIZE;
56
57/** Pointer to first available field in cbuffer. */
58static char *cbp = cbuffer;
59
60
61/** Write one character to the console via IPC. */
62static void cons_putchar(wchar_t c)
63{
64 console_wait();
65 async_msg_1(console_phone, CONSOLE_PUTCHAR, c);
66}
67
68/** Write characters to the console via IPC or to klog */
69static ssize_t cons_write(const char *buf, size_t size)
70{
71 console_open(false);
72
73 if (console_phone >= 0) {
74 async_serialize_start();
75
76 ipc_call_t answer;
77 aid_t req = async_send_0(console_phone, CONSOLE_WRITE, &answer);
78 ipcarg_t rc = ipc_data_write_start(console_phone, (void *) buf, size);
79
80 if (rc != EOK) {
81 async_wait_for(req, NULL);
82 async_serialize_end();
83 return (ssize_t) rc;
84 }
85
86 async_wait_for(req, &rc);
87 async_serialize_end();
88
89 if (rc == EOK)
90 return (ssize_t) IPC_GET_ARG1(answer);
91 else
92 return -1;
93 } else
94 return __SYSCALL3(SYS_KLOG, 1, (sysarg_t) buf, size);
95}
96
97/** Write all data from output buffer to the console. */
98static void cbuffer_flush(void)
99{
100 size_t len = cbp - cbuffer;
101
102 while (len > 0) {
103 ssize_t rc = cons_write(cbuffer, cbp - cbuffer);
104 if (rc < 0)
105 return;
106
107 len -= rc;
108 }
109
110 cbp = cbuffer;
111}
112
113/** Drop all data in console output buffer. */
114static void cbuffer_drain(void)
115{
116 cbp = cbuffer;
117}
118
119/** Write one character to the output buffer. */
120static inline void cbuffer_putc(char c)
121{
122 if (cbp == cbuffer_end)
123 cbuffer_flush();
124
125 *cbp++ = c;
126
127 if (c == '\n')
128 cbuffer_flush();
129}
130
131int console_open(bool blocking)
132{
133 if (console_phone < 0) {
134 int phone;
135
136 if (blocking)
137 phone = ipc_connect_me_to_blocking(PHONE_NS,
138 SERVICE_CONSOLE, 0, 0);
139 else
140 phone = ipc_connect_me_to(PHONE_NS,
141 SERVICE_CONSOLE, 0, 0);
142
143 if (phone >= 0)
144 console_phone = phone;
145 }
146
147 return console_phone;
148}
149
150void console_close(void)
151{
152 if (console_phone >= 0) {
153 if (ipc_hangup(console_phone) == 0)
154 console_phone = -1;
155 }
156}
157
158void console_wait(void)
159{
160 while (console_phone < 0)
161 console_open(true);
162}
163
164void console_clear(void)
165{
166 console_wait();
167 cbuffer_drain();
168 async_msg_0(console_phone, CONSOLE_CLEAR);
169}
170
171int console_get_size(int *rows, int *cols)
172{
173 console_wait();
174
175 ipcarg_t r;
176 ipcarg_t c;
177 int rc = async_req_0_2(console_phone, CONSOLE_GETSIZE, &r, &c);
178
179 *rows = (int) r;
180 *cols = (int) c;
181
182 return rc;
183}
184
185void console_set_style(int style)
186{
187 console_wait();
188 cbuffer_flush();
189 async_msg_1(console_phone, CONSOLE_SET_STYLE, style);
190}
191
192void console_set_color(int fg_color, int bg_color, int flags)
193{
194 console_wait();
195 cbuffer_flush();
196 async_msg_3(console_phone, CONSOLE_SET_COLOR, fg_color, bg_color, flags);
197}
198
199void console_set_rgb_color(int fg_color, int bg_color)
200{
201 console_wait();
202 cbuffer_flush();
203 async_msg_2(console_phone, CONSOLE_SET_RGB_COLOR, fg_color, bg_color);
204}
205
206void console_cursor_visibility(int show)
207{
208 console_wait();
209 cbuffer_flush();
210 async_msg_1(console_phone, CONSOLE_CURSOR_VISIBILITY, show != 0);
211}
212
213void console_kcon_enable(void)
214{
215 console_wait();
216 cbuffer_flush();
217 async_msg_0(console_phone, CONSOLE_KCON_ENABLE);
218}
219
220void console_goto(int row, int col)
221{
222 console_wait();
223 cbuffer_flush();
224 async_msg_2(console_phone, CONSOLE_GOTO, row, col);
225}
226
227void console_putchar(wchar_t c)
228{
229 console_wait();
230 cbuffer_flush();
231 cons_putchar(c);
232}
233
234/** Write characters to the console. */
235ssize_t console_write(const char *buf, size_t size)
236{
237 size_t left = size;
238
239 while (left > 0) {
240 cbuffer_putc(*buf++);
241 left--;
242 }
243
244 return size;
245}
246
247/** Write a NULL-terminated string to the console. */
248void console_putstr(const char *str)
249{
250 size_t left = str_size(str);
251
252 while (left > 0) {
253 ssize_t rc = console_write(str, left);
254
255 if (rc < 0) {
256 /* Error */
257 return;
258 }
259
260 str += rc;
261 left -= rc;
262 }
263}
264
265/** Flush all output to the console or klog. */
266void console_flush(void)
267{
268 cbuffer_flush();
269 if (console_phone >= 0)
270 async_msg_0(console_phone, CONSOLE_FLUSH);
271}
272
273/** @}
274 */
Note: See TracBrowser for help on using the repository browser.