Index: uspace/srv/hid/console/Makefile
===================================================================
--- uspace/srv/hid/console/Makefile	(revision 16dc8870242df10ae64ee7bcbf125aa8607cb7fb)
+++ uspace/srv/hid/console/Makefile	(revision 7c014d1fbbe9734e6ee3616fac584d8cc996df36)
@@ -29,20 +29,20 @@
 
 USPACE_PREFIX = ../../..
-LIBS = $(LIBIMGMAP_PREFIX)/libimgmap.a
-EXTRA_CFLAGS += -I$(LIBIMGMAP_PREFIX)
+LIBS = $(LIBFB_PREFIX)/libfb.a
+EXTRA_CFLAGS += -I$(LIBFB_PREFIX)
 BINARY = console
 
 SOURCES = \
 	console.c \
-	keybuffer.c \
-	images.c \
-	gcons.c
+	images.c
 
 IMAGES = \
 	gfx/helenos.tga \
 	gfx/nameic.tga \
-	gfx/cons_selected.tga \
+	gfx/cons_data.tga \
+	gfx/cons_dis.tga \
+	gfx/cons_dis_sel.tga \
 	gfx/cons_idle.tga \
-	gfx/cons_has_data.tga \
+	gfx/cons_sel.tga \
 	gfx/cons_kernel.tga \
 	gfx/anim_1.tga \
Index: uspace/srv/hid/console/console.c
===================================================================
--- uspace/srv/hid/console/console.c	(revision 16dc8870242df10ae64ee7bcbf125aa8607cb7fb)
+++ uspace/srv/hid/console/console.c	(revision 7c014d1fbbe9734e6ee3616fac584d8cc996df36)
@@ -1,5 +1,4 @@
 /*
- * Copyright (c) 2006 Josef Cejka
- * Copyright (c) 2011 Jiri Svoboda
+ * Copyright (c) 2011 Martin Decky
  * All rights reserved.
  *
@@ -34,458 +33,521 @@
  */
 
-#include <libc.h>
+#include <async.h>
+#include <stdio.h>
+#include <adt/prodcons.h>
 #include <ipc/input.h>
-#include <io/keycode.h>
-#include <ipc/fb.h>
-#include <ipc/services.h>
-#include <ns.h>
-#include <ns_obsolete.h>
+#include <ipc/console.h>
+#include <ipc/vfs.h>
 #include <errno.h>
 #include <str_error.h>
-#include <ipc/console.h>
-#include <unistd.h>
-#include <async.h>
-#include <async_obsolete.h>
-#include <adt/fifo.h>
-#include <sys/mman.h>
-#include <stdio.h>
-#include <str.h>
-#include <sysinfo.h>
+#include <loc.h>
 #include <event.h>
-#include <loc.h>
-#include <fcntl.h>
-#include <vfs/vfs.h>
+#include <io/keycode.h>
+#include <screenbuffer.h>
+#include <fb.h>
+#include <imgmap.h>
+#include <align.h>
+#include <malloc.h>
+#include <as.h>
 #include <fibril_synch.h>
-#include <io/style.h>
-#include <io/screenbuffer.h>
-
+#include "images.h"
 #include "console.h"
-#include "gcons.h"
-#include "keybuffer.h"
 
 #define NAME       "console"
 #define NAMESPACE  "term"
 
-/** Session with the input server. */
+#define CONSOLE_TOP     66
+#define CONSOLE_MARGIN  12
+
+#define STATE_START   110
+#define STATE_TOP     8
+#define STATE_SPACE   4
+#define STATE_WIDTH   48
+#define STATE_HEIGHT  48
+
+typedef enum {
+	CONS_DISCONNECTED = 0,
+	CONS_DISCONNECTED_SELECTED,
+	CONS_SELECTED,
+	CONS_IDLE,
+	CONS_DATA,
+	CONS_KERNEL,
+	CONS_LAST
+} console_state_t;
+
+typedef struct {
+	atomic_t refcnt;           /**< Connection reference count */
+	prodcons_t input_pc;       /**< Incoming keyboard events */
+	
+	fibril_mutex_t mtx;        /**< Lock protecting mutable fields */
+	
+	size_t index;              /**< Console index */
+	console_state_t state;     /**< Console state */
+	service_id_t dsid;         /**< Service handle */
+	
+	vp_handle_t state_vp;      /**< State icon viewport */
+	sysarg_t cols;             /**< Number of columns */
+	sysarg_t rows;             /**< Number of rows */
+	console_caps_t ccaps;      /**< Console capabilities */
+	
+	screenbuffer_t *frontbuf;  /**< Front buffer */
+	frontbuf_handle_t fbid;    /**< Front buffer handle */
+} console_t;
+
+typedef enum {
+	GRAPHICS_NONE = 0,
+	GRAPHICS_BASIC = 1,
+	GRAPHICS_FULL = 2
+} graphics_state_t;
+
+/** Current console state */
+static graphics_state_t graphics_state = GRAPHICS_NONE;
+
+/** State icons */
+static imagemap_handle_t state_icons[CONS_LAST];
+
+/** Session to the input server */
 static async_sess_t *input_sess;
 
-/** Information about framebuffer */
-struct {
-	int phone;           /**< Framebuffer phone */
-	sysarg_t cols;       /**< Framebuffer columns */
-	sysarg_t rows;       /**< Framebuffer rows */
-	sysarg_t color_cap;  /**< Color capabilities (FB_CCAP_xxx) */
-} fb_info;
-
-typedef struct {
-	size_t index;             /**< Console index */
-	size_t refcount;          /**< Connection reference count */
-	service_id_t service_id;  /**< Service ID */
-	keybuffer_t keybuffer;    /**< Buffer for incoming keys. */
-	screenbuffer_t scr;       /**< Screenbuffer for saving screen
-	                               contents and related settings. */
-} console_t;
+/** Session to the framebuffer server */
+static async_sess_t *fb_sess;
+
+/** Framebuffer resolution */
+static sysarg_t xres;
+static sysarg_t yres;
 
 /** Array of data for virtual consoles */
 static console_t consoles[CONSOLE_COUNT];
 
+/** Mutex for console switching */
+static FIBRIL_MUTEX_INITIALIZE(switch_mtx);
+
+static console_t *prev_console = &consoles[0];
 static console_t *active_console = &consoles[0];
-static console_t *prev_console = &consoles[0];
 static console_t *kernel_console = &consoles[KERNEL_CONSOLE];
 
-/** Pointer to memory shared with framebufer used for
-    faster virtual console switching */
-static keyfield_t *interbuffer = NULL;
-
-/** Information on row-span yet unsent to FB driver. */
+static imgmap_t *logo_img;
+static imgmap_t *nameic_img;
+
+static imgmap_t *anim_1_img;
+static imgmap_t *anim_2_img;
+static imgmap_t *anim_3_img;
+static imgmap_t *anim_4_img;
+
+static imagemap_handle_t anim_1;
+static imagemap_handle_t anim_2;
+static imagemap_handle_t anim_3;
+static imagemap_handle_t anim_4;
+
+static sequence_handle_t anim_seq;
+
+static imgmap_t *cons_data_img;
+static imgmap_t *cons_dis_img;
+static imgmap_t *cons_dis_sel_img;
+static imgmap_t *cons_idle_img;
+static imgmap_t *cons_kernel_img;
+static imgmap_t *cons_sel_img;
+
+static vp_handle_t logo_vp;
+static imagemap_handle_t logo_handle;
+
+static vp_handle_t nameic_vp;
+static imagemap_handle_t nameic_handle;
+
+static vp_handle_t screen_vp;
+static vp_handle_t console_vp;
+
 struct {
-	sysarg_t col;  /**< Leftmost column of the span. */
-	sysarg_t row;  /**< Row where the span lies. */
-	sysarg_t cnt;  /**< Width of the span. */
-} fb_pending;
-
-static FIBRIL_MUTEX_INITIALIZE(input_mutex);
-static FIBRIL_CONDVAR_INITIALIZE(input_cv);
-
-static FIBRIL_MUTEX_INITIALIZE(big_console_lock);
-
-static void console_serialize_start(void)
-{
-	fibril_mutex_lock(&big_console_lock);
-}
-
-static void console_serialize_end(void)
-{
-	fibril_mutex_unlock(&big_console_lock);
-}
-
-static void curs_visibility(bool visible)
-{
-	async_obsolete_msg_1(fb_info.phone, FB_CURSOR_VISIBILITY, visible); 
-}
-
-static void curs_hide_sync(void)
-{
-	async_obsolete_req_1_0(fb_info.phone, FB_CURSOR_VISIBILITY, false); 
-}
-
-static void curs_goto(sysarg_t x, sysarg_t y)
-{
-	async_obsolete_msg_2(fb_info.phone, FB_CURSOR_GOTO, x, y);
-}
-
-static void screen_clear(void)
-{
-	async_obsolete_msg_0(fb_info.phone, FB_CLEAR);
-}
-
-static void screen_yield(void)
-{
-	async_obsolete_req_0_0(fb_info.phone, FB_SCREEN_YIELD);
-}
-
-static void screen_reclaim(void)
-{
-	async_obsolete_req_0_0(fb_info.phone, FB_SCREEN_RECLAIM);
-}
-
-static void input_yield(void)
-{
-	async_exch_t *exch = async_exchange_begin(input_sess);
-	if (exch == NULL) {
-		printf("%s: Failed starting exchange with input device.\n",
-		    NAME);
+	sysarg_t x;
+	sysarg_t y;
+	
+	sysarg_t btn_x;
+	sysarg_t btn_y;
+	
+	bool pressed;
+} mouse;
+
+static void cons_redraw_state(console_t *cons)
+{
+	if (graphics_state == GRAPHICS_FULL) {
+		fibril_mutex_lock(&cons->mtx);
+		
+		fb_vp_imagemap_damage(fb_sess, cons->state_vp,
+		    state_icons[cons->state], 0, 0, STATE_WIDTH, STATE_HEIGHT);
+		
+		if ((cons->state != CONS_DISCONNECTED) &&
+		    (cons->state != CONS_KERNEL) &&
+		    (cons->state != CONS_DISCONNECTED_SELECTED)) {
+			char data[5];
+			snprintf(data, 5, "%zu", cons->index + 1);
+			
+			for (size_t i = 0; data[i] != 0; i++)
+				fb_vp_putchar(fb_sess, cons->state_vp, i + 2, 1, data[i]);
+		}
+		
+		fibril_mutex_unlock(&cons->mtx);
+	}
+}
+
+static void cons_kernel_sequence_start(console_t *cons)
+{
+	if (graphics_state == GRAPHICS_FULL) {
+		fibril_mutex_lock(&cons->mtx);
+		
+		fb_vp_sequence_start(fb_sess, cons->state_vp, anim_seq);
+		fb_vp_imagemap_damage(fb_sess, cons->state_vp,
+		    state_icons[cons->state], 0, 0, STATE_WIDTH, STATE_HEIGHT);
+		
+		fibril_mutex_unlock(&cons->mtx);
+	}
+}
+
+static void cons_update_state(console_t *cons, console_state_t state)
+{
+	bool update = false;
+	
+	fibril_mutex_lock(&cons->mtx);
+	
+	if (cons->state != state) {
+		cons->state = state;
+		update = true;
+	}
+	
+	fibril_mutex_unlock(&cons->mtx);
+	
+	if (update)
+		cons_redraw_state(cons);
+}
+
+static void cons_notify_data(console_t *cons)
+{
+	fibril_mutex_lock(&switch_mtx);
+	
+	if (cons != active_console)
+		cons_update_state(cons, CONS_DATA);
+	
+	fibril_mutex_unlock(&switch_mtx);
+}
+
+static void cons_notify_connect(console_t *cons)
+{
+	fibril_mutex_lock(&switch_mtx);
+	
+	if (cons == active_console)
+		cons_update_state(cons, CONS_SELECTED);
+	else
+		cons_update_state(cons, CONS_IDLE);
+	
+	fibril_mutex_unlock(&switch_mtx);
+}
+
+static void cons_notify_disconnect(console_t *cons)
+{
+	fibril_mutex_lock(&switch_mtx);
+	
+	if (cons == active_console)
+		cons_update_state(cons, CONS_DISCONNECTED_SELECTED);
+	else
+		cons_update_state(cons, CONS_DISCONNECTED);
+	
+	fibril_mutex_unlock(&switch_mtx);
+}
+
+static void cons_update(console_t *cons)
+{
+	fibril_mutex_lock(&switch_mtx);
+	fibril_mutex_lock(&cons->mtx);
+	
+	if ((cons == active_console) && (active_console != kernel_console)) {
+		fb_vp_update(fb_sess, console_vp, cons->fbid);
+		fb_vp_cursor_update(fb_sess, console_vp, cons->fbid);
+	}
+	
+	fibril_mutex_unlock(&cons->mtx);
+	fibril_mutex_unlock(&switch_mtx);
+}
+
+static void cons_update_cursor(console_t *cons)
+{
+	fibril_mutex_lock(&switch_mtx);
+	fibril_mutex_lock(&cons->mtx);
+	
+	if ((cons == active_console) && (active_console != kernel_console))
+		fb_vp_cursor_update(fb_sess, console_vp, cons->fbid);
+	
+	fibril_mutex_unlock(&cons->mtx);
+	fibril_mutex_unlock(&switch_mtx);
+}
+
+static void cons_clear(console_t *cons)
+{
+	fibril_mutex_lock(&cons->mtx);
+	screenbuffer_clear(cons->frontbuf);
+	fibril_mutex_unlock(&cons->mtx);
+	
+	cons_update(cons);
+}
+
+static void cons_damage_all(console_t *cons)
+{
+	fibril_mutex_lock(&switch_mtx);
+	fibril_mutex_lock(&cons->mtx);
+	
+	if ((cons == active_console) && (active_console != kernel_console)) {
+		fb_vp_damage(fb_sess, console_vp, cons->fbid, 0, 0, cons->cols,
+		    cons->rows);
+		fb_vp_cursor_update(fb_sess, console_vp, cons->fbid);
+	}
+	
+	fibril_mutex_unlock(&cons->mtx);
+	fibril_mutex_unlock(&switch_mtx);
+}
+
+static void cons_switch(console_t *cons)
+{
+	fibril_mutex_lock(&switch_mtx);
+	
+	if (cons == active_console) {
+		fibril_mutex_unlock(&switch_mtx);
 		return;
 	}
 	
-	async_req_0_0(exch, INPUT_YIELD);
-	async_exchange_end(exch);
-}
-
-static void input_reclaim(void)
-{
-	async_exch_t *exch = async_exchange_begin(input_sess);
-	if (exch == NULL) {
-		printf("%s: Failed starting exchange with input device.\n",
-		    NAME);
-		return;
-	}
-	
-	async_req_0_0(exch, INPUT_RECLAIM);
-	async_exchange_end(exch);
-}
-
-static void set_style(uint8_t style)
-{
-	async_obsolete_msg_1(fb_info.phone, FB_SET_STYLE, style);
-}
-
-static void set_color(uint8_t fgcolor, uint8_t bgcolor, uint8_t flags)
-{
-	async_obsolete_msg_3(fb_info.phone, FB_SET_COLOR, fgcolor, bgcolor, flags);
-}
-
-static void set_rgb_color(uint32_t fgcolor, uint32_t bgcolor)
-{
-	async_obsolete_msg_2(fb_info.phone, FB_SET_RGB_COLOR, fgcolor, bgcolor); 
-}
-
-static void set_attrs(attrs_t *attrs)
-{
-	switch (attrs->t) {
-	case at_style:
-		set_style(attrs->a.s.style);
-		break;
-	case at_idx:
-		set_color(attrs->a.i.fg_color, attrs->a.i.bg_color,
-		    attrs->a.i.flags);
-		break;
-	case at_rgb:
-		set_rgb_color(attrs->a.r.fg_color, attrs->a.r.bg_color);
-		break;
-	}
-}
-
-static int ccap_fb_to_con(sysarg_t ccap_fb, sysarg_t *ccap_con)
-{
-	switch (ccap_fb) {
-	case FB_CCAP_NONE:
-		*ccap_con = CONSOLE_CCAP_NONE;
-		break;
-	case FB_CCAP_STYLE:
-		*ccap_con = CONSOLE_CCAP_STYLE;
-		break;
-	case FB_CCAP_INDEXED:
-		*ccap_con = CONSOLE_CCAP_INDEXED;
-		break;
-	case FB_CCAP_RGB:
-		*ccap_con = CONSOLE_CCAP_RGB;
-		break;
-	default:
-		return EINVAL;
-	}
-	
-	return EOK;
-}
-
-/** Send an area of screenbuffer to the FB driver. */
-static void fb_update_area(console_t *cons, sysarg_t x0, sysarg_t y0, sysarg_t width, sysarg_t height)
-{
-	if (interbuffer) {
-		sysarg_t x;
-		sysarg_t y;
-		
-		for (y = 0; y < height; y++) {
-			for (x = 0; x < width; x++) {
-				interbuffer[y * width + x] =
-				    *get_field_at(&cons->scr, x0 + x, y0 + y);
-			}
-		}
-		
-		async_obsolete_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
-		    x0, y0, width, height);
-	}
-}
-
-/** Flush pending cells to FB. */
-static void fb_pending_flush(void)
-{
-	if (fb_pending.cnt > 0) {
-		fb_update_area(active_console, fb_pending.col,
-		    fb_pending.row, fb_pending.cnt, 1);
-		fb_pending.cnt = 0;
-	}
-}
-
-/** Mark a character cell as changed.
+	if (cons == kernel_console) {
+		fb_yield(fb_sess);
+		if (!console_kcon()) {
+			fb_claim(fb_sess);
+			fibril_mutex_unlock(&switch_mtx);
+			return;
+		}
+	}
+	
+	if (active_console == kernel_console)
+		fb_claim(fb_sess);
+	
+	prev_console = active_console;
+	active_console = cons;
+	
+	if (prev_console->state == CONS_DISCONNECTED_SELECTED)
+		cons_update_state(prev_console, CONS_DISCONNECTED);
+	else
+		cons_update_state(prev_console, CONS_IDLE);
+	
+	if ((cons->state == CONS_DISCONNECTED) ||
+	    (cons->state == CONS_DISCONNECTED_SELECTED))
+		cons_update_state(cons, CONS_DISCONNECTED_SELECTED);
+	else
+		cons_update_state(cons, CONS_SELECTED);
+	
+	fibril_mutex_unlock(&switch_mtx);
+	
+	cons_damage_all(cons);
+}
+
+static ssize_t limit(ssize_t val, ssize_t lo, ssize_t hi)
+{
+	if (val > hi)
+		return hi;
+	
+	if (val < lo)
+		return lo;
+	
+	return val;
+}
+
+static void cons_mouse_move(sysarg_t dx, sysarg_t dy)
+{
+	ssize_t sx = (ssize_t) dx;
+	ssize_t sy = (ssize_t) dy;
+	
+	mouse.x = limit(mouse.x + sx, 0, xres);
+	mouse.y = limit(mouse.y + sy, 0, yres);
+	
+	fb_pointer_update(fb_sess, mouse.x, mouse.y, true);
+}
+
+static console_t *cons_find_icon(sysarg_t x, sysarg_t y)
+{
+	sysarg_t status_start = STATE_START + (xres - 800) / 2;
+	
+	if ((y < STATE_TOP) || (y >= STATE_TOP + STATE_HEIGHT))
+		return NULL;
+	
+	if (x < status_start)
+		return NULL;
+	
+	if (x >= status_start + (STATE_WIDTH + STATE_SPACE) * CONSOLE_COUNT)
+		return NULL;
+	
+	if (((x - status_start) % (STATE_WIDTH + STATE_SPACE)) < STATE_SPACE)
+		return NULL;
+	
+	sysarg_t btn = (x - status_start) / (STATE_WIDTH + STATE_SPACE);
+	
+	if (btn < CONSOLE_COUNT)
+		return consoles + btn;
+	
+	return NULL;
+}
+
+/** Handle mouse click
  *
- * This adds the cell to the pending rowspan if possible. Otherwise
- * the old span is flushed first.
+ * @param state Button state (true - pressed, false - depressed)
  *
  */
-static void cell_mark_changed(sysarg_t col, sysarg_t row)
-{
-	if (fb_pending.cnt != 0) {
-		if ((col != fb_pending.col + fb_pending.cnt)
-		    || (row != fb_pending.row)) {
-			fb_pending_flush();
-		}
-	}
-	
-	if (fb_pending.cnt == 0) {
-		fb_pending.col = col;
-		fb_pending.row = row;
-	}
-	
-	fb_pending.cnt++;
-}
-
-/** Print a character to the active VC with buffering. */
-static void fb_putchar(wchar_t c, sysarg_t col, sysarg_t row)
-{
-	async_obsolete_msg_3(fb_info.phone, FB_PUTCHAR, c, col, row);
+static console_t *cons_mouse_button(bool state)
+{
+	if (graphics_state != GRAPHICS_FULL)
+		return NULL;
+	
+	if (state) {
+		console_t *cons = cons_find_icon(mouse.x, mouse.y);
+		if (cons != NULL) {
+			mouse.btn_x = mouse.x;
+			mouse.btn_y = mouse.y;
+			mouse.pressed = true;
+		}
+		
+		return NULL;
+	}
+	
+	if ((!state) && (!mouse.pressed))
+		return NULL;
+	
+	console_t *cons = cons_find_icon(mouse.x, mouse.y);
+	if (cons == cons_find_icon(mouse.btn_x, mouse.btn_y))
+		return cons;
+	
+	mouse.pressed = false;
+	return NULL;
+}
+
+static void input_events(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	/* Ignore parameters, the connection is already opened */
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		if (!IPC_GET_IMETHOD(call)) {
+			/* TODO: Handle hangup */
+			async_hangup(input_sess);
+			return;
+		}
+		
+		kbd_event_type_t type;
+		keycode_t key;
+		keymod_t mods;
+		wchar_t c;
+		
+		switch (IPC_GET_IMETHOD(call)) {
+		case INPUT_EVENT_KEY:
+			type = IPC_GET_ARG1(call);
+			key = IPC_GET_ARG2(call);
+			mods = IPC_GET_ARG3(call);
+			c = IPC_GET_ARG4(call);
+			
+			if ((key >= KC_F1) && (key < KC_F1 + CONSOLE_COUNT) &&
+			    ((mods & KM_CTRL) == 0))
+				cons_switch(&consoles[key - KC_F1]);
+			else {
+				/* Got key press/release event */
+				kbd_event_t *event =
+				    (kbd_event_t *) malloc(sizeof(kbd_event_t));
+				if (event == NULL) {
+					async_answer_0(callid, ENOMEM);
+					break;
+				}
+				
+				link_initialize(&event->link);
+				event->type = type;
+				event->key = key;
+				event->mods = mods;
+				event->c = c;
+				
+				prodcons_produce(&active_console->input_pc, &event->link);
+			}
+			
+			async_answer_0(callid, EOK);
+			break;
+		case INPUT_EVENT_MOVE:
+			cons_mouse_move(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
+			async_answer_0(callid, EOK);
+			break;
+		case INPUT_EVENT_BUTTON:
+			/* Got pointer button press/release event */
+			if (IPC_GET_ARG1(call) == 1) {
+				console_t *cons =
+				    cons_mouse_button((bool) IPC_GET_ARG2(call));
+				if (cons != NULL)
+					cons_switch(cons);
+			}
+			async_answer_0(callid, EOK);
+			break;
+		default:
+			async_answer_0(callid, EINVAL);
+		}
+	}
 }
 
 /** Process a character from the client (TTY emulation). */
-static void write_char(console_t *cons, wchar_t ch)
-{
-	bool flush_cursor = false;
+static void cons_write_char(console_t *cons, wchar_t ch)
+{
+	sysarg_t updated = 0;
+	
+	fibril_mutex_lock(&cons->mtx);
 	
 	switch (ch) {
 	case '\n':
-		fb_pending_flush();
-		flush_cursor = true;
-		cons->scr.position_y++;
-		cons->scr.position_x = 0;
+		updated = screenbuffer_newline(cons->frontbuf);
 		break;
 	case '\r':
 		break;
 	case '\t':
-		cons->scr.position_x += 8;
-		cons->scr.position_x -= cons->scr.position_x % 8;
+		updated = screenbuffer_tabstop(cons->frontbuf, 8);
 		break;
 	case '\b':
-		if (cons->scr.position_x == 0)
-			break;
-		cons->scr.position_x--;
-		if (cons == active_console)
-			cell_mark_changed(cons->scr.position_x, cons->scr.position_y);
-		screenbuffer_putchar(&cons->scr, ' ');
+		updated = screenbuffer_backspace(cons->frontbuf);
 		break;
 	default:
-		if (cons == active_console)
-			cell_mark_changed(cons->scr.position_x, cons->scr.position_y);
-		
-		screenbuffer_putchar(&cons->scr, ch);
-		cons->scr.position_x++;
-	}
-	
-	if (cons->scr.position_x >= cons->scr.size_x) {
-		flush_cursor = true;
-		cons->scr.position_y++;
-	}
-	
-	if (cons->scr.position_y >= cons->scr.size_y) {
-		fb_pending_flush();
-		cons->scr.position_y = cons->scr.size_y - 1;
-		screenbuffer_clear_line(&cons->scr, cons->scr.top_line);
-		cons->scr.top_line = (cons->scr.top_line + 1) % cons->scr.size_y;
-		
-		if (cons == active_console)
-			async_obsolete_msg_1(fb_info.phone, FB_SCROLL, 1);
-	}
-	
-	if (cons == active_console && flush_cursor)
-		curs_goto(cons->scr.position_x, cons->scr.position_y);
-	cons->scr.position_x = cons->scr.position_x % cons->scr.size_x;
-}
-
-/** Switch to new console */
-static void change_console(console_t *cons)
-{
-	if (cons == active_console)
-		return;
-	
-	fb_pending_flush();
-	
-	if (cons == kernel_console) {
-		console_serialize_start();
-		curs_hide_sync();
-		gcons_in_kernel();
-		screen_yield();
-		input_yield();
-		console_serialize_end();
-		
-		if (console_kcon()) {
-			prev_console = active_console;
-			active_console = kernel_console;
-		} else
-			cons = active_console;
-	}
-	
-	if (cons != kernel_console) {
-		console_serialize_start();
-		
-		if (active_console == kernel_console) {
-			screen_reclaim();
-			input_reclaim();
-			gcons_redraw_console();
-		}
-		
-		active_console = cons;
-		gcons_change_console(cons->index);
-		
-		set_attrs(&cons->scr.attrs);
-		curs_visibility(false);
-		
-		sysarg_t x;
-		sysarg_t y;
-		int rc = 0;
-		
-		if (interbuffer) {
-			for (y = 0; y < cons->scr.size_y; y++) {
-				for (x = 0; x < cons->scr.size_x; x++) {
-					interbuffer[y * cons->scr.size_x + x] =
-					    *get_field_at(&cons->scr, x, y);
-				}
-			}
-			
-			/* This call can preempt, but we are already at the end */
-			rc = async_obsolete_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
-			    0, 0, cons->scr.size_x,
-			    cons->scr.size_y);
-		}
-		
-		if ((!interbuffer) || (rc != 0)) {
-			set_attrs(&cons->scr.attrs);
-			screen_clear();
-			
-			for (y = 0; y < cons->scr.size_y; y++)
-				for (x = 0; x < cons->scr.size_x; x++) {
-					keyfield_t *field = get_field_at(&cons->scr, x, y);
-					
-					if (!attrs_same(cons->scr.attrs, field->attrs))
-						set_attrs(&field->attrs);
-					
-					cons->scr.attrs = field->attrs;
-					if ((field->character == ' ') &&
-					    (attrs_same(field->attrs, cons->scr.attrs)))
-						continue;
-					
-					fb_putchar(field->character, x, y);
-				}
-		}
-		
-		curs_goto(cons->scr.position_x, cons->scr.position_y);
-		curs_visibility(cons->scr.is_cursor_visible);
-		
-		console_serialize_end();
-	}
-}
-
-/** Handler for input events */
-static void input_events(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	/* Ignore parameters, the connection is already opened */
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		int retval;
-		kbd_event_t ev;
-		
-		if (!IPC_GET_IMETHOD(call)) {
-			/* TODO: Handle hangup */
-			async_hangup(input_sess);
-			return;
-		}
-		
-		switch (IPC_GET_IMETHOD(call)) {
-		case INPUT_EVENT_KEY:
-			/* Got key press/release event */
-			retval = 0;
-			ev.type = IPC_GET_ARG1(call);
-			ev.key = IPC_GET_ARG2(call);
-			ev.mods = IPC_GET_ARG3(call);
-			ev.c = IPC_GET_ARG4(call);
-			
-			if ((ev.key >= KC_F1) && (ev.key < KC_F1 +
-			    CONSOLE_COUNT) && ((ev.mods & KM_CTRL) == 0)) {
-				if (ev.key == KC_F1 + KERNEL_CONSOLE)
-					change_console(kernel_console);
-				else
-					change_console(&consoles[ev.key - KC_F1]);
-				break;
-			}
-			
-			fibril_mutex_lock(&input_mutex);
-			keybuffer_push(&active_console->keybuffer, &ev);
-			fibril_condvar_broadcast(&input_cv);
-			fibril_mutex_unlock(&input_mutex);
-			break;
-		case INPUT_EVENT_MOVE:
-			/* Got pointer move event */
-			gcons_mouse_move((int) IPC_GET_ARG1(call),
-			    (int) IPC_GET_ARG2(call));
-			retval = 0;
-			break;
-		case INPUT_EVENT_BUTTON:
-			/* Got pointer button press/release event */
-			if (IPC_GET_ARG1(call) == 1) {
-				int newcon = gcons_mouse_btn((bool) IPC_GET_ARG2(call));
-				if (newcon != -1)
-					change_console(&consoles[newcon]);
-			}
-			retval = 0;
-			break;
-		default:
-			retval = ENOENT;
-		}
-
-		async_answer_0(callid, retval);
-	}
-}
-
-static void cons_write(console_t *cons, ipc_callid_t rid, ipc_call_t *request)
+		updated = screenbuffer_putchar(cons->frontbuf, ch, true);
+	}
+	
+	fibril_mutex_unlock(&cons->mtx);
+	
+	if (updated > 1)
+		cons_update(cons);
+}
+
+static void cons_set_cursor(console_t *cons, sysarg_t col, sysarg_t row)
+{
+	fibril_mutex_lock(&cons->mtx);
+	screenbuffer_set_cursor(cons->frontbuf, col, row);
+	fibril_mutex_unlock(&cons->mtx);
+	
+	cons_update_cursor(cons);
+}
+
+static void cons_set_cursor_visibility(console_t *cons, bool visible)
+{
+	fibril_mutex_lock(&cons->mtx);
+	screenbuffer_set_cursor_visibility(cons->frontbuf, visible);
+	fibril_mutex_unlock(&cons->mtx);
+	
+	cons_update_cursor(cons);
+}
+
+static void cons_get_cursor(console_t *cons, ipc_callid_t iid, ipc_call_t *icall)
+{
+	sysarg_t col;
+	sysarg_t row;
+	
+	fibril_mutex_lock(&cons->mtx);
+	screenbuffer_get_cursor(cons->frontbuf, &col, &row);
+	fibril_mutex_unlock(&cons->mtx);
+	
+	async_answer_2(iid, EOK, col, row);
+}
+
+static void cons_write(console_t *cons, ipc_callid_t iid, ipc_call_t *icall)
 {
 	void *buf;
@@ -494,25 +556,19 @@
 	
 	if (rc != EOK) {
-		async_answer_0(rid, rc);
+		async_answer_0(iid, rc);
 		return;
 	}
 	
-	console_serialize_start();
-	
 	size_t off = 0;
-	while (off < size) {
-		wchar_t ch = str_decode(buf, &off, size);
-		write_char(cons, ch);
-	}
-	
-	console_serialize_end();
-	
-	gcons_notify_char(cons->index);
-	async_answer_1(rid, EOK, size);
-	
+	while (off < size)
+		cons_write_char(cons, str_decode(buf, &off, size));
+	
+	async_answer_1(iid, EOK, size);
 	free(buf);
-}
-
-static void cons_read(console_t *cons, ipc_callid_t rid, ipc_call_t *request)
+	
+	cons_notify_data(cons);
+}
+
+static void cons_read(console_t *cons, ipc_callid_t iid, ipc_call_t *icall)
 {
 	ipc_callid_t callid;
@@ -520,5 +576,5 @@
 	if (!async_data_read_receive(&callid, &size)) {
 		async_answer_0(callid, EINVAL);
-		async_answer_0(rid, EINVAL);
+		async_answer_0(iid, EINVAL);
 		return;
 	}
@@ -527,60 +583,67 @@
 	if (buf == NULL) {
 		async_answer_0(callid, ENOMEM);
-		async_answer_0(rid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
 		return;
 	}
 	
 	size_t pos = 0;
-	kbd_event_t ev;
-	fibril_mutex_lock(&input_mutex);
-	
-recheck:
-	while ((keybuffer_pop(&cons->keybuffer, &ev)) && (pos < size)) {
-		if (ev.type == KEY_PRESS) {
-			buf[pos] = ev.c;
+	while (pos < size) {
+		link_t *link = prodcons_consume(&cons->input_pc);
+		kbd_event_t *event = list_get_instance(link, kbd_event_t, link);
+		
+		if (event->type == KEY_PRESS) {
+			buf[pos] = event->c;
 			pos++;
 		}
-	}
-	
-	if (pos == size) {
-		(void) async_data_read_finalize(callid, buf, size);
-		async_answer_1(rid, EOK, size);
-		free(buf);
-	} else {
-		fibril_condvar_wait(&input_cv, &input_mutex);
-		goto recheck;
-	}
-	
-	fibril_mutex_unlock(&input_mutex);
-}
-
-static void cons_get_event(console_t *cons, ipc_callid_t rid, ipc_call_t *request)
-{
-	kbd_event_t ev;
-	
-	fibril_mutex_lock(&input_mutex);
-	
-recheck:
-	if (keybuffer_pop(&cons->keybuffer, &ev)) {
-		async_answer_4(rid, EOK, ev.type, ev.key, ev.mods, ev.c);
-	} else {
-		fibril_condvar_wait(&input_cv, &input_mutex);
-		goto recheck;
-	}
-	
-	fibril_mutex_unlock(&input_mutex);
-}
-
-/** Default thread for new connections */
+		
+		free(event);
+	}
+	
+	(void) async_data_read_finalize(callid, buf, size);
+	async_answer_1(iid, EOK, size);
+	free(buf);
+}
+
+static void cons_set_style(console_t *cons, console_style_t style)
+{
+	fibril_mutex_lock(&cons->mtx);
+	screenbuffer_set_style(cons->frontbuf, style);
+	fibril_mutex_unlock(&cons->mtx);
+}
+
+static void cons_set_color(console_t *cons, console_color_t bgcolor,
+    console_color_t fgcolor, console_color_attr_t attr)
+{
+	fibril_mutex_lock(&cons->mtx);
+	screenbuffer_set_color(cons->frontbuf, bgcolor, fgcolor, attr);
+	fibril_mutex_unlock(&cons->mtx);
+}
+
+static void cons_set_rgb_color(console_t *cons, pixel_t bgcolor,
+    pixel_t fgcolor)
+{
+	fibril_mutex_lock(&cons->mtx);
+	screenbuffer_set_rgb_color(cons->frontbuf, bgcolor, fgcolor);
+	fibril_mutex_unlock(&cons->mtx);
+}
+
+static void cons_get_event(console_t *cons, ipc_callid_t iid, ipc_call_t *icall)
+{
+	link_t *link = prodcons_consume(&cons->input_pc);
+	kbd_event_t *event = list_get_instance(link, kbd_event_t, link);
+	
+	async_answer_4(iid, EOK, event->type, event->key, event->mods, event->c);
+	free(event);
+}
+
 static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	console_t *cons = NULL;
 	
-	size_t i;
-	for (i = 0; i < CONSOLE_COUNT; i++) {
+	for (size_t i = 0; i < CONSOLE_COUNT; i++) {
 		if (i == KERNEL_CONSOLE)
 			continue;
 		
-		if (consoles[i].service_id == (service_id_t) IPC_GET_ARG1(*icall)) {
+		if (consoles[i].dsid == (service_id_t) IPC_GET_ARG1(*icall)) {
 			cons = &consoles[i];
 			break;
@@ -593,17 +656,8 @@
 	}
 	
-	ipc_callid_t callid;
-	ipc_call_t call;
-	sysarg_t arg1;
-	sysarg_t arg2;
-	sysarg_t arg3;
-	
-	int rc;
-	
-	console_serialize_start();
-	if (cons->refcount == 0)
-		gcons_notify_connect(cons->index);
-	
-	cons->refcount++;
+	if (atomic_postinc(&cons->refcnt) == 0) {
+		cons_set_cursor_visibility(cons, true);
+		cons_notify_connect(cons);
+	}
 	
 	/* Accept the connection */
@@ -611,17 +665,11 @@
 	
 	while (true) {
-		console_serialize_end();
-		callid = async_get_call(&call);
-		console_serialize_start();
-		
-		arg1 = 0;
-		arg2 = 0;
-		arg3 = 0;
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
 		
 		if (!IPC_GET_IMETHOD(call)) {
-			cons->refcount--;
-			if (cons->refcount == 0)
-				gcons_notify_disconnect(cons->index);
-			console_serialize_end();
+			if (atomic_postdec(&cons->refcnt) == 1)
+				cons_notify_disconnect(cons);
+			
 			return;
 		}
@@ -629,128 +677,80 @@
 		switch (IPC_GET_IMETHOD(call)) {
 		case VFS_OUT_READ:
-			console_serialize_end();
 			cons_read(cons, callid, &call);
-			console_serialize_start();
-			continue;
+			break;
 		case VFS_OUT_WRITE:
-			console_serialize_end();
 			cons_write(cons, callid, &call);
-			console_serialize_start();
-			continue;
+			break;
 		case VFS_OUT_SYNC:
-			fb_pending_flush();
-			if (cons == active_console) {
-				async_obsolete_req_0_0(fb_info.phone, FB_FLUSH);
-				curs_goto(cons->scr.position_x, cons->scr.position_y);
-			}
+			cons_update(cons);
+			async_answer_0(callid, EOK);
 			break;
 		case CONSOLE_CLEAR:
-			/* Send message to fb */
-			if (cons == active_console)
-				async_obsolete_msg_0(fb_info.phone, FB_CLEAR);
-			
-			screenbuffer_clear(&cons->scr);
-			
+			cons_clear(cons);
+			async_answer_0(callid, EOK);
 			break;
 		case CONSOLE_GOTO:
-			screenbuffer_goto(&cons->scr,
-			    IPC_GET_ARG1(call), IPC_GET_ARG2(call));
-			if (cons == active_console)
-				curs_goto(IPC_GET_ARG1(call),
-				    IPC_GET_ARG2(call));
+			cons_set_cursor(cons, IPC_GET_ARG1(call), IPC_GET_ARG2(call));
+			async_answer_0(callid, EOK);
 			break;
 		case CONSOLE_GET_POS:
-			arg1 = cons->scr.position_x;
-			arg2 = cons->scr.position_y;
+			cons_get_cursor(cons, callid, &call);
 			break;
 		case CONSOLE_GET_SIZE:
-			arg1 = fb_info.cols;
-			arg2 = fb_info.rows;
+			async_answer_2(callid, EOK, cons->cols, cons->rows);
 			break;
 		case CONSOLE_GET_COLOR_CAP:
-			rc = ccap_fb_to_con(fb_info.color_cap, &arg1);
-			if (rc != EOK) {
-				async_answer_0(callid, rc);
-				continue;
-			}
+			async_answer_1(callid, EOK, cons->ccaps);
 			break;
 		case CONSOLE_SET_STYLE:
-			fb_pending_flush();
-			arg1 = IPC_GET_ARG1(call);
-			screenbuffer_set_style(&cons->scr, arg1);
-			if (cons == active_console)
-				set_style(arg1);
+			cons_set_style(cons, IPC_GET_ARG1(call));
+			async_answer_0(callid, EOK);
 			break;
 		case CONSOLE_SET_COLOR:
-			fb_pending_flush();
-			arg1 = IPC_GET_ARG1(call);
-			arg2 = IPC_GET_ARG2(call);
-			arg3 = IPC_GET_ARG3(call);
-			screenbuffer_set_color(&cons->scr, arg1, arg2, arg3);
-			if (cons == active_console)
-				set_color(arg1, arg2, arg3);
+			cons_set_color(cons, IPC_GET_ARG1(call), IPC_GET_ARG2(call),
+			    IPC_GET_ARG3(call));
+			async_answer_0(callid, EOK);
 			break;
 		case CONSOLE_SET_RGB_COLOR:
-			fb_pending_flush();
-			arg1 = IPC_GET_ARG1(call);
-			arg2 = IPC_GET_ARG2(call);
-			screenbuffer_set_rgb_color(&cons->scr, arg1, arg2);
-			if (cons == active_console)
-				set_rgb_color(arg1, arg2);
+			cons_set_rgb_color(cons, IPC_GET_ARG1(call), IPC_GET_ARG2(call));
+			async_answer_0(callid, EOK);
 			break;
 		case CONSOLE_CURSOR_VISIBILITY:
-			fb_pending_flush();
-			arg1 = IPC_GET_ARG1(call);
-			cons->scr.is_cursor_visible = arg1;
-			if (cons == active_console)
-				curs_visibility(arg1);
+			cons_set_cursor_visibility(cons, IPC_GET_ARG1(call));
+			async_answer_0(callid, EOK);
 			break;
 		case CONSOLE_GET_EVENT:
-			console_serialize_end();
 			cons_get_event(cons, callid, &call);
-			console_serialize_start();
-			continue;
-		}
-		async_answer_3(callid, EOK, arg1, arg2, arg3);
-	}
-}
-
-static void interrupt_received(ipc_callid_t callid, ipc_call_t *call)
-{
-	change_console(prev_console);
-}
-
-static async_sess_t *connect_input(const char *svc_path)
+			break;
+		default:
+			async_answer_0(callid, EINVAL);
+		}
+	}
+}
+
+static async_sess_t *input_connect(const char *svc)
 {
 	async_sess_t *sess;
-	async_exch_t *exch;
-	service_id_t service_id;
-	
-	int rc = loc_service_get_id(svc_path, &service_id, 0);
+	service_id_t dsid;
+	
+	int rc = loc_service_get_id(svc, &dsid, 0);
 	if (rc == EOK) {
-		sess = loc_service_connect(EXCHANGE_ATOMIC, service_id, 0);
+		sess = loc_service_connect(EXCHANGE_ATOMIC, dsid, 0);
 		if (sess == NULL) {
-			printf("%s: Failed to connect to input server\n", NAME);
+			printf("%s: Unable to connect to input service %s\n", NAME,
+			    svc);
 			return NULL;
 		}
-	} else {
+	} else
 		return NULL;
-	}
-	
-	exch = async_exchange_begin(sess);
-	if (exch == NULL) {
-		printf("%s: Failed to create callback from input server.\n", NAME);
-		return NULL;
-	}
-	
-	/* NB: The callback connection is slotted for removal */
+	
+	async_exch_t *exch = async_exchange_begin(sess);
 	rc = async_connect_to_me(exch, 0, 0, 0, input_events, NULL);
-
 	async_exchange_end(exch);
-
+	
 	if (rc != EOK) {
 		async_hangup(sess);
-		printf("%s: Failed to create callback from input server (%s).\n",
-		    NAME, str_error(rc));
+		printf("%s: Unable to create callback connection to service %s (%s)\n",
+		    NAME, svc, str_error(rc));
 		return NULL;
 	}
@@ -759,88 +759,202 @@
 }
 
-static bool console_srv_init(char *input_dev)
-{
-	/* Connect to input server */
-	input_sess = connect_input(input_dev);
+static void interrupt_received(ipc_callid_t callid, ipc_call_t *call)
+{
+	cons_switch(prev_console);
+}
+
+static async_sess_t *fb_connect(const char *svc)
+{
+	async_sess_t *sess;
+	service_id_t dsid;
+	
+	int rc = loc_service_get_id(svc, &dsid, 0);
+	if (rc == EOK) {
+		sess = loc_service_connect(EXCHANGE_SERIALIZE, dsid, 0);
+		if (sess == NULL) {
+			printf("%s: Unable to connect to framebuffer service %s\n",
+			    NAME, svc);
+			return NULL;
+		}
+	} else
+		return NULL;
+	
+	return sess;
+}
+
+static bool console_srv_init(char *input_svc, char *fb_svc)
+{
+	/* Avoid double initialization */
+	if (graphics_state != GRAPHICS_NONE)
+		return false;
+	
+	/* Connect to input service */
+	input_sess = input_connect(input_svc);
 	if (input_sess == NULL)
 		return false;
 	
-	/* Connect to framebuffer driver */
-	fb_info.phone = service_obsolete_connect_blocking(SERVICE_VIDEO, 0, 0);
-	if (fb_info.phone < 0) {
-		printf("%s: Failed to connect to video service\n", NAME);
+	/* Connect to framebuffer service */
+	fb_sess = fb_connect(fb_svc);
+	if (fb_sess == NULL)
 		return false;
-	}
 	
 	/* Register server */
 	int rc = loc_server_register(NAME, client_connection);
 	if (rc < 0) {
-		printf("%s: Unable to register server (%d)\n", NAME, rc);
+		printf("%s: Unable to register server (%s)\n", NAME,
+		    str_error(rc));
 		return false;
 	}
 	
-	/* Initialize gcons */
-	gcons_init(fb_info.phone);
-	
-	/* Synchronize, the gcons could put something in queue */
-	async_obsolete_req_0_0(fb_info.phone, FB_FLUSH);
-	async_obsolete_req_0_2(fb_info.phone, FB_GET_CSIZE, &fb_info.cols, &fb_info.rows);
-	async_obsolete_req_0_1(fb_info.phone, FB_GET_COLOR_CAP, &fb_info.color_cap);
-	
-	/* Set up shared memory buffer. */
-	size_t ib_size = sizeof(keyfield_t) * fb_info.cols * fb_info.rows;
-	interbuffer = as_get_mappable_page(ib_size);
-	
-	if (as_area_create(interbuffer, ib_size, AS_AREA_READ |
-	    AS_AREA_WRITE | AS_AREA_CACHEABLE) != interbuffer)
-		interbuffer = NULL;
-	
-	if (interbuffer) {
-		if (async_obsolete_share_out_start(fb_info.phone, interbuffer,
-		    AS_AREA_READ) != EOK) {
-			as_area_destroy(interbuffer);
-			interbuffer = NULL;
-		}
-	}
-	
-	fb_pending.cnt = 0;
+	fb_get_resolution(fb_sess, &xres, &yres);
+	
+	/* Initialize the screen */
+	screen_vp = fb_vp_create(fb_sess, 0, 0, xres, yres);
+	
+	if ((xres >= 800) && (yres >= 600)) {
+		logo_vp = fb_vp_create(fb_sess, xres - 66, 2, 64, 60);
+		logo_img = imgmap_decode_tga((void *) helenos_tga,
+		    helenos_tga_size, IMGMAP_FLAG_SHARED);
+		logo_handle = fb_imagemap_create(fb_sess, logo_img);
+		
+		nameic_vp = fb_vp_create(fb_sess, 5, 17, 100, 26);
+		nameic_img = imgmap_decode_tga((void *) nameic_tga,
+		    nameic_tga_size, IMGMAP_FLAG_SHARED);
+		nameic_handle = fb_imagemap_create(fb_sess, nameic_img);
+		
+		cons_data_img = imgmap_decode_tga((void *) cons_data_tga,
+		    cons_data_tga_size, IMGMAP_FLAG_SHARED);
+		cons_dis_img = imgmap_decode_tga((void *) cons_dis_tga,
+		    cons_dis_tga_size, IMGMAP_FLAG_SHARED);
+		cons_dis_sel_img = imgmap_decode_tga((void *) cons_dis_sel_tga,
+		    cons_dis_sel_tga_size, IMGMAP_FLAG_SHARED);
+		cons_idle_img = imgmap_decode_tga((void *) cons_idle_tga,
+		    cons_idle_tga_size, IMGMAP_FLAG_SHARED);
+		cons_kernel_img = imgmap_decode_tga((void *) cons_kernel_tga,
+		    cons_kernel_tga_size, IMGMAP_FLAG_SHARED);
+		cons_sel_img = imgmap_decode_tga((void *) cons_sel_tga,
+		    cons_sel_tga_size, IMGMAP_FLAG_SHARED);
+		
+		state_icons[CONS_DISCONNECTED] =
+		    fb_imagemap_create(fb_sess, cons_dis_img);
+		state_icons[CONS_DISCONNECTED_SELECTED] =
+		    fb_imagemap_create(fb_sess, cons_dis_sel_img);
+		state_icons[CONS_SELECTED] =
+		    fb_imagemap_create(fb_sess, cons_sel_img);
+		state_icons[CONS_IDLE] =
+		    fb_imagemap_create(fb_sess, cons_idle_img);
+		state_icons[CONS_DATA] =
+		    fb_imagemap_create(fb_sess, cons_data_img);
+		state_icons[CONS_KERNEL] =
+		    fb_imagemap_create(fb_sess, cons_kernel_img);
+		
+		anim_1_img = imgmap_decode_tga((void *) anim_1_tga,
+		    anim_1_tga_size, IMGMAP_FLAG_SHARED);
+		anim_2_img = imgmap_decode_tga((void *) anim_2_tga,
+		    anim_2_tga_size, IMGMAP_FLAG_SHARED);
+		anim_3_img = imgmap_decode_tga((void *) anim_3_tga,
+		    anim_3_tga_size, IMGMAP_FLAG_SHARED);
+		anim_4_img = imgmap_decode_tga((void *) anim_4_tga,
+		    anim_4_tga_size, IMGMAP_FLAG_SHARED);
+		
+		anim_1 = fb_imagemap_create(fb_sess, anim_1_img);
+		anim_2 = fb_imagemap_create(fb_sess, anim_2_img);
+		anim_3 = fb_imagemap_create(fb_sess, anim_3_img);
+		anim_4 = fb_imagemap_create(fb_sess, anim_4_img);
+		
+		anim_seq = fb_sequence_create(fb_sess);
+		fb_sequence_add_imagemap(fb_sess, anim_seq, anim_1);
+		fb_sequence_add_imagemap(fb_sess, anim_seq, anim_2);
+		fb_sequence_add_imagemap(fb_sess, anim_seq, anim_3);
+		fb_sequence_add_imagemap(fb_sess, anim_seq, anim_4);
+		
+		console_vp = fb_vp_create(fb_sess, CONSOLE_MARGIN, CONSOLE_TOP,
+		    xres - 2 * CONSOLE_MARGIN, yres - (CONSOLE_TOP + CONSOLE_MARGIN));
+		
+		fb_vp_clear(fb_sess, screen_vp);
+		fb_vp_imagemap_damage(fb_sess, logo_vp, logo_handle,
+		    0, 0, 64, 60);
+		fb_vp_imagemap_damage(fb_sess, nameic_vp, nameic_handle,
+		    0, 0, 100, 26);
+		
+		graphics_state = GRAPHICS_FULL;
+	} else {
+		console_vp = screen_vp;
+		graphics_state = GRAPHICS_BASIC;
+	}
+	
+	fb_vp_set_style(fb_sess, console_vp, STYLE_NORMAL);
+	fb_vp_clear(fb_sess, console_vp);
+	
+	sysarg_t cols;
+	sysarg_t rows;
+	fb_vp_get_dimensions(fb_sess, console_vp, &cols, &rows);
+	
+	console_caps_t ccaps;
+	fb_vp_get_caps(fb_sess, console_vp, &ccaps);
+	
+	mouse.pressed = false;
 	
 	/* Inititalize consoles */
-	size_t i;
-	for (i = 0; i < CONSOLE_COUNT; i++) {
-		if (i != KERNEL_CONSOLE) {
-			if (screenbuffer_init(&consoles[i].scr,
-			    fb_info.cols, fb_info.rows) == NULL) {
-				printf("%s: Unable to allocate screen buffer %zu\n", NAME, i);
-				return false;
-			}
-			screenbuffer_clear(&consoles[i].scr);
-			keybuffer_init(&consoles[i].keybuffer);
-			consoles[i].index = i;
-			consoles[i].refcount = 0;
-			
-			char vc[LOC_NAME_MAXLEN + 1];
-			snprintf(vc, LOC_NAME_MAXLEN, "%s/vc%zu", NAMESPACE, i);
-			
-			if (loc_service_register(vc, &consoles[i].service_id) != EOK) {
-				printf("%s: Unable to register service %s\n", NAME, vc);
-				return false;
-			}
-		}
-	}
-	
-	/* Initialize the screen */
-	console_serialize_start();
-	gcons_redraw_console();
-	set_style(STYLE_NORMAL);
-	screen_clear();
-	curs_goto(0, 0);
-	curs_visibility(active_console->scr.is_cursor_visible);
-	console_serialize_end();
+	for (size_t i = 0; i < CONSOLE_COUNT; i++) {
+		consoles[i].index = i;
+		atomic_set(&consoles[i].refcnt, 0);
+		fibril_mutex_initialize(&consoles[i].mtx);
+		
+		if (graphics_state == GRAPHICS_FULL) {
+			/* Create state buttons */
+			consoles[i].state_vp =
+			    fb_vp_create(fb_sess, STATE_START + (xres - 800) / 2 +
+			    CONSOLE_MARGIN + i * (STATE_WIDTH + STATE_SPACE),
+			    STATE_TOP, STATE_WIDTH, STATE_HEIGHT);
+		}
+		
+		if (i == KERNEL_CONSOLE) {
+			consoles[i].state = CONS_KERNEL;
+			cons_redraw_state(&consoles[i]);
+			cons_kernel_sequence_start(&consoles[i]);
+			continue;
+		}
+		
+		if (i == 0)
+			consoles[i].state = CONS_DISCONNECTED_SELECTED;
+		else
+			consoles[i].state = CONS_DISCONNECTED;
+		
+		consoles[i].cols = cols;
+		consoles[i].rows = rows;
+		consoles[i].ccaps = ccaps;
+		consoles[i].frontbuf =
+		    screenbuffer_create(cols, rows, SCREENBUFFER_FLAG_SHARED);
+		
+		if (consoles[i].frontbuf == NULL) {
+			printf("%s: Unable to allocate frontbuffer %zu\n", NAME, i);
+			return false;
+		}
+		
+		consoles[i].fbid = fb_frontbuf_create(fb_sess, consoles[i].frontbuf);
+		if (consoles[i].fbid == 0) {
+			printf("%s: Unable to create frontbuffer %zu\n", NAME, i);
+			return false;
+		}
+		
+		prodcons_initialize(&consoles[i].input_pc);
+		cons_redraw_state(&consoles[i]);
+		
+		char vc[LOC_NAME_MAXLEN + 1];
+		snprintf(vc, LOC_NAME_MAXLEN, "%s/vc%zu", NAMESPACE, i);
+		
+		if (loc_service_register(vc, &consoles[i].dsid) != EOK) {
+			printf("%s: Unable to register device %s\n", NAME, vc);
+			return false;
+		}
+	}
 	
 	/* Receive kernel notifications */
 	async_set_interrupt_received(interrupt_received);
-	if (event_subscribe(EVENT_KCONSOLE, 0) != EOK)
-		printf("%s: Error registering kconsole notifications\n", NAME);
+	rc = event_subscribe(EVENT_KCONSOLE, 0);
+	if (rc != EOK)
+		printf("%s: Failed to register kconsole notifications (%s)\n",
+		    NAME, str_error(rc));
 	
 	return true;
@@ -849,20 +963,21 @@
 static void usage(void)
 {
-	printf("Usage: console <input_dev>\n");
+	printf("Usage: console <input_dev> <framebuffer_dev>\n");
 }
 
 int main(int argc, char *argv[])
 {
-	if (argc < 2) {
+	if (argc < 3) {
 		usage();
 		return -1;
 	}
 	
-	printf(NAME ": HelenOS Console service\n");
-	
-	if (!console_srv_init(argv[1]))
+	printf("%s: HelenOS Console service\n", NAME);
+	
+	if (!console_srv_init(argv[1], argv[2]))
 		return -1;
 	
-	printf(NAME ": Accepting connections\n");
+	printf("%s: Accepting connections\n", NAME);
+	task_retval(0);
 	async_manager();
 	
Index: uspace/srv/hid/console/console.h
===================================================================
--- uspace/srv/hid/console/console.h	(revision 16dc8870242df10ae64ee7bcbf125aa8607cb7fb)
+++ uspace/srv/hid/console/console.h	(revision 7c014d1fbbe9734e6ee3616fac584d8cc996df36)
@@ -33,6 +33,6 @@
  */
 
-#ifndef __CONSOLE_H__
-#define __CONSOLE_H__
+#ifndef CONSOLE_CONSOLE_H__
+#define CONSOLE_CONSOLE_H__
 
 #define CONSOLE_COUNT   12
Index: uspace/srv/hid/console/gcons.c
===================================================================
--- uspace/srv/hid/console/gcons.c	(revision 16dc8870242df10ae64ee7bcbf125aa8607cb7fb)
+++ 	(revision )
@@ -1,564 +1,0 @@
-/*
- * Copyright (c) 2006 Ondrej Palkovsky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup console
- * @{
- */
-/** @file
- */
-
-#include <ipc/fb.h>
-#include <async.h>
-#include <async_obsolete.h>
-#include <stdio.h>
-#include <sys/mman.h>
-#include <str.h>
-#include <align.h>
-#include <bool.h>
-#include <imgmap.h>
-
-#include "console.h"
-#include "gcons.h"
-#include "images.h"
-
-#define CONSOLE_TOP     66
-#define CONSOLE_MARGIN  6
-
-#define STATUS_START   110
-#define STATUS_TOP     8
-#define STATUS_SPACE   4
-#define STATUS_WIDTH   48
-#define STATUS_HEIGHT  48
-
-#define COLOR_MAIN        0xffffff
-#define COLOR_FOREGROUND  0x202020
-#define COLOR_BACKGROUND  0xffffff
-
-static bool use_gcons = false;
-static sysarg_t xres;
-static sysarg_t yres;
-
-static imgmap_t *helenos_img;
-static imgmap_t *nameic_img;
-
-static imgmap_t *anim_1_img;
-static imgmap_t *anim_2_img;
-static imgmap_t *anim_3_img;
-static imgmap_t *anim_4_img;
-
-static imgmap_t *cons_has_data_img;
-static imgmap_t *cons_idle_img;
-static imgmap_t *cons_kernel_img;
-static imgmap_t *cons_selected_img;
-
-enum butstate {
-	CONS_DISCONNECTED = 0,
-	CONS_SELECTED,
-	CONS_IDLE,
-	CONS_HAS_DATA,
-	CONS_KERNEL,
-	CONS_DISCONNECTED_SEL,
-	CONS_LAST
-};
-
-static int console_vp;
-static int cstatus_vp[CONSOLE_COUNT];
-static enum butstate console_state[CONSOLE_COUNT];
-
-static int fbphone;
-
-/** List of image maps identifying these icons */
-static int ic_imgmaps[CONS_LAST] = {-1, -1, -1, -1, -1, -1};
-static int animation = -1;
-
-static size_t active_console = 0;
-
-static sysarg_t mouse_x = 0;
-static sysarg_t mouse_y= 0;
-
-static bool btn_pressed = false;
-static sysarg_t btn_x = 0;
-static sysarg_t btn_y = 0;
-
-static void vp_switch(int vp)
-{
-	async_obsolete_msg_1(fbphone, FB_VIEWPORT_SWITCH, vp);
-}
-
-/** Create view port */
-static int vp_create(sysarg_t x, sysarg_t y, sysarg_t width, sysarg_t height)
-{
-	return async_obsolete_req_2_0(fbphone, FB_VIEWPORT_CREATE, (x << 16) | y,
-	    (width << 16) | height);
-}
-
-static void clear(void)
-{
-	async_obsolete_msg_0(fbphone, FB_CLEAR);
-}
-
-static void set_rgb_color(uint32_t fgcolor, uint32_t bgcolor)
-{
-	async_obsolete_msg_2(fbphone, FB_SET_RGB_COLOR, fgcolor, bgcolor);
-}
-
-/** Transparent putchar */
-static void tran_putch(wchar_t ch, sysarg_t col, sysarg_t row)
-{
-	async_obsolete_msg_3(fbphone, FB_PUTCHAR, ch, col, row);
-}
-
-/** Redraw the button showing state of a given console */
-static void redraw_state(size_t index)
-{
-	vp_switch(cstatus_vp[index]);
-	
-	enum butstate state = console_state[index];
-	
-	if (ic_imgmaps[state] != -1)
-		async_obsolete_msg_2(fbphone, FB_VP_DRAW_IMGMAP, cstatus_vp[index],
-		    ic_imgmaps[state]);
-	
-	if ((state != CONS_DISCONNECTED) && (state != CONS_KERNEL)
-	    && (state != CONS_DISCONNECTED_SEL)) {
-		
-		char data[5];
-		snprintf(data, 5, "%zu", index + 1);
-		
-		size_t i;
-		for (i = 0; data[i] != 0; i++)
-			tran_putch(data[i], 2 + i, 1);
-	}
-}
-
-/** Notification run on changing console (except kernel console) */
-void gcons_change_console(size_t index)
-{
-	if (!use_gcons) {
-		active_console = index;
-		return;
-	}
-	
-	if (active_console == KERNEL_CONSOLE) {
-		size_t i;
-		
-		for (i = 0; i < CONSOLE_COUNT; i++)
-			redraw_state(i);
-		
-		if (animation != -1)
-			async_obsolete_msg_1(fbphone, FB_ANIM_START, animation);
-	} else {
-		if (console_state[active_console] == CONS_DISCONNECTED_SEL)
-			console_state[active_console] = CONS_DISCONNECTED;
-		else
-			console_state[active_console] = CONS_IDLE;
-		
-		redraw_state(active_console);
-	}
-	
-	active_console = index;
-	
-	if ((console_state[index] == CONS_DISCONNECTED)
-	    || (console_state[index] == CONS_DISCONNECTED_SEL))
-		console_state[index] = CONS_DISCONNECTED_SEL;
-	else
-		console_state[index] = CONS_SELECTED;
-	
-	redraw_state(index);
-	vp_switch(console_vp);
-}
-
-/** Notification function that gets called on new output to virtual console */
-void gcons_notify_char(size_t index)
-{
-	if (!use_gcons)
-		return;
-	
-	if ((index == active_console)
-	    || (console_state[index] == CONS_HAS_DATA))
-		return;
-	
-	console_state[index] = CONS_HAS_DATA;
-	
-	if (active_console == KERNEL_CONSOLE)
-		return;
-	
-	redraw_state(index);
-	vp_switch(console_vp);
-}
-
-/** Notification function called on service disconnect from console */
-void gcons_notify_disconnect(size_t index)
-{
-	if (!use_gcons)
-		return;
-	
-	if (index == active_console)
-		console_state[index] = CONS_DISCONNECTED_SEL;
-	else
-		console_state[index] = CONS_DISCONNECTED;
-	
-	if (active_console == KERNEL_CONSOLE)
-		return;
-	
-	redraw_state(index);
-	vp_switch(console_vp);
-}
-
-/** Notification function called on console connect */
-void gcons_notify_connect(size_t index)
-{
-	if (!use_gcons)
-		return;
-	
-	if (index == active_console)
-		console_state[index] = CONS_SELECTED;
-	else
-		console_state[index] = CONS_IDLE;
-	
-	if (active_console == KERNEL_CONSOLE)
-		return;
-	
-	redraw_state(index);
-	vp_switch(console_vp);
-}
-
-/** Change to kernel console */
-void gcons_in_kernel(void)
-{
-	if (animation != -1)
-		async_obsolete_msg_1(fbphone, FB_ANIM_STOP, animation);
-	
-	active_console = KERNEL_CONSOLE;
-	vp_switch(0);
-}
-
-/** Return x, where left <= x <= right && |a-x| == min(|a-x|) is smallest */
-static inline ssize_t limit(ssize_t a, ssize_t left, ssize_t right)
-{
-	if (a < left)
-		a = left;
-	
-	if (a >= right)
-		a = right - 1;
-	
-	return a;
-}
-
-/** Handle mouse move
- *
- * @param dx Delta X of mouse move
- * @param dy Delta Y of mouse move
- */
-void gcons_mouse_move(ssize_t dx, ssize_t dy)
-{
-	ssize_t nx = (ssize_t) mouse_x + dx;
-	ssize_t ny = (ssize_t) mouse_y + dy;
-	
-	/* Until gcons is initalized we don't have the screen resolution */
-	if (xres == 0 || yres == 0)
-		return;
-	
-	mouse_x = (size_t) limit(nx, 0, xres);
-	mouse_y = (size_t) limit(ny, 0, yres);
-	
-	if (active_console != KERNEL_CONSOLE)
-		async_obsolete_msg_2(fbphone, FB_POINTER_MOVE, mouse_x, mouse_y);
-}
-
-static int gcons_find_conbut(sysarg_t x, sysarg_t y)
-{
-	sysarg_t status_start = STATUS_START + (xres - 800) / 2;
-	
-	if ((y < STATUS_TOP) || (y >= STATUS_TOP + STATUS_HEIGHT))
-		return -1;
-	
-	if (x < status_start)
-		return -1;
-	
-	if (x >= status_start + (STATUS_WIDTH + STATUS_SPACE) * CONSOLE_COUNT)
-		return -1;
-	
-	if (((x - status_start) % (STATUS_WIDTH + STATUS_SPACE)) < STATUS_SPACE)
-		return -1;
-	
-	sysarg_t btn = (x - status_start) / (STATUS_WIDTH + STATUS_SPACE);
-	
-	if (btn < CONSOLE_COUNT)
-		return btn;
-	
-	return -1;
-}
-
-/** Handle mouse click
- *
- * @param state New state (true - pressed, false - depressed)
- *
- */
-int gcons_mouse_btn(bool state)
-{
-	/* Ignore mouse clicks if no buttons
-	   are drawn at all */
-	if (xres < 800)
-		return -1;
-	
-	if (state) {
-		int conbut = gcons_find_conbut(mouse_x, mouse_y);
-		if (conbut != -1) {
-			btn_pressed = true;
-			btn_x = mouse_x;
-			btn_y = mouse_y;
-		}
-		return -1;
-	}
-	
-	if ((!state) && (!btn_pressed))
-		return -1;
-	
-	btn_pressed = false;
-	
-	int conbut = gcons_find_conbut(mouse_x, mouse_y);
-	if (conbut == gcons_find_conbut(btn_x, btn_y))
-		return conbut;
-	
-	return -1;
-}
-
-/** Draw an image map to framebuffer
- *
- * @param img  Image map
- * @param x    Coordinate of upper left corner
- * @param y    Coordinate of upper left corner
- *
- */
-static void draw_imgmap(imgmap_t *img, sysarg_t x, sysarg_t y)
-{
-	if (img == NULL)
-		return;
-	
-	/* Create area */
-	char *shm = mmap(NULL, img->size, PROTO_READ | PROTO_WRITE, MAP_SHARED |
-	    MAP_ANONYMOUS, 0, 0);
-	if (shm == MAP_FAILED)
-		return;
-	
-	memcpy(shm, img, img->size);
-	
-	/* Send area */
-	int rc = async_obsolete_req_1_0(fbphone, FB_PREPARE_SHM, (sysarg_t) shm);
-	if (rc)
-		goto exit;
-	
-	rc = async_obsolete_share_out_start(fbphone, shm, PROTO_READ);
-	if (rc)
-		goto drop;
-	
-	/* Draw logo */
-	async_obsolete_msg_2(fbphone, FB_DRAW_IMGMAP, x, y);
-	
-drop:
-	/* Drop area */
-	async_obsolete_msg_0(fbphone, FB_DROP_SHM);
-	
-exit:
-	/* Remove area */
-	munmap(shm, img->size);
-}
-
-/** Redraws console graphics */
-void gcons_redraw_console(void)
-{
-	if (!use_gcons)
-		return;
-	
-	vp_switch(0);
-	set_rgb_color(COLOR_MAIN, COLOR_MAIN);
-	clear();
-	draw_imgmap(helenos_img, xres - 66, 2);
-	draw_imgmap(nameic_img, 5, 17);
-	
-	unsigned int i;
-	for (i = 0; i < CONSOLE_COUNT; i++)
-		redraw_state(i);
-	
-	vp_switch(console_vp);
-}
-
-/** Create an image map on framebuffer
- *
- * @param img Image map.
- *
- * @return Image map identification
- *
- */
-static int make_imgmap(imgmap_t *img)
-{
-	if (img == NULL)
-		return -1;
-	
-	/* Create area */
-	char *shm = mmap(NULL, img->size, PROTO_READ | PROTO_WRITE,
-	    MAP_SHARED | MAP_ANONYMOUS, 0, 0);
-	if (shm == MAP_FAILED)
-		return -1;
-	
-	memcpy(shm, img, img->size);
-	
-	int id = -1;
-	
-	/* Send area */
-	int rc = async_obsolete_req_1_0(fbphone, FB_PREPARE_SHM, (sysarg_t) shm);
-	if (rc)
-		goto exit;
-	
-	rc = async_obsolete_share_out_start(fbphone, shm, PROTO_READ);
-	if (rc)
-		goto drop;
-	
-	/* Obtain image map identifier */
-	rc = async_obsolete_req_0_0(fbphone, FB_SHM2IMGMAP);
-	if (rc < 0)
-		goto drop;
-	
-	id = rc;
-	
-drop:
-	/* Drop area */
-	async_obsolete_msg_0(fbphone, FB_DROP_SHM);
-	
-exit:
-	/* Remove area */
-	munmap(shm, img->size);
-	
-	return id;
-}
-
-static void make_anim(void)
-{
-	int an = async_obsolete_req_1_0(fbphone, FB_ANIM_CREATE,
-	    cstatus_vp[KERNEL_CONSOLE]);
-	if (an < 0)
-		return;
-	
-	int pm = make_imgmap(anim_1_img);
-	async_obsolete_msg_2(fbphone, FB_ANIM_ADDIMGMAP, an, pm);
-	
-	pm = make_imgmap(anim_2_img);
-	async_obsolete_msg_2(fbphone, FB_ANIM_ADDIMGMAP, an, pm);
-	
-	pm = make_imgmap(anim_3_img);
-	async_obsolete_msg_2(fbphone, FB_ANIM_ADDIMGMAP, an, pm);
-	
-	pm = make_imgmap(anim_4_img);
-	async_obsolete_msg_2(fbphone, FB_ANIM_ADDIMGMAP, an, pm);
-	
-	async_obsolete_msg_1(fbphone, FB_ANIM_START, an);
-	
-	animation = an;
-}
-
-/** Initialize nice graphical console environment */
-void gcons_init(int phone)
-{
-	fbphone = phone;
-	
-	int rc = async_obsolete_req_0_2(phone, FB_GET_RESOLUTION, &xres, &yres);
-	if (rc)
-		return;
-	
-	if ((xres < 800) || (yres < 600))
-		return;
-	
-	/* Create image maps */
-	helenos_img = imgmap_decode_tga((void *) helenos_tga,
-	    helenos_tga_size);
-	nameic_img = imgmap_decode_tga((void *) nameic_tga,
-	    nameic_tga_size);
-	
-	anim_1_img = imgmap_decode_tga((void *) anim_1_tga,
-	    anim_1_tga_size);
-	anim_2_img = imgmap_decode_tga((void *) anim_2_tga,
-	    anim_2_tga_size);
-	anim_3_img = imgmap_decode_tga((void *) anim_3_tga,
-	    anim_3_tga_size);
-	anim_4_img = imgmap_decode_tga((void *) anim_4_tga,
-	    anim_4_tga_size);
-	
-	cons_has_data_img = imgmap_decode_tga((void *) cons_has_data_tga,
-	    cons_has_data_tga_size);
-	cons_idle_img = imgmap_decode_tga((void *) cons_idle_tga,
-	    cons_idle_tga_size);
-	cons_kernel_img = imgmap_decode_tga((void *) cons_kernel_tga,
-	    cons_kernel_tga_size);
-	cons_selected_img = imgmap_decode_tga((void *) cons_selected_tga,
-	    cons_selected_tga_size);
-	
-	/* Create console viewport */
-	
-	/* Align width & height to character size */
-	console_vp = vp_create(CONSOLE_MARGIN, CONSOLE_TOP,
-	    ALIGN_DOWN(xres - 2 * CONSOLE_MARGIN, 8),
-	    ALIGN_DOWN(yres - (CONSOLE_TOP + CONSOLE_MARGIN), 16));
-	
-	if (console_vp < 0)
-		return;
-	
-	/* Create status buttons */
-	sysarg_t status_start = STATUS_START + (xres - 800) / 2;
-	size_t i;
-	for (i = 0; i < CONSOLE_COUNT; i++) {
-		cstatus_vp[i] = vp_create(status_start + CONSOLE_MARGIN +
-		    i * (STATUS_WIDTH + STATUS_SPACE), STATUS_TOP,
-		    STATUS_WIDTH, STATUS_HEIGHT);
-		
-		if (cstatus_vp[i] < 0)
-			return;
-		
-		vp_switch(cstatus_vp[i]);
-		set_rgb_color(COLOR_FOREGROUND, COLOR_BACKGROUND);
-	}
-	
-	/* Initialize icons */
-	ic_imgmaps[CONS_SELECTED] = make_imgmap(cons_selected_img);
-	ic_imgmaps[CONS_IDLE] = make_imgmap(cons_idle_img);
-	ic_imgmaps[CONS_HAS_DATA] = make_imgmap(cons_has_data_img);
-	ic_imgmaps[CONS_DISCONNECTED] = make_imgmap(cons_idle_img);
-	ic_imgmaps[CONS_KERNEL] = make_imgmap(cons_kernel_img);
-	ic_imgmaps[CONS_DISCONNECTED_SEL] = ic_imgmaps[CONS_SELECTED];
-	
-	make_anim();
-	
-	use_gcons = true;
-	console_state[0] = CONS_DISCONNECTED_SEL;
-	console_state[KERNEL_CONSOLE] = CONS_KERNEL;
-	
-	vp_switch(console_vp);
-}
-
-/** @}
- */
Index: uspace/srv/hid/console/gcons.h
===================================================================
--- uspace/srv/hid/console/gcons.h	(revision 16dc8870242df10ae64ee7bcbf125aa8607cb7fb)
+++ 	(revision )
@@ -1,56 +1,0 @@
-/*
- * Copyright (c) 2006 Ondrej Palkovsky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup console
- * @{
- */
-/** @file
- */
-
-#ifndef GCONS_H_
-#define GCONS_H_
-
-#include <sys/types.h>
-
-void gcons_init(int);
-
-void gcons_redraw_console(void);
-void gcons_change_console(size_t);
-void gcons_notify_char(size_t);
-void gcons_in_kernel(void);
-
-void gcons_notify_connect(size_t);
-void gcons_notify_disconnect(size_t);
-
-void gcons_mouse_move(ssize_t, ssize_t);
-int gcons_mouse_btn(bool state);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/hid/console/keybuffer.c
===================================================================
--- uspace/srv/hid/console/keybuffer.c	(revision 16dc8870242df10ae64ee7bcbf125aa8607cb7fb)
+++ 	(revision )
@@ -1,132 +1,0 @@
-/*
- * Copyright (c) 2006 Josef Cejka
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbdgen
- * @brief HelenOS generic uspace keyboard handler.
- * @ingroup kbd
- * @{
- */
-/** @file
- */
-
-#include <futex.h>
-#include "keybuffer.h"
-
-atomic_t keybuffer_futex = FUTEX_INITIALIZER;
-
-/** Clear key buffer.
- */
-void keybuffer_free(keybuffer_t *keybuffer)
-{
-	futex_down(&keybuffer_futex);
-	keybuffer->head = 0;
-	keybuffer->tail = 0;
-	keybuffer->items = 0;
-	futex_up(&keybuffer_futex);
-}
-
-/** Key buffer initialization.
- *
- */
-void keybuffer_init(keybuffer_t *keybuffer)
-{
-	keybuffer_free(keybuffer);
-}
-
-/** Get free space in buffer.
- *
- * This function is useful for processing some scancodes that are translated
- * to more than one character.
- *
- * @return empty buffer space
- *
- */
-size_t keybuffer_available(keybuffer_t *keybuffer)
-{
-	return KEYBUFFER_SIZE - keybuffer->items;
-}
-
-/**
- *
- * @return nonzero, if buffer is not empty.
- *
- */
-bool keybuffer_empty(keybuffer_t *keybuffer)
-{
-	return (keybuffer->items == 0);
-}
-
-/** Push key event to key buffer.
- *
- * If the buffer is full, the event is ignored.
- *
- * @param keybuffer The keybuffer.
- * @param ev        The event to push.
- *
- */
-void keybuffer_push(keybuffer_t *keybuffer, const kbd_event_t *ev)
-{
-	futex_down(&keybuffer_futex);
-	
-	if (keybuffer->items < KEYBUFFER_SIZE) {
-		keybuffer->fifo[keybuffer->tail] = *ev;
-		keybuffer->tail = (keybuffer->tail + 1) % KEYBUFFER_SIZE;
-		keybuffer->items++;
-	}
-	
-	futex_up(&keybuffer_futex);
-}
-
-/** Pop event from buffer.
- *
- * @param edst Pointer to where the event should be saved.
- *
- * @return True if an event was popped.
- *
- */
-bool keybuffer_pop(keybuffer_t *keybuffer, kbd_event_t *edst)
-{
-	futex_down(&keybuffer_futex);
-	
-	if (keybuffer->items > 0) {
-		keybuffer->items--;
-		*edst = (keybuffer->fifo[keybuffer->head]);
-		keybuffer->head = (keybuffer->head + 1) % KEYBUFFER_SIZE;
-		futex_up(&keybuffer_futex);
-		
-		return true;
-	}
-	
-	futex_up(&keybuffer_futex);
-	
-	return false;
-}
-
-/**
- * @}
- */
Index: uspace/srv/hid/console/keybuffer.h
===================================================================
--- uspace/srv/hid/console/keybuffer.h	(revision 16dc8870242df10ae64ee7bcbf125aa8607cb7fb)
+++ 	(revision )
@@ -1,65 +1,0 @@
-/*
- * Copyright (c) 2006 Josef Cejka
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbdgen
- * @brief HelenOS generic uspace keyboard handler.
- * @ingroup kbd
- * @{
- */
-/** @file
- */
-
-#ifndef __KEYBUFFER_H__
-#define __KEYBUFFER_H__
-
-#include <sys/types.h>
-#include <io/console.h>
-#include <bool.h>
-
-/** Size of buffer for pressed keys */
-#define KEYBUFFER_SIZE  128
-
-typedef struct {
-	kbd_event_t fifo[KEYBUFFER_SIZE];
-	size_t head;
-	size_t tail;
-	size_t items;
-} keybuffer_t;
-
-extern void keybuffer_free(keybuffer_t *);
-extern void keybuffer_init(keybuffer_t *);
-extern size_t keybuffer_available(keybuffer_t *);
-extern bool keybuffer_empty(keybuffer_t *);
-extern void keybuffer_push(keybuffer_t *, const kbd_event_t *);
-extern bool keybuffer_pop(keybuffer_t *, kbd_event_t *);
-
-#endif
-
-/**
- * @}
- */
