32,8 → 32,9 |
* @{ |
*/ |
/** @file |
*/ |
*/ |
|
#include <libc.h> |
#include <async.h> |
#include <io/stream.h> |
#include <ipc/console.h> |
45,7 → 46,7 |
static int console_phone = -1; |
|
/** Size of cbuffer. */ |
#define CBUFFER_SIZE 256 |
#define CBUFFER_SIZE 256 |
|
/** Buffer for writing characters to the console. */ |
static char cbuffer[CBUFFER_SIZE]; |
56,92 → 57,56 |
/** Pointer to first available field in cbuffer. */ |
static char *cbp = cbuffer; |
|
static ssize_t cons_write(const char *buf, size_t nbyte); |
static void cons_putchar(wchar_t c); |
|
static void cbuffer_flush(void); |
static void cbuffer_drain(void); |
static inline void cbuffer_putc(int c); |
|
|
void console_open(bool blocking) |
/** Write one character to the console via IPC. */ |
static void cons_putchar(wchar_t c) |
{ |
if (console_phone < 0) { |
int phone; |
if (blocking) { |
phone = ipc_connect_me_to_blocking(PHONE_NS, |
SERVICE_CONSOLE, 0, 0); |
} else { |
phone = ipc_connect_me_to(PHONE_NS, SERVICE_CONSOLE, 0, |
0); |
} |
if (phone >= 0) |
console_phone = phone; |
} |
console_wait(); |
async_msg_1(console_phone, CONSOLE_PUTCHAR, c); |
} |
|
void console_close(void) |
/** Write characters to the console via IPC or to klog */ |
static ssize_t cons_write(const char *buf, size_t size) |
{ |
console_open(false); |
|
if (console_phone >= 0) { |
if (ipc_hangup(console_phone) == 0) { |
console_phone = -1; |
async_serialize_start(); |
|
ipc_call_t answer; |
aid_t req = async_send_0(console_phone, CONSOLE_WRITE, &answer); |
ipcarg_t rc = ipc_data_write_start(console_phone, (void *) buf, size); |
|
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
return (ssize_t) rc; |
} |
} |
|
async_wait_for(req, &rc); |
async_serialize_end(); |
|
if (rc == EOK) |
return (ssize_t) IPC_GET_ARG1(answer); |
else |
return -1; |
} else |
return __SYSCALL3(SYS_KLOG, 1, (sysarg_t) buf, size); |
} |
|
int console_phone_get(bool blocking) |
{ |
if (console_phone < 0) |
console_open(blocking); |
|
return console_phone; |
} |
|
void console_wait(void) |
{ |
while (console_phone < 0) |
console_open(true); |
} |
|
void console_clear(void) |
{ |
int cons_phone = console_phone_get(true); |
|
cbuffer_drain(); |
async_msg_0(cons_phone, CONSOLE_CLEAR); |
} |
|
void console_goto(int row, int col) |
{ |
int cons_phone = console_phone_get(true); |
|
cbuffer_flush(); |
async_msg_2(cons_phone, CONSOLE_GOTO, row, col); |
} |
|
void console_putchar(wchar_t c) |
{ |
// cbuffer_putc(c); |
cbuffer_flush(); |
cons_putchar(c); |
} |
|
/** Write all data from output buffer to the console. */ |
static void cbuffer_flush(void) |
{ |
int rc; |
int len; |
|
len = cbp - cbuffer; |
|
size_t len = cbp - cbuffer; |
|
while (len > 0) { |
rc = cons_write(cbuffer, cbp - cbuffer); |
ssize_t rc = cons_write(cbuffer, cbp - cbuffer); |
if (rc < 0) |
return; |
|
|
len -= rc; |
} |
|
|
cbp = cbuffer; |
} |
|
152,151 → 117,158 |
} |
|
/** Write one character to the output buffer. */ |
static inline void cbuffer_putc(int c) |
static inline void cbuffer_putc(char c) |
{ |
if (cbp == cbuffer_end) |
cbuffer_flush(); |
|
|
*cbp++ = c; |
|
|
if (c == '\n') |
cbuffer_flush(); |
} |
|
/** Write one character to the console via IPC. */ |
static void cons_putchar(wchar_t c) |
int console_open(bool blocking) |
{ |
int cons_phone = console_phone_get(true); |
async_msg_1(cons_phone, CONSOLE_PUTCHAR, c); |
} |
|
/** Write characters to the console via IPC. */ |
static ssize_t cons_write(const char *buf, size_t nbyte) |
{ |
int cons_phone = console_phone_get(true); |
ipcarg_t rc; |
ipc_call_t answer; |
aid_t req; |
|
async_serialize_start(); |
if (console_phone < 0) { |
int phone; |
|
if (blocking) |
phone = ipc_connect_me_to_blocking(PHONE_NS, |
SERVICE_CONSOLE, 0, 0); |
else |
phone = ipc_connect_me_to(PHONE_NS, |
SERVICE_CONSOLE, 0, 0); |
|
if (phone >= 0) |
console_phone = phone; |
} |
|
req = async_send_0(cons_phone, CONSOLE_WRITE, &answer); |
rc = ipc_data_write_start(cons_phone, (void *) buf, nbyte); |
|
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
return (ssize_t) rc; |
} |
|
async_wait_for(req, &rc); |
async_serialize_end(); |
|
if (rc == EOK) |
return (ssize_t) IPC_GET_ARG1(answer); |
else |
return -1; |
return console_phone; |
} |
|
/** Write characters to the console. */ |
ssize_t console_write(const char *buf, size_t nbyte) |
void console_close(void) |
{ |
size_t left; |
|
left = nbyte; |
|
while (left > 0) { |
cbuffer_putc(*buf++); |
--left; |
if (console_phone >= 0) { |
if (ipc_hangup(console_phone) == 0) |
console_phone = -1; |
} |
|
return nbyte; |
} |
|
/** Write a NULL-terminated string to the console. */ |
void console_putstr(const char *s) |
void console_wait(void) |
{ |
size_t len; |
ssize_t rc; |
|
len = str_size(s); |
while (len > 0) { |
rc = console_write(s, len); |
if (rc < 0) |
return; /* Error */ |
s += rc; |
len -= rc; |
} |
while (console_phone < 0) |
console_open(true); |
} |
|
/** Flush all output to the console. */ |
void console_flush(void) |
void console_clear(void) |
{ |
int cons_phone = console_phone_get(false); |
|
cbuffer_flush(); |
async_msg_0(cons_phone, CONSOLE_FLUSH); |
console_wait(); |
cbuffer_drain(); |
async_msg_0(console_phone, CONSOLE_CLEAR); |
} |
|
void console_flush_optional(void) |
{ |
if (console_phone >= 0) |
console_flush(); |
} |
|
int console_get_size(int *rows, int *cols) |
{ |
int cons_phone = console_phone_get(true); |
ipcarg_t r, c; |
int rc; |
|
rc = async_req_0_2(cons_phone, CONSOLE_GETSIZE, &r, &c); |
|
console_wait(); |
|
ipcarg_t r; |
ipcarg_t c; |
int rc = async_req_0_2(console_phone, CONSOLE_GETSIZE, &r, &c); |
|
*rows = (int) r; |
*cols = (int) c; |
|
|
return rc; |
} |
|
void console_set_style(int style) |
{ |
int cons_phone = console_phone_get(true); |
|
console_wait(); |
cbuffer_flush(); |
async_msg_1(cons_phone, CONSOLE_SET_STYLE, style); |
async_msg_1(console_phone, CONSOLE_SET_STYLE, style); |
} |
|
void console_set_color(int fg_color, int bg_color, int flags) |
{ |
int cons_phone = console_phone_get(true); |
|
console_wait(); |
cbuffer_flush(); |
async_msg_3(cons_phone, CONSOLE_SET_COLOR, fg_color, bg_color, flags); |
async_msg_3(console_phone, CONSOLE_SET_COLOR, fg_color, bg_color, flags); |
} |
|
void console_set_rgb_color(int fg_color, int bg_color) |
{ |
int cons_phone = console_phone_get(true); |
|
console_wait(); |
cbuffer_flush(); |
async_msg_2(cons_phone, CONSOLE_SET_RGB_COLOR, fg_color, bg_color); |
async_msg_2(console_phone, CONSOLE_SET_RGB_COLOR, fg_color, bg_color); |
} |
|
void console_cursor_visibility(int show) |
{ |
int cons_phone = console_phone_get(true); |
|
console_wait(); |
cbuffer_flush(); |
async_msg_1(cons_phone, CONSOLE_CURSOR_VISIBILITY, show != 0); |
async_msg_1(console_phone, CONSOLE_CURSOR_VISIBILITY, show != 0); |
} |
|
void console_kcon_enable(void) |
{ |
int cons_phone = console_phone_get(true); |
console_wait(); |
cbuffer_flush(); |
async_msg_0(console_phone, CONSOLE_KCON_ENABLE); |
} |
|
void console_goto(int row, int col) |
{ |
console_wait(); |
cbuffer_flush(); |
async_msg_0(cons_phone, CONSOLE_KCON_ENABLE); |
async_msg_2(console_phone, CONSOLE_GOTO, row, col); |
} |
|
void console_putchar(wchar_t c) |
{ |
console_wait(); |
cbuffer_flush(); |
cons_putchar(c); |
} |
|
/** Write characters to the console. */ |
ssize_t console_write(const char *buf, size_t size) |
{ |
size_t left = size; |
|
while (left > 0) { |
cbuffer_putc(*buf++); |
left--; |
} |
|
return size; |
} |
|
/** Write a NULL-terminated string to the console. */ |
void console_putstr(const char *str) |
{ |
size_t left = str_size(str); |
|
while (left > 0) { |
ssize_t rc = console_write(str, left); |
|
if (rc < 0) { |
/* Error */ |
return; |
} |
|
str += rc; |
left -= rc; |
} |
} |
|
/** Flush all output to the console or klog. */ |
void console_flush(void) |
{ |
cbuffer_flush(); |
if (console_phone >= 0) |
async_msg_0(console_phone, CONSOLE_FLUSH); |
} |
|
/** @} |
*/ |