Index: uspace/drv/char/i8042/i8042.c
===================================================================
--- uspace/drv/char/i8042/i8042.c	(revision ecc63239f3038d00cb3dfb606a3e802e10e0d480)
+++ uspace/drv/char/i8042/i8042.c	(revision a455321ecc56b9c24a97830fbdeaa114844e4ce4)
@@ -55,6 +55,4 @@
 static int i8042_write_kbd(ddf_fun_t *, char *, size_t);
 static int i8042_read_kbd(ddf_fun_t *, char *, size_t);
-static int i8042_write_aux(ddf_fun_t *, char *, size_t);
-static int i8042_read_aux(ddf_fun_t *, char *, size_t);
 
 /** Primary port interface structure. */
@@ -64,18 +62,15 @@
 };
 
-/** Auxiliary port interface structure. */
-static char_dev_ops_t aux_iface = {
-    .read = i8042_read_aux,
-    .write = i8042_write_aux,
-};
+void default_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
 
 /** Primary port function operations. */
 static ddf_dev_ops_t kbd_ops = {
-	.interfaces[CHAR_DEV_IFACE] = &kbd_iface
+	.interfaces[CHAR_DEV_IFACE] = &kbd_iface,
+	.default_handler = default_handler,
 };
 
 /** Auxiliary port function operations. */
-static ddf_dev_ops_t aux_ops = {
-	.interfaces[CHAR_DEV_IFACE] = &aux_iface
+static ddf_dev_ops_t ops = {
+	.default_handler = default_handler,
 };
 
@@ -181,21 +176,21 @@
 	}
 
-	dev->mouse_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2b");
-	if (!dev->mouse_fun) {
+	dev->aux_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2b");
+	if (!dev->aux_fun) {
 		ddf_fun_destroy(dev->kbd_fun);
 		return ENOMEM;
 	}
 
-	ret = ddf_fun_add_match_id(dev->mouse_fun, "char/ps2mouse", 90);
+	ret = ddf_fun_add_match_id(dev->aux_fun, "char/ps2mouse", 90);
 	if (ret != EOK) {
 		ddf_fun_destroy(dev->kbd_fun);
-		ddf_fun_destroy(dev->mouse_fun);
+		ddf_fun_destroy(dev->aux_fun);
 		return ret;
 	}
 
 	dev->kbd_fun->ops = &kbd_ops;
-	dev->mouse_fun->ops = &aux_ops;
+	dev->aux_fun->ops = &ops;
 	dev->kbd_fun->driver_data = dev;
-	dev->mouse_fun->driver_data = dev;
+	dev->aux_fun->driver_data = dev;
 
 	buffer_init(&dev->kbd_buffer, dev->kbd_data, BUFFER_SIZE);
@@ -210,7 +205,7 @@
 		ddf_fun_destroy(dev->kbd_fun); \
 	} \
-	if (dev->mouse_fun) { \
-		dev->mouse_fun->driver_data = NULL; \
-		ddf_fun_destroy(dev->mouse_fun); \
+	if (dev->aux_fun) { \
+		dev->aux_fun->driver_data = NULL; \
+		ddf_fun_destroy(dev->aux_fun); \
 	} \
 } else (void)0
@@ -220,5 +215,5 @@
 	    "Failed to bind keyboard function: %s.", str_error(ret));
 
-	ret = ddf_fun_bind(dev->mouse_fun);
+	ret = ddf_fun_bind(dev->aux_fun);
 	CHECK_RET_DESTROY(ret,
 	    "Failed to bind mouse function: %s.", str_error(ret));
@@ -242,8 +237,8 @@
 		ddf_fun_destroy(dev->kbd_fun); \
 	} \
-	if (dev->mouse_fun) { \
-		ddf_fun_unbind(dev->mouse_fun); \
-		dev->mouse_fun->driver_data = NULL; \
-		ddf_fun_destroy(dev->mouse_fun); \
+	if (dev->aux_fun) { \
+		ddf_fun_unbind(dev->aux_fun); \
+		dev->aux_fun->driver_data = NULL; \
+		ddf_fun_destroy(dev->aux_fun); \
 	} \
 } else (void)0
@@ -328,5 +323,11 @@
 }
 
-/** Write data to i8042 auxiliary port.
+// TODO use shared instead of own copy
+enum {
+	IPC_CHAR_READ = DEV_FIRST_CUSTOM_METHOD,
+	IPC_CHAR_WRITE,
+};
+
+/** Write data to i8042 port.
  * @param fun DDF function.
  * @param buffer Data source.
@@ -334,5 +335,5 @@
  * @return Bytes written.
  */
-static int i8042_write_aux(ddf_fun_t *fun, char *buffer, size_t size)
+static int i8042_write(ddf_fun_t *fun, char *buffer, size_t size)
 {
 	assert(fun);
@@ -342,5 +343,7 @@
 	for (size_t i = 0; i < size; ++i) {
 		wait_ready(controller);
-		pio_write_8(&controller->regs->status, i8042_CMD_WRITE_AUX);
+		if (controller->aux_fun == fun)
+			pio_write_8(
+			    &controller->regs->status, i8042_CMD_WRITE_AUX);
 		pio_write_8(&controller->regs->data, buffer[i]);
 	}
@@ -349,5 +352,5 @@
 }
 
-/** Read data from i8042 auxiliary port.
+/** Read data from i8042 port.
  * @param fun DDF function.
  * @param buffer Data place.
@@ -355,15 +358,48 @@
  * @return Bytes read.
  */
-static int i8042_read_aux(ddf_fun_t *fun, char *buffer, size_t size)
+static int i8042_read(ddf_fun_t *fun, char *data, size_t size)
 {
 	assert(fun);
 	assert(fun->driver_data);
-	bzero(buffer, size);
 
 	i8042_t *controller = fun->driver_data;
+	buffer_t *buffer = (fun == controller->aux_fun) ?
+	    &controller->aux_buffer : &controller->kbd_buffer;
 	for (size_t i = 0; i < size; ++i) {
-		*buffer++ = buffer_read(&controller->aux_buffer);
+		*data++ = buffer_read(buffer);
 	}
 	return size;
+}
+
+void default_handler(ddf_fun_t *fun, ipc_callid_t id, ipc_call_t *call)
+{
+	const sysarg_t method = IPC_GET_IMETHOD(*call);
+	const size_t size = IPC_GET_ARG1(*call);
+	switch (method) {
+	case IPC_CHAR_READ:
+		if (size <= 4 * sizeof(sysarg_t)) {
+			sysarg_t message[4] = { 0 };
+			i8042_read(fun, (char*)message, size);
+			async_answer_4(id, size, message[0], message[1],
+			    message[2], message[3]);
+		} else {
+			async_answer_0(id, ELIMIT);
+		}
+		break;
+
+	case IPC_CHAR_WRITE:
+		if (size <= 3 * sizeof(sysarg_t)) {
+			const sysarg_t message[3] = {
+				IPC_GET_ARG2(*call), IPC_GET_ARG3(*call),
+				IPC_GET_ARG4(*call) };
+			i8042_write(fun, (char*)message, size);
+			async_answer_0(id, size);
+		} else {
+			async_answer_0(id, ELIMIT);
+		}
+
+	default:
+		async_answer_0(id, EINVAL);
+	}
 }
 /**
Index: uspace/drv/char/i8042/i8042.h
===================================================================
--- uspace/drv/char/i8042/i8042.h	(revision ecc63239f3038d00cb3dfb606a3e802e10e0d480)
+++ uspace/drv/char/i8042/i8042.h	(revision a455321ecc56b9c24a97830fbdeaa114844e4ce4)
@@ -57,5 +57,5 @@
 	i8042_regs_t *regs;    /**< I/O registers. */
 	ddf_fun_t *kbd_fun;    /**< Pirmary port device function. */
-	ddf_fun_t *mouse_fun;  /**< Auxiliary port device function. */
+	ddf_fun_t *aux_fun;  /**< Auxiliary port device function. */
 	buffer_t kbd_buffer;   /**< Primary port buffer. */
 	buffer_t aux_buffer;   /**< Aux. port buffer. */
Index: uspace/drv/char/ps2mouse/Makefile
===================================================================
--- uspace/drv/char/ps2mouse/Makefile	(revision ecc63239f3038d00cb3dfb606a3e802e10e0d480)
+++ uspace/drv/char/ps2mouse/Makefile	(revision a455321ecc56b9c24a97830fbdeaa114844e4ce4)
@@ -33,4 +33,5 @@
 
 SOURCES = \
+	chardev.c \
 	main.c \
 	ps2mouse.c
Index: uspace/drv/char/ps2mouse/chardev.c
===================================================================
--- uspace/drv/char/ps2mouse/chardev.c	(revision a455321ecc56b9c24a97830fbdeaa114844e4ce4)
+++ uspace/drv/char/ps2mouse/chardev.c	(revision a455321ecc56b9c24a97830fbdeaa114844e4ce4)
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * 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.
+ */
+
+#include <errno.h>
+#include <mem.h>
+#include <ipc/dev_iface.h>
+#include <ddf/log.h>
+
+#include "chardev.h"
+
+// TODO make this shared
+enum {
+	IPC_CHAR_READ = DEV_FIRST_CUSTOM_METHOD,
+	IPC_CHAR_WRITE,
+};
+
+static ssize_t chardev_read_int(async_exch_t *exch, void *data, size_t size)
+{
+	if (!exch)
+		return EBADMEM;
+	if (size > 4 * sizeof(sysarg_t))
+		return ELIMIT;
+
+	sysarg_t message[4] = { 0 };
+	const ssize_t ret = async_req_1_4(exch, IPC_CHAR_READ, size,
+	    &message[0], &message[1], &message[2], &message[3]);
+	if (ret > 0 && (size_t)ret <= size)
+		memcpy(data, message, size);
+	return ret;
+}
+
+static ssize_t chardev_write_int(async_exch_t *exch, const void *data, size_t size)
+{
+	if (!exch)
+		return EBADMEM;
+	if (size > 3 * sizeof(sysarg_t))
+		return ELIMIT;
+
+	sysarg_t message[3] = { 0 };
+	memcpy(message, data, size);
+	return async_req_4_0(exch, IPC_CHAR_WRITE, size,
+	    message[0], message[1], message[2]);
+}
+
+
+ssize_t chardev_write(async_sess_t *sess, const void *data, size_t size)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	const ssize_t ret = chardev_write_int(exch, data, size);
+	async_exchange_end(exch);
+	return ret;
+}
+
+ssize_t chardev_read(async_sess_t *sess, void *data, size_t size)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	const ssize_t ret = chardev_read_int(exch, data, size);
+	async_exchange_end(exch);
+	return ret;
+}
Index: uspace/drv/char/ps2mouse/chardev.h
===================================================================
--- uspace/drv/char/ps2mouse/chardev.h	(revision a455321ecc56b9c24a97830fbdeaa114844e4ce4)
+++ uspace/drv/char/ps2mouse/chardev.h	(revision a455321ecc56b9c24a97830fbdeaa114844e4ce4)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * 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 drvmouse
+ * @{
+ */
+/** @file
+ * @brief ps/2 mouse driver.
+ */
+
+#ifndef _CHARDEV_H_
+#define _CHARDEV_H_
+
+#include <libarch/types.h>
+#include <async.h>
+
+ssize_t chardev_read(async_sess_t *, void *, size_t);
+ssize_t chardev_write(async_sess_t *, const void *, size_t);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/char/ps2mouse/ps2mouse.c
===================================================================
--- uspace/drv/char/ps2mouse/ps2mouse.c	(revision ecc63239f3038d00cb3dfb606a3e802e10e0d480)
+++ uspace/drv/char/ps2mouse/ps2mouse.c	(revision a455321ecc56b9c24a97830fbdeaa114844e4ce4)
@@ -36,5 +36,4 @@
 #include <errno.h>
 #include <devman.h>
-#include <device/char_dev.h>
 #include <ddf/log.h>
 #include <io/keycode.h>
@@ -44,4 +43,5 @@
 
 #include "ps2mouse.h"
+#include "chardev.h"
 
 #define PS2_MOUSE_GET_DEVICE_ID   0xf2
@@ -74,5 +74,5 @@
 do { \
 	uint8_t data = 0; \
-	const ssize_t size = char_dev_read(session, &data, 1); \
+	const ssize_t size = chardev_read(session, &data, 1); \
 	if (size != 1) { \
 		ddf_msg(LVL_ERROR, "Failed reading byte: %d)", size);\
@@ -85,8 +85,9 @@
 	} \
 } while (0)
+
 #define MOUSE_WRITE_BYTE(sess, value) \
 do { \
 	uint8_t data = (value); \
-	const ssize_t size = char_dev_write(session, &data, 1); \
+	const ssize_t size = chardev_write(session, &data, 1); \
 	if (size < 0 ) { \
 		ddf_msg(LVL_ERROR, "Failed writing byte: %hhx", value); \
@@ -155,5 +156,5 @@
 	/* Enable mouse data reporting. */
 	uint8_t report = PS2_MOUSE_ENABLE_DATA_REPORT;
-	ssize_t size = char_dev_write(mouse->parent_sess, &report, 1);
+	ssize_t size = chardev_write(mouse->parent_sess, &report, 1);
 	if (size != 1) {
 		ddf_msg(LVL_ERROR, "Failed to enable data reporting.");
@@ -165,5 +166,5 @@
 	}
 
-	size = char_dev_read(mouse->parent_sess, &report, 1);
+	size = chardev_read(mouse->parent_sess, &report, 1);
 	if (size != 1 || report != PS2_MOUSE_ACK) {
 		ddf_msg(LVL_ERROR, "Failed to confirm data reporting: %hhx.",
@@ -203,5 +204,5 @@
 		uint8_t packet[PS2_BUFSIZE] = {};
 		const ssize_t size =
-		    char_dev_read(mouse->parent_sess, packet, PS2_BUFSIZE);
+		    chardev_read(mouse->parent_sess, packet, PS2_BUFSIZE);
 
 		if (size != PS2_BUFSIZE) {
@@ -257,5 +258,5 @@
 
 		uint8_t packet[INTELLIMOUSE_BUFSIZE] = {};
-		const ssize_t size = char_dev_read(
+		const ssize_t size = chardev_read(
 		    mouse->parent_sess, packet, INTELLIMOUSE_BUFSIZE);
 
