Rev 4317 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 4317 | Rev 4482 | ||
|---|---|---|---|
| Line 34... | Line 34... | ||
| 34 | /** @file |
34 | /** @file |
| 35 | */ |
35 | */ |
| 36 | 36 | ||
| 37 | #include <libc.h> |
37 | #include <libc.h> |
| 38 | #include <async.h> |
38 | #include <async.h> |
| 39 | #include <io/stream.h> |
39 | #include <io/console.h> |
| 40 | #include <ipc/console.h> |
40 | #include <ipc/console.h> |
| 41 | #include <ipc/services.h> |
- | |
| 42 | #include <errno.h> |
- | |
| 43 | #include <string.h> |
- | |
| 44 | #include <console.h> |
- | |
| 45 | 41 | ||
| 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) |
42 | void console_clear(int phone) |
| 63 | { |
43 | { |
| 64 | console_wait(); |
- | |
| 65 | async_msg_1(console_phone, CONSOLE_PUTCHAR, c); |
44 | async_msg_0(phone, CONSOLE_CLEAR); |
| 66 | } |
45 | } |
| 67 | 46 | ||
| 68 | /** Write characters to the console via IPC or to klog */ |
- | |
| 69 | static ssize_t cons_write(const char *buf, size_t size) |
47 | int console_get_size(int phone, ipcarg_t *rows, ipcarg_t *cols) |
| 70 | { |
48 | { |
| 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); |
49 | return async_req_0_2(phone, CONSOLE_GET_SIZE, rows, cols); |
| 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 | } |
50 | } |
| 96 | 51 | ||
| 97 | /** Write all data from output buffer to the console. */ |
52 | void console_set_style(int phone, int style) |
| 98 | static void cbuffer_flush(void) |
- | |
| 99 | { |
53 | { |
| 100 | size_t len = cbp - cbuffer; |
- | |
| 101 | - | ||
| 102 | while (len > 0) { |
- | |
| 103 | ssize_t rc = cons_write(cbuffer, cbp - cbuffer); |
54 | async_msg_1(phone, CONSOLE_SET_STYLE, style); |
| 104 | if (rc < 0) |
- | |
| 105 | return; |
- | |
| 106 | - | ||
| 107 | len -= rc; |
- | |
| 108 | } |
- | |
| 109 | - | ||
| 110 | cbp = cbuffer; |
- | |
| 111 | } |
55 | } |
| 112 | 56 | ||
| 113 | /** Drop all data in console output buffer. */ |
57 | void console_set_color(int phone, int fg_color, int bg_color, int flags) |
| 114 | static void cbuffer_drain(void) |
- | |
| 115 | { |
58 | { |
| 116 | cbp = cbuffer; |
59 | async_msg_3(phone, CONSOLE_SET_COLOR, fg_color, bg_color, flags); |
| 117 | } |
60 | } |
| 118 | 61 | ||
| 119 | /** Write one character to the output buffer. */ |
62 | void console_set_rgb_color(int phone, int fg_color, int bg_color) |
| 120 | static inline void cbuffer_putc(char c) |
- | |
| 121 | { |
63 | { |
| 122 | if (cbp == cbuffer_end) |
64 | async_msg_2(phone, CONSOLE_SET_RGB_COLOR, fg_color, bg_color); |
| 123 | cbuffer_flush(); |
- | |
| 124 | - | ||
| 125 | *cbp++ = c; |
- | |
| 126 | - | ||
| 127 | if (c == '\n') |
- | |
| 128 | cbuffer_flush(); |
- | |
| 129 | } |
65 | } |
| 130 | 66 | ||
| 131 | int console_open(bool blocking) |
67 | void console_cursor_visibility(int phone, bool show) |
| 132 | { |
68 | { |
| 133 | if (console_phone < 0) { |
- | |
| 134 | int phone; |
- | |
| 135 | - | ||
| 136 | if (blocking) |
- | |
| 137 | phone = ipc_connect_me_to_blocking(PHONE_NS, |
69 | async_msg_1(phone, CONSOLE_CURSOR_VISIBILITY, show != false); |
| 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 | } |
70 | } |
| 149 | 71 | ||
| 150 | void console_close(void) |
72 | void console_kcon_enable(int phone) |
| 151 | { |
73 | { |
| 152 | if (console_phone >= 0) { |
- | |
| 153 | if (ipc_hangup(console_phone) == 0) |
74 | async_msg_0(phone, CONSOLE_KCON_ENABLE); |
| 154 | console_phone = -1; |
- | |
| 155 | } |
- | |
| 156 | } |
75 | } |
| 157 | 76 | ||
| 158 | void console_wait(void) |
77 | void console_goto(int phone, ipcarg_t row, ipcarg_t col) |
| 159 | { |
78 | { |
| 160 | while (console_phone < 0) |
79 | async_msg_2(phone, CONSOLE_GOTO, row, col); |
| 161 | console_open(true); |
- | |
| 162 | } |
80 | } |
| 163 | 81 | ||
| 164 | void console_clear(void) |
82 | bool console_get_event(int phone, console_event_t *event) |
| 165 | { |
83 | { |
| 166 | console_wait(); |
84 | ipcarg_t type; |
| 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(); |
85 | ipcarg_t key; |
| 174 | - | ||
| 175 | ipcarg_t r; |
86 | ipcarg_t mods; |
| 176 | ipcarg_t c; |
87 | 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 | 88 | ||
| - | 89 | int rc = async_req_0_4(phone, CONSOLE_GET_EVENT, &type, &key, &mods, &c); |
|
| - | 90 | if (rc < 0) |
|
| 244 | return size; |
91 | return false; |
| 245 | } |
92 | |
| 246 | - | ||
| 247 | /** Write a NULL-terminated string to the console. */ |
93 | event->type = type; |
| 248 | void console_putstr(const char *str) |
94 | event->key = key; |
| 249 | { |
- | |
| 250 | size_t left = str_size(str); |
95 | event->mods = mods; |
| - | 96 | event->c = c; |
|
| 251 | 97 | ||
| 252 | while (left > 0) { |
- | |
| 253 | ssize_t rc = console_write(str, left); |
- | |
| 254 | - | ||
| 255 | if (rc < 0) { |
- | |
| 256 | /* Error */ |
- | |
| 257 | return; |
98 | return true; |
| 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 | } |
99 | } |
| 272 | 100 | ||
| 273 | /** @} |
101 | /** @} |
| 274 | */ |
102 | */ |