Subversion Repositories HelenOS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4377 svoboda 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
 
46
static int console_phone = -1;
47
 
48
/** Size of cbuffer. */
49
#define CBUFFER_SIZE  256
50
 
51
/** Buffer for writing characters to the console. */
52
static char cbuffer[CBUFFER_SIZE];
53
 
54
/** Pointer to end of cbuffer. */
55
static char *cbuffer_end = cbuffer + CBUFFER_SIZE;
56
 
57
/** Pointer to first available field in cbuffer. */
58
static char *cbp = cbuffer;
59
 
60
 
61
/** Write one character to the console via IPC. */
62
static 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 */
69
static 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. */
98
static 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. */
114
static void cbuffer_drain(void)
115
{
116
    cbp = cbuffer;
117
}
118
 
119
/** Write one character to the output buffer. */
120
static 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
 
131
int 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
 
150
void console_close(void)
151
{
152
    if (console_phone >= 0) {
153
        if (ipc_hangup(console_phone) == 0)
154
            console_phone = -1;
155
    }
156
}
157
 
158
void console_wait(void)
159
{
160
    while (console_phone < 0)
161
        console_open(true);
162
}
163
 
164
void console_clear(void)
165
{
166
    console_wait();
167
    cbuffer_drain();
168
    async_msg_0(console_phone, CONSOLE_CLEAR);
169
}
170
 
171
int 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
 
185
void console_set_style(int style)
186
{
187
    console_wait();
188
    cbuffer_flush();
189
    async_msg_1(console_phone, CONSOLE_SET_STYLE, style);
190
}
191
 
192
void 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
 
199
void 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
 
206
void 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
 
213
void console_kcon_enable(void)
214
{
215
    console_wait();
216
    cbuffer_flush();
217
    async_msg_0(console_phone, CONSOLE_KCON_ENABLE);
218
}
219
 
220
void 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
 
227
void console_putchar(wchar_t c)
228
{
229
    console_wait();
230
    cbuffer_flush();
231
    cons_putchar(c);
232
}
233
 
234
/** Write characters to the console. */
235
ssize_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. */
248
void 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. */
266
void console_flush(void)
267
{
268
    cbuffer_flush();
269
    if (console_phone >= 0)
270
        async_msg_0(console_phone, CONSOLE_FLUSH);
271
}
272
 
273
/** @}
274
 */