Index: uspace/drv/char/i8042/i8042.c
===================================================================
--- uspace/drv/char/i8042/i8042.c	(revision 2f79a38dd6a40386b181045cc2e754875bf24fec)
+++ uspace/drv/char/i8042/i8042.c	(revision bd87ae077e8b79fbea920fcc3c62b1f896e52b38)
@@ -47,5 +47,4 @@
 #include <ddf/log.h>
 #include <ddf/interrupt.h>
-#include <ops/char_dev.h>
 
 #include "i8042.h"
@@ -53,22 +52,7 @@
 #define NAME       "i8042"
 
-static int i8042_write_kbd(ddf_fun_t *, char *, size_t);
-static int i8042_read_kbd(ddf_fun_t *, char *, size_t);
-
-/** Primary port interface structure. */
-static char_dev_ops_t kbd_iface = {
-    .read = i8042_read_kbd,
-    .write = i8042_write_kbd,
-};
-
 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,
-	.default_handler = default_handler,
-};
-
-/** Auxiliary port function operations. */
+/** Port function operations. */
 static ddf_dev_ops_t ops = {
 	.default_handler = default_handler,
@@ -189,5 +173,5 @@
 	}
 
-	dev->kbd_fun->ops = &kbd_ops;
+	dev->kbd_fun->ops = &ops;
 	dev->aux_fun->ops = &ops;
 	dev->kbd_fun->driver_data = dev;
@@ -283,45 +267,5 @@
 }
 
-/** Write data to i8042 primary port.
- * @param fun DDF function.
- * @param buffer Data source.
- * @param size Data size.
- * @return Bytes written.
- */
-static int i8042_write_kbd(ddf_fun_t *fun, char *buffer, size_t size)
-{
-	assert(fun);
-	assert(fun->driver_data);
-	i8042_t *controller = fun->driver_data;
-	fibril_mutex_lock(&controller->write_guard);
-	for (size_t i = 0; i < size; ++i) {
-		wait_ready(controller);
-		pio_write_8(&controller->regs->data, buffer[i]);
-	}
-	fibril_mutex_unlock(&controller->write_guard);
-	return size;
-}
-
-/** Read data from i8042 primary port.
- * @param fun DDF function.
- * @param buffer Data place.
- * @param size Data place size.
- * @return Bytes read.
- */
-static int i8042_read_kbd(ddf_fun_t *fun, char *buffer, size_t size)
-{
-	assert(fun);
-	assert(fun->driver_data);
-	bzero(buffer, size);
-
-	i8042_t *controller = fun->driver_data;
-
-	for (size_t i = 0; i < size; ++i) {
-		*buffer++ = buffer_read(&controller->kbd_buffer);
-	}
-	return size;
-}
-
-// TODO use shared instead of own copy
+// TODO use shared instead this
 enum {
 	IPC_CHAR_READ = DEV_FIRST_CUSTOM_METHOD,
@@ -372,4 +316,9 @@
 }
 
+/** Handle data requests.
+ * @param fun ddf_fun_t function.
+ * @param id callid
+ * @param call IPC request.
+ */
 void default_handler(ddf_fun_t *fun, ipc_callid_t id, ipc_call_t *call)
 {
Index: uspace/drv/char/xtkbd/Makefile
===================================================================
--- uspace/drv/char/xtkbd/Makefile	(revision 2f79a38dd6a40386b181045cc2e754875bf24fec)
+++ uspace/drv/char/xtkbd/Makefile	(revision bd87ae077e8b79fbea920fcc3c62b1f896e52b38)
@@ -33,4 +33,5 @@
 
 SOURCES = \
+	chardev.c \
 	main.c \
 	xtkbd.c
Index: uspace/drv/char/xtkbd/chardev.c
===================================================================
--- uspace/drv/char/xtkbd/chardev.c	(revision bd87ae077e8b79fbea920fcc3c62b1f896e52b38)
+++ uspace/drv/char/xtkbd/chardev.c	(revision bd87ae077e8b79fbea920fcc3c62b1f896e52b38)
@@ -0,0 +1,68 @@
+/*
+ * 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,
+};
+
+ssize_t chardev_read(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;
+}
+
+ssize_t chardev_write(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]);
+}
Index: uspace/drv/char/xtkbd/chardev.h
===================================================================
--- uspace/drv/char/xtkbd/chardev.h	(revision bd87ae077e8b79fbea920fcc3c62b1f896e52b38)
+++ uspace/drv/char/xtkbd/chardev.h	(revision bd87ae077e8b79fbea920fcc3c62b1f896e52b38)
@@ -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 drvkbd
+ * @{
+ */
+/** @file
+ * @brief ps/2 mouse driver.
+ */
+
+#ifndef _CHARDEV_H_
+#define _CHARDEV_H_
+
+#include <libarch/types.h>
+#include <async.h>
+
+ssize_t chardev_read(async_exch_t *, void *, size_t);
+ssize_t chardev_write(async_exch_t *, const void *, size_t);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/char/xtkbd/xtkbd.c
===================================================================
--- uspace/drv/char/xtkbd/xtkbd.c	(revision 2f79a38dd6a40386b181045cc2e754875bf24fec)
+++ uspace/drv/char/xtkbd/xtkbd.c	(revision bd87ae077e8b79fbea920fcc3c62b1f896e52b38)
@@ -35,5 +35,4 @@
 #include <errno.h>
 #include <devman.h>
-#include <device/char_dev.h>
 #include <ddf/log.h>
 #include <io/keycode.h>
@@ -42,4 +41,5 @@
 #include <abi/ipc/methods.h>
 
+#include "chardev.h"
 #include "xtkbd.h"
 
@@ -259,10 +259,14 @@
 
 	assert(kbd->parent_sess);
+	async_exch_t *parent_exch = async_exchange_begin(kbd->parent_sess);
 	while (1) {
+		if (!parent_exch)
+			parent_exch = async_exchange_begin(kbd->parent_sess);
+
 		const int *map = scanmap_simple;
 		size_t map_size = sizeof(scanmap_simple) / sizeof(int);
 
 		uint8_t code = 0;
-		ssize_t size = char_dev_read(kbd->parent_sess, &code, 1);
+		ssize_t size = chardev_read(parent_exch, &code, 1);
 
 		/** Ignore AT command reply */
@@ -274,5 +278,5 @@
 			map = scanmap_e0;
 			map_size = sizeof(scanmap_e0) / sizeof(int);
-			size = char_dev_read(kbd->parent_sess, &code, 1);
+			size = chardev_read(parent_exch, &code, 1);
 			// TODO handle print screen
 		}
@@ -334,6 +338,7 @@
 		    ((mods & KM_SCROLL_LOCK) ? LI_SCROLL : 0);
 		uint8_t cmds[] = { KBD_CMD_SET_LEDS, status };
-		const ssize_t size =
-		     char_dev_write(kbd->parent_sess, cmds, sizeof(cmds));
+		async_exch_t *exch = async_exchange_begin(kbd->parent_sess);
+		const ssize_t size = chardev_write(exch, cmds, sizeof(cmds));
+		async_exchange_end(exch);
 		async_answer_0(icallid, size < 0 ? size : EOK);
 		break;
