Index: uspace/lib/libc/generic/device/char.c
===================================================================
--- uspace/lib/libc/generic/device/char.c	(revision ba95e8f41817124410b7cfa7c805434f83686dff)
+++ uspace/lib/libc/generic/device/char.c	(revision ca97cad5803ad9a8511c331f8c9583385867b64d)
@@ -40,14 +40,33 @@
 #include <stdio.h>
 
-
-int read_dev(int dev_phone, void *buf, size_t len)
-{	
+/** Read to or write from the device using its character interface.
+ * 
+ * Helper function.
+ * 
+ * @param dev_phone phone to the device.
+ * @param buf the buffer for the data read from or written to the device.
+ * @param len the maximum length of the data 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 int rw_dev(int dev_phone, void *buf, size_t len, bool read) 
+{
 	ipc_call_t answer;
 	
 	async_serialize_start();
 	
-	aid_t req = async_send_1(dev_phone, DEV_IFACE_ID(CHAR_DEV_IFACE), CHAR_READ_DEV, &answer);
+	aid_t req;
+	int rc;
 	
-	int rc = async_data_read_start(dev_phone, buf, len);
+	if (read) {
+		req = async_send_1(dev_phone, DEV_IFACE_ID(CHAR_DEV_IFACE), CHAR_READ_DEV, &answer);
+		rc = async_data_read_start(dev_phone, buf, len);		
+	} else {
+		req = async_send_1(dev_phone, DEV_IFACE_ID(CHAR_DEV_IFACE), CHAR_WRITE_DEV, &answer);
+		rc = async_data_write_start(dev_phone, buf, len);
+	}
 	
 	if (rc != EOK) {
@@ -70,11 +89,31 @@
 	}
 	
-	return IPC_GET_ARG1(answer);
+	return IPC_GET_ARG1(answer);	
 }
 
+/** Read from the device using its character interface.
+ * 
+ * @param dev_phone phone to the device.
+ * @param buf the output buffer for the data read from the device.
+ * @param len the maximum length of the data to be read.
+ * 
+ * @return non-negative number of bytes actually read from the device on success, negative error number otherwise.
+ */
+int read_dev(int dev_phone, void *buf, size_t len)
+{	
+	return rw_dev(dev_phone, buf, len, true);
+}
+
+/** Write to the device using its character interface.
+ * 
+ * @param dev_phone phone to the device.
+ * @param buf the input buffer containg the data to be written to the device.
+ * @param len the maximum length of the data to be written.
+ * 
+ * @return non-negative number of bytes actually written to the device on success, negative error number otherwise.
+ */
 int write_dev(int dev_phone, void *buf, size_t len)
 {
-	// TODO
-	return 0;
+	return rw_dev(dev_phone, buf, len, false);
 }
 
Index: uspace/lib/libdrv/generic/remote_char.c
===================================================================
--- uspace/lib/libdrv/generic/remote_char.c	(revision ba95e8f41817124410b7cfa7c805434f83686dff)
+++ uspace/lib/libdrv/generic/remote_char.c	(revision ca97cad5803ad9a8511c331f8c9583385867b64d)
@@ -45,4 +45,6 @@
 static void remote_char_write(device_t *dev, void *iface, ipc_callid_t callid, ipc_call_t *call);
 
+/** Remote character interface operations. 
+ */
 static remote_iface_func_ptr_t remote_char_iface_ops [] = {
 	&remote_char_read,
@@ -50,4 +52,7 @@
 }; 
  
+/** Remote character interface structure. 
+ * Interface for processing request from remote clients addressed to the character interface.
+ */
 remote_iface_t remote_char_iface = {
 	.method_count = sizeof(remote_char_iface_ops) / sizeof(remote_iface_func_ptr_t),
@@ -55,4 +60,12 @@
 };
 
+/** 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 dev the device from which the data are read.
+ * @param iface the local interface structure. 
+ */
 static void remote_char_read(device_t *dev, void *iface, ipc_callid_t callid, ipc_call_t *call)
 {	
@@ -86,21 +99,34 @@
 	}
 	
+	// the operation was successful, return the number of data read
 	async_data_read_finalize(cid, buf, ret);
 	ipc_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 dev the device to which the data are written.
+ * @param iface the local interface structure. 
+ */
 static void remote_char_write(device_t *dev, void *iface, ipc_callid_t callid, ipc_call_t *call)
 {
 	char_iface_t *char_iface = (char_iface_t *)iface;
+	ipc_callid_t cid;
+	size_t len;
+	
+	if (!async_data_write_receive(&cid, &len)) {
+		// TODO handle protocol error
+		ipc_answer_0(callid, EINVAL);
+		return;
+    }
+	
 	if (!char_iface->write) {
+		async_data_write_finalize(cid, NULL, 0);
 		ipc_answer_0(callid, ENOTSUP);
 		return;
 	}	
-	
-	size_t len;
-	if (!async_data_write_receive(&callid, &len)) {
-		// TODO handle protocol error
-		return;
-    }
 	
 	if (len > MAX_CHAR_RW_COUNT) {
@@ -110,5 +136,5 @@
 	char buf[MAX_CHAR_RW_COUNT];
 	
-	async_data_write_finalize(callid, buf, len);
+	async_data_write_finalize(cid, buf, len);
 	
 	int ret = (*char_iface->write)(dev, buf, len);
@@ -116,4 +142,5 @@
 		ipc_answer_0(callid, ret);
 	} else {
+		// the operation was successful, return the number of data written
 		ipc_answer_1(callid, EOK, ret);
 	}
