Index: uspace/drv/char/i8042/buffer.h
===================================================================
--- uspace/drv/char/i8042/buffer.h	(revision 5d50c419de1e8d7b6b57065ea652ba23b83e5a97)
+++ uspace/drv/char/i8042/buffer.h	(revision c657bd7f48e0cda0c4e65bc45f24367c51318513)
@@ -113,15 +113,22 @@
  *
  * @param buffer Cyclic buffer to read from.
+ * @param rb Place to store byte read
+ * @param wait @c True to wait until byte is available
  *
- * @return Byte read.
+ * @return EOK on success, EAGAIN if @c wait is false and no data is available
  *
  */
-static inline uint8_t buffer_read(buffer_t *buffer)
+static inline int buffer_read(buffer_t *buffer, uint8_t *rb, bool wait)
 {
 	fibril_mutex_lock(&buffer->guard);
 	
 	/* Buffer is empty. */
-	while (buffer->write_head == buffer->read_head)
+	while (wait && buffer->write_head == buffer->read_head)
 		fibril_condvar_wait(&buffer->change, &buffer->guard);
+	
+	if (buffer->write_head == buffer->read_head) {
+		fibril_mutex_unlock(&buffer->guard);
+		return EAGAIN;
+	}
 	
 	/* Next position. */
@@ -144,5 +151,6 @@
 	
 	fibril_mutex_unlock(&buffer->guard);
-	return data;
+	*rb = data;
+	return EOK;
 }
 
Index: uspace/drv/char/i8042/i8042.c
===================================================================
--- uspace/drv/char/i8042/i8042.c	(revision 5d50c419de1e8d7b6b57065ea652ba23b83e5a97)
+++ uspace/drv/char/i8042/i8042.c	(revision c657bd7f48e0cda0c4e65bc45f24367c51318513)
@@ -374,12 +374,18 @@
 	i8042_t *i8042 = port->ctl;
 	uint8_t *destp = (uint8_t *)dest;
+	int rc;
+	size_t i;
 	
 	buffer_t *buffer = (port == i8042->aux) ?
 	    &i8042->aux_buffer : &i8042->kbd_buffer;
 	
-	for (size_t i = 0; i < size; ++i)
-		*destp++ = buffer_read(buffer);
-	
-	return size;
+	for (i = 0; i < size; ++i) {
+		rc = buffer_read(buffer, destp, i == 0);
+		if (rc != EOK)
+			break;
+		++destp;
+	}
+	
+	return i;
 }
 
Index: uspace/drv/char/pl050/pl050.c
===================================================================
--- uspace/drv/char/pl050/pl050.c	(revision 5d50c419de1e8d7b6b57065ea652ba23b83e5a97)
+++ uspace/drv/char/pl050/pl050.c	(revision c657bd7f48e0cda0c4e65bc45f24367c51318513)
@@ -246,6 +246,8 @@
 	left = size;
 	while (left > 0) {
-		while (pl050->buf_rp == pl050->buf_wp)
+		while (left == size && pl050->buf_rp == pl050->buf_wp)
 			fibril_condvar_wait(&pl050->buf_cv, &pl050->buf_lock);
+		if (pl050->buf_rp == pl050->buf_wp)
+			break;
 		*bp++ = pl050->buffer[pl050->buf_rp];
 		--left;
@@ -255,5 +257,5 @@
 	fibril_mutex_unlock(&pl050->buf_lock);
 
-	return size;
+	return size - left;
 }
 
Index: uspace/drv/hid/ps2mouse/ps2mouse.c
===================================================================
--- uspace/drv/hid/ps2mouse/ps2mouse.c	(revision 5d50c419de1e8d7b6b57065ea652ba23b83e5a97)
+++ uspace/drv/hid/ps2mouse/ps2mouse.c	(revision c657bd7f48e0cda0c4e65bc45f24367c51318513)
@@ -212,4 +212,35 @@
 }
 
+/** Read fixed-size mouse packet.
+ *
+ * Continue reading until entire packet is received.
+ *
+ * @param mouse Mouse device
+ * @param pbuf Buffer for storing packet
+ * @param psize Packet size
+ *
+ * @return EOK on success or non-zero error code
+ */
+static int ps2_mouse_read_packet(ps2_mouse_t *mouse, void *pbuf, size_t psize)
+{
+	int rc;
+	size_t pos;
+	size_t nread;
+
+	pos = 0;
+	while (pos < psize) {
+		rc = chardev_read(mouse->chardev, pbuf + pos, psize - pos,
+		    &nread);
+		if (rc != EOK) {
+			ddf_msg(LVL_WARN, "Error reading packet.");
+			return rc;
+		}
+
+		pos += nread;
+	}
+
+	return EOK;
+}
+
 /** Get data and parse ps2 protocol packets.
  * @param arg Pointer to ps2_mouse_t structure.
@@ -219,5 +250,4 @@
 {
 	ps2_mouse_t *mouse = (ps2_mouse_t *) arg;
-	size_t nread;
 	int rc;
 
@@ -225,9 +255,7 @@
 	while (1) {
 		uint8_t packet[PS2_BUFSIZE] = {};
-		rc = chardev_read(mouse->chardev, packet, PS2_BUFSIZE, &nread);
-		if (rc != EOK || nread != PS2_BUFSIZE) {
-			ddf_msg(LVL_WARN, "Incorrect packet size: %zd.", nread);
+		rc = ps2_mouse_read_packet(mouse, packet, PS2_BUFSIZE);
+		if (rc != EOK)
 			continue;
-		}
 
 		ddf_msg(LVL_DEBUG2, "Got packet: %hhx:%hhx:%hhx.",
@@ -274,5 +302,4 @@
 {
 	ps2_mouse_t *mouse = (ps2_mouse_t *) arg;
-	size_t nread;
 	int rc;
 
@@ -280,10 +307,8 @@
 	while (1) {
 		uint8_t packet[INTELLIMOUSE_BUFSIZE] = {};
-		rc = chardev_read(mouse->chardev, packet, INTELLIMOUSE_BUFSIZE,
-		    &nread);
-		if (rc != EOK || nread != INTELLIMOUSE_BUFSIZE) {
-			ddf_msg(LVL_WARN, "Incorrect packet size: %zd.", nread);
+		rc = ps2_mouse_read_packet(mouse, packet, INTELLIMOUSE_BUFSIZE);
+		if (rc != EOK)
 			continue;
-		}
+
 		ddf_msg(LVL_DEBUG2, "Got packet: %hhx:%hhx:%hhx:%hhx.",
 		    packet[0], packet[1], packet[2], packet[3]);
Index: uspace/drv/hid/xtkbd/xtkbd.c
===================================================================
--- uspace/drv/hid/xtkbd/xtkbd.c	(revision 5d50c419de1e8d7b6b57065ea652ba23b83e5a97)
+++ uspace/drv/hid/xtkbd/xtkbd.c	(revision c657bd7f48e0cda0c4e65bc45f24367c51318513)
@@ -353,8 +353,11 @@
 		
 		size_t nwr;
-		int rc = chardev_write(kbd->chardev, cmds, sizeof(cmds), &nwr);
-		if (nwr != sizeof(cmds))
-			rc = EIO;
-
+		int rc = chardev_write(kbd->chardev, &cmds[0], 1, &nwr);
+		if (rc != EOK) {
+			async_answer_0(icallid, rc);
+			break;
+		}
+
+		rc = chardev_write(kbd->chardev, &cmds[1], 1, &nwr);
 		async_answer_0(icallid, rc);
 		break;
