Index: uspace/drv/char/i8042/buffer.h
===================================================================
--- uspace/drv/char/i8042/buffer.h	(revision 7a6065c264dbab78e1758685fd1eda498ab9b73d)
+++ 	(revision )
@@ -1,161 +1,0 @@
-/*
- * 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 kbd
- * @{
- */
-
-/** @file
- * @brief Cyclic buffer structure.
- */
-
-#ifndef BUFFER_H_
-#define BUFFER_H_
-
-#include <assert.h>
-#include <fibril_synch.h>
-
-/** Cyclic buffer that blocks on full/empty.
- *
- * read_head == write_head means that the buffer is empty.
- * write_head + 1 == read_head means that the buffer is full.
- * Attempt to insert byte into the full buffer will block until it can succeed.
- * Attempt to read from empty buffer will block until it can succeed.
- *
- */
-typedef struct {
-	uint8_t *buffer;          /**< Storage space. */
-	uint8_t *buffer_end;      /**< End of storage place. */
-	fibril_mutex_t guard;     /**< Protects buffer structures. */
-	fibril_condvar_t change;  /**< Indicates change (empty/full). */
-	uint8_t *read_head;       /**< Place of the next readable element. */
-	uint8_t *write_head;      /**< Pointer to the next writable place. */
-} buffer_t;
-
-/** Initialize cyclic buffer using provided memory space.
- *
- * @param buffer Cyclic buffer structure to initialize.
- * @param data   Memory space to use.
- * @param size   Size of the memory place.
- *
- */
-static inline void buffer_init(buffer_t *buffer, uint8_t *data, size_t size)
-{
-	assert(buffer);
-	
-	fibril_mutex_initialize(&buffer->guard);
-	fibril_condvar_initialize(&buffer->change);
-	buffer->buffer = data;
-	buffer->buffer_end = data + size;
-	buffer->read_head = buffer->buffer;
-	buffer->write_head = buffer->buffer;
-	memset(buffer->buffer, 0, size);
-}
-
-/** Write byte to cyclic buffer.
- *
- * @param buffer Cyclic buffer to write to.
- * @param data   Data to write.
- *
- */
-static inline void buffer_write(buffer_t *buffer, uint8_t data)
-{
-	fibril_mutex_lock(&buffer->guard);
-	
-	/* Next position. */
-	uint8_t *new_head = buffer->write_head + 1;
-	if (new_head == buffer->buffer_end)
-		new_head = buffer->buffer;
-	
-	/* Buffer full. */
-	while (new_head == buffer->read_head)
-		fibril_condvar_wait(&buffer->change, &buffer->guard);
-	
-	/* Write data. */
-	*buffer->write_head = data;
-	
-	/* Buffer was empty. */
-	if (buffer->write_head == buffer->read_head)
-		fibril_condvar_broadcast(&buffer->change);
-	
-	/* Move head */
-	buffer->write_head = new_head;
-	fibril_mutex_unlock(&buffer->guard);
-}
-
-/** Read byte from cyclic buffer.
- *
- * @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 EOK on success, EAGAIN if @c wait is false and no data is available
- *
- */
-static inline int buffer_read(buffer_t *buffer, uint8_t *rb, bool wait)
-{
-	fibril_mutex_lock(&buffer->guard);
-	
-	/* Buffer is empty. */
-	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. */
-	uint8_t *new_head = buffer->read_head + 1;
-	if (new_head == buffer->buffer_end)
-		new_head = buffer->buffer;
-	
-	/* Read data. */
-	const uint8_t data = *buffer->read_head;
-	
-	/* Buffer was full. */
-	uint8_t *new_write_head = buffer->write_head + 1;
-	if (new_write_head == buffer->buffer_end)
-		new_write_head = buffer->buffer;
-	if (new_write_head == buffer->read_head)
-		fibril_condvar_broadcast(&buffer->change);
-	
-	/* Move head */
-	buffer->read_head = new_head;
-	
-	fibril_mutex_unlock(&buffer->guard);
-	*rb = data;
-	return EOK;
-}
-
-#endif
-
-/**
- * @}
- */
Index: uspace/drv/char/i8042/i8042.c
===================================================================
--- uspace/drv/char/i8042/i8042.c	(revision 7a6065c264dbab78e1758685fd1eda498ab9b73d)
+++ uspace/drv/char/i8042/i8042.c	(revision e7588a831a1d2d5847475a67a5b1bc4b10366d7c)
@@ -2,5 +2,5 @@
  * Copyright (c) 2001-2004 Jakub Jermar
  * Copyright (c) 2006 Josef Cejka
- * Copyright (c) 2014 Jiri Svoboda
+ * Copyright (c) 2017 Jiri Svoboda
  * Copyright (c) 2011 Jan Vesely
  * All rights reserved.
@@ -39,4 +39,5 @@
  */
 
+#include <adt/circ_buf.h>
 #include <ddf/log.h>
 #include <ddf/interrupt.h>
@@ -130,12 +131,22 @@
 {
 	i8042_t *controller = ddf_dev_data_get(dev);
+	int rc;
 	
 	const uint8_t status = IPC_GET_ARG1(*call);
 	const uint8_t data = IPC_GET_ARG2(*call);
 	
-	buffer_t *buffer = (status & i8042_AUX_DATA) ?
+	circ_buf_t *cbuf = (status & i8042_AUX_DATA) ?
 	    &controller->aux_buffer : &controller->kbd_buffer;
-	
-	buffer_write(buffer, data);
+	i8042_port_t *port = (status & i8042_AUX_DATA) ?
+	    controller->aux : controller->kbd;
+	
+	fibril_mutex_lock(&port->buf_lock);
+	
+	rc = circ_buf_push(cbuf, &data);
+	if (rc != EOK)
+		ddf_msg(LVL_ERROR, "Buffer overrun");
+
+	fibril_mutex_unlock(&port->buf_lock);
+	fibril_condvar_broadcast(&port->buf_cv);
 }
 
@@ -194,4 +205,6 @@
 	dev->kbd->cds.ops = &i8042_chardev_ops;
 	dev->kbd->cds.sarg = dev->kbd;
+	fibril_mutex_initialize(&dev->kbd->buf_lock);
+	fibril_condvar_initialize(&dev->kbd->buf_cv);
 	
 	rc = ddf_fun_add_match_id(dev->kbd_fun, "char/xtkbd", 90);
@@ -215,4 +228,6 @@
 	dev->aux->cds.ops = &i8042_chardev_ops;
 	dev->aux->cds.sarg = dev->aux;
+	fibril_mutex_initialize(&dev->aux->buf_lock);
+	fibril_condvar_initialize(&dev->aux->buf_cv);
 	
 	rc = ddf_fun_add_match_id(dev->aux_fun, "char/ps2mouse", 90);
@@ -223,6 +238,6 @@
 	ddf_fun_set_conn_handler(dev->aux_fun, i8042_char_conn);
 	
-	buffer_init(&dev->kbd_buffer, dev->kbd_data, BUFFER_SIZE);
-	buffer_init(&dev->aux_buffer, dev->aux_data, BUFFER_SIZE);
+	circ_buf_init(&dev->kbd_buffer, dev->kbd_data, BUFFER_SIZE, 1);
+	circ_buf_init(&dev->aux_buffer, dev->aux_data, BUFFER_SIZE, 1);
 	fibril_mutex_initialize(&dev->write_guard);
 	
@@ -377,20 +392,28 @@
 {
 	i8042_port_t *port = (i8042_port_t *)srv->srvs->sarg;
+	size_t p;
 	i8042_t *i8042 = port->ctl;
 	uint8_t *destp = (uint8_t *)dest;
 	int rc;
-	size_t i;
-	
-	buffer_t *buffer = (port == i8042->aux) ?
+	
+	circ_buf_t *cbuf = (port == i8042->aux) ?
 	    &i8042->aux_buffer : &i8042->kbd_buffer;
 	
-	for (i = 0; i < size; ++i) {
-		rc = buffer_read(buffer, destp, i == 0);
+	fibril_mutex_lock(&port->buf_lock);
+	
+	while (circ_buf_nused(cbuf) == 0)
+		fibril_condvar_wait(&port->buf_cv, &port->buf_lock);
+
+	p = 0;
+	while (p < size) {
+		rc = circ_buf_pop(cbuf, &destp[p]);
 		if (rc != EOK)
 			break;
-		++destp;
-	}
-	
-	*nread = i;
+		++p;
+	}
+
+	fibril_mutex_unlock(&port->buf_lock);
+
+	*nread = p;
 	return EOK;
 }
Index: uspace/drv/char/i8042/i8042.h
===================================================================
--- uspace/drv/char/i8042/i8042.h	(revision 7a6065c264dbab78e1758685fd1eda498ab9b73d)
+++ uspace/drv/char/i8042/i8042.h	(revision e7588a831a1d2d5847475a67a5b1bc4b10366d7c)
@@ -40,9 +40,9 @@
 #define i8042_H_
 
+#include <adt/circ_buf.h>
 #include <io/chardev_srv.h>
 #include <ddi.h>
 #include <fibril_synch.h>
 #include <ddf/driver.h>
-#include "buffer.h"
 
 #define NAME  "i8042"
@@ -61,4 +61,6 @@
 	struct i8042 *ctl;		/**< Controller */
 	chardev_srvs_t cds;		/**< Character device server data */
+	fibril_mutex_t buf_lock;	/**< Protect buffer */
+	fibril_condvar_t buf_cv;	/**< Signal new data in buffer */
 } i8042_port_t;
 
@@ -68,6 +70,6 @@
 	ddf_fun_t *kbd_fun;             /**< Pirmary port device function. */
 	ddf_fun_t *aux_fun;             /**< Auxiliary port device function. */
-	buffer_t kbd_buffer;            /**< Primary port buffer. */
-	buffer_t aux_buffer;            /**< Aux. port buffer. */
+	circ_buf_t kbd_buffer;          /**< Primary port buffer. */
+	circ_buf_t aux_buffer;          /**< Aux. port buffer. */
 	uint8_t aux_data[BUFFER_SIZE];  /**< Primary port buffer space. */
 	uint8_t kbd_data[BUFFER_SIZE];  /**< Aux. port buffer space. */
