Index: uspace/srv/hid/input/input.c
===================================================================
--- uspace/srv/hid/input/input.c	(revision c4c60250a236ed30397cd89ce5cea5eaf59cfba5)
+++ uspace/srv/hid/input/input.c	(revision 74017cef2e4edaf9405cf38ba4b0958f664e700c)
@@ -37,30 +37,31 @@
  */
 
+#include <adt/fifo.h>
 #include <adt/list.h>
-#include <stdbool.h>
+#include <async.h>
+#include <config.h>
+#include <errno.h>
+#include <fibril.h>
 #include <fibril_synch.h>
+#include <io/chardev.h>
+#include <io/console.h>
+#include <io/keycode.h>
 #include <ipc/services.h>
 #include <ipc/input.h>
-#include <config.h>
+#include <loc.h>
+#include <ns.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <ns.h>
-#include <async.h>
-#include <errno.h>
-#include <adt/fifo.h>
-#include <io/console.h>
-#include <io/keycode.h>
-#include <loc.h>
 #include <str_error.h>
-#include <char_dev_iface.h>
-#include <fibril.h>
-#include "layout.h"
+
+#include "input.h"
 #include "kbd.h"
 #include "kbd_port.h"
 #include "kbd_ctl.h"
+#include "layout.h"
 #include "mouse.h"
 #include "mouse_proto.h"
 #include "serial.h"
-#include "input.h"
 
 #define NUM_LAYOUTS  4
@@ -536,6 +537,8 @@
 	while (true) {
 		uint8_t data;
-
-		char_dev_read(sdev->sess, &data, sizeof(data));
+		size_t nread;
+
+		chardev_read(sdev->chardev, &data, sizeof(data), &nread);
+		/* XXX Handle error */
 		kbd_push_data(sdev->kdev, data);
 	}
@@ -552,4 +555,5 @@
 {
 	bool match = false;
+	int rc;
 
 	serial_dev_t *sdev = serial_dev_new();
@@ -559,5 +563,5 @@
 	sdev->kdev->svc_id = service_id;
 	
-	int rc = loc_service_get_name(service_id, &sdev->kdev->svc_name);
+	rc = loc_service_get_name(service_id, &sdev->kdev->svc_name);
 	if (rc != EOK)
 		goto fail;
@@ -582,4 +586,12 @@
 		sdev->sess = loc_service_connect(service_id, INTERFACE_DDF,
 		    IPC_FLAG_BLOCKING);
+
+		rc = chardev_open(sdev->sess, &sdev->chardev);
+		if (rc != EOK) {
+			async_hangup(sdev->sess);
+			sdev->sess = NULL;
+			list_remove(&sdev->link);
+			goto fail;
+		}
 
 		fid_t fid = fibril_create(serial_consumer, sdev);
Index: uspace/srv/hid/input/serial.h
===================================================================
--- uspace/srv/hid/input/serial.h	(revision c4c60250a236ed30397cd89ce5cea5eaf59cfba5)
+++ uspace/srv/hid/input/serial.h	(revision 74017cef2e4edaf9405cf38ba4b0958f664e700c)
@@ -39,4 +39,5 @@
 
 #include <async.h>
+#include <io/chardev.h>
 #include "kbd.h"
 
@@ -45,4 +46,5 @@
 	link_t link;
 	async_sess_t *sess;
+	chardev_t *chardev;
 } serial_dev_t;
 
Index: uspace/srv/hid/isdv4_tablet/isdv4.c
===================================================================
--- uspace/srv/hid/isdv4_tablet/isdv4.c	(revision c4c60250a236ed30397cd89ce5cea5eaf59cfba5)
+++ uspace/srv/hid/isdv4_tablet/isdv4.c	(revision 74017cef2e4edaf9405cf38ba4b0958f664e700c)
@@ -27,10 +27,10 @@
  */
 
-#include <char_dev_iface.h>
 #include <errno.h>
+#include <io/chardev.h>
+#include <mem.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include <stdlib.h>
-#include <mem.h>
 #include <thread.h>
 
@@ -298,9 +298,12 @@
 	bool reading = true;
 	while (reading) {
-		ssize_t read = char_dev_read(state->sess, state->buf + state->buf_end,
-		    state->buf_size - state->buf_end);
-		if (read < 0)
+		size_t nread;
+		int rc;
+
+		rc = chardev_read(state->chardev, state->buf + state->buf_end,
+		    state->buf_size - state->buf_end, &nread);
+		if (rc != EOK && nread == 0)
 			return EIO;
-		state->buf_end += read;
+		state->buf_end += nread;
 
 		size_t i = 0;
@@ -357,7 +360,12 @@
 	return EOK;
 }
-static bool write_command(async_sess_t *sess, uint8_t command)
-{
-	return char_dev_write(sess, &command, 1) == 1;
+
+static bool write_command(chardev_t *chardev, uint8_t command)
+{
+	int rc;
+	size_t nwr;
+
+	rc = chardev_write(chardev, &command, 1, &nwr);
+	return rc == EOK;
 }
 
@@ -365,9 +373,22 @@
     isdv4_event_fn event_fn)
 {
+	chardev_t *chardev;
+	int rc;
+
+	rc = chardev_open(sess, &chardev);
+	if (rc != EOK)
+		return rc;
+
 	memset(state, 0, sizeof(isdv4_state_t));
+
 	state->sess = sess;
+	state->chardev = chardev;
+
 	state->buf = malloc(BUF_SIZE);
-	if (state->buf == NULL)
+	if (state->buf == NULL) {
+		chardev_close(chardev);
 		return ENOMEM;
+	}
+
 	state->buf_size = BUF_SIZE;
 	state->emit_event_fn = event_fn;
@@ -377,5 +398,5 @@
 int isdv4_init_tablet(isdv4_state_t *state)
 {
-	if (!write_command(state->sess, CMD_STOP))
+	if (!write_command(state->chardev, CMD_STOP))
 		return EIO;
 
@@ -383,5 +404,5 @@
 
 	// FIXME: Read all possible garbage before sending commands
-	if (!write_command(state->sess, CMD_QUERY_STYLUS))
+	if (!write_command(state->chardev, CMD_QUERY_STYLUS))
 		return EIO;
 
@@ -390,5 +411,5 @@
 		return rc;
 
-	if (!write_command(state->sess, CMD_QUERY_TOUCH))
+	if (!write_command(state->chardev, CMD_QUERY_TOUCH))
 		return EIO;
 
@@ -397,5 +418,5 @@
 		return rc;
 
-	if (!write_command(state->sess, CMD_START))
+	if (!write_command(state->chardev, CMD_START))
 		return EIO;
 
Index: uspace/srv/hid/isdv4_tablet/isdv4.h
===================================================================
--- uspace/srv/hid/isdv4_tablet/isdv4.h	(revision c4c60250a236ed30397cd89ce5cea5eaf59cfba5)
+++ uspace/srv/hid/isdv4_tablet/isdv4.h	(revision 74017cef2e4edaf9405cf38ba4b0958f664e700c)
@@ -31,4 +31,5 @@
 
 #include <async.h>
+#include <io/chardev.h>
 
 typedef struct isdv4_event isdv4_event_t;
@@ -58,6 +59,8 @@
 	bool finger1_pressed; /* Reported as touch button 1 */
 
-	/* Session to the serial device */
+	/** Session with the serial device */
 	async_sess_t *sess;
+	/** Character device */
+	chardev_t *chardev;
 
 	/* Receive buffer state */
@@ -66,5 +69,5 @@
 	size_t buf_end;
 
-	/* Callbacks */
+	/** Callbacks */
 	isdv4_event_fn emit_event_fn;
 } isdv4_state_t;
Index: uspace/srv/hid/output/port/chardev.c
===================================================================
--- uspace/srv/hid/output/port/chardev.c	(revision c4c60250a236ed30397cd89ce5cea5eaf59cfba5)
+++ uspace/srv/hid/output/port/chardev.c	(revision 74017cef2e4edaf9405cf38ba4b0958f664e700c)
@@ -30,15 +30,15 @@
  */
 
+#include <async.h>
+#include <config.h>
+#include <errno.h>
+#include <fibril_synch.h>
+#include <io/chardev.h>
+#include <loc.h>
 #include <stddef.h>
 #include <stdint.h>
-#include <char_dev_iface.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <async.h>
-#include <fibril_synch.h>
-#include <loc.h>
-#include <errno.h>
 #include <str.h>
-#include <config.h>
 #include "../ctl/serial.h"
 #include "../output.h"
@@ -48,4 +48,5 @@
 
 static async_sess_t *sess;
+static chardev_t *chardev;
 static service_id_t serial_cat_id;
 
@@ -57,10 +58,14 @@
 {
 	uint8_t byte = (uint8_t) ch;
-	char_dev_write(sess, &byte, 1); 
+	size_t nwr;
+	chardev_write(chardev, &byte, 1, &nwr);
+	/* XXX Handle error */
 }
 
 static void chardev_control_puts(const char *str)
 {
-	char_dev_write(sess, (void *) str, str_size(str));
+	size_t nwr;
+	chardev_write(chardev, (void *) str, str_size(str), &nwr);
+	/* XXX Handle error */
 }
 
@@ -126,4 +131,12 @@
 		return;
 	}
+
+	rc = chardev_open(sess, &chardev);
+	if (rc != EOK) {
+		fibril_mutex_unlock(&discovery_lock);
+		printf("%s: Failed opening character device\n", NAME);
+		return;
+	}
+
 	serial_init(chardev_putchar, chardev_control_puts);
 
Index: uspace/srv/net/slip/slip.c
===================================================================
--- uspace/srv/net/slip/slip.c	(revision c4c60250a236ed30397cd89ce5cea5eaf59cfba5)
+++ uspace/srv/net/slip/slip.c	(revision 74017cef2e4edaf9405cf38ba4b0958f664e700c)
@@ -40,5 +40,5 @@
 #include <inet/addr.h>
 #include <inet/iplink_srv.h>
-#include <char_dev_iface.h>
+#include <io/chardev.h>
 #include <io/log.h>
 #include <errno.h>
@@ -96,29 +96,29 @@
 }
 
-static void write_flush(async_sess_t *sess)
+static void write_flush(chardev_t *chardev)
 {
 	size_t written = 0;
 
 	while (slip_send_pending > 0) {
-		ssize_t size;
-
-		size = char_dev_write(sess, &slip_send_buf[written],
-		    slip_send_pending);
-		if (size < 0) {
+		int rc;
+		size_t nwr;
+
+		rc = chardev_write(chardev, &slip_send_buf[written],
+		    slip_send_pending, &nwr);
+		if (rc != EOK) {
 			log_msg(LOG_DEFAULT, LVL_ERROR,
-			    "char_dev_write() returned %d",
-			    (int) size);
+			    "chardev_write() returned %d", rc);
 			slip_send_pending = 0;
 			break;
 		}
-		written += size;
-		slip_send_pending -= size;
-	}
-}
-
-static void write_buffered(async_sess_t *sess, uint8_t ch)
+		written += nwr;
+		slip_send_pending -= nwr;
+	}
+}
+
+static void write_buffered(chardev_t *chardev, uint8_t ch)
 {
 	if (slip_send_pending == sizeof(slip_send_buf))
-		write_flush(sess);
+		write_flush(chardev);
 	slip_send_buf[slip_send_pending++] = ch;
 }
@@ -128,5 +128,5 @@
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "slip_send()");
 	
-	async_sess_t *sess = (async_sess_t *) srv->arg;
+	chardev_t *chardev = (chardev_t *) srv->arg;
 	uint8_t *data = sdu->data;
 	
@@ -136,24 +136,24 @@
 	 * measure for dealing with previous possible noise on the line.
 	 */
-	write_buffered(sess, SLIP_END);
+	write_buffered(chardev, SLIP_END);
 	
 	for (size_t i = 0; i < sdu->size; i++) {
 		switch (data[i]) {
 		case SLIP_END:
-			write_buffered(sess, SLIP_ESC);
-			write_buffered(sess, SLIP_ESC_END);
+			write_buffered(chardev, SLIP_ESC);
+			write_buffered(chardev, SLIP_ESC_END);
 			break;
 		case SLIP_ESC:
-			write_buffered(sess, SLIP_ESC);
-			write_buffered(sess, SLIP_ESC_ESC);
+			write_buffered(chardev, SLIP_ESC);
+			write_buffered(chardev, SLIP_ESC_ESC);
 			break;
 		default:
-			write_buffered(sess, data[i]);
+			write_buffered(chardev, data[i]);
 			break;
 		}
 	}
 	
-	write_buffered(sess, SLIP_END);
-	write_flush(sess);
+	write_buffered(chardev, SLIP_END);
+	write_flush(chardev);
 	
 	return EOK;
@@ -203,17 +203,21 @@
 }
 
-static uint8_t read_buffered(async_sess_t *sess)
+static uint8_t read_buffered(chardev_t *chardev)
 {
 	while (slip_recv_pending == 0) {
-		ssize_t size;
-
-		size = char_dev_read(sess, slip_recv_buf,
-		    sizeof(slip_recv_buf));
-		if (size < 0) {
+		int rc;
+		size_t nread;
+
+		rc = chardev_read(chardev, slip_recv_buf,
+		    sizeof(slip_recv_buf), &nread);
+		if (rc != EOK) {
 			log_msg(LOG_DEFAULT, LVL_ERROR,
-			    "char_dev_read() returned %d", (int) size);
+			    "char_dev_read() returned %d", rc);
+		}
+
+		if (nread == 0)
 			return SLIP_END;
-		}
-		slip_recv_pending = size;
+
+		slip_recv_pending = nread;
 		slip_recv_read = 0;
 	}
@@ -224,5 +228,5 @@
 static int slip_recv_fibril(void *arg)
 {
-	async_sess_t *sess = (async_sess_t *) arg;
+	chardev_t *chardev = (chardev_t *) arg;
 	static uint8_t recv_final[SLIP_MTU];
 	iplink_recv_sdu_t sdu;
@@ -234,5 +238,5 @@
 	while (true) {
 		for (sdu.size = 0; sdu.size < sizeof(recv_final); /**/) {
-			ch = read_buffered(sess);
+			ch = read_buffered(chardev);
 			switch (ch) {
 			case SLIP_END:
@@ -246,9 +250,9 @@
 
 			case SLIP_ESC:
-				ch = read_buffered(sess);
+				ch = read_buffered(chardev);
 				if (ch == SLIP_ESC_END) {
 					recv_final[sdu.size++] = SLIP_END;
 					break;
-				} else if (ch ==  SLIP_ESC_ESC) {
+				} else if (ch == SLIP_ESC_ESC) {
 					recv_final[sdu.size++] = SLIP_ESC;
 					break;
@@ -295,4 +299,6 @@
 	async_sess_t *sess_in = NULL;
 	async_sess_t *sess_out = NULL;
+	chardev_t *chardev_in = NULL;
+	chardev_t *chardev_out = NULL;
 	fid_t fid;
 	int rc;
@@ -336,5 +342,13 @@
 		return ENOENT;
 	}
-	slip_iplink.arg = sess_out;
+
+	rc = chardev_open(sess_out, &chardev_out);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR,
+		    "Failed opening character device.");
+		return ENOENT;
+	}
+
+	slip_iplink.arg = chardev_out;
 
 	sess_in = loc_service_connect(svcid, INTERFACE_DDF, 0);
@@ -347,4 +361,11 @@
 	}
 
+	rc = chardev_open(sess_in, &chardev_in);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR,
+		    "Failed opening character device.");
+		return ENOENT;
+	}
+
 	rc = loc_service_register(linkstr, &linksid);
 	if (rc != EOK) {
@@ -363,5 +384,5 @@
 	}
 
-	fid = fibril_create(slip_recv_fibril, sess_in);
+	fid = fibril_create(slip_recv_fibril, chardev_in);
 	if (!fid) {
 		log_msg(LOG_DEFAULT, LVL_ERROR,
@@ -375,6 +396,8 @@
 
 fail:
+	chardev_close(chardev_out);
 	if (sess_out)
 		async_hangup(sess_out);
+	chardev_close(chardev_in);
 	if (sess_in)
 		async_hangup(sess_in);
