Index: uspace/drv/char/i8042/i8042.c
===================================================================
--- uspace/drv/char/i8042/i8042.c	(revision 19ea61d4d9f3c1ab64d2df09da1ad3f2772d554f)
+++ uspace/drv/char/i8042/i8042.c	(revision 677cad5e3bf910241afff855ef729cbe70035d68)
@@ -67,6 +67,6 @@
 
 static void i8042_char_conn(ipc_callid_t, ipc_call_t *, void *);
-static int i8042_read(chardev_srv_t *, void *, size_t);
-static int i8042_write(chardev_srv_t *, const void *, size_t);
+static int i8042_read(chardev_srv_t *, void *, size_t, size_t *);
+static int i8042_write(chardev_srv_t *, const void *, size_t, size_t *);
 
 static chardev_ops_t i8042_chardev_ops = {
@@ -333,9 +333,11 @@
  * @param buffer Data source
  * @param size   Data size
- *
- * @return Bytes written.
- *
- */
-static int i8042_write(chardev_srv_t *srv, const void *data, size_t size)
+ * @param nwr    Place to store number of bytes successfully written
+ *
+ * @return EOK on success or non-zero error code
+ *
+ */
+static int i8042_write(chardev_srv_t *srv, const void *data, size_t size,
+    size_t *nwr)
 {
 	i8042_port_t *port = (i8042_port_t *)srv->srvs->sarg;
@@ -357,5 +359,6 @@
 	
 	fibril_mutex_unlock(&i8042->write_guard);
-	return size;
+	*nwr = size;
+	return EOK;
 }
 
@@ -365,9 +368,11 @@
  * @param buffer Data place
  * @param size   Data place size
- *
- * @return Bytes read.
- *
- */
-static int i8042_read(chardev_srv_t *srv, void *dest, size_t size)
+ * @param nread  Place to store number of bytes successfully read
+ *
+ * @return EOK on success or non-zero error code
+ *
+ */
+static int i8042_read(chardev_srv_t *srv, void *dest, size_t size,
+    size_t *nread)
 {
 	i8042_port_t *port = (i8042_port_t *)srv->srvs->sarg;
@@ -387,5 +392,6 @@
 	}
 	
-	return i;
+	*nread = i;
+	return EOK;
 }
 
Index: uspace/drv/char/pl050/pl050.c
===================================================================
--- uspace/drv/char/pl050/pl050.c	(revision 19ea61d4d9f3c1ab64d2df09da1ad3f2772d554f)
+++ uspace/drv/char/pl050/pl050.c	(revision 677cad5e3bf910241afff855ef729cbe70035d68)
@@ -54,6 +54,6 @@
 static int pl050_fun_offline(ddf_fun_t *);
 static void pl050_char_conn(ipc_callid_t, ipc_call_t *, void *);
-static int pl050_read(chardev_srv_t *, void *, size_t);
-static int pl050_write(chardev_srv_t *, const void *, size_t);
+static int pl050_read(chardev_srv_t *, void *, size_t, size_t *);
+static int pl050_write(chardev_srv_t *, const void *, size_t, size_t *);
 
 static driver_ops_t driver_ops = {
@@ -236,5 +236,6 @@
 }
 
-static int pl050_read(chardev_srv_t *srv, void *buffer, size_t size)
+static int pl050_read(chardev_srv_t *srv, void *buffer, size_t size,
+    size_t *nread)
 {
 	pl050_t *pl050 = (pl050_t *)srv->srvs->sarg;
@@ -257,8 +258,10 @@
 	fibril_mutex_unlock(&pl050->buf_lock);
 
-	return size - left;
-}
-
-static int pl050_write(chardev_srv_t *srv, const void *data, size_t size)
+	*nread = size - left;
+	return EOK;
+}
+
+static int pl050_write(chardev_srv_t *srv, const void *data, size_t size,
+    size_t *nwritten)
 {
 	pl050_t *pl050 = (pl050_t *)srv->srvs->sarg;
@@ -278,5 +281,6 @@
 	ddf_msg(LVL_NOTE, "%s/pl050_write() success", pl050->name);
 
-	return size;
+	*nwritten = size;
+	return EOK;
 }
 
Index: uspace/lib/c/generic/io/chardev_srv.c
===================================================================
--- uspace/lib/c/generic/io/chardev_srv.c	(revision 19ea61d4d9f3c1ab64d2df09da1ad3f2772d554f)
+++ uspace/lib/c/generic/io/chardev_srv.c	(revision 677cad5e3bf910241afff855ef729cbe70035d68)
@@ -48,4 +48,5 @@
 	void *buf;
 	size_t size;
+	size_t nread;
 	int rc;
 	ipc_callid_t rcallid;
@@ -70,6 +71,6 @@
 	}
 
-	rc = srv->srvs->ops->read(srv, buf, size);
-	if (rc < 0) {
+	rc = srv->srvs->ops->read(srv, buf, size, &nread);
+	if (rc != EOK && nread == 0) {
 		async_answer_0(rcallid, rc);
 		async_answer_0(callid, rc);
@@ -78,8 +79,8 @@
 	}
 
-	async_data_read_finalize(rcallid, buf, size);
+	async_data_read_finalize(rcallid, buf, nread);
 
 	free(buf);
-	async_answer_2(callid, EOK, EOK, rc /* nread */);
+	async_answer_2(callid, EOK, rc, nread);
 }
 
@@ -89,4 +90,5 @@
 	void *data;
 	size_t size;
+	size_t nwr;
 	int rc;
 
@@ -102,10 +104,12 @@
 	}
 
-	rc = srv->srvs->ops->write(srv, data, size);
+	rc = srv->srvs->ops->write(srv, data, size, &nwr);
 	free(data);
-	if (rc < 0)
+	if (rc != EOK && nwr == 0) {
 		async_answer_0(callid, rc);
+		return;
+	}
 
-	async_answer_2(callid, EOK, EOK, rc /* nwritten */);
+	async_answer_2(callid, EOK, rc, nwr);
 }
 
Index: uspace/lib/c/include/io/chardev_srv.h
===================================================================
--- uspace/lib/c/include/io/chardev_srv.h	(revision 19ea61d4d9f3c1ab64d2df09da1ad3f2772d554f)
+++ uspace/lib/c/include/io/chardev_srv.h	(revision 677cad5e3bf910241afff855ef729cbe70035d68)
@@ -59,6 +59,6 @@
 	int (*open)(chardev_srvs_t *, chardev_srv_t *);
 	int (*close)(chardev_srv_t *);
-	int (*read)(chardev_srv_t *, void *, size_t);
-	int (*write)(chardev_srv_t *, const void *, size_t);
+	int (*read)(chardev_srv_t *, void *, size_t, size_t *);
+	int (*write)(chardev_srv_t *, const void *, size_t, size_t *);
 };
 
