Index: uspace/lib/c/Makefile
===================================================================
--- uspace/lib/c/Makefile	(revision 503ffceaab0f4c54907677d3399c3ed1363e507f)
+++ uspace/lib/c/Makefile	(revision 98cb5e0d438f111dd28c92d57d12c9aa74bd2f98)
@@ -143,4 +143,5 @@
 	generic/getopt.c \
 	generic/adt/checksum.c \
+	generic/adt/circ_buf.c \
 	generic/adt/list.c \
 	generic/adt/hash_table.c \
@@ -181,4 +182,5 @@
 
 TEST_SOURCES = \
+	test/adt/circ_buf.c \
 	test/fibril/timer.c \
 	test/main.c \
Index: uspace/lib/c/generic/adt/circ_buf.c
===================================================================
--- uspace/lib/c/generic/adt/circ_buf.c	(revision 98cb5e0d438f111dd28c92d57d12c9aa74bd2f98)
+++ uspace/lib/c/generic/adt/circ_buf.c	(revision 98cb5e0d438f111dd28c92d57d12c9aa74bd2f98)
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2017 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 Circular buffer
+ */
+
+#include <adt/circ_buf.h>
+#include <errno.h>
+#include <mem.h>
+#include <stddef.h>
+
+/** Initialize circular buffer.
+ *
+ * @param cbuf Circular buffer
+ * @param buf Buffer for storing data
+ * @param nmemb Number of entries in @a buf
+ * @param size Size of individual buffer entry
+ */
+void circ_buf_init(circ_buf_t *cbuf, void *buf, size_t nmemb, size_t size)
+{
+	cbuf->buf = buf;
+	cbuf->nmemb = nmemb;
+	cbuf->size = size;
+	cbuf->rp = 0;
+	cbuf->wp = 0;
+	cbuf->nused = 0;
+}
+
+/** Return number of free buffer entries.
+ *
+ * @param cbuf Circular buffer
+ * @return Number of free buffer entries
+ */
+size_t circ_buf_nfree(circ_buf_t *cbuf)
+{
+	return cbuf->nmemb - cbuf->nused;
+}
+
+/** Return number of used buffer entries.
+ *
+ * @param cbuf Circular buffer
+ * @return Number of used buffer entries
+ */
+size_t circ_buf_nused(circ_buf_t *cbuf)
+{
+	return cbuf->nused;
+}
+
+/** Push new entry into circular buffer.
+ *
+ * @param cbuf Circular buffer
+ * @param data Pointer to entry data
+ * @return EOK on success, EAGAIN if circular buffer is full
+ */
+int circ_buf_push(circ_buf_t *cbuf, const void *data)
+{
+	if (circ_buf_nfree(cbuf) == 0)
+		return EAGAIN;
+
+	memcpy(cbuf->buf + cbuf->size * cbuf->wp, data, cbuf->size);
+	cbuf->wp = (cbuf->wp + 1) % cbuf->nmemb;
+	cbuf->nused++;
+	return EOK;
+}
+
+/** Pop entry from circular buffer.
+ *
+ * @param cbuf Circular buffer
+ * @param datab Pointer to data buffer for storing entry
+ * @return EOK on success, EAGAIN if circular buffer is full
+ */
+int circ_buf_pop(circ_buf_t *cbuf, void *datab)
+{
+	if (cbuf->nused == 0)
+		return EAGAIN;
+
+	memcpy(datab, cbuf->buf + cbuf->size * cbuf->rp, cbuf->size);
+	cbuf->rp = (cbuf->rp + 1) % cbuf->nmemb;
+	cbuf->nused--;
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/io/chardev_srv.c
===================================================================
--- uspace/lib/c/generic/io/chardev_srv.c	(revision 503ffceaab0f4c54907677d3399c3ed1363e507f)
+++ uspace/lib/c/generic/io/chardev_srv.c	(revision 98cb5e0d438f111dd28c92d57d12c9aa74bd2f98)
@@ -169,5 +169,8 @@
 			break;
 		default:
-			async_answer_0(callid, EINVAL);
+			if (srv->srvs->ops->def_handler != NULL)
+				srv->srvs->ops->def_handler(srv, callid, &call);
+			else
+				async_answer_0(callid, ENOTSUP);
 		}
 	}
Index: uspace/lib/c/include/adt/circ_buf.h
===================================================================
--- uspace/lib/c/include/adt/circ_buf.h	(revision 98cb5e0d438f111dd28c92d57d12c9aa74bd2f98)
+++ uspace/lib/c/include/adt/circ_buf.h	(revision 98cb5e0d438f111dd28c92d57d12c9aa74bd2f98)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2017 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 Circular buffer
+ */
+
+#ifndef LIBC_CIRC_BUF_H_
+#define LIBC_CIRC_BUF_H_
+
+#include <stddef.h>
+
+/** Circular buffer */
+typedef struct {
+	/** Buffer */
+	void *buf;
+	/** Number of buffer members */
+	size_t nmemb;
+	/** Member size */
+	size_t size;
+	/** Read position */
+	size_t rp;
+	/** Write position */
+	size_t wp;
+	/** Number of used entries */
+	size_t nused;
+} circ_buf_t;
+
+extern void circ_buf_init(circ_buf_t *, void *, size_t, size_t);
+extern size_t circ_buf_nfree(circ_buf_t *);
+extern size_t circ_buf_nused(circ_buf_t *);
+extern int circ_buf_push(circ_buf_t *, const void *);
+extern int circ_buf_pop(circ_buf_t *, void *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/io/chardev_srv.h
===================================================================
--- uspace/lib/c/include/io/chardev_srv.h	(revision 503ffceaab0f4c54907677d3399c3ed1363e507f)
+++ uspace/lib/c/include/io/chardev_srv.h	(revision 98cb5e0d438f111dd28c92d57d12c9aa74bd2f98)
@@ -61,4 +61,5 @@
 	int (*read)(chardev_srv_t *, void *, size_t, size_t *);
 	int (*write)(chardev_srv_t *, const void *, size_t, size_t *);
+	void (*def_handler)(chardev_srv_t *, ipc_callid_t, ipc_call_t *);
 };
 
Index: uspace/lib/c/include/ipc/char.h
===================================================================
--- uspace/lib/c/include/ipc/char.h	(revision 503ffceaab0f4c54907677d3399c3ed1363e507f)
+++ 	(revision )
@@ -1,52 +1,0 @@
-/*
- * Copyright (c) 2009 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 libcipc
- * @{
- */
-/** @file
- * @brief Character device interface.
- */
-
-#ifndef LIBC_IPC_CHAR_H_
-#define LIBC_IPC_CHAR_H_
-
-#include <ipc/common.h>
-
-typedef enum {
-	CHAR_WRITE_BYTE = IPC_FIRST_USER_METHOD
-} char_request_t;
-
-typedef enum {
-	CHAR_NOTIF_BYTE = IPC_FIRST_USER_METHOD
-} char_notif_t;
-
-#endif
-
-/** @}
- */
Index: uspace/lib/c/include/ipc/chardev.h
===================================================================
--- uspace/lib/c/include/ipc/chardev.h	(revision 503ffceaab0f4c54907677d3399c3ed1363e507f)
+++ uspace/lib/c/include/ipc/chardev.h	(revision 98cb5e0d438f111dd28c92d57d12c9aa74bd2f98)
@@ -41,6 +41,10 @@
 typedef enum {
 	CHARDEV_READ = IPC_FIRST_USER_METHOD,
-	CHARDEV_WRITE
+	CHARDEV_WRITE,
 } chardev_request_t;
+
+enum {
+	CHARDEV_LIMIT = CHARDEV_WRITE + 1
+};
 
 #endif
Index: uspace/lib/c/include/ipc/serial_ctl.h
===================================================================
--- uspace/lib/c/include/ipc/serial_ctl.h	(revision 503ffceaab0f4c54907677d3399c3ed1363e507f)
+++ uspace/lib/c/include/ipc/serial_ctl.h	(revision 98cb5e0d438f111dd28c92d57d12c9aa74bd2f98)
@@ -30,5 +30,5 @@
 #define LIBC_IPC_SERIAL_CTL_H_
 
-#include <ipc/dev_iface.h>
+#include <ipc/chardev.h>
 
 /** IPC methods for getting/setting serial communication properties
@@ -41,5 +41,5 @@
  */
 typedef enum {
-	SERIAL_GET_COM_PROPS = DEV_FIRST_CUSTOM_METHOD,
+	SERIAL_GET_COM_PROPS = CHARDEV_LIMIT,
 	SERIAL_SET_COM_PROPS
 } serial_ctl_t;
Index: uspace/lib/c/test/adt/circ_buf.c
===================================================================
--- uspace/lib/c/test/adt/circ_buf.c	(revision 98cb5e0d438f111dd28c92d57d12c9aa74bd2f98)
+++ uspace/lib/c/test/adt/circ_buf.c	(revision 98cb5e0d438f111dd28c92d57d12c9aa74bd2f98)
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2017 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.
+ */
+
+#include <adt/circ_buf.h>
+#include <pcut/pcut.h>
+
+PCUT_INIT
+
+PCUT_TEST_SUITE(circ_buf);
+
+enum {
+	buffer_size = 16
+};
+
+static int buffer[buffer_size];
+
+/** Basic insertion/deletion test.
+ *
+ * Test initialization, emptiness, pushing buffer until it is full,
+ * then emptying it again.
+ */
+PCUT_TEST(push_pop)
+{
+	circ_buf_t cbuf;
+	int i;
+	int j;
+	int rc;
+
+	circ_buf_init(&cbuf, buffer, buffer_size, sizeof(int));
+
+	for (i = 0; i < buffer_size; i++) {
+		PCUT_ASSERT_INT_EQUALS(buffer_size - i, circ_buf_nfree(&cbuf));
+		PCUT_ASSERT_INT_EQUALS(i, circ_buf_nused(&cbuf));
+		rc = circ_buf_push(&cbuf, &i);
+		PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	}
+
+	rc = circ_buf_push(&cbuf, &i);
+	PCUT_ASSERT_ERRNO_VAL(EAGAIN, rc);
+
+	for (i = 0; i < buffer_size; i++) {
+		PCUT_ASSERT_INT_EQUALS(i, circ_buf_nfree(&cbuf));
+		PCUT_ASSERT_INT_EQUALS(buffer_size - i, circ_buf_nused(&cbuf));
+		rc = circ_buf_pop(&cbuf, &j);
+		PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+		PCUT_ASSERT_INT_EQUALS(i, j);
+	}
+
+	PCUT_ASSERT_INT_EQUALS(buffer_size, circ_buf_nfree(&cbuf));
+	PCUT_ASSERT_INT_EQUALS(0, circ_buf_nused(&cbuf));
+
+	rc = circ_buf_pop(&cbuf, &j);
+	PCUT_ASSERT_ERRNO_VAL(EAGAIN, rc);
+}
+
+PCUT_EXPORT(circ_buf);
Index: uspace/lib/c/test/main.c
===================================================================
--- uspace/lib/c/test/main.c	(revision 503ffceaab0f4c54907677d3399c3ed1363e507f)
+++ uspace/lib/c/test/main.c	(revision 98cb5e0d438f111dd28c92d57d12c9aa74bd2f98)
@@ -32,4 +32,5 @@
 PCUT_INIT
 
+PCUT_IMPORT(circ_buf);
 PCUT_IMPORT(fibril_timer);
 PCUT_IMPORT(odict);
Index: uspace/lib/drv/Makefile
===================================================================
--- uspace/lib/drv/Makefile	(revision 503ffceaab0f4c54907677d3399c3ed1363e507f)
+++ uspace/lib/drv/Makefile	(revision 98cb5e0d438f111dd28c92d57d12c9aa74bd2f98)
@@ -43,5 +43,4 @@
 	generic/remote_hw_res.c \
 	generic/remote_pio_window.c \
-	generic/remote_char_dev.c \
 	generic/remote_nic.c \
 	generic/remote_ieee80211.c \
Index: uspace/lib/drv/generic/dev_iface.c
===================================================================
--- uspace/lib/drv/generic/dev_iface.c	(revision 503ffceaab0f4c54907677d3399c3ed1363e507f)
+++ uspace/lib/drv/generic/dev_iface.c	(revision 98cb5e0d438f111dd28c92d57d12c9aa74bd2f98)
@@ -42,5 +42,4 @@
 #include "remote_hw_res.h"
 #include "remote_pio_window.h"
-#include "remote_char_dev.h"
 #include "remote_clock_dev.h"
 #include "remote_led_dev.h"
@@ -62,5 +61,4 @@
 		[HW_RES_DEV_IFACE] = &remote_hw_res_iface,
 		[PIO_WINDOW_DEV_IFACE] = &remote_pio_window_iface,
-		[CHAR_DEV_IFACE] = &remote_char_dev_iface,
 		[NIC_DEV_IFACE] = &remote_nic_iface,
 		[IEEE80211_DEV_IFACE] = &remote_ieee80211_iface,
Index: uspace/lib/drv/generic/private/remote_char_dev.h
===================================================================
--- uspace/lib/drv/generic/private/remote_char_dev.h	(revision 503ffceaab0f4c54907677d3399c3ed1363e507f)
+++ 	(revision )
@@ -1,44 +1,0 @@
-/*
- * Copyright (c) 2010 Lenka Trochtova
- * 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 libdrv
- * @{
- */
-/** @file
- */
-
-#ifndef LIBDRV_REMOTE_CHAR_DEV_H_
-#define LIBDRV_REMOTE_CHAR_DEV_H_
-
-extern remote_iface_t remote_char_dev_iface;
-
-#endif
-
-/**
- * @}
- */
Index: uspace/lib/drv/generic/remote_char_dev.c
===================================================================
--- uspace/lib/drv/generic/remote_char_dev.c	(revision 503ffceaab0f4c54907677d3399c3ed1363e507f)
+++ 	(revision )
@@ -1,246 +1,0 @@
-/*
- * Copyright (c) 2010 Lenka Trochtova
- * 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 libdrv
- * @{
- */
-/** @file
- */
-
-#include <async.h>
-#include <errno.h>
-#include <macros.h>
-
-#include "ops/char_dev.h"
-#include "char_dev_iface.h"
-#include "ddf/driver.h"
-
-#define MAX_CHAR_RW_COUNT 256
-
-/** Read to or write from device.
- *
- * Helper function to read to or write from a device
- * using its character interface.
- *
- * @param sess Session to the device.
- * @param buf  Buffer for the data read from or written to the device.
- * @param size Maximum size of data (in bytes) to be read or written.
- * @param read Read from the device if true, write to it otherwise.
- *
- * @return Non-negative number of bytes actually read from or
- *         written to the device on success, negative error number
- *         otherwise.
- *
- */
-static ssize_t char_dev_rw(async_sess_t *sess, void *buf, size_t size, bool read)
-{
-	ipc_call_t answer;
-	aid_t req;
-	int ret;
-	
-	async_exch_t *exch = async_exchange_begin(sess);
-	
-	if (read) {
-		req = async_send_1(exch, DEV_IFACE_ID(CHAR_DEV_IFACE),
-		    CHAR_DEV_READ, &answer);
-		ret = async_data_read_start(exch, buf, size);
-	} else {
-		req = async_send_1(exch, DEV_IFACE_ID(CHAR_DEV_IFACE),
-		    CHAR_DEV_WRITE, &answer);
-		ret = async_data_write_start(exch, buf, size);
-	}
-	
-	async_exchange_end(exch);
-	
-	sysarg_t rc;
-	if (ret != EOK) {
-		async_wait_for(req, &rc);
-		if (rc == EOK)
-			return (ssize_t) ret;
-		
-		return (ssize_t) rc;
-	}
-	
-	async_wait_for(req, &rc);
-	
-	ret = (int) rc;
-	if (ret != EOK)
-		return (ssize_t) ret;
-	
-	return (ssize_t) IPC_GET_ARG1(answer);
-}
-
-/** Read from character device.
- *
- * @param sess Session to the device.
- * @param buf  Output buffer for the data read from the device.
- * @param size Maximum size (in bytes) of the data to be read.
- *
- * @return Non-negative number of bytes actually read from the
- *         device on success, negative error number otherwise.
- *
- */
-ssize_t char_dev_read(async_sess_t *sess, void *buf, size_t size)
-{
-	return char_dev_rw(sess, buf, size, true);
-}
-
-/** Write to character device.
- *
- * @param sess Session to the device.
- * @param buf  Input buffer containg the data to be written to the
- *             device.
- * @param size Maximum size (in bytes) of the data to be written.
- *
- * @return Non-negative number of bytes actually written to the
- *         device on success, negative error number otherwise.
- *
- */
-ssize_t char_dev_write(async_sess_t *sess, void *buf, size_t size)
-{
-	return char_dev_rw(sess, buf, size, false);
-}
-
-static void remote_char_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
-static void remote_char_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
-
-/** Remote character interface operations. */
-static const remote_iface_func_ptr_t remote_char_dev_iface_ops[] = {
-	[CHAR_DEV_READ] = remote_char_read,
-	[CHAR_DEV_WRITE] = remote_char_write
-};
-
-/** Remote character interface structure.
- *
- * Interface for processing request from remote clients addressed to the
- * character interface.
- */
-const remote_iface_t remote_char_dev_iface = {
-	.method_count = ARRAY_SIZE(remote_char_dev_iface_ops),
-	.methods = remote_char_dev_iface_ops
-};
-
-/** Process the read request from the remote client.
- *
- * Receive the read request's parameters from the remote client and pass them
- * to the local interface. Return the result of the operation processed by the
- * local interface to the remote client.
- *
- * @param fun		The function from which the data are read.
- * @param ops		The local ops structure.
- */
-static void
-remote_char_read(ddf_fun_t *fun, void *ops, ipc_callid_t callid,
-    ipc_call_t *call)
-{
-	char_dev_ops_t *char_dev_ops = (char_dev_ops_t *) ops;
-	ipc_callid_t cid;
-	
-	size_t len;
-	if (!async_data_read_receive(&cid, &len)) {
-		/* TODO handle protocol error. */
-		async_answer_0(callid, EINVAL);
-		return;
-	}
-	
-	if (!char_dev_ops->read) {
-		async_data_read_finalize(cid, NULL, 0);
-		async_answer_0(callid, ENOTSUP);
-		return;
-	}
-	
-	if (len > MAX_CHAR_RW_COUNT)
-		len = MAX_CHAR_RW_COUNT;
-	
-	char buf[MAX_CHAR_RW_COUNT];
-	int ret = (*char_dev_ops->read)(fun, buf, len);
-	
-	if (ret < 0) {
-		/* Some error occured. */
-		async_data_read_finalize(cid, buf, 0);
-		async_answer_0(callid, ret);
-		return;
-	}
-	
-	/* The operation was successful, return the number of data read. */
-	async_data_read_finalize(cid, buf, ret);
-	async_answer_1(callid, EOK, ret);
-}
-
-/** Process the write request from the remote client.
- *
- * Receive the write request's parameters from the remote client and pass them
- * to the local interface. Return the result of the operation processed by the
- * local interface to the remote client.
- *
- * @param fun		The function to which the data are written.
- * @param ops		The local ops structure.
- */
-static void
-remote_char_write(ddf_fun_t *fun, void *ops, ipc_callid_t callid,
-    ipc_call_t *call)
-{
-	char_dev_ops_t *char_dev_ops = (char_dev_ops_t *) ops;
-	ipc_callid_t cid;
-	size_t len;
-	
-	if (!async_data_write_receive(&cid, &len)) {
-		/* TODO handle protocol error. */
-		async_answer_0(callid, EINVAL);
-		return;
-	}
-	
-	if (!char_dev_ops->write) {
-		async_data_write_finalize(cid, NULL, 0);
-		async_answer_0(callid, ENOTSUP);
-		return;
-	}
-	
-	if (len > MAX_CHAR_RW_COUNT)
-		len = MAX_CHAR_RW_COUNT;
-	
-	char buf[MAX_CHAR_RW_COUNT];
-	
-	async_data_write_finalize(cid, buf, len);
-	
-	int ret = (*char_dev_ops->write)(fun, buf, len);
-	if (ret < 0) {
-		/* Some error occured. */
-		async_answer_0(callid, ret);
-	} else {
-		/*
-		 * The operation was successful, return the number of data
-		 * written.
-		 */
-		async_answer_1(callid, EOK, ret);
-	}
-}
-
-/**
- * @}
- */
