/uspace/trunk/console/gcons.h |
---|
32,5 → 32,6 |
void gcons_init(int phone); |
void gcons_change_console(int consnum); |
void gcons_notify_char(int consnum); |
void gcons_in_kernel(void); |
#endif |
/uspace/trunk/console/screenbuffer.h |
---|
30,8 → 30,8 |
#define __SCREENBUFFER_H__ |
#define DEFAULT_FOREGROUND_COLOR 0xffffff /**< default console foreground color */ |
#define DEFAULT_BACKGROUND_COLOR 0x00003f /**< default console background color */ |
#define DEFAULT_FOREGROUND 0xffff00 /**< default console foreground color */ |
#define DEFAULT_BACKGROUND 0x000080 /**< default console background color */ |
typedef struct { |
unsigned int bg_color; /**< background color */ |
/uspace/trunk/console/console.c |
---|
69,10 → 69,12 |
screenbuffer_t screenbuffer; /**< Screenbuffer for saving screen contents and related settings. */ |
} connection_t; |
connection_t connections[CONSOLE_COUNT]; /**< Array of data for virtual consoles */ |
keyfield_t *interbuffer = NULL; /**< Pointer to memory shared with framebufer used for faster virt. console switching */ |
static connection_t connections[CONSOLE_COUNT]; /**< Array of data for virtual consoles */ |
static keyfield_t *interbuffer = NULL; /**< Pointer to memory shared with framebufer used for faster virt. console switching */ |
static int kernel_pixmap = -1; /**< Number of fb pixmap, where kernel console is stored */ |
/** Find unused virtual console. |
* |
*/ |
103,6 → 105,38 |
return CONSOLE_COUNT; |
} |
static void clrscr(void) |
{ |
nsend_call(fb_info.phone, FB_CLEAR, 0); |
} |
static void curs_visibility(int v) |
{ |
send_call(fb_info.phone, FB_CURSOR_VISIBILITY, v); |
} |
static void curs_goto(int row, int col) |
{ |
nsend_call_2(fb_info.phone, FB_CURSOR_GOTO, row, col); |
} |
static void set_style(style_t *style) |
{ |
nsend_call_2(fb_info.phone, FB_SET_STYLE, style->fg_color, style->bg_color); |
} |
static void set_style_col(int fgcolor, int bgcolor) |
{ |
nsend_call_2(fb_info.phone, FB_SET_STYLE, fgcolor, bgcolor); |
} |
static void prtchr(char c, int row, int col) |
{ |
nsend_call_3(fb_info.phone, FB_PUTCHAR, c, row, col); |
} |
/** Check key and process special keys. |
* |
* */ |
127,17 → 161,15 |
scr->position_x--; |
if (console == active_console) { |
nsend_call_3(fb_info.phone, FB_PUTCHAR, ' ', scr->position_y, scr->position_x); |
} |
if (console == active_console) |
prtchr(' ', scr->position_y, scr->position_x); |
screenbuffer_putchar(scr, ' '); |
break; |
default: |
if (console == active_console) { |
nsend_call_3(fb_info.phone, FB_PUTCHAR, key, scr->position_y, scr->position_x); |
} |
if (console == active_console) |
prtchr(key, scr->position_y, scr->position_x); |
screenbuffer_putchar(scr, key); |
scr->position_x++; |
154,12 → 186,98 |
scr->position_x = scr->position_x % scr->size_x; |
if (console == active_console) |
send_call_2(fb_info.phone, FB_CURSOR_GOTO, scr->position_y, scr->position_x); |
if (console == active_console) |
curs_goto(scr->position_y, scr->position_x); |
} |
/** Save current screen to pixmap, draw old pixmap |
* |
* @param oldpixmap Old pixmap |
* @return ID of pixmap of current screen |
*/ |
static int switch_screens(int oldpixmap) |
{ |
int newpmap; |
/* Save screen */ |
newpmap = sync_send(fb_info.phone, FB_VP2PIXMAP, 0, NULL); |
if (newpmap < 0) |
return -1; |
if (oldpixmap != -1) { |
/* Show old screen */ |
nsend_call_2(fb_info.phone, FB_VP_DRAW_PIXMAP, 0, oldpixmap); |
/* Drop old pixmap */ |
nsend_call(fb_info.phone, FB_DROP_PIXMAP, oldpixmap); |
} |
return newpmap; |
} |
/** Switch to new console */ |
static void change_console(int newcons) |
{ |
connection_t *conn; |
static int console_pixmap = -1; |
int i, j; |
char c; |
if (newcons == active_console) |
return; |
if (newcons == -1) { |
if (active_console == -1) |
return; |
active_console = -1; |
curs_visibility(0); |
if (kernel_pixmap == -1) { |
/* store/restore unsupported */ |
set_style_col(DEFAULT_FOREGROUND, DEFAULT_BACKGROUND); |
clrscr(); |
} else { |
gcons_in_kernel(); |
console_pixmap = switch_screens(kernel_pixmap); |
kernel_pixmap = -1; |
} |
__SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE); |
return; |
} |
if (console_pixmap != -1) { |
kernel_pixmap = switch_screens(console_pixmap); |
console_pixmap = -1; |
} |
active_console = newcons; |
gcons_change_console(newcons); |
conn = &connections[active_console]; |
curs_visibility(0); |
if (interbuffer) { |
for (i = 0; i < conn->screenbuffer.size_x; i++) |
for (j = 0; j < conn->screenbuffer.size_y; j++) |
interbuffer[i + j*conn->screenbuffer.size_x] = *get_field_at(&(conn->screenbuffer),i, j); |
sync_send_2(fb_info.phone, FB_DRAW_TEXT_DATA, 0, 0, NULL, NULL); |
} else { |
clrscr(); |
for (i = 0; i < conn->screenbuffer.size_x; i++) |
for (j = 0; j < conn->screenbuffer.size_y; j++) { |
c = get_field_at(&(conn->screenbuffer),i, j)->character; |
if (c && c != ' ') |
prtchr(c, j, i); |
} |
} |
curs_goto(conn->screenbuffer.position_y, conn->screenbuffer.position_x); |
set_style(&conn->screenbuffer.style); |
curs_visibility(1); |
} |
/** Handler for keyboard */ |
static void keyboard_events(ipc_callid_t iid, ipc_call_t *icall) |
{ |
166,8 → 284,7 |
ipc_callid_t callid; |
ipc_call_t call; |
int retval; |
int i, j; |
char c,d; |
char c; |
connection_t *conn; |
/* Ignore parameters, the connection is alread opened */ |
188,51 → 305,10 |
conn = &connections[active_console]; |
// if ((c >= KBD_KEY_F1) && (c < KBD_KEY_F1 + CONSOLE_COUNT)) { |
if ((c >= '0') && (c < '0' + CONSOLE_COUNT)) { |
if (c == '0') { |
/* switch to kernel console*/ |
nsend_call(fb_info.phone, FB_CURSOR_VISIBILITY, 0); |
nsend_call_2(fb_info.phone, FB_SET_STYLE, DEFAULT_FOREGROUND_COLOR, DEFAULT_BACKGROUND_COLOR); |
nsend_call(fb_info.phone, FB_CLEAR, 0); |
/* FIXME: restore kernel console */ |
__SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE); |
break; |
} else { |
c = c - '1'; |
if (c == active_console) |
break; |
active_console = c; |
gcons_change_console(c); |
} |
conn = &connections[active_console]; |
nsend_call(fb_info.phone, FB_CURSOR_VISIBILITY, 0); |
if (interbuffer) { |
for (i = 0; i < conn->screenbuffer.size_x; i++) |
for (j = 0; j < conn->screenbuffer.size_y; j++) |
interbuffer[i + j*conn->screenbuffer.size_x] = *get_field_at(&(conn->screenbuffer),i, j); |
sync_send_2(fb_info.phone, FB_DRAW_TEXT_DATA, 0, 0, NULL, NULL); |
} else { |
nsend_call(fb_info.phone, FB_CLEAR, 0); |
for (i = 0; i < conn->screenbuffer.size_x; i++) |
for (j = 0; j < conn->screenbuffer.size_y; j++) { |
d = get_field_at(&(conn->screenbuffer),i, j)->character; |
if (d && d != ' ') |
nsend_call_3(fb_info.phone, FB_PUTCHAR, d, j, i); |
} |
} |
nsend_call_2(fb_info.phone, FB_CURSOR_GOTO, conn->screenbuffer.position_y, conn->screenbuffer.position_x); |
nsend_call_2(fb_info.phone, FB_SET_STYLE, conn->screenbuffer.style.fg_color, \ |
conn->screenbuffer.style.bg_color); |
send_call(fb_info.phone, FB_CURSOR_VISIBILITY, 1); |
if (c == '0') |
change_console(-1); |
else |
change_console(c - '1'); |
break; |
} |
314,7 → 390,7 |
arg2 = IPC_GET_ARG2(call); |
screenbuffer_set_style(&(connections[consnum].screenbuffer),arg1, arg2); |
if (consnum == active_console) |
nsend_call_2(fb_info.phone, FB_SET_STYLE, arg1, arg2); |
set_style_col(arg1, arg2); |
break; |
case CONSOLE_GETCHAR: |
361,6 → 437,9 |
while ((fb_info.phone = ipc_connect_me_to(PHONE_NS, SERVICE_VIDEO, 0)) < 0) { |
usleep(10000); |
} |
/* Save old kernel screen */ |
kernel_pixmap = switch_screens(-1); |
/* Initialize gcons */ |
gcons_init(fb_info.phone); |
369,8 → 448,8 |
ipc_call_sync_2(fb_info.phone, FB_GET_CSIZE, 0, 0, &(fb_info.rows), &(fb_info.cols)); |
nsend_call_2(fb_info.phone, FB_SET_STYLE, DEFAULT_FOREGROUND_COLOR, DEFAULT_BACKGROUND_COLOR); |
nsend_call(fb_info.phone, FB_CLEAR, 0); |
set_style_col(DEFAULT_FOREGROUND, DEFAULT_BACKGROUND); |
clrscr(); |
/* Init virtual consoles */ |
for (i = 0; i < CONSOLE_COUNT; i++) { |
394,8 → 473,6 |
} |
} |
/* FIXME: save kernel console screen */ |
async_new_connection(phonehash, 0, NULL, keyboard_events); |
sync_send_2(fb_info.phone, FB_CURSOR_GOTO, 0, 0, NULL, NULL); |
/uspace/trunk/console/gcons.c |
---|
125,8 → 125,9 |
{ |
if (!use_gcons) |
return; |
draw_stat(active_console, CONS_IDLE); |
if (active_console != -1) |
draw_stat(active_console, CONS_IDLE); |
active_console = consnum; |
draw_stat(consnum, CONS_ACTIVE); |
console_has_input[consnum] = 0; |
134,6 → 135,7 |
vp_switch(console_vp); |
} |
/** Notification function that gets called on new output to virtual console */ |
void gcons_notify_char(int consnum) |
{ |
if (!use_gcons) |
143,11 → 145,31 |
return; |
console_has_input[consnum] = 1; |
if (active_console == -1) |
return; |
draw_stat(consnum, CONS_HAS_INPUT); |
vp_switch(console_vp); |
} |
/** Change to kernel console */ |
void gcons_in_kernel(void) |
{ |
draw_stat(active_console, CONS_IDLE); |
active_console = -1; /* Set to kernel console */ |
vp_switch(0); |
} |
/** Draw a PPM pixmap to framebuffer |
* |
* @param logo Pointer to PPM data |
* @param size Size of PPM data |
* @param x Coordinate of upper left corner |
* @param y Coordinate of upper left corner |
*/ |
static void draw_pixmap(char *logo, size_t size, int x, int y) |
{ |
char *shm; |
/uspace/trunk/fb/fb.c |
---|
83,6 → 83,18 |
int cursor_shown; |
} viewport_t; |
/** Maximum number of saved pixmaps |
* Pixmap is a saved rectangle |
*/ |
#define MAX_PIXMAPS 256 |
typedef struct { |
unsigned int width; |
unsigned int height; |
void *data; |
} pixmap_t; |
static pixmap_t pixmaps[MAX_PIXMAPS]; |
/* Viewport is a rectangular area on the screen */ |
#define MAX_VIEWPORTS 128 |
static viewport_t viewports[128]; |
286,24 → 298,6 |
invert_pixel(vp, col * COL_WIDTH + x, row * FONT_SCANLINES + y); |
} |
static void draw_logo(int vp,unsigned int startx, unsigned int starty) |
{ |
unsigned int x; |
unsigned int y; |
unsigned int byte; |
unsigned int rowbytes; |
rowbytes = (helenos_width - 1) / 8 + 1; |
for (y = 0; y < helenos_height; y++) |
for (x = 0; x < helenos_width; x++) { |
byte = helenos_bits[rowbytes * y + x / 8]; |
byte >>= x % 8; |
if (byte & 1) |
putpixel(vp ,startx + x, starty + y, viewports[vp].style.fg_color); |
} |
} |
/***************************************************************/ |
/* Stdout specific functions */ |
395,6 → 389,7 |
viewport_create(0,0,xres,yres); |
} |
/** Hide cursor if it is shown */ |
static void cursor_hide(int vp) |
{ |
viewport_t *vport = &viewports[vp]; |
405,6 → 400,7 |
} |
} |
/** Show cursor if cursor showing is enabled */ |
static void cursor_print(int vp) |
{ |
viewport_t *vport = &viewports[vp]; |
416,6 → 412,7 |
} |
} |
/** Invert cursor, if it is enabled */ |
static void cursor_blink(int vp) |
{ |
viewport_t *vport = &viewports[vp]; |
457,6 → 454,11 |
cursor_print(vp); |
} |
/** Draw text data to viewport |
* |
* @param vp Viewport id |
* @param data Text data fitting exactly into viewport |
*/ |
static void draw_text_data(int vp, keyfield_t *data) |
{ |
viewport_t *vport = &viewports[vp]; |
475,6 → 477,26 |
cursor_print(vp); |
} |
/** Handle shared memory communication calls |
* |
* Protocol for drawing pixmaps: |
* - FB_PREPARE_SHM(client shm identification) |
* - IPC_M_SEND_AS_AREA |
* - FB_DRAW_PPM(startx,starty) |
* - FB_DROP_SHM |
* |
* Protocol for text drawing |
* - IPC_M_SEND_AS_AREA |
* - FB_DRAW_TEXT_DATA |
* |
* @param callid Callid of the current call |
* @param call Current call data |
* @param vp Active viewport |
* @return 0 if the call was not handled byt this function, 1 otherwise |
* |
* note: this function is not threads safe, you would have |
* to redefine static variables with __thread |
*/ |
static int shm_handle(ipc_callid_t callid, ipc_call_t *call, int vp) |
{ |
static keyfield_t *interbuffer = NULL; |
558,6 → 580,124 |
return handled; |
} |
/** Return first free pixmap */ |
static int find_free_pixmap(void) |
{ |
int i; |
for (i=0;i < MAX_PIXMAPS;i++) |
if (!pixmaps[i].data) |
return i; |
return -1; |
} |
/** Save viewport to pixmap */ |
static int save_vp_to_pixmap(int vp) |
{ |
int pm; |
pixmap_t *pmap; |
viewport_t *vport = &viewports[vp]; |
int x,y; |
int rowsize; |
int tmp; |
pm = find_free_pixmap(); |
if (pm == -1) |
return ELIMIT; |
pmap = &pixmaps[pm]; |
pmap->data = malloc(screen.pixelbytes * vport->width * vport->height); |
if (!pmap->data) |
return ENOMEM; |
pmap->width = vport->width; |
pmap->height = vport->height; |
rowsize = vport->width * screen.pixelbytes; |
for (y=0;y < vport->height; y++) { |
tmp = (vport->y + y) * screen.scanline + vport->x * screen.pixelbytes; |
memcpy(pmap->data + rowsize*y, screen.fbaddress + tmp, rowsize); |
} |
return pm; |
} |
/** Draw pixmap on screen |
* |
* @param vp Viewport to draw on |
* @param pm Pixmap identifier |
*/ |
static int draw_pixmap(int vp, int pm) |
{ |
pixmap_t *pmap = &pixmaps[pm]; |
viewport_t *vport = &viewports[vp]; |
int x,y; |
int tmp, srcrowsize; |
int realwidth, realheight, realrowsize; |
if (!pmap->data) |
return EINVAL; |
realwidth = pmap->width <= vport->width ? pmap->width : vport->width; |
realheight = pmap->height <= vport->height ? pmap->height : vport->height; |
srcrowsize = vport->width * screen.pixelbytes; |
realrowsize = realwidth * screen.pixelbytes; |
for (y=0; y < realheight; y++) { |
tmp = (vport->y + y) * screen.scanline + vport->x * screen.pixelbytes; |
memcpy(screen.fbaddress + tmp, pmap->data + y * srcrowsize, realrowsize); |
} |
} |
/** Handler for messages concerning pixmap handling */ |
static int pixmap_handle(ipc_callid_t callid, ipc_call_t *call, int vp) |
{ |
int handled = 1; |
int retval = 0; |
int i,nvp; |
switch (IPC_GET_METHOD(*call)) { |
case FB_VP_DRAW_PIXMAP: |
nvp = IPC_GET_ARG1(*call); |
if (nvp == -1) |
nvp = vp; |
if (nvp < 0 || nvp >= MAX_VIEWPORTS || !viewports[nvp].initialized) { |
retval = EINVAL; |
break; |
} |
i = IPC_GET_ARG2(*call); |
retval = draw_pixmap(nvp, i); |
break; |
case FB_VP2PIXMAP: |
nvp = IPC_GET_ARG1(*call); |
if (nvp == -1) |
nvp = vp; |
if (nvp < 0 || nvp >= MAX_VIEWPORTS || !viewports[nvp].initialized) |
retval = EINVAL; |
else |
retval = save_vp_to_pixmap(nvp); |
break; |
case FB_DROP_PIXMAP: |
i = IPC_GET_ARG1(*call); |
if (i >= MAX_PIXMAPS) { |
retval = EINVAL; |
break; |
} |
if (pixmaps[i].data) { |
free(pixmaps[i].data); |
pixmaps[i].data = NULL; |
} |
break; |
default: |
handled = 0; |
} |
if (handled) |
ipc_answer_fast(callid, retval, 0, 0); |
return handled; |
} |
/** Function for handling connections to FB |
* |
*/ |
588,6 → 728,8 |
} |
if (shm_handle(callid, &call, vp)) |
continue; |
if (pixmap_handle(callid, &call, vp)) |
continue; |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
/uspace/trunk/libc/include/async.h |
---|
70,6 → 70,8 |
*r2 = IPC_GET_ARG2(result); |
return rc; |
} |
#define sync_send(phoneid, method, arg1, r1) sync_send_2(phoneid, method, arg1, 0, r1, 0) |
static inline ipcarg_t sync_send_3(int phoneid, ipcarg_t method, ipcarg_t arg1, |
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t *r1, |
ipcarg_t *r2, ipcarg_t *r3) |
/uspace/trunk/libc/include/ipc/fb.h |
---|
23,5 → 23,10 |
#define FB_DRAW_PPM 1038 |
#define FB_PREPARE_SHM 1039 |
#define FB_DROP_SHM 1040 |
#define FB_SHM2PIXMAP 1041 |
#define FB_VP_DRAW_PIXMAP 1042 |
#define FB_VP2PIXMAP 1043 |
#define FB_DROP_PIXMAP 1044 |
#endif |