Subversion Repositories HelenOS

Rev

Rev 4264 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4264 Rev 4293
1
/*
1
/*
2
 * Copyright (c) 2006 Josef Cejka
2
 * Copyright (c) 2006 Josef Cejka
3
 * Copyright (c) 2006 Jakub Vana
3
 * Copyright (c) 2006 Jakub Vana
4
 * Copyright (c) 2008 Jiri Svoboda
4
 * Copyright (c) 2008 Jiri Svoboda
5
 * All rights reserved.
5
 * All rights reserved.
6
 *
6
 *
7
 * Redistribution and use in source and binary forms, with or without
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
8
 * modification, are permitted provided that the following conditions
9
 * are met:
9
 * are met:
10
 *
10
 *
11
 * - Redistributions of source code must retain the above copyright
11
 * - Redistributions of source code must retain the above copyright
12
 *   notice, this list of conditions and the following disclaimer.
12
 *   notice, this list of conditions and the following disclaimer.
13
 * - Redistributions in binary form must reproduce the above copyright
13
 * - Redistributions in binary form must reproduce the above copyright
14
 *   notice, this list of conditions and the following disclaimer in the
14
 *   notice, this list of conditions and the following disclaimer in the
15
 *   documentation and/or other materials provided with the distribution.
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
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.
17
 *   derived from this software without specific prior written permission.
18
 *
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
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
20
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
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
25
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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
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.
28
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
 */
29
 */
30
 
30
 
31
/** @addtogroup libc
31
/** @addtogroup libc
32
 * @{
32
 * @{
33
 */
33
 */
34
/** @file
34
/** @file
35
 */
35
 */
36
 
36
 
37
#include <async.h>
37
#include <async.h>
38
#include <io/stream.h>
38
#include <io/stream.h>
39
#include <ipc/console.h>
39
#include <ipc/console.h>
40
#include <ipc/services.h>
40
#include <ipc/services.h>
41
#include <errno.h>
41
#include <errno.h>
42
#include <string.h>
42
#include <string.h>
43
#include <console.h>
43
#include <console.h>
44
 
44
 
45
static int console_phone = -1;
45
static int console_phone = -1;
46
 
46
 
47
/** Size of cbuffer. */
47
/** Size of cbuffer. */
48
#define CBUFFER_SIZE 256
48
#define CBUFFER_SIZE 256
49
 
49
 
50
/** Buffer for writing characters to the console. */
50
/** Buffer for writing characters to the console. */
51
static char cbuffer[CBUFFER_SIZE];
51
static char cbuffer[CBUFFER_SIZE];
52
 
52
 
53
/** Pointer to end of cbuffer. */
53
/** Pointer to end of cbuffer. */
54
static char *cbuffer_end = cbuffer + CBUFFER_SIZE;
54
static char *cbuffer_end = cbuffer + CBUFFER_SIZE;
55
 
55
 
56
/** Pointer to first available field in cbuffer. */
56
/** Pointer to first available field in cbuffer. */
57
static char *cbp = cbuffer;
57
static char *cbp = cbuffer;
58
 
58
 
59
static ssize_t cons_write(const char *buf, size_t nbyte);
59
static ssize_t cons_write(const char *buf, size_t nbyte);
60
static void cons_putchar(wchar_t c);
60
static void cons_putchar(wchar_t c);
61
 
61
 
62
static void cbuffer_flush(void);
62
static void cbuffer_flush(void);
63
static void cbuffer_drain(void);
63
static void cbuffer_drain(void);
64
static inline void cbuffer_putc(int c);
64
static inline void cbuffer_putc(int c);
65
 
65
 
66
 
66
 
67
void console_open(bool blocking)
67
void console_open(bool blocking)
68
{
68
{
69
    if (console_phone < 0) {
69
    if (console_phone < 0) {
70
        int phone;
70
        int phone;
71
        if (blocking) {
71
        if (blocking) {
72
            phone = ipc_connect_me_to_blocking(PHONE_NS,
72
            phone = ipc_connect_me_to_blocking(PHONE_NS,
73
                SERVICE_CONSOLE, 0, 0);
73
                SERVICE_CONSOLE, 0, 0);
74
        } else {
74
        } else {
75
            phone = ipc_connect_me_to(PHONE_NS, SERVICE_CONSOLE, 0,
75
            phone = ipc_connect_me_to(PHONE_NS, SERVICE_CONSOLE, 0,
76
                0);
76
                0);
77
        }
77
        }
78
        if (phone >= 0)
78
        if (phone >= 0)
79
            console_phone = phone;
79
            console_phone = phone;
80
    }
80
    }
81
}
81
}
82
 
82
 
83
void console_close(void)
83
void console_close(void)
84
{
84
{
85
    if (console_phone >= 0) {
85
    if (console_phone >= 0) {
86
        if (ipc_hangup(console_phone) == 0) {
86
        if (ipc_hangup(console_phone) == 0) {
87
            console_phone = -1;
87
            console_phone = -1;
88
        }
88
        }
89
    }
89
    }
90
}
90
}
91
 
91
 
92
int console_phone_get(bool blocking)
92
int console_phone_get(bool blocking)
93
{
93
{
94
    if (console_phone < 0)
94
    if (console_phone < 0)
95
        console_open(blocking);
95
        console_open(blocking);
96
   
96
   
97
    return console_phone;
97
    return console_phone;
98
}
98
}
99
 
99
 
100
void console_wait(void)
100
void console_wait(void)
101
{
101
{
102
    while (console_phone < 0)
102
    while (console_phone < 0)
103
        console_open(true);
103
        console_open(true);
104
}
104
}
105
 
105
 
106
void console_clear(void)
106
void console_clear(void)
107
{
107
{
108
    int cons_phone = console_phone_get(true);
108
    int cons_phone = console_phone_get(true);
109
 
109
 
110
    cbuffer_drain();
110
    cbuffer_drain();
111
    async_msg_0(cons_phone, CONSOLE_CLEAR);
111
    async_msg_0(cons_phone, CONSOLE_CLEAR);
112
}
112
}
113
 
113
 
114
void console_goto(int row, int col)
114
void console_goto(int row, int col)
115
{
115
{
116
    int cons_phone = console_phone_get(true);
116
    int cons_phone = console_phone_get(true);
117
 
117
 
118
    cbuffer_flush();
118
    cbuffer_flush();
119
    async_msg_2(cons_phone, CONSOLE_GOTO, row, col);
119
    async_msg_2(cons_phone, CONSOLE_GOTO, row, col);
120
}
120
}
121
 
121
 
122
void console_putchar(wchar_t c)
122
void console_putchar(wchar_t c)
123
{
123
{
124
//  cbuffer_putc(c);
124
//  cbuffer_putc(c);
125
    cbuffer_flush();
125
    cbuffer_flush();
126
    cons_putchar(c);
126
    cons_putchar(c);
127
}
127
}
128
 
128
 
129
/** Write all data from output buffer to the console. */
129
/** Write all data from output buffer to the console. */
130
static void cbuffer_flush(void)
130
static void cbuffer_flush(void)
131
{
131
{
132
    int rc;
132
    int rc;
133
    int len;
133
    int len;
134
 
134
 
135
    len = cbp - cbuffer;
135
    len = cbp - cbuffer;
136
 
136
 
137
    while (len > 0) {
137
    while (len > 0) {
138
        rc = cons_write(cbuffer, cbp - cbuffer);
138
        rc = cons_write(cbuffer, cbp - cbuffer);
139
        if (rc < 0)
139
        if (rc < 0)
140
            return;
140
            return;
141
 
141
 
142
        len -= rc;
142
        len -= rc;
143
    }
143
    }
144
 
144
 
145
    cbp = cbuffer;
145
    cbp = cbuffer;
146
}
146
}
147
 
147
 
148
/** Drop all data in console output buffer. */
148
/** Drop all data in console output buffer. */
149
static void cbuffer_drain(void)
149
static void cbuffer_drain(void)
150
{
150
{
151
    cbp = cbuffer;
151
    cbp = cbuffer;
152
}
152
}
153
 
153
 
154
/** Write one character to the output buffer. */
154
/** Write one character to the output buffer. */
155
static inline void cbuffer_putc(int c)
155
static inline void cbuffer_putc(int c)
156
{
156
{
157
    if (cbp == cbuffer_end)
157
    if (cbp == cbuffer_end)
158
        cbuffer_flush();
158
        cbuffer_flush();
159
 
159
 
160
    *cbp++ = c;
160
    *cbp++ = c;
161
 
161
 
162
    if (c == '\n')
162
    if (c == '\n')
163
        cbuffer_flush();
163
        cbuffer_flush();
164
}
164
}
165
 
165
 
166
/** Write one character to the console via IPC. */
166
/** Write one character to the console via IPC. */
167
static void cons_putchar(wchar_t c)
167
static void cons_putchar(wchar_t c)
168
{
168
{
169
    int cons_phone = console_phone_get(true);
169
    int cons_phone = console_phone_get(true);
170
    async_msg_1(cons_phone, CONSOLE_PUTCHAR, c);
170
    async_msg_1(cons_phone, CONSOLE_PUTCHAR, c);
171
}
171
}
172
 
172
 
173
/** Write characters to the console via IPC. */
173
/** Write characters to the console via IPC. */
174
static ssize_t cons_write(const char *buf, size_t nbyte)
174
static ssize_t cons_write(const char *buf, size_t nbyte)
175
{
175
{
176
    int cons_phone = console_phone_get(true);
176
    int cons_phone = console_phone_get(true);
177
    ipcarg_t rc;
177
    ipcarg_t rc;
178
    ipc_call_t answer;
178
    ipc_call_t answer;
179
    aid_t req;
179
    aid_t req;
180
 
180
 
181
    async_serialize_start();
181
    async_serialize_start();
182
   
182
   
183
    req = async_send_0(cons_phone, CONSOLE_WRITE, &answer);
183
    req = async_send_0(cons_phone, CONSOLE_WRITE, &answer);
184
    rc = ipc_data_write_start(cons_phone, (void *) buf, nbyte);
184
    rc = ipc_data_write_start(cons_phone, (void *) buf, nbyte);
185
 
185
 
186
    if (rc != EOK) {
186
    if (rc != EOK) {
187
        async_wait_for(req, NULL);
187
        async_wait_for(req, NULL);
188
        async_serialize_end();
188
        async_serialize_end();
189
        return (ssize_t) rc;
189
        return (ssize_t) rc;
190
    }
190
    }
191
 
191
 
192
    async_wait_for(req, &rc);
192
    async_wait_for(req, &rc);
193
    async_serialize_end();
193
    async_serialize_end();
194
 
194
 
195
    if (rc == EOK)
195
    if (rc == EOK)
196
        return (ssize_t) IPC_GET_ARG1(answer);
196
        return (ssize_t) IPC_GET_ARG1(answer);
197
    else
197
    else
198
        return -1;
198
        return -1;
199
}
199
}
200
 
200
 
201
/** Write characters to the console. */
201
/** Write characters to the console. */
202
ssize_t console_write(const char *buf, size_t nbyte)
202
ssize_t console_write(const char *buf, size_t nbyte)
203
{
203
{
204
    size_t left;
204
    size_t left;
205
 
205
 
206
    left = nbyte;
206
    left = nbyte;
207
 
207
 
208
    while (left > 0) {
208
    while (left > 0) {
209
        cbuffer_putc(*buf++);
209
        cbuffer_putc(*buf++);
210
        --left;
210
        --left;
211
    }
211
    }
212
 
212
 
213
    return nbyte;
213
    return nbyte;
214
}
214
}
215
 
215
 
216
/** Write a NULL-terminated string to the console. */
216
/** Write a NULL-terminated string to the console. */
217
void console_putstr(const char *s)
217
void console_putstr(const char *s)
218
{
218
{
219
    size_t len;
219
    size_t len;
220
    ssize_t rc;
220
    ssize_t rc;
221
 
221
 
222
    len = str_size(s);
222
    len = str_size(s);
223
    while (len > 0) {
223
    while (len > 0) {
224
        rc = console_write(s, len);
224
        rc = console_write(s, len);
225
        if (rc < 0)
225
        if (rc < 0)
226
            return; /* Error */
226
            return; /* Error */
227
        s += rc;
227
        s += rc;
228
        len -= rc;
228
        len -= rc;
229
    }
229
    }
230
}
230
}
231
 
231
 
232
/** Flush all output to the console. */
232
/** Flush all output to the console. */
233
void console_flush(void)
233
void console_flush(void)
234
{
234
{
235
    int cons_phone = console_phone_get(false);
235
    int cons_phone = console_phone_get(false);
236
 
236
 
237
    cbuffer_flush();
237
    cbuffer_flush();
238
    async_msg_0(cons_phone, CONSOLE_FLUSH);
238
    async_msg_0(cons_phone, CONSOLE_FLUSH);
239
}
239
}
240
 
240
 
-
 
241
void console_flush_optional(void)
-
 
242
{
-
 
243
    if (console_phone >= 0)
-
 
244
        console_flush();
-
 
245
}
-
 
246
 
241
int console_get_size(int *rows, int *cols)
247
int console_get_size(int *rows, int *cols)
242
{
248
{
243
    int cons_phone = console_phone_get(true);
249
    int cons_phone = console_phone_get(true);
244
    ipcarg_t r, c;
250
    ipcarg_t r, c;
245
    int rc;
251
    int rc;
246
 
252
 
247
    rc = async_req_0_2(cons_phone, CONSOLE_GETSIZE, &r, &c);
253
    rc = async_req_0_2(cons_phone, CONSOLE_GETSIZE, &r, &c);
248
 
254
 
249
    *rows = (int) r;
255
    *rows = (int) r;
250
    *cols = (int) c;
256
    *cols = (int) c;
251
 
257
 
252
    return rc;
258
    return rc;
253
}
259
}
254
 
260
 
255
void console_set_style(int style)
261
void console_set_style(int style)
256
{
262
{
257
    int cons_phone = console_phone_get(true);
263
    int cons_phone = console_phone_get(true);
258
 
264
 
259
    cbuffer_flush();
265
    cbuffer_flush();
260
    async_msg_1(cons_phone, CONSOLE_SET_STYLE, style);
266
    async_msg_1(cons_phone, CONSOLE_SET_STYLE, style);
261
}
267
}
262
 
268
 
263
void console_set_color(int fg_color, int bg_color, int flags)
269
void console_set_color(int fg_color, int bg_color, int flags)
264
{
270
{
265
    int cons_phone = console_phone_get(true);
271
    int cons_phone = console_phone_get(true);
266
 
272
 
267
    cbuffer_flush();
273
    cbuffer_flush();
268
    async_msg_3(cons_phone, CONSOLE_SET_COLOR, fg_color, bg_color, flags);
274
    async_msg_3(cons_phone, CONSOLE_SET_COLOR, fg_color, bg_color, flags);
269
}
275
}
270
 
276
 
271
void console_set_rgb_color(int fg_color, int bg_color)
277
void console_set_rgb_color(int fg_color, int bg_color)
272
{
278
{
273
    int cons_phone = console_phone_get(true);
279
    int cons_phone = console_phone_get(true);
274
 
280
 
275
    cbuffer_flush();
281
    cbuffer_flush();
276
    async_msg_2(cons_phone, CONSOLE_SET_RGB_COLOR, fg_color, bg_color);
282
    async_msg_2(cons_phone, CONSOLE_SET_RGB_COLOR, fg_color, bg_color);
277
}
283
}
278
 
284
 
279
void console_cursor_visibility(int show)
285
void console_cursor_visibility(int show)
280
{
286
{
281
    int cons_phone = console_phone_get(true);
287
    int cons_phone = console_phone_get(true);
282
 
288
 
283
    cbuffer_flush();
289
    cbuffer_flush();
284
    async_msg_1(cons_phone, CONSOLE_CURSOR_VISIBILITY, show != 0);
290
    async_msg_1(cons_phone, CONSOLE_CURSOR_VISIBILITY, show != 0);
285
}
291
}
286
 
292
 
287
void console_kcon_enable(void)
293
void console_kcon_enable(void)
288
{
294
{
289
    int cons_phone = console_phone_get(true);
295
    int cons_phone = console_phone_get(true);
290
 
296
 
291
    cbuffer_flush();
297
    cbuffer_flush();
292
    async_msg_0(cons_phone, CONSOLE_KCON_ENABLE);
298
    async_msg_0(cons_phone, CONSOLE_KCON_ENABLE);
293
}
299
}
294
 
300
 
295
/** @}
301
/** @}
296
 */
302
 */
297
 
303