Index: uspace/app/mkbd/meson.build
===================================================================
--- uspace/app/mkbd/meson.build	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ uspace/app/mkbd/meson.build	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -27,4 +27,4 @@
 #
 
-deps = [ 'usb', 'usbdev', 'usbhid', 'drv' ]
+deps = [ 'usb', 'usbdev', 'usbhid', 'drv', 'console' ]
 src = files('main.c')
Index: uspace/app/modplay/meson.build
===================================================================
--- uspace/app/modplay/meson.build	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ uspace/app/modplay/meson.build	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -27,5 +27,5 @@
 #
 
-deps = [ 'trackmod', 'hound', 'pcm' ]
+deps = [ 'trackmod', 'hound', 'pcm', 'console' ]
 src = files('modplay.c')
 
Index: uspace/app/netecho/meson.build
===================================================================
--- uspace/app/netecho/meson.build	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ uspace/app/netecho/meson.build	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -27,4 +27,4 @@
 #
 
-deps = [ 'inet' ]
+deps = [ 'inet', 'console' ]
 src = files('comm.c', 'netecho.c')
Index: uspace/app/nterm/meson.build
===================================================================
--- uspace/app/nterm/meson.build	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ uspace/app/nterm/meson.build	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -27,4 +27,4 @@
 #
 
-deps = [ 'inet' ]
+deps = [ 'inet', 'console' ]
 src = files('conn.c', 'nterm.c')
Index: uspace/app/ping/meson.build
===================================================================
--- uspace/app/ping/meson.build	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ uspace/app/ping/meson.build	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -27,4 +27,4 @@
 #
 
-deps = [ 'inet' ]
+deps = [ 'inet', 'console' ]
 src = files('ping.c')
Index: uspace/app/tester/meson.build
===================================================================
--- uspace/app/tester/meson.build	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ uspace/app/tester/meson.build	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -29,5 +29,5 @@
 #
 
-deps = [ 'block', 'codepage', 'drv', 'math', 'ipctest' ]
+deps = [ 'block', 'codepage', 'drv', 'math', 'ipctest', 'console' ]
 src = files(
 	'tester.c',
Index: uspace/app/tetris/meson.build
===================================================================
--- uspace/app/tetris/meson.build	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ uspace/app/tetris/meson.build	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -28,4 +28,5 @@
 #
 
+deps = [ 'console' ]
 src = files(
 	'shapes.c',
Index: uspace/app/top/meson.build
===================================================================
--- uspace/app/top/meson.build	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ uspace/app/top/meson.build	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -28,4 +28,5 @@
 #
 
+deps = [ 'console' ]
 src = files(
 	'top.c',
Index: uspace/app/trace/meson.build
===================================================================
--- uspace/app/trace/meson.build	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ uspace/app/trace/meson.build	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -28,4 +28,5 @@
 #
 
+deps = [ 'console' ]
 src = files(
 	'trace.c',
Index: uspace/drv/hid/adb-kbd/adb-kbd.c
===================================================================
--- uspace/drv/hid/adb-kbd/adb-kbd.c	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ uspace/drv/hid/adb-kbd/adb-kbd.c	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -34,5 +34,5 @@
 #include <ddf/log.h>
 #include <errno.h>
-#include <io/console.h>
+#include <io/kbd_event.h>
 #include <ipc/adb.h>
 #include <ipc/kbdev.h>
Index: uspace/drv/hid/adb-kbd/ctl.c
===================================================================
--- uspace/drv/hid/adb-kbd/ctl.c	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ uspace/drv/hid/adb-kbd/ctl.c	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -33,5 +33,5 @@
 
 #include <errno.h>
-#include <io/console.h>
+#include <io/kbd_event.h>
 #include <io/keycode.h>
 
Index: uspace/drv/hid/atkbd/atkbd.c
===================================================================
--- uspace/drv/hid/atkbd/atkbd.c	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ uspace/drv/hid/atkbd/atkbd.c	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -38,7 +38,7 @@
 #include <errno.h>
 #include <ddf/log.h>
+#include <io/kbd_event.h>
 #include <io/keycode.h>
 #include <io/chardev.h>
-#include <io/console.h>
 #include <ipc/kbdev.h>
 #include <abi/ipc/methods.h>
Index: uspace/drv/hid/ps2mouse/ps2mouse.c
===================================================================
--- uspace/drv/hid/ps2mouse/ps2mouse.c	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ uspace/drv/hid/ps2mouse/ps2mouse.c	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -40,5 +40,4 @@
 #include <io/keycode.h>
 #include <io/chardev.h>
-#include <io/console.h>
 #include <ipc/mouseev.h>
 #include <abi/ipc/methods.h>
Index: uspace/drv/hid/usbhid/kbd/kbddev.c
===================================================================
--- uspace/drv/hid/usbhid/kbd/kbddev.c	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ uspace/drv/hid/usbhid/kbd/kbddev.c	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -41,5 +41,5 @@
 
 #include <io/keycode.h>
-#include <io/console.h>
+#include <io/kbd_event.h>
 #include <abi/ipc/methods.h>
 #include <ipc/kbdev.h>
Index: uspace/drv/hid/usbhid/kbd/kbdrepeat.c
===================================================================
--- uspace/drv/hid/usbhid/kbd/kbdrepeat.c	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ uspace/drv/hid/usbhid/kbd/kbdrepeat.c	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -36,6 +36,6 @@
 
 #include <fibril_synch.h>
+#include <io/kbd_event.h>
 #include <io/keycode.h>
-#include <io/console.h>
 #include <errno.h>
 
Index: uspace/drv/hid/usbhid/mouse/mousedev.c
===================================================================
--- uspace/drv/hid/usbhid/mouse/mousedev.c	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ uspace/drv/hid/usbhid/mouse/mousedev.c	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -46,5 +46,4 @@
 #include <str_error.h>
 #include <ipc/mouseev.h>
-#include <io/console.h>
 
 #include <ipc/kbdev.h>
Index: uspace/drv/hid/usbhid/multimedia/multimedia.c
===================================================================
--- uspace/drv/hid/usbhid/multimedia/multimedia.c	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ uspace/drv/hid/usbhid/multimedia/multimedia.c	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -51,5 +51,5 @@
 
 #include <ipc/kbdev.h>
-#include <io/console.h>
+#include <io/kbd_event.h>
 
 #define NAME  "multimedia-keys"
Index: uspace/drv/hid/xtkbd/xtkbd.c
===================================================================
--- uspace/drv/hid/xtkbd/xtkbd.c	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ uspace/drv/hid/xtkbd/xtkbd.c	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -39,5 +39,5 @@
 #include <io/keycode.h>
 #include <io/chardev.h>
-#include <io/console.h>
+#include <io/kbd_event.h>
 #include <ipc/kbdev.h>
 #include <abi/ipc/methods.h>
Index: uspace/lib/c/generic/io/chargrid.c
===================================================================
--- uspace/lib/c/generic/io/chargrid.c	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ uspace/lib/c/generic/io/chargrid.c	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libc
+/** @addtogroup libconsole
  * @{
  */
Index: pace/lib/c/generic/io/con_srv.c
===================================================================
--- uspace/lib/c/generic/io/con_srv.c	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ 	(revision )
@@ -1,539 +1,0 @@
-/*
- * Copyright (c) 2021 Jiri Svoboda
- * 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 libc
- * @{
- */
-/**
- * @file
- * @brief Console protocol server stub
- */
-#include <as.h>
-#include <errno.h>
-#include <io/cons_event.h>
-#include <ipc/console.h>
-#include <stdlib.h>
-#include <stddef.h>
-
-#include <io/con_srv.h>
-
-static errno_t console_ev_encode(cons_event_t *event, ipc_call_t *icall)
-{
-	ipc_set_arg1(icall, event->type);
-
-	switch (event->type) {
-	case CEV_KEY:
-		ipc_set_arg2(icall, event->ev.key.type);
-		ipc_set_arg3(icall, event->ev.key.key);
-		ipc_set_arg4(icall, event->ev.key.mods);
-		ipc_set_arg5(icall, event->ev.key.c);
-		break;
-	case CEV_POS:
-		ipc_set_arg2(icall, (event->ev.pos.pos_id << 16) | (event->ev.pos.type & 0xffff));
-		ipc_set_arg3(icall, event->ev.pos.btn_num);
-		ipc_set_arg4(icall, event->ev.pos.hpos);
-		ipc_set_arg5(icall, event->ev.pos.vpos);
-		break;
-	default:
-		return EIO;
-	}
-
-	return EOK;
-}
-
-static void con_read_srv(con_srv_t *srv, ipc_call_t *icall)
-{
-	void *buf;
-	size_t size;
-	errno_t rc;
-
-	ipc_call_t call;
-	if (!async_data_read_receive(&call, &size)) {
-		async_answer_0(icall, EINVAL);
-		return;
-	}
-
-	buf = malloc(size);
-	if (buf == NULL) {
-		async_answer_0(&call, ENOMEM);
-		async_answer_0(icall, ENOMEM);
-		return;
-	}
-
-	if (srv->srvs->ops->read == NULL) {
-		async_answer_0(&call, ENOTSUP);
-		async_answer_0(icall, ENOTSUP);
-		free(buf);
-		return;
-	}
-
-	size_t nread;
-	rc = srv->srvs->ops->read(srv, buf, size, &nread);
-	if (rc != EOK) {
-		async_answer_0(&call, rc);
-		async_answer_0(icall, rc);
-		free(buf);
-		return;
-	}
-
-	async_data_read_finalize(&call, buf, nread);
-	free(buf);
-
-	async_answer_1(icall, EOK, nread);
-}
-
-static void con_write_srv(con_srv_t *srv, ipc_call_t *icall)
-{
-	void *data;
-	size_t size;
-	errno_t rc;
-
-	rc = async_data_write_accept(&data, false, 0, 0, 0, &size);
-	if (rc != EOK) {
-		async_answer_0(icall, rc);
-		return;
-	}
-
-	if (srv->srvs->ops->write == NULL) {
-		async_answer_0(icall, ENOTSUP);
-		return;
-	}
-
-	size_t nwritten = 0;
-	rc = srv->srvs->ops->write(srv, data, size, &nwritten);
-	free(data);
-
-	async_answer_1(icall, rc, nwritten);
-}
-
-static void con_sync_srv(con_srv_t *srv, ipc_call_t *icall)
-{
-	if (srv->srvs->ops->sync == NULL) {
-		async_answer_0(icall, ENOTSUP);
-		return;
-	}
-
-	srv->srvs->ops->sync(srv);
-	async_answer_0(icall, EOK);
-}
-
-static void con_clear_srv(con_srv_t *srv, ipc_call_t *icall)
-{
-	if (srv->srvs->ops->clear == NULL) {
-		async_answer_0(icall, ENOTSUP);
-		return;
-	}
-
-	srv->srvs->ops->clear(srv);
-	async_answer_0(icall, EOK);
-}
-
-static void con_set_pos_srv(con_srv_t *srv, ipc_call_t *icall)
-{
-	sysarg_t col;
-	sysarg_t row;
-
-	col = ipc_get_arg1(icall);
-	row = ipc_get_arg2(icall);
-
-	if (srv->srvs->ops->set_pos == NULL) {
-		async_answer_0(icall, ENOTSUP);
-		return;
-	}
-
-	srv->srvs->ops->set_pos(srv, col, row);
-	async_answer_0(icall, EOK);
-}
-
-static void con_get_pos_srv(con_srv_t *srv, ipc_call_t *icall)
-{
-	errno_t rc;
-	sysarg_t col;
-	sysarg_t row;
-
-	if (srv->srvs->ops->get_pos == NULL) {
-		async_answer_0(icall, ENOTSUP);
-		return;
-	}
-
-	rc = srv->srvs->ops->get_pos(srv, &col, &row);
-	async_answer_2(icall, rc, col, row);
-}
-
-static void con_get_size_srv(con_srv_t *srv, ipc_call_t *icall)
-{
-	errno_t rc;
-	sysarg_t cols;
-	sysarg_t rows;
-
-	if (srv->srvs->ops->get_size == NULL) {
-		async_answer_0(icall, ENOTSUP);
-		return;
-	}
-
-	rc = srv->srvs->ops->get_size(srv, &cols, &rows);
-	async_answer_2(icall, rc, cols, rows);
-}
-
-static void con_get_color_cap_srv(con_srv_t *srv, ipc_call_t *icall)
-{
-	errno_t rc;
-	console_caps_t ccap;
-
-	if (srv->srvs->ops->get_color_cap == NULL) {
-		async_answer_0(icall, ENOTSUP);
-		return;
-	}
-
-	rc = srv->srvs->ops->get_color_cap(srv, &ccap);
-	async_answer_1(icall, rc, (sysarg_t)ccap);
-}
-
-static void con_set_style_srv(con_srv_t *srv, ipc_call_t *icall)
-{
-	console_style_t style;
-
-	style = ipc_get_arg1(icall);
-
-	if (srv->srvs->ops->set_style == NULL) {
-		async_answer_0(icall, ENOTSUP);
-		return;
-	}
-
-	srv->srvs->ops->set_style(srv, style);
-	async_answer_0(icall, EOK);
-}
-
-static void con_set_color_srv(con_srv_t *srv, ipc_call_t *icall)
-{
-	console_color_t bgcolor;
-	console_color_t fgcolor;
-	console_color_attr_t flags;
-
-	bgcolor = ipc_get_arg1(icall);
-	fgcolor = ipc_get_arg2(icall);
-	flags = ipc_get_arg3(icall);
-
-	if (srv->srvs->ops->set_color == NULL) {
-		async_answer_0(icall, ENOTSUP);
-		return;
-	}
-
-	srv->srvs->ops->set_color(srv, bgcolor, fgcolor, flags);
-	async_answer_0(icall, EOK);
-}
-
-static void con_set_rgb_color_srv(con_srv_t *srv, ipc_call_t *icall)
-{
-	pixel_t bgcolor;
-	pixel_t fgcolor;
-
-	bgcolor = ipc_get_arg1(icall);
-	fgcolor = ipc_get_arg2(icall);
-
-	if (srv->srvs->ops->set_rgb_color == NULL) {
-		async_answer_0(icall, ENOTSUP);
-		return;
-	}
-
-	srv->srvs->ops->set_rgb_color(srv, bgcolor, fgcolor);
-	async_answer_0(icall, EOK);
-}
-
-static void con_set_cursor_visibility_srv(con_srv_t *srv, ipc_call_t *icall)
-{
-	bool show;
-
-	show = ipc_get_arg1(icall);
-
-	if (srv->srvs->ops->set_cursor_visibility == NULL) {
-		async_answer_0(icall, ENOTSUP);
-		return;
-	}
-
-	srv->srvs->ops->set_cursor_visibility(srv, show);
-	async_answer_0(icall, EOK);
-}
-
-static void con_set_caption_srv(con_srv_t *srv, ipc_call_t *icall)
-{
-	char *caption;
-	errno_t rc;
-
-	rc = async_data_write_accept((void **) &caption, true, 0,
-	    CON_CAPTION_MAXLEN, 0, NULL);
-	if (rc != EOK) {
-		async_answer_0(icall, rc);
-		return;
-	}
-
-	if (srv->srvs->ops->set_caption == NULL) {
-		async_answer_0(icall, ENOTSUP);
-		return;
-	}
-
-	srv->srvs->ops->set_caption(srv, caption);
-	free(caption);
-	async_answer_0(icall, EOK);
-}
-
-static void con_get_event_srv(con_srv_t *srv, ipc_call_t *icall)
-{
-	errno_t rc;
-	cons_event_t event;
-	ipc_call_t result;
-
-	if (srv->srvs->ops->get_event == NULL) {
-		async_answer_0(icall, ENOTSUP);
-		return;
-	}
-
-	rc = srv->srvs->ops->get_event(srv, &event);
-	if (rc != EOK) {
-		async_answer_0(icall, rc);
-		return;
-	}
-
-	rc = console_ev_encode(&event, &result);
-	if (rc != EOK) {
-		async_answer_0(icall, rc);
-		return;
-	}
-
-	async_answer_5(icall, rc, ipc_get_arg1(&result), ipc_get_arg2(&result),
-	    ipc_get_arg3(&result), ipc_get_arg4(&result), ipc_get_arg5(&result));
-}
-
-/** Create shared buffer for efficient rendering */
-static void con_map_srv(con_srv_t *srv, ipc_call_t *icall)
-{
-	errno_t rc;
-	charfield_t *buf;
-	sysarg_t cols, rows;
-	ipc_call_t call;
-	size_t size;
-
-	if (srv->srvs->ops->map == NULL || srv->srvs->ops->unmap == NULL) {
-		async_answer_0(icall, ENOTSUP);
-		return;
-	}
-
-	cols = ipc_get_arg1(icall);
-	rows = ipc_get_arg2(icall);
-
-	if (!async_share_in_receive(&call, &size)) {
-		async_answer_0(icall, EINVAL);
-		return;
-	}
-
-	/* Check size */
-	if (size != PAGES2SIZE(SIZE2PAGES(cols * rows * sizeof(charfield_t)))) {
-		async_answer_0(&call, EINVAL);
-		async_answer_0(icall, EINVAL);
-		return;
-	}
-
-	rc = srv->srvs->ops->map(srv, cols, rows, &buf);
-	if (rc != EOK) {
-		async_answer_0(&call, rc);
-		async_answer_0(icall, rc);
-		return;
-	}
-
-	rc = async_share_in_finalize(&call, buf, AS_AREA_READ |
-	    AS_AREA_WRITE | AS_AREA_CACHEABLE);
-	if (rc != EOK) {
-		srv->srvs->ops->unmap(srv);
-		async_answer_0(icall, EIO);
-		return;
-	}
-
-	async_answer_0(icall, EOK);
-}
-
-/** Delete shared buffer */
-static void con_unmap_srv(con_srv_t *srv, ipc_call_t *icall)
-{
-	if (srv->srvs->ops->unmap == NULL) {
-		async_answer_0(icall, ENOTSUP);
-		return;
-	}
-
-	srv->srvs->ops->unmap(srv);
-	async_answer_0(icall, EOK);
-}
-
-/** Update console area from shared buffer */
-static void con_update_srv(con_srv_t *srv, ipc_call_t *icall)
-{
-	sysarg_t c0, r0, c1, r1;
-
-	c0 = ipc_get_arg1(icall);
-	r0 = ipc_get_arg2(icall);
-	c1 = ipc_get_arg3(icall);
-	r1 = ipc_get_arg4(icall);
-
-	if (srv->srvs->ops->update == NULL) {
-		async_answer_0(icall, ENOTSUP);
-		return;
-	}
-
-	srv->srvs->ops->update(srv, c0, r0, c1, r1);
-	async_answer_0(icall, EOK);
-}
-
-static con_srv_t *con_srv_create(con_srvs_t *srvs)
-{
-	con_srv_t *srv;
-
-	srv = calloc(1, sizeof(*srv));
-	if (srv == NULL)
-		return NULL;
-
-	srv->srvs = srvs;
-	return srv;
-}
-
-void con_srvs_init(con_srvs_t *srvs)
-{
-	srvs->ops = NULL;
-	srvs->sarg = NULL;
-	srvs->abort_timeout = 0;
-	srvs->aborted = false;
-}
-
-errno_t con_conn(ipc_call_t *icall, con_srvs_t *srvs)
-{
-	con_srv_t *srv;
-	errno_t rc;
-
-	/* Accept the connection */
-	async_accept_0(icall);
-
-	srv = con_srv_create(srvs);
-	if (srv == NULL)
-		return ENOMEM;
-
-	srv->client_sess = NULL;
-
-	rc = srvs->ops->open(srvs, srv);
-	if (rc != EOK)
-		return rc;
-
-	while (true) {
-		ipc_call_t call;
-		bool received = false;
-
-		while (!received) {
-			/* XXX Need to be able to abort immediately */
-			received = async_get_call_timeout(&call,
-			    srvs->abort_timeout);
-
-			if (srv->srvs->aborted) {
-				if (received)
-					async_answer_0(&call, EINTR);
-				break;
-			}
-		}
-
-		if (!received)
-			break;
-
-		sysarg_t method = ipc_get_imethod(&call);
-
-		if (!method) {
-			/* The other side has hung up */
-			async_answer_0(&call, EOK);
-			break;
-		}
-
-		switch (method) {
-		case VFS_OUT_READ:
-			con_read_srv(srv, &call);
-			break;
-		case VFS_OUT_WRITE:
-			con_write_srv(srv, &call);
-			break;
-		case VFS_OUT_SYNC:
-			con_sync_srv(srv, &call);
-			break;
-		case CONSOLE_CLEAR:
-			con_clear_srv(srv, &call);
-			break;
-		case CONSOLE_SET_POS:
-			con_set_pos_srv(srv, &call);
-			break;
-		case CONSOLE_GET_POS:
-			con_get_pos_srv(srv, &call);
-			break;
-		case CONSOLE_GET_SIZE:
-			con_get_size_srv(srv, &call);
-			break;
-		case CONSOLE_GET_COLOR_CAP:
-			con_get_color_cap_srv(srv, &call);
-			break;
-		case CONSOLE_SET_STYLE:
-			con_set_style_srv(srv, &call);
-			break;
-		case CONSOLE_SET_COLOR:
-			con_set_color_srv(srv, &call);
-			break;
-		case CONSOLE_SET_RGB_COLOR:
-			con_set_rgb_color_srv(srv, &call);
-			break;
-		case CONSOLE_SET_CURSOR_VISIBILITY:
-			con_set_cursor_visibility_srv(srv, &call);
-			break;
-		case CONSOLE_SET_CAPTION:
-			con_set_caption_srv(srv, &call);
-			break;
-		case CONSOLE_GET_EVENT:
-			con_get_event_srv(srv, &call);
-			break;
-		case CONSOLE_MAP:
-			con_map_srv(srv, &call);
-			break;
-		case CONSOLE_UNMAP:
-			con_unmap_srv(srv, &call);
-			break;
-		case CONSOLE_UPDATE:
-			con_update_srv(srv, &call);
-			break;
-		default:
-			async_answer_0(&call, ENOTSUP);
-		}
-	}
-
-	rc = srvs->ops->close(srv);
-	free(srv);
-
-	return rc;
-}
-
-/** @}
- */
Index: pace/lib/c/generic/io/console.c
===================================================================
--- uspace/lib/c/generic/io/console.c	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ 	(revision )
@@ -1,378 +1,0 @@
-/*
- * Copyright (c) 2021 Jiri Svoboda
- * Copyright (c) 2006 Josef Cejka
- * Copyright (c) 2006 Jakub Vana
- * 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 libc
- * @{
- */
-/** @file
- */
-
-#include <as.h>
-#include <libc.h>
-#include <async.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <str.h>
-#include <vfs/vfs_sess.h>
-#include <io/console.h>
-#include <ipc/console.h>
-
-console_ctrl_t *console_init(FILE *ifile, FILE *ofile)
-{
-	console_ctrl_t *ctrl = malloc(sizeof(console_ctrl_t));
-	if (!ctrl)
-		return NULL;
-
-	ctrl->input_sess = vfs_fsession(ifile, INTERFACE_CONSOLE);
-	if (!ctrl->input_sess) {
-		free(ctrl);
-		return NULL;
-	}
-
-	ctrl->output_sess = vfs_fsession(ofile, INTERFACE_CONSOLE);
-	if (!ctrl->output_sess) {
-		free(ctrl);
-		return NULL;
-	}
-
-	ctrl->input = ifile;
-	ctrl->output = ofile;
-	ctrl->input_aid = 0;
-
-	return ctrl;
-}
-
-void console_done(console_ctrl_t *ctrl)
-{
-	free(ctrl);
-}
-
-bool console_kcon(void)
-{
-	return __SYSCALL0(SYS_DEBUG_CONSOLE);
-}
-
-void console_flush(console_ctrl_t *ctrl)
-{
-	fflush(ctrl->output);
-}
-
-void console_clear(console_ctrl_t *ctrl)
-{
-	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
-	async_req_0_0(exch, CONSOLE_CLEAR);
-	async_exchange_end(exch);
-}
-
-errno_t console_get_size(console_ctrl_t *ctrl, sysarg_t *cols, sysarg_t *rows)
-{
-	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
-	errno_t rc = async_req_0_2(exch, CONSOLE_GET_SIZE, cols, rows);
-	async_exchange_end(exch);
-
-	return rc;
-}
-
-void console_set_style(console_ctrl_t *ctrl, uint8_t style)
-{
-	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
-	async_req_1_0(exch, CONSOLE_SET_STYLE, style);
-	async_exchange_end(exch);
-}
-
-void console_set_color(console_ctrl_t *ctrl, uint8_t bgcolor, uint8_t fgcolor,
-    uint8_t flags)
-{
-	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
-	async_req_3_0(exch, CONSOLE_SET_COLOR, bgcolor, fgcolor, flags);
-	async_exchange_end(exch);
-}
-
-void console_set_rgb_color(console_ctrl_t *ctrl, uint32_t bgcolor,
-    uint32_t fgcolor)
-{
-	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
-	async_req_2_0(exch, CONSOLE_SET_RGB_COLOR, bgcolor, fgcolor);
-	async_exchange_end(exch);
-}
-
-void console_cursor_visibility(console_ctrl_t *ctrl, bool show)
-{
-	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
-	async_req_1_0(exch, CONSOLE_SET_CURSOR_VISIBILITY, (show != false));
-	async_exchange_end(exch);
-}
-
-/** Set console caption.
- *
- * Set caption text for the console (if the console suports captions).
- *
- * @param ctrl Console
- * @param caption Caption text
- * @return EOK on success or an error code
- */
-errno_t console_set_caption(console_ctrl_t *ctrl, const char *caption)
-{
-	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
-	ipc_call_t answer;
-	aid_t req = async_send_0(exch, CONSOLE_SET_CAPTION, &answer);
-	errno_t retval = async_data_write_start(exch, caption, str_size(caption));
-
-	if (retval != EOK) {
-		async_forget(req);
-		async_exchange_end(exch);
-		return retval;
-	}
-
-	async_wait_for(req, &retval);
-	async_exchange_end(exch);
-	return EOK;
-}
-
-errno_t console_get_color_cap(console_ctrl_t *ctrl, sysarg_t *ccap)
-{
-	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
-	errno_t rc = async_req_0_1(exch, CONSOLE_GET_COLOR_CAP, ccap);
-	async_exchange_end(exch);
-
-	return rc;
-}
-
-errno_t console_get_pos(console_ctrl_t *ctrl, sysarg_t *col, sysarg_t *row)
-{
-	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
-	errno_t rc = async_req_0_2(exch, CONSOLE_GET_POS, col, row);
-	async_exchange_end(exch);
-
-	return rc;
-}
-
-void console_set_pos(console_ctrl_t *ctrl, sysarg_t col, sysarg_t row)
-{
-	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
-	async_req_2_0(exch, CONSOLE_SET_POS, col, row);
-	async_exchange_end(exch);
-}
-
-static errno_t console_ev_decode(ipc_call_t *call, cons_event_t *event)
-{
-	event->type = ipc_get_arg1(call);
-
-	switch (event->type) {
-	case CEV_KEY:
-		event->ev.key.type = ipc_get_arg2(call);
-		event->ev.key.key = ipc_get_arg3(call);
-		event->ev.key.mods = ipc_get_arg4(call);
-		event->ev.key.c = ipc_get_arg5(call);
-		break;
-	case CEV_POS:
-		event->ev.pos.pos_id = ipc_get_arg2(call) >> 16;
-		event->ev.pos.type = ipc_get_arg2(call) & 0xffff;
-		event->ev.pos.btn_num = ipc_get_arg3(call);
-		event->ev.pos.hpos = ipc_get_arg4(call);
-		event->ev.pos.vpos = ipc_get_arg5(call);
-		break;
-	default:
-		return EIO;
-	}
-
-	return EOK;
-}
-
-/** Get console event.
- *
- * @param ctrl Console
- * @param event Place to store event
- * @return EOK on success, EIO on failure
- */
-errno_t console_get_event(console_ctrl_t *ctrl, cons_event_t *event)
-{
-	if (ctrl->input_aid == 0) {
-		ipc_call_t result;
-
-		async_exch_t *exch = async_exchange_begin(ctrl->input_sess);
-		aid_t aid = async_send_0(exch, CONSOLE_GET_EVENT, &result);
-		async_exchange_end(exch);
-
-		errno_t rc;
-		async_wait_for(aid, &rc);
-
-		if (rc != EOK)
-			return EIO;
-
-		rc = console_ev_decode(&result, event);
-		if (rc != EOK)
-			return EIO;
-	} else {
-		errno_t retval;
-		async_wait_for(ctrl->input_aid, &retval);
-
-		ctrl->input_aid = 0;
-
-		if (retval != EOK)
-			return EIO;
-
-		errno_t rc = console_ev_decode(&ctrl->input_call, event);
-		if (rc != EOK)
-			return EIO;
-	}
-
-	return EOK;
-}
-
-/** Get console event with timeout.
- *
- * @param ctrl Console
- * @param event Place to store event
- * @param timeout Pointer to timeout. This will be updated to reflect
- *                the remaining time in case of timeout.
- * @return EOK on success (event received), ETIMEOUT on time out,
- *         EIO on I/O error (e.g. lost console connection), ENOMEM
- *         if out of memory
- */
-errno_t console_get_event_timeout(console_ctrl_t *ctrl, cons_event_t *event,
-    usec_t *timeout)
-{
-	struct timespec t0;
-	getuptime(&t0);
-
-	if (ctrl->input_aid == 0) {
-		async_exch_t *exch = async_exchange_begin(ctrl->input_sess);
-		ctrl->input_aid = async_send_0(exch, CONSOLE_GET_EVENT,
-		    &ctrl->input_call);
-		async_exchange_end(exch);
-	}
-
-	errno_t retval;
-	errno_t rc = async_wait_timeout(ctrl->input_aid, &retval, *timeout);
-	if (rc != EOK) {
-		if (rc == ENOMEM)
-			return ENOMEM;
-		*timeout = 0;
-		return ETIMEOUT;
-	}
-
-	ctrl->input_aid = 0;
-
-	if (retval != EOK)
-		return EIO;
-
-	rc = console_ev_decode(&ctrl->input_call, event);
-	if (rc != EOK)
-		return EIO;
-
-	/* Update timeout */
-	struct timespec t1;
-	getuptime(&t1);
-	*timeout -= NSEC2USEC(ts_sub_diff(&t1, &t0));
-
-	return EOK;
-}
-
-/** Create a shared buffer for fast rendering to the console.
- *
- * @param ctrl Console
- * @param cols Number of columns
- * @param rows Number of rows
- * @param rbuf Place to store pointer to the shared buffer
- * @return EOK on success or an error code
- */
-errno_t console_map(console_ctrl_t *ctrl, sysarg_t cols, sysarg_t rows,
-    charfield_t **rbuf)
-{
-	async_exch_t *exch = NULL;
-	void *buf;
-	aid_t req;
-	ipc_call_t answer;
-	size_t asize;
-	errno_t rc;
-
-	exch = async_exchange_begin(ctrl->output_sess);
-	req = async_send_2(exch, CONSOLE_MAP, cols, rows, &answer);
-
-	asize = PAGES2SIZE(SIZE2PAGES(cols * rows * sizeof(charfield_t)));
-
-	rc = async_share_in_start_0_0(exch, asize, &buf);
-	if (rc != EOK) {
-		async_forget(req);
-		goto error;
-	}
-
-	async_exchange_end(exch);
-	exch = NULL;
-
-	async_wait_for(req, &rc);
-	if (rc != EOK)
-		goto error;
-
-	*rbuf = (charfield_t *)buf;
-	return EOK;
-error:
-	if (exch != NULL)
-		async_exchange_end(exch);
-	return rc;
-}
-
-/** Unmap console shared buffer.
- *
- * @param ctrl Console
- * @param buf Buffer
- */
-void console_unmap(console_ctrl_t *ctrl, charfield_t *buf)
-{
-	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
-	(void) async_req_0_0(exch, CONSOLE_UNMAP);
-	async_exchange_end(exch);
-
-	as_area_destroy(buf);
-}
-
-/** Update console rectangle from shared buffer.
- *
- * @param ctrl Console
- * @param c0 Column coordinate of top-left corner (inclusive)
- * @param r0 Row coordinate of top-left corner (inclusive)
- * @param c1 Column coordinate of bottom-right corner (exclusive)
- * @param r1 Row coordinate of bottom-right corner (exclusive)
- *
- * @return EOK on sucess or an error code
- */
-errno_t console_update(console_ctrl_t *ctrl, sysarg_t c0, sysarg_t r0,
-    sysarg_t c1, sysarg_t r1)
-{
-	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
-	errno_t rc = async_req_4_0(exch, CONSOLE_UPDATE, c0, r0, c1, r1);
-	async_exchange_end(exch);
-
-	return rc;
-}
-
-/** @}
- */
Index: uspace/lib/c/include/io/charfield.h
===================================================================
--- uspace/lib/c/include/io/charfield.h	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ uspace/lib/c/include/io/charfield.h	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -28,5 +28,5 @@
  */
 
-/** @addtogroup libc
+/** @addtogroup libconsole
  * @{
  */
@@ -34,6 +34,6 @@
  */
 
-#ifndef _LIBC_IO_CHARFIELD_H_
-#define _LIBC_IO_CHARFIELD_H_
+#ifndef _LIBCONSOLE_IO_CHARFIELD_H_
+#define _LIBCONSOLE_IO_CHARFIELD_H_
 
 #include <stdbool.h>
Index: uspace/lib/c/include/io/chargrid.h
===================================================================
--- uspace/lib/c/include/io/chargrid.h	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ uspace/lib/c/include/io/chargrid.h	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libc
+/** @addtogroup libconsole
  * @{
  */
@@ -34,6 +34,6 @@
  */
 
-#ifndef _LIBC_IO_CHARGRID_H_
-#define _LIBC_IO_CHARGRID_H_
+#ifndef _LIBCONSOLE_IO_CHARGRID_H_
+#define _LIBCONSOLE_IO_CHARGRID_H_
 
 #include <io/charfield.h>
Index: uspace/lib/c/include/io/color.h
===================================================================
--- uspace/lib/c/include/io/color.h	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ uspace/lib/c/include/io/color.h	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2008 Jiri Svoboda
+ * Copyright (c) 2023 Jiri Svoboda
  * All rights reserved.
  *
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libc
+/** @addtogroup libconsole
  * @{
  */
@@ -33,6 +33,6 @@
  */
 
-#ifndef _LIBC_IO_COLOR_H_
-#define _LIBC_IO_COLOR_H_
+#ifndef _LIBCONSOLE_IO_COLOR_H_
+#define _LIBCONSOLE_IO_COLOR_H_
 
 typedef enum {
Index: pace/lib/c/include/io/con_srv.h
===================================================================
--- uspace/lib/c/include/io/con_srv.h	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ 	(revision )
@@ -1,101 +1,0 @@
-/*
- * Copyright (c) 2021 Jiri Svoboda
- * 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 libc
- * @{
- */
-/** @file
- */
-
-#ifndef _LIBC_CON_SRV_H_
-#define _LIBC_CON_SRV_H_
-
-#include <adt/list.h>
-#include <async.h>
-#include <fibril_synch.h>
-#include <io/charfield.h>
-#include <io/color.h>
-#include <io/concaps.h>
-#include <io/cons_event.h>
-#include <io/pixel.h>
-#include <io/style.h>
-#include <stdbool.h>
-#include <time.h>
-#include <stddef.h>
-
-typedef struct con_ops con_ops_t;
-
-#define CON_CAPTION_MAXLEN 255
-
-/** Service setup (per sevice) */
-typedef struct {
-	con_ops_t *ops;
-	void *sarg;
-	/** Period to check for abort */
-	usec_t abort_timeout;
-	bool aborted;
-} con_srvs_t;
-
-/** Server structure (per client session) */
-typedef struct {
-	con_srvs_t *srvs;
-	async_sess_t *client_sess;
-	void *carg;
-} con_srv_t;
-
-struct con_ops {
-	errno_t (*open)(con_srvs_t *, con_srv_t *);
-	errno_t (*close)(con_srv_t *);
-	errno_t (*read)(con_srv_t *, void *, size_t, size_t *);
-	errno_t (*write)(con_srv_t *, void *, size_t, size_t *);
-	void (*sync)(con_srv_t *);
-	void (*clear)(con_srv_t *);
-	void (*set_pos)(con_srv_t *, sysarg_t col, sysarg_t row);
-	errno_t (*get_pos)(con_srv_t *, sysarg_t *, sysarg_t *);
-	errno_t (*get_size)(con_srv_t *, sysarg_t *, sysarg_t *);
-	errno_t (*get_color_cap)(con_srv_t *, console_caps_t *);
-	void (*set_style)(con_srv_t *, console_style_t);
-	void (*set_color)(con_srv_t *, console_color_t, console_color_t,
-	    console_color_attr_t);
-	void (*set_rgb_color)(con_srv_t *, pixel_t, pixel_t);
-	void (*set_cursor_visibility)(con_srv_t *, bool);
-	errno_t (*set_caption)(con_srv_t *, const char *);
-	errno_t (*get_event)(con_srv_t *, cons_event_t *);
-	errno_t (*map)(con_srv_t *, sysarg_t, sysarg_t, charfield_t **);
-	void (*unmap)(con_srv_t *);
-	void (*update)(con_srv_t *, sysarg_t, sysarg_t, sysarg_t, sysarg_t);
-};
-
-extern void con_srvs_init(con_srvs_t *);
-
-extern errno_t con_conn(ipc_call_t *, con_srvs_t *);
-
-#endif
-
-/** @}
- */
Index: uspace/lib/c/include/io/concaps.h
===================================================================
--- uspace/lib/c/include/io/concaps.h	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ uspace/lib/c/include/io/concaps.h	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2012 Jiri Svoboda
+ * Copyright (c) 2023 Jiri Svoboda
  * All rights reserved.
  *
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libcipc
+/** @addtogroup libconsole
  * @{
  */
@@ -33,6 +33,6 @@
  */
 
-#ifndef _LIBC_IO_CONCAPS_H_
-#define _LIBC_IO_CONCAPS_H_
+#ifndef _LIBCONSOLE_IO_CONCAPS_H_
+#define _LIBCONSOLE_IO_CONCAPS_H_
 
 typedef enum {
Index: pace/lib/c/include/io/cons_event.h
===================================================================
--- uspace/lib/c/include/io/cons_event.h	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ 	(revision )
@@ -1,66 +1,0 @@
-/*
- * Copyright (c) 2013 Jiri Svoboda
- * 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 libc
- * @{
- */
-/** @file
- */
-
-#ifndef _LIBC_IO_CONS_EVENT_H_
-#define _LIBC_IO_CONS_EVENT_H_
-
-#include <adt/list.h>
-#include <io/kbd_event.h>
-#include <io/pos_event.h>
-
-typedef enum {
-	/** Key event */
-	CEV_KEY,
-	/** Position event */
-	CEV_POS
-} cons_event_type_t;
-
-/** Console event structure. */
-typedef struct {
-	/** List handle */
-	link_t link;
-
-	/** Event type */
-	cons_event_type_t type;
-
-	union {
-		kbd_event_t key;
-		pos_event_t pos;
-	} ev;
-} cons_event_t;
-
-#endif
-
-/** @}
- */
Index: pace/lib/c/include/io/console.h
===================================================================
--- uspace/lib/c/include/io/console.h	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ 	(revision )
@@ -1,99 +1,0 @@
-/*
- * Copyright (c) 2021 Jiri Svoboda
- * 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 libc
- * @{
- */
-/** @file
- */
-
-#ifndef _LIBC_IO_CONSOLE_H_
-#define _LIBC_IO_CONSOLE_H_
-
-#include <time.h>
-#include <io/charfield.h>
-#include <io/concaps.h>
-#include <io/kbd_event.h>
-#include <io/cons_event.h>
-#include <io/keycode.h>
-#include <async.h>
-#include <stdbool.h>
-#include <stdio.h>
-
-/** Console control structure. */
-typedef struct {
-	/** Console input file */
-	FILE *input;
-
-	/** Console output file */
-	FILE *output;
-
-	/** Console input session */
-	async_sess_t *input_sess;
-
-	/** Console output session */
-	async_sess_t *output_sess;
-
-	/** Input request call with timeout */
-	ipc_call_t input_call;
-
-	/** Input response with timeout */
-	aid_t input_aid;
-} console_ctrl_t;
-
-extern console_ctrl_t *console_init(FILE *, FILE *);
-extern void console_done(console_ctrl_t *);
-extern bool console_kcon(void);
-
-extern void console_flush(console_ctrl_t *);
-extern void console_clear(console_ctrl_t *);
-
-extern errno_t console_get_size(console_ctrl_t *, sysarg_t *, sysarg_t *);
-extern errno_t console_get_pos(console_ctrl_t *, sysarg_t *, sysarg_t *);
-extern void console_set_pos(console_ctrl_t *, sysarg_t, sysarg_t);
-
-extern void console_set_style(console_ctrl_t *, uint8_t);
-extern void console_set_color(console_ctrl_t *, uint8_t, uint8_t, uint8_t);
-extern void console_set_rgb_color(console_ctrl_t *, uint32_t, uint32_t);
-
-extern void console_cursor_visibility(console_ctrl_t *, bool);
-extern errno_t console_set_caption(console_ctrl_t *, const char *);
-extern errno_t console_get_color_cap(console_ctrl_t *, sysarg_t *);
-extern errno_t console_get_event(console_ctrl_t *, cons_event_t *);
-extern errno_t console_get_event_timeout(console_ctrl_t *, cons_event_t *,
-    usec_t *);
-extern errno_t console_map(console_ctrl_t *, sysarg_t, sysarg_t,
-    charfield_t **);
-extern void console_unmap(console_ctrl_t *, charfield_t *);
-extern errno_t console_update(console_ctrl_t *, sysarg_t, sysarg_t, sysarg_t,
-    sysarg_t);
-
-#endif
-
-/** @}
- */
Index: uspace/lib/c/include/io/output.h
===================================================================
--- uspace/lib/c/include/io/output.h	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ uspace/lib/c/include/io/output.h	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -38,5 +38,6 @@
 #include <ipc/output.h>
 #include <io/chargrid.h>
-#include <io/console.h>
+#include <io/concaps.h>
+#include <io/style.h>
 
 extern errno_t output_yield(async_sess_t *);
Index: pace/lib/c/include/ipc/console.h
===================================================================
--- uspace/lib/c/include/ipc/console.h	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ 	(revision )
@@ -1,61 +1,0 @@
-/*
- * Copyright (c) 2021 Jiri Svoboda
- * 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 libcipc
- * @{
- */
-/** @file
- */
-
-#ifndef _LIBC_IPC_CONSOLE_H_
-#define _LIBC_IPC_CONSOLE_H_
-
-#include <ipc/vfs.h>
-
-typedef enum {
-	CONSOLE_GET_SIZE = VFS_OUT_LAST,
-	CONSOLE_GET_COLOR_CAP,
-	CONSOLE_GET_EVENT,
-	CONSOLE_GET_POS,
-	CONSOLE_SET_POS,
-	CONSOLE_CLEAR,
-	CONSOLE_SET_STYLE,
-	CONSOLE_SET_COLOR,
-	CONSOLE_SET_RGB_COLOR,
-	CONSOLE_SET_CURSOR_VISIBILITY,
-	CONSOLE_SET_CAPTION,
-	CONSOLE_MAP,
-	CONSOLE_UNMAP,
-	CONSOLE_UPDATE
-} console_request_t;
-
-#endif
-
-/** @}
- */
Index: uspace/lib/c/meson.build
===================================================================
--- uspace/lib/c/meson.build	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ uspace/lib/c/meson.build	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -115,6 +115,4 @@
 	'generic/io/vprintf.c',
 	'generic/io/vsnprintf.c',
-	'generic/io/con_srv.c',
-	'generic/io/console.c',
 	'generic/io/table.c',
 	'generic/irq.c',
Index: uspace/lib/clui/meson.build
===================================================================
--- uspace/lib/clui/meson.build	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ uspace/lib/clui/meson.build	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -27,5 +27,5 @@
 #
 
-deps = [ 'clipboard' ]
+deps = [ 'clipboard', 'console' ]
 src = files(
 	'nchoice.c',
Index: uspace/lib/congfx/meson.build
===================================================================
--- uspace/lib/congfx/meson.build	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ uspace/lib/congfx/meson.build	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -27,5 +27,5 @@
 #
 
-deps = [ 'gfx' ]
+deps = [ 'gfx', 'console' ]
 src = files(
 	'src/console.c',
Index: uspace/lib/console/include/io/con_srv.h
===================================================================
--- uspace/lib/console/include/io/con_srv.h	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
+++ uspace/lib/console/include/io/con_srv.h	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2023 Jiri Svoboda
+ * 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 libconsole
+ * @{
+ */
+/** @file
+ */
+
+#ifndef _LIBCONSOLE_IO_CON_SRV_H_
+#define _LIBCONSOLE_IO_CON_SRV_H_
+
+#include <adt/list.h>
+#include <async.h>
+#include <fibril_synch.h>
+#include <io/charfield.h>
+#include <io/color.h>
+#include <io/concaps.h>
+#include <io/cons_event.h>
+#include <io/pixel.h>
+#include <io/style.h>
+#include <stdbool.h>
+#include <time.h>
+#include <stddef.h>
+
+typedef struct con_ops con_ops_t;
+
+#define CON_CAPTION_MAXLEN 255
+
+/** Service setup (per sevice) */
+typedef struct {
+	con_ops_t *ops;
+	void *sarg;
+	/** Period to check for abort */
+	usec_t abort_timeout;
+	bool aborted;
+} con_srvs_t;
+
+/** Server structure (per client session) */
+typedef struct {
+	con_srvs_t *srvs;
+	async_sess_t *client_sess;
+	void *carg;
+} con_srv_t;
+
+struct con_ops {
+	errno_t (*open)(con_srvs_t *, con_srv_t *);
+	errno_t (*close)(con_srv_t *);
+	errno_t (*read)(con_srv_t *, void *, size_t, size_t *);
+	errno_t (*write)(con_srv_t *, void *, size_t, size_t *);
+	void (*sync)(con_srv_t *);
+	void (*clear)(con_srv_t *);
+	void (*set_pos)(con_srv_t *, sysarg_t col, sysarg_t row);
+	errno_t (*get_pos)(con_srv_t *, sysarg_t *, sysarg_t *);
+	errno_t (*get_size)(con_srv_t *, sysarg_t *, sysarg_t *);
+	errno_t (*get_color_cap)(con_srv_t *, console_caps_t *);
+	void (*set_style)(con_srv_t *, console_style_t);
+	void (*set_color)(con_srv_t *, console_color_t, console_color_t,
+	    console_color_attr_t);
+	void (*set_rgb_color)(con_srv_t *, pixel_t, pixel_t);
+	void (*set_cursor_visibility)(con_srv_t *, bool);
+	errno_t (*set_caption)(con_srv_t *, const char *);
+	errno_t (*get_event)(con_srv_t *, cons_event_t *);
+	errno_t (*map)(con_srv_t *, sysarg_t, sysarg_t, charfield_t **);
+	void (*unmap)(con_srv_t *);
+	void (*update)(con_srv_t *, sysarg_t, sysarg_t, sysarg_t, sysarg_t);
+};
+
+extern void con_srvs_init(con_srvs_t *);
+
+extern errno_t con_conn(ipc_call_t *, con_srvs_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/console/include/io/cons_event.h
===================================================================
--- uspace/lib/console/include/io/cons_event.h	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
+++ uspace/lib/console/include/io/cons_event.h	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2023 Jiri Svoboda
+ * 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 libconsole
+ * @{
+ */
+/** @file
+ */
+
+#ifndef _LIBCONSOLE_IO_CONS_EVENT_H_
+#define _LIBCONSOLE_IO_CONS_EVENT_H_
+
+#include <adt/list.h>
+#include <io/kbd_event.h>
+#include <io/pos_event.h>
+
+typedef enum {
+	/** Key event */
+	CEV_KEY,
+	/** Position event */
+	CEV_POS
+} cons_event_type_t;
+
+/** Console event structure. */
+typedef struct {
+	/** List handle */
+	link_t link;
+
+	/** Event type */
+	cons_event_type_t type;
+
+	union {
+		kbd_event_t key;
+		pos_event_t pos;
+	} ev;
+} cons_event_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/console/include/io/console.h
===================================================================
--- uspace/lib/console/include/io/console.h	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
+++ uspace/lib/console/include/io/console.h	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2023 Jiri Svoboda
+ * 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 libconsole
+ * @{
+ */
+/** @file
+ */
+
+#ifndef _LIBCONSOLE_IO_CONSOLE_H_
+#define _LIBCONSOLE_IO_CONSOLE_H_
+
+#include <time.h>
+#include <io/charfield.h>
+#include <io/concaps.h>
+#include <io/kbd_event.h>
+#include <io/cons_event.h>
+#include <io/keycode.h>
+#include <async.h>
+#include <stdbool.h>
+#include <stdio.h>
+
+/** Console control structure. */
+typedef struct {
+	/** Console input file */
+	FILE *input;
+
+	/** Console output file */
+	FILE *output;
+
+	/** Console input session */
+	async_sess_t *input_sess;
+
+	/** Console output session */
+	async_sess_t *output_sess;
+
+	/** Input request call with timeout */
+	ipc_call_t input_call;
+
+	/** Input response with timeout */
+	aid_t input_aid;
+} console_ctrl_t;
+
+extern console_ctrl_t *console_init(FILE *, FILE *);
+extern void console_done(console_ctrl_t *);
+extern bool console_kcon(void);
+
+extern void console_flush(console_ctrl_t *);
+extern void console_clear(console_ctrl_t *);
+
+extern errno_t console_get_size(console_ctrl_t *, sysarg_t *, sysarg_t *);
+extern errno_t console_get_pos(console_ctrl_t *, sysarg_t *, sysarg_t *);
+extern void console_set_pos(console_ctrl_t *, sysarg_t, sysarg_t);
+
+extern void console_set_style(console_ctrl_t *, uint8_t);
+extern void console_set_color(console_ctrl_t *, uint8_t, uint8_t, uint8_t);
+extern void console_set_rgb_color(console_ctrl_t *, uint32_t, uint32_t);
+
+extern void console_cursor_visibility(console_ctrl_t *, bool);
+extern errno_t console_set_caption(console_ctrl_t *, const char *);
+extern errno_t console_get_color_cap(console_ctrl_t *, sysarg_t *);
+extern errno_t console_get_event(console_ctrl_t *, cons_event_t *);
+extern errno_t console_get_event_timeout(console_ctrl_t *, cons_event_t *,
+    usec_t *);
+extern errno_t console_map(console_ctrl_t *, sysarg_t, sysarg_t,
+    charfield_t **);
+extern void console_unmap(console_ctrl_t *, charfield_t *);
+extern errno_t console_update(console_ctrl_t *, sysarg_t, sysarg_t, sysarg_t,
+    sysarg_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/console/include/ipc/console.h
===================================================================
--- uspace/lib/console/include/ipc/console.h	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
+++ uspace/lib/console/include/ipc/console.h	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2023 Jiri Svoboda
+ * 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 libconsole
+ * @{
+ */
+/** @file
+ */
+
+#ifndef _LIBCONSOLE_IPC_CONSOLE_H_
+#define _LIBCONSOLE_IPC_CONSOLE_H_
+
+#include <ipc/vfs.h>
+
+typedef enum {
+	CONSOLE_GET_SIZE = VFS_OUT_LAST,
+	CONSOLE_GET_COLOR_CAP,
+	CONSOLE_GET_EVENT,
+	CONSOLE_GET_POS,
+	CONSOLE_SET_POS,
+	CONSOLE_CLEAR,
+	CONSOLE_SET_STYLE,
+	CONSOLE_SET_COLOR,
+	CONSOLE_SET_RGB_COLOR,
+	CONSOLE_SET_CURSOR_VISIBILITY,
+	CONSOLE_SET_CAPTION,
+	CONSOLE_MAP,
+	CONSOLE_UNMAP,
+	CONSOLE_UPDATE
+} console_request_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/console/src/con_srv.c
===================================================================
--- uspace/lib/console/src/con_srv.c	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
+++ uspace/lib/console/src/con_srv.c	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -0,0 +1,539 @@
+/*
+ * Copyright (c) 2021 Jiri Svoboda
+ * 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 libconsole
+ * @{
+ */
+/**
+ * @file
+ * @brief Console protocol server stub
+ */
+#include <as.h>
+#include <errno.h>
+#include <io/cons_event.h>
+#include <ipc/console.h>
+#include <stdlib.h>
+#include <stddef.h>
+
+#include <io/con_srv.h>
+
+static errno_t console_ev_encode(cons_event_t *event, ipc_call_t *icall)
+{
+	ipc_set_arg1(icall, event->type);
+
+	switch (event->type) {
+	case CEV_KEY:
+		ipc_set_arg2(icall, event->ev.key.type);
+		ipc_set_arg3(icall, event->ev.key.key);
+		ipc_set_arg4(icall, event->ev.key.mods);
+		ipc_set_arg5(icall, event->ev.key.c);
+		break;
+	case CEV_POS:
+		ipc_set_arg2(icall, (event->ev.pos.pos_id << 16) | (event->ev.pos.type & 0xffff));
+		ipc_set_arg3(icall, event->ev.pos.btn_num);
+		ipc_set_arg4(icall, event->ev.pos.hpos);
+		ipc_set_arg5(icall, event->ev.pos.vpos);
+		break;
+	default:
+		return EIO;
+	}
+
+	return EOK;
+}
+
+static void con_read_srv(con_srv_t *srv, ipc_call_t *icall)
+{
+	void *buf;
+	size_t size;
+	errno_t rc;
+
+	ipc_call_t call;
+	if (!async_data_read_receive(&call, &size)) {
+		async_answer_0(icall, EINVAL);
+		return;
+	}
+
+	buf = malloc(size);
+	if (buf == NULL) {
+		async_answer_0(&call, ENOMEM);
+		async_answer_0(icall, ENOMEM);
+		return;
+	}
+
+	if (srv->srvs->ops->read == NULL) {
+		async_answer_0(&call, ENOTSUP);
+		async_answer_0(icall, ENOTSUP);
+		free(buf);
+		return;
+	}
+
+	size_t nread;
+	rc = srv->srvs->ops->read(srv, buf, size, &nread);
+	if (rc != EOK) {
+		async_answer_0(&call, rc);
+		async_answer_0(icall, rc);
+		free(buf);
+		return;
+	}
+
+	async_data_read_finalize(&call, buf, nread);
+	free(buf);
+
+	async_answer_1(icall, EOK, nread);
+}
+
+static void con_write_srv(con_srv_t *srv, ipc_call_t *icall)
+{
+	void *data;
+	size_t size;
+	errno_t rc;
+
+	rc = async_data_write_accept(&data, false, 0, 0, 0, &size);
+	if (rc != EOK) {
+		async_answer_0(icall, rc);
+		return;
+	}
+
+	if (srv->srvs->ops->write == NULL) {
+		async_answer_0(icall, ENOTSUP);
+		return;
+	}
+
+	size_t nwritten = 0;
+	rc = srv->srvs->ops->write(srv, data, size, &nwritten);
+	free(data);
+
+	async_answer_1(icall, rc, nwritten);
+}
+
+static void con_sync_srv(con_srv_t *srv, ipc_call_t *icall)
+{
+	if (srv->srvs->ops->sync == NULL) {
+		async_answer_0(icall, ENOTSUP);
+		return;
+	}
+
+	srv->srvs->ops->sync(srv);
+	async_answer_0(icall, EOK);
+}
+
+static void con_clear_srv(con_srv_t *srv, ipc_call_t *icall)
+{
+	if (srv->srvs->ops->clear == NULL) {
+		async_answer_0(icall, ENOTSUP);
+		return;
+	}
+
+	srv->srvs->ops->clear(srv);
+	async_answer_0(icall, EOK);
+}
+
+static void con_set_pos_srv(con_srv_t *srv, ipc_call_t *icall)
+{
+	sysarg_t col;
+	sysarg_t row;
+
+	col = ipc_get_arg1(icall);
+	row = ipc_get_arg2(icall);
+
+	if (srv->srvs->ops->set_pos == NULL) {
+		async_answer_0(icall, ENOTSUP);
+		return;
+	}
+
+	srv->srvs->ops->set_pos(srv, col, row);
+	async_answer_0(icall, EOK);
+}
+
+static void con_get_pos_srv(con_srv_t *srv, ipc_call_t *icall)
+{
+	errno_t rc;
+	sysarg_t col;
+	sysarg_t row;
+
+	if (srv->srvs->ops->get_pos == NULL) {
+		async_answer_0(icall, ENOTSUP);
+		return;
+	}
+
+	rc = srv->srvs->ops->get_pos(srv, &col, &row);
+	async_answer_2(icall, rc, col, row);
+}
+
+static void con_get_size_srv(con_srv_t *srv, ipc_call_t *icall)
+{
+	errno_t rc;
+	sysarg_t cols;
+	sysarg_t rows;
+
+	if (srv->srvs->ops->get_size == NULL) {
+		async_answer_0(icall, ENOTSUP);
+		return;
+	}
+
+	rc = srv->srvs->ops->get_size(srv, &cols, &rows);
+	async_answer_2(icall, rc, cols, rows);
+}
+
+static void con_get_color_cap_srv(con_srv_t *srv, ipc_call_t *icall)
+{
+	errno_t rc;
+	console_caps_t ccap;
+
+	if (srv->srvs->ops->get_color_cap == NULL) {
+		async_answer_0(icall, ENOTSUP);
+		return;
+	}
+
+	rc = srv->srvs->ops->get_color_cap(srv, &ccap);
+	async_answer_1(icall, rc, (sysarg_t)ccap);
+}
+
+static void con_set_style_srv(con_srv_t *srv, ipc_call_t *icall)
+{
+	console_style_t style;
+
+	style = ipc_get_arg1(icall);
+
+	if (srv->srvs->ops->set_style == NULL) {
+		async_answer_0(icall, ENOTSUP);
+		return;
+	}
+
+	srv->srvs->ops->set_style(srv, style);
+	async_answer_0(icall, EOK);
+}
+
+static void con_set_color_srv(con_srv_t *srv, ipc_call_t *icall)
+{
+	console_color_t bgcolor;
+	console_color_t fgcolor;
+	console_color_attr_t flags;
+
+	bgcolor = ipc_get_arg1(icall);
+	fgcolor = ipc_get_arg2(icall);
+	flags = ipc_get_arg3(icall);
+
+	if (srv->srvs->ops->set_color == NULL) {
+		async_answer_0(icall, ENOTSUP);
+		return;
+	}
+
+	srv->srvs->ops->set_color(srv, bgcolor, fgcolor, flags);
+	async_answer_0(icall, EOK);
+}
+
+static void con_set_rgb_color_srv(con_srv_t *srv, ipc_call_t *icall)
+{
+	pixel_t bgcolor;
+	pixel_t fgcolor;
+
+	bgcolor = ipc_get_arg1(icall);
+	fgcolor = ipc_get_arg2(icall);
+
+	if (srv->srvs->ops->set_rgb_color == NULL) {
+		async_answer_0(icall, ENOTSUP);
+		return;
+	}
+
+	srv->srvs->ops->set_rgb_color(srv, bgcolor, fgcolor);
+	async_answer_0(icall, EOK);
+}
+
+static void con_set_cursor_visibility_srv(con_srv_t *srv, ipc_call_t *icall)
+{
+	bool show;
+
+	show = ipc_get_arg1(icall);
+
+	if (srv->srvs->ops->set_cursor_visibility == NULL) {
+		async_answer_0(icall, ENOTSUP);
+		return;
+	}
+
+	srv->srvs->ops->set_cursor_visibility(srv, show);
+	async_answer_0(icall, EOK);
+}
+
+static void con_set_caption_srv(con_srv_t *srv, ipc_call_t *icall)
+{
+	char *caption;
+	errno_t rc;
+
+	rc = async_data_write_accept((void **) &caption, true, 0,
+	    CON_CAPTION_MAXLEN, 0, NULL);
+	if (rc != EOK) {
+		async_answer_0(icall, rc);
+		return;
+	}
+
+	if (srv->srvs->ops->set_caption == NULL) {
+		async_answer_0(icall, ENOTSUP);
+		return;
+	}
+
+	srv->srvs->ops->set_caption(srv, caption);
+	free(caption);
+	async_answer_0(icall, EOK);
+}
+
+static void con_get_event_srv(con_srv_t *srv, ipc_call_t *icall)
+{
+	errno_t rc;
+	cons_event_t event;
+	ipc_call_t result;
+
+	if (srv->srvs->ops->get_event == NULL) {
+		async_answer_0(icall, ENOTSUP);
+		return;
+	}
+
+	rc = srv->srvs->ops->get_event(srv, &event);
+	if (rc != EOK) {
+		async_answer_0(icall, rc);
+		return;
+	}
+
+	rc = console_ev_encode(&event, &result);
+	if (rc != EOK) {
+		async_answer_0(icall, rc);
+		return;
+	}
+
+	async_answer_5(icall, rc, ipc_get_arg1(&result), ipc_get_arg2(&result),
+	    ipc_get_arg3(&result), ipc_get_arg4(&result), ipc_get_arg5(&result));
+}
+
+/** Create shared buffer for efficient rendering */
+static void con_map_srv(con_srv_t *srv, ipc_call_t *icall)
+{
+	errno_t rc;
+	charfield_t *buf;
+	sysarg_t cols, rows;
+	ipc_call_t call;
+	size_t size;
+
+	if (srv->srvs->ops->map == NULL || srv->srvs->ops->unmap == NULL) {
+		async_answer_0(icall, ENOTSUP);
+		return;
+	}
+
+	cols = ipc_get_arg1(icall);
+	rows = ipc_get_arg2(icall);
+
+	if (!async_share_in_receive(&call, &size)) {
+		async_answer_0(icall, EINVAL);
+		return;
+	}
+
+	/* Check size */
+	if (size != PAGES2SIZE(SIZE2PAGES(cols * rows * sizeof(charfield_t)))) {
+		async_answer_0(&call, EINVAL);
+		async_answer_0(icall, EINVAL);
+		return;
+	}
+
+	rc = srv->srvs->ops->map(srv, cols, rows, &buf);
+	if (rc != EOK) {
+		async_answer_0(&call, rc);
+		async_answer_0(icall, rc);
+		return;
+	}
+
+	rc = async_share_in_finalize(&call, buf, AS_AREA_READ |
+	    AS_AREA_WRITE | AS_AREA_CACHEABLE);
+	if (rc != EOK) {
+		srv->srvs->ops->unmap(srv);
+		async_answer_0(icall, EIO);
+		return;
+	}
+
+	async_answer_0(icall, EOK);
+}
+
+/** Delete shared buffer */
+static void con_unmap_srv(con_srv_t *srv, ipc_call_t *icall)
+{
+	if (srv->srvs->ops->unmap == NULL) {
+		async_answer_0(icall, ENOTSUP);
+		return;
+	}
+
+	srv->srvs->ops->unmap(srv);
+	async_answer_0(icall, EOK);
+}
+
+/** Update console area from shared buffer */
+static void con_update_srv(con_srv_t *srv, ipc_call_t *icall)
+{
+	sysarg_t c0, r0, c1, r1;
+
+	c0 = ipc_get_arg1(icall);
+	r0 = ipc_get_arg2(icall);
+	c1 = ipc_get_arg3(icall);
+	r1 = ipc_get_arg4(icall);
+
+	if (srv->srvs->ops->update == NULL) {
+		async_answer_0(icall, ENOTSUP);
+		return;
+	}
+
+	srv->srvs->ops->update(srv, c0, r0, c1, r1);
+	async_answer_0(icall, EOK);
+}
+
+static con_srv_t *con_srv_create(con_srvs_t *srvs)
+{
+	con_srv_t *srv;
+
+	srv = calloc(1, sizeof(*srv));
+	if (srv == NULL)
+		return NULL;
+
+	srv->srvs = srvs;
+	return srv;
+}
+
+void con_srvs_init(con_srvs_t *srvs)
+{
+	srvs->ops = NULL;
+	srvs->sarg = NULL;
+	srvs->abort_timeout = 0;
+	srvs->aborted = false;
+}
+
+errno_t con_conn(ipc_call_t *icall, con_srvs_t *srvs)
+{
+	con_srv_t *srv;
+	errno_t rc;
+
+	/* Accept the connection */
+	async_accept_0(icall);
+
+	srv = con_srv_create(srvs);
+	if (srv == NULL)
+		return ENOMEM;
+
+	srv->client_sess = NULL;
+
+	rc = srvs->ops->open(srvs, srv);
+	if (rc != EOK)
+		return rc;
+
+	while (true) {
+		ipc_call_t call;
+		bool received = false;
+
+		while (!received) {
+			/* XXX Need to be able to abort immediately */
+			received = async_get_call_timeout(&call,
+			    srvs->abort_timeout);
+
+			if (srv->srvs->aborted) {
+				if (received)
+					async_answer_0(&call, EINTR);
+				break;
+			}
+		}
+
+		if (!received)
+			break;
+
+		sysarg_t method = ipc_get_imethod(&call);
+
+		if (!method) {
+			/* The other side has hung up */
+			async_answer_0(&call, EOK);
+			break;
+		}
+
+		switch (method) {
+		case VFS_OUT_READ:
+			con_read_srv(srv, &call);
+			break;
+		case VFS_OUT_WRITE:
+			con_write_srv(srv, &call);
+			break;
+		case VFS_OUT_SYNC:
+			con_sync_srv(srv, &call);
+			break;
+		case CONSOLE_CLEAR:
+			con_clear_srv(srv, &call);
+			break;
+		case CONSOLE_SET_POS:
+			con_set_pos_srv(srv, &call);
+			break;
+		case CONSOLE_GET_POS:
+			con_get_pos_srv(srv, &call);
+			break;
+		case CONSOLE_GET_SIZE:
+			con_get_size_srv(srv, &call);
+			break;
+		case CONSOLE_GET_COLOR_CAP:
+			con_get_color_cap_srv(srv, &call);
+			break;
+		case CONSOLE_SET_STYLE:
+			con_set_style_srv(srv, &call);
+			break;
+		case CONSOLE_SET_COLOR:
+			con_set_color_srv(srv, &call);
+			break;
+		case CONSOLE_SET_RGB_COLOR:
+			con_set_rgb_color_srv(srv, &call);
+			break;
+		case CONSOLE_SET_CURSOR_VISIBILITY:
+			con_set_cursor_visibility_srv(srv, &call);
+			break;
+		case CONSOLE_SET_CAPTION:
+			con_set_caption_srv(srv, &call);
+			break;
+		case CONSOLE_GET_EVENT:
+			con_get_event_srv(srv, &call);
+			break;
+		case CONSOLE_MAP:
+			con_map_srv(srv, &call);
+			break;
+		case CONSOLE_UNMAP:
+			con_unmap_srv(srv, &call);
+			break;
+		case CONSOLE_UPDATE:
+			con_update_srv(srv, &call);
+			break;
+		default:
+			async_answer_0(&call, ENOTSUP);
+		}
+	}
+
+	rc = srvs->ops->close(srv);
+	free(srv);
+
+	return rc;
+}
+
+/** @}
+ */
Index: uspace/lib/console/src/console.c
===================================================================
--- uspace/lib/console/src/console.c	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
+++ uspace/lib/console/src/console.c	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -0,0 +1,378 @@
+/*
+ * Copyright (c) 2021 Jiri Svoboda
+ * Copyright (c) 2006 Josef Cejka
+ * Copyright (c) 2006 Jakub Vana
+ * 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 libconsole
+ * @{
+ */
+/** @file
+ */
+
+#include <as.h>
+#include <libc.h>
+#include <async.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <str.h>
+#include <vfs/vfs_sess.h>
+#include <io/console.h>
+#include <ipc/console.h>
+
+console_ctrl_t *console_init(FILE *ifile, FILE *ofile)
+{
+	console_ctrl_t *ctrl = malloc(sizeof(console_ctrl_t));
+	if (!ctrl)
+		return NULL;
+
+	ctrl->input_sess = vfs_fsession(ifile, INTERFACE_CONSOLE);
+	if (!ctrl->input_sess) {
+		free(ctrl);
+		return NULL;
+	}
+
+	ctrl->output_sess = vfs_fsession(ofile, INTERFACE_CONSOLE);
+	if (!ctrl->output_sess) {
+		free(ctrl);
+		return NULL;
+	}
+
+	ctrl->input = ifile;
+	ctrl->output = ofile;
+	ctrl->input_aid = 0;
+
+	return ctrl;
+}
+
+void console_done(console_ctrl_t *ctrl)
+{
+	free(ctrl);
+}
+
+bool console_kcon(void)
+{
+	return __SYSCALL0(SYS_DEBUG_CONSOLE);
+}
+
+void console_flush(console_ctrl_t *ctrl)
+{
+	fflush(ctrl->output);
+}
+
+void console_clear(console_ctrl_t *ctrl)
+{
+	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
+	async_req_0_0(exch, CONSOLE_CLEAR);
+	async_exchange_end(exch);
+}
+
+errno_t console_get_size(console_ctrl_t *ctrl, sysarg_t *cols, sysarg_t *rows)
+{
+	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
+	errno_t rc = async_req_0_2(exch, CONSOLE_GET_SIZE, cols, rows);
+	async_exchange_end(exch);
+
+	return rc;
+}
+
+void console_set_style(console_ctrl_t *ctrl, uint8_t style)
+{
+	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
+	async_req_1_0(exch, CONSOLE_SET_STYLE, style);
+	async_exchange_end(exch);
+}
+
+void console_set_color(console_ctrl_t *ctrl, uint8_t bgcolor, uint8_t fgcolor,
+    uint8_t flags)
+{
+	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
+	async_req_3_0(exch, CONSOLE_SET_COLOR, bgcolor, fgcolor, flags);
+	async_exchange_end(exch);
+}
+
+void console_set_rgb_color(console_ctrl_t *ctrl, uint32_t bgcolor,
+    uint32_t fgcolor)
+{
+	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
+	async_req_2_0(exch, CONSOLE_SET_RGB_COLOR, bgcolor, fgcolor);
+	async_exchange_end(exch);
+}
+
+void console_cursor_visibility(console_ctrl_t *ctrl, bool show)
+{
+	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
+	async_req_1_0(exch, CONSOLE_SET_CURSOR_VISIBILITY, (show != false));
+	async_exchange_end(exch);
+}
+
+/** Set console caption.
+ *
+ * Set caption text for the console (if the console suports captions).
+ *
+ * @param ctrl Console
+ * @param caption Caption text
+ * @return EOK on success or an error code
+ */
+errno_t console_set_caption(console_ctrl_t *ctrl, const char *caption)
+{
+	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
+	ipc_call_t answer;
+	aid_t req = async_send_0(exch, CONSOLE_SET_CAPTION, &answer);
+	errno_t retval = async_data_write_start(exch, caption, str_size(caption));
+
+	if (retval != EOK) {
+		async_forget(req);
+		async_exchange_end(exch);
+		return retval;
+	}
+
+	async_wait_for(req, &retval);
+	async_exchange_end(exch);
+	return EOK;
+}
+
+errno_t console_get_color_cap(console_ctrl_t *ctrl, sysarg_t *ccap)
+{
+	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
+	errno_t rc = async_req_0_1(exch, CONSOLE_GET_COLOR_CAP, ccap);
+	async_exchange_end(exch);
+
+	return rc;
+}
+
+errno_t console_get_pos(console_ctrl_t *ctrl, sysarg_t *col, sysarg_t *row)
+{
+	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
+	errno_t rc = async_req_0_2(exch, CONSOLE_GET_POS, col, row);
+	async_exchange_end(exch);
+
+	return rc;
+}
+
+void console_set_pos(console_ctrl_t *ctrl, sysarg_t col, sysarg_t row)
+{
+	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
+	async_req_2_0(exch, CONSOLE_SET_POS, col, row);
+	async_exchange_end(exch);
+}
+
+static errno_t console_ev_decode(ipc_call_t *call, cons_event_t *event)
+{
+	event->type = ipc_get_arg1(call);
+
+	switch (event->type) {
+	case CEV_KEY:
+		event->ev.key.type = ipc_get_arg2(call);
+		event->ev.key.key = ipc_get_arg3(call);
+		event->ev.key.mods = ipc_get_arg4(call);
+		event->ev.key.c = ipc_get_arg5(call);
+		break;
+	case CEV_POS:
+		event->ev.pos.pos_id = ipc_get_arg2(call) >> 16;
+		event->ev.pos.type = ipc_get_arg2(call) & 0xffff;
+		event->ev.pos.btn_num = ipc_get_arg3(call);
+		event->ev.pos.hpos = ipc_get_arg4(call);
+		event->ev.pos.vpos = ipc_get_arg5(call);
+		break;
+	default:
+		return EIO;
+	}
+
+	return EOK;
+}
+
+/** Get console event.
+ *
+ * @param ctrl Console
+ * @param event Place to store event
+ * @return EOK on success, EIO on failure
+ */
+errno_t console_get_event(console_ctrl_t *ctrl, cons_event_t *event)
+{
+	if (ctrl->input_aid == 0) {
+		ipc_call_t result;
+
+		async_exch_t *exch = async_exchange_begin(ctrl->input_sess);
+		aid_t aid = async_send_0(exch, CONSOLE_GET_EVENT, &result);
+		async_exchange_end(exch);
+
+		errno_t rc;
+		async_wait_for(aid, &rc);
+
+		if (rc != EOK)
+			return EIO;
+
+		rc = console_ev_decode(&result, event);
+		if (rc != EOK)
+			return EIO;
+	} else {
+		errno_t retval;
+		async_wait_for(ctrl->input_aid, &retval);
+
+		ctrl->input_aid = 0;
+
+		if (retval != EOK)
+			return EIO;
+
+		errno_t rc = console_ev_decode(&ctrl->input_call, event);
+		if (rc != EOK)
+			return EIO;
+	}
+
+	return EOK;
+}
+
+/** Get console event with timeout.
+ *
+ * @param ctrl Console
+ * @param event Place to store event
+ * @param timeout Pointer to timeout. This will be updated to reflect
+ *                the remaining time in case of timeout.
+ * @return EOK on success (event received), ETIMEOUT on time out,
+ *         EIO on I/O error (e.g. lost console connection), ENOMEM
+ *         if out of memory
+ */
+errno_t console_get_event_timeout(console_ctrl_t *ctrl, cons_event_t *event,
+    usec_t *timeout)
+{
+	struct timespec t0;
+	getuptime(&t0);
+
+	if (ctrl->input_aid == 0) {
+		async_exch_t *exch = async_exchange_begin(ctrl->input_sess);
+		ctrl->input_aid = async_send_0(exch, CONSOLE_GET_EVENT,
+		    &ctrl->input_call);
+		async_exchange_end(exch);
+	}
+
+	errno_t retval;
+	errno_t rc = async_wait_timeout(ctrl->input_aid, &retval, *timeout);
+	if (rc != EOK) {
+		if (rc == ENOMEM)
+			return ENOMEM;
+		*timeout = 0;
+		return ETIMEOUT;
+	}
+
+	ctrl->input_aid = 0;
+
+	if (retval != EOK)
+		return EIO;
+
+	rc = console_ev_decode(&ctrl->input_call, event);
+	if (rc != EOK)
+		return EIO;
+
+	/* Update timeout */
+	struct timespec t1;
+	getuptime(&t1);
+	*timeout -= NSEC2USEC(ts_sub_diff(&t1, &t0));
+
+	return EOK;
+}
+
+/** Create a shared buffer for fast rendering to the console.
+ *
+ * @param ctrl Console
+ * @param cols Number of columns
+ * @param rows Number of rows
+ * @param rbuf Place to store pointer to the shared buffer
+ * @return EOK on success or an error code
+ */
+errno_t console_map(console_ctrl_t *ctrl, sysarg_t cols, sysarg_t rows,
+    charfield_t **rbuf)
+{
+	async_exch_t *exch = NULL;
+	void *buf;
+	aid_t req;
+	ipc_call_t answer;
+	size_t asize;
+	errno_t rc;
+
+	exch = async_exchange_begin(ctrl->output_sess);
+	req = async_send_2(exch, CONSOLE_MAP, cols, rows, &answer);
+
+	asize = PAGES2SIZE(SIZE2PAGES(cols * rows * sizeof(charfield_t)));
+
+	rc = async_share_in_start_0_0(exch, asize, &buf);
+	if (rc != EOK) {
+		async_forget(req);
+		goto error;
+	}
+
+	async_exchange_end(exch);
+	exch = NULL;
+
+	async_wait_for(req, &rc);
+	if (rc != EOK)
+		goto error;
+
+	*rbuf = (charfield_t *)buf;
+	return EOK;
+error:
+	if (exch != NULL)
+		async_exchange_end(exch);
+	return rc;
+}
+
+/** Unmap console shared buffer.
+ *
+ * @param ctrl Console
+ * @param buf Buffer
+ */
+void console_unmap(console_ctrl_t *ctrl, charfield_t *buf)
+{
+	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
+	(void) async_req_0_0(exch, CONSOLE_UNMAP);
+	async_exchange_end(exch);
+
+	as_area_destroy(buf);
+}
+
+/** Update console rectangle from shared buffer.
+ *
+ * @param ctrl Console
+ * @param c0 Column coordinate of top-left corner (inclusive)
+ * @param r0 Row coordinate of top-left corner (inclusive)
+ * @param c1 Column coordinate of bottom-right corner (exclusive)
+ * @param r1 Row coordinate of bottom-right corner (exclusive)
+ *
+ * @return EOK on sucess or an error code
+ */
+errno_t console_update(console_ctrl_t *ctrl, sysarg_t c0, sysarg_t r0,
+    sysarg_t c1, sysarg_t r1)
+{
+	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
+	errno_t rc = async_req_4_0(exch, CONSOLE_UPDATE, c0, r0, c1, r1);
+	async_exchange_end(exch);
+
+	return rc;
+}
+
+/** @}
+ */
Index: uspace/lib/fmtutil/meson.build
===================================================================
--- uspace/lib/fmtutil/meson.build	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ uspace/lib/fmtutil/meson.build	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -27,3 +27,4 @@
 #
 
+deps = [ 'console' ]
 src = files('fmtutil.c')
Index: uspace/lib/meson.build
===================================================================
--- uspace/lib/meson.build	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ uspace/lib/meson.build	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -53,4 +53,5 @@
 	'inet',
 
+	'console',
 	'device',
 
Index: uspace/srv/hid/console/console.c
===================================================================
--- uspace/srv/hid/console/console.c	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ uspace/srv/hid/console/console.c	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -37,4 +37,5 @@
 #include <stdio.h>
 #include <adt/prodcons.h>
+#include <io/console.h>
 #include <io/input.h>
 #include <ipc/vfs.h>
Index: uspace/srv/hid/console/meson.build
===================================================================
--- uspace/srv/hid/console/meson.build	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ uspace/srv/hid/console/meson.build	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -28,3 +28,4 @@
 #
 
+deps = [ 'console' ]
 src = files('console.c')
Index: uspace/srv/hid/input/meson.build
===================================================================
--- uspace/srv/hid/input/meson.build	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ uspace/srv/hid/input/meson.build	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -28,5 +28,5 @@
 #
 
-deps = [ 'drv' ]
+deps = [ 'drv', 'console' ]
 src = files(
 	'layout/cz.c',
Index: uspace/srv/hid/output/meson.build
===================================================================
--- uspace/srv/hid/output/meson.build	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ uspace/srv/hid/output/meson.build	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -28,5 +28,5 @@
 #
 
-deps = [ 'codepage', 'drv', 'fbfont', 'pixconv', 'ddev' ]
+deps = [ 'codepage', 'console', 'drv', 'fbfont', 'pixconv', 'ddev' ]
 src = files(
 	'ctl/serial.c',
Index: uspace/srv/hid/remcons/meson.build
===================================================================
--- uspace/srv/hid/remcons/meson.build	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ uspace/srv/hid/remcons/meson.build	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -28,4 +28,4 @@
 #
 
-deps = [ 'inet' ]
+deps = [ 'inet', 'console' ]
 src = files('remcons.c', 'user.c')
Index: uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.c
===================================================================
--- uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.c	(revision cad7b7e39ca70d44e5a6c1bbca2a247c8ce1010d)
+++ uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.c	(revision a635535739c9e7901c0b9b5b1890f38965383f17)
@@ -39,5 +39,4 @@
 #include <ddi.h>
 #include <loc.h>
-#include <io/console.h>
 #include <vfs/vfs.h>
 #include <ipc/mouseev.h>
