36,239 → 36,67 |
|
#include <libc.h> |
#include <async.h> |
#include <io/stream.h> |
#include <io/console.h> |
#include <ipc/console.h> |
#include <ipc/services.h> |
#include <errno.h> |
#include <string.h> |
#include <console.h> |
|
static int console_phone = -1; |
|
/** Size of cbuffer. */ |
#define CBUFFER_SIZE 256 |
|
/** Buffer for writing characters to the console. */ |
static char cbuffer[CBUFFER_SIZE]; |
|
/** Pointer to end of cbuffer. */ |
static char *cbuffer_end = cbuffer + CBUFFER_SIZE; |
|
/** Pointer to first available field in cbuffer. */ |
static char *cbp = cbuffer; |
|
|
/** Write one character to the console via IPC. */ |
static void cons_putchar(wchar_t c) |
void console_clear(int phone) |
{ |
console_wait(); |
async_msg_1(console_phone, CONSOLE_PUTCHAR, c); |
async_msg_0(phone, CONSOLE_CLEAR); |
} |
|
/** Write characters to the console via IPC or to klog */ |
static ssize_t cons_write(const char *buf, size_t size) |
int console_get_size(int phone, ipcarg_t *rows, ipcarg_t *cols) |
{ |
console_open(false); |
|
if (console_phone >= 0) { |
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); |
return async_req_0_2(phone, CONSOLE_GET_SIZE, rows, cols); |
} |
|
/** Write all data from output buffer to the console. */ |
static void cbuffer_flush(void) |
void console_set_style(int phone, int style) |
{ |
size_t len = cbp - cbuffer; |
|
while (len > 0) { |
ssize_t rc = cons_write(cbuffer, cbp - cbuffer); |
if (rc < 0) |
return; |
|
len -= rc; |
} |
|
cbp = cbuffer; |
async_msg_1(phone, CONSOLE_SET_STYLE, style); |
} |
|
/** Drop all data in console output buffer. */ |
static void cbuffer_drain(void) |
void console_set_color(int phone, int fg_color, int bg_color, int flags) |
{ |
cbp = cbuffer; |
async_msg_3(phone, CONSOLE_SET_COLOR, fg_color, bg_color, flags); |
} |
|
/** Write one character to the output buffer. */ |
static inline void cbuffer_putc(char c) |
void console_set_rgb_color(int phone, int fg_color, int bg_color) |
{ |
if (cbp == cbuffer_end) |
cbuffer_flush(); |
|
*cbp++ = c; |
|
if (c == '\n') |
cbuffer_flush(); |
async_msg_2(phone, CONSOLE_SET_RGB_COLOR, fg_color, bg_color); |
} |
|
int console_open(bool blocking) |
void console_cursor_visibility(int phone, bool show) |
{ |
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; |
} |
|
return console_phone; |
async_msg_1(phone, CONSOLE_CURSOR_VISIBILITY, show != false); |
} |
|
void console_close(void) |
void console_kcon_enable(int phone) |
{ |
if (console_phone >= 0) { |
if (ipc_hangup(console_phone) == 0) |
console_phone = -1; |
} |
async_msg_0(phone, CONSOLE_KCON_ENABLE); |
} |
|
void console_wait(void) |
void console_goto(int phone, ipcarg_t row, ipcarg_t col) |
{ |
while (console_phone < 0) |
console_open(true); |
async_msg_2(phone, CONSOLE_GOTO, row, col); |
} |
|
void console_clear(void) |
bool console_get_event(int phone, console_event_t *event) |
{ |
console_wait(); |
cbuffer_drain(); |
async_msg_0(console_phone, CONSOLE_CLEAR); |
} |
|
int console_get_size(int *rows, int *cols) |
{ |
console_wait(); |
|
ipcarg_t r; |
ipcarg_t type; |
ipcarg_t key; |
ipcarg_t mods; |
ipcarg_t c; |
int rc = async_req_0_2(console_phone, CONSOLE_GETSIZE, &r, &c); |
|
*rows = (int) r; |
*cols = (int) c; |
int rc = async_req_0_4(phone, CONSOLE_GET_EVENT, &type, &key, &mods, &c); |
if (rc < 0) |
return false; |
|
return rc; |
} |
|
void console_set_style(int style) |
{ |
console_wait(); |
cbuffer_flush(); |
async_msg_1(console_phone, CONSOLE_SET_STYLE, style); |
} |
|
void console_set_color(int fg_color, int bg_color, int flags) |
{ |
console_wait(); |
cbuffer_flush(); |
async_msg_3(console_phone, CONSOLE_SET_COLOR, fg_color, bg_color, flags); |
} |
|
void console_set_rgb_color(int fg_color, int bg_color) |
{ |
console_wait(); |
cbuffer_flush(); |
async_msg_2(console_phone, CONSOLE_SET_RGB_COLOR, fg_color, bg_color); |
} |
|
void console_cursor_visibility(int show) |
{ |
console_wait(); |
cbuffer_flush(); |
async_msg_1(console_phone, CONSOLE_CURSOR_VISIBILITY, show != 0); |
} |
|
void console_kcon_enable(void) |
{ |
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_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; |
event->type = type; |
event->key = key; |
event->mods = mods; |
event->c = c; |
|
while (left > 0) { |
cbuffer_putc(*buf++); |
left--; |
} |
|
return size; |
return true; |
} |
|
/** 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); |
} |
|
/** @} |
*/ |