/trunk/uspace/app/tetris/screen.c |
---|
117,11 → 117,6 |
console_goto(r, c); |
} |
static void fflush(void) |
{ |
console_flush(); |
} |
winsize_t winsize; |
static int get_display_size(winsize_t *ws) |
274,7 → 269,7 |
} |
if (cur_so) |
resume_normal(); |
fflush(); |
fflush(stdout); |
} |
/* |
/trunk/uspace/app/tetris/tetris.c |
---|
390,7 → 390,7 |
scr_update(); |
scr_msg(key_msg, 0); |
scr_msg(msg, 1); |
// (void) fflush(stdout); |
(void) fflush(stdout); |
} while (rwait((struct timeval *)NULL) == -1); |
scr_msg(msg, 0); |
scr_msg(key_msg, 1); |
/trunk/uspace/lib/libc/include/console.h |
---|
48,6 → 48,8 |
extern void console_clear(void); |
extern void console_goto(int, int); |
extern void console_putchar(int); |
extern ssize_t console_write(const char *buf, size_t nbyte); |
extern void console_putstr(const char *s); |
extern void console_flush(void); |
extern int console_get_size(int *, int *); |
/trunk/uspace/lib/libc/include/stdio.h |
---|
69,6 → 69,7 |
extern int puts(const char *); |
extern int putchar(int); |
extern int fflush(FILE *); |
extern int printf(const char *, ...); |
extern int asprintf(char **, const char *, ...); |
/trunk/uspace/lib/libc/include/io/stream.h |
---|
44,6 → 44,7 |
extern ssize_t read_stdin(void *, size_t); |
extern ssize_t write_stdout(const void *, size_t); |
extern ssize_t write_stderr(const void *, size_t); |
extern int flush_stdout(void); |
#endif |
/trunk/uspace/lib/libc/include/ipc/console.h |
---|
40,6 → 40,7 |
typedef enum { |
CONSOLE_GETKEY = IPC_FIRST_USER_METHOD, |
CONSOLE_PUTCHAR, |
CONSOLE_WRITE, |
CONSOLE_CLEAR, |
CONSOLE_GOTO, |
CONSOLE_GETSIZE, |
/trunk/uspace/lib/libc/include/ipc/fb.h |
---|
39,6 → 39,7 |
typedef enum { |
FB_PUTCHAR = IPC_FIRST_USER_METHOD, |
FB_WRITE, |
FB_CLEAR, |
FB_GET_CSIZE, |
FB_CURSOR_VISIBILITY, |
/trunk/uspace/lib/libc/generic/console.c |
---|
38,10 → 38,32 |
#include <io/stream.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; |
static ssize_t cons_write(const char *buf, size_t nbyte); |
static void cons_putchar(int c); |
static void cbuffer_flush(void); |
static void cbuffer_drain(void); |
static void cbuffer_putc(int c); |
void console_open(bool blocking) |
{ |
if (console_phone < 0) { |
84,6 → 106,8 |
void console_clear(void) |
{ |
int cons_phone = console_phone_get(true); |
cbuffer_drain(); |
async_msg_0(cons_phone, CONSOLE_CLEAR); |
} |
90,18 → 114,125 |
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(int c) |
{ |
cbuffer_putc(c); |
} |
/** Write all data from output buffer to the console. */ |
static void cbuffer_flush(void) |
{ |
int rc; |
int len; |
len = cbp - cbuffer; |
while (len > 0) { |
rc = cons_write(cbuffer, cbp - cbuffer); |
if (rc < 0) |
return; |
len -= rc; |
} |
cbp = cbuffer; |
} |
/** Drop all data in console output buffer. */ |
static void cbuffer_drain(void) |
{ |
cbp = cbuffer; |
} |
/** Write one character to the output buffer. */ |
static inline void cbuffer_putc(int 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(int c) |
{ |
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(); |
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; |
} |
/** Write characters to the console. */ |
ssize_t console_write(const char *buf, size_t nbyte) |
{ |
size_t left; |
left = nbyte; |
while (left > 0) { |
cbuffer_putc(*buf++); |
--left; |
} |
return nbyte; |
} |
/** Write a NULL-terminated string to the console. */ |
void console_putstr(const char *s) |
{ |
size_t len; |
ssize_t rc; |
len = strlen(s); |
while (len > 0) { |
rc = console_write(s, len); |
if (rc < 0) |
return; /* Error */ |
s += rc; |
len -= rc; |
} |
} |
/** Flush all output to the console. */ |
void console_flush(void) |
{ |
int cons_phone = console_phone_get(true); |
int cons_phone = console_phone_get(false); |
cbuffer_flush(); |
async_msg_0(cons_phone, CONSOLE_FLUSH); |
} |
122,6 → 253,8 |
void console_set_style(int style) |
{ |
int cons_phone = console_phone_get(true); |
cbuffer_flush(); |
async_msg_1(cons_phone, CONSOLE_SET_STYLE, style); |
} |
128,6 → 261,8 |
void console_set_color(int fg_color, int bg_color, int flags) |
{ |
int cons_phone = console_phone_get(true); |
cbuffer_flush(); |
async_msg_3(cons_phone, CONSOLE_SET_COLOR, fg_color, bg_color, flags); |
} |
134,6 → 269,8 |
void console_set_rgb_color(int fg_color, int bg_color) |
{ |
int cons_phone = console_phone_get(true); |
cbuffer_flush(); |
async_msg_2(cons_phone, CONSOLE_SET_RGB_COLOR, fg_color, bg_color); |
} |
140,6 → 277,8 |
void console_cursor_visibility(int show) |
{ |
int cons_phone = console_phone_get(true); |
cbuffer_flush(); |
async_msg_1(cons_phone, CONSOLE_CURSOR_VISIBILITY, show != 0); |
} |
/trunk/uspace/lib/libc/generic/io/io.c |
---|
97,6 → 97,8 |
int getchar(void) |
{ |
unsigned char c; |
flush_stdout(); |
if (read_stdin((void *) &c, 1) == 1) |
return c; |
103,5 → 105,11 |
return EOF; |
} |
int fflush(FILE *f) |
{ |
(void) f; |
return flush_stdout(); |
} |
/** @} |
*/ |
/trunk/uspace/lib/libc/generic/io/stream.c |
---|
80,12 → 80,19 |
ssize_t write_stdout(const void *buf, size_t count) |
{ |
int cons_phone = console_phone_get(false); |
int left, rc; |
if (cons_phone >= 0) { |
int i; |
for (i = 0; i < count; i++) |
console_putchar(((const char *) buf)[i]); |
left = count; |
while (left > 0) { |
rc = console_write(buf, left); |
if (rc < 0) |
break; |
buf += rc; |
left -= rc; |
} |
return count; |
} else |
92,6 → 99,12 |
return __SYSCALL3(SYS_KLOG, 1, (sysarg_t) buf, count); |
} |
int flush_stdout(void) |
{ |
console_flush(); |
return 0; |
} |
void klog_update(void) |
{ |
(void) __SYSCALL3(SYS_KLOG, 1, NULL, 0); |
/trunk/uspace/srv/console/console.c |
---|
89,8 → 89,25 |
* with framebufer used for |
* faster virtual console |
* switching */ |
/** Size of fb_buf. */ |
#define FB_BUF_SIZE 256 |
/** Buffer for sending characters to FB driver. */ |
static char fb_buf[FB_BUF_SIZE]; |
/* Properties of fb_buf data. */ |
static int fb_buf_row; /**< Row where fb_buf data belong. */ |
static int fb_buf_col; /**< Column where fb_buf data start. */ |
static int fb_console; /**< VC to which fb_buf data belong. */ |
int fb_bi = 0; /**< Number of valid chars in fb_buf. */ |
/** Size of cwrite_buf. */ |
#define CWRITE_BUF_SIZE 256 |
/** Buffer for receiving data via the CONSOLE_WRITE call from the client. */ |
static char cwrite_buf[CWRITE_BUF_SIZE]; |
/** Find unused virtual console. |
* |
*/ |
158,9 → 175,66 |
} |
} |
/** Write a character vector to FB driver via IPC. */ |
static ssize_t fb_write(const char *buf, size_t nbyte, int row, int col) |
{ |
ipcarg_t rc; |
ipc_call_t answer; |
aid_t req; |
async_serialize_start(); |
req = async_send_2(fb_info.phone, FB_WRITE, row, col, &answer); |
rc = ipc_data_write_start(fb_info.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; |
} |
/** Flush buffered characters to FB. */ |
static void fb_buf_flush(void) |
{ |
screenbuffer_t *scr; |
int i; |
scr = &(connections[fb_console].screenbuffer); |
if (fb_bi > 0) { |
if (fb_write(fb_buf, fb_bi, fb_buf_row, fb_buf_col) < 0) { |
/* Try falling back to char-by-char. */ |
for (i = 0; i < fb_bi; i++) { |
async_msg_3(fb_info.phone, FB_PUTCHAR, fb_buf[i], |
fb_buf_row, fb_buf_col + i); |
} |
} |
fb_bi = 0; |
} |
} |
/** Print a character to the active VC with buffering. */ |
static void prtchr(char c, int row, int col) |
{ |
async_msg_3(fb_info.phone, FB_PUTCHAR, c, row, col); |
if (fb_bi >= FB_BUF_SIZE) |
fb_buf_flush(); |
if (fb_bi == 0) { |
fb_buf_row = row; |
fb_buf_col = col; |
fb_console = active_console; |
} |
fb_buf[fb_bi++] = c; |
} |
/** Check key and process special keys. |
169,20 → 243,26 |
*/ |
static void write_char(int console, char key) |
{ |
bool flush_cursor = false; |
screenbuffer_t *scr = &(connections[console].screenbuffer); |
switch (key) { |
case '\n': |
fb_buf_flush(); |
flush_cursor = true; |
scr->position_y++; |
scr->position_x = 0; |
break; |
case '\r': |
fb_buf_flush(); |
break; |
case '\t': |
fb_buf_flush(); |
scr->position_x += 8; |
scr->position_x -= scr->position_x % 8; |
break; |
case '\b': |
fb_buf_flush(); |
if (scr->position_x == 0) |
break; |
scr->position_x--; |
197,9 → 277,13 |
screenbuffer_putchar(scr, key); |
scr->position_x++; |
} |
if (scr->position_x >= scr->size_x) { |
fb_buf_flush(); |
flush_cursor = true; |
scr->position_y++; |
} |
scr->position_y += (scr->position_x >= scr->size_x); |
if (scr->position_y >= scr->size_y) { |
scr->position_y = scr->size_y - 1; |
screenbuffer_clear_line(scr, scr->top_line); |
207,12 → 291,11 |
if (console == active_console) |
async_msg_1(fb_info.phone, FB_SCROLL, 1); |
} |
scr->position_x = scr->position_x % scr->size_x; |
if (console == active_console) |
if (console == active_console && flush_cursor) |
curs_goto(scr->position_y, scr->position_x); |
} |
/** Switch to new console */ |
225,7 → 308,9 |
if (newcons == active_console) |
return; |
fb_buf_flush(); |
if (newcons == KERNEL_CONSOLE) { |
async_serialize_start(); |
curs_hide_sync(); |
360,6 → 445,31 |
} |
} |
/** Handle CONSOLE_WRITE call. */ |
static void cons_write(int consnum, ipc_callid_t rid, ipc_call_t *request) |
{ |
ipc_callid_t callid; |
size_t len; |
size_t i; |
if (!ipc_data_write_receive(&callid, &len)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
} |
if (len > CWRITE_BUF_SIZE) |
len = CWRITE_BUF_SIZE; |
(void) ipc_data_write_finalize(callid, cwrite_buf, len); |
for (i = 0; i < len; i++) { |
write_char(consnum, cwrite_buf[i]); |
} |
gcons_notify_char(consnum); |
ipc_answer_1(rid, EOK, len); |
} |
/** Default thread for new connections */ |
static void client_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
411,6 → 521,9 |
write_char(consnum, IPC_GET_ARG1(call)); |
gcons_notify_char(consnum); |
break; |
case CONSOLE_WRITE: |
cons_write(consnum, callid, &call); |
continue; |
case CONSOLE_CLEAR: |
/* Send message to fb */ |
if (consnum == active_console) { |
421,6 → 534,7 |
break; |
case CONSOLE_GOTO: |
fb_buf_flush(); |
screenbuffer_goto(&conn->screenbuffer, |
IPC_GET_ARG2(call), IPC_GET_ARG1(call)); |
if (consnum == active_console) |
432,10 → 546,12 |
arg2 = fb_info.cols; |
break; |
case CONSOLE_FLUSH: |
fb_buf_flush(); |
if (consnum == active_console) |
async_req_0_0(fb_info.phone, FB_FLUSH); |
break; |
case CONSOLE_SET_STYLE: |
fb_buf_flush(); |
arg1 = IPC_GET_ARG1(call); |
screenbuffer_set_style(&conn->screenbuffer, arg1); |
if (consnum == active_console) |
442,6 → 558,7 |
set_style(arg1); |
break; |
case CONSOLE_SET_COLOR: |
fb_buf_flush(); |
arg1 = IPC_GET_ARG1(call); |
arg2 = IPC_GET_ARG2(call); |
arg3 = IPC_GET_ARG3(call); |
451,6 → 568,7 |
set_color(arg1, arg2, arg3); |
break; |
case CONSOLE_SET_RGB_COLOR: |
fb_buf_flush(); |
arg1 = IPC_GET_ARG1(call); |
arg2 = IPC_GET_ARG2(call); |
screenbuffer_set_rgb_color(&conn->screenbuffer, arg1, |
459,6 → 577,7 |
set_rgb_color(arg1, arg2); |
break; |
case CONSOLE_CURSOR_VISIBILITY: |
fb_buf_flush(); |
arg1 = IPC_GET_ARG1(call); |
conn->screenbuffer.is_cursor_visible = arg1; |
if (consnum == active_console) |
/trunk/uspace/srv/fb/serial_console.c |
---|
243,6 → 243,54 |
} |
} |
int lastcol = 0; |
int lastrow = 0; |
#define FB_WRITE_BUF_SIZE 256 |
static char fb_write_buf[FB_WRITE_BUF_SIZE]; |
static void fb_write(ipc_callid_t rid, ipc_call_t *request) |
{ |
int row, col; |
ipc_callid_t callid; |
size_t len; |
size_t i; |
row = IPC_GET_ARG1(*request); |
col = IPC_GET_ARG2(*request); |
if ((col >= scr_width) || (row >= scr_height)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
if (!ipc_data_write_receive(&callid, &len)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
if (len > FB_WRITE_BUF_SIZE) |
len = FB_WRITE_BUF_SIZE; |
if (len >= scr_width - col) |
len = scr_width - col; |
(void) ipc_data_write_finalize(callid, fb_write_buf, len); |
if ((lastcol != col) || (lastrow != row)) |
serial_goto(row, col); |
for (i = 0; i < len; i++) { |
(*putc_function)(fb_write_buf[i]); |
} |
lastcol = col + len; |
lastrow = row; |
ipc_answer_1(rid, EOK, len); |
} |
/** |
* Main function of the thread serving client connections. |
*/ |
255,8 → 303,6 |
size_t intersize = 0; |
char c; |
int lastcol = 0; |
int lastrow = 0; |
int newcol; |
int newrow; |
int fgcolor; |
317,6 → 363,11 |
(*putc_function)(c); |
retval = 0; |
break; |
case FB_WRITE: |
fb_write(callid, &call); |
/* Message already answered */ |
continue; |
case FB_CURSOR_GOTO: |
newrow = IPC_GET_ARG1(call); |
newcol = IPC_GET_ARG2(call); |
/trunk/uspace/srv/fb/fb.c |
---|
1472,6 → 1472,46 |
return rgb_from_idx(&vport->attr, fg_color, bg_color, flags); |
} |
#define FB_WRITE_BUF_SIZE 256 |
static char fb_write_buf[FB_WRITE_BUF_SIZE]; |
static void fb_write(viewport_t *vport, ipc_callid_t rid, ipc_call_t *request) |
{ |
int row, col; |
ipc_callid_t callid; |
size_t len; |
size_t i; |
row = IPC_GET_ARG1(*request); |
col = IPC_GET_ARG2(*request); |
if ((col >= vport->cols) || (row >= vport->rows)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
if (!ipc_data_write_receive(&callid, &len)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
if (len > FB_WRITE_BUF_SIZE) |
len = FB_WRITE_BUF_SIZE; |
if (len >= vport->cols - col) |
len = vport->cols - col; |
(void) ipc_data_write_finalize(callid, fb_write_buf, len); |
for (i = 0; i < len; i++) { |
draw_char(vport, fb_write_buf[i], col++, row); |
} |
ipc_answer_1(rid, EOK, len); |
} |
/** Function for handling connections to FB |
* |
*/ |
1546,6 → 1586,11 |
/* Message already answered */ |
continue; |
case FB_WRITE: |
fb_write(vport, callid, &call); |
/* Message already answered */ |
continue; |
case FB_CLEAR: |
vport_clear(vport); |
cursor_show(vport); |
/trunk/uspace/srv/fb/ega.c |
---|
359,7 → 359,7 |
break; |
default: |
retval = ENOENT; |
retval = EINVAL; |
} |
ipc_answer_0(callid, retval); |
} |