Index: uspace/srv/hid/console/console.c
===================================================================
--- uspace/srv/hid/console/console.c	(revision d17a4a9b9b7d8b1ef841975044255958f61fbacc)
+++ uspace/srv/hid/console/console.c	(revision d6cd626db59cf8f2784e8800dfdb1dd6e8d2e5ca)
@@ -37,5 +37,4 @@
 #include <adt/prodcons.h>
 #include <io/input.h>
-#include <ipc/console.h>
 #include <ipc/vfs.h>
 #include <errno.h>
@@ -43,8 +42,8 @@
 #include <loc.h>
 #include <event.h>
+#include <io/con_srv.h>
 #include <io/kbd_event.h>
 #include <io/keycode.h>
 #include <io/chargrid.h>
-#include <io/console.h>
 #include <io/output.h>
 #include <align.h>
@@ -80,4 +79,5 @@
 	chargrid_t *frontbuf;    /**< Front buffer */
 	frontbuf_handle_t fbid;  /**< Front buffer handle */
+	con_srvs_t srvs;         /**< Console service setup */
 } console_t;
 
@@ -114,4 +114,44 @@
 };
 
+static int cons_open(con_srvs_t *, con_srv_t *);
+static int cons_close(con_srv_t *);
+static int cons_read(con_srv_t *, void *, size_t);
+static int cons_write(con_srv_t *, void *, size_t);
+static void cons_sync(con_srv_t *);
+static void cons_clear(con_srv_t *);
+static void cons_set_pos(con_srv_t *, sysarg_t col, sysarg_t row);
+static int cons_get_pos(con_srv_t *, sysarg_t *, sysarg_t *);
+static int cons_get_size(con_srv_t *, sysarg_t *, sysarg_t *);
+static int cons_get_color_cap(con_srv_t *, console_caps_t *);
+static void cons_set_style(con_srv_t *, console_style_t);
+static void cons_set_color(con_srv_t *, console_color_t, console_color_t,
+    console_color_attr_t);
+static void cons_set_rgb_color(con_srv_t *, pixel_t, pixel_t);
+static void cons_set_cursor_visibility(con_srv_t *, bool);
+static int cons_get_event(con_srv_t *, kbd_event_t *);
+
+static con_ops_t con_ops = {
+	.open = cons_open,
+	.close = cons_close,
+	.read = cons_read,
+	.write = cons_write,
+	.sync = cons_sync,
+	.clear = cons_clear,
+	.set_pos = cons_set_pos,
+	.get_pos = cons_get_pos,
+	.get_size = cons_get_size,
+	.get_color_cap = cons_get_color_cap,
+	.set_style = cons_set_style,
+	.set_color = cons_set_color,
+	.set_rgb_color = cons_set_rgb_color,
+	.set_cursor_visibility = cons_set_cursor_visibility,
+	.get_event = cons_get_event
+};
+
+static console_t *srv_to_console(con_srv_t *srv)
+{
+	return srv->srvs->sarg;
+}
+
 static void cons_update(console_t *cons)
 {
@@ -138,13 +178,4 @@
 	fibril_mutex_unlock(&cons->mtx);
 	fibril_mutex_unlock(&switch_mtx);
-}
-
-static void cons_clear(console_t *cons)
-{
-	fibril_mutex_lock(&cons->mtx);
-	chargrid_clear(cons->frontbuf);
-	fibril_mutex_unlock(&cons->mtx);
-	
-	cons_update(cons);
 }
 
@@ -288,8 +319,8 @@
 }
 
-static void cons_set_cursor(console_t *cons, sysarg_t col, sysarg_t row)
-{
-	fibril_mutex_lock(&cons->mtx);
-	chargrid_set_cursor(cons->frontbuf, col, row);
+static void cons_set_cursor_vis(console_t *cons, bool visible)
+{
+	fibril_mutex_lock(&cons->mtx);
+	chargrid_set_cursor_visibility(cons->frontbuf, visible);
 	fibril_mutex_unlock(&cons->mtx);
 	
@@ -297,61 +328,18 @@
 }
 
-static void cons_set_cursor_visibility(console_t *cons, bool visible)
-{
-	fibril_mutex_lock(&cons->mtx);
-	chargrid_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);
-	chargrid_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;
-	size_t size;
-	int rc = async_data_write_accept(&buf, false, 0, 0, 0, &size);
-	
-	if (rc != EOK) {
-		async_answer_0(iid, rc);
-		return;
-	}
-	
-	size_t off = 0;
-	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 iid, ipc_call_t *icall)
-{
-	ipc_callid_t callid;
-	size_t size;
-	if (!async_data_read_receive(&callid, &size)) {
-		async_answer_0(callid, EINVAL);
-		async_answer_0(iid, EINVAL);
-		return;
-	}
-	
-	char *buf = (char *) malloc(size);
-	if (buf == NULL) {
-		async_answer_0(callid, ENOMEM);
-		async_answer_0(iid, ENOMEM);
-		return;
-	}
-	
+static int cons_open(con_srvs_t *srvs, con_srv_t *srv)
+{
+	return EOK;
+}
+
+static int cons_close(con_srv_t *srv)
+{
+	return EOK;
+}
+
+static int cons_read(con_srv_t *srv, void *buf, size_t size)
+{
+	uint8_t *bbuf = buf;
+	console_t *cons = srv_to_console(srv);
 	size_t pos = 0;
 	
@@ -364,5 +352,5 @@
 		/* Copy to the buffer remaining characters. */
 		while ((pos < size) && (cons->char_remains_len > 0)) {
-			buf[pos] = cons->char_remains[0];
+			bbuf[pos] = cons->char_remains[0];
 			pos++;
 			
@@ -389,12 +377,85 @@
 		}
 	}
-	
-	(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)
-{
+
+	return size;
+}
+
+static int cons_write(con_srv_t *srv, void *data, size_t size)
+{
+	console_t *cons = srv_to_console(srv);
+
+	size_t off = 0;
+	while (off < size)
+		cons_write_char(cons, str_decode(data, &off, size));
+	return size;
+}
+
+static void cons_sync(con_srv_t *srv)
+{
+	console_t *cons = srv_to_console(srv);
+	
+	cons_update(cons);
+}
+
+static void cons_clear(con_srv_t *srv)
+{
+	console_t *cons = srv_to_console(srv);
+	
+	fibril_mutex_lock(&cons->mtx);
+	chargrid_clear(cons->frontbuf);
+	fibril_mutex_unlock(&cons->mtx);
+	
+	cons_update(cons);
+}
+
+static void cons_set_pos(con_srv_t *srv, sysarg_t col, sysarg_t row)
+{
+	console_t *cons = srv_to_console(srv);
+	
+	fibril_mutex_lock(&cons->mtx);
+	chargrid_set_cursor(cons->frontbuf, col, row);
+	fibril_mutex_unlock(&cons->mtx);
+	
+	cons_update_cursor(cons);
+}
+
+static int cons_get_pos(con_srv_t *srv, sysarg_t *col, sysarg_t *row)
+{
+	console_t *cons = srv_to_console(srv);
+	
+	fibril_mutex_lock(&cons->mtx);
+	chargrid_get_cursor(cons->frontbuf, col, row);
+	fibril_mutex_unlock(&cons->mtx);
+	
+	return EOK;
+}
+
+static int cons_get_size(con_srv_t *srv, sysarg_t *cols, sysarg_t *rows)
+{
+	console_t *cons = srv_to_console(srv);
+	
+	fibril_mutex_lock(&cons->mtx);
+	*cols = cons->cols;
+	*rows = cons->rows;
+	fibril_mutex_unlock(&cons->mtx);
+	
+	return EOK;
+}
+
+static int cons_get_color_cap(con_srv_t *srv, console_caps_t *ccaps)
+{
+	console_t *cons = srv_to_console(srv);
+	
+	fibril_mutex_lock(&cons->mtx);
+	*ccaps = cons->ccaps;
+	fibril_mutex_unlock(&cons->mtx);
+	
+	return EOK;
+}
+
+static void cons_set_style(con_srv_t *srv, console_style_t style)
+{
+	console_t *cons = srv_to_console(srv);
+	
 	fibril_mutex_lock(&cons->mtx);
 	chargrid_set_style(cons->frontbuf, style);
@@ -402,7 +463,9 @@
 }
 
-static void cons_set_color(console_t *cons, console_color_t bgcolor,
+static void cons_set_color(con_srv_t *srv, console_color_t bgcolor,
     console_color_t fgcolor, console_color_attr_t attr)
 {
+	console_t *cons = srv_to_console(srv);
+	
 	fibril_mutex_lock(&cons->mtx);
 	chargrid_set_color(cons->frontbuf, bgcolor, fgcolor, attr);
@@ -410,7 +473,9 @@
 }
 
-static void cons_set_rgb_color(console_t *cons, pixel_t bgcolor,
+static void cons_set_rgb_color(con_srv_t *srv, pixel_t bgcolor,
     pixel_t fgcolor)
 {
+	console_t *cons = srv_to_console(srv);
+	
 	fibril_mutex_lock(&cons->mtx);
 	chargrid_set_rgb_color(cons->frontbuf, bgcolor, fgcolor);
@@ -418,11 +483,20 @@
 }
 
-static void cons_get_event(console_t *cons, ipc_callid_t iid, ipc_call_t *icall)
-{
+static void cons_set_cursor_visibility(con_srv_t *srv, bool visible)
+{
+	console_t *cons = srv_to_console(srv);
+	
+	cons_set_cursor_vis(cons, visible);
+}
+
+static int cons_get_event(con_srv_t *srv, kbd_event_t *event)
+{
+	console_t *cons = srv_to_console(srv);
 	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);
+	kbd_event_t *kevent = list_get_instance(link, kbd_event_t, link);
+	
+	*event = *kevent;
+	free(kevent);
+	return EOK;
 }
 
@@ -447,69 +521,9 @@
 	
 	if (atomic_postinc(&cons->refcnt) == 0)
-		cons_set_cursor_visibility(cons, true);
-	
-	/* Accept the connection */
-	async_answer_0(iid, EOK);
-	
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		if (!IPC_GET_IMETHOD(call))
-			return;
-		
-		switch (IPC_GET_IMETHOD(call)) {
-		case VFS_OUT_READ:
-			cons_read(cons, callid, &call);
-			break;
-		case VFS_OUT_WRITE:
-			cons_write(cons, callid, &call);
-			break;
-		case VFS_OUT_SYNC:
-			cons_update(cons);
-			async_answer_0(callid, EOK);
-			break;
-		case CONSOLE_CLEAR:
-			cons_clear(cons);
-			async_answer_0(callid, EOK);
-			break;
-		case CONSOLE_GOTO:
-			cons_set_cursor(cons, IPC_GET_ARG1(call), IPC_GET_ARG2(call));
-			async_answer_0(callid, EOK);
-			break;
-		case CONSOLE_GET_POS:
-			cons_get_cursor(cons, callid, &call);
-			break;
-		case CONSOLE_GET_SIZE:
-			async_answer_2(callid, EOK, cons->cols, cons->rows);
-			break;
-		case CONSOLE_GET_COLOR_CAP:
-			async_answer_1(callid, EOK, cons->ccaps);
-			break;
-		case CONSOLE_SET_STYLE:
-			cons_set_style(cons, IPC_GET_ARG1(call));
-			async_answer_0(callid, EOK);
-			break;
-		case CONSOLE_SET_COLOR:
-			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:
-			cons_set_rgb_color(cons, IPC_GET_ARG1(call), IPC_GET_ARG2(call));
-			async_answer_0(callid, EOK);
-			break;
-		case CONSOLE_CURSOR_VISIBILITY:
-			cons_set_cursor_visibility(cons, IPC_GET_ARG1(call));
-			async_answer_0(callid, EOK);
-			break;
-		case CONSOLE_GET_EVENT:
-			cons_get_event(cons, callid, &call);
-			break;
-		default:
-			async_answer_0(callid, EINVAL);
-		}
-	}
-}
+		cons_set_cursor_vis(cons, true);
+	
+	con_conn(iid, icall, &cons->srvs);
+}
+
 
 static int input_connect(const char *svc)
@@ -624,4 +638,8 @@
 		}
 		
+		con_srvs_init(&consoles[i].srvs);
+		consoles[i].srvs.ops = &con_ops;
+		consoles[i].srvs.sarg = &consoles[i];
+		
 		char vc[LOC_NAME_MAXLEN + 1];
 		snprintf(vc, LOC_NAME_MAXLEN, "%s/vc%zu", NAMESPACE, i);
Index: uspace/srv/hid/remcons/remcons.c
===================================================================
--- uspace/srv/hid/remcons/remcons.c	(revision d17a4a9b9b7d8b1ef841975044255958f61fbacc)
+++ uspace/srv/hid/remcons/remcons.c	(revision d6cd626db59cf8f2784e8800dfdb1dd6e8d2e5ca)
@@ -34,10 +34,8 @@
 
 #include <async.h>
+#include <errno.h>
+#include <io/con_srv.h>
 #include <stdio.h>
-#include <adt/prodcons.h>
-#include <ipc/input.h>
-#include <ipc/console.h>
-#include <ipc/vfs.h>
-#include <errno.h>
+#include <stdlib.h>
 #include <str_error.h>
 #include <loc.h>
@@ -45,6 +43,4 @@
 #include <io/keycode.h>
 #include <align.h>
-#include <malloc.h>
-#include <as.h>
 #include <fibril_synch.h>
 #include <task.h>
@@ -75,116 +71,131 @@
     sizeof(telnet_force_character_mode_command) / sizeof(telnet_cmd_t);
 
-
-/** Handling client requests (VFS and console interface).
- *
- * @param user Telnet user the requests belong to.
- */
-static void client_connection_message_loop(telnet_user_t *user)
-{
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = 0;
-
-		/*
-		 * The getterm task might terminate while we are here,
-		 * waiting for a call. Also, the socket might be closed
-		 * meanwhile.
-		 * We want to detect this situation early, so we use a
-		 * timeout variant of async_get_call().
-		 */
-		while (callid == 0) {
-			callid = async_get_call_timeout(&call, 1000);
-
-			if (telnet_user_is_zombie(user)) {
-				if (callid != 0) {
-					async_answer_0(callid, EINTR);
-				}
-				return;
-			}
-		}
-		
-		if (!IPC_GET_IMETHOD(call)) {
-			return;
-		}
-
-		switch (IPC_GET_IMETHOD(call)) {
-		case CONSOLE_GET_SIZE:
-			async_answer_2(callid, EOK, 100, 1);
-			break;
-		case CONSOLE_GET_POS:
-			fibril_mutex_lock(&user->guard);
-			async_answer_2(callid, EOK, user->cursor_x, 0);
-			fibril_mutex_unlock(&user->guard);
-			break;
-		case CONSOLE_GET_EVENT: {
-			kbd_event_t event;
-			int rc = telnet_user_get_next_keyboard_event(user, &event);
-			if (rc != EOK) {
-				/* Silently ignore. */
-				async_answer_0(callid, EOK);
-				break;
-			}
-			async_answer_4(callid, EOK, event.type, event.key, event.mods, event.c);
-			break;
-		}
-		case CONSOLE_GOTO: {
-			int new_x = IPC_GET_ARG1(call);
-			telnet_user_update_cursor_x(user, new_x);
-			async_answer_0(callid, ENOTSUP);
-			break;
-		}
-		case VFS_OUT_READ:
-			async_answer_0(callid, ENOTSUP);
-			break;
-		case VFS_OUT_WRITE: {
-			uint8_t *buf;
-			size_t size;
-			int rc = async_data_write_accept((void **)&buf, false, 0, 0, 0, &size);
-
-			if (rc != EOK) {
-				async_answer_0(callid, rc);
-				break;
-			}
-
-			rc = telnet_user_send_data(user, buf, size);
-			free(buf);
-
-			if (rc != EOK) {
-				async_answer_0(callid, rc);
-				break;
-			}
-
-			async_answer_1(callid, EOK, size);
-			break;
-		}
-		case VFS_OUT_SYNC:
-			async_answer_0(callid, EOK);
-			break;
-		case CONSOLE_CLEAR:
-			async_answer_0(callid, EOK);
-			break;
-
-		case CONSOLE_GET_COLOR_CAP:
-			async_answer_1(callid, EOK, CONSOLE_CAP_NONE);
-			break;
-		case CONSOLE_SET_STYLE:
-			async_answer_0(callid, ENOTSUP);
-			break;
-		case CONSOLE_SET_COLOR:
-			async_answer_0(callid, ENOTSUP);
-			break;
-		case CONSOLE_SET_RGB_COLOR:
-			async_answer_0(callid, ENOTSUP);
-			break;
-
-		case CONSOLE_CURSOR_VISIBILITY:
-			async_answer_0(callid, ENOTSUP);
-			break;
-
-		default:
-			async_answer_0(callid, EINVAL);
-			break;
-		}
-	}
+static int remcons_open(con_srvs_t *, con_srv_t *);
+static int remcons_close(con_srv_t *);
+static int remcons_write(con_srv_t *, void *, size_t);
+static void remcons_sync(con_srv_t *);
+static void remcons_clear(con_srv_t *);
+static void remcons_set_pos(con_srv_t *, sysarg_t col, sysarg_t row);
+static int remcons_get_pos(con_srv_t *, sysarg_t *, sysarg_t *);
+static int remcons_get_size(con_srv_t *, sysarg_t *, sysarg_t *);
+static int remcons_get_color_cap(con_srv_t *, console_caps_t *);
+static int remcons_get_event(con_srv_t *, kbd_event_t *);
+
+static con_ops_t con_ops = {
+	.open = remcons_open,
+	.close = remcons_close,
+	.read = NULL,
+	.write = remcons_write,
+	.sync = remcons_sync,
+	.clear = remcons_clear,
+	.set_pos = remcons_set_pos,
+	.get_pos = remcons_get_pos,
+	.get_size = remcons_get_size,
+	.get_color_cap = remcons_get_color_cap,
+	.set_style = NULL,
+	.set_color = NULL,
+	.set_rgb_color = NULL,
+	.set_cursor_visibility = NULL,
+	.get_event = remcons_get_event
+};
+
+static telnet_user_t *srv_to_user(con_srv_t *srv)
+{
+	return srv->srvs->sarg;
+}
+
+static int remcons_open(con_srvs_t *srvs, con_srv_t *srv)
+{
+	telnet_user_t *user = srv_to_user(srv);
+
+	telnet_user_log(user, "New client connected (%p).", srv);
+
+	/* Force character mode. */
+	send(user->socket, (void *)telnet_force_character_mode_command,
+	    telnet_force_character_mode_command_count, 0);
+
+	return EOK;
+}
+
+static int remcons_close(con_srv_t *srv)
+{
+	telnet_user_t *user = srv_to_user(srv);
+
+	telnet_user_notify_client_disconnected(user);
+	telnet_user_log(user, "Client disconnected (%p).", srv);
+
+	return EOK;
+}
+
+static int remcons_write(con_srv_t *srv, void *data, size_t size)
+{
+	telnet_user_t *user = srv_to_user(srv);
+	int rc;
+
+	rc = telnet_user_send_data(user, data, size);
+	if (rc != EOK)
+		return rc;
+
+	return size;
+}
+
+static void remcons_sync(con_srv_t *srv)
+{
+	(void) srv;
+}
+
+static void remcons_clear(con_srv_t *srv)
+{
+	(void) srv;
+}
+
+static void remcons_set_pos(con_srv_t *srv, sysarg_t col, sysarg_t row)
+{
+	telnet_user_t *user = srv_to_user(srv);
+
+	telnet_user_update_cursor_x(user, col);
+}
+
+static int remcons_get_pos(con_srv_t *srv, sysarg_t *col, sysarg_t *row)
+{
+	telnet_user_t *user = srv_to_user(srv);
+
+	*col = user->cursor_x;
+	*row = 0;
+
+	return EOK;
+}
+
+static int remcons_get_size(con_srv_t *srv, sysarg_t *cols, sysarg_t *rows)
+{
+	(void) srv;
+
+	*cols = 100;
+	*rows = 1;
+
+	return EOK;
+}
+
+static int remcons_get_color_cap(con_srv_t *srv, console_caps_t *ccaps)
+{
+	(void) srv;
+	*ccaps = CONSOLE_CAP_NONE;
+
+	return EOK;
+}
+
+static int remcons_get_event(con_srv_t *srv, kbd_event_t *event)
+{
+	telnet_user_t *user = srv_to_user(srv);
+	int rc;
+
+	rc = telnet_user_get_next_keyboard_event(user, event);
+	if (rc != EOK) {
+		/* XXX What? */
+		memset(event, 0, sizeof(*event));
+		return EOK;
+	}
+
+	return EOK;
 }
 
@@ -198,17 +209,7 @@
 		return;
 	}
-	async_answer_0(iid, EOK);
-
-	telnet_user_log(user, "New client connected (%" PRIxn").", iid);
-
-	/* Force character mode. */
-	send(user->socket, (void *)telnet_force_character_mode_command,
-	    telnet_force_character_mode_command_count, 0);
 
 	/* Handle messages. */
-	client_connection_message_loop(user);
-
-	telnet_user_notify_client_disconnected(user);
-	telnet_user_log(user, "Client disconnected (%" PRIxn").", iid);
+	con_conn(iid, icall, &user->srvs);
 }
 
@@ -232,4 +233,5 @@
 		fibril_mutex_lock(&user->guard);
 		user->task_finished = true;
+		user->srvs.aborted = true;
 		fibril_condvar_signal(&user->refcount_cv);
 		fibril_mutex_unlock(&user->guard);
@@ -251,4 +253,5 @@
 	fibril_mutex_lock(&user->guard);
 	user->task_finished = true;
+	user->srvs.aborted = true;
 	fibril_condvar_signal(&user->refcount_cv);
 	fibril_mutex_unlock(&user->guard);
@@ -295,4 +298,5 @@
 			closesocket(user->socket);
 			user->socket_closed = true;
+			user->srvs.aborted = true;
 			continue;
 		} else if (user->socket_closed) {
@@ -380,4 +384,11 @@
 		assert(user);
 
+		con_srvs_init(&user->srvs);
+		user->srvs.ops = &con_ops;
+		user->srvs.sarg = user;
+		user->srvs.abort_timeout = 1000;
+
+		telnet_user_add(user);
+
 		fid_t fid = fibril_create(network_user_fibril, user);
 		assert(fid);
Index: uspace/srv/hid/remcons/user.c
===================================================================
--- uspace/srv/hid/remcons/user.c	(revision d17a4a9b9b7d8b1ef841975044255958f61fbacc)
+++ uspace/srv/hid/remcons/user.c	(revision d6cd626db59cf8f2784e8800dfdb1dd6e8d2e5ca)
@@ -35,7 +35,4 @@
 #include <stdio.h>
 #include <adt/prodcons.h>
-#include <ipc/input.h>
-#include <ipc/console.h>
-#include <ipc/vfs.h>
 #include <errno.h>
 #include <str_error.h>
@@ -95,12 +92,14 @@
 	user->locsrv_connection_count = 0;
 
-
+	user->cursor_x = 0;
+
+	return user;
+}
+
+void telnet_user_add(telnet_user_t *user)
+{
 	fibril_mutex_lock(&users_guard);
 	list_append(&user->link, &users);
 	fibril_mutex_unlock(&users_guard);
-
-	user->cursor_x = 0;
-
-	return user;
 }
 
@@ -199,4 +198,5 @@
 		if ((recv_length == 0) || (recv_length == ENOTCONN)) {
 			user->socket_closed = true;
+			user->srvs.aborted = true;
 			return ENOENT;
 		}
Index: uspace/srv/hid/remcons/user.h
===================================================================
--- uspace/srv/hid/remcons/user.h	(revision d17a4a9b9b7d8b1ef841975044255958f61fbacc)
+++ uspace/srv/hid/remcons/user.h	(revision d6cd626db59cf8f2784e8800dfdb1dd6e8d2e5ca)
@@ -36,6 +36,8 @@
 #define TELNET_USER_H_
 
+#include <adt/prodcons.h>
 #include <fibril_synch.h>
 #include <inttypes.h>
+#include <io/con_srv.h>
 #include "remcons.h"
 
@@ -55,4 +57,6 @@
 	/** Path name of the service. */
 	char *service_name;
+	/** Console service setup */
+	con_srvs_t srvs;
 
 	/** Producer-consumer of kbd_event_t. */
@@ -77,4 +81,5 @@
 
 extern telnet_user_t *telnet_user_create(int);
+extern void telnet_user_add(telnet_user_t *);
 extern void telnet_user_destroy(telnet_user_t *);
 extern telnet_user_t *telnet_user_get_for_client_connection(service_id_t);
