Index: uspace/drv/ehci-hcd/main.c
===================================================================
--- uspace/drv/ehci-hcd/main.c	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ uspace/drv/ehci-hcd/main.c	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -119,5 +119,5 @@
 int main(int argc, char *argv[])
 {
-	usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
+	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
 	return ddf_driver_main(&ehci_driver);
 }
Index: uspace/drv/ohci/batch.c
===================================================================
--- uspace/drv/ohci/batch.c	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ uspace/drv/ohci/batch.c	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -118,5 +118,5 @@
 	instance->next_step = batch_call_in_and_dispose;
 	/* TODO: implement */
-	usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
+	usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance);
 }
 /*----------------------------------------------------------------------------*/
Index: uspace/drv/ohci/iface.c
===================================================================
--- uspace/drv/ohci/iface.c	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ uspace/drv/ohci/iface.c	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -33,11 +33,6 @@
  */
 #include <ddf/driver.h>
-#include <ddf/interrupt.h>
-#include <device/hw_res.h>
 #include <errno.h>
-#include <str_error.h>
-
-#include <usb_iface.h>
-#include <usb/ddfiface.h>
+
 #include <usb/debug.h>
 
@@ -60,10 +55,10 @@
 static int reserve_default_address(ddf_fun_t *fun, usb_speed_t speed)
 {
-  assert(fun);
-  hc_t *hc = fun_to_hc(fun);
-  assert(hc);
-  usb_log_debug("Default address request with speed %d.\n", speed);
-  usb_device_keeper_reserve_default_address(&hc->manager, speed);
-  return EOK;
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	usb_log_debug("Default address request with speed %d.\n", speed);
+	usb_device_keeper_reserve_default_address(&hc->manager, speed);
+	return EOK;
 }
 /*----------------------------------------------------------------------------*/
@@ -75,10 +70,10 @@
 static int release_default_address(ddf_fun_t *fun)
 {
-  assert(fun);
-  hc_t *hc = fun_to_hc(fun);
-  assert(hc);
-  usb_log_debug("Default address release.\n");
-  usb_device_keeper_release_default_address(&hc->manager);
-  return EOK;
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	usb_log_debug("Default address release.\n");
+	usb_device_keeper_release_default_address(&hc->manager);
+	return EOK;
 }
 /*----------------------------------------------------------------------------*/
@@ -90,18 +85,18 @@
  * @return Error code.
  */
-static int request_address(ddf_fun_t *fun, usb_speed_t speed,
-    usb_address_t *address)
-{
-  assert(fun);
-  hc_t *hc = fun_to_hc(fun);
-  assert(hc);
-  assert(address);
-
-  usb_log_debug("Address request with speed %d.\n", speed);
-  *address = device_keeper_get_free_address(&hc->manager, speed);
-  usb_log_debug("Address request with result: %d.\n", *address);
-  if (*address <= 0)
-    return *address;
-  return EOK;
+static int request_address(
+    ddf_fun_t *fun, usb_speed_t speed, usb_address_t *address)
+{
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	assert(address);
+
+	usb_log_debug("Address request with speed %d.\n", speed);
+	*address = device_keeper_get_free_address(&hc->manager, speed);
+	usb_log_debug("Address request with result: %d.\n", *address);
+	if (*address <= 0)
+		return *address;
+	return EOK;
 }
 /*----------------------------------------------------------------------------*/
@@ -113,13 +108,13 @@
  * @return Error code.
  */
-static int bind_address(ddf_fun_t *fun,
-    usb_address_t address, devman_handle_t handle)
-{
-  assert(fun);
-  hc_t *hc = fun_to_hc(fun);
-  assert(hc);
-  usb_log_debug("Address bind %d-%d.\n", address, handle);
-  usb_device_keeper_bind(&hc->manager, address, handle);
-  return EOK;
+static int bind_address(
+    ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)
+{
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	usb_log_debug("Address bind %d-%d.\n", address, handle);
+	usb_device_keeper_bind(&hc->manager, address, handle);
+	return EOK;
 }
 /*----------------------------------------------------------------------------*/
@@ -132,12 +127,12 @@
 static int release_address(ddf_fun_t *fun, usb_address_t address)
 {
-  assert(fun);
-  hc_t *hc = fun_to_hc(fun);
-  assert(hc);
-  usb_log_debug("Address release %d.\n", address);
-  usb_device_keeper_release(&hc->manager, address);
-  return EOK;
-}
-
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	usb_log_debug("Address release %d.\n", address);
+	usb_device_keeper_release(&hc->manager, address);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
 /** Register endpoint for bandwidth reservation.
  *
@@ -151,6 +146,6 @@
  * @return Error code.
  */
-static int register_endpoint(ddf_fun_t *fun,
-    usb_address_t address, usb_endpoint_t endpoint,
+static int register_endpoint(
+    ddf_fun_t *fun, usb_address_t address, usb_endpoint_t endpoint,
     usb_transfer_type_t transfer_type, usb_direction_t direction,
     size_t max_packet_size, unsigned int interval)
@@ -160,5 +155,5 @@
 	return ENOTSUP;
 }
-
+/*----------------------------------------------------------------------------*/
 /** Unregister endpoint (free some bandwidth reservation).
  *
@@ -169,5 +164,6 @@
  * @return Error code.
  */
-static int unregister_endpoint(ddf_fun_t *fun, usb_address_t address,
+static int unregister_endpoint(
+    ddf_fun_t *fun, usb_address_t address,
     usb_endpoint_t endpoint, usb_direction_t direction)
 {
@@ -194,27 +190,28 @@
  * @return Error code.
  */
-static int interrupt_out(ddf_fun_t *fun, usb_target_t target,
-    size_t max_packet_size, void *data, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-  hc_t *hc = fun_to_hc(fun);
-  assert(hc);
-  usb_speed_t speed = usb_device_keeper_get_speed(&hc->manager, target.address);
-
-  usb_log_debug("Interrupt OUT %d:%d %zu(%zu).\n",
-      target.address, target.endpoint, size, max_packet_size);
-
-  usb_transfer_batch_t *batch = batch_get(fun, target, USB_TRANSFER_INTERRUPT,
-      max_packet_size, speed, data, size, NULL, 0, NULL, callback, arg,
-      &hc->manager);
-  if (!batch)
-    return ENOMEM;
-  batch_interrupt_out(batch);
-  const int ret = hc_schedule(hc, batch);
-  if (ret != EOK) {
-    batch_dispose(batch);
-    return ret;
-  }
-  return EOK;
+static int interrupt_out(
+    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
+    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	usb_speed_t speed =
+	    usb_device_keeper_get_speed(&hc->manager, target.address);
+
+	usb_log_debug("Interrupt OUT %d:%d %zu(%zu).\n",
+	    target.address, target.endpoint, size, max_packet_size);
+
+	usb_transfer_batch_t *batch =
+	    batch_get(fun, target, USB_TRANSFER_INTERRUPT, max_packet_size,
+	        speed, data, size, NULL, 0, NULL, callback, arg, &hc->manager);
+	if (!batch)
+		return ENOMEM;
+	batch_interrupt_out(batch);
+	const int ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		batch_dispose(batch);
+	}
+	return ret;
 }
 /*----------------------------------------------------------------------------*/
@@ -236,27 +233,27 @@
  * @return Error code.
  */
-static int interrupt_in(ddf_fun_t *fun, usb_target_t target,
-    size_t max_packet_size, void *data, size_t size,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-  assert(fun);
-  hc_t *hc = fun_to_hc(fun);
-  assert(hc);
-  usb_speed_t speed = usb_device_keeper_get_speed(&hc->manager, target.address);
-  usb_log_debug("Interrupt IN %d:%d %zu(%zu).\n", 
-      target.address, target.endpoint, size, max_packet_size);
-
-  usb_transfer_batch_t *batch = batch_get(fun, target, USB_TRANSFER_INTERRUPT,
-      max_packet_size, speed, data, size, NULL, 0, callback, NULL, arg,
-      &hc->manager);
-  if (!batch)
-    return ENOMEM;
-  batch_interrupt_in(batch);
-  const int ret = hc_schedule(hc, batch);
-  if (ret != EOK) {
-    batch_dispose(batch);
-    return ret;
-  }
-  return EOK;
+static int interrupt_in(
+    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
+    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	usb_speed_t speed =
+	    usb_device_keeper_get_speed(&hc->manager, target.address);
+	usb_log_debug("Interrupt IN %d:%d %zu(%zu).\n",
+	    target.address, target.endpoint, size, max_packet_size);
+
+	usb_transfer_batch_t *batch =
+	    batch_get(fun, target, USB_TRANSFER_INTERRUPT, max_packet_size,
+	        speed, data, size, NULL, 0, callback, NULL, arg, &hc->manager);
+	if (!batch)
+		return ENOMEM;
+	batch_interrupt_in(batch);
+	const int ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		batch_dispose(batch);
+	}
+	return ret;
 }
 /*----------------------------------------------------------------------------*/
@@ -278,29 +275,28 @@
  * @return Error code.
  */
-static int bulk_out(ddf_fun_t *fun, usb_target_t target,
-    size_t max_packet_size, void *data, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-  assert(fun);
-  hc_t *hc = fun_to_hc(fun);
-  assert(hc);
-  usb_speed_t speed = usb_device_keeper_get_speed(&hc->manager, target.address);
-
-  usb_log_debug("Bulk OUT %d:%d %zu(%zu).\n",
-      target.address, target.endpoint, size, max_packet_size);
-
-  usb_transfer_batch_t *batch = batch_get(fun, target, USB_TRANSFER_BULK,
-      max_packet_size, speed, data, size, NULL, 0, NULL, callback, arg,
-      &hc->manager);
-  if (!batch)
-    return ENOMEM;
-  batch_bulk_out(batch);
-  const int ret = hc_schedule(hc, batch);
-  if (ret != EOK) {
-    batch_dispose(batch);
-    return ret;
-  }
-  return EOK;
-
+static int bulk_out(
+    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
+    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	usb_speed_t speed =
+	    usb_device_keeper_get_speed(&hc->manager, target.address);
+
+	usb_log_debug("Bulk OUT %d:%d %zu(%zu).\n",
+	    target.address, target.endpoint, size, max_packet_size);
+
+	usb_transfer_batch_t *batch =
+	    batch_get(fun, target, USB_TRANSFER_BULK, max_packet_size, speed,
+	        data, size, NULL, 0, NULL, callback, arg, &hc->manager);
+	if (!batch)
+		return ENOMEM;
+	batch_bulk_out(batch);
+	const int ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		batch_dispose(batch);
+	}
+	return ret;
 }
 /*----------------------------------------------------------------------------*/
@@ -322,27 +318,27 @@
  * @return Error code.
  */
-static int bulk_in(ddf_fun_t *fun, usb_target_t target,
-    size_t max_packet_size, void *data, size_t size,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-  assert(fun);
-  hc_t *hc = fun_to_hc(fun);
-  assert(hc);
-  usb_speed_t speed = usb_device_keeper_get_speed(&hc->manager, target.address);
-  usb_log_debug("Bulk IN %d:%d %zu(%zu).\n",
-      target.address, target.endpoint, size, max_packet_size);
-
-  usb_transfer_batch_t *batch = batch_get(fun, target, USB_TRANSFER_BULK,
-      max_packet_size, speed, data, size, NULL, 0, callback, NULL, arg,
-      &hc->manager);
-  if (!batch)
-    return ENOMEM;
-  batch_bulk_in(batch);
-  const int ret = hc_schedule(hc, batch);
-  if (ret != EOK) {
-    batch_dispose(batch);
-    return ret;
-  }
-  return EOK;
+static int bulk_in(
+    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
+    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	usb_speed_t speed =
+	    usb_device_keeper_get_speed(&hc->manager, target.address);
+	usb_log_debug("Bulk IN %d:%d %zu(%zu).\n",
+	    target.address, target.endpoint, size, max_packet_size);
+
+	usb_transfer_batch_t *batch =
+	    batch_get(fun, target, USB_TRANSFER_BULK, max_packet_size, speed,
+	        data, size, NULL, 0, callback, NULL, arg, &hc->manager);
+	if (!batch)
+		return ENOMEM;
+	batch_bulk_in(batch);
+	const int ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		batch_dispose(batch);
+	}
+	return ret;
 }
 /*----------------------------------------------------------------------------*/
@@ -367,33 +363,33 @@
  * @return Error code.
  */
-static int control_write(ddf_fun_t *fun, usb_target_t target,
-    size_t max_packet_size,
-    void *setup_data, size_t setup_size,
-    void *data, size_t size,
+static int control_write(
+    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,
+    void *setup_data, size_t setup_size, void *data, size_t size,
     usbhc_iface_transfer_out_callback_t callback, void *arg)
 {
-  assert(fun);
-  hc_t *hc = fun_to_hc(fun);
-  assert(hc);
-  usb_speed_t speed = usb_device_keeper_get_speed(&hc->manager, target.address);
-  usb_log_debug("Control WRITE (%d) %d:%d %zu(%zu).\n",
-      speed, target.address, target.endpoint, size, max_packet_size);
-
-  if (setup_size != 8)
-    return EINVAL;
-
-  usb_transfer_batch_t *batch = batch_get(fun, target, USB_TRANSFER_CONTROL,
-      max_packet_size, speed, data, size, setup_data, setup_size,
-      NULL, callback, arg, &hc->manager);
-  if (!batch)
-    return ENOMEM;
-  usb_device_keeper_reset_if_need(&hc->manager, target, setup_data);
-  batch_control_write(batch);
-  const int ret = hc_schedule(hc, batch);
-  if (ret != EOK) {
-    batch_dispose(batch);
-    return ret;
-  }
-  return EOK;
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	usb_speed_t speed =
+	    usb_device_keeper_get_speed(&hc->manager, target.address);
+	usb_log_debug("Control WRITE (%d) %d:%d %zu(%zu).\n",
+	    speed, target.address, target.endpoint, size, max_packet_size);
+
+	if (setup_size != 8)
+		return EINVAL;
+
+	usb_transfer_batch_t *batch =
+	    batch_get(fun, target, USB_TRANSFER_CONTROL, max_packet_size,
+	        speed, data, size, setup_data, setup_size, NULL, callback, arg,
+		&hc->manager);
+	if (!batch)
+		return ENOMEM;
+	usb_device_keeper_reset_if_need(&hc->manager, target, setup_data);
+	batch_control_write(batch);
+	const int ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		batch_dispose(batch);
+	}
+	return ret;
 }
 /*----------------------------------------------------------------------------*/
@@ -418,29 +414,29 @@
  * @return Error code.
  */
-static int control_read(ddf_fun_t *fun, usb_target_t target,
-    size_t max_packet_size,
-    void *setup_data, size_t setup_size,
-    void *data, size_t size,
+static int control_read(
+    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,
+    void *setup_data, size_t setup_size, void *data, size_t size,
     usbhc_iface_transfer_in_callback_t callback, void *arg)
 {
-  assert(fun);
-  hc_t *hc = fun_to_hc(fun);
-  assert(hc);
-  usb_speed_t speed = usb_device_keeper_get_speed(&hc->manager, target.address);
-
-  usb_log_debug("Control READ(%d) %d:%d %zu(%zu).\n",
-      speed, target.address, target.endpoint, size, max_packet_size);
-  usb_transfer_batch_t *batch = batch_get(fun, target, USB_TRANSFER_CONTROL,
-      max_packet_size, speed, data, size, setup_data, setup_size, callback,
-      NULL, arg, &hc->manager);
-  if (!batch)
-    return ENOMEM;
-  batch_control_read(batch);
-  const int ret = hc_schedule(hc, batch);
-  if (ret != EOK) {
-    batch_dispose(batch);
-    return ret;
-  }
-  return EOK;
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	usb_speed_t speed =
+	    usb_device_keeper_get_speed(&hc->manager, target.address);
+
+	usb_log_debug("Control READ(%d) %d:%d %zu(%zu).\n",
+	    speed, target.address, target.endpoint, size, max_packet_size);
+	usb_transfer_batch_t *batch =
+	    batch_get(fun, target, USB_TRANSFER_CONTROL, max_packet_size,
+	        speed, data, size, setup_data, setup_size, callback, NULL, arg,
+		&hc->manager);
+	if (!batch)
+		return ENOMEM;
+	batch_control_read(batch);
+	const int ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		batch_dispose(batch);
+	}
+	return ret;
 }
 /*----------------------------------------------------------------------------*/
@@ -463,5 +459,5 @@
 
 	.control_write = control_write,
-	.control_read = control_read
+	.control_read = control_read,
 };
 
Index: uspace/drv/ohci/main.c
===================================================================
--- uspace/drv/ohci/main.c	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ uspace/drv/ohci/main.c	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -149,14 +149,21 @@
 	}
 
+
 	bool interrupts = false;
+#ifdef CONFIG_USBHC_NO_INTERRUPTS
+	usb_log_warning("Interrupts disabled in OS config, " \
+	    "falling back to polling.\n");
+#else
 	ret = pci_enable_interrupts(device);
 	if (ret != EOK) {
-		usb_log_warning(
-		    "Failed(%d) to enable interrupts, fall back to polling.\n",
-		    ret);
+		usb_log_warning("Failed to enable interrupts: %s.\n",
+		    str_error(ret));
+		usb_log_info("HW interrupts not available, " \
+		    "falling back to polling.\n");
 	} else {
 		usb_log_debug("Hw interrupts enabled.\n");
 		interrupts = true;
 	}
+#endif
 
 	ret = hc_init(hcd, hc_fun, device, mem_reg_base, mem_reg_size, interrupts);
@@ -199,5 +206,5 @@
 int main(int argc, char *argv[])
 {
-	usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
+	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
 	sleep(5);
 	return ddf_driver_main(&ohci_driver);
Index: uspace/drv/uhci-hcd/Makefile
===================================================================
--- uspace/drv/uhci-hcd/Makefile	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ uspace/drv/uhci-hcd/Makefile	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -37,7 +37,7 @@
 	transfer_list.c \
 	uhci.c \
-	uhci_hc.c \
-	uhci_rh.c \
-	uhci_struct/transfer_descriptor.c \
+	hc.c \
+	root_hub.c \
+	hw_struct/transfer_descriptor.c \
 	pci.c \
 	batch.c
Index: uspace/drv/uhci-hcd/batch.c
===================================================================
--- uspace/drv/uhci-hcd/batch.c	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ uspace/drv/uhci-hcd/batch.c	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -40,7 +40,6 @@
 #include "batch.h"
 #include "transfer_list.h"
-#include "uhci_hc.h"
+#include "hw_struct/transfer_descriptor.h"
 #include "utils/malloc32.h"
-#include "uhci_struct/transfer_descriptor.h"
 
 #define DEFAULT_ERROR_COUNT 3
@@ -49,5 +48,5 @@
 	qh_t *qh;
 	td_t *tds;
-	size_t packets;
+	size_t transfers;
 	usb_device_keeper_t *manager;
 } uhci_batch_t;
@@ -65,5 +64,5 @@
  * @param[in] target Device and endpoint target of the transaction.
  * @param[in] transfer_type Interrupt, Control or Bulk.
- * @param[in] max_packet_size maximum allowed size of data packets.
+ * @param[in] max_packet_size maximum allowed size of data transfers.
  * @param[in] speed Speed of the transaction.
  * @param[in] buffer Data source/destination.
@@ -78,5 +77,5 @@
  * NULL otherwise.
  *
- * Determines the number of needed packets (TDs). Prepares a transport buffer
+ * Determines the number of needed transfers (TDs). Prepares a transport buffer
  * (that is accessible by the hardware). Initializes parameters needed for the
  * transaction and callback.
@@ -118,13 +117,13 @@
 	instance->private_data = data;
 
-	data->packets = (buffer_size + max_packet_size - 1) / max_packet_size;
+	data->transfers = (buffer_size + max_packet_size - 1) / max_packet_size;
 	if (transfer_type == USB_TRANSFER_CONTROL) {
-		data->packets += 2;
-	}
-
-	data->tds = malloc32(sizeof(td_t) * data->packets);
+		data->transfers += 2;
+	}
+
+	data->tds = malloc32(sizeof(td_t) * data->transfers);
 	CHECK_NULL_DISPOSE_RETURN(
 	    data->tds, "Failed to allocate transfer descriptors.\n");
-	bzero(data->tds, sizeof(td_t) * data->packets);
+	bzero(data->tds, sizeof(td_t) * data->transfers);
 
 	data->qh = malloc32(sizeof(qh_t));
@@ -167,9 +166,9 @@
 	assert(data);
 
-	usb_log_debug2("Batch(%p) checking %d packet(s) for completion.\n",
-	    instance, data->packets);
+	usb_log_debug2("Batch(%p) checking %d transfer(s) for completion.\n",
+	    instance, data->transfers);
 	instance->transfered_size = 0;
 	size_t i = 0;
-	for (;i < data->packets; ++i) {
+	for (;i < data->transfers; ++i) {
 		if (td_is_active(&data->tds[i])) {
 			return false;
@@ -299,8 +298,8 @@
  *
  * @param[in] instance Batch structure to use.
- * @param[in] pid to use for data packets.
+ * @param[in] pid Pid to use for data transfers.
  *
  * Packets with alternating toggle bit and supplied pid value.
- * The last packet is marked with IOC flag.
+ * The last transfer is marked with IOC flag.
  */
 void batch_data(usb_transfer_batch_t *instance, usb_packet_id pid)
@@ -315,5 +314,5 @@
 	assert(toggle == 0 || toggle == 1);
 
-	size_t packet = 0;
+	size_t transfer = 0;
 	size_t remain_size = instance->buffer_size;
 	while (remain_size > 0) {
@@ -326,21 +325,21 @@
 		    remain_size : instance->max_packet_size;
 
-		td_t *next_packet = (packet + 1 < data->packets)
-		    ? &data->tds[packet + 1] : NULL;
-
-		assert(packet < data->packets);
+		td_t *next_transfer = (transfer + 1 < data->transfers)
+		    ? &data->tds[transfer + 1] : NULL;
+
+		assert(transfer < data->transfers);
 		assert(packet_size <= remain_size);
 
 		td_init(
-		    &data->tds[packet], DEFAULT_ERROR_COUNT, packet_size,
+		    &data->tds[transfer], DEFAULT_ERROR_COUNT, packet_size,
 		    toggle, false, low_speed, instance->target, pid, trans_data,
-		    next_packet);
+		    next_transfer);
 
 
 		toggle = 1 - toggle;
 		remain_size -= packet_size;
-		++packet;
-	}
-	td_set_ioc(&data->tds[packet - 1]);
+		++transfer;
+	}
+	td_set_ioc(&data->tds[transfer - 1]);
 	usb_device_keeper_set_toggle(data->manager, instance->target,
 	    instance->direction, toggle);
@@ -350,11 +349,11 @@
  *
  * @param[in] instance Batch structure to use.
- * @param[in] data_stage to use for data packets.
- * @param[in] status_stage to use for data packets.
+ * @param[in] data_stage Pid to use for data transfers.
+ * @param[in] status_stage Pid to use for data transfers.
  *
  * Setup stage with toggle 0 and USB_PID_SETUP.
  * Data stage with alternating toggle and pid supplied by parameter.
  * Status stage with toggle 1 and pid supplied by parameter.
- * The last packet is marked with IOC.
+ * The last transfer is marked with IOC.
  */
 void batch_control(usb_transfer_batch_t *instance,
@@ -364,5 +363,5 @@
 	uhci_batch_t *data = instance->private_data;
 	assert(data);
-	assert(data->packets >= 2);
+	assert(data->transfers >= 2);
 
 	const bool low_speed = instance->speed == USB_SPEED_LOW;
@@ -375,5 +374,5 @@
 
 	/* data stage */
-	size_t packet = 1;
+	size_t transfer = 1;
 	size_t remain_size = instance->buffer_size;
 	while (remain_size > 0) {
@@ -389,10 +388,10 @@
 
 		td_init(
-		    &data->tds[packet], DEFAULT_ERROR_COUNT, packet_size,
+		    &data->tds[transfer], DEFAULT_ERROR_COUNT, packet_size,
 		    toggle, false, low_speed, instance->target, data_stage,
-		    control_data, &data->tds[packet + 1]);
-
-		++packet;
-		assert(packet < data->packets);
+		    control_data, &data->tds[transfer + 1]);
+
+		++transfer;
+		assert(transfer < data->transfers);
 		assert(packet_size <= remain_size);
 		remain_size -= packet_size;
@@ -400,13 +399,13 @@
 
 	/* status stage */
-	assert(packet == data->packets - 1);
+	assert(transfer == data->transfers - 1);
 
 	td_init(
-	    &data->tds[packet], DEFAULT_ERROR_COUNT, 0, 1, false, low_speed,
+	    &data->tds[transfer], DEFAULT_ERROR_COUNT, 0, 1, false, low_speed,
 	    instance->target, status_stage, NULL, NULL);
-	td_set_ioc(&data->tds[packet]);
+	td_set_ioc(&data->tds[transfer]);
 
 	usb_log_debug2("Control last TD status: %x.\n",
-	    data->tds[packet].status);
+	    data->tds[transfer].status);
 }
 /*----------------------------------------------------------------------------*/
Index: uspace/drv/uhci-hcd/batch.h
===================================================================
--- uspace/drv/uhci-hcd/batch.h	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ uspace/drv/uhci-hcd/batch.h	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -42,5 +42,5 @@
 #include <usb/host/batch.h>
 
-#include "uhci_struct/queue_head.h"
+#include "hw_struct/queue_head.h"
 
 usb_transfer_batch_t * batch_get(
Index: uspace/drv/uhci-hcd/hc.c
===================================================================
--- uspace/drv/uhci-hcd/hc.c	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
+++ uspace/drv/uhci-hcd/hc.c	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -0,0 +1,499 @@
+/*
+ * 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 drvusbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI Host controller driver routines
+ */
+#include <errno.h>
+#include <str_error.h>
+#include <adt/list.h>
+#include <libarch/ddi.h>
+
+#include <usb/debug.h>
+#include <usb/usb.h>
+#include <usb/ddfiface.h>
+#include <usb_iface.h>
+
+#include "hc.h"
+
+static irq_cmd_t uhci_cmds[] = {
+	{
+		.cmd = CMD_PIO_READ_16,
+		.addr = NULL, /* patched for every instance */
+		.dstarg = 1
+	},
+	{
+		.cmd = CMD_PIO_WRITE_16,
+		.addr = NULL, /* pathed for every instance */
+		.value = 0x1f
+	},
+	{
+		.cmd = CMD_ACCEPT
+	}
+};
+/*----------------------------------------------------------------------------*/
+static int hc_init_transfer_lists(hc_t *instance);
+static int hc_init_mem_structures(hc_t *instance);
+static void hc_init_hw(hc_t *instance);
+
+static int hc_interrupt_emulator(void *arg);
+static int hc_debug_checker(void *arg);
+
+static bool usb_is_allowed(
+    bool low_speed, usb_transfer_type_t transfer, size_t size);
+/*----------------------------------------------------------------------------*/
+/** Initialize UHCI hcd driver structure
+ *
+ * @param[in] instance Memory place to initialize.
+ * @param[in] fun DDF function.
+ * @param[in] regs Address of I/O control registers.
+ * @param[in] size Size of I/O control registers.
+ * @return Error code.
+ * @note Should be called only once on any structure.
+ *
+ * Initializes memory structures, starts up hw, and launches debugger and
+ * interrupt fibrils.
+ */
+int hc_init(hc_t *instance, ddf_fun_t *fun,
+    void *regs, size_t reg_size, bool interrupts)
+{
+	assert(reg_size >= sizeof(regs_t));
+	int ret;
+
+#define CHECK_RET_DEST_FUN_RETURN(ret, message...) \
+	if (ret != EOK) { \
+		usb_log_error(message); \
+		if (instance->ddf_instance) \
+			ddf_fun_destroy(instance->ddf_instance); \
+		return ret; \
+	} else (void) 0
+
+	instance->hw_interrupts = interrupts;
+	instance->hw_failures = 0;
+
+	/* Setup UHCI function. */
+	instance->ddf_instance = fun;
+
+	/* allow access to hc control registers */
+	regs_t *io;
+	ret = pio_enable(regs, reg_size, (void**)&io);
+	CHECK_RET_DEST_FUN_RETURN(ret,
+	    "Failed(%d) to gain access to registers at %p: %s.\n",
+	    ret, str_error(ret), io);
+	instance->registers = io;
+	usb_log_debug("Device registers at %p(%u) accessible.\n",
+	    io, reg_size);
+
+	ret = hc_init_mem_structures(instance);
+	CHECK_RET_DEST_FUN_RETURN(ret,
+	    "Failed to initialize UHCI memory structures.\n");
+
+	hc_init_hw(instance);
+	if (!interrupts) {
+		instance->cleaner =
+		    fibril_create(hc_interrupt_emulator, instance);
+		fibril_add_ready(instance->cleaner);
+	} else {
+		/* TODO: enable interrupts here */
+	}
+
+	instance->debug_checker =
+	    fibril_create(hc_debug_checker, instance);
+//	fibril_add_ready(instance->debug_checker);
+
+	return EOK;
+#undef CHECK_RET_DEST_FUN_RETURN
+}
+/*----------------------------------------------------------------------------*/
+/** Initialize UHCI hc hw resources.
+ *
+ * @param[in] instance UHCI structure to use.
+ * For magic values see UHCI Design Guide
+ */
+void hc_init_hw(hc_t *instance)
+{
+	assert(instance);
+	regs_t *registers = instance->registers;
+
+	/* Reset everything, who knows what touched it before us */
+	pio_write_16(&registers->usbcmd, UHCI_CMD_GLOBAL_RESET);
+	async_usleep(10000); /* 10ms according to USB spec */
+	pio_write_16(&registers->usbcmd, 0);
+
+	/* Reset hc, all states and counters */
+	pio_write_16(&registers->usbcmd, UHCI_CMD_HCRESET);
+	do { async_usleep(10); }
+	while ((pio_read_16(&registers->usbcmd) & UHCI_CMD_HCRESET) != 0);
+
+	/* Set frame to exactly 1ms */
+	pio_write_8(&registers->sofmod, 64);
+
+	/* Set frame list pointer */
+	const uint32_t pa = addr_to_phys(instance->frame_list);
+	pio_write_32(&registers->flbaseadd, pa);
+
+	if (instance->hw_interrupts) {
+		/* Enable all interrupts, but resume interrupt */
+		pio_write_16(&instance->registers->usbintr,
+		    UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET);
+	}
+
+	uint16_t status = pio_read_16(&registers->usbcmd);
+	if (status != 0)
+		usb_log_warning("Previous command value: %x.\n", status);
+
+	/* Start the hc with large(64B) packet FSBR */
+	pio_write_16(&registers->usbcmd,
+	    UHCI_CMD_RUN_STOP | UHCI_CMD_MAX_PACKET | UHCI_CMD_CONFIGURE);
+}
+/*----------------------------------------------------------------------------*/
+/** Initialize UHCI hc memory structures.
+ *
+ * @param[in] instance UHCI structure to use.
+ * @return Error code
+ * @note Should be called only once on any structure.
+ *
+ * Structures:
+ *  - interrupt code (I/O addressses are customized per instance)
+ *  - transfer lists (queue heads need to be accessible by the hw)
+ *  - frame list page (needs to be one UHCI hw accessible 4K page)
+ */
+int hc_init_mem_structures(hc_t *instance)
+{
+	assert(instance);
+#define CHECK_RET_DEST_CMDS_RETURN(ret, message...) \
+	if (ret != EOK) { \
+		usb_log_error(message); \
+		if (instance->interrupt_code.cmds != NULL) \
+			free(instance->interrupt_code.cmds); \
+		return ret; \
+	} else (void) 0
+
+	/* Init interrupt code */
+	instance->interrupt_code.cmds = malloc(sizeof(uhci_cmds));
+	int ret = (instance->interrupt_code.cmds == NULL) ? ENOMEM : EOK;
+	CHECK_RET_DEST_CMDS_RETURN(ret,
+	    "Failed to allocate interrupt cmds space.\n");
+
+	{
+		irq_cmd_t *interrupt_commands = instance->interrupt_code.cmds;
+		memcpy(interrupt_commands, uhci_cmds, sizeof(uhci_cmds));
+		interrupt_commands[0].addr =
+		    (void*)&instance->registers->usbsts;
+		interrupt_commands[1].addr =
+		    (void*)&instance->registers->usbsts;
+		instance->interrupt_code.cmdcount =
+		    sizeof(uhci_cmds) / sizeof(irq_cmd_t);
+	}
+
+	/* Init transfer lists */
+	ret = hc_init_transfer_lists(instance);
+	CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to init transfer lists.\n");
+	usb_log_debug("Initialized transfer lists.\n");
+
+	/* Init USB frame list page*/
+	instance->frame_list = get_page();
+	ret = instance ? EOK : ENOMEM;
+	CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to get frame list page.\n");
+	usb_log_debug("Initialized frame list.\n");
+
+	/* Set all frames to point to the first queue head */
+	const uint32_t queue =
+	  instance->transfers_interrupt.queue_head_pa
+	  | LINK_POINTER_QUEUE_HEAD_FLAG;
+
+	unsigned i = 0;
+	for(; i < UHCI_FRAME_LIST_COUNT; ++i) {
+		instance->frame_list[i] = queue;
+	}
+
+	/* Init device keeper*/
+	usb_device_keeper_init(&instance->manager);
+	usb_log_debug("Initialized device manager.\n");
+
+	return EOK;
+#undef CHECK_RET_DEST_CMDS_RETURN
+}
+/*----------------------------------------------------------------------------*/
+/** Initialize UHCI hc transfer lists.
+ *
+ * @param[in] instance UHCI structure to use.
+ * @return Error code
+ * @note Should be called only once on any structure.
+ *
+ * Initializes transfer lists and sets them in one chain to support proper
+ * USB scheduling. Sets pointer table for quick access.
+ */
+int hc_init_transfer_lists(hc_t *instance)
+{
+	assert(instance);
+#define CHECK_RET_CLEAR_RETURN(ret, message...) \
+	if (ret != EOK) { \
+		usb_log_error(message); \
+		transfer_list_fini(&instance->transfers_bulk_full); \
+		transfer_list_fini(&instance->transfers_control_full); \
+		transfer_list_fini(&instance->transfers_control_slow); \
+		transfer_list_fini(&instance->transfers_interrupt); \
+		return ret; \
+	} else (void) 0
+
+	/* initialize TODO: check errors */
+	int ret;
+	ret = transfer_list_init(&instance->transfers_bulk_full, "BULK_FULL");
+	CHECK_RET_CLEAR_RETURN(ret, "Failed to init BULK list.");
+
+	ret = transfer_list_init(
+	    &instance->transfers_control_full, "CONTROL_FULL");
+	CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL FULL list.");
+
+	ret = transfer_list_init(
+	    &instance->transfers_control_slow, "CONTROL_SLOW");
+	CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL SLOW list.");
+
+	ret = transfer_list_init(&instance->transfers_interrupt, "INTERRUPT");
+	CHECK_RET_CLEAR_RETURN(ret, "Failed to init INTERRUPT list.");
+
+	transfer_list_set_next(&instance->transfers_control_full,
+		&instance->transfers_bulk_full);
+	transfer_list_set_next(&instance->transfers_control_slow,
+		&instance->transfers_control_full);
+	transfer_list_set_next(&instance->transfers_interrupt,
+		&instance->transfers_control_slow);
+
+	/*FSBR*/
+#ifdef FSBR
+	transfer_list_set_next(&instance->transfers_bulk_full,
+		&instance->transfers_control_full);
+#endif
+
+	/* Assign pointers to be used during scheduling */
+	instance->transfers[USB_SPEED_FULL][USB_TRANSFER_INTERRUPT] =
+	  &instance->transfers_interrupt;
+	instance->transfers[USB_SPEED_LOW][USB_TRANSFER_INTERRUPT] =
+	  &instance->transfers_interrupt;
+	instance->transfers[USB_SPEED_FULL][USB_TRANSFER_CONTROL] =
+	  &instance->transfers_control_full;
+	instance->transfers[USB_SPEED_LOW][USB_TRANSFER_CONTROL] =
+	  &instance->transfers_control_slow;
+	instance->transfers[USB_SPEED_FULL][USB_TRANSFER_BULK] =
+	  &instance->transfers_bulk_full;
+
+	return EOK;
+#undef CHECK_RET_CLEAR_RETURN
+}
+/*----------------------------------------------------------------------------*/
+/** Schedule batch for execution.
+ *
+ * @param[in] instance UHCI structure to use.
+ * @param[in] batch Transfer batch to schedule.
+ * @return Error code
+ *
+ * Checks for bandwidth availability and appends the batch to the proper queue.
+ */
+int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch)
+{
+	assert(instance);
+	assert(batch);
+	const int low_speed = (batch->speed == USB_SPEED_LOW);
+	if (!usb_is_allowed(
+	    low_speed, batch->transfer_type, batch->max_packet_size)) {
+		usb_log_warning(
+		    "Invalid USB transfer specified %s SPEED %d %zu.\n",
+		    low_speed ? "LOW" : "FULL" , batch->transfer_type,
+		    batch->max_packet_size);
+		return ENOTSUP;
+	}
+	/* TODO: check available bandwidth here */
+
+	transfer_list_t *list =
+	    instance->transfers[batch->speed][batch->transfer_type];
+	assert(list);
+	transfer_list_add_batch(list, batch);
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Take action based on the interrupt cause.
+ *
+ * @param[in] instance UHCI structure to use.
+ * @param[in] status Value of the status register at the time of interrupt.
+ *
+ * Interrupt might indicate:
+ * - transaction completed, either by triggering IOC, SPD, or an error
+ * - some kind of device error
+ * - resume from suspend state (not implemented)
+ */
+void hc_interrupt(hc_t *instance, uint16_t status)
+{
+	assert(instance);
+	/* TODO: Resume interrupts are not supported */
+	/* Lower 2 bits are transaction error and transaction complete */
+	if (status & 0x3) {
+		transfer_list_remove_finished(&instance->transfers_interrupt);
+		transfer_list_remove_finished(&instance->transfers_control_slow);
+		transfer_list_remove_finished(&instance->transfers_control_full);
+		transfer_list_remove_finished(&instance->transfers_bulk_full);
+	}
+	/* bits 4 and 5 indicate hc error */
+	if (status & 0x18) {
+		usb_log_error("UHCI hardware failure!.\n");
+		++instance->hw_failures;
+		transfer_list_abort_all(&instance->transfers_interrupt);
+		transfer_list_abort_all(&instance->transfers_control_slow);
+		transfer_list_abort_all(&instance->transfers_control_full);
+		transfer_list_abort_all(&instance->transfers_bulk_full);
+
+		if (instance->hw_failures < UHCI_ALLOWED_HW_FAIL) {
+			/* reinitialize hw, this triggers virtual disconnect*/
+			hc_init_hw(instance);
+		} else {
+			usb_log_fatal("Too many UHCI hardware failures!.\n");
+			hc_fini(instance);
+		}
+	}
+}
+/*----------------------------------------------------------------------------*/
+/** Polling function, emulates interrupts.
+ *
+ * @param[in] arg UHCI hc structure to use.
+ * @return EOK (should never return)
+ */
+int hc_interrupt_emulator(void* arg)
+{
+	usb_log_debug("Started interrupt emulator.\n");
+	hc_t *instance = (hc_t*)arg;
+	assert(instance);
+
+	while (1) {
+		/* read and ack interrupts */
+		uint16_t status = pio_read_16(&instance->registers->usbsts);
+		pio_write_16(&instance->registers->usbsts, 0x1f);
+		if (status != 0)
+			usb_log_debug2("UHCI status: %x.\n", status);
+		hc_interrupt(instance, status);
+		async_usleep(UHCI_CLEANER_TIMEOUT);
+	}
+	return EOK;
+}
+/*---------------------------------------------------------------------------*/
+/** Debug function, checks consistency of memory structures.
+ *
+ * @param[in] arg UHCI structure to use.
+ * @return EOK (should never return)
+ */
+int hc_debug_checker(void *arg)
+{
+	hc_t *instance = (hc_t*)arg;
+	assert(instance);
+
+#define QH(queue) \
+	instance->transfers_##queue.queue_head
+
+	while (1) {
+		const uint16_t cmd = pio_read_16(&instance->registers->usbcmd);
+		const uint16_t sts = pio_read_16(&instance->registers->usbsts);
+		const uint16_t intr =
+		    pio_read_16(&instance->registers->usbintr);
+
+		if (((cmd & UHCI_CMD_RUN_STOP) != 1) || (sts != 0)) {
+			usb_log_debug2("Command: %X Status: %X Intr: %x\n",
+			    cmd, sts, intr);
+		}
+
+		uintptr_t frame_list =
+		    pio_read_32(&instance->registers->flbaseadd) & ~0xfff;
+		if (frame_list != addr_to_phys(instance->frame_list)) {
+			usb_log_debug("Framelist address: %p vs. %p.\n",
+			    frame_list, addr_to_phys(instance->frame_list));
+		}
+
+		int frnum = pio_read_16(&instance->registers->frnum) & 0x3ff;
+
+		uintptr_t expected_pa = instance->frame_list[frnum]
+		    & LINK_POINTER_ADDRESS_MASK;
+		uintptr_t real_pa = addr_to_phys(QH(interrupt));
+		if (expected_pa != real_pa) {
+			usb_log_debug("Interrupt QH: %p(frame: %d) vs. %p.\n",
+			    expected_pa, frnum, real_pa);
+		}
+
+		expected_pa = QH(interrupt)->next & LINK_POINTER_ADDRESS_MASK;
+		real_pa = addr_to_phys(QH(control_slow));
+		if (expected_pa != real_pa) {
+			usb_log_debug("Control Slow QH: %p vs. %p.\n",
+			    expected_pa, real_pa);
+		}
+
+		expected_pa = QH(control_slow)->next & LINK_POINTER_ADDRESS_MASK;
+		real_pa = addr_to_phys(QH(control_full));
+		if (expected_pa != real_pa) {
+			usb_log_debug("Control Full QH: %p vs. %p.\n",
+			    expected_pa, real_pa);
+		}
+
+		expected_pa = QH(control_full)->next & LINK_POINTER_ADDRESS_MASK;
+		real_pa = addr_to_phys(QH(bulk_full));
+		if (expected_pa != real_pa ) {
+			usb_log_debug("Bulk QH: %p vs. %p.\n",
+			    expected_pa, real_pa);
+		}
+		async_usleep(UHCI_DEBUGER_TIMEOUT);
+	}
+	return EOK;
+#undef QH
+}
+/*----------------------------------------------------------------------------*/
+/** Check transfers for USB validity
+ *
+ * @param[in] low_speed Transfer speed.
+ * @param[in] transfer Transer type
+ * @param[in] size Size of data packets
+ * @return True if transaction is allowed by USB specs, false otherwise
+ */
+bool usb_is_allowed(
+    bool low_speed, usb_transfer_type_t transfer, size_t size)
+{
+	/* see USB specification chapter 5.5-5.8 for magic numbers used here */
+	switch(transfer)
+	{
+	case USB_TRANSFER_ISOCHRONOUS:
+		return (!low_speed && size < 1024);
+	case USB_TRANSFER_INTERRUPT:
+		return size <= (low_speed ? 8 : 64);
+	case USB_TRANSFER_CONTROL: /* device specifies its own max size */
+		return (size <= (low_speed ? 8 : 64));
+	case USB_TRANSFER_BULK: /* device specifies its own max size */
+		return (!low_speed && size <= 64);
+	}
+	return false;
+}
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/hc.h
===================================================================
--- uspace/drv/uhci-hcd/hc.h	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
+++ uspace/drv/uhci-hcd/hc.h	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -0,0 +1,131 @@
+/*
+ * 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 drvusbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI host controller driver structure
+ */
+#ifndef DRV_UHCI_UHCI_HC_H
+#define DRV_UHCI_UHCI_HC_H
+
+#include <fibril.h>
+#include <fibril_synch.h>
+#include <adt/list.h>
+#include <ddi.h>
+
+#include <usbhc_iface.h>
+#include <usb/host/device_keeper.h>
+
+#include "batch.h"
+#include "transfer_list.h"
+
+typedef struct uhci_regs {
+	uint16_t usbcmd;
+#define UHCI_CMD_MAX_PACKET (1 << 7)
+#define UHCI_CMD_CONFIGURE  (1 << 6)
+#define UHCI_CMD_DEBUG  (1 << 5)
+#define UHCI_CMD_FORCE_GLOBAL_RESUME  (1 << 4)
+#define UHCI_CMD_FORCE_GLOBAL_SUSPEND  (1 << 3)
+#define UHCI_CMD_GLOBAL_RESET  (1 << 2)
+#define UHCI_CMD_HCRESET  (1 << 1)
+#define UHCI_CMD_RUN_STOP  (1 << 0)
+
+	uint16_t usbsts;
+#define UHCI_STATUS_HALTED (1 << 5)
+#define UHCI_STATUS_PROCESS_ERROR (1 << 4)
+#define UHCI_STATUS_SYSTEM_ERROR (1 << 3)
+#define UHCI_STATUS_RESUME (1 << 2)
+#define UHCI_STATUS_ERROR_INTERRUPT (1 << 1)
+#define UHCI_STATUS_INTERRUPT (1 << 0)
+
+	uint16_t usbintr;
+#define UHCI_INTR_SHORT_PACKET (1 << 3)
+#define UHCI_INTR_COMPLETE (1 << 2)
+#define UHCI_INTR_RESUME (1 << 1)
+#define UHCI_INTR_CRC (1 << 0)
+
+	uint16_t frnum;
+	uint32_t flbaseadd;
+	uint8_t sofmod;
+} regs_t;
+
+#define UHCI_FRAME_LIST_COUNT 1024
+#define UHCI_CLEANER_TIMEOUT 10000
+#define UHCI_DEBUGER_TIMEOUT 5000000
+#define UHCI_ALLOWED_HW_FAIL 5
+
+typedef struct hc {
+	usb_device_keeper_t manager;
+
+	regs_t *registers;
+
+	link_pointer_t *frame_list;
+
+	transfer_list_t transfers_bulk_full;
+	transfer_list_t transfers_control_full;
+	transfer_list_t transfers_control_slow;
+	transfer_list_t transfers_interrupt;
+
+	transfer_list_t *transfers[2][4];
+
+	irq_code_t interrupt_code;
+
+	fid_t cleaner;
+	fid_t debug_checker;
+	bool hw_interrupts;
+	unsigned hw_failures;
+
+	ddf_fun_t *ddf_instance;
+} hc_t;
+
+int hc_init(hc_t *instance, ddf_fun_t *fun,
+    void *regs, size_t reg_size, bool interupts);
+
+int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch);
+
+void hc_interrupt(hc_t *instance, uint16_t status);
+
+/** Safely dispose host controller internal structures
+ *
+ * @param[in] instance Host controller structure to use.
+ */
+static inline void hc_fini(hc_t *instance) { /* TODO: implement*/ };
+
+/** Get and cast pointer to the driver data
+ *
+ * @param[in] fun DDF function pointer
+ * @return cast pointer to driver_data
+ */
+static inline hc_t * fun_to_hc(ddf_fun_t *fun)
+	{ return (hc_t*)fun->driver_data; }
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/hw_struct/link_pointer.h
===================================================================
--- uspace/drv/uhci-hcd/hw_struct/link_pointer.h	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
+++ uspace/drv/uhci-hcd/hw_struct/link_pointer.h	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2010 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 drvusbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef DRV_UHCI_LINK_POINTER_H
+#define DRV_UHCI_LINK_POINTER_H
+
+/* UHCI link pointer, used by many data structures */
+typedef uint32_t link_pointer_t;
+
+#define LINK_POINTER_TERMINATE_FLAG (1 << 0)
+#define LINK_POINTER_QUEUE_HEAD_FLAG (1 << 1)
+#define LINK_POINTER_ZERO_BIT_FLAG (1 << 2)
+#define LINK_POINTER_VERTICAL_FLAG (1 << 2)
+#define LINK_POINTER_RESERVED_FLAG (1 << 3)
+
+#define LINK_POINTER_ADDRESS_MASK 0xfffffff0 /* upper 28 bits */
+
+#define LINK_POINTER_QH(address) \
+	((address & LINK_POINTER_ADDRESS_MASK) | LINK_POINTER_QUEUE_HEAD_FLAG)
+
+#define LINK_POINTER_TD(address) \
+	(address & LINK_POINTER_ADDRESS_MASK)
+
+#define LINK_POINTER_TERM \
+	((link_pointer_t)LINK_POINTER_TERMINATE_FLAG)
+
+#endif
+/**
+ * @}
+ */
+
Index: uspace/drv/uhci-hcd/hw_struct/queue_head.h
===================================================================
--- uspace/drv/uhci-hcd/hw_struct/queue_head.h	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
+++ uspace/drv/uhci-hcd/hw_struct/queue_head.h	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2010 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 drv usbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef DRV_UHCI_QH_H
+#define DRV_UHCI_QH_H
+
+/* libc */
+#include <assert.h>
+
+#include "link_pointer.h"
+#include "utils/malloc32.h"
+
+typedef struct queue_head {
+	volatile link_pointer_t next;
+	volatile link_pointer_t element;
+} __attribute__((packed)) qh_t;
+/*----------------------------------------------------------------------------*/
+/** Initialize queue head structure
+ *
+ * @param[in] instance qh_t structure to initialize.
+ *
+ * Sets both pointer to terminal NULL.
+ */
+static inline void qh_init(qh_t *instance)
+{
+	assert(instance);
+
+	instance->element = 0 | LINK_POINTER_TERMINATE_FLAG;
+	instance->next = 0 | LINK_POINTER_TERMINATE_FLAG;
+}
+/*----------------------------------------------------------------------------*/
+/** Set queue head next pointer
+ *
+ * @param[in] instance qh_t structure to use.
+ * @param[in] pa Physical address of the next queue head.
+ *
+ * Adds proper flag. If the pointer is NULL or terminal, sets next to terminal
+ * NULL.
+ */
+static inline void qh_set_next_qh(qh_t *instance, uint32_t pa)
+{
+	/* Address is valid and not terminal */
+	if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) {
+		instance->next = LINK_POINTER_QH(pa);
+	} else {
+		instance->next = LINK_POINTER_TERM;
+	}
+}
+/*----------------------------------------------------------------------------*/
+/** Set queue head element pointer
+ *
+ * @param[in] instance qh_t structure to initialize.
+ * @param[in] pa Physical address of the next queue head.
+ *
+ * Adds proper flag. If the pointer is NULL or terminal, sets element
+ * to terminal NULL.
+ */
+static inline void qh_set_element_qh(qh_t *instance, uint32_t pa)
+{
+	/* Address is valid and not terminal */
+	if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) {
+		instance->element = LINK_POINTER_QH(pa);
+	} else {
+		instance->element = LINK_POINTER_TERM;
+	}
+}
+/*----------------------------------------------------------------------------*/
+/** Set queue head element pointer
+ *
+ * @param[in] instance qh_t structure to initialize.
+ * @param[in] pa Physical address of the TD structure.
+ *
+ * Adds proper flag. If the pointer is NULL or terminal, sets element
+ * to terminal NULL.
+ */
+static inline void qh_set_element_td(qh_t *instance, uint32_t pa)
+{
+	if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) {
+		instance->element = LINK_POINTER_TD(pa);
+	} else {
+		instance->element = LINK_POINTER_TERM;
+	}
+}
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/hw_struct/transfer_descriptor.c
===================================================================
--- uspace/drv/uhci-hcd/hw_struct/transfer_descriptor.c	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
+++ uspace/drv/uhci-hcd/hw_struct/transfer_descriptor.c	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -0,0 +1,173 @@
+/*
+ * 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 drvusbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#include <errno.h>
+#include <usb/debug.h>
+
+#include "transfer_descriptor.h"
+#include "utils/malloc32.h"
+
+/** Initialize Transfer Descriptor
+ *
+ * @param[in] instance Memory place to initialize.
+ * @param[in] err_count Number of retries hc should attempt.
+ * @param[in] size Size of data source.
+ * @param[in] toggle Value of toggle bit.
+ * @param[in] iso True if TD represents Isochronous transfer.
+ * @param[in] low_speed Target device's speed.
+ * @param[in] target Address and endpoint receiving the transfer.
+ * @param[in] pid Packet identification (SETUP, IN or OUT).
+ * @param[in] buffer Source of data.
+ * @param[in] next Net TD in transaction.
+ * @return Error code.
+ *
+ * Uses a mix of supplied and default values.
+ * Implicit values:
+ *  - all TDs have vertical flag set (makes transfers to endpoints atomic)
+ *  - in the error field only active it is set
+ *  - if the packet uses PID_IN and is not isochronous SPD is set
+ *
+ * Dumps 8 bytes of buffer if PID_SETUP is used.
+ */
+void td_init(td_t *instance, int err_count, size_t size, bool toggle, bool iso,
+    bool low_speed, usb_target_t target, usb_packet_id pid, void *buffer,
+    td_t *next)
+{
+	assert(instance);
+	assert(size < 1024);
+	assert((pid == USB_PID_SETUP) || (pid == USB_PID_IN)
+	    || (pid == USB_PID_OUT));
+
+	const uint32_t next_pa = addr_to_phys(next);
+	assert((next_pa & LINK_POINTER_ADDRESS_MASK) == next_pa);
+
+	instance->next = 0
+	    | LINK_POINTER_VERTICAL_FLAG
+	    | (next_pa ? next_pa : LINK_POINTER_TERMINATE_FLAG);
+
+	instance->status = 0
+	    | ((err_count & TD_STATUS_ERROR_COUNT_MASK) << TD_STATUS_ERROR_COUNT_POS)
+	    | (low_speed ? TD_STATUS_LOW_SPEED_FLAG : 0)
+	    | (iso ? TD_STATUS_ISOCHRONOUS_FLAG : 0)
+	    | TD_STATUS_ERROR_ACTIVE;
+
+	if (pid == USB_PID_IN && !iso) {
+		instance->status |= TD_STATUS_SPD_FLAG;
+	}
+
+	instance->device = 0
+	    | (((size - 1) & TD_DEVICE_MAXLEN_MASK) << TD_DEVICE_MAXLEN_POS)
+	    | (toggle ? TD_DEVICE_DATA_TOGGLE_ONE_FLAG : 0)
+	    | ((target.address & TD_DEVICE_ADDRESS_MASK) << TD_DEVICE_ADDRESS_POS)
+	    | ((target.endpoint & TD_DEVICE_ENDPOINT_MASK) << TD_DEVICE_ENDPOINT_POS)
+	    | ((pid & TD_DEVICE_PID_MASK) << TD_DEVICE_PID_POS);
+
+	instance->buffer_ptr = addr_to_phys(buffer);
+
+	usb_log_debug2("Created TD(%p): %X:%X:%X:%X(%p).\n",
+	    instance, instance->next, instance->status, instance->device,
+	    instance->buffer_ptr, buffer);
+	td_print_status(instance);
+	if (pid == USB_PID_SETUP) {
+		usb_log_debug("SETUP BUFFER: %s\n",
+		    usb_debug_str_buffer(buffer, 8, 8));
+	}
+}
+/*----------------------------------------------------------------------------*/
+/** Convert TD status into standard error code
+ *
+ * @param[in] instance TD structure to use.
+ * @return Error code.
+ */
+int td_status(td_t *instance)
+{
+	assert(instance);
+
+	/* this is hc internal error it should never be reported */
+	if ((instance->status & TD_STATUS_ERROR_BIT_STUFF) != 0)
+		return EAGAIN;
+
+	/* CRC or timeout error, like device not present or bad data,
+	 * it won't be reported unless err count reached zero */
+	if ((instance->status & TD_STATUS_ERROR_CRC) != 0)
+		return EBADCHECKSUM;
+
+	/* hc does not end transaction on these, it should never be reported */
+	if ((instance->status & TD_STATUS_ERROR_NAK) != 0)
+		return EAGAIN;
+
+	/* buffer overrun or underrun */
+	if ((instance->status & TD_STATUS_ERROR_BUFFER) != 0)
+		return ERANGE;
+
+	/* device babble is something serious */
+	if ((instance->status & TD_STATUS_ERROR_BABBLE) != 0)
+		return EIO;
+
+	/* stall might represent err count reaching zero or stall response from
+	 * the device, is err count reached zero, one of the above is reported*/
+	if ((instance->status & TD_STATUS_ERROR_STALLED) != 0)
+		return ESTALL;
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Print values in status field (dw1) in a human readable way.
+ *
+ * @param[in] instance TD structure to use.
+ */
+void td_print_status(td_t *instance)
+{
+	assert(instance);
+	const uint32_t s = instance->status;
+	usb_log_debug2("TD(%p) status(%#x):%s %d,%s%s%s%s%s%s%s%s%s%s%s %d.\n",
+	    instance, instance->status,
+	    (s & TD_STATUS_SPD_FLAG) ? " SPD," : "",
+	    (s >> TD_STATUS_ERROR_COUNT_POS) & TD_STATUS_ERROR_COUNT_MASK,
+	    (s & TD_STATUS_LOW_SPEED_FLAG) ? " LOW SPEED," : "",
+	    (s & TD_STATUS_ISOCHRONOUS_FLAG) ? " ISOCHRONOUS," : "",
+	    (s & TD_STATUS_IOC_FLAG) ? " IOC," : "",
+	    (s & TD_STATUS_ERROR_ACTIVE) ? " ACTIVE," : "",
+	    (s & TD_STATUS_ERROR_STALLED) ? " STALLED," : "",
+	    (s & TD_STATUS_ERROR_BUFFER) ? " BUFFER," : "",
+	    (s & TD_STATUS_ERROR_BABBLE) ? " BABBLE," : "",
+	    (s & TD_STATUS_ERROR_NAK) ? " NAK," : "",
+	    (s & TD_STATUS_ERROR_CRC) ? " CRC/TIMEOUT," : "",
+	    (s & TD_STATUS_ERROR_BIT_STUFF) ? " BIT_STUFF," : "",
+	    (s & TD_STATUS_ERROR_RESERVED) ? " RESERVED," : "",
+	    td_act_size(instance)
+	);
+}
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/hw_struct/transfer_descriptor.h
===================================================================
--- uspace/drv/uhci-hcd/hw_struct/transfer_descriptor.h	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
+++ uspace/drv/uhci-hcd/hw_struct/transfer_descriptor.h	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -0,0 +1,161 @@
+/*
+ * 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 drvusbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef DRV_UHCI_TRANSFER_DESCRIPTOR_H
+#define DRV_UHCI_TRANSFER_DESCRIPTOR_H
+
+#include <mem.h>
+#include <usb/usb.h>
+
+#include "link_pointer.h"
+
+/** UHCI Transfer Descriptor */
+typedef struct transfer_descriptor {
+	link_pointer_t next;
+
+	volatile uint32_t status;
+#define TD_STATUS_RESERVED_MASK 0xc000f800
+#define TD_STATUS_SPD_FLAG ( 1 << 29 )
+#define TD_STATUS_ERROR_COUNT_POS ( 27 )
+#define TD_STATUS_ERROR_COUNT_MASK ( 0x3 )
+#define TD_STATUS_LOW_SPEED_FLAG ( 1 << 26 )
+#define TD_STATUS_ISOCHRONOUS_FLAG ( 1 << 25 )
+#define TD_STATUS_IOC_FLAG ( 1 << 24 )
+
+#define TD_STATUS_ERROR_ACTIVE ( 1 << 23 )
+#define TD_STATUS_ERROR_STALLED ( 1 << 22 )
+#define TD_STATUS_ERROR_BUFFER ( 1 << 21 )
+#define TD_STATUS_ERROR_BABBLE ( 1 << 20 )
+#define TD_STATUS_ERROR_NAK ( 1 << 19 )
+#define TD_STATUS_ERROR_CRC ( 1 << 18 )
+#define TD_STATUS_ERROR_BIT_STUFF ( 1 << 17 )
+#define TD_STATUS_ERROR_RESERVED ( 1 << 16 )
+#define TD_STATUS_ERROR_POS 16
+#define TD_STATUS_ERROR_MASK ( 0xff )
+
+#define TD_STATUS_ACTLEN_POS 0
+#define TD_STATUS_ACTLEN_MASK 0x7ff
+
+	volatile uint32_t device;
+#define TD_DEVICE_MAXLEN_POS 21
+#define TD_DEVICE_MAXLEN_MASK ( 0x7ff )
+#define TD_DEVICE_RESERVED_FLAG ( 1 << 20 )
+#define TD_DEVICE_DATA_TOGGLE_ONE_FLAG ( 1 << 19 )
+#define TD_DEVICE_ENDPOINT_POS 15
+#define TD_DEVICE_ENDPOINT_MASK ( 0xf )
+#define TD_DEVICE_ADDRESS_POS 8
+#define TD_DEVICE_ADDRESS_MASK ( 0x7f )
+#define TD_DEVICE_PID_POS 0
+#define TD_DEVICE_PID_MASK ( 0xff )
+
+	volatile uint32_t buffer_ptr;
+
+	/* there is 16 bytes of data available here, according to UHCI
+	 * Design guide, according to linux kernel the hardware does not care,
+	 * it just needs to be aligned, we don't use it anyway
+	 */
+} __attribute__((packed)) td_t;
+
+
+void td_init(td_t *instance, int error_count, size_t size, bool toggle,
+    bool iso, bool low_speed, usb_target_t target, usb_packet_id pid,
+    void *buffer, td_t *next);
+
+int td_status(td_t *instance);
+
+void td_print_status(td_t *instance);
+/*----------------------------------------------------------------------------*/
+/** Helper function for parsing actual size out of TD.
+ *
+ * @param[in] instance TD structure to use.
+ * @return Parsed actual size.
+ */
+static inline size_t td_act_size(td_t *instance)
+{
+	assert(instance);
+	const uint32_t s = instance->status;
+	return ((s >> TD_STATUS_ACTLEN_POS) + 1) & TD_STATUS_ACTLEN_MASK;
+}
+/*----------------------------------------------------------------------------*/
+/** Check whether less than max data were received on SPD marked transfer.
+ *
+ * @param[in] instance TD structure to use.
+ * @return True if data packet is short (less than max bytes and SPD set),
+ * false otherwise.
+ */
+static inline bool td_is_short(td_t *instance)
+{
+	const size_t act_size = td_act_size(instance);
+	const size_t max_size =
+	    ((instance->device >> TD_DEVICE_MAXLEN_POS) + 1)
+	    & TD_DEVICE_MAXLEN_MASK;
+	return
+	    (instance->status | TD_STATUS_SPD_FLAG) && act_size < max_size;
+}
+/*----------------------------------------------------------------------------*/
+/** Helper function for parsing value of toggle bit.
+ *
+ * @param[in] instance TD structure to use.
+ * @return Toggle bit value.
+ */
+static inline int td_toggle(td_t *instance)
+{
+	assert(instance);
+	return (instance->device & TD_DEVICE_DATA_TOGGLE_ONE_FLAG) ? 1 : 0;
+}
+/*----------------------------------------------------------------------------*/
+/** Helper function for parsing value of active bit
+ *
+ * @param[in] instance TD structure to use.
+ * @return Active bit value.
+ */
+static inline bool td_is_active(td_t *instance)
+{
+	assert(instance);
+	return (instance->status & TD_STATUS_ERROR_ACTIVE) != 0;
+}
+/*----------------------------------------------------------------------------*/
+/** Helper function for setting IOC bit.
+ *
+ * @param[in] instance TD structure to use.
+ */
+static inline void td_set_ioc(td_t *instance)
+{
+	assert(instance);
+	instance->status |= TD_STATUS_IOC_FLAG;
+}
+/*----------------------------------------------------------------------------*/
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/iface.c
===================================================================
--- uspace/drv/uhci-hcd/iface.c	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ uspace/drv/uhci-hcd/iface.c	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -33,12 +33,10 @@
  */
 #include <ddf/driver.h>
-#include <remote_usbhc.h>
+#include <errno.h>
 
 #include <usb/debug.h>
 
-#include <errno.h>
-
 #include "iface.h"
-#include "uhci_hc.h"
+#include "hc.h"
 
 /** Reserve default address interface function
@@ -48,12 +46,11 @@
  * @return Error code.
  */
-/*----------------------------------------------------------------------------*/
 static int reserve_default_address(ddf_fun_t *fun, usb_speed_t speed)
 {
 	assert(fun);
-	uhci_hc_t *hc = fun_to_uhci_hc(fun);
+	hc_t *hc = fun_to_hc(fun);
 	assert(hc);
 	usb_log_debug("Default address request with speed %d.\n", speed);
-	usb_device_keeper_reserve_default_address(&hc->device_manager, speed);
+	usb_device_keeper_reserve_default_address(&hc->manager, speed);
 	return EOK;
 }
@@ -67,8 +64,8 @@
 {
 	assert(fun);
-	uhci_hc_t *hc = fun_to_uhci_hc(fun);
+	hc_t *hc = fun_to_hc(fun);
 	assert(hc);
 	usb_log_debug("Default address release.\n");
-	usb_device_keeper_release_default_address(&hc->device_manager);
+	usb_device_keeper_release_default_address(&hc->manager);
 	return EOK;
 }
@@ -81,17 +78,17 @@
  * @return Error code.
  */
-static int request_address(ddf_fun_t *fun, usb_speed_t speed,
-    usb_address_t *address)
-{
-	assert(fun);
-	uhci_hc_t *hc = fun_to_uhci_hc(fun);
+static int request_address(
+    ddf_fun_t *fun, usb_speed_t speed, usb_address_t *address)
+{
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
 	assert(hc);
 	assert(address);
 
 	usb_log_debug("Address request with speed %d.\n", speed);
-	*address = device_keeper_get_free_address(&hc->device_manager, speed);
+	*address = device_keeper_get_free_address(&hc->manager, speed);
 	usb_log_debug("Address request with result: %d.\n", *address);
 	if (*address <= 0)
-	  return *address;
+		return *address;
 	return EOK;
 }
@@ -108,8 +105,8 @@
 {
 	assert(fun);
-	uhci_hc_t *hc = fun_to_uhci_hc(fun);
+	hc_t *hc = fun_to_hc(fun);
 	assert(hc);
 	usb_log_debug("Address bind %d-%d.\n", address, handle);
-	usb_device_keeper_bind(&hc->device_manager, address, handle);
+	usb_device_keeper_bind(&hc->manager, address, handle);
 	return EOK;
 }
@@ -124,8 +121,8 @@
 {
 	assert(fun);
-	uhci_hc_t *hc = fun_to_uhci_hc(fun);
+	hc_t *hc = fun_to_hc(fun);
 	assert(hc);
 	usb_log_debug("Address release %d.\n", address);
-	usb_device_keeper_release(&hc->device_manager, address);
+	usb_device_keeper_release(&hc->manager, address);
 	return EOK;
 }
@@ -142,28 +139,28 @@
  * @return Error code.
  */
-static int interrupt_out(ddf_fun_t *fun, usb_target_t target,
-    size_t max_packet_size, void *data, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	assert(fun);
-	uhci_hc_t *hc = fun_to_uhci_hc(fun);
-	assert(hc);
-	usb_speed_t speed = usb_device_keeper_get_speed(&hc->device_manager, target.address);
+static int interrupt_out(
+    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
+    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	usb_speed_t speed =
+	    usb_device_keeper_get_speed(&hc->manager, target.address);
 
 	usb_log_debug("Interrupt OUT %d:%d %zu(%zu).\n",
 	    target.address, target.endpoint, size, max_packet_size);
 
-	usb_transfer_batch_t *batch = batch_get(fun, target, USB_TRANSFER_INTERRUPT,
-	    max_packet_size, speed, data, size, NULL, 0, NULL, callback, arg,
-	    &hc->device_manager);
+	usb_transfer_batch_t *batch =
+	    batch_get(fun, target, USB_TRANSFER_INTERRUPT, max_packet_size,
+	        speed, data, size, NULL, 0, NULL, callback, arg, &hc->manager);
 	if (!batch)
 		return ENOMEM;
 	batch_interrupt_out(batch);
-	const int ret = uhci_hc_schedule(hc, batch);
-	if (ret != EOK) {
-		batch_dispose(batch);
-		return ret;
-	}
-	return EOK;
+	const int ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		batch_dispose(batch);
+	}
+	return ret;
 }
 /*----------------------------------------------------------------------------*/
@@ -179,27 +176,27 @@
  * @return Error code.
  */
-static int interrupt_in(ddf_fun_t *fun, usb_target_t target,
-    size_t max_packet_size, void *data, size_t size,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	assert(fun);
-	uhci_hc_t *hc = fun_to_uhci_hc(fun);
-	assert(hc);
-	usb_speed_t speed = usb_device_keeper_get_speed(&hc->device_manager, target.address);
+static int interrupt_in(
+    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
+    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	usb_speed_t speed =
+	    usb_device_keeper_get_speed(&hc->manager, target.address);
 	usb_log_debug("Interrupt IN %d:%d %zu(%zu).\n",
 	    target.address, target.endpoint, size, max_packet_size);
 
-	usb_transfer_batch_t *batch = batch_get(fun, target, USB_TRANSFER_INTERRUPT,
-	    max_packet_size, speed, data, size, NULL, 0, callback, NULL, arg,
-			&hc->device_manager);
+	usb_transfer_batch_t *batch =
+	    batch_get(fun, target, USB_TRANSFER_INTERRUPT, max_packet_size,
+	        speed, data, size, NULL, 0, callback, NULL, arg, &hc->manager);
 	if (!batch)
 		return ENOMEM;
 	batch_interrupt_in(batch);
-	const int ret = uhci_hc_schedule(hc, batch);
-	if (ret != EOK) {
-		batch_dispose(batch);
-		return ret;
-	}
-	return EOK;
+	const int ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		batch_dispose(batch);
+	}
+	return ret;
 }
 /*----------------------------------------------------------------------------*/
@@ -215,28 +212,28 @@
  * @return Error code.
  */
-static int bulk_out(ddf_fun_t *fun, usb_target_t target,
-    size_t max_packet_size, void *data, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	assert(fun);
-	uhci_hc_t *hc = fun_to_uhci_hc(fun);
-	assert(hc);
-	usb_speed_t speed = usb_device_keeper_get_speed(&hc->device_manager, target.address);
+static int bulk_out(
+    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
+    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	usb_speed_t speed =
+	    usb_device_keeper_get_speed(&hc->manager, target.address);
 
 	usb_log_debug("Bulk OUT %d:%d %zu(%zu).\n",
 	    target.address, target.endpoint, size, max_packet_size);
 
-	usb_transfer_batch_t *batch = batch_get(fun, target, USB_TRANSFER_BULK,
-	    max_packet_size, speed, data, size, NULL, 0, NULL, callback, arg,
-	    &hc->device_manager);
+	usb_transfer_batch_t *batch =
+	    batch_get(fun, target, USB_TRANSFER_BULK, max_packet_size, speed,
+	        data, size, NULL, 0, NULL, callback, arg, &hc->manager);
 	if (!batch)
 		return ENOMEM;
 	batch_bulk_out(batch);
-	const int ret = uhci_hc_schedule(hc, batch);
-	if (ret != EOK) {
-		batch_dispose(batch);
-		return ret;
-	}
-	return EOK;
+	const int ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		batch_dispose(batch);
+	}
+	return ret;
 }
 /*----------------------------------------------------------------------------*/
@@ -252,27 +249,27 @@
  * @return Error code.
  */
-static int bulk_in(ddf_fun_t *fun, usb_target_t target,
-    size_t max_packet_size, void *data, size_t size,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	assert(fun);
-	uhci_hc_t *hc = fun_to_uhci_hc(fun);
-	assert(hc);
-	usb_speed_t speed = usb_device_keeper_get_speed(&hc->device_manager, target.address);
+static int bulk_in(
+    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
+    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	usb_speed_t speed =
+	    usb_device_keeper_get_speed(&hc->manager, target.address);
 	usb_log_debug("Bulk IN %d:%d %zu(%zu).\n",
 	    target.address, target.endpoint, size, max_packet_size);
 
-	usb_transfer_batch_t *batch = batch_get(fun, target, USB_TRANSFER_BULK,
-	    max_packet_size, speed, data, size, NULL, 0, callback, NULL, arg,
-	    &hc->device_manager);
+	usb_transfer_batch_t *batch =
+	    batch_get(fun, target, USB_TRANSFER_BULK, max_packet_size, speed,
+	        data, size, NULL, 0, callback, NULL, arg, &hc->manager);
 	if (!batch)
 		return ENOMEM;
 	batch_bulk_in(batch);
-	const int ret = uhci_hc_schedule(hc, batch);
-	if (ret != EOK) {
-		batch_dispose(batch);
-		return ret;
-	}
-	return EOK;
+	const int ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		batch_dispose(batch);
+	}
+	return ret;
 }
 /*----------------------------------------------------------------------------*/
@@ -282,6 +279,6 @@
  * @param[in] target USB device to write to.
  * @param[in] max_packet_size maximum size of data packet the device accepts.
- * @param[in] setup_data Data to send with SETUP packet.
- * @param[in] setup_size Size of data to send with SETUP packet (should be 8B).
+ * @param[in] setup_data Data to send with SETUP transfer.
+ * @param[in] setup_size Size of data to send with SETUP transfer (always 8B).
  * @param[in] data Source of data.
  * @param[in] size Size of data source.
@@ -290,13 +287,14 @@
  * @return Error code.
  */
-static int control_write(ddf_fun_t *fun, usb_target_t target,
-    size_t max_packet_size,
+static int control_write(
+    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,
     void *setup_data, size_t setup_size, void *data, size_t size,
     usbhc_iface_transfer_out_callback_t callback, void *arg)
 {
 	assert(fun);
-	uhci_hc_t *hc = fun_to_uhci_hc(fun);
-	assert(hc);
-	usb_speed_t speed = usb_device_keeper_get_speed(&hc->device_manager, target.address);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	usb_speed_t speed =
+	    usb_device_keeper_get_speed(&hc->manager, target.address);
 	usb_log_debug("Control WRITE (%d) %d:%d %zu(%zu).\n",
 	    speed, target.address, target.endpoint, size, max_packet_size);
@@ -305,17 +303,17 @@
 		return EINVAL;
 
-	usb_transfer_batch_t *batch = batch_get(fun, target, USB_TRANSFER_CONTROL,
-	    max_packet_size, speed, data, size, setup_data, setup_size,
-	    NULL, callback, arg, &hc->device_manager);
-	if (!batch)
-		return ENOMEM;
-	usb_device_keeper_reset_if_need(&hc->device_manager, target, setup_data);
+	usb_transfer_batch_t *batch =
+	    batch_get(fun, target, USB_TRANSFER_CONTROL, max_packet_size, speed,
+	        data, size, setup_data, setup_size, NULL, callback, arg,
+	        &hc->manager);
+	if (!batch)
+		return ENOMEM;
+	usb_device_keeper_reset_if_need(&hc->manager, target, setup_data);
 	batch_control_write(batch);
-	const int ret = uhci_hc_schedule(hc, batch);
-	if (ret != EOK) {
-		batch_dispose(batch);
-		return ret;
-	}
-	return EOK;
+	const int ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		batch_dispose(batch);
+	}
+	return ret;
 }
 /*----------------------------------------------------------------------------*/
@@ -333,31 +331,32 @@
  * @return Error code.
  */
-static int control_read(ddf_fun_t *fun, usb_target_t target,
-    size_t max_packet_size,
+static int control_read(
+    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,
     void *setup_data, size_t setup_size, void *data, size_t size,
     usbhc_iface_transfer_in_callback_t callback, void *arg)
 {
 	assert(fun);
-	uhci_hc_t *hc = fun_to_uhci_hc(fun);
-	assert(hc);
-	usb_speed_t speed = usb_device_keeper_get_speed(&hc->device_manager, target.address);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	usb_speed_t speed =
+	    usb_device_keeper_get_speed(&hc->manager, target.address);
 
 	usb_log_debug("Control READ(%d) %d:%d %zu(%zu).\n",
 	    speed, target.address, target.endpoint, size, max_packet_size);
-	usb_transfer_batch_t *batch = batch_get(fun, target, USB_TRANSFER_CONTROL,
-	    max_packet_size, speed, data, size, setup_data, setup_size, callback,
-	    NULL, arg, &hc->device_manager);
+	usb_transfer_batch_t *batch =
+	    batch_get(fun, target, USB_TRANSFER_CONTROL, max_packet_size, speed,
+	        data, size, setup_data, setup_size, callback, NULL, arg,
+		&hc->manager);
 	if (!batch)
 		return ENOMEM;
 	batch_control_read(batch);
-	const int ret = uhci_hc_schedule(hc, batch);
-	if (ret != EOK) {
-		batch_dispose(batch);
-		return ret;
-	}
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-usbhc_iface_t uhci_hc_iface = {
+	const int ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		batch_dispose(batch);
+	}
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+usbhc_iface_t hc_iface = {
 	.reserve_default_address = reserve_default_address,
 	.release_default_address = release_default_address,
@@ -369,9 +368,9 @@
 	.interrupt_in = interrupt_in,
 
+	.bulk_out = bulk_out,
 	.bulk_in = bulk_in,
-	.bulk_out = bulk_out,
-
+
+	.control_write = control_write,
 	.control_read = control_read,
-	.control_write = control_write,
 };
 /**
Index: uspace/drv/uhci-hcd/iface.h
===================================================================
--- uspace/drv/uhci-hcd/iface.h	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ uspace/drv/uhci-hcd/iface.h	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -38,5 +38,5 @@
 #include <usbhc_iface.h>
 
-extern usbhc_iface_t uhci_hc_iface;
+extern usbhc_iface_t hc_iface;
 
 #endif
Index: uspace/drv/uhci-hcd/main.c
===================================================================
--- uspace/drv/uhci-hcd/main.c	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ uspace/drv/uhci-hcd/main.c	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -62,5 +62,5 @@
 int uhci_add_device(ddf_dev_t *device)
 {
-	usb_log_info("uhci_add_device() called\n");
+	usb_log_debug("uhci_add_device() called\n");
 	assert(device);
 	uhci_t *uhci = malloc(sizeof(uhci_t));
@@ -72,8 +72,12 @@
 	int ret = uhci_init(uhci, device);
 	if (ret != EOK) {
-		usb_log_error("Failed to initialzie UHCI driver.\n");
+		usb_log_error("Failed to initialize UHCI driver: %s.\n",
+		    str_error(ret));
 		return ret;
 	}
 	device->driver_data = uhci;
+
+	usb_log_info("Controlling new UHCI device `%s'.\n", device->name);
+
 	return EOK;
 }
@@ -89,6 +93,8 @@
 int main(int argc, char *argv[])
 {
+	printf(NAME ": HelenOS UHCI driver.\n");
+
 	sleep(3); /* TODO: remove in final version */
-	usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
+	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
 
 	return ddf_driver_main(&uhci_driver);
Index: uspace/drv/uhci-hcd/root_hub.c
===================================================================
--- uspace/drv/uhci-hcd/root_hub.c	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
+++ uspace/drv/uhci-hcd/root_hub.c	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -0,0 +1,82 @@
+/*
+ * 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 drvusbuhci
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#include <assert.h>
+#include <errno.h>
+#include <str_error.h>
+#include <stdio.h>
+
+#include <usb/debug.h>
+
+#include "root_hub.h"
+
+/** Root hub initialization
+ * @param[in] instance RH structure to initialize
+ * @param[in] fun DDF function representing UHCI root hub
+ * @param[in] reg_addr Address of root hub status and control registers.
+ * @param[in] reg_size Size of accessible address space.
+ * @return Error code.
+ */
+int rh_init(
+    rh_t *instance, ddf_fun_t *fun, uintptr_t reg_addr, size_t reg_size)
+{
+	assert(fun);
+
+	char *match_str = NULL;
+	int ret = asprintf(&match_str, "usb&uhci&root-hub");
+	if (ret < 0) {
+		usb_log_error("Failed to create root hub match string.\n");
+		return ENOMEM;
+	}
+
+	ret = ddf_fun_add_match_id(fun, match_str, 100);
+	if (ret != EOK) {
+		usb_log_error("Failed(%d) to add root hub match id: %s\n",
+		    ret, str_error(ret));
+		return ret;
+	}
+
+	hw_resource_list_t *resource_list = &instance->resource_list;
+	resource_list->count = 1;
+	resource_list->resources = &instance->io_regs;
+	assert(resource_list->resources);
+	instance->io_regs.type = IO_RANGE;
+	instance->io_regs.res.io_range.address = reg_addr;
+	instance->io_regs.res.io_range.size = reg_size;
+	instance->io_regs.res.io_range.endianness = LITTLE_ENDIAN;
+
+	return EOK;
+}
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/root_hub.h
===================================================================
--- uspace/drv/uhci-hcd/root_hub.h	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
+++ uspace/drv/uhci-hcd/root_hub.h	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -0,0 +1,52 @@
+/*
+ * 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 drvusbuhci
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef DRV_UHCI_UHCI_RH_H
+#define DRV_UHCI_UHCI_RH_H
+
+#include <ddf/driver.h>
+#include <ops/hw_res.h>
+
+typedef struct rh {
+	hw_resource_list_t resource_list;
+	hw_resource_t io_regs;
+} rh_t;
+
+int rh_init(
+    rh_t *instance, ddf_fun_t *fun, uintptr_t reg_addr, size_t reg_size);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/transfer_list.c
===================================================================
--- uspace/drv/uhci-hcd/transfer_list.c	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ uspace/drv/uhci-hcd/transfer_list.c	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -79,7 +79,6 @@
 	if (!instance->queue_head)
 		return;
-	/* Set both next and element to point to the same QH */
+	/* Set both queue_head.next to point to the follower */
 	qh_set_next_qh(instance->queue_head, next->queue_head_pa);
-	qh_set_element_qh(instance->queue_head, next->queue_head_pa);
 }
 /*----------------------------------------------------------------------------*/
@@ -92,5 +91,6 @@
  * The batch is added to the end of the list and queue.
  */
-void transfer_list_add_batch(transfer_list_t *instance, usb_transfer_batch_t *batch)
+void transfer_list_add_batch(
+    transfer_list_t *instance, usb_transfer_batch_t *batch)
 {
 	assert(instance);
@@ -98,25 +98,24 @@
 	usb_log_debug2("Queue %s: Adding batch(%p).\n", instance->name, batch);
 
-	const uint32_t pa = addr_to_phys(batch_qh(batch));
-	assert((pa & LINK_POINTER_ADDRESS_MASK) == pa);
-
-	/* New batch will be added to the end of the current list
-	 * so set the link accordingly */
-	qh_set_next_qh(batch_qh(batch), instance->queue_head->next);
-
 	fibril_mutex_lock(&instance->guard);
 
+	qh_t *last_qh = NULL;
 	/* Add to the hardware queue. */
 	if (list_empty(&instance->batch_list)) {
 		/* There is nothing scheduled */
-		qh_t *qh = instance->queue_head;
-		assert(qh->element == qh->next);
-		qh_set_element_qh(qh, pa);
+		last_qh = instance->queue_head;
 	} else {
 		/* There is something scheduled */
 		usb_transfer_batch_t *last = list_get_instance(
 		    instance->batch_list.prev, usb_transfer_batch_t, link);
-		qh_set_next_qh(batch_qh(last), pa);
-	}
+		last_qh = batch_qh(last);
+	}
+	const uint32_t pa = addr_to_phys(batch_qh(batch));
+	assert((pa & LINK_POINTER_ADDRESS_MASK) == pa);
+
+	/* keep link */
+	batch_qh(batch)->next = last_qh->next;
+	qh_set_next_qh(last_qh, pa);
+
 	/* Add to the driver list */
 	list_append(&batch->link, &instance->batch_list);
@@ -148,5 +147,6 @@
 	while (current != &instance->batch_list) {
 		link_t *next = current->next;
-		usb_transfer_batch_t *batch = list_get_instance(current, usb_transfer_batch_t, link);
+		usb_transfer_batch_t *batch =
+		    list_get_instance(current, usb_transfer_batch_t, link);
 
 		if (batch_is_complete(batch)) {
@@ -162,5 +162,6 @@
 		link_t *item = done.next;
 		list_remove(item);
-		usb_transfer_batch_t *batch = list_get_instance(item, usb_transfer_batch_t, link);
+		usb_transfer_batch_t *batch =
+		    list_get_instance(item, usb_transfer_batch_t, link);
 		batch->next_step(batch);
 	}
@@ -174,7 +175,8 @@
 {
 	fibril_mutex_lock(&instance->guard);
-	while (list_empty(&instance->batch_list)) {
+	while (!list_empty(&instance->batch_list)) {
 		link_t *current = instance->batch_list.next;
-		usb_transfer_batch_t *batch = list_get_instance(current, usb_transfer_batch_t, link);
+		usb_transfer_batch_t *batch =
+		    list_get_instance(current, usb_transfer_batch_t, link);
 		transfer_list_remove_batch(instance, batch);
 		usb_transfer_batch_finish(batch, EIO);
@@ -191,5 +193,6 @@
  * Does not lock the transfer list, caller is responsible for that.
  */
-void transfer_list_remove_batch(transfer_list_t *instance, usb_transfer_batch_t *batch)
+void transfer_list_remove_batch(
+    transfer_list_t *instance, usb_transfer_batch_t *batch)
 {
 	assert(instance);
@@ -197,23 +200,30 @@
 	assert(batch);
 	assert(batch_qh(batch));
+	assert(fibril_mutex_is_locked(&instance->guard));
+
 	usb_log_debug2(
 	    "Queue %s: removing batch(%p).\n", instance->name, batch);
 
-	const char * pos = NULL;
+	const char *qpos = NULL;
 	/* Remove from the hardware queue */
-	if (batch->link.prev == &instance->batch_list) {
+	if (instance->batch_list.next == &batch->link) {
 		/* I'm the first one here */
-		qh_set_element_qh(instance->queue_head, batch_qh(batch)->next);
-		pos = "FIRST";
+		assert((instance->queue_head->next & LINK_POINTER_ADDRESS_MASK)
+		    == addr_to_phys(batch_qh(batch)));
+		instance->queue_head->next = batch_qh(batch)->next;
+		qpos = "FIRST";
 	} else {
 		usb_transfer_batch_t *prev =
-		    list_get_instance(batch->link.prev, usb_transfer_batch_t, link);
-		qh_set_next_qh(batch_qh(prev), batch_qh(batch)->next);
-		pos = "NOT FIRST";
-	}
-	/* Remove from the driver list */
+		    list_get_instance(
+		        batch->link.prev, usb_transfer_batch_t, link);
+		assert((batch_qh(prev)->next & LINK_POINTER_ADDRESS_MASK)
+		    == addr_to_phys(batch_qh(batch)));
+		batch_qh(prev)->next = batch_qh(batch)->next;
+		qpos = "NOT FIRST";
+	}
+	/* Remove from the batch list */
 	list_remove(&batch->link);
-	usb_log_debug("Batch(%p) removed (%s) from %s, next element %x.\n",
-	    batch, pos, instance->name, batch_qh(batch)->next);
+	usb_log_debug("Batch(%p) removed (%s) from %s, next %x.\n",
+	    batch, qpos, instance->name, batch_qh(batch)->next);
 }
 /**
Index: uspace/drv/uhci-hcd/transfer_list.h
===================================================================
--- uspace/drv/uhci-hcd/transfer_list.h	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ uspace/drv/uhci-hcd/transfer_list.h	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -37,7 +37,6 @@
 #include <fibril_synch.h>
 
-#include "uhci_struct/queue_head.h"
-
 #include "batch.h"
+#include "hw_struct/queue_head.h"
 
 typedef struct transfer_list
Index: uspace/drv/uhci-hcd/uhci.c
===================================================================
--- uspace/drv/uhci-hcd/uhci.c	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ uspace/drv/uhci-hcd/uhci.c	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -54,8 +54,8 @@
 {
 	assert(dev);
-	uhci_hc_t *hc = &((uhci_t*)dev->driver_data)->hc;
+	hc_t *hc = &((uhci_t*)dev->driver_data)->hc;
 	uint16_t status = IPC_GET_ARG1(*call);
 	assert(hc);
-	uhci_hc_interrupt(hc, status);
+	hc_interrupt(hc, status);
 }
 /*----------------------------------------------------------------------------*/
@@ -70,5 +70,5 @@
 {
 	assert(fun);
-	usb_device_keeper_t *manager = &((uhci_t*)fun->dev->driver_data)->hc.device_manager;
+	usb_device_keeper_t *manager = &((uhci_t*)fun->dev->driver_data)->hc.manager;
 
 	usb_address_t addr = usb_device_keeper_find(manager, handle);
@@ -107,7 +107,7 @@
 };
 /*----------------------------------------------------------------------------*/
-static ddf_dev_ops_t uhci_hc_ops = {
+static ddf_dev_ops_t hc_ops = {
 	.interfaces[USB_DEV_IFACE] = &usb_iface,
-	.interfaces[USBHC_DEV_IFACE] = &uhci_hc_iface, /* see iface.h/c */
+	.interfaces[USBHC_DEV_IFACE] = &hc_iface, /* see iface.h/c */
 };
 /*----------------------------------------------------------------------------*/
@@ -120,5 +120,5 @@
 {
 	assert(fun);
-	return &((uhci_rh_t*)fun->driver_data)->resource_list;
+	return &((rh_t*)fun->driver_data)->resource_list;
 }
 /*----------------------------------------------------------------------------*/
@@ -128,5 +128,5 @@
 };
 /*----------------------------------------------------------------------------*/
-static ddf_dev_ops_t uhci_rh_ops = {
+static ddf_dev_ops_t rh_ops = {
 	.interfaces[USB_DEV_IFACE] = &usb_iface,
 	.interfaces[HW_RES_DEV_IFACE] = &hw_res_iface
@@ -167,5 +167,5 @@
 	CHECK_RET_DEST_FUN_RETURN(ret,
 	    "Failed(%d) to get I/O addresses:.\n", ret, device->handle);
-	usb_log_info("I/O regs at 0x%X (size %zu), IRQ %d.\n",
+	usb_log_debug("I/O regs at 0x%X (size %zu), IRQ %d.\n",
 	    io_reg_base, io_reg_size, irq);
 
@@ -175,13 +175,19 @@
 
 	bool interrupts = false;
+#ifdef CONFIG_USBHC_NO_INTERRUPTS
+	usb_log_warning("Interrupts disabled in OS config, " \
+	    "falling back to polling.\n");
+#else
 	ret = pci_enable_interrupts(device);
 	if (ret != EOK) {
-		usb_log_warning(
-		    "Failed(%d) to enable interrupts, fall back to polling.\n",
-		    ret);
+		usb_log_warning("Failed to enable interrupts: %s.\n",
+		    str_error(ret));
+		usb_log_info("HW interrupts not available, " \
+		    "falling back to polling.\n");
 	} else {
 		usb_log_debug("Hw interrupts enabled.\n");
 		interrupts = true;
 	}
+#endif
 
 	instance->hc_fun = ddf_fun_create(device, fun_exposed, "uhci-hc");
@@ -190,8 +196,8 @@
 	    "Failed(%d) to create HC function.\n", ret);
 
-	ret = uhci_hc_init(&instance->hc, instance->hc_fun,
+	ret = hc_init(&instance->hc, instance->hc_fun,
 	    (void*)io_reg_base, io_reg_size, interrupts);
 	CHECK_RET_DEST_FUN_RETURN(ret, "Failed(%d) to init uhci-hcd.\n", ret);
-	instance->hc_fun->ops = &uhci_hc_ops;
+	instance->hc_fun->ops = &hc_ops;
 	instance->hc_fun->driver_data = &instance->hc;
 	ret = ddf_fun_bind(instance->hc_fun);
@@ -208,5 +214,5 @@
 	if (instance->rh_fun) \
 		ddf_fun_destroy(instance->rh_fun); \
-	uhci_hc_fini(&instance->hc); \
+	hc_fini(&instance->hc); \
 	return ret; \
 }
@@ -223,10 +229,10 @@
 	    "Failed(%d) to create root hub function.\n", ret);
 
-	ret = uhci_rh_init(&instance->rh, instance->rh_fun,
+	ret = rh_init(&instance->rh, instance->rh_fun,
 	    (uintptr_t)instance->hc.registers + 0x10, 4);
 	CHECK_RET_FINI_RETURN(ret,
 	    "Failed(%d) to setup UHCI root hub.\n", ret);
 
-	instance->rh_fun->ops = &uhci_rh_ops;
+	instance->rh_fun->ops = &rh_ops;
 	instance->rh_fun->driver_data = &instance->rh;
 	ret = ddf_fun_bind(instance->rh_fun);
Index: uspace/drv/uhci-hcd/uhci.h
===================================================================
--- uspace/drv/uhci-hcd/uhci.h	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ uspace/drv/uhci-hcd/uhci.h	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -38,6 +38,6 @@
 #include <ddf/driver.h>
 
-#include "uhci_hc.h"
-#include "uhci_rh.h"
+#include "hc.h"
+#include "root_hub.h"
 
 typedef struct uhci {
@@ -45,6 +45,6 @@
 	ddf_fun_t *rh_fun;
 
-	uhci_hc_t hc;
-	uhci_rh_t rh;
+	hc_t hc;
+	rh_t rh;
 } uhci_t;
 
Index: uspace/drv/uhci-hcd/uhci_hc.c
===================================================================
--- uspace/drv/uhci-hcd/uhci_hc.c	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ 	(revision )
@@ -1,499 +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 drvusbuhcihc
- * @{
- */
-/** @file
- * @brief UHCI Host controller driver routines
- */
-#include <errno.h>
-#include <str_error.h>
-#include <adt/list.h>
-#include <libarch/ddi.h>
-
-#include <usb/debug.h>
-#include <usb/usb.h>
-#include <usb/ddfiface.h>
-#include <usb_iface.h>
-
-#include "uhci_hc.h"
-
-static irq_cmd_t uhci_cmds[] = {
-	{
-		.cmd = CMD_PIO_READ_16,
-		.addr = NULL, /* patched for every instance */
-		.dstarg = 1
-	},
-	{
-		.cmd = CMD_PIO_WRITE_16,
-		.addr = NULL, /* pathed for every instance */
-		.value = 0x1f
-	},
-	{
-		.cmd = CMD_ACCEPT
-	}
-};
-/*----------------------------------------------------------------------------*/
-static int uhci_hc_init_transfer_lists(uhci_hc_t *instance);
-static int uhci_hc_init_mem_structures(uhci_hc_t *instance);
-static void uhci_hc_init_hw(uhci_hc_t *instance);
-
-static int uhci_hc_interrupt_emulator(void *arg);
-static int uhci_hc_debug_checker(void *arg);
-
-static bool allowed_usb_packet(
-    bool low_speed, usb_transfer_type_t transfer, size_t size);
-/*----------------------------------------------------------------------------*/
-/** Initialize UHCI hcd driver structure
- *
- * @param[in] instance Memory place to initialize.
- * @param[in] fun DDF function.
- * @param[in] regs Address of I/O control registers.
- * @param[in] size Size of I/O control registers.
- * @return Error code.
- * @note Should be called only once on any structure.
- *
- * Initializes memory structures, starts up hw, and launches debugger and
- * interrupt fibrils.
- */
-int uhci_hc_init(uhci_hc_t *instance, ddf_fun_t *fun,
-    void *regs, size_t reg_size, bool interrupts)
-{
-	assert(reg_size >= sizeof(regs_t));
-	int ret;
-
-#define CHECK_RET_DEST_FUN_RETURN(ret, message...) \
-	if (ret != EOK) { \
-		usb_log_error(message); \
-		if (instance->ddf_instance) \
-			ddf_fun_destroy(instance->ddf_instance); \
-		return ret; \
-	} else (void) 0
-
-	instance->hw_interrupts = interrupts;
-	instance->hw_failures = 0;
-
-	/* Setup UHCI function. */
-	instance->ddf_instance = fun;
-
-	/* allow access to hc control registers */
-	regs_t *io;
-	ret = pio_enable(regs, reg_size, (void**)&io);
-	CHECK_RET_DEST_FUN_RETURN(ret,
-	    "Failed(%d) to gain access to registers at %p: %s.\n",
-	    ret, str_error(ret), io);
-	instance->registers = io;
-	usb_log_debug("Device registers at %p(%u) accessible.\n",
-	    io, reg_size);
-
-	ret = uhci_hc_init_mem_structures(instance);
-	CHECK_RET_DEST_FUN_RETURN(ret,
-	    "Failed to initialize UHCI memory structures.\n");
-
-	uhci_hc_init_hw(instance);
-	if (!interrupts) {
-		instance->cleaner =
-		    fibril_create(uhci_hc_interrupt_emulator, instance);
-		fibril_add_ready(instance->cleaner);
-	} else {
-		/* TODO: enable interrupts here */
-	}
-
-	instance->debug_checker = fibril_create(uhci_hc_debug_checker, instance);
-	fibril_add_ready(instance->debug_checker);
-
-	usb_log_info("Started UHCI driver.\n");
-	return EOK;
-#undef CHECK_RET_DEST_FUN_RETURN
-}
-/*----------------------------------------------------------------------------*/
-/** Initialize UHCI hc hw resources.
- *
- * @param[in] instance UHCI structure to use.
- * For magic values see UHCI Design Guide
- */
-void uhci_hc_init_hw(uhci_hc_t *instance)
-{
-	assert(instance);
-	regs_t *registers = instance->registers;
-
-	/* Reset everything, who knows what touched it before us */
-	pio_write_16(&registers->usbcmd, UHCI_CMD_GLOBAL_RESET);
-	async_usleep(10000); /* 10ms according to USB spec */
-	pio_write_16(&registers->usbcmd, 0);
-
-	/* Reset hc, all states and counters */
-	pio_write_16(&registers->usbcmd, UHCI_CMD_HCRESET);
-	do { async_usleep(10); }
-	while ((pio_read_16(&registers->usbcmd) & UHCI_CMD_HCRESET) != 0);
-
-	/* Set frame to exactly 1ms */
-	pio_write_8(&registers->sofmod, 64);
-
-	/* Set frame list pointer */
-	const uint32_t pa = addr_to_phys(instance->frame_list);
-	pio_write_32(&registers->flbaseadd, pa);
-
-	if (instance->hw_interrupts) {
-		/* Enable all interrupts, but resume interrupt */
-		pio_write_16(&instance->registers->usbintr,
-		    UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET);
-	}
-
-	uint16_t status = pio_read_16(&registers->usbcmd);
-	if (status != 0)
-		usb_log_warning("Previous command value: %x.\n", status);
-
-	/* Start the hc with large(64B) packet FSBR */
-	pio_write_16(&registers->usbcmd,
-	    UHCI_CMD_RUN_STOP | UHCI_CMD_MAX_PACKET | UHCI_CMD_CONFIGURE);
-}
-/*----------------------------------------------------------------------------*/
-/** Initialize UHCI hc memory structures.
- *
- * @param[in] instance UHCI structure to use.
- * @return Error code
- * @note Should be called only once on any structure.
- *
- * Structures:
- *  - interrupt code (I/O addressses are customized per instance)
- *  - transfer lists (queue heads need to be accessible by the hw)
- *  - frame list page (needs to be one UHCI hw accessible 4K page)
- */
-int uhci_hc_init_mem_structures(uhci_hc_t *instance)
-{
-	assert(instance);
-#define CHECK_RET_DEST_CMDS_RETURN(ret, message...) \
-	if (ret != EOK) { \
-		usb_log_error(message); \
-		if (instance->interrupt_code.cmds != NULL) \
-			free(instance->interrupt_code.cmds); \
-		return ret; \
-	} else (void) 0
-
-	/* Init interrupt code */
-	instance->interrupt_code.cmds = malloc(sizeof(uhci_cmds));
-	int ret = (instance->interrupt_code.cmds == NULL) ? ENOMEM : EOK;
-	CHECK_RET_DEST_CMDS_RETURN(ret,
-	    "Failed to allocate interrupt cmds space.\n");
-
-	{
-		irq_cmd_t *interrupt_commands = instance->interrupt_code.cmds;
-		memcpy(interrupt_commands, uhci_cmds, sizeof(uhci_cmds));
-		interrupt_commands[0].addr =
-		    (void*)&instance->registers->usbsts;
-		interrupt_commands[1].addr =
-		    (void*)&instance->registers->usbsts;
-		instance->interrupt_code.cmdcount =
-		    sizeof(uhci_cmds) / sizeof(irq_cmd_t);
-	}
-
-	/* Init transfer lists */
-	ret = uhci_hc_init_transfer_lists(instance);
-	CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to init transfer lists.\n");
-	usb_log_debug("Initialized transfer lists.\n");
-
-	/* Init USB frame list page*/
-	instance->frame_list = get_page();
-	ret = instance ? EOK : ENOMEM;
-	CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to get frame list page.\n");
-	usb_log_debug("Initialized frame list.\n");
-
-	/* Set all frames to point to the first queue head */
-	const uint32_t queue =
-	  instance->transfers_interrupt.queue_head_pa
-	  | LINK_POINTER_QUEUE_HEAD_FLAG;
-
-	unsigned i = 0;
-	for(; i < UHCI_FRAME_LIST_COUNT; ++i) {
-		instance->frame_list[i] = queue;
-	}
-
-	/* Init device keeper*/
-	usb_device_keeper_init(&instance->device_manager);
-	usb_log_debug("Initialized device manager.\n");
-
-	return EOK;
-#undef CHECK_RET_DEST_CMDS_RETURN
-}
-/*----------------------------------------------------------------------------*/
-/** Initialize UHCI hc transfer lists.
- *
- * @param[in] instance UHCI structure to use.
- * @return Error code
- * @note Should be called only once on any structure.
- *
- * Initializes transfer lists and sets them in one chain to support proper
- * USB scheduling. Sets pointer table for quick access.
- */
-int uhci_hc_init_transfer_lists(uhci_hc_t *instance)
-{
-	assert(instance);
-#define CHECK_RET_CLEAR_RETURN(ret, message...) \
-	if (ret != EOK) { \
-		usb_log_error(message); \
-		transfer_list_fini(&instance->transfers_bulk_full); \
-		transfer_list_fini(&instance->transfers_control_full); \
-		transfer_list_fini(&instance->transfers_control_slow); \
-		transfer_list_fini(&instance->transfers_interrupt); \
-		return ret; \
-	} else (void) 0
-
-	/* initialize TODO: check errors */
-	int ret;
-	ret = transfer_list_init(&instance->transfers_bulk_full, "BULK_FULL");
-	CHECK_RET_CLEAR_RETURN(ret, "Failed to init BULK list.");
-
-	ret = transfer_list_init(
-	    &instance->transfers_control_full, "CONTROL_FULL");
-	CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL FULL list.");
-
-	ret = transfer_list_init(
-	    &instance->transfers_control_slow, "CONTROL_SLOW");
-	CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL SLOW list.");
-
-	ret = transfer_list_init(&instance->transfers_interrupt, "INTERRUPT");
-	CHECK_RET_CLEAR_RETURN(ret, "Failed to init INTERRUPT list.");
-
-	transfer_list_set_next(&instance->transfers_control_full,
-		&instance->transfers_bulk_full);
-	transfer_list_set_next(&instance->transfers_control_slow,
-		&instance->transfers_control_full);
-	transfer_list_set_next(&instance->transfers_interrupt,
-		&instance->transfers_control_slow);
-
-	/*FSBR*/
-#ifdef FSBR
-	transfer_list_set_next(&instance->transfers_bulk_full,
-		&instance->transfers_control_full);
-#endif
-
-	/* Assign pointers to be used during scheduling */
-	instance->transfers[USB_SPEED_FULL][USB_TRANSFER_INTERRUPT] =
-	  &instance->transfers_interrupt;
-	instance->transfers[USB_SPEED_LOW][USB_TRANSFER_INTERRUPT] =
-	  &instance->transfers_interrupt;
-	instance->transfers[USB_SPEED_FULL][USB_TRANSFER_CONTROL] =
-	  &instance->transfers_control_full;
-	instance->transfers[USB_SPEED_LOW][USB_TRANSFER_CONTROL] =
-	  &instance->transfers_control_slow;
-	instance->transfers[USB_SPEED_FULL][USB_TRANSFER_BULK] =
-	  &instance->transfers_bulk_full;
-
-	return EOK;
-#undef CHECK_RET_CLEAR_RETURN
-}
-/*----------------------------------------------------------------------------*/
-/** Schedule batch for execution.
- *
- * @param[in] instance UHCI structure to use.
- * @param[in] batch Transfer batch to schedule.
- * @return Error code
- *
- * Checks for bandwidth availability and appends the batch to the proper queue.
- */
-int uhci_hc_schedule(uhci_hc_t *instance, usb_transfer_batch_t *batch)
-{
-	assert(instance);
-	assert(batch);
-	const int low_speed = (batch->speed == USB_SPEED_LOW);
-	if (!allowed_usb_packet(
-	    low_speed, batch->transfer_type, batch->max_packet_size)) {
-		usb_log_warning(
-		    "Invalid USB packet specified %s SPEED %d %zu.\n",
-		    low_speed ? "LOW" : "FULL" , batch->transfer_type,
-		    batch->max_packet_size);
-		return ENOTSUP;
-	}
-	/* TODO: check available bandwidth here */
-
-	transfer_list_t *list =
-	    instance->transfers[batch->speed][batch->transfer_type];
-	assert(list);
-	transfer_list_add_batch(list, batch);
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/** Take action based on the interrupt cause.
- *
- * @param[in] instance UHCI structure to use.
- * @param[in] status Value of the status register at the time of interrupt.
- *
- * Interrupt might indicate:
- * - transaction completed, either by triggering IOC, SPD, or an error
- * - some kind of device error
- * - resume from suspend state (not implemented)
- */
-void uhci_hc_interrupt(uhci_hc_t *instance, uint16_t status)
-{
-	assert(instance);
-	/* TODO: Resume interrupts are not supported */
-	/* Lower 2 bits are transaction error and transaction complete */
-	if (status & 0x3) {
-		transfer_list_remove_finished(&instance->transfers_interrupt);
-		transfer_list_remove_finished(&instance->transfers_control_slow);
-		transfer_list_remove_finished(&instance->transfers_control_full);
-		transfer_list_remove_finished(&instance->transfers_bulk_full);
-	}
-	/* bits 4 and 5 indicate hc error */
-	if (status & 0x18) {
-		usb_log_error("UHCI hardware failure!.\n");
-		++instance->hw_failures;
-		transfer_list_abort_all(&instance->transfers_interrupt);
-		transfer_list_abort_all(&instance->transfers_control_slow);
-		transfer_list_abort_all(&instance->transfers_control_full);
-		transfer_list_abort_all(&instance->transfers_bulk_full);
-
-		if (instance->hw_failures < UHCI_ALLOWED_HW_FAIL) {
-			/* reinitialize hw, this triggers virtual disconnect*/
-			uhci_hc_init_hw(instance);
-		} else {
-			usb_log_fatal("Too many UHCI hardware failures!.\n");
-			uhci_hc_fini(instance);
-		}
-	}
-}
-/*----------------------------------------------------------------------------*/
-/** Polling function, emulates interrupts.
- *
- * @param[in] arg UHCI hc structure to use.
- * @return EOK (should never return)
- */
-int uhci_hc_interrupt_emulator(void* arg)
-{
-	usb_log_debug("Started interrupt emulator.\n");
-	uhci_hc_t *instance = (uhci_hc_t*)arg;
-	assert(instance);
-
-	while (1) {
-		/* read and ack interrupts */
-		uint16_t status = pio_read_16(&instance->registers->usbsts);
-		pio_write_16(&instance->registers->usbsts, 0x1f);
-		if (status != 0)
-			usb_log_debug2("UHCI status: %x.\n", status);
-		uhci_hc_interrupt(instance, status);
-		async_usleep(UHCI_CLEANER_TIMEOUT);
-	}
-	return EOK;
-}
-/*---------------------------------------------------------------------------*/
-/** Debug function, checks consistency of memory structures.
- *
- * @param[in] arg UHCI structure to use.
- * @return EOK (should never return)
- */
-int uhci_hc_debug_checker(void *arg)
-{
-	uhci_hc_t *instance = (uhci_hc_t*)arg;
-	assert(instance);
-
-#define QH(queue) \
-	instance->transfers_##queue.queue_head
-
-	while (1) {
-		const uint16_t cmd = pio_read_16(&instance->registers->usbcmd);
-		const uint16_t sts = pio_read_16(&instance->registers->usbsts);
-		const uint16_t intr =
-		    pio_read_16(&instance->registers->usbintr);
-
-		if (((cmd & UHCI_CMD_RUN_STOP) != 1) || (sts != 0)) {
-			usb_log_debug2("Command: %X Status: %X Intr: %x\n",
-			    cmd, sts, intr);
-		}
-
-		uintptr_t frame_list =
-		    pio_read_32(&instance->registers->flbaseadd) & ~0xfff;
-		if (frame_list != addr_to_phys(instance->frame_list)) {
-			usb_log_debug("Framelist address: %p vs. %p.\n",
-			    frame_list, addr_to_phys(instance->frame_list));
-		}
-
-		int frnum = pio_read_16(&instance->registers->frnum) & 0x3ff;
-
-		uintptr_t expected_pa = instance->frame_list[frnum]
-		    & LINK_POINTER_ADDRESS_MASK;
-		uintptr_t real_pa = addr_to_phys(QH(interrupt));
-		if (expected_pa != real_pa) {
-			usb_log_debug("Interrupt QH: %p(frame: %d) vs. %p.\n",
-			    expected_pa, frnum, real_pa);
-		}
-
-		expected_pa = QH(interrupt)->next & LINK_POINTER_ADDRESS_MASK;
-		real_pa = addr_to_phys(QH(control_slow));
-		if (expected_pa != real_pa) {
-			usb_log_debug("Control Slow QH: %p vs. %p.\n",
-			    expected_pa, real_pa);
-		}
-
-		expected_pa = QH(control_slow)->next & LINK_POINTER_ADDRESS_MASK;
-		real_pa = addr_to_phys(QH(control_full));
-		if (expected_pa != real_pa) {
-			usb_log_debug("Control Full QH: %p vs. %p.\n",
-			    expected_pa, real_pa);
-		}
-
-		expected_pa = QH(control_full)->next & LINK_POINTER_ADDRESS_MASK;
-		real_pa = addr_to_phys(QH(bulk_full));
-		if (expected_pa != real_pa ) {
-			usb_log_debug("Bulk QH: %p vs. %p.\n",
-			    expected_pa, real_pa);
-		}
-		async_usleep(UHCI_DEBUGER_TIMEOUT);
-	}
-	return EOK;
-#undef QH
-}
-/*----------------------------------------------------------------------------*/
-/** Check transfer packets, for USB validity
- *
- * @param[in] low_speed Transfer speed.
- * @param[in] transfer Transer type
- * @param[in] size Maximum size of used packets
- * @return True if transaction is allowed by USB specs, false otherwise
- */
-bool allowed_usb_packet(
-    bool low_speed, usb_transfer_type_t transfer, size_t size)
-{
-	/* see USB specification chapter 5.5-5.8 for magic numbers used here */
-	switch(transfer)
-	{
-	case USB_TRANSFER_ISOCHRONOUS:
-		return (!low_speed && size < 1024);
-	case USB_TRANSFER_INTERRUPT:
-		return size <= (low_speed ? 8 : 64);
-	case USB_TRANSFER_CONTROL: /* device specifies its own max size */
-		return (size <= (low_speed ? 8 : 64));
-	case USB_TRANSFER_BULK: /* device specifies its own max size */
-		return (!low_speed && size <= 64);
-	}
-	return false;
-}
-/**
- * @}
- */
Index: uspace/drv/uhci-hcd/uhci_hc.h
===================================================================
--- uspace/drv/uhci-hcd/uhci_hc.h	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ 	(revision )
@@ -1,131 +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 drvusbuhcihc
- * @{
- */
-/** @file
- * @brief UHCI host controller driver structure
- */
-#ifndef DRV_UHCI_UHCI_HC_H
-#define DRV_UHCI_UHCI_HC_H
-
-#include <fibril.h>
-#include <fibril_synch.h>
-#include <adt/list.h>
-#include <ddi.h>
-
-#include <usbhc_iface.h>
-#include <usb/host/device_keeper.h>
-
-#include "batch.h"
-#include "transfer_list.h"
-
-typedef struct uhci_regs {
-	uint16_t usbcmd;
-#define UHCI_CMD_MAX_PACKET (1 << 7)
-#define UHCI_CMD_CONFIGURE  (1 << 6)
-#define UHCI_CMD_DEBUG  (1 << 5)
-#define UHCI_CMD_FORCE_GLOBAL_RESUME  (1 << 4)
-#define UHCI_CMD_FORCE_GLOBAL_SUSPEND  (1 << 3)
-#define UHCI_CMD_GLOBAL_RESET  (1 << 2)
-#define UHCI_CMD_HCRESET  (1 << 1)
-#define UHCI_CMD_RUN_STOP  (1 << 0)
-
-	uint16_t usbsts;
-#define UHCI_STATUS_HALTED (1 << 5)
-#define UHCI_STATUS_PROCESS_ERROR (1 << 4)
-#define UHCI_STATUS_SYSTEM_ERROR (1 << 3)
-#define UHCI_STATUS_RESUME (1 << 2)
-#define UHCI_STATUS_ERROR_INTERRUPT (1 << 1)
-#define UHCI_STATUS_INTERRUPT (1 << 0)
-
-	uint16_t usbintr;
-#define UHCI_INTR_SHORT_PACKET (1 << 3)
-#define UHCI_INTR_COMPLETE (1 << 2)
-#define UHCI_INTR_RESUME (1 << 1)
-#define UHCI_INTR_CRC (1 << 0)
-
-	uint16_t frnum;
-	uint32_t flbaseadd;
-	uint8_t sofmod;
-} regs_t;
-
-#define UHCI_FRAME_LIST_COUNT 1024
-#define UHCI_CLEANER_TIMEOUT 10000
-#define UHCI_DEBUGER_TIMEOUT 5000000
-#define UHCI_ALLOWED_HW_FAIL 5
-
-typedef struct uhci_hc {
-	usb_device_keeper_t device_manager;
-
-	regs_t *registers;
-
-	link_pointer_t *frame_list;
-
-	transfer_list_t transfers_bulk_full;
-	transfer_list_t transfers_control_full;
-	transfer_list_t transfers_control_slow;
-	transfer_list_t transfers_interrupt;
-
-	transfer_list_t *transfers[2][4];
-
-	irq_code_t interrupt_code;
-
-	fid_t cleaner;
-	fid_t debug_checker;
-	bool hw_interrupts;
-	unsigned hw_failures;
-
-	ddf_fun_t *ddf_instance;
-} uhci_hc_t;
-
-int uhci_hc_init(uhci_hc_t *instance, ddf_fun_t *fun,
-    void *regs, size_t reg_size, bool interupts);
-
-int uhci_hc_schedule(uhci_hc_t *instance, usb_transfer_batch_t *batch);
-
-void uhci_hc_interrupt(uhci_hc_t *instance, uint16_t status);
-
-/** Safely dispose host controller internal structures
- *
- * @param[in] instance Host controller structure to use.
- */
-static inline void uhci_hc_fini(uhci_hc_t *instance) { /* TODO: implement*/ };
-
-/** Get and cast pointer to the driver data
- *
- * @param[in] fun DDF function pointer
- * @return cast pointer to driver_data
- */
-static inline uhci_hc_t * fun_to_uhci_hc(ddf_fun_t *fun)
-	{ return (uhci_hc_t*)fun->driver_data; }
-#endif
-/**
- * @}
- */
Index: uspace/drv/uhci-hcd/uhci_rh.c
===================================================================
--- uspace/drv/uhci-hcd/uhci_rh.c	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ 	(revision )
@@ -1,83 +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 drvusbuhci
- * @{
- */
-/** @file
- * @brief UHCI driver
- */
-#include <assert.h>
-#include <errno.h>
-#include <str_error.h>
-#include <stdio.h>
-
-#include <usb/debug.h>
-
-#include "uhci_rh.h"
-#include "uhci_hc.h"
-
-/** Root hub initialization
- * @param[in] instance RH structure to initialize
- * @param[in] fun DDF function representing UHCI root hub
- * @param[in] reg_addr Address of root hub status and control registers.
- * @param[in] reg_size Size of accessible address space.
- * @return Error code.
- */
-int uhci_rh_init(
-    uhci_rh_t *instance, ddf_fun_t *fun, uintptr_t reg_addr, size_t reg_size)
-{
-	assert(fun);
-
-	char *match_str = NULL;
-	int ret = asprintf(&match_str, "usb&uhci&root-hub");
-	if (ret < 0) {
-		usb_log_error("Failed to create root hub match string.\n");
-		return ENOMEM;
-	}
-
-	ret = ddf_fun_add_match_id(fun, match_str, 100);
-	if (ret != EOK) {
-		usb_log_error("Failed(%d) to add root hub match id: %s\n",
-		    ret, str_error(ret));
-		return ret;
-	}
-
-	hw_resource_list_t *resource_list = &instance->resource_list;
-	resource_list->count = 1;
-	resource_list->resources = &instance->io_regs;
-	assert(resource_list->resources);
-	instance->io_regs.type = IO_RANGE;
-	instance->io_regs.res.io_range.address = reg_addr;
-	instance->io_regs.res.io_range.size = reg_size;
-	instance->io_regs.res.io_range.endianness = LITTLE_ENDIAN;
-
-	return EOK;
-}
-/**
- * @}
- */
Index: uspace/drv/uhci-hcd/uhci_rh.h
===================================================================
--- uspace/drv/uhci-hcd/uhci_rh.h	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ 	(revision )
@@ -1,52 +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 drvusbuhci
- * @{
- */
-/** @file
- * @brief UHCI driver
- */
-#ifndef DRV_UHCI_UHCI_RH_H
-#define DRV_UHCI_UHCI_RH_H
-
-#include <ddf/driver.h>
-#include <ops/hw_res.h>
-
-typedef struct uhci_rh {
-	hw_resource_list_t resource_list;
-	hw_resource_t io_regs;
-} uhci_rh_t;
-
-int uhci_rh_init(
-    uhci_rh_t *instance, ddf_fun_t *fun, uintptr_t reg_addr, size_t reg_size);
-
-#endif
-/**
- * @}
- */
Index: uspace/drv/uhci-hcd/uhci_struct/link_pointer.h
===================================================================
--- uspace/drv/uhci-hcd/uhci_struct/link_pointer.h	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ 	(revision )
@@ -1,55 +1,0 @@
-/*
- * Copyright (c) 2010 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 drvusbuhcihc
- * @{
- */
-/** @file
- * @brief UHCI driver
- */
-#ifndef DRV_UHCI_LINK_POINTER_H
-#define DRV_UHCI_LINK_POINTER_H
-
-/* UHCI link pointer, used by many data structures */
-typedef uint32_t link_pointer_t;
-
-#define LINK_POINTER_TERMINATE_FLAG (1 << 0)
-#define LINK_POINTER_QUEUE_HEAD_FLAG (1 << 1)
-#define LINK_POINTER_ZERO_BIT_FLAG (1 << 2)
-#define LINK_POINTER_VERTICAL_FLAG (1 << 2)
-#define LINK_POINTER_RESERVED_FLAG (1 << 3)
-
-#define LINK_POINTER_ADDRESS_MASK 0xfffffff0 /* upper 28 bits */
-
-#define LINK_POINTER_QH(address) \
-	((address & LINK_POINTER_ADDRESS_MASK) | LINK_POINTER_QUEUE_HEAD_FLAG)
-
-#endif
-/**
- * @}
- */
-
Index: uspace/drv/uhci-hcd/uhci_struct/queue_head.h
===================================================================
--- uspace/drv/uhci-hcd/uhci_struct/queue_head.h	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ 	(revision )
@@ -1,120 +1,0 @@
-/*
- * Copyright (c) 2010 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 drv usbuhcihc
- * @{
- */
-/** @file
- * @brief UHCI driver
- */
-#ifndef DRV_UHCI_QH_H
-#define DRV_UHCI_QH_H
-
-/* libc */
-#include <assert.h>
-
-#include "link_pointer.h"
-#include "utils/malloc32.h"
-
-typedef struct queue_head {
-	volatile link_pointer_t next;
-	volatile link_pointer_t element;
-} __attribute__((packed)) qh_t;
-/*----------------------------------------------------------------------------*/
-/** Initialize queue head structure
- *
- * @param[in] instance qh_t structure to initialize.
- *
- * Sets both pointer to terminal NULL.
- */
-static inline void qh_init(qh_t *instance)
-{
-	assert(instance);
-
-	instance->element = 0 | LINK_POINTER_TERMINATE_FLAG;
-	instance->next = 0 | LINK_POINTER_TERMINATE_FLAG;
-}
-/*----------------------------------------------------------------------------*/
-/** Set queue head next pointer
- *
- * @param[in] instance qh_t structure to use.
- * @param[in] pa Physical address of the next queue head.
- *
- * Adds proper flag. If the pointer is NULL or terminal, sets next to terminal
- * NULL.
- */
-static inline void qh_set_next_qh(qh_t *instance, uint32_t pa)
-{
-	/* Address is valid and not terminal */
-	if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) {
-		instance->next = (pa & LINK_POINTER_ADDRESS_MASK)
-		    | LINK_POINTER_QUEUE_HEAD_FLAG;
-	} else {
-		instance->next = 0 | LINK_POINTER_TERMINATE_FLAG;
-	}
-}
-/*----------------------------------------------------------------------------*/
-/** Set queue head element pointer
- *
- * @param[in] instance qh_t structure to initialize.
- * @param[in] pa Physical address of the next queue head.
- *
- * Adds proper flag. If the pointer is NULL or terminal, sets element
- * to terminal NULL.
- */
-static inline void qh_set_element_qh(qh_t *instance, uint32_t pa)
-{
-	/* Address is valid and not terminal */
-	if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) {
-		instance->element = (pa & LINK_POINTER_ADDRESS_MASK)
-		    | LINK_POINTER_QUEUE_HEAD_FLAG;
-	} else {
-		instance->element = 0 | LINK_POINTER_TERMINATE_FLAG;
-	}
-}
-/*----------------------------------------------------------------------------*/
-/** Set queue head element pointer
- *
- * @param[in] instance qh_t structure to initialize.
- * @param[in] pa Physical address of the TD structure.
- *
- * Adds proper flag. If the pointer is NULL or terminal, sets element
- * to terminal NULL.
- */
-static inline void qh_set_element_td(qh_t *instance, uint32_t pa)
-{
-	if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) {
-		instance->element = (pa & LINK_POINTER_ADDRESS_MASK);
-	} else {
-		instance->element = 0 | LINK_POINTER_TERMINATE_FLAG;
-	}
-}
-
-#endif
-/**
- * @}
- */
Index: uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c
===================================================================
--- uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ 	(revision )
@@ -1,166 +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 drvusbuhcihc
- * @{
- */
-/** @file
- * @brief UHCI driver
- */
-#include <errno.h>
-#include <usb/debug.h>
-
-#include "transfer_descriptor.h"
-#include "utils/malloc32.h"
-
-/** Initialize Transfer Descriptor
- *
- * @param[in] instance Memory place to initialize.
- * @param[in] err_count Number of retries hc should attempt.
- * @param[in] size Size of data source.
- * @param[in] toggle Value of toggle bit.
- * @param[in] iso True if TD represents Isochronous transfer.
- * @param[in] low_speed Target device's speed.
- * @param[in] target Address and endpoint receiving the transfer.
- * @param[in] pid Packet identification (SETUP, IN or OUT).
- * @param[in] buffer Source of data.
- * @param[in] next Net TD in transaction.
- * @return Error code.
- *
- * Uses a mix of supplied and default values.
- * Implicit values:
- *  - all TDs have vertical flag set (makes transfers to endpoints atomic)
- *  - in the error field only active it is set
- *  - if the packet uses PID_IN and is not isochronous SPD is set
- *
- * Dumps 8 bytes of buffer if PID_SETUP is used.
- */
-void td_init(td_t *instance, int err_count, size_t size, bool toggle, bool iso,
-    bool low_speed, usb_target_t target, usb_packet_id pid, void *buffer,
-    td_t *next)
-{
-	assert(instance);
-	assert(size < 1024);
-	assert((pid == USB_PID_SETUP) || (pid == USB_PID_IN)
-	    || (pid == USB_PID_OUT));
-
-	instance->next = 0
-	    | LINK_POINTER_VERTICAL_FLAG
-	    | ((next != NULL) ? addr_to_phys(next) : LINK_POINTER_TERMINATE_FLAG);
-
-	instance->status = 0
-	    | ((err_count & TD_STATUS_ERROR_COUNT_MASK) << TD_STATUS_ERROR_COUNT_POS)
-	    | (low_speed ? TD_STATUS_LOW_SPEED_FLAG : 0)
-	    | (iso ? TD_STATUS_ISOCHRONOUS_FLAG : 0)
-	    | TD_STATUS_ERROR_ACTIVE;
-
-	if (pid == USB_PID_IN && !iso) {
-		instance->status |= TD_STATUS_SPD_FLAG;
-	}
-
-	instance->device = 0
-	    | (((size - 1) & TD_DEVICE_MAXLEN_MASK) << TD_DEVICE_MAXLEN_POS)
-	    | (toggle ? TD_DEVICE_DATA_TOGGLE_ONE_FLAG : 0)
-	    | ((target.address & TD_DEVICE_ADDRESS_MASK) << TD_DEVICE_ADDRESS_POS)
-	    | ((target.endpoint & TD_DEVICE_ENDPOINT_MASK) << TD_DEVICE_ENDPOINT_POS)
-	    | ((pid & TD_DEVICE_PID_MASK) << TD_DEVICE_PID_POS);
-
-	instance->buffer_ptr = 0;
-
-	if (size) {
-		instance->buffer_ptr = (uintptr_t)addr_to_phys(buffer);
-	}
-
-	usb_log_debug2("Created TD(%p): %X:%X:%X:%X(%p).\n",
-	    instance, instance->next, instance->status, instance->device,
-	    instance->buffer_ptr, buffer);
-	td_print_status(instance);
-	if (pid == USB_PID_SETUP) {
-		usb_log_debug("SETUP BUFFER: %s\n",
-		    usb_debug_str_buffer(buffer, 8, 8));
-	}
-}
-/*----------------------------------------------------------------------------*/
-/** Convert TD status into standard error code
- *
- * @param[in] instance TD structure to use.
- * @return Error code.
- */
-int td_status(td_t *instance)
-{
-	assert(instance);
-
-	if ((instance->status & TD_STATUS_ERROR_STALLED) != 0)
-		return ESTALL;
-
-	if ((instance->status & TD_STATUS_ERROR_CRC) != 0)
-		return EBADCHECKSUM;
-
-	if ((instance->status & TD_STATUS_ERROR_BUFFER) != 0)
-		return EAGAIN;
-
-	if ((instance->status & TD_STATUS_ERROR_BABBLE) != 0)
-		return EIO;
-
-	if ((instance->status & TD_STATUS_ERROR_NAK) != 0)
-		return EAGAIN;
-
-	if ((instance->status & TD_STATUS_ERROR_BIT_STUFF) != 0)
-		return EAGAIN;
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/** Print values in status field (dw1) in a human readable way.
- *
- * @param[in] instance TD structure to use.
- */
-void td_print_status(td_t *instance)
-{
-	assert(instance);
-	const uint32_t s = instance->status;
-	usb_log_debug2("TD(%p) status(%#x):%s %d,%s%s%s%s%s%s%s%s%s%s%s %d.\n",
-	    instance, instance->status,
-	    (s & TD_STATUS_SPD_FLAG) ? " SPD," : "",
-	    (s >> TD_STATUS_ERROR_COUNT_POS) & TD_STATUS_ERROR_COUNT_MASK,
-	    (s & TD_STATUS_LOW_SPEED_FLAG) ? " LOW SPEED," : "",
-	    (s & TD_STATUS_ISOCHRONOUS_FLAG) ? " ISOCHRONOUS," : "",
-	    (s & TD_STATUS_IOC_FLAG) ? " IOC," : "",
-	    (s & TD_STATUS_ERROR_ACTIVE) ? " ACTIVE," : "",
-	    (s & TD_STATUS_ERROR_STALLED) ? " STALLED," : "",
-	    (s & TD_STATUS_ERROR_BUFFER) ? " BUFFER," : "",
-	    (s & TD_STATUS_ERROR_BABBLE) ? " BABBLE," : "",
-	    (s & TD_STATUS_ERROR_NAK) ? " NAK," : "",
-	    (s & TD_STATUS_ERROR_CRC) ? " CRC/TIMEOUT," : "",
-	    (s & TD_STATUS_ERROR_BIT_STUFF) ? " BIT_STUFF," : "",
-	    (s & TD_STATUS_ERROR_RESERVED) ? " RESERVED," : "",
-	    td_act_size(instance)
-	);
-}
-/**
- * @}
- */
Index: uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h
===================================================================
--- uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ 	(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 drvusbuhcihc
- * @{
- */
-/** @file
- * @brief UHCI driver
- */
-#ifndef DRV_UHCI_TRANSFER_DESCRIPTOR_H
-#define DRV_UHCI_TRANSFER_DESCRIPTOR_H
-
-#include <mem.h>
-#include <usb/usb.h>
-
-#include "link_pointer.h"
-
-/** UHCI Transfer Descriptor */
-typedef struct transfer_descriptor {
-	link_pointer_t next;
-
-	volatile uint32_t status;
-#define TD_STATUS_RESERVED_MASK 0xc000f800
-#define TD_STATUS_SPD_FLAG ( 1 << 29 )
-#define TD_STATUS_ERROR_COUNT_POS ( 27 )
-#define TD_STATUS_ERROR_COUNT_MASK ( 0x3 )
-#define TD_STATUS_LOW_SPEED_FLAG ( 1 << 26 )
-#define TD_STATUS_ISOCHRONOUS_FLAG ( 1 << 25 )
-#define TD_STATUS_IOC_FLAG ( 1 << 24 )
-
-#define TD_STATUS_ERROR_ACTIVE ( 1 << 23 )
-#define TD_STATUS_ERROR_STALLED ( 1 << 22 )
-#define TD_STATUS_ERROR_BUFFER ( 1 << 21 )
-#define TD_STATUS_ERROR_BABBLE ( 1 << 20 )
-#define TD_STATUS_ERROR_NAK ( 1 << 19 )
-#define TD_STATUS_ERROR_CRC ( 1 << 18 )
-#define TD_STATUS_ERROR_BIT_STUFF ( 1 << 17 )
-#define TD_STATUS_ERROR_RESERVED ( 1 << 16 )
-#define TD_STATUS_ERROR_POS 16
-#define TD_STATUS_ERROR_MASK ( 0xff )
-
-#define TD_STATUS_ACTLEN_POS 0
-#define TD_STATUS_ACTLEN_MASK 0x7ff
-
-	volatile uint32_t device;
-#define TD_DEVICE_MAXLEN_POS 21
-#define TD_DEVICE_MAXLEN_MASK ( 0x7ff )
-#define TD_DEVICE_RESERVED_FLAG ( 1 << 20 )
-#define TD_DEVICE_DATA_TOGGLE_ONE_FLAG ( 1 << 19 )
-#define TD_DEVICE_ENDPOINT_POS 15
-#define TD_DEVICE_ENDPOINT_MASK ( 0xf )
-#define TD_DEVICE_ADDRESS_POS 8
-#define TD_DEVICE_ADDRESS_MASK ( 0x7f )
-#define TD_DEVICE_PID_POS 0
-#define TD_DEVICE_PID_MASK ( 0xff )
-
-	volatile uint32_t buffer_ptr;
-
-	/* there is 16 bytes of data available here, according to UHCI
-	 * Design guide, according to linux kernel the hardware does not care,
-	 * it just needs to be aligned, we don't use it anyway
-	 */
-} __attribute__((packed)) td_t;
-
-
-void td_init(td_t *instance, int error_count, size_t size, bool toggle,
-    bool iso, bool low_speed, usb_target_t target, usb_packet_id pid,
-    void *buffer, td_t *next);
-
-int td_status(td_t *instance);
-
-void td_print_status(td_t *instance);
-/*----------------------------------------------------------------------------*/
-/** Helper function for parsing actual size out of TD.
- *
- * @param[in] instance TD structure to use.
- * @return Parsed actual size.
- */
-static inline size_t td_act_size(td_t *instance)
-{
-	assert(instance);
-	const uint32_t s = instance->status;
-	return ((s >> TD_STATUS_ACTLEN_POS) + 1) & TD_STATUS_ACTLEN_MASK;
-}
-/*----------------------------------------------------------------------------*/
-/** Check whether less than max data were recieved and packet is marked as SPD.
- *
- * @param[in] instance TD structure to use.
- * @return True if packet is short (less than max bytes and SPD set), false
- *     otherwise.
- */
-static inline bool td_is_short(td_t *instance)
-{
-	const size_t act_size = td_act_size(instance);
-	const size_t max_size =
-	    ((instance->device >> TD_DEVICE_MAXLEN_POS) + 1)
-	    & TD_DEVICE_MAXLEN_MASK;
-	return
-	    (instance->status | TD_STATUS_SPD_FLAG) && act_size < max_size;
-}
-/*----------------------------------------------------------------------------*/
-/** Helper function for parsing value of toggle bit.
- *
- * @param[in] instance TD structure to use.
- * @return Toggle bit value.
- */
-static inline int td_toggle(td_t *instance)
-{
-	assert(instance);
-	return (instance->device & TD_DEVICE_DATA_TOGGLE_ONE_FLAG) ? 1 : 0;
-}
-/*----------------------------------------------------------------------------*/
-/** Helper function for parsing value of active bit
- *
- * @param[in] instance TD structure to use.
- * @return Active bit value.
- */
-static inline bool td_is_active(td_t *instance)
-{
-	assert(instance);
-	return (instance->status & TD_STATUS_ERROR_ACTIVE) != 0;
-}
-/*----------------------------------------------------------------------------*/
-/** Helper function for setting IOC bit.
- *
- * @param[in] instance TD structure to use.
- */
-static inline void td_set_ioc(td_t *instance)
-{
-	assert(instance);
-	instance->status |= TD_STATUS_IOC_FLAG;
-}
-/*----------------------------------------------------------------------------*/
-#endif
-/**
- * @}
- */
Index: uspace/drv/uhci-hcd/utils/malloc32.h
===================================================================
--- uspace/drv/uhci-hcd/utils/malloc32.h	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ uspace/drv/uhci-hcd/utils/malloc32.h	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -50,4 +50,7 @@
 static inline uintptr_t addr_to_phys(void *addr)
 {
+	if (addr == NULL)
+		return 0;
+
 	uintptr_t result;
 	int ret = as_get_physical_mapping(addr, &result);
Index: uspace/drv/uhci-rhd/main.c
===================================================================
--- uspace/drv/uhci-rhd/main.c	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ uspace/drv/uhci-rhd/main.c	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -36,4 +36,5 @@
 #include <device/hw_res.h>
 #include <errno.h>
+#include <str_error.h>
 #include <usb_iface.h>
 #include <usb/ddfiface.h>
@@ -86,8 +87,8 @@
 	int ret = hc_get_my_registers(device, &io_regs, &io_size);
 	if (ret != EOK) {
-		usb_log_error("Failed(%d) to get registers from parent hc.",
-		    ret);
-	}
-	usb_log_info("I/O regs at %#X (size %zu).\n", io_regs, io_size);
+		usb_log_error("Failed to get registers from parent HC: %s.\n",
+		    str_error(ret));
+	}
+	usb_log_debug("I/O regs at %#X (size %zu).\n", io_regs, io_size);
 
 	uhci_root_hub_t *rh = malloc(sizeof(uhci_root_hub_t));
@@ -99,5 +100,6 @@
 	ret = uhci_root_hub_init(rh, (void*)io_regs, io_size, device);
 	if (ret != EOK) {
-		usb_log_error("Failed(%d) to initialize driver instance.\n", ret);
+		usb_log_error("Failed to initialize driver instance: %s.\n",
+		    str_error(ret));
 		free(rh);
 		return ret;
@@ -105,6 +107,6 @@
 
 	device->driver_data = rh;
-	usb_log_info("Sucessfully initialized driver instance for device:%d.\n",
-	    device->handle);
+	usb_log_info("Controlling root hub `%s' (%llu).\n",
+	    device->name, device->handle);
 	return EOK;
 }
@@ -129,5 +131,8 @@
 int main(int argc, char *argv[])
 {
-	usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
+	printf(NAME ": HelenOS UHCI root hub driver.\n");
+
+	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
+
 	return ddf_driver_main(&uhci_rh_driver);
 }
Index: uspace/drv/uhci-rhd/port.c
===================================================================
--- uspace/drv/uhci-rhd/port.c	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ uspace/drv/uhci-rhd/port.c	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -256,5 +256,5 @@
 	assert(usb_hc_connection_is_opened(&port->hc_connection));
 
-	usb_log_info("%s: Detected new device.\n", port->id_string);
+	usb_log_debug("%s: Detected new device.\n", port->id_string);
 
 	usb_address_t dev_addr;
@@ -270,6 +270,6 @@
 	}
 
-	usb_log_info("%s: New device has address %d (handle %zu).\n",
-	    port->id_string, dev_addr, port->attached_device);
+	usb_log_info("New device at port %u, address %d (handle %llu).\n",
+	    port->number, dev_addr, port->attached_device);
 
 	return EOK;
@@ -315,5 +315,5 @@
 	uhci_port_write_status(port, port_status);
 
-	usb_log_info("%s: %sabled port.\n",
+	usb_log_debug("%s: %sabled port.\n",
 		port->id_string, enabled ? "En" : "Dis");
 	return EOK;
Index: uspace/drv/usbflbk/main.c
===================================================================
--- uspace/drv/usbflbk/main.c	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ uspace/drv/usbflbk/main.c	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -86,5 +86,5 @@
 int main(int argc, char *argv[])
 {
-	usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
+	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
 
 	return usb_driver_main(&usbfallback_driver);
Index: uspace/drv/usbhid/Makefile
===================================================================
--- uspace/drv/usbhid/Makefile	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ 	(revision )
@@ -1,55 +1,0 @@
-#
-# Copyright (c) 2010-2011 Vojtech Horky
-# 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.
-#
-
-USPACE_PREFIX = ../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBUSB_PREFIX)/libusb.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBUSB_PREFIX)/include -I.
-BINARY = usbhid
-
-STOLEN_LAYOUT_SOURCES = \
-	layout/us_qwerty.c \
-	layout/us_dvorak.c \
-	layout/cz.c
-
-SOURCES = \
-	main.c \
-	conv.c \
-	hidreq.c \
-	kbddev.c \
-	kbdrepeat.c \
-	hiddev.c \
-	$(STOLEN_LAYOUT_SOURCES)
-
-EXTRA_CLEAN = $(STOLEN_LAYOUT_SOURCES)
-
-SRV_KBD = $(USPACE_PREFIX)/srv/hid/kbd
-
-include $(USPACE_PREFIX)/Makefile.common
-
-layout/%.c: $(SRV_KBD)/layout/%.c
-	ln -sfn ../$< $@
Index: uspace/drv/usbhid/conv.c
===================================================================
--- uspace/drv/usbhid/conv.c	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ 	(revision )
@@ -1,193 +1,0 @@
-/*
- * Copyright (c) 2011 Lubos Slovak
- * 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 drvusbhid
- * @{
- */
-/** @file
- * USB scancode parser.
- */
-
-#include <io/keycode.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <usb/debug.h>
-#include "conv.h"
-
-/**
- * Mapping between USB HID key codes (from HID Usage Tables) and corresponding
- * HelenOS key codes.
- */
-static int scanmap_simple[255] = {
-
-//	[0x29] = KC_BACKTICK,
-
-//	[0x02] = KC_1,
-//	[0x03] = KC_2,
-	[0x04] = KC_A,
-	[0x05] = KC_B,
-	[0x06] = KC_C,
-	[0x07] = KC_D,
-	[0x08] = KC_E,
-	[0x09] = KC_F,
-	[0x0a] = KC_G,
-	[0x0b] = KC_H,
-	[0x0c] = KC_I,
-	[0x0d] = KC_J,
-	[0x0e] = KC_K,
-	[0x0f] = KC_L,
-	[0x10] = KC_M,
-	[0x11] = KC_N,
-	[0x12] = KC_O,
-	[0x13] = KC_P,
-	[0x14] = KC_Q,
-	[0x15] = KC_R,
-	[0x16] = KC_S,
-	[0x17] = KC_T,
-	[0x18] = KC_U,
-	[0x19] = KC_V,
-	[0x1a] = KC_W,
-	[0x1b] = KC_X,
-	[0x1c] = KC_Y,
-	[0x1d] = KC_Z,
-
-	[0x1e] = KC_1,
-	[0x1f] = KC_2,
-	[0x20] = KC_3,
-	[0x21] = KC_4,
-	[0x22] = KC_5,
-	[0x23] = KC_6,
-	[0x24] = KC_7,
-	[0x25] = KC_8,
-	[0x26] = KC_9,
-	[0x27] = KC_0,
-	
-	[0x28] = KC_ENTER,
-	[0x29] = KC_ESCAPE,
-	[0x2a] = KC_BACKSPACE,
-	[0x2b] = KC_TAB,
-	[0x2c] = KC_SPACE,
-
-	[0x2d] = KC_MINUS,  // same as DASH? (- or _)
-	[0x2e] = KC_EQUALS,
-	[0x2f] = KC_LBRACKET,
-	[0x30] = KC_RBRACKET,
-	[0x31] = KC_BACKSLASH,
-	//[0x32] = KC_,	// TODO: HASH??? maybe some as 0x31 - backslash
-	[0x33] = KC_SEMICOLON,
-	[0x34] = KC_QUOTE,  // same as APOSTROPHE? (')
-	[0x35] = KC_BACKTICK,  // same as GRAVE ACCENT?? (`)
-	[0x36] = KC_COMMA,
-	[0x37] = KC_PERIOD,
-	[0x38] = KC_SLASH,
-
-	[0x39] = KC_CAPS_LOCK,
-	
-	[0x3a] = KC_F1,
-	[0x3b] = KC_F2,
-	[0x3c] = KC_F3,
-	[0x3d] = KC_F4,
-	[0x3e] = KC_F5,
-	[0x3f] = KC_F6,
-	[0x40] = KC_F7,
-	[0x41] = KC_F8,
-	[0x42] = KC_F9,
-	[0x43] = KC_F10,
-	[0x44] = KC_F11,
-	[0x45] = KC_F12,
-	
-	[0x46] = KC_PRTSCR,
-	[0x47] = KC_SCROLL_LOCK,
-	[0x48] = KC_PAUSE,
-	[0x49] = KC_INSERT,
-	[0x4a] = KC_HOME,
-	[0x4b] = KC_PAGE_UP,
-	[0x4c] = KC_DELETE,
-	[0x4d] = KC_END,
-	[0x4e] = KC_PAGE_DOWN,
-	[0x4f] = KC_RIGHT,
-	[0x50] = KC_LEFT,
-	[0x51] = KC_DOWN,
-	[0x52] = KC_UP,
-	
-	//[0x64] = // some funny key
-	
-	[0xe0] = KC_LCTRL,
-	[0xe1] = KC_LSHIFT,
-	[0xe2] = KC_LALT,
-	//[0xe3] = KC_L	// TODO: left GUI
-	[0xe4] = KC_RCTRL,
-	[0xe5] = KC_RSHIFT,
-	[0xe6] = KC_RALT,
-	//[0xe7] = KC_R	// TODO: right GUI
-	
-	[0x53] = KC_NUM_LOCK,
-	[0x54] = KC_NSLASH,
-	[0x55] = KC_NTIMES,
-	[0x56] = KC_NMINUS,
-	[0x57] = KC_NPLUS,
-	[0x58] = KC_NENTER,
-	[0x59] = KC_N1,
-	[0x5a] = KC_N2,
-	[0x5b] = KC_N3,
-	[0x5c] = KC_N4,
-	[0x5d] = KC_N5,
-	[0x5e] = KC_N6,
-	[0x5f] = KC_N7,
-	[0x60] = KC_N8,
-	[0x61] = KC_N9,
-	[0x62] = KC_N0,
-	[0x63] = KC_NPERIOD
-	
-};
-
-/**
- * Translate USB HID key codes (from HID Usage Tables) to generic key codes
- * recognized by HelenOS.
- *
- * @param scancode USB HID key code (from HID Usage Tables).
- * 
- * @retval HelenOS key code corresponding to the given USB HID key code.
- */
-unsigned int usbhid_parse_scancode(int scancode)
-{
-	unsigned int key;
-	int *map = scanmap_simple;
-	size_t map_length = sizeof(scanmap_simple) / sizeof(int);
-
-	if ((scancode < 0) || ((size_t) scancode >= map_length))
-		return -1;
-
-	key = map[scancode];
-	
-	return key;
-}
-
-/**
- * @}
- */
Index: uspace/drv/usbhid/conv.h
===================================================================
--- uspace/drv/usbhid/conv.h	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ 	(revision )
@@ -1,45 +1,0 @@
-/*
- * Copyright (c) 2011 Lubos Slovak
- * 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 drvusbhid
- * @{
- */
-/** @file
- * USB scancode parser.
- */
-
-#ifndef USBHID_CONV_H_
-#define USBHID_CONV_H_
-
-unsigned int usbhid_parse_scancode(int scancode);
-
-#endif /* USBHID_CONV_H_ */
-
-/**
- * @}
- */
Index: uspace/drv/usbhid/descdump.c
===================================================================
--- uspace/drv/usbhid/descdump.c	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ 	(revision )
@@ -1,201 +1,0 @@
-/*
- * Copyright (c) 2010 Lubos Slovak
- * 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 drvusbhid
- * @{
- */
-/** @file
- * Descriptor dumping.
- */
-
-#include <usb/classes/hid.h>
-#include <stdio.h>
-#include <assert.h>
-
-#include "descdump.h"
-
-/*----------------------------------------------------------------------------*/
-
-#define BYTES_PER_LINE 12
-
-/**
- * Dumps the given buffer in hexadecimal format to standard output.
- *
- * @param msg Message to print before the buffer.
- * @param buffer Buffer to print.
- * @param length Size of the buffer in bytes.
- */
-static void dump_buffer(const char *msg, const uint8_t *buffer, size_t length)
-{
-	printf("%s\n", msg);
-
-	size_t i;
-	for (i = 0; i < length; i++) {
-		printf("  0x%02X", buffer[i]);
-		if (((i > 0) && (((i+1) % BYTES_PER_LINE) == 0))
-		    || (i + 1 == length)) {
-			printf("\n");
-		}
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-#define INDENT "  "
-
-/**
- * Print standard configuration descriptor to standard output.
- *
- * @param index Index of the descriptor.
- * @param d Standard configuration descriptor to print.
- */
-void dump_standard_configuration_descriptor(
-    int index, const usb_standard_configuration_descriptor_t *d)
-{
-	bool self_powered = d->attributes & 64;
-	bool remote_wakeup = d->attributes & 32;
-	
-	printf("Standard configuration descriptor #%d\n", index);
-	printf(INDENT "bLength = %d\n", d->length);
-	printf(INDENT "bDescriptorType = 0x%02x\n", d->descriptor_type);
-	printf(INDENT "wTotalLength = %d\n", d->total_length);
-	printf(INDENT "bNumInterfaces = %d\n", d->interface_count);
-	printf(INDENT "bConfigurationValue = %d\n", d->configuration_number);
-	printf(INDENT "iConfiguration = %d\n", d->str_configuration);
-	printf(INDENT "bmAttributes = %d [%s%s%s]\n", d->attributes,
-	    self_powered ? "self-powered" : "",
-	    (self_powered & remote_wakeup) ? ", " : "",
-	    remote_wakeup ? "remote-wakeup" : "");
-	printf(INDENT "MaxPower = %d (%dmA)\n", d->max_power,
-	    2 * d->max_power);
-	// printf(INDENT " = %d\n", d->);
-}
-
-/**
- * Print standard interface descriptor to standard output.
- *
- * @param d Standard interface descriptor to print.
- */
-void dump_standard_interface_descriptor(
-    const usb_standard_interface_descriptor_t *d)
-{
-	printf("Standard interface descriptor\n");
-	printf(INDENT "bLength = %d\n", d->length);
-	printf(INDENT "bDescriptorType = 0x%02x\n", d->descriptor_type);
-	printf(INDENT "bInterfaceNumber = %d\n", d->interface_number);
-	printf(INDENT "bAlternateSetting = %d\n", d->alternate_setting);
-	printf(INDENT "bNumEndpoints = %d\n", d->endpoint_count);
-	printf(INDENT "bInterfaceClass = %d\n", d->interface_class);
-	printf(INDENT "bInterfaceSubClass = %d\n", d->interface_subclass);
-	printf(INDENT "bInterfaceProtocol = %d\n", d->interface_protocol);
-	printf(INDENT "iInterface = %d\n", d->str_interface);
-}
-
-/**
- * Print standard endpoint descriptor to standard output.
- *
- * @param d Standard endpoint descriptor to print.
- */
-void dump_standard_endpoint_descriptor(
-    const usb_standard_endpoint_descriptor_t *d)
-{
-	const char *transfer_type;
-	switch (d->attributes & 3) {
-	case USB_TRANSFER_CONTROL:
-		transfer_type = "control";
-		break;
-	case USB_TRANSFER_ISOCHRONOUS:
-		transfer_type = "isochronous";
-		break;
-	case USB_TRANSFER_BULK:
-		transfer_type = "bulk";
-		break;
-	case USB_TRANSFER_INTERRUPT:
-		transfer_type = "interrupt";
-		break;
-	}
-
-	printf("Standard endpoint descriptor\n");
-	printf(INDENT "bLength = %d\n", d->length);
-	printf(INDENT "bDescriptorType = 0x%02x\n", d->descriptor_type);
-	printf(INDENT "bmAttributes = %d [%s]\n", d->attributes, transfer_type);
-	printf(INDENT "wMaxPacketSize = %d\n", d->max_packet_size);
-	printf(INDENT "bInterval = %d\n", d->poll_interval);
-}
-
-/**
- * Print standard HID descriptor to standard output.
- *
- * @param d Standard HID descriptor to print.
- */
-void dump_standard_hid_descriptor_header(
-    const usb_standard_hid_descriptor_t *d)
-{
-	printf("Standard HID descriptor\n");
-	printf(INDENT "bLength = %d\n", d->length);
-	printf(INDENT "bDescriptorType = 0x%02x\n", d->descriptor_type);
-	printf(INDENT "bcdHID = %d\n", d->spec_release);
-	printf(INDENT "bCountryCode = %d\n", d->country_code);
-	printf(INDENT "bNumDescriptors = %d\n", d->class_desc_count);
-	printf(INDENT "bDescriptorType = %d\n", d->report_desc_info.type);
-	printf(INDENT "wDescriptorLength = %d\n", d->report_desc_info.length);
-}
-
-/**
- * Print HID class-specific descriptor header (type and length) to standard 
- * output.
- * 
- * @param d HID class-specific descriptor header to print.
- */
-void dump_standard_hid_class_descriptor_info(
-    const usb_standard_hid_class_descriptor_info_t *d)
-{
-	printf(INDENT "bDescriptorType = %d\n", d->type);
-	printf(INDENT "wDescriptorLength = %d\n", d->length);
-}
-
-/**
- * Print HID class-specific descriptor (without the header) to standard output.
- *
- * @param index Index of the descriptor.
- * @param type Type of the HID class-specific descriptor (Report or Physical).
- * @param d HID class descriptor to print.
- * @param size Size of the descriptor in bytes.
- */
-void dump_hid_class_descriptor(int index, uint8_t type, 
-    const uint8_t *d, size_t size )
-{
-	printf("Class-specific descriptor #%d (type: %u)\n", index, type);
-	assert(d != NULL);
-	dump_buffer("", d, size);
-}
-
-/**
- * @}
- */
-
Index: uspace/drv/usbhid/descdump.h
===================================================================
--- uspace/drv/usbhid/descdump.h	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ 	(revision )
@@ -1,64 +1,0 @@
-/*
- * Copyright (c) 2010 Lubos Slovak
- * 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 drvusbhid
- * @{
- */
-/** @file
- * Descriptor dumping.
- */
-
-#ifndef USBHID_DESCDUMP_H_
-#define USBHID_DESCDUMP_H_
-
-#include <usb/descriptor.h>
-#include <usb/classes/hid.h>
-
-void dump_standard_configuration_descriptor(
-    int index, const usb_standard_configuration_descriptor_t *d);
-
-void dump_standard_interface_descriptor(
-    const usb_standard_interface_descriptor_t *d);
-
-void dump_standard_endpoint_descriptor(
-    const usb_standard_endpoint_descriptor_t *d);
-
-void dump_standard_hid_descriptor_header(
-    const usb_standard_hid_descriptor_t *d);
-
-void dump_standard_hid_class_descriptor_info(
-    const usb_standard_hid_class_descriptor_info_t *d);
-
-void dump_hid_class_descriptor(int index, uint8_t type, 
-    const uint8_t *d, size_t size);
-
-#endif /* USBHID_DESCDUMP_H_ */
-
-/**
- * @}
- */
Index: uspace/drv/usbhid/hiddev.c
===================================================================
--- uspace/drv/usbhid/hiddev.c	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ 	(revision )
@@ -1,463 +1,0 @@
-/*
- * Copyright (c) 2011 Lubos Slovak
- * 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 drvusbhid
- * @{
- */
-/**
- * @file
- * Generic USB HID device structure and API.
- */
-
-#include <assert.h>
-#include <errno.h>
-#include <str_error.h>
-
-#include <ddf/driver.h>
-
-#include <usb/dp.h>
-#include <usb/debug.h>
-#include <usb/request.h>
-#include <usb/descriptor.h>
-#include <usb/classes/hid.h>
-#include <usb/pipes.h>
-
-#include "hiddev.h"
-
-/*----------------------------------------------------------------------------*/
-/* Non-API functions                                                          */
-/*----------------------------------------------------------------------------*/
-/**
- * Retreives HID Report descriptor from the device.
- *
- * This function first parses the HID descriptor from the Interface descriptor
- * to get the size of the Report descriptor and then requests the Report 
- * descriptor from the device.
- *
- * @param hid_dev HID device structure.
- * @param config_desc Full configuration descriptor (including all nested
- *                    descriptors).
- * @param config_desc_size Size of the full configuration descriptor (in bytes).
- * @param iface_desc Pointer to the interface descriptor inside the full
- *                   configuration descriptor (@a config_desc) for the interface
- *                   assigned with this device (@a hid_dev).
- *
- * @retval EOK if successful.
- * @retval ENOENT if no HID descriptor could be found.
- * @retval EINVAL if the HID descriptor  or HID report descriptor have different
- *                size than expected.
- * @retval ENOMEM if some allocation failed.
- * @return Other value inherited from function usb_request_get_descriptor().
- *
- * @sa usb_request_get_descriptor()
- */
-static int usbhid_dev_get_report_descriptor(usbhid_dev_t *hid_dev, 
-    uint8_t *config_desc, size_t config_desc_size, uint8_t *iface_desc)
-{
-	assert(hid_dev != NULL);
-	assert(config_desc != NULL);
-	assert(config_desc_size != 0);
-	assert(iface_desc != NULL);
-	
-	usb_dp_parser_t parser =  {
-		.nesting = usb_dp_standard_descriptor_nesting
-	};
-	
-	usb_dp_parser_data_t parser_data = {
-		.data = config_desc,
-		.size = config_desc_size,
-		.arg = NULL
-	};
-	
-	/*
-	 * First nested descriptor of interface descriptor.
-	 */
-	uint8_t *d = 
-	    usb_dp_get_nested_descriptor(&parser, &parser_data, iface_desc);
-	
-	/*
-	 * Search through siblings until the HID descriptor is found.
-	 */
-	while (d != NULL && *(d + 1) != USB_DESCTYPE_HID) {
-		d = usb_dp_get_sibling_descriptor(&parser, &parser_data, 
-		    iface_desc, d);
-	}
-	
-	if (d == NULL) {
-		usb_log_fatal("No HID descriptor found!\n");
-		return ENOENT;
-	}
-	
-	if (*d != sizeof(usb_standard_hid_descriptor_t)) {
-		usb_log_fatal("HID descriptor hass wrong size (%u, expected %u"
-		    ")\n", *d, sizeof(usb_standard_hid_descriptor_t));
-		return EINVAL;
-	}
-	
-	usb_standard_hid_descriptor_t *hid_desc = 
-	    (usb_standard_hid_descriptor_t *)d;
-	
-	uint16_t length =  hid_desc->report_desc_info.length;
-	size_t actual_size = 0;
-
-	/*
-	 * Allocate space for the report descriptor.
-	 */
-	hid_dev->report_desc = (uint8_t *)malloc(length);
-	if (hid_dev->report_desc == NULL) {
-		usb_log_fatal("Failed to allocate space for Report descriptor."
-		    "\n");
-		return ENOMEM;
-	}
-	
-	usb_log_debug("Getting Report descriptor, expected size: %u\n", length);
-	
-	/*
-	 * Get the descriptor from the device.
-	 */
-	int rc = usb_request_get_descriptor(&hid_dev->ctrl_pipe,
-	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE,
-	    USB_DESCTYPE_HID_REPORT, 0,
-	    hid_dev->iface, hid_dev->report_desc, length, &actual_size);
-
-	if (rc != EOK) {
-		return rc;
-	}
-
-	if (actual_size != length) {
-		free(hid_dev->report_desc);
-		hid_dev->report_desc = NULL;
-		usb_log_fatal("Report descriptor has wrong size (%u, expected "
-		    "%u)\n", actual_size, length);
-		return EINVAL;
-	}
-	
-	hid_dev->report_desc_size = length;
-	
-	usb_log_debug("Done.\n");
-	
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-/**
- * Retreives descriptors from the device, initializes pipes and stores 
- * important information from descriptors.
- *
- * Initializes the polling pipe described by the given endpoint description
- * (@a poll_ep_desc).
- * 
- * Information retreived from descriptors and stored in the HID device structure:
- *    - Assigned interface number (the interface controlled by this instance of
- *                                 the driver)
- *    - Polling interval (from the interface descriptor)
- *    - Report descriptor
- *
- * @param hid_dev HID device structure to be initialized.
- * @param poll_ep_desc Description of the polling (Interrupt In) endpoint
- *                     that has to be present in the device in order to
- *                     successfuly initialize the structure.
- *
- * @sa usb_pipe_initialize_from_configuration(), 
- *     usbhid_dev_get_report_descriptor()
- */
-static int usbhid_dev_process_descriptors(usbhid_dev_t *hid_dev, 
-    usb_endpoint_description_t *poll_ep_desc) 
-{
-	assert(hid_dev != NULL);
-	
-	usb_log_info("Processing descriptors...\n");
-	
-	int rc;
-
-	uint8_t *descriptors = NULL;
-	size_t descriptors_size;
-	rc = usb_request_get_full_configuration_descriptor_alloc(
-	    &hid_dev->ctrl_pipe, 0, (void **) &descriptors, &descriptors_size);
-	if (rc != EOK) {
-		usb_log_error("Failed to retrieve config descriptor: %s.\n",
-		    str_error(rc));
-		return rc;
-	}
-	
-	/*
-	 * Initialize the interrupt in endpoint.
-	 */
-	usb_endpoint_mapping_t endpoint_mapping[1] = {
-		{
-			.pipe = &hid_dev->poll_pipe,
-			.description = poll_ep_desc,
-			.interface_no =
-			    usb_device_get_assigned_interface(hid_dev->device)
-		}
-	};
-	
-	rc = usb_pipe_initialize_from_configuration(
-	    endpoint_mapping, 1, descriptors, descriptors_size,
-	    &hid_dev->wire);
-	
-	if (rc != EOK) {
-		usb_log_error("Failed to initialize poll pipe: %s.\n",
-		    str_error(rc));
-		free(descriptors);
-		return rc;
-	}
-	
-	if (!endpoint_mapping[0].present) {
-		usb_log_warning("Not accepting device.\n");
-		free(descriptors);
-		return EREFUSED;  // probably not very good return value
-	}
-	
-	usb_log_debug("Accepted device. Saving interface, and getting Report"
-	    " descriptor.\n");
-	
-	/*
-	 * Save assigned interface number.
-	 */
-	if (endpoint_mapping[0].interface_no < 0) {
-		usb_log_error("Bad interface number.\n");
-		free(descriptors);
-		return EINVAL;
-	}
-	
-	hid_dev->iface = endpoint_mapping[0].interface_no;
-	
-	assert(endpoint_mapping[0].interface != NULL);
-	
-	/*
-	 * Save polling interval
-	 */
-	hid_dev->poll_interval = endpoint_mapping[0].descriptor->poll_interval;
-	assert(hid_dev->poll_interval > 0);
-	
-	rc = usbhid_dev_get_report_descriptor(hid_dev,
-	    descriptors, descriptors_size,
-	    (uint8_t *)endpoint_mapping[0].interface);
-	
-	free(descriptors);
-	
-	if (rc != EOK) {
-		usb_log_warning("Problem with getting Report descriptor: %s.\n",
-		    str_error(rc));
-		return rc;
-	}
-	
-	rc = usb_hid_parse_report_descriptor(hid_dev->parser, 
-	    hid_dev->report_desc, hid_dev->report_desc_size);
-	if (rc != EOK) {
-		usb_log_warning("Problem parsing Report descriptor: %s.\n",
-		    str_error(rc));
-		return rc;
-	}
-	
-	usb_hid_descriptor_print(hid_dev->parser);
-	
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-/* API functions                                                              */
-/*----------------------------------------------------------------------------*/
-/**
- * Creates new uninitialized HID device structure.
- *
- * @return Pointer to the new HID device structure, or NULL if an error occured.
- */
-usbhid_dev_t *usbhid_dev_new(void)
-{
-	usbhid_dev_t *dev = 
-	    (usbhid_dev_t *)malloc(sizeof(usbhid_dev_t));
-
-	if (dev == NULL) {
-		usb_log_fatal("No memory!\n");
-		return NULL;
-	}
-	
-	memset(dev, 0, sizeof(usbhid_dev_t));
-	
-	dev->parser = (usb_hid_report_parser_t *)(malloc(sizeof(
-	    usb_hid_report_parser_t)));
-	if (dev->parser == NULL) {
-		usb_log_fatal("No memory!\n");
-		free(dev);
-		return NULL;
-	}
-	
-	dev->initialized = 0;
-	
-	return dev;
-}
-
-/*----------------------------------------------------------------------------*/
-/**
- * Properly destroys the HID device structure.
- *
- * @note Currently does not clean-up the used pipes, as there are no functions
- *       offering such functionality.
- * 
- * @param hid_dev Pointer to the structure to be destroyed.
- */
-void usbhid_dev_free(usbhid_dev_t **hid_dev)
-{
-	if (hid_dev == NULL || *hid_dev == NULL) {
-		return;
-	}
-	
-	// free the report descriptor
-	if ((*hid_dev)->report_desc != NULL) {
-		free((*hid_dev)->report_desc);
-	}
-	// destroy the parser
-	if ((*hid_dev)->parser != NULL) {
-		usb_hid_free_report_parser((*hid_dev)->parser);
-	}
-	
-	// TODO: cleanup pipes
-	
-	free(*hid_dev);
-	*hid_dev = NULL;
-}
-
-/*----------------------------------------------------------------------------*/
-/**
- * Initializes HID device structure.
- *
- * @param hid_dev HID device structure to be initialized.
- * @param dev DDF device representing the HID device.
- * @param poll_ep_desc Description of the polling (Interrupt In) endpoint
- *                     that has to be present in the device in order to
- *                     successfuly initialize the structure.
- *
- * @retval EOK if successful.
- * @retval EINVAL if some argument is missing.
- * @return Other value inherited from one of functions 
- *         usb_device_connection_initialize_from_device(),
- *         usb_pipe_initialize_default_control(),
- *         usb_pipe_start_session(), usb_pipe_end_session(),
- *         usbhid_dev_process_descriptors().
- *
- * @sa usbhid_dev_process_descriptors()
- */
-int usbhid_dev_init(usbhid_dev_t *hid_dev, ddf_dev_t *dev, 
-    usb_endpoint_description_t *poll_ep_desc)
-{
-	usb_log_info("Initializing HID device structure.\n");
-	
-	if (hid_dev == NULL) {
-		usb_log_error("Failed to init HID device structure: no "
-		    "structure given.\n");
-		return EINVAL;
-	}
-	
-	if (dev == NULL) {
-		usb_log_error("Failed to init HID device structure: no device"
-		    " given.\n");
-		return EINVAL;
-	}
-	
-	if (poll_ep_desc == NULL) {
-		usb_log_error("No poll endpoint description given.\n");
-		return EINVAL;
-	}
-	
-	hid_dev->device = dev;
-	
-	int rc;
-
-	/*
-	 * Initialize the backing connection to the host controller.
-	 */
-	rc = usb_device_connection_initialize_from_device(&hid_dev->wire, dev);
-	if (rc != EOK) {
-		usb_log_error("Problem initializing connection to device: %s."
-		    "\n", str_error(rc));
-		return rc;
-	}
-
-	/*
-	 * Initialize device pipes.
-	 */
-	rc = usb_pipe_initialize_default_control(&hid_dev->ctrl_pipe,
-	    &hid_dev->wire);
-	if (rc != EOK) {
-		usb_log_error("Failed to initialize default control pipe: %s."
-		    "\n", str_error(rc));
-		return rc;
-	}
-	rc = usb_pipe_probe_default_control(&hid_dev->ctrl_pipe);
-	if (rc != EOK) {
-		usb_log_error("Probing default control pipe failed: %s.\n",
-		    str_error(rc));
-		return rc;
-	}
-
-	/*
-	 * Initialize the report parser.
-	 */
-	rc = usb_hid_parser_init(hid_dev->parser);
-	if (rc != EOK) {
-		usb_log_error("Failed to initialize report parser.\n");
-		return rc;
-	}
-
-	/*
-	 * Get descriptors, parse descriptors and save endpoints.
-	 */
-	rc = usb_pipe_start_session(&hid_dev->ctrl_pipe);
-	if (rc != EOK) {
-		usb_log_error("Failed to start session on the control pipe: %s"
-		    ".\n", str_error(rc));
-		return rc;
-	}
-	
-	rc = usbhid_dev_process_descriptors(hid_dev, poll_ep_desc);
-	if (rc != EOK) {
-		/* TODO: end session?? */
-		usb_pipe_end_session(&hid_dev->ctrl_pipe);
-		usb_log_error("Failed to process descriptors: %s.\n",
-		    str_error(rc));
-		return rc;
-	}
-	
-	rc = usb_pipe_end_session(&hid_dev->ctrl_pipe);
-	if (rc != EOK) {
-		usb_log_warning("Failed to start session on the control pipe: "
-		    "%s.\n", str_error(rc));
-		return rc;
-	}
-	
-	hid_dev->initialized = 1;
-	usb_log_info("HID device structure initialized.\n");
-	
-	return EOK;
-}
-
-/**
- * @}
- */
Index: uspace/drv/usbhid/hiddev.h
===================================================================
--- uspace/drv/usbhid/hiddev.h	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ 	(revision )
@@ -1,107 +1,0 @@
-/*
- * Copyright (c) 2011 Lubos Slovak
- * 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 drvusbhid
- * @{
- */
-/** @file
- * Generic USB HID device structure and API.
- *
- * @todo Add function for parsing report - this is generic HID function, not
- *       keyboard-specific, as the report parser is also generic.
- * @todo Add function for polling as that is also a generic HID process.
- * @todo Add interrupt in pipe to the structure.
- */
-
-#ifndef USBHID_HIDDEV_H_
-#define USBHID_HIDDEV_H_
-
-#include <stdint.h>
-
-#include <ddf/driver.h>
-
-#include <usb/classes/hid.h>
-#include <usb/pipes.h>
-#include <usb/classes/hidparser.h>
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * USB/HID device type.
- *
- * Holds a reference to DDF device structure, and HID-specific data, such 
- * as information about used pipes (one Control pipe and one Interrupt In pipe),
- * polling interval, assigned interface number, Report descriptor and a
- * reference to the Report parser used to parse incoming reports and composing
- * outgoing reports.
- */
-typedef struct {
-	/** DDF device representing the controlled HID device. */
-	ddf_dev_t *device;
-
-	/** Physical connection to the device. */
-	usb_device_connection_t wire;
-	/** USB pipe corresponding to the default Control endpoint. */
-	usb_pipe_t ctrl_pipe;
-	/** USB pipe corresponding to the Interrupt In (polling) pipe. */
-	usb_pipe_t poll_pipe;
-	
-	/** Polling interval retreived from the Interface descriptor. */
-	short poll_interval;
-	
-	/** Interface number assigned to this device. */
-	uint16_t iface;
-	
-	/** Report descriptor. */
-	uint8_t *report_desc;
-
-	size_t report_desc_size;
-
-	/** HID Report parser. */
-	usb_hid_report_parser_t *parser;
-	
-	/** State of the structure (for checking before use). */
-	int initialized;
-} usbhid_dev_t;
-
-/*----------------------------------------------------------------------------*/
-
-usbhid_dev_t *usbhid_dev_new(void);
-
-void usbhid_dev_free(usbhid_dev_t **hid_dev);
-
-int usbhid_dev_init(usbhid_dev_t *hid_dev, ddf_dev_t *dev,
-    usb_endpoint_description_t *poll_ep_desc);
-
-/*----------------------------------------------------------------------------*/
-
-#endif /* USBHID_HIDDEV_H_ */
-
-/**
- * @}
- */
Index: uspace/drv/usbhid/hidreq.c
===================================================================
--- uspace/drv/usbhid/hidreq.c	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ 	(revision )
@@ -1,446 +1,0 @@
-/*
- * Copyright (c) 2011 Lubos Slovak
- * 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 drvusbhid
- * @{
- */
-/** @file
- * HID class-specific requests.
- */
-
-#include <stdint.h>
-#include <errno.h>
-#include <str_error.h>
-
-#include <usb/classes/hid.h>
-#include <usb/debug.h>
-#include <usb/request.h>
-
-#include "hidreq.h"
-#include "hiddev.h"
-
-/*----------------------------------------------------------------------------*/
-/**
- * Send Set Report request to the HID device.
- *
- * @param hid_dev HID device to send the request to.
- * @param type Type of the report.
- * @param buffer Report data.
- * @param buf_size Report data size (in bytes).
- *
- * @retval EOK if successful.
- * @retval EINVAL if no HID device is given.
- * @return Other value inherited from one of functions 
- *         usb_pipe_start_session(), usb_pipe_end_session(),
- *         usb_control_request_set().
- */
-int usbhid_req_set_report(usbhid_dev_t *hid_dev,
-    usb_hid_report_type_t type, uint8_t *buffer, size_t buf_size)
-{
-	if (hid_dev == NULL) {
-		usb_log_error("usbhid_req_set_report(): no HID device structure"
-		    " given.\n");
-		return EINVAL;
-	}
-	
-	/*
-	 * No need for checking other parameters, as they are checked in
-	 * the called function (usb_control_request_set()).
-	 */
-	
-	int rc, sess_rc;
-	
-	sess_rc = usb_pipe_start_session(&hid_dev->ctrl_pipe);
-	if (sess_rc != EOK) {
-		usb_log_warning("Failed to start a session: %s.\n",
-		    str_error(sess_rc));
-		return sess_rc;
-	}
-	
-	uint16_t value = 0;
-	value |= (type << 8);
-
-	usb_log_debug("Sending Set_Report request to the device.\n");
-	
-	rc = usb_control_request_set(&hid_dev->ctrl_pipe, 
-	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
-	    USB_HIDREQ_SET_REPORT, value, hid_dev->iface, buffer, buf_size);
-
-	sess_rc = usb_pipe_end_session(&hid_dev->ctrl_pipe);
-
-	if (rc != EOK) {
-		usb_log_warning("Error sending output report to the keyboard: "
-		    "%s.\n", str_error(rc));
-		return rc;
-	}
-
-	if (sess_rc != EOK) {
-		usb_log_warning("Error closing session: %s.\n",
-		    str_error(sess_rc));
-		return sess_rc;
-	}
-	
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-/**
- * Send Set Protocol request to the HID device.
- *
- * @param hid_dev HID device to send the request to.
- * @param protocol Protocol to set.
- *
- * @retval EOK if successful.
- * @retval EINVAL if no HID device is given.
- * @return Other value inherited from one of functions 
- *         usb_pipe_start_session(), usb_pipe_end_session(),
- *         usb_control_request_set().
- */
-int usbhid_req_set_protocol(usbhid_dev_t *hid_dev, usb_hid_protocol_t protocol)
-{
-	if (hid_dev == NULL) {
-		usb_log_error("usbhid_req_set_protocol(): no HID device "
-		    "structure given.\n");
-		return EINVAL;
-	}
-	
-	/*
-	 * No need for checking other parameters, as they are checked in
-	 * the called function (usb_control_request_set()).
-	 */
-	
-	int rc, sess_rc;
-	
-	sess_rc = usb_pipe_start_session(&hid_dev->ctrl_pipe);
-	if (sess_rc != EOK) {
-		usb_log_warning("Failed to start a session: %s.\n",
-		    str_error(sess_rc));
-		return sess_rc;
-	}
-
-	usb_log_debug("Sending Set_Protocol request to the device ("
-	    "protocol: %d, iface: %d).\n", protocol, hid_dev->iface);
-	
-	rc = usb_control_request_set(&hid_dev->ctrl_pipe, 
-	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
-	    USB_HIDREQ_SET_PROTOCOL, protocol, hid_dev->iface, NULL, 0);
-
-	sess_rc = usb_pipe_end_session(&hid_dev->ctrl_pipe);
-
-	if (rc != EOK) {
-		usb_log_warning("Error sending output report to the keyboard: "
-		    "%s.\n", str_error(rc));
-		return rc;
-	}
-
-	if (sess_rc != EOK) {
-		usb_log_warning("Error closing session: %s.\n",
-		    str_error(sess_rc));
-		return sess_rc;
-	}
-	
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-/**
- * Send Set Idle request to the HID device.
- *
- * @param hid_dev HID device to send the request to.
- * @param duration Duration value (is multiplicated by 4 by the device to
- *                 get real duration in miliseconds).
- *
- * @retval EOK if successful.
- * @retval EINVAL if no HID device is given.
- * @return Other value inherited from one of functions 
- *         usb_pipe_start_session(), usb_pipe_end_session(),
- *         usb_control_request_set().
- */
-int usbhid_req_set_idle(usbhid_dev_t *hid_dev, uint8_t duration)
-{
-	if (hid_dev == NULL) {
-		usb_log_error("usbhid_req_set_idle(): no HID device "
-		    "structure given.\n");
-		return EINVAL;
-	}
-	
-	/*
-	 * No need for checking other parameters, as they are checked in
-	 * the called function (usb_control_request_set()).
-	 */
-	
-	int rc, sess_rc;
-	
-	sess_rc = usb_pipe_start_session(&hid_dev->ctrl_pipe);
-	if (sess_rc != EOK) {
-		usb_log_warning("Failed to start a session: %s.\n",
-		    str_error(sess_rc));
-		return sess_rc;
-	}
-
-	usb_log_debug("Sending Set_Idle request to the device ("
-	    "duration: %u, iface: %d).\n", duration, hid_dev->iface);
-	
-	uint16_t value = duration << 8;
-	
-	rc = usb_control_request_set(&hid_dev->ctrl_pipe, 
-	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
-	    USB_HIDREQ_SET_IDLE, value, hid_dev->iface, NULL, 0);
-
-	sess_rc = usb_pipe_end_session(&hid_dev->ctrl_pipe);
-
-	if (rc != EOK) {
-		usb_log_warning("Error sending output report to the keyboard: "
-		    "%s.\n", str_error(rc));
-		return rc;
-	}
-
-	if (sess_rc != EOK) {
-		usb_log_warning("Error closing session: %s.\n",
-		    str_error(sess_rc));
-		return sess_rc;
-	}
-	
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-/**
- * Send Get Report request to the HID device.
- *
- * @param[in] hid_dev HID device to send the request to.
- * @param[in] type Type of the report.
- * @param[in][out] buffer Buffer for the report data.
- * @param[in] buf_size Size of the buffer (in bytes).
- * @param[out] actual_size Actual size of report received from the device 
- *                         (in bytes).
- *
- * @retval EOK if successful.
- * @retval EINVAL if no HID device is given.
- * @return Other value inherited from one of functions 
- *         usb_pipe_start_session(), usb_pipe_end_session(),
- *         usb_control_request_set().
- */
-int usbhid_req_get_report(usbhid_dev_t *hid_dev, usb_hid_report_type_t type, 
-    uint8_t *buffer, size_t buf_size, size_t *actual_size)
-{
-	if (hid_dev == NULL) {
-		usb_log_error("usbhid_req_set_report(): no HID device structure"
-		    " given.\n");
-		return EINVAL;
-	}
-	
-	/*
-	 * No need for checking other parameters, as they are checked in
-	 * the called function (usb_control_request_set()).
-	 */
-	
-	int rc, sess_rc;
-	
-	sess_rc = usb_pipe_start_session(&hid_dev->ctrl_pipe);
-	if (sess_rc != EOK) {
-		usb_log_warning("Failed to start a session: %s.\n",
-		    str_error(sess_rc));
-		return sess_rc;
-	}
-
-	uint16_t value = 0;
-	value |= (type << 8);
-	
-	usb_log_debug("Sending Get_Report request to the device.\n");
-	
-	rc = usb_control_request_get(&hid_dev->ctrl_pipe, 
-	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
-	    USB_HIDREQ_GET_REPORT, value, hid_dev->iface, buffer, buf_size,
-	    actual_size);
-
-	sess_rc = usb_pipe_end_session(&hid_dev->ctrl_pipe);
-
-	if (rc != EOK) {
-		usb_log_warning("Error sending output report to the keyboard: "
-		    "%s.\n", str_error(rc));
-		return rc;
-	}
-
-	if (sess_rc != EOK) {
-		usb_log_warning("Error closing session: %s.\n",
-		    str_error(sess_rc));
-		return sess_rc;
-	}
-	
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-/**
- * Send Get Protocol request to the HID device.
- *
- * @param[in] hid_dev HID device to send the request to.
- * @param[out] protocol Current protocol of the device.
- *
- * @retval EOK if successful.
- * @retval EINVAL if no HID device is given.
- * @return Other value inherited from one of functions 
- *         usb_pipe_start_session(), usb_pipe_end_session(),
- *         usb_control_request_set().
- */
-int usbhid_req_get_protocol(usbhid_dev_t *hid_dev, usb_hid_protocol_t *protocol)
-{
-	if (hid_dev == NULL) {
-		usb_log_error("usbhid_req_set_protocol(): no HID device "
-		    "structure given.\n");
-		return EINVAL;
-	}
-	
-	/*
-	 * No need for checking other parameters, as they are checked in
-	 * the called function (usb_control_request_set()).
-	 */
-	
-	int rc, sess_rc;
-	
-	sess_rc = usb_pipe_start_session(&hid_dev->ctrl_pipe);
-	if (sess_rc != EOK) {
-		usb_log_warning("Failed to start a session: %s.\n",
-		    str_error(sess_rc));
-		return sess_rc;
-	}
-
-	usb_log_debug("Sending Get_Protocol request to the device ("
-	    "iface: %d).\n", hid_dev->iface);
-	
-	uint8_t buffer[1];
-	size_t actual_size = 0;
-	
-	rc = usb_control_request_get(&hid_dev->ctrl_pipe, 
-	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
-	    USB_HIDREQ_GET_PROTOCOL, 0, hid_dev->iface, buffer, 1, &actual_size);
-
-	sess_rc = usb_pipe_end_session(&hid_dev->ctrl_pipe);
-
-	if (rc != EOK) {
-		usb_log_warning("Error sending output report to the keyboard: "
-		    "%s.\n", str_error(rc));
-		return rc;
-	}
-
-	if (sess_rc != EOK) {
-		usb_log_warning("Error closing session: %s.\n",
-		    str_error(sess_rc));
-		return sess_rc;
-	}
-	
-	if (actual_size != 1) {
-		usb_log_warning("Wrong data size: %zu, expected: 1.\n",
-			actual_size);
-		return ELIMIT;
-	}
-	
-	*protocol = buffer[0];
-	
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-/**
- * Send Get Idle request to the HID device.
- *
- * @param[in] hid_dev HID device to send the request to.
- * @param[out] duration Duration value (multiplicate by 4 to get real duration
- *                      in miliseconds).
- *
- * @retval EOK if successful.
- * @retval EINVAL if no HID device is given.
- * @return Other value inherited from one of functions 
- *         usb_pipe_start_session(), usb_pipe_end_session(),
- *         usb_control_request_set().
- */
-int usbhid_req_get_idle(usbhid_dev_t *hid_dev, uint8_t *duration)
-{
-	if (hid_dev == NULL) {
-		usb_log_error("usbhid_req_set_idle(): no HID device "
-		    "structure given.\n");
-		return EINVAL;
-	}
-	
-	/*
-	 * No need for checking other parameters, as they are checked in
-	 * the called function (usb_control_request_set()).
-	 */
-	
-	int rc, sess_rc;
-	
-	sess_rc = usb_pipe_start_session(&hid_dev->ctrl_pipe);
-	if (sess_rc != EOK) {
-		usb_log_warning("Failed to start a session: %s.\n",
-		    str_error(sess_rc));
-		return sess_rc;
-	}
-
-	usb_log_debug("Sending Get_Idle request to the device ("
-	    "iface: %d).\n", hid_dev->iface);
-	
-	uint16_t value = 0;
-	uint8_t buffer[1];
-	size_t actual_size = 0;
-	
-	rc = usb_control_request_get(&hid_dev->ctrl_pipe, 
-	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
-	    USB_HIDREQ_GET_IDLE, value, hid_dev->iface, buffer, 1, 
-	    &actual_size);
-
-	sess_rc = usb_pipe_end_session(&hid_dev->ctrl_pipe);
-
-	if (rc != EOK) {
-		usb_log_warning("Error sending output report to the keyboard: "
-		    "%s.\n", str_error(rc));
-		return rc;
-	}
-
-	if (sess_rc != EOK) {
-		usb_log_warning("Error closing session: %s.\n",
-		    str_error(sess_rc));
-		return sess_rc;
-	}
-	
-	if (actual_size != 1) {
-		usb_log_warning("Wrong data size: %zu, expected: 1.\n",
-			actual_size);
-		return ELIMIT;
-	}
-	
-	*duration = buffer[0];
-	
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * @}
- */
Index: uspace/drv/usbhid/hidreq.h
===================================================================
--- uspace/drv/usbhid/hidreq.h	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ 	(revision )
@@ -1,67 +1,0 @@
-/*
- * Copyright (c) 2011 Lubos Slovak
- * 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 drvusbhid
- * @{
- */
-/** @file
- * HID class-specific requests.
- */
-
-#ifndef USBHID_HIDREQ_H_
-#define USBHID_HIDREQ_H_
-
-#include <stdint.h>
-
-#include <usb/classes/hid.h>
-
-#include "hiddev.h"
-
-/*----------------------------------------------------------------------------*/
-
-int usbhid_req_set_report(usbhid_dev_t *hid_dev,
-    usb_hid_report_type_t type, uint8_t *buffer, size_t buf_size);
-
-int usbhid_req_set_protocol(usbhid_dev_t *hid_dev, usb_hid_protocol_t protocol);
-
-int usbhid_req_set_idle(usbhid_dev_t *hid_dev, uint8_t duration);
-
-int usbhid_req_get_report(usbhid_dev_t *hid_dev, usb_hid_report_type_t type, 
-    uint8_t *buffer, size_t buf_size, size_t *actual_size);
-
-int usbhid_req_get_protocol(usbhid_dev_t *hid_dev, usb_hid_protocol_t *protocol);
-
-int usbhid_req_get_idle(usbhid_dev_t *hid_dev, uint8_t *duration);
-
-/*----------------------------------------------------------------------------*/
-
-#endif /* USBHID_HIDREQ_H_ */
-
-/**
- * @}
- */
Index: uspace/drv/usbhid/kbd.h
===================================================================
--- uspace/drv/usbhid/kbd.h	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ 	(revision )
@@ -1,5 +1,0 @@
-/*
- * Dummy file because of shared layout sources.
- *
- * Do not delete.
- */
Index: uspace/drv/usbhid/kbddev.c
===================================================================
--- uspace/drv/usbhid/kbddev.c	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ 	(revision )
@@ -1,1023 +1,0 @@
-/*
- * Copyright (c) 2011 Lubos Slovak
- * 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 drvusbhid
- * @{
- */
-/**
- * @file
- * USB HID keyboard device structure and API.
- */
-
-#include <errno.h>
-#include <str_error.h>
-#include <stdio.h>
-
-#include <io/keycode.h>
-#include <ipc/kbd.h>
-#include <async.h>
-#include <fibril.h>
-#include <fibril_synch.h>
-
-#include <usb/usb.h>
-#include <usb/classes/hid.h>
-#include <usb/pipes.h>
-#include <usb/debug.h>
-#include <usb/classes/hidparser.h>
-#include <usb/classes/classes.h>
-#include <usb/classes/hidut.h>
-
-#include "kbddev.h"
-#include "hiddev.h"
-#include "hidreq.h"
-#include "layout.h"
-#include "conv.h"
-#include "kbdrepeat.h"
-
-/*----------------------------------------------------------------------------*/
-/** Default modifiers when the keyboard is initialized. */
-static const unsigned DEFAULT_ACTIVE_MODS = KM_NUM_LOCK;
-
-/** Boot protocol report size (key part). */
-static const size_t BOOTP_REPORT_SIZE = 6;
-
-/** Boot protocol total report size. */
-static const size_t BOOTP_BUFFER_SIZE = 8;
-
-/** Boot protocol output report size. */
-static const size_t BOOTP_BUFFER_OUT_SIZE = 1;
-
-/** Boot protocol error key code. */
-static const uint8_t BOOTP_ERROR_ROLLOVER = 1;
-
-/** Default idle rate for keyboards. */
-static const uint8_t IDLE_RATE = 0;
-
-/** Delay before a pressed key starts auto-repeating. */
-static const unsigned int DEFAULT_DELAY_BEFORE_FIRST_REPEAT = 500 * 1000;
-
-/** Delay between two repeats of a pressed key when auto-repeating. */
-static const unsigned int DEFAULT_REPEAT_DELAY = 50 * 1000;
-
-/** Keyboard polling endpoint description for boot protocol class. */
-static usb_endpoint_description_t poll_endpoint_description = {
-	.transfer_type = USB_TRANSFER_INTERRUPT,
-	.direction = USB_DIRECTION_IN,
-	.interface_class = USB_CLASS_HID,
-	.interface_subclass = USB_HID_SUBCLASS_BOOT,
-	.interface_protocol = USB_HID_PROTOCOL_KEYBOARD,
-	.flags = 0
-};
-
-typedef enum usbhid_kbd_flags {
-	USBHID_KBD_STATUS_UNINITIALIZED = 0,
-	USBHID_KBD_STATUS_INITIALIZED = 1,
-	USBHID_KBD_STATUS_TO_DESTROY = -1
-} usbhid_kbd_flags;
-
-/*----------------------------------------------------------------------------*/
-/* Keyboard layouts                                                           */
-/*----------------------------------------------------------------------------*/
-
-#define NUM_LAYOUTS 3
-
-/** Keyboard layout map. */
-static layout_op_t *layout[NUM_LAYOUTS] = {
-	&us_qwerty_op,
-	&us_dvorak_op,
-	&cz_op
-};
-
-static int active_layout = 0;
-
-/*----------------------------------------------------------------------------*/
-/* Modifier constants                                                         */
-/*----------------------------------------------------------------------------*/
-/** Mapping of USB modifier key codes to generic modifier key codes. */
-static const keycode_t usbhid_modifiers_keycodes[USB_HID_MOD_COUNT] = {
-	KC_LCTRL,         /* USB_HID_MOD_LCTRL */
-	KC_LSHIFT,        /* USB_HID_MOD_LSHIFT */
-	KC_LALT,          /* USB_HID_MOD_LALT */
-	0,                /* USB_HID_MOD_LGUI */
-	KC_RCTRL,         /* USB_HID_MOD_RCTRL */
-	KC_RSHIFT,        /* USB_HID_MOD_RSHIFT */
-	KC_RALT,          /* USB_HID_MOD_RALT */
-	0,                /* USB_HID_MOD_RGUI */
-};
-
-typedef enum usbhid_lock_code {
-	USBHID_LOCK_NUM = 0x53,
-	USBHID_LOCK_CAPS = 0x39,
-	USBHID_LOCK_SCROLL = 0x47,
-	USBHID_LOCK_COUNT = 3
-} usbhid_lock_code;
-
-static const usbhid_lock_code usbhid_lock_codes[USBHID_LOCK_COUNT] = {
-	USBHID_LOCK_NUM,
-	USBHID_LOCK_CAPS,
-	USBHID_LOCK_SCROLL
-};
-
-/*----------------------------------------------------------------------------*/
-/* IPC method handler                                                         */
-/*----------------------------------------------------------------------------*/
-
-static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
-static ddf_dev_ops_t keyboard_ops = {
-	.default_handler = default_connection_handler
-};
-
-/** 
- * Default handler for IPC methods not handled by DDF.
- *
- * Currently recognizes only one method (IPC_M_CONNECT_TO_ME), in which case it
- * assumes the caller is the console and thus it stores IPC phone to it for 
- * later use by the driver to notify about key events.
- *
- * @param fun Device function handling the call.
- * @param icallid Call id.
- * @param icall Call data.
- */
-void default_connection_handler(ddf_fun_t *fun,
-    ipc_callid_t icallid, ipc_call_t *icall)
-{
-	sysarg_t method = IPC_GET_IMETHOD(*icall);
-	
-	usbhid_kbd_t *kbd_dev = (usbhid_kbd_t *)fun->driver_data;
-	assert(kbd_dev != NULL);
-
-	if (method == IPC_M_CONNECT_TO_ME) {
-		int callback = IPC_GET_ARG5(*icall);
-
-		if (kbd_dev->console_phone != -1) {
-			async_answer_0(icallid, ELIMIT);
-			return;
-		}
-
-		kbd_dev->console_phone = callback;
-		async_answer_0(icallid, EOK);
-		return;
-	}
-	
-	async_answer_0(icallid, EINVAL);
-}
-
-/*----------------------------------------------------------------------------*/
-/* Key processing functions                                                   */
-/*----------------------------------------------------------------------------*/
-/**
- * Handles turning of LED lights on and off.
- *
- * In case of USB keyboards, the LEDs are handled in the driver, not in the 
- * device. When there should be a change (lock key was pressed), the driver
- * uses a Set_Report request sent to the device to set the state of the LEDs.
- *
- * This functions sets the LED lights according to current settings of modifiers
- * kept in the keyboard device structure.
- *
- * @param kbd_dev Keyboard device structure.
- */
-static void usbhid_kbd_set_led(usbhid_kbd_t *kbd_dev) 
-{
-	uint8_t buffer[BOOTP_BUFFER_OUT_SIZE];
-	int rc= 0;
-	
-	memset(buffer, 0, BOOTP_BUFFER_OUT_SIZE);
-	uint8_t leds = 0;
-
-	if (kbd_dev->mods & KM_NUM_LOCK) {
-		leds |= USB_HID_LED_NUM_LOCK;
-	}
-	
-	if (kbd_dev->mods & KM_CAPS_LOCK) {
-		leds |= USB_HID_LED_CAPS_LOCK;
-	}
-	
-	if (kbd_dev->mods & KM_SCROLL_LOCK) {
-		leds |= USB_HID_LED_SCROLL_LOCK;
-	}
-
-	// TODO: COMPOSE and KANA
-	
-	usb_log_debug("Creating output report.\n");
-	usb_log_debug("Leds: 0x%x\n", leds);
-	if ((rc = usb_hid_boot_keyboard_output_report(
-	    leds, buffer, BOOTP_BUFFER_OUT_SIZE)) != EOK) {
-		usb_log_warning("Error composing output report to the keyboard:"
-		    "%s.\n", str_error(rc));
-		return;
-	}
-	
-	usb_log_debug("Output report buffer: %s\n", 
-	    usb_debug_str_buffer(buffer, BOOTP_BUFFER_OUT_SIZE, 0));
-	
-	assert(kbd_dev->hid_dev != NULL);
-	assert(kbd_dev->hid_dev->initialized == USBHID_KBD_STATUS_INITIALIZED);
-	usbhid_req_set_report(kbd_dev->hid_dev, USB_HID_REPORT_TYPE_OUTPUT, 
-	    buffer, BOOTP_BUFFER_OUT_SIZE);
-}
-
-/*----------------------------------------------------------------------------*/
-/**
- * Processes key events.
- *
- * @note This function was copied from AT keyboard driver and modified to suit
- *       USB keyboard.
- *
- * @note Lock keys are not sent to the console, as they are completely handled
- *       in the driver. It may, however, be required later that the driver
- *       sends also these keys to application (otherwise it cannot use those
- *       keys at all).
- * 
- * @param kbd_dev Keyboard device structure.
- * @param type Type of the event (press / release). Recognized values: 
- *             KEY_PRESS, KEY_RELEASE
- * @param key Key code of the key according to HID Usage Tables.
- */
-void usbhid_kbd_push_ev(usbhid_kbd_t *kbd_dev, int type, unsigned int key)
-{
-	console_event_t ev;
-	unsigned mod_mask;
-
-	/*
-	 * These parts are copy-pasted from the AT keyboard driver.
-	 *
-	 * They definitely require some refactoring, but will keep it for later
-	 * when the console and keyboard system is changed in HelenOS.
-	 */
-	switch (key) {
-	case KC_LCTRL: mod_mask = KM_LCTRL; break;
-	case KC_RCTRL: mod_mask = KM_RCTRL; break;
-	case KC_LSHIFT: mod_mask = KM_LSHIFT; break;
-	case KC_RSHIFT: mod_mask = KM_RSHIFT; break;
-	case KC_LALT: mod_mask = KM_LALT; break;
-	case KC_RALT: mod_mask = KM_RALT; break;
-	default: mod_mask = 0; break;
-	}
-
-	if (mod_mask != 0) {
-		if (type == KEY_PRESS)
-			kbd_dev->mods = kbd_dev->mods | mod_mask;
-		else
-			kbd_dev->mods = kbd_dev->mods & ~mod_mask;
-	}
-
-	switch (key) {
-	case KC_CAPS_LOCK: mod_mask = KM_CAPS_LOCK; break;
-	case KC_NUM_LOCK: mod_mask = KM_NUM_LOCK; break;
-	case KC_SCROLL_LOCK: mod_mask = KM_SCROLL_LOCK; break;
-	default: mod_mask = 0; break;
-	}
-
-	if (mod_mask != 0) {
-		if (type == KEY_PRESS) {
-			/*
-			 * Only change lock state on transition from released
-			 * to pressed. This prevents autorepeat from messing
-			 * up the lock state.
-			 */
-			unsigned int locks_old = kbd_dev->lock_keys;
-			
-			kbd_dev->mods = 
-			    kbd_dev->mods ^ (mod_mask & ~kbd_dev->lock_keys);
-			kbd_dev->lock_keys = kbd_dev->lock_keys | mod_mask;
-
-			/* Update keyboard lock indicator lights. */
-			if (kbd_dev->lock_keys != locks_old) {
-				usbhid_kbd_set_led(kbd_dev);
-			}
-		} else {
-			kbd_dev->lock_keys = kbd_dev->lock_keys & ~mod_mask;
-		}
-	}
-
-	if (key == KC_CAPS_LOCK || key == KC_NUM_LOCK || key == KC_SCROLL_LOCK) {
-		// do not send anything to the console, this is our business
-		return;
-	}
-	
-	if (type == KEY_PRESS && (kbd_dev->mods & KM_LCTRL) && key == KC_F1) {
-		active_layout = 0;
-		layout[active_layout]->reset();
-		return;
-	}
-
-	if (type == KEY_PRESS && (kbd_dev->mods & KM_LCTRL) && key == KC_F2) {
-		active_layout = 1;
-		layout[active_layout]->reset();
-		return;
-	}
-
-	if (type == KEY_PRESS && (kbd_dev->mods & KM_LCTRL) && key == KC_F3) {
-		active_layout = 2;
-		layout[active_layout]->reset();
-		return;
-	}
-	
-	ev.type = type;
-	ev.key = key;
-	ev.mods = kbd_dev->mods;
-
-	ev.c = layout[active_layout]->parse_ev(&ev);
-
-	usb_log_debug2("Sending key %d to the console\n", ev.key);
-	if (kbd_dev->console_phone < 0) {
-		usb_log_warning(
-		    "Connection to console not ready, key discarded.\n");
-		return;
-	}
-	
-	async_msg_4(kbd_dev->console_phone, KBD_EVENT, ev.type, ev.key, 
-	    ev.mods, ev.c);
-}
-
-/*----------------------------------------------------------------------------*/
-/**
- * Checks if modifiers were pressed or released and generates key events.
- *
- * @param kbd_dev Keyboard device structure.
- * @param modifiers Bitmap of modifiers.
- *
- * @sa usbhid_kbd_push_ev()
- */
-//static void usbhid_kbd_check_modifier_changes(usbhid_kbd_t *kbd_dev, 
-//    const uint8_t *key_codes, size_t count)
-//{
-//	/*
-//	 * TODO: why the USB keyboard has NUM_, SCROLL_ and CAPS_LOCK
-//	 *       both as modifiers and as keyUSB_HID_LOCK_COUNTs with their own scancodes???
-//	 *
-//	 * modifiers should be sent as normal keys to usbhid_parse_scancode()!!
-//	 * so maybe it would be better if I received it from report parser in 
-//	 * that way
-//	 */
-	
-//	int i;
-//	for (i = 0; i < count; ++i) {
-//		if ((modifiers & usb_hid_modifiers_consts[i]) &&
-//		    !(kbd_dev->modifiers & usb_hid_modifiers_consts[i])) {
-//			// modifier pressed
-//			if (usbhid_modifiers_keycodes[i] != 0) {
-//				usbhid_kbd_push_ev(kbd_dev, KEY_PRESS, 
-//				    usbhid_modifiers_keycodes[i]);
-//			}
-//		} else if (!(modifiers & usb_hid_modifiers_consts[i]) &&
-//		    (kbd_dev->modifiers & usb_hid_modifiers_consts[i])) {
-//			// modifier released
-//			if (usbhid_modifiers_keycodes[i] != 0) {
-//				usbhid_kbd_push_ev(kbd_dev, KEY_RELEASE, 
-//				    usbhid_modifiers_keycodes[i]);
-//			}
-//		}	// no change
-//	}
-	
-//	kbd_dev->modifiers = modifiers;
-//}
-
-/*----------------------------------------------------------------------------*/
-
-static inline int usbhid_kbd_is_lock(unsigned int key_code) 
-{
-	return (key_code == KC_NUM_LOCK
-	    || key_code == KC_SCROLL_LOCK
-	    || key_code == KC_CAPS_LOCK);
-}
-
-/*----------------------------------------------------------------------------*/
-/**
- * Checks if some keys were pressed or released and generates key events.
- *
- * An event is created only when key is pressed or released. Besides handling
- * the events (usbhid_kbd_push_ev()), the auto-repeat fibril is notified about
- * key presses and releases (see usbhid_kbd_repeat_start() and 
- * usbhid_kbd_repeat_stop()).
- *
- * @param kbd_dev Keyboard device structure.
- * @param key_codes Parsed keyboard report - codes of currently pressed keys 
- *                  according to HID Usage Tables.
- * @param count Number of key codes in report (size of the report).
- *
- * @sa usbhid_kbd_push_ev(), usbhid_kbd_repeat_start(), usbhid_kbd_repeat_stop()
- */
-static void usbhid_kbd_check_key_changes(usbhid_kbd_t *kbd_dev, 
-    const uint8_t *key_codes, size_t count)
-{
-	unsigned int key;
-	unsigned int i, j;
-	
-	/*
-	 * First of all, check if the kbd have reported phantom state.
-	 *
-	 * TODO: this must be changed as we don't know which keys are modifiers
-	 *       and which are regular keys.
-	 */
-	i = 0;
-	// all fields should report Error Rollover
-	while (i < count &&
-	    key_codes[i] == BOOTP_ERROR_ROLLOVER) {
-		++i;
-	}
-	if (i == count) {
-		usb_log_debug("Phantom state occured.\n");
-		// phantom state, do nothing
-		return;
-	}
-	
-	/* TODO: quite dummy right now, think of better implementation */
-	assert(count == kbd_dev->key_count);
-	
-	/*
-	 * 1) Key releases
-	 */
-	for (j = 0; j < count; ++j) {
-		// try to find the old key in the new key list
-		i = 0;
-		while (i < kbd_dev->key_count
-		    && key_codes[i] != kbd_dev->keys[j]) {
-			++i;
-		}
-		
-		if (i == count) {
-			// not found, i.e. the key was released
-			key = usbhid_parse_scancode(kbd_dev->keys[j]);
-			if (!usbhid_kbd_is_lock(key)) {
-				usbhid_kbd_repeat_stop(kbd_dev, key);
-			}
-			usbhid_kbd_push_ev(kbd_dev, KEY_RELEASE, key);
-			usb_log_debug2("Key released: %d\n", key);
-		} else {
-			// found, nothing happens
-		}
-	}
-	
-	/*
-	 * 1) Key presses
-	 */
-	for (i = 0; i < kbd_dev->key_count; ++i) {
-		// try to find the new key in the old key list
-		j = 0;
-		while (j < count && kbd_dev->keys[j] != key_codes[i]) { 
-			++j;
-		}
-		
-		if (j == count) {
-			// not found, i.e. new key pressed
-			key = usbhid_parse_scancode(key_codes[i]);
-			usb_log_debug2("Key pressed: %d (keycode: %d)\n", key,
-			    key_codes[i]);
-			usbhid_kbd_push_ev(kbd_dev, KEY_PRESS, key);
-			if (!usbhid_kbd_is_lock(key)) {
-				usbhid_kbd_repeat_start(kbd_dev, key);
-			}
-		} else {
-			// found, nothing happens
-		}
-	}
-	
-	memcpy(kbd_dev->keys, key_codes, count);
-
-	usb_log_debug("New stored keycodes: %s\n", 
-	    usb_debug_str_buffer(kbd_dev->keys, kbd_dev->key_count, 0));
-}
-
-/*----------------------------------------------------------------------------*/
-/* Callbacks for parser                                                       */
-/*----------------------------------------------------------------------------*/
-/**
- * Callback function for the HID report parser.
- *
- * This function is called by the HID report parser with the parsed report.
- * The parsed report is used to check if any events occured (key was pressed or
- * released, modifier was pressed or released).
- *
- * @param key_codes Parsed keyboard report - codes of currently pressed keys 
- *                  according to HID Usage Tables.
- * @param count Number of key codes in report (size of the report).
- * @param modifiers Bitmap of modifiers (Ctrl, Alt, Shift, GUI).
- * @param arg User-specified argument. Expects pointer to the keyboard device
- *            structure representing the keyboard.
- *
- * @sa usbhid_kbd_check_key_changes(), usbhid_kbd_check_modifier_changes()
- */
-static void usbhid_kbd_process_keycodes(const uint8_t *key_codes, size_t count,
-    uint8_t modifiers, void *arg)
-{
-	if (arg == NULL) {
-		usb_log_warning("Missing argument in callback "
-		    "usbhid_process_keycodes().\n");
-		return;
-	}
-	
-	usbhid_kbd_t *kbd_dev = (usbhid_kbd_t *)arg;
-	assert(kbd_dev != NULL);
-
-	usb_log_debug("Got keys from parser: %s\n", 
-	    usb_debug_str_buffer(key_codes, count, 0));
-	
-	if (count != kbd_dev->key_count) {
-		usb_log_warning("Number of received keycodes (%d) differs from"
-		    " expected number (%d).\n", count, kbd_dev->key_count);
-		return;
-	}
-	
-	///usbhid_kbd_check_modifier_changes(kbd_dev, key_codes, count);
-	usbhid_kbd_check_key_changes(kbd_dev, key_codes, count);
-}
-
-/*----------------------------------------------------------------------------*/
-/* General kbd functions                                                      */
-/*----------------------------------------------------------------------------*/
-/**
- * Processes data received from the device in form of report.
- *
- * This function uses the HID report parser to translate the data received from
- * the device into generic USB HID key codes and into generic modifiers bitmap.
- * The parser then calls the given callback (usbhid_kbd_process_keycodes()).
- *
- * @note Currently, only the boot protocol is supported.
- *
- * @param kbd_dev Keyboard device structure (must be initialized).
- * @param buffer Data from the keyboard (i.e. the report).
- * @param actual_size Size of the data from keyboard (report size) in bytes.
- *
- * @sa usbhid_kbd_process_keycodes(), usb_hid_boot_keyboard_input_report().
- */
-static void usbhid_kbd_process_data(usbhid_kbd_t *kbd_dev,
-                                    uint8_t *buffer, size_t actual_size)
-{
-	assert(kbd_dev->initialized == USBHID_KBD_STATUS_INITIALIZED);
-	assert(kbd_dev->hid_dev->parser != NULL);
-	
-	usb_hid_report_in_callbacks_t *callbacks =
-	    (usb_hid_report_in_callbacks_t *)malloc(
-	        sizeof(usb_hid_report_in_callbacks_t));
-	
-	callbacks->keyboard = usbhid_kbd_process_keycodes;
-
-	usb_log_debug("Calling usb_hid_parse_report() with "
-	    "buffer %s\n", usb_debug_str_buffer(buffer, actual_size, 0));
-	
-//	int rc = usb_hid_boot_keyboard_input_report(buffer, actual_size,
-//	    callbacks, kbd_dev);
-	int rc = usb_hid_parse_report(kbd_dev->hid_dev->parser, buffer,
-	    actual_size, callbacks, kbd_dev);
-	
-	if (rc != EOK) {
-		usb_log_warning("Error in usb_hid_boot_keyboard_input_report():"
-		    "%s\n", str_error(rc));
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-/* HID/KBD structure manipulation                                             */
-/*----------------------------------------------------------------------------*/
-/**
- * Creates a new USB/HID keyboard structure.
- *
- * The structure returned by this function is not initialized. Use 
- * usbhid_kbd_init() to initialize it prior to polling.
- *
- * @return New uninitialized structure for representing a USB/HID keyboard or
- *         NULL if not successful (memory error).
- */
-static usbhid_kbd_t *usbhid_kbd_new(void)
-{
-	usbhid_kbd_t *kbd_dev = 
-	    (usbhid_kbd_t *)malloc(sizeof(usbhid_kbd_t));
-
-	if (kbd_dev == NULL) {
-		usb_log_fatal("No memory!\n");
-		return NULL;
-	}
-	
-	memset(kbd_dev, 0, sizeof(usbhid_kbd_t));
-	
-	kbd_dev->hid_dev = usbhid_dev_new();
-	if (kbd_dev->hid_dev == NULL) {
-		usb_log_fatal("Could not create HID device structure.\n");
-		return NULL;
-	}
-	
-	kbd_dev->console_phone = -1;
-	kbd_dev->initialized = USBHID_KBD_STATUS_UNINITIALIZED;
-	
-	return kbd_dev;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static void usbhid_kbd_mark_unusable(usbhid_kbd_t *kbd_dev)
-{
-	kbd_dev->initialized = USBHID_KBD_STATUS_TO_DESTROY;
-}
-
-/*----------------------------------------------------------------------------*/
-/**
- * Initialization of the USB/HID keyboard structure.
- *
- * This functions initializes required structures from the device's descriptors.
- *
- * During initialization, the keyboard is switched into boot protocol, the idle
- * rate is set to 0 (infinity), resulting in the keyboard only reporting event
- * when a key is pressed or released. Finally, the LED lights are turned on 
- * according to the default setup of lock keys.
- *
- * @note By default, the keyboards is initialized with Num Lock turned on and 
- *       other locks turned off.
- *
- * @param kbd_dev Keyboard device structure to be initialized.
- * @param dev DDF device structure of the keyboard.
- *
- * @retval EOK if successful.
- * @retval EINVAL if some parameter is not given.
- * @return Other value inherited from function usbhid_dev_init().
- */
-static int usbhid_kbd_init(usbhid_kbd_t *kbd_dev, ddf_dev_t *dev)
-{
-	int rc;
-	
-	usb_log_info("Initializing HID/KBD structure...\n");
-	
-	if (kbd_dev == NULL) {
-		usb_log_error("Failed to init keyboard structure: no structure"
-		    " given.\n");
-		return EINVAL;
-	}
-	
-	if (dev == NULL) {
-		usb_log_error("Failed to init keyboard structure: no device"
-		    " given.\n");
-		return EINVAL;
-	}
-	
-	if (kbd_dev->initialized == USBHID_KBD_STATUS_INITIALIZED) {
-		usb_log_warning("Keyboard structure already initialized.\n");
-		return EINVAL;
-	}
-	
-	rc = usbhid_dev_init(kbd_dev->hid_dev, dev, &poll_endpoint_description);
-	
-	if (rc != EOK) {
-		usb_log_error("Failed to initialize HID device structure: %s\n",
-		   str_error(rc));
-		return rc;
-	}
-	
-	assert(kbd_dev->hid_dev->initialized == USBHID_KBD_STATUS_INITIALIZED);
-	
-	// save the size of the report (boot protocol report by default)
-//	kbd_dev->key_count = BOOTP_REPORT_SIZE;
-	
-	usb_hid_report_path_t path;
-	path.usage_page = USB_HIDUT_PAGE_KEYBOARD;
-	kbd_dev->key_count = usb_hid_report_input_length(
-	    kbd_dev->hid_dev->parser, &path);
-	
-	usb_log_debug("Size of the input report: %zu\n", kbd_dev->key_count);
-	
-	kbd_dev->keys = (uint8_t *)calloc(
-	    kbd_dev->key_count, sizeof(uint8_t));
-	
-	if (kbd_dev->keys == NULL) {
-		usb_log_fatal("No memory!\n");
-		return ENOMEM;
-	}
-	
-	kbd_dev->modifiers = 0;
-	kbd_dev->mods = DEFAULT_ACTIVE_MODS;
-	kbd_dev->lock_keys = 0;
-	
-	kbd_dev->repeat.key_new = 0;
-	kbd_dev->repeat.key_repeated = 0;
-	kbd_dev->repeat.delay_before = DEFAULT_DELAY_BEFORE_FIRST_REPEAT;
-	kbd_dev->repeat.delay_between = DEFAULT_REPEAT_DELAY;
-	
-	kbd_dev->repeat_mtx = (fibril_mutex_t *)(
-	    malloc(sizeof(fibril_mutex_t)));
-	if (kbd_dev->repeat_mtx == NULL) {
-		usb_log_fatal("No memory!\n");
-		free(kbd_dev->keys);
-		return ENOMEM;
-	}
-	
-	fibril_mutex_initialize(kbd_dev->repeat_mtx);
-	
-	/*
-	 * Set boot protocol.
-	 * Set LEDs according to initial setup.
-	 * Set Idle rate
-	 */
-	assert(kbd_dev->hid_dev != NULL);
-	assert(kbd_dev->hid_dev->initialized);
-	//usbhid_req_set_protocol(kbd_dev->hid_dev, USB_HID_PROTOCOL_BOOT);
-	
-	usbhid_kbd_set_led(kbd_dev);
-	
-	usbhid_req_set_idle(kbd_dev->hid_dev, IDLE_RATE);
-	
-	kbd_dev->initialized = USBHID_KBD_STATUS_INITIALIZED;
-	usb_log_info("HID/KBD device structure initialized.\n");
-	
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-/* HID/KBD polling                                                            */
-/*----------------------------------------------------------------------------*/
-/**
- * Main keyboard polling function.
- *
- * This function uses the Interrupt In pipe of the keyboard to poll for events.
- * The keyboard is initialized in a way that it reports only when a key is 
- * pressed or released, so there is no actual need for any sleeping between
- * polls (see usbhid_kbd_try_add_device() or usbhid_kbd_init()).
- *
- * @param kbd_dev Initialized keyboard structure representing the device to 
- *                poll.
- *
- * @sa usbhid_kbd_process_data()
- */
-static void usbhid_kbd_poll(usbhid_kbd_t *kbd_dev)
-{
-	int rc, sess_rc;
-	uint8_t buffer[BOOTP_BUFFER_SIZE];
-	size_t actual_size;
-	
-	usb_log_info("Polling keyboard...\n");
-	
-	if (!kbd_dev->initialized) {
-		usb_log_error("HID/KBD device not initialized!\n");
-		return;
-	}
-	
-	assert(kbd_dev->hid_dev != NULL);
-	assert(kbd_dev->hid_dev->initialized);
-
-	while (true) {
-		sess_rc = usb_pipe_start_session(
-		    &kbd_dev->hid_dev->poll_pipe);
-		if (sess_rc != EOK) {
-			usb_log_warning("Failed to start a session: %s.\n",
-			    str_error(sess_rc));
-			break;
-		}
-
-		rc = usb_pipe_read(&kbd_dev->hid_dev->poll_pipe, 
-		    buffer, BOOTP_BUFFER_SIZE, &actual_size);
-		
-		sess_rc = usb_pipe_end_session(
-		    &kbd_dev->hid_dev->poll_pipe);
-
-		if (rc != EOK) {
-			usb_log_warning("Error polling the keyboard: %s.\n",
-			    str_error(rc));
-			break;
-		}
-
-		if (sess_rc != EOK) {
-			usb_log_warning("Error closing session: %s.\n",
-			    str_error(sess_rc));
-			break;
-		}
-
-		/*
-		 * If the keyboard answered with NAK, it returned no data.
-		 * This implies that no change happened since last query.
-		 */
-		if (actual_size == 0) {
-			usb_log_debug("Keyboard returned NAK\n");
-			continue;
-		}
-
-		/*
-		 * TODO: Process pressed keys.
-		 */
-		usb_log_debug("Calling usbhid_kbd_process_data()\n");
-		usbhid_kbd_process_data(kbd_dev, buffer, actual_size);
-		
-		// disabled for now, no reason to sleep
-		//async_usleep(kbd_dev->hid_dev->poll_interval);
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-/**
- * Function executed by the main driver fibril.
- *
- * Just starts polling the keyboard for events.
- * 
- * @param arg Initialized keyboard device structure (of type usbhid_kbd_t) 
- *            representing the device.
- *
- * @retval EOK if the fibril finished polling the device.
- * @retval EINVAL if no device was given in the argument.
- *
- * @sa usbhid_kbd_poll()
- *
- * @todo Change return value - only case when the fibril finishes is in case
- *       of some error, so the error should probably be propagated from function
- *       usbhid_kbd_poll() to here and up.
- */
-static int usbhid_kbd_fibril(void *arg)
-{
-	if (arg == NULL) {
-		usb_log_error("No device!\n");
-		return EINVAL;
-	}
-	
-	usbhid_kbd_t *kbd_dev = (usbhid_kbd_t *)arg;
-
-	usbhid_kbd_poll(kbd_dev);
-	
-	// as there is another fibril using this device, so we must leave the
-	// structure to it, but mark it for destroying.
-	usbhid_kbd_mark_unusable(kbd_dev);
-	// at the end, properly destroy the KBD structure
-//	usbhid_kbd_free(&kbd_dev);
-//	assert(kbd_dev == NULL);
-
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-/* API functions                                                              */
-/*----------------------------------------------------------------------------*/
-/**
- * Function for adding a new device of type USB/HID/keyboard.
- *
- * This functions initializes required structures from the device's descriptors
- * and starts new fibril for polling the keyboard for events and another one for
- * handling auto-repeat of keys.
- *
- * During initialization, the keyboard is switched into boot protocol, the idle
- * rate is set to 0 (infinity), resulting in the keyboard only reporting event
- * when a key is pressed or released. Finally, the LED lights are turned on 
- * according to the default setup of lock keys.
- *
- * @note By default, the keyboards is initialized with Num Lock turned on and 
- *       other locks turned off.
- * @note Currently supports only boot-protocol keyboards.
- *
- * @param dev Device to add.
- *
- * @retval EOK if successful.
- * @retval ENOMEM if there
- * @return Other error code inherited from one of functions usbhid_kbd_init(),
- *         ddf_fun_bind() and ddf_fun_add_to_class().
- *
- * @sa usbhid_kbd_fibril(), usbhid_kbd_repeat_fibril()
- */
-int usbhid_kbd_try_add_device(ddf_dev_t *dev)
-{
-	/*
-	 * Create default function.
-	 */
-	ddf_fun_t *kbd_fun = ddf_fun_create(dev, fun_exposed, "keyboard");
-	if (kbd_fun == NULL) {
-		usb_log_error("Could not create DDF function node.\n");
-		return ENOMEM;
-	}
-	
-	/* 
-	 * Initialize device (get and process descriptors, get address, etc.)
-	 */
-	usb_log_info("Initializing USB/HID KBD device...\n");
-	
-	usbhid_kbd_t *kbd_dev = usbhid_kbd_new();
-	if (kbd_dev == NULL) {
-		usb_log_error("Error while creating USB/HID KBD device "
-		    "structure.\n");
-		ddf_fun_destroy(kbd_fun);
-		return ENOMEM;  // TODO: some other code??
-	}
-	
-	int rc = usbhid_kbd_init(kbd_dev, dev);
-	
-	if (rc != EOK) {
-		usb_log_error("Failed to initialize USB/HID KBD device.\n");
-		ddf_fun_destroy(kbd_fun);
-		usbhid_kbd_free(&kbd_dev);
-		return rc;
-	}	
-	
-	usb_log_info("USB/HID KBD device structure initialized.\n");
-	
-	/*
-	 * Store the initialized keyboard device and keyboard ops
-	 * to the DDF function.
-	 */
-	kbd_fun->driver_data = kbd_dev;
-	kbd_fun->ops = &keyboard_ops;
-
-	rc = ddf_fun_bind(kbd_fun);
-	if (rc != EOK) {
-		usb_log_error("Could not bind DDF function.\n");
-		// TODO: Can / should I destroy the DDF function?
-		ddf_fun_destroy(kbd_fun);
-		usbhid_kbd_free(&kbd_dev);
-		return rc;
-	}
-	
-	rc = ddf_fun_add_to_class(kbd_fun, "keyboard");
-	if (rc != EOK) {
-		usb_log_error("Could not add DDF function to class 'keyboard'"
-		    "\n");
-		// TODO: Can / should I destroy the DDF function?
-		ddf_fun_destroy(kbd_fun);
-		usbhid_kbd_free(&kbd_dev);
-		return rc;
-	}
-	
-	/*
-	 * Create new fibril for handling this keyboard
-	 */
-	fid_t fid = fibril_create(usbhid_kbd_fibril, kbd_dev);
-	if (fid == 0) {
-		usb_log_error("Failed to start fibril for KBD device\n");
-		return ENOMEM;
-	}
-	fibril_add_ready(fid);
-	
-	/*
-	 * Create new fibril for auto-repeat
-	 */
-	fid = fibril_create(usbhid_kbd_repeat_fibril, kbd_dev);
-	if (fid == 0) {
-		usb_log_error("Failed to start fibril for KBD auto-repeat");
-		return ENOMEM;
-	}
-	fibril_add_ready(fid);
-
-	(void)keyboard_ops;
-
-	/*
-	 * Hurrah, device is initialized.
-	 */
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-int usbhid_kbd_is_usable(const usbhid_kbd_t *kbd_dev)
-{
-	return (kbd_dev->initialized == USBHID_KBD_STATUS_INITIALIZED);
-}
-
-/*----------------------------------------------------------------------------*/
-/**
- * Properly destroys the USB/HID keyboard structure.
- *
- * @param kbd_dev Pointer to the structure to be destroyed.
- */
-void usbhid_kbd_free(usbhid_kbd_t **kbd_dev)
-{
-	if (kbd_dev == NULL || *kbd_dev == NULL) {
-		return;
-	}
-	
-	// hangup phone to the console
-	async_hangup((*kbd_dev)->console_phone);
-	
-	if ((*kbd_dev)->hid_dev != NULL) {
-		usbhid_dev_free(&(*kbd_dev)->hid_dev);
-		assert((*kbd_dev)->hid_dev == NULL);
-	}
-	
-	if ((*kbd_dev)->repeat_mtx != NULL) {
-		/* TODO: replace by some check and wait */
-		assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx));
-		free((*kbd_dev)->repeat_mtx);
-	}
-
-	free(*kbd_dev);
-	*kbd_dev = NULL;
-}
-
-/**
- * @}
- */
Index: uspace/drv/usbhid/kbddev.h
===================================================================
--- uspace/drv/usbhid/kbddev.h	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ 	(revision )
@@ -1,126 +1,0 @@
-/*
- * Copyright (c) 2011 Lubos Slovak
- * 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 drvusbhid
- * @{
- */
-/** @file
- * USB HID keyboard device structure and API.
- */
-
-#ifndef USBHID_KBDDEV_H_
-#define USBHID_KBDDEV_H_
-
-#include <stdint.h>
-
-#include <fibril_synch.h>
-
-#include <usb/classes/hid.h>
-#include <usb/classes/hidparser.h>
-#include <ddf/driver.h>
-#include <usb/pipes.h>
-
-#include "hiddev.h"
-
-/*----------------------------------------------------------------------------*/
-/**
- * Structure for keeping information needed for auto-repeat of keys.
- */
-typedef struct {
-	/** Last pressed key. */
-	unsigned int key_new;
-	/** Key to be repeated. */
-	unsigned int key_repeated;
-	/** Delay before first repeat in microseconds. */
-	unsigned int delay_before;
-	/** Delay between repeats in microseconds. */
-	unsigned int delay_between;
-} usbhid_kbd_repeat_t;
-
-/**
- * USB/HID keyboard device type.
- *
- * Holds a reference to generic USB/HID device structure and keyboard-specific
- * data, such as currently pressed keys, modifiers and lock keys.
- *
- * Also holds a IPC phone to the console (since there is now no other way to 
- * communicate with it).
- *
- * @note Storing active lock keys in this structure results in their setting
- *       being device-specific.
- */
-typedef struct {
-	/** Structure holding generic USB/HID device information. */
-	usbhid_dev_t *hid_dev;
-	
-	/** Currently pressed keys (not translated to key codes). */
-	uint8_t *keys;
-	/** Count of stored keys (i.e. number of keys in the report). */
-	size_t key_count;
-	/** Currently pressed modifiers (bitmap). */
-	uint8_t modifiers;
-	
-	/** Currently active modifiers including locks. Sent to the console. */
-	unsigned mods;
-	
-	/** Currently active lock keys. */
-	unsigned lock_keys;
-	
-	/** IPC phone to the console device (for sending key events). */
-	int console_phone;
-	
-	/** Information for auto-repeat of keys. */
-	usbhid_kbd_repeat_t repeat;
-	
-	/** Mutex for accessing the information about auto-repeat. */
-	fibril_mutex_t *repeat_mtx;
-	
-	/** State of the structure (for checking before use). 
-	 * 
-	 * 0 - not initialized
-	 * 1 - initialized
-	 * -1 - ready for destroying
-	 */
-	int initialized;
-} usbhid_kbd_t;
-
-/*----------------------------------------------------------------------------*/
-
-int usbhid_kbd_try_add_device(ddf_dev_t *dev);
-
-int usbhid_kbd_is_usable(const usbhid_kbd_t *kbd_dev);
-
-void usbhid_kbd_free(usbhid_kbd_t **kbd_dev);
-
-void usbhid_kbd_push_ev(usbhid_kbd_t *kbd_dev, int type, unsigned int key);
-
-#endif /* USBHID_KBDDEV_H_ */
-
-/**
- * @}
- */
Index: uspace/drv/usbhid/kbdrepeat.c
===================================================================
--- uspace/drv/usbhid/kbdrepeat.c	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ 	(revision )
@@ -1,183 +1,0 @@
-/*
- * Copyright (c) 2011 Lubos Slovak
- * 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 drvusbhid
- * @{
- */
-/**
- * @file
- * USB HID keyboard autorepeat facilities
- */
-
-#include <fibril_synch.h>
-#include <io/keycode.h>
-#include <io/console.h>
-#include <errno.h>
-
-#include <usb/debug.h>
-
-#include "kbdrepeat.h"
-#include "kbddev.h"
-
-
-/** Delay between auto-repeat state checks when no key is being repeated. */
-static unsigned int CHECK_DELAY = 10000;
-
-/*----------------------------------------------------------------------------*/
-/**
- * Main loop handling the auto-repeat of keys.
- *
- * This functions periodically checks if there is some key to be auto-repeated.
- *
- * If a new key is to be repeated, it uses the delay before first repeat stored
- * in the keyboard structure to wait until the key has to start repeating.
- *
- * If the same key is still pressed, it uses the delay between repeats stored
- * in the keyboard structure to wait until the key should be repeated.
- * 
- * If the currently repeated key is not pressed any more (
- * usbhid_kbd_repeat_stop() was called), it stops repeating it and starts 
- * checking again.
- *
- * @note For accessing the keyboard device auto-repeat information a fibril
- *       mutex (repeat_mtx) from the @a kbd structure is used.
- * 
- * @param kbd Keyboard device structure.
- */
-static void usbhid_kbd_repeat_loop(usbhid_kbd_t *kbd)
-{
-	unsigned int delay = 0;
-	
-	usb_log_debug("Starting autorepeat loop.\n");
-
-	while (true) {
-		// check if the kbd structure is usable
-		if (!usbhid_kbd_is_usable(kbd)) {
-			usbhid_kbd_free(&kbd);
-			assert(kbd == NULL);
-			return;
-		}
-		
-		fibril_mutex_lock(kbd->repeat_mtx);
-
-		if (kbd->repeat.key_new > 0) {
-			if (kbd->repeat.key_new == kbd->repeat.key_repeated) {
-				usb_log_debug2("Repeating key: %u.\n", 
-				    kbd->repeat.key_repeated);
-				usbhid_kbd_push_ev(kbd, KEY_PRESS, 
-				    kbd->repeat.key_repeated);
-				delay = kbd->repeat.delay_between;
-			} else {
-				usb_log_debug("New key to repeat: %u.\n", 
-				    kbd->repeat.key_new);
-				kbd->repeat.key_repeated = kbd->repeat.key_new;
-				delay = kbd->repeat.delay_before;
-			}
-		} else {
-			if (kbd->repeat.key_repeated > 0) {
-				usb_log_debug("Stopping to repeat key: %u.\n", 
-				    kbd->repeat.key_repeated);
-				kbd->repeat.key_repeated = 0;
-			}
-			delay = CHECK_DELAY;
-		}
-		fibril_mutex_unlock(kbd->repeat_mtx);
-		
-		async_usleep(delay);
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-/**
- * Main routine to be executed by a fibril for handling auto-repeat.
- *
- * Starts the loop for checking changes in auto-repeat.
- * 
- * @param arg User-specified argument. Expects pointer to the keyboard device
- *            structure representing the keyboard.
- *
- * @retval EOK if the routine has finished.
- * @retval EINVAL if no argument is supplied.
- */
-int usbhid_kbd_repeat_fibril(void *arg)
-{
-	usb_log_debug("Autorepeat fibril spawned.\n");
-	
-	if (arg == NULL) {
-		usb_log_error("No device!\n");
-		return EINVAL;
-	}
-	
-	usbhid_kbd_t *kbd = (usbhid_kbd_t *)arg;
-	
-	usbhid_kbd_repeat_loop(kbd);
-	
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-/**
- * Start repeating particular key.
- *
- * @note Only one key is repeated at any time, so calling this function 
- *       effectively cancels auto-repeat of the current repeated key (if any)
- *       and 'schedules' another key for auto-repeat.
- *
- * @param kbd Keyboard device structure.
- * @param key Key to start repeating.
- */
-void usbhid_kbd_repeat_start(usbhid_kbd_t *kbd, unsigned int key)
-{
-	fibril_mutex_lock(kbd->repeat_mtx);
-	kbd->repeat.key_new = key;
-	fibril_mutex_unlock(kbd->repeat_mtx);
-}
-
-/*----------------------------------------------------------------------------*/
-/**
- * Stop repeating particular key.
- *
- * @note Only one key is repeated at any time, but this function may be called
- *       even with key that is not currently repeated (in that case nothing 
- *       happens).
- *
- * @param kbd Keyboard device structure.
- * @param key Key to stop repeating.
- */
-void usbhid_kbd_repeat_stop(usbhid_kbd_t *kbd, unsigned int key)
-{
-	fibril_mutex_lock(kbd->repeat_mtx);
-	if (key == kbd->repeat.key_new) {
-		kbd->repeat.key_new = 0;
-	}
-	fibril_mutex_unlock(kbd->repeat_mtx);
-}
-
-/**
- * @}
- */
Index: uspace/drv/usbhid/kbdrepeat.h
===================================================================
--- uspace/drv/usbhid/kbdrepeat.h	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ 	(revision )
@@ -1,53 +1,0 @@
-/*
- * Copyright (c) 2011 Lubos Slovak
- * 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 drvusbhid
- * @{
- */
-/** @file
- * USB HID keyboard autorepeat facilities
- */
-
-#ifndef USBHID_KBDREPEAT_H_
-#define USBHID_KBDREPEAT_H_
-
-#include "kbddev.h"
-
-/*----------------------------------------------------------------------------*/
-
-int usbhid_kbd_repeat_fibril(void *arg);
-
-void usbhid_kbd_repeat_start(usbhid_kbd_t *kbd, unsigned int key);
-
-void usbhid_kbd_repeat_stop(usbhid_kbd_t *kbd, unsigned int key);
-
-#endif /* USBHID_KBDREPEAT_H_ */
-
-/**
- * @}
- */
Index: uspace/drv/usbhid/layout.h
===================================================================
--- uspace/drv/usbhid/layout.h	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ 	(revision )
@@ -1,57 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * Copyright (c) 2011 Lubos Slovak 
- * (copied from /uspace/srv/hid/kbd/include/layout.h)
- * 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 drvusbhid
- * @{
- */
-/** @file
- * Keyboard layout.
- */
-
-#ifndef USBHID_LAYOUT_H_
-#define USBHID_LAYOUT_H_
-
-#include <sys/types.h>
-#include <io/console.h>
-
-typedef struct {
-	void (*reset)(void);
-	wchar_t (*parse_ev)(console_event_t *);
-} layout_op_t;
-
-extern layout_op_t us_qwerty_op;
-extern layout_op_t us_dvorak_op;
-extern layout_op_t cz_op;
-
-#endif
-
-/**
- * @}
- */
Index: uspace/drv/usbhid/main.c
===================================================================
--- uspace/drv/usbhid/main.c	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ 	(revision )
@@ -1,97 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * Copyright (c) 2011 Lubos Slovak
- * 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 drvusbhid
- * @{
- */
-/**
- * @file
- * Main routines of USB HID driver.
- */
-
-#include <ddf/driver.h>
-#include <usb/debug.h>
-#include <errno.h>
-
-#include "kbddev.h"
-
-/*----------------------------------------------------------------------------*/
-
-#define NAME "usbhid"
-
-/*----------------------------------------------------------------------------*/
-/**
- * Callback for passing a new device to the driver.
- *
- * @note Currently, only boot-protocol keyboards are supported by this driver.
- *
- * @param dev Structure representing the new device.
- *
- * @retval EOK if successful. 
- * @retval EREFUSED if the device is not supported.
- */
-static int usbhid_add_device(ddf_dev_t *dev)
-{
-	usb_log_debug("usbhid_add_device()\n");
-	
-	int rc = usbhid_kbd_try_add_device(dev);
-	
-	if (rc != EOK) {
-		usb_log_info("Device is not a supported keyboard.\n");
-		usb_log_error("Failed to add HID device.\n");
-		return EREFUSED;
-	}
-	
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static driver_ops_t kbd_driver_ops = {
-	.add_device = usbhid_add_device,
-};
-
-/*----------------------------------------------------------------------------*/
-
-static driver_t kbd_driver = {
-	.name = NAME,
-	.driver_ops = &kbd_driver_ops
-};
-
-/*----------------------------------------------------------------------------*/
-
-int main(int argc, char *argv[])
-{
-	usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
-	return ddf_driver_main(&kbd_driver);
-}
-
-/**
- * @}
- */
Index: uspace/drv/usbhid/usbhid.ma
===================================================================
--- uspace/drv/usbhid/usbhid.ma	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ 	(revision )
@@ -1,2 +1,0 @@
-100 usb&interface&class=HID&subclass=0x01&protocol=0x01
-10 usb&interface&class=HID
Index: uspace/drv/usbhub/main.c
===================================================================
--- uspace/drv/usbhub/main.c	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ uspace/drv/usbhub/main.c	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -76,5 +76,5 @@
 	printf(NAME ": HelenOS USB hub driver.\n");
 
-	usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
+	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
 	
 	return usb_driver_main(&usb_hub_driver);
Index: uspace/drv/usbhub/usbhub.c
===================================================================
--- uspace/drv/usbhub/usbhub.c	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ uspace/drv/usbhub/usbhub.c	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -132,5 +132,5 @@
 		return opResult;
 	}
-	usb_log_info("setting port count to %d\n",descriptor->ports_count);
+	usb_log_debug("setting port count to %d\n",descriptor->ports_count);
 	hub_info->port_count = descriptor->ports_count;
 	hub_info->attached_devs = (usb_hc_attached_device_t*)
@@ -159,5 +159,5 @@
 	usb_standard_device_descriptor_t *std_descriptor
 	    = &hub_info->usb_device->descriptors.device;
-	usb_log_info("hub has %d configurations\n",
+	usb_log_debug("hub has %d configurations\n",
 	    std_descriptor->configuration_count);
 	if(std_descriptor->configuration_count<1){
@@ -288,5 +288,5 @@
 	//if this hub already uses default address, it cannot request it once more
 	if(hub->is_default_address_used) return;
-	usb_log_info("some connection changed\n");
+	usb_log_debug("some connection changed\n");
 	assert(hub->control_pipe->hc_phone);
 	int opResult = usb_hub_clear_port_feature(hub->control_pipe,
@@ -331,5 +331,5 @@
 
 	int opResult;
-	usb_log_info("finalizing add device\n");
+	usb_log_debug("finalizing add device\n");
 	opResult = usb_hub_clear_port_feature(hub->control_pipe,
 	    port, USB_HUB_FEATURE_C_PORT_RESET);
@@ -363,5 +363,5 @@
 		return;
 	}
-	usb_log_info("setting new address %d\n",new_device_address);
+	usb_log_debug("setting new address %d\n",new_device_address);
 	//opResult = usb_drv_req_set_address(hc, USB_ADDRESS_DEFAULT,
 	//    new_device_address);
@@ -403,7 +403,8 @@
 		return;
 	}
-	usb_log_info("new device address %d, handle %zu\n",
+	usb_log_info("Detected new device on `%s' (port %d), " \
+	    "address %d (handle %llu).\n",
+	    hub->usb_device->ddf_dev->name, (int) port,
 	    new_device_address, child_handle);
-
 }
 
@@ -502,5 +503,5 @@
 	if (usb_port_connect_change(&status)) {
 		if (usb_port_dev_connected(&status)) {
-			usb_log_info("some connection changed\n");
+			usb_log_debug("some connection changed\n");
 			usb_hub_init_add_device(hub, port, usb_port_speed(&status));
 		} else {
@@ -514,5 +515,5 @@
 			usb_hub_over_current(hub,port);
 		}else{
-			usb_log_info("over current condition was auto-resolved on port %d\n",
+			usb_log_debug("over current condition was auto-resolved on port %d\n",
 					port);
 		}
@@ -520,5 +521,5 @@
 	//port reset
 	if (usb_port_reset_completed(&status)) {
-		usb_log_info("port reset complete\n");
+		usb_log_debug("port reset complete\n");
 		if (usb_port_enabled(&status)) {
 			usb_hub_finalize_add_device(hub, port, usb_port_speed(&status));
Index: uspace/drv/usbkbd/Makefile
===================================================================
--- uspace/drv/usbkbd/Makefile	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
+++ uspace/drv/usbkbd/Makefile	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -0,0 +1,53 @@
+#
+# Copyright (c) 2010-2011 Vojtech Horky
+# 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.
+#
+
+USPACE_PREFIX = ../..
+LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBUSB_PREFIX)/libusb.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBUSB_PREFIX)/include -I.
+BINARY = usbkbd
+
+STOLEN_LAYOUT_SOURCES = \
+	layout/us_qwerty.c \
+	layout/us_dvorak.c \
+	layout/cz.c
+
+SOURCES = \
+	main.c \
+	conv.c \
+	kbddev.c \
+	kbdrepeat.c \
+	$(STOLEN_LAYOUT_SOURCES)
+
+EXTRA_CLEAN = $(STOLEN_LAYOUT_SOURCES)
+
+SRV_KBD = $(USPACE_PREFIX)/srv/hid/kbd
+
+include $(USPACE_PREFIX)/Makefile.common
+
+layout/%.c: $(SRV_KBD)/layout/%.c
+	ln -sfn ../$< $@
Index: uspace/drv/usbkbd/conv.c
===================================================================
--- uspace/drv/usbkbd/conv.c	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
+++ uspace/drv/usbkbd/conv.c	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/** @file
+ * USB scancode parser.
+ */
+
+#include <io/keycode.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <usb/debug.h>
+#include "conv.h"
+
+/**
+ * Mapping between USB HID key codes (from HID Usage Tables) and corresponding
+ * HelenOS key codes.
+ */
+static int scanmap_simple[255] = {
+
+//	[0x29] = KC_BACKTICK,
+
+//	[0x02] = KC_1,
+//	[0x03] = KC_2,
+	[0x04] = KC_A,
+	[0x05] = KC_B,
+	[0x06] = KC_C,
+	[0x07] = KC_D,
+	[0x08] = KC_E,
+	[0x09] = KC_F,
+	[0x0a] = KC_G,
+	[0x0b] = KC_H,
+	[0x0c] = KC_I,
+	[0x0d] = KC_J,
+	[0x0e] = KC_K,
+	[0x0f] = KC_L,
+	[0x10] = KC_M,
+	[0x11] = KC_N,
+	[0x12] = KC_O,
+	[0x13] = KC_P,
+	[0x14] = KC_Q,
+	[0x15] = KC_R,
+	[0x16] = KC_S,
+	[0x17] = KC_T,
+	[0x18] = KC_U,
+	[0x19] = KC_V,
+	[0x1a] = KC_W,
+	[0x1b] = KC_X,
+	[0x1c] = KC_Y,
+	[0x1d] = KC_Z,
+
+	[0x1e] = KC_1,
+	[0x1f] = KC_2,
+	[0x20] = KC_3,
+	[0x21] = KC_4,
+	[0x22] = KC_5,
+	[0x23] = KC_6,
+	[0x24] = KC_7,
+	[0x25] = KC_8,
+	[0x26] = KC_9,
+	[0x27] = KC_0,
+	
+	[0x28] = KC_ENTER,
+	[0x29] = KC_ESCAPE,
+	[0x2a] = KC_BACKSPACE,
+	[0x2b] = KC_TAB,
+	[0x2c] = KC_SPACE,
+
+	[0x2d] = KC_MINUS,  // same as DASH? (- or _)
+	[0x2e] = KC_EQUALS,
+	[0x2f] = KC_LBRACKET,
+	[0x30] = KC_RBRACKET,
+	[0x31] = KC_BACKSLASH,
+	//[0x32] = KC_,	// TODO: HASH??? maybe some as 0x31 - backslash
+	[0x33] = KC_SEMICOLON,
+	[0x34] = KC_QUOTE,  // same as APOSTROPHE? (')
+	[0x35] = KC_BACKTICK,  // same as GRAVE ACCENT?? (`)
+	[0x36] = KC_COMMA,
+	[0x37] = KC_PERIOD,
+	[0x38] = KC_SLASH,
+
+	[0x39] = KC_CAPS_LOCK,
+	
+	[0x3a] = KC_F1,
+	[0x3b] = KC_F2,
+	[0x3c] = KC_F3,
+	[0x3d] = KC_F4,
+	[0x3e] = KC_F5,
+	[0x3f] = KC_F6,
+	[0x40] = KC_F7,
+	[0x41] = KC_F8,
+	[0x42] = KC_F9,
+	[0x43] = KC_F10,
+	[0x44] = KC_F11,
+	[0x45] = KC_F12,
+	
+	[0x46] = KC_PRTSCR,
+	[0x47] = KC_SCROLL_LOCK,
+	[0x48] = KC_PAUSE,
+	[0x49] = KC_INSERT,
+	[0x4a] = KC_HOME,
+	[0x4b] = KC_PAGE_UP,
+	[0x4c] = KC_DELETE,
+	[0x4d] = KC_END,
+	[0x4e] = KC_PAGE_DOWN,
+	[0x4f] = KC_RIGHT,
+	[0x50] = KC_LEFT,
+	[0x51] = KC_DOWN,
+	[0x52] = KC_UP,
+	
+	//[0x64] = // some funny key
+	
+	[0xe0] = KC_LCTRL,
+	[0xe1] = KC_LSHIFT,
+	[0xe2] = KC_LALT,
+	//[0xe3] = KC_L	// TODO: left GUI
+	[0xe4] = KC_RCTRL,
+	[0xe5] = KC_RSHIFT,
+	[0xe6] = KC_RALT,
+	//[0xe7] = KC_R	// TODO: right GUI
+	
+	[0x53] = KC_NUM_LOCK,
+	[0x54] = KC_NSLASH,
+	[0x55] = KC_NTIMES,
+	[0x56] = KC_NMINUS,
+	[0x57] = KC_NPLUS,
+	[0x58] = KC_NENTER,
+	[0x59] = KC_N1,
+	[0x5a] = KC_N2,
+	[0x5b] = KC_N3,
+	[0x5c] = KC_N4,
+	[0x5d] = KC_N5,
+	[0x5e] = KC_N6,
+	[0x5f] = KC_N7,
+	[0x60] = KC_N8,
+	[0x61] = KC_N9,
+	[0x62] = KC_N0,
+	[0x63] = KC_NPERIOD
+	
+};
+
+/**
+ * Translate USB HID key codes (from HID Usage Tables) to generic key codes
+ * recognized by HelenOS.
+ *
+ * @param scancode USB HID key code (from HID Usage Tables).
+ * 
+ * @retval HelenOS key code corresponding to the given USB HID key code.
+ */
+unsigned int usbhid_parse_scancode(int scancode)
+{
+	unsigned int key;
+	int *map = scanmap_simple;
+	size_t map_length = sizeof(scanmap_simple) / sizeof(int);
+
+	if ((scancode < 0) || ((size_t) scancode >= map_length))
+		return -1;
+
+	key = map[scancode];
+	
+	return key;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/usbkbd/conv.h
===================================================================
--- uspace/drv/usbkbd/conv.h	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
+++ uspace/drv/usbkbd/conv.h	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/** @file
+ * USB scancode parser.
+ */
+
+#ifndef USB_KBD_CONV_H_
+#define USB_KBD_CONV_H_
+
+unsigned int usbhid_parse_scancode(int scancode);
+
+#endif /* USB_KBD_CONV_H_ */
+
+/**
+ * @}
+ */
Index: uspace/drv/usbkbd/kbd.h
===================================================================
--- uspace/drv/usbkbd/kbd.h	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
+++ uspace/drv/usbkbd/kbd.h	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -0,0 +1,5 @@
+/*
+ * Dummy file because of shared layout sources.
+ *
+ * Do not delete.
+ */
Index: uspace/drv/usbkbd/kbddev.c
===================================================================
--- uspace/drv/usbkbd/kbddev.c	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
+++ uspace/drv/usbkbd/kbddev.c	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -0,0 +1,889 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/**
+ * @file
+ * USB HID keyboard device structure and API.
+ */
+
+#include <errno.h>
+#include <str_error.h>
+#include <stdio.h>
+
+#include <io/keycode.h>
+#include <ipc/kbd.h>
+#include <async.h>
+#include <fibril.h>
+#include <fibril_synch.h>
+
+#include <usb/usb.h>
+#include <usb/dp.h>
+#include <usb/request.h>
+#include <usb/classes/hid.h>
+#include <usb/pipes.h>
+#include <usb/debug.h>
+#include <usb/classes/hidparser.h>
+#include <usb/classes/classes.h>
+#include <usb/classes/hidut.h>
+#include <usb/classes/hidreq.h>
+#include <usb/classes/hidreport.h>
+
+#include <usb/devdrv.h>
+
+#include "kbddev.h"
+
+#include "layout.h"
+#include "conv.h"
+#include "kbdrepeat.h"
+
+/*----------------------------------------------------------------------------*/
+/** Default modifiers when the keyboard is initialized. */
+static const unsigned DEFAULT_ACTIVE_MODS = KM_NUM_LOCK;
+
+/** Boot protocol report size (key part). */
+static const size_t BOOTP_REPORT_SIZE = 6;
+
+/** Boot protocol total report size. */
+static const size_t BOOTP_BUFFER_SIZE = 8;
+
+/** Boot protocol output report size. */
+static const size_t BOOTP_BUFFER_OUT_SIZE = 1;
+
+/** Boot protocol error key code. */
+static const uint8_t BOOTP_ERROR_ROLLOVER = 1;
+
+/** Default idle rate for keyboards. */
+static const uint8_t IDLE_RATE = 0;
+
+/** Delay before a pressed key starts auto-repeating. */
+static const unsigned int DEFAULT_DELAY_BEFORE_FIRST_REPEAT = 500 * 1000;
+
+/** Delay between two repeats of a pressed key when auto-repeating. */
+static const unsigned int DEFAULT_REPEAT_DELAY = 50 * 1000;
+
+/*----------------------------------------------------------------------------*/
+
+/** Keyboard polling endpoint description for boot protocol class. */
+static usb_endpoint_description_t boot_poll_endpoint_description = {
+	.transfer_type = USB_TRANSFER_INTERRUPT,
+	.direction = USB_DIRECTION_IN,
+	.interface_class = USB_CLASS_HID,
+	.interface_subclass = USB_HID_SUBCLASS_BOOT,
+	.interface_protocol = USB_HID_PROTOCOL_KEYBOARD,
+	.flags = 0
+};
+
+/* Array of endpoints expected on the device, NULL terminated. */
+usb_endpoint_description_t 
+    *usb_kbd_endpoints[USB_KBD_POLL_EP_COUNT + 1] = {
+	&boot_poll_endpoint_description,
+	NULL
+};
+
+/*----------------------------------------------------------------------------*/
+
+enum {
+	BOOT_REPORT_DESCRIPTOR_SIZE = 63
+};
+
+static const uint8_t BOOT_REPORT_DESCRIPTOR[BOOT_REPORT_DESCRIPTOR_SIZE] = {
+        0x05, 0x01,  // Usage Page (Generic Desktop),
+        0x09, 0x06,  // Usage (Keyboard),
+        0xA1, 0x01,  // Collection (Application),
+        0x75, 0x01,  //   Report Size (1),
+        0x95, 0x08,  //   Report Count (8),       
+        0x05, 0x07,  //   Usage Page (Key Codes);
+        0x19, 0xE0,  //   Usage Minimum (224),
+        0x29, 0xE7,  //   Usage Maximum (231),
+        0x15, 0x00,  //   Logical Minimum (0),
+        0x25, 0x01,  //   Logical Maximum (1),
+        0x81, 0x02,  //   Input (Data, Variable, Absolute),   ; Modifier byte
+	0x95, 0x01,  //   Report Count (1),
+        0x75, 0x08,  //   Report Size (8),
+        0x81, 0x01,  //   Input (Constant),                   ; Reserved byte
+        0x95, 0x05,  //   Report Count (5),
+        0x75, 0x01,  //   Report Size (1),
+        0x05, 0x08,  //   Usage Page (Page# for LEDs),
+        0x19, 0x01,  //   Usage Minimum (1),
+        0x29, 0x05,  //   Usage Maxmimum (5),
+        0x91, 0x02,  //   Output (Data, Variable, Absolute),  ; LED report
+        0x95, 0x01,  //   Report Count (1),
+        0x75, 0x03,  //   Report Size (3),
+        0x91, 0x01,  //   Output (Constant),              ; LED report padding
+        0x95, 0x06,  //   Report Count (6),
+        0x75, 0x08,  //   Report Size (8),
+        0x15, 0x00,  //   Logical Minimum (0),
+        0x25, 0xff,  //   Logical Maximum (255),
+        0x05, 0x07,  //   Usage Page (Key Codes),
+        0x19, 0x00,  //   Usage Minimum (0),
+        0x29, 0xff,  //   Usage Maximum (255),
+        0x81, 0x00,  //   Input (Data, Array),            ; Key arrays (6 bytes)
+        0xC0           // End Collection
+
+};
+
+/*----------------------------------------------------------------------------*/
+
+typedef enum usb_kbd_flags {
+	USB_KBD_STATUS_UNINITIALIZED = 0,
+	USB_KBD_STATUS_INITIALIZED = 1,
+	USB_KBD_STATUS_TO_DESTROY = -1
+} usb_kbd_flags;
+
+/*----------------------------------------------------------------------------*/
+/* Keyboard layouts                                                           */
+/*----------------------------------------------------------------------------*/
+
+#define NUM_LAYOUTS 3
+
+/** Keyboard layout map. */
+static layout_op_t *layout[NUM_LAYOUTS] = {
+	&us_qwerty_op,
+	&us_dvorak_op,
+	&cz_op
+};
+
+static int active_layout = 0;
+
+/*----------------------------------------------------------------------------*/
+/* Modifier constants                                                         */
+/*----------------------------------------------------------------------------*/
+/** Mapping of USB modifier key codes to generic modifier key codes. */
+static const keycode_t usbhid_modifiers_keycodes[USB_HID_MOD_COUNT] = {
+	KC_LCTRL,         /* USB_HID_MOD_LCTRL */
+	KC_LSHIFT,        /* USB_HID_MOD_LSHIFT */
+	KC_LALT,          /* USB_HID_MOD_LALT */
+	0,                /* USB_HID_MOD_LGUI */
+	KC_RCTRL,         /* USB_HID_MOD_RCTRL */
+	KC_RSHIFT,        /* USB_HID_MOD_RSHIFT */
+	KC_RALT,          /* USB_HID_MOD_RALT */
+	0,                /* USB_HID_MOD_RGUI */
+};
+
+typedef enum usbhid_lock_code {
+	USB_KBD_LOCK_NUM = 0x53,
+	USB_KBD_LOCK_CAPS = 0x39,
+	USB_KBD_LOCK_SCROLL = 0x47,
+	USB_KBD_LOCK_COUNT = 3
+} usbhid_lock_code;
+
+static const usbhid_lock_code usbhid_lock_codes[USB_KBD_LOCK_COUNT] = {
+	USB_KBD_LOCK_NUM,
+	USB_KBD_LOCK_CAPS,
+	USB_KBD_LOCK_SCROLL
+};
+
+/*----------------------------------------------------------------------------*/
+/* IPC method handler                                                         */
+/*----------------------------------------------------------------------------*/
+
+static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
+ddf_dev_ops_t keyboard_ops = {
+	.default_handler = default_connection_handler
+};
+
+/** 
+ * Default handler for IPC methods not handled by DDF.
+ *
+ * Currently recognizes only one method (IPC_M_CONNECT_TO_ME), in which case it
+ * assumes the caller is the console and thus it stores IPC phone to it for 
+ * later use by the driver to notify about key events.
+ *
+ * @param fun Device function handling the call.
+ * @param icallid Call id.
+ * @param icall Call data.
+ */
+void default_connection_handler(ddf_fun_t *fun,
+    ipc_callid_t icallid, ipc_call_t *icall)
+{
+	sysarg_t method = IPC_GET_IMETHOD(*icall);
+	
+	usb_kbd_t *kbd_dev = (usb_kbd_t *)fun->driver_data;
+	assert(kbd_dev != NULL);
+
+	if (method == IPC_M_CONNECT_TO_ME) {
+		int callback = IPC_GET_ARG5(*icall);
+
+		if (kbd_dev->console_phone != -1) {
+			async_answer_0(icallid, ELIMIT);
+			return;
+		}
+
+		kbd_dev->console_phone = callback;
+		async_answer_0(icallid, EOK);
+		return;
+	}
+	
+	async_answer_0(icallid, EINVAL);
+}
+
+/*----------------------------------------------------------------------------*/
+/* Key processing functions                                                   */
+/*----------------------------------------------------------------------------*/
+/**
+ * Handles turning of LED lights on and off.
+ *
+ * In case of USB keyboards, the LEDs are handled in the driver, not in the 
+ * device. When there should be a change (lock key was pressed), the driver
+ * uses a Set_Report request sent to the device to set the state of the LEDs.
+ *
+ * This functions sets the LED lights according to current settings of modifiers
+ * kept in the keyboard device structure.
+ *
+ * @param kbd_dev Keyboard device structure.
+ */
+static void usb_kbd_set_led(usb_kbd_t *kbd_dev) 
+{
+	uint8_t buffer[BOOTP_BUFFER_OUT_SIZE];
+	int rc= 0;
+	
+	memset(buffer, 0, BOOTP_BUFFER_OUT_SIZE);
+	uint8_t leds = 0;
+
+	if (kbd_dev->mods & KM_NUM_LOCK) {
+		leds |= USB_HID_LED_NUM_LOCK;
+	}
+	
+	if (kbd_dev->mods & KM_CAPS_LOCK) {
+		leds |= USB_HID_LED_CAPS_LOCK;
+	}
+	
+	if (kbd_dev->mods & KM_SCROLL_LOCK) {
+		leds |= USB_HID_LED_SCROLL_LOCK;
+	}
+
+	// TODO: COMPOSE and KANA
+	
+	usb_log_debug("Creating output report.\n");
+	usb_log_debug("Leds: 0x%x\n", leds);
+	if ((rc = usb_hid_boot_keyboard_output_report(
+	    leds, buffer, BOOTP_BUFFER_OUT_SIZE)) != EOK) {
+		usb_log_warning("Error composing output report to the keyboard:"
+		    "%s.\n", str_error(rc));
+		return;
+	}
+	
+	usb_log_debug("Output report buffer: %s\n", 
+	    usb_debug_str_buffer(buffer, BOOTP_BUFFER_OUT_SIZE, 0));
+	
+	assert(kbd_dev->usb_dev != NULL);
+	
+	usbhid_req_set_report(&kbd_dev->usb_dev->ctrl_pipe, 
+	    kbd_dev->usb_dev->interface_no, USB_HID_REPORT_TYPE_OUTPUT, 
+	    buffer, BOOTP_BUFFER_OUT_SIZE);
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Processes key events.
+ *
+ * @note This function was copied from AT keyboard driver and modified to suit
+ *       USB keyboard.
+ *
+ * @note Lock keys are not sent to the console, as they are completely handled
+ *       in the driver. It may, however, be required later that the driver
+ *       sends also these keys to application (otherwise it cannot use those
+ *       keys at all).
+ * 
+ * @param kbd_dev Keyboard device structure.
+ * @param type Type of the event (press / release). Recognized values: 
+ *             KEY_PRESS, KEY_RELEASE
+ * @param key Key code of the key according to HID Usage Tables.
+ */
+void usb_kbd_push_ev(usb_kbd_t *kbd_dev, int type, unsigned int key)
+{
+	console_event_t ev;
+	unsigned mod_mask;
+
+	/*
+	 * These parts are copy-pasted from the AT keyboard driver.
+	 *
+	 * They definitely require some refactoring, but will keep it for later
+	 * when the console and keyboard system is changed in HelenOS.
+	 */
+	switch (key) {
+	case KC_LCTRL: mod_mask = KM_LCTRL; break;
+	case KC_RCTRL: mod_mask = KM_RCTRL; break;
+	case KC_LSHIFT: mod_mask = KM_LSHIFT; break;
+	case KC_RSHIFT: mod_mask = KM_RSHIFT; break;
+	case KC_LALT: mod_mask = KM_LALT; break;
+	case KC_RALT: mod_mask = KM_RALT; break;
+	default: mod_mask = 0; break;
+	}
+
+	if (mod_mask != 0) {
+		if (type == KEY_PRESS)
+			kbd_dev->mods = kbd_dev->mods | mod_mask;
+		else
+			kbd_dev->mods = kbd_dev->mods & ~mod_mask;
+	}
+
+	switch (key) {
+	case KC_CAPS_LOCK: mod_mask = KM_CAPS_LOCK; break;
+	case KC_NUM_LOCK: mod_mask = KM_NUM_LOCK; break;
+	case KC_SCROLL_LOCK: mod_mask = KM_SCROLL_LOCK; break;
+	default: mod_mask = 0; break;
+	}
+
+	if (mod_mask != 0) {
+		if (type == KEY_PRESS) {
+			/*
+			 * Only change lock state on transition from released
+			 * to pressed. This prevents autorepeat from messing
+			 * up the lock state.
+			 */
+			unsigned int locks_old = kbd_dev->lock_keys;
+			
+			kbd_dev->mods = 
+			    kbd_dev->mods ^ (mod_mask & ~kbd_dev->lock_keys);
+			kbd_dev->lock_keys = kbd_dev->lock_keys | mod_mask;
+
+			/* Update keyboard lock indicator lights. */
+			if (kbd_dev->lock_keys != locks_old) {
+				usb_kbd_set_led(kbd_dev);
+			}
+		} else {
+			kbd_dev->lock_keys = kbd_dev->lock_keys & ~mod_mask;
+		}
+	}
+
+	if (key == KC_CAPS_LOCK || key == KC_NUM_LOCK || key == KC_SCROLL_LOCK) {
+		// do not send anything to the console, this is our business
+		return;
+	}
+	
+	if (type == KEY_PRESS && (kbd_dev->mods & KM_LCTRL) && key == KC_F1) {
+		active_layout = 0;
+		layout[active_layout]->reset();
+		return;
+	}
+
+	if (type == KEY_PRESS && (kbd_dev->mods & KM_LCTRL) && key == KC_F2) {
+		active_layout = 1;
+		layout[active_layout]->reset();
+		return;
+	}
+
+	if (type == KEY_PRESS && (kbd_dev->mods & KM_LCTRL) && key == KC_F3) {
+		active_layout = 2;
+		layout[active_layout]->reset();
+		return;
+	}
+	
+	ev.type = type;
+	ev.key = key;
+	ev.mods = kbd_dev->mods;
+
+	ev.c = layout[active_layout]->parse_ev(&ev);
+
+	usb_log_debug2("Sending key %d to the console\n", ev.key);
+	if (kbd_dev->console_phone < 0) {
+		usb_log_warning(
+		    "Connection to console not ready, key discarded.\n");
+		return;
+	}
+	
+	async_msg_4(kbd_dev->console_phone, KBD_EVENT, ev.type, ev.key, 
+	    ev.mods, ev.c);
+}
+
+/*----------------------------------------------------------------------------*/
+
+static inline int usb_kbd_is_lock(unsigned int key_code) 
+{
+	return (key_code == KC_NUM_LOCK
+	    || key_code == KC_SCROLL_LOCK
+	    || key_code == KC_CAPS_LOCK);
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Checks if some keys were pressed or released and generates key events.
+ *
+ * An event is created only when key is pressed or released. Besides handling
+ * the events (usb_kbd_push_ev()), the auto-repeat fibril is notified about
+ * key presses and releases (see usb_kbd_repeat_start() and 
+ * usb_kbd_repeat_stop()).
+ *
+ * @param kbd_dev Keyboard device structure.
+ * @param key_codes Parsed keyboard report - codes of currently pressed keys 
+ *                  according to HID Usage Tables.
+ * @param count Number of key codes in report (size of the report).
+ *
+ * @sa usb_kbd_push_ev(), usb_kbd_repeat_start(), usb_kbd_repeat_stop()
+ */
+static void usb_kbd_check_key_changes(usb_kbd_t *kbd_dev, 
+    const uint8_t *key_codes, size_t count)
+{
+	unsigned int key;
+	unsigned int i, j;
+	
+	/*
+	 * First of all, check if the kbd have reported phantom state.
+	 *
+	 *  this must be changed as we don't know which keys are modifiers
+	 *       and which are regular keys.
+	 */
+	i = 0;
+	// all fields should report Error Rollover
+	while (i < count &&
+	    key_codes[i] == BOOTP_ERROR_ROLLOVER) {
+		++i;
+	}
+	if (i == count) {
+		usb_log_debug("Phantom state occured.\n");
+		// phantom state, do nothing
+		return;
+	}
+	
+	/* TODO: quite dummy right now, think of better implementation */
+	assert(count == kbd_dev->key_count);
+	
+	/*
+	 * 1) Key releases
+	 */
+	for (j = 0; j < count; ++j) {
+		// try to find the old key in the new key list
+		i = 0;
+		while (i < kbd_dev->key_count
+		    && key_codes[i] != kbd_dev->keys[j]) {
+			++i;
+		}
+		
+		if (i == count) {
+			// not found, i.e. the key was released
+			key = usbhid_parse_scancode(kbd_dev->keys[j]);
+			if (!usb_kbd_is_lock(key)) {
+				usb_kbd_repeat_stop(kbd_dev, key);
+			}
+			usb_kbd_push_ev(kbd_dev, KEY_RELEASE, key);
+			usb_log_debug2("Key released: %d\n", key);
+		} else {
+			// found, nothing happens
+		}
+	}
+	
+	/*
+	 * 1) Key presses
+	 */
+	for (i = 0; i < kbd_dev->key_count; ++i) {
+		// try to find the new key in the old key list
+		j = 0;
+		while (j < count && kbd_dev->keys[j] != key_codes[i]) { 
+			++j;
+		}
+		
+		if (j == count) {
+			// not found, i.e. new key pressed
+			key = usbhid_parse_scancode(key_codes[i]);
+			usb_log_debug2("Key pressed: %d (keycode: %d)\n", key,
+			    key_codes[i]);
+			usb_kbd_push_ev(kbd_dev, KEY_PRESS, key);
+			if (!usb_kbd_is_lock(key)) {
+				usb_kbd_repeat_start(kbd_dev, key);
+			}
+		} else {
+			// found, nothing happens
+		}
+	}
+	
+	memcpy(kbd_dev->keys, key_codes, count);
+
+	usb_log_debug("New stored keycodes: %s\n", 
+	    usb_debug_str_buffer(kbd_dev->keys, kbd_dev->key_count, 0));
+}
+
+/*----------------------------------------------------------------------------*/
+/* Callbacks for parser                                                       */
+/*----------------------------------------------------------------------------*/
+/**
+ * Callback function for the HID report parser.
+ *
+ * This function is called by the HID report parser with the parsed report.
+ * The parsed report is used to check if any events occured (key was pressed or
+ * released, modifier was pressed or released).
+ *
+ * @param key_codes Parsed keyboard report - codes of currently pressed keys 
+ *                  according to HID Usage Tables.
+ * @param count Number of key codes in report (size of the report).
+ * @param modifiers Bitmap of modifiers (Ctrl, Alt, Shift, GUI).
+ * @param arg User-specified argument. Expects pointer to the keyboard device
+ *            structure representing the keyboard.
+ *
+ * @sa usb_kbd_check_key_changes(), usb_kbd_check_modifier_changes()
+ */
+static void usb_kbd_process_keycodes(const uint8_t *key_codes, size_t count,
+    uint8_t modifiers, void *arg)
+{
+	if (arg == NULL) {
+		usb_log_warning("Missing argument in callback "
+		    "usbhid_process_keycodes().\n");
+		return;
+	}
+	
+	usb_kbd_t *kbd_dev = (usb_kbd_t *)arg;
+	assert(kbd_dev != NULL);
+
+	usb_log_debug("Got keys from parser: %s\n", 
+	    usb_debug_str_buffer(key_codes, count, 0));
+	
+	if (count != kbd_dev->key_count) {
+		usb_log_warning("Number of received keycodes (%d) differs from"
+		    " expected number (%d).\n", count, kbd_dev->key_count);
+		return;
+	}
+	
+	///usb_kbd_check_modifier_changes(kbd_dev, key_codes, count);
+	usb_kbd_check_key_changes(kbd_dev, key_codes, count);
+}
+
+/*----------------------------------------------------------------------------*/
+/* General kbd functions                                                      */
+/*----------------------------------------------------------------------------*/
+/**
+ * Processes data received from the device in form of report.
+ *
+ * This function uses the HID report parser to translate the data received from
+ * the device into generic USB HID key codes and into generic modifiers bitmap.
+ * The parser then calls the given callback (usb_kbd_process_keycodes()).
+ *
+ * @note Currently, only the boot protocol is supported.
+ *
+ * @param kbd_dev Keyboard device structure (must be initialized).
+ * @param buffer Data from the keyboard (i.e. the report).
+ * @param actual_size Size of the data from keyboard (report size) in bytes.
+ *
+ * @sa usb_kbd_process_keycodes(), usb_hid_boot_keyboard_input_report(),
+ *     usb_hid_parse_report().
+ */
+static void usb_kbd_process_data(usb_kbd_t *kbd_dev,
+                                    uint8_t *buffer, size_t actual_size)
+{
+	assert(kbd_dev->initialized == USB_KBD_STATUS_INITIALIZED);
+	assert(kbd_dev->parser != NULL);
+	
+	usb_hid_report_in_callbacks_t *callbacks =
+	    (usb_hid_report_in_callbacks_t *)malloc(
+	        sizeof(usb_hid_report_in_callbacks_t));
+	
+	callbacks->keyboard = usb_kbd_process_keycodes;
+
+	usb_log_debug("Calling usb_hid_parse_report() with "
+	    "buffer %s\n", usb_debug_str_buffer(buffer, actual_size, 0));
+	
+//	int rc = usb_hid_boot_keyboard_input_report(buffer, actual_size,
+//	    callbacks, kbd_dev);
+	usb_hid_report_path_t *path = usb_hid_report_path();
+	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
+	
+	int rc = usb_hid_parse_report(kbd_dev->parser, buffer,
+	    actual_size, path, USB_HID_PATH_COMPARE_STRICT, callbacks, kbd_dev);
+
+	usb_hid_report_path_free (path);
+	
+	if (rc != EOK) {
+		usb_log_warning("Error in usb_hid_boot_keyboard_input_report():"
+		    "%s\n", str_error(rc));
+	}
+}
+
+/*----------------------------------------------------------------------------*/
+/* HID/KBD structure manipulation                                             */
+/*----------------------------------------------------------------------------*/
+
+static void usb_kbd_mark_unusable(usb_kbd_t *kbd_dev)
+{
+	kbd_dev->initialized = USB_KBD_STATUS_TO_DESTROY;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/* API functions                                                              */
+/*----------------------------------------------------------------------------*/
+/**
+ * Creates a new USB/HID keyboard structure.
+ *
+ * The structure returned by this function is not initialized. Use 
+ * usb_kbd_init() to initialize it prior to polling.
+ *
+ * @return New uninitialized structure for representing a USB/HID keyboard or
+ *         NULL if not successful (memory error).
+ */
+usb_kbd_t *usb_kbd_new(void)
+{
+	usb_kbd_t *kbd_dev = 
+	    (usb_kbd_t *)malloc(sizeof(usb_kbd_t));
+
+	if (kbd_dev == NULL) {
+		usb_log_fatal("No memory!\n");
+		return NULL;
+	}
+	
+	memset(kbd_dev, 0, sizeof(usb_kbd_t));
+	
+	kbd_dev->parser = (usb_hid_report_parser_t *)(malloc(sizeof(
+	    usb_hid_report_parser_t)));
+	if (kbd_dev->parser == NULL) {
+		usb_log_fatal("No memory!\n");
+		free(kbd_dev);
+		return NULL;
+	}
+	
+	kbd_dev->console_phone = -1;
+	kbd_dev->initialized = USB_KBD_STATUS_UNINITIALIZED;
+	
+	return kbd_dev;
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Initialization of the USB/HID keyboard structure.
+ *
+ * This functions initializes required structures from the device's descriptors.
+ *
+ * During initialization, the keyboard is switched into boot protocol, the idle
+ * rate is set to 0 (infinity), resulting in the keyboard only reporting event
+ * when a key is pressed or released. Finally, the LED lights are turned on 
+ * according to the default setup of lock keys.
+ *
+ * @note By default, the keyboards is initialized with Num Lock turned on and 
+ *       other locks turned off.
+ *
+ * @param kbd_dev Keyboard device structure to be initialized.
+ * @param dev DDF device structure of the keyboard.
+ *
+ * @retval EOK if successful.
+ * @retval EINVAL if some parameter is not given.
+ * @return Other value inherited from function usbhid_dev_init().
+ */
+int usb_kbd_init(usb_kbd_t *kbd_dev, usb_device_t *dev)
+{
+	int rc;
+	
+	usb_log_debug("Initializing HID/KBD structure...\n");
+	
+	if (kbd_dev == NULL) {
+		usb_log_error("Failed to init keyboard structure: no structure"
+		    " given.\n");
+		return EINVAL;
+	}
+	
+	if (dev == NULL) {
+		usb_log_error("Failed to init keyboard structure: no USB device"
+		    " given.\n");
+		return EINVAL;
+	}
+	
+	if (kbd_dev->initialized == USB_KBD_STATUS_INITIALIZED) {
+		usb_log_warning("Keyboard structure already initialized.\n");
+		return EINVAL;
+	}
+	
+	/* TODO: does not work! */
+	if (!dev->pipes[USB_KBD_POLL_EP_NO].present) {
+		usb_log_warning("Required endpoint not found - probably not "
+		    "a supported device.\n");
+		return ENOTSUP;
+	}
+	
+	/* The USB device should already be initialized, save it in structure */
+	kbd_dev->usb_dev = dev;
+	
+	/* Initialize the report parser. */
+	rc = usb_hid_parser_init(kbd_dev->parser);
+	if (rc != EOK) {
+		usb_log_error("Failed to initialize report parser.\n");
+		return rc;
+	}
+	
+	/* Get the report descriptor and parse it. */
+	rc = usb_hid_process_report_descriptor(kbd_dev->usb_dev, 
+	    kbd_dev->parser);
+	if (rc != EOK) {
+		usb_log_warning("Could not process report descriptor, "
+		    "falling back to boot protocol.\n");
+		rc = usb_hid_parse_report_descriptor(kbd_dev->parser, 
+		    BOOT_REPORT_DESCRIPTOR, BOOT_REPORT_DESCRIPTOR_SIZE);
+		if (rc != EOK) {
+			usb_log_error("Failed to parse boot report descriptor:"
+			    " %s.\n", str_error(rc));
+			return rc;
+		}
+		
+		rc = usbhid_req_set_protocol(&kbd_dev->usb_dev->ctrl_pipe, 
+		    kbd_dev->usb_dev->interface_no, USB_HID_PROTOCOL_BOOT);
+		
+		if (rc != EOK) {
+			usb_log_warning("Failed to set boot protocol to the "
+			    "device: %s\n", str_error(rc));
+			return rc;
+		}
+	}
+	
+	/*
+	 * TODO: make more general
+	 */
+	usb_hid_report_path_t *path = usb_hid_report_path();
+	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
+	kbd_dev->key_count = usb_hid_report_input_length(
+	    kbd_dev->parser, path, USB_HID_PATH_COMPARE_STRICT);
+	usb_hid_report_path_free (path);
+	
+	usb_log_debug("Size of the input report: %zu\n", kbd_dev->key_count);
+	
+	kbd_dev->keys = (uint8_t *)calloc(
+	    kbd_dev->key_count, sizeof(uint8_t));
+	
+	if (kbd_dev->keys == NULL) {
+		usb_log_fatal("No memory!\n");
+		return ENOMEM;
+	}
+	
+	kbd_dev->modifiers = 0;
+	kbd_dev->mods = DEFAULT_ACTIVE_MODS;
+	kbd_dev->lock_keys = 0;
+	
+	kbd_dev->repeat.key_new = 0;
+	kbd_dev->repeat.key_repeated = 0;
+	kbd_dev->repeat.delay_before = DEFAULT_DELAY_BEFORE_FIRST_REPEAT;
+	kbd_dev->repeat.delay_between = DEFAULT_REPEAT_DELAY;
+	
+	kbd_dev->repeat_mtx = (fibril_mutex_t *)(
+	    malloc(sizeof(fibril_mutex_t)));
+	if (kbd_dev->repeat_mtx == NULL) {
+		usb_log_fatal("No memory!\n");
+		free(kbd_dev->keys);
+		return ENOMEM;
+	}
+	
+	fibril_mutex_initialize(kbd_dev->repeat_mtx);
+	
+	/*
+	 * Set LEDs according to initial setup.
+	 * Set Idle rate
+	 */
+	usb_kbd_set_led(kbd_dev);
+	
+	usbhid_req_set_idle(&kbd_dev->usb_dev->ctrl_pipe, 
+	    kbd_dev->usb_dev->interface_no, IDLE_RATE);
+	
+	kbd_dev->initialized = USB_KBD_STATUS_INITIALIZED;
+	usb_log_debug("HID/KBD device structure initialized.\n");
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+bool usb_kbd_polling_callback(usb_device_t *dev, uint8_t *buffer,
+     size_t buffer_size, void *arg)
+{
+	if (dev == NULL || buffer == NULL || arg == NULL) {
+		// do not continue polling (???)
+		return false;
+	}
+	
+	usb_kbd_t *kbd_dev = (usb_kbd_t *)arg;
+	
+	// TODO: add return value from this function
+	usb_kbd_process_data(kbd_dev, buffer, buffer_size);
+	
+	return true;
+}
+
+/*----------------------------------------------------------------------------*/
+
+void usb_kbd_polling_ended_callback(usb_device_t *dev, bool reason, 
+     void *arg)
+{
+	if (dev == NULL || arg == NULL) {
+		return;
+	}
+	
+	usb_kbd_t *kbd = (usb_kbd_t *)arg;
+	
+	usb_kbd_mark_unusable(kbd);
+}
+
+/*----------------------------------------------------------------------------*/
+
+int usb_kbd_is_initialized(const usb_kbd_t *kbd_dev)
+{
+	return (kbd_dev->initialized == USB_KBD_STATUS_INITIALIZED);
+}
+
+/*----------------------------------------------------------------------------*/
+
+int usb_kbd_is_ready_to_destroy(const usb_kbd_t *kbd_dev)
+{
+	return (kbd_dev->initialized == USB_KBD_STATUS_TO_DESTROY);
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Properly destroys the USB/HID keyboard structure.
+ *
+ * @param kbd_dev Pointer to the structure to be destroyed.
+ */
+void usb_kbd_free(usb_kbd_t **kbd_dev)
+{
+	if (kbd_dev == NULL || *kbd_dev == NULL) {
+		return;
+	}
+	
+	// hangup phone to the console
+	async_hangup((*kbd_dev)->console_phone);
+	
+//	if ((*kbd_dev)->hid_dev != NULL) {
+//		usbhid_dev_free(&(*kbd_dev)->hid_dev);
+//		assert((*kbd_dev)->hid_dev == NULL);
+//	}
+	
+	if ((*kbd_dev)->repeat_mtx != NULL) {
+		/* TODO: replace by some check and wait */
+		assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx));
+		free((*kbd_dev)->repeat_mtx);
+	}
+	
+	// destroy the parser
+	if ((*kbd_dev)->parser != NULL) {
+		usb_hid_free_report_parser((*kbd_dev)->parser);
+	}
+	
+	/* TODO: what about the USB device structure?? */
+
+	free(*kbd_dev);
+	*kbd_dev = NULL;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/usbkbd/kbddev.h
===================================================================
--- uspace/drv/usbkbd/kbddev.h	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
+++ uspace/drv/usbkbd/kbddev.h	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/** @file
+ * USB HID keyboard device structure and API.
+ */
+
+#ifndef USB_KBDDEV_H_
+#define USB_KBDDEV_H_
+
+#include <stdint.h>
+
+#include <fibril_synch.h>
+
+#include <usb/classes/hid.h>
+#include <usb/classes/hidparser.h>
+#include <ddf/driver.h>
+#include <usb/pipes.h>
+#include <usb/devdrv.h>
+
+#include "kbdrepeat.h"
+
+/*----------------------------------------------------------------------------*/
+/**
+ * USB/HID keyboard device type.
+ *
+ * Holds a reference to generic USB/HID device structure and keyboard-specific
+ * data, such as currently pressed keys, modifiers and lock keys.
+ *
+ * Also holds a IPC phone to the console (since there is now no other way to 
+ * communicate with it).
+ *
+ * @note Storing active lock keys in this structure results in their setting
+ *       being device-specific.
+ */
+typedef struct usb_kbd_t {
+	/** Structure holding generic USB device information. */
+	//usbhid_dev_t *hid_dev;
+	usb_device_t *usb_dev;
+	
+	/** Currently pressed keys (not translated to key codes). */
+	uint8_t *keys;
+	/** Count of stored keys (i.e. number of keys in the report). */
+	size_t key_count;
+	/** Currently pressed modifiers (bitmap). */
+	uint8_t modifiers;
+	
+	/** Currently active modifiers including locks. Sent to the console. */
+	unsigned mods;
+	
+	/** Currently active lock keys. */
+	unsigned lock_keys;
+	
+	/** IPC phone to the console device (for sending key events). */
+	int console_phone;
+	
+	/** Information for auto-repeat of keys. */
+	usb_kbd_repeat_t repeat;
+	
+	/** Mutex for accessing the information about auto-repeat. */
+	fibril_mutex_t *repeat_mtx;
+	
+	/** Report descriptor. */
+	uint8_t *report_desc;
+
+	/** Report descriptor size. */
+	size_t report_desc_size;
+
+	/** HID Report parser. */
+	usb_hid_report_parser_t *parser;
+	
+	/** State of the structure (for checking before use). 
+	 * 
+	 * 0 - not initialized
+	 * 1 - initialized
+	 * -1 - ready for destroying
+	 */
+	int initialized;
+} usb_kbd_t;
+
+/*----------------------------------------------------------------------------*/
+
+enum {
+	USB_KBD_POLL_EP_NO = 0,
+	USB_KBD_POLL_EP_COUNT = 1
+};
+
+usb_endpoint_description_t *usb_kbd_endpoints[USB_KBD_POLL_EP_COUNT + 1];
+
+ddf_dev_ops_t keyboard_ops;
+
+/*----------------------------------------------------------------------------*/
+
+usb_kbd_t *usb_kbd_new(void);
+
+int usb_kbd_init(usb_kbd_t *kbd_dev, usb_device_t *dev);
+
+bool usb_kbd_polling_callback(usb_device_t *dev, uint8_t *buffer,
+     size_t buffer_size, void *arg);
+
+void usb_kbd_polling_ended_callback(usb_device_t *dev, bool reason, 
+     void *arg);
+
+int usb_kbd_is_initialized(const usb_kbd_t *kbd_dev);
+
+int usb_kbd_is_ready_to_destroy(const usb_kbd_t *kbd_dev);
+
+void usb_kbd_free(usb_kbd_t **kbd_dev);
+
+void usb_kbd_push_ev(usb_kbd_t *kbd_dev, int type, unsigned int key);
+
+#endif /* USB_KBDDEV_H_ */
+
+/**
+ * @}
+ */
Index: uspace/drv/usbkbd/kbdrepeat.c
===================================================================
--- uspace/drv/usbkbd/kbdrepeat.c	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
+++ uspace/drv/usbkbd/kbdrepeat.c	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/**
+ * @file
+ * USB HID keyboard autorepeat facilities
+ */
+
+#include <fibril_synch.h>
+#include <io/keycode.h>
+#include <io/console.h>
+#include <errno.h>
+
+#include <usb/debug.h>
+
+#include "kbdrepeat.h"
+#include "kbddev.h"
+
+
+/** Delay between auto-repeat state checks when no key is being repeated. */
+static unsigned int CHECK_DELAY = 10000;
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Main loop handling the auto-repeat of keys.
+ *
+ * This functions periodically checks if there is some key to be auto-repeated.
+ *
+ * If a new key is to be repeated, it uses the delay before first repeat stored
+ * in the keyboard structure to wait until the key has to start repeating.
+ *
+ * If the same key is still pressed, it uses the delay between repeats stored
+ * in the keyboard structure to wait until the key should be repeated.
+ * 
+ * If the currently repeated key is not pressed any more (
+ * usb_kbd_repeat_stop() was called), it stops repeating it and starts 
+ * checking again.
+ *
+ * @note For accessing the keyboard device auto-repeat information a fibril
+ *       mutex (repeat_mtx) from the @a kbd structure is used.
+ * 
+ * @param kbd Keyboard device structure.
+ */
+static void usb_kbd_repeat_loop(usb_kbd_t *kbd)
+{
+	unsigned int delay = 0;
+	
+	usb_log_debug("Starting autorepeat loop.\n");
+
+	while (true) {
+		// check if the kbd structure is usable
+		if (!usb_kbd_is_initialized(kbd)) {
+			if (usb_kbd_is_ready_to_destroy(kbd)) {
+				usb_kbd_free(&kbd);
+				assert(kbd == NULL);
+			}
+			return;
+		}
+		
+		fibril_mutex_lock(kbd->repeat_mtx);
+
+		if (kbd->repeat.key_new > 0) {
+			if (kbd->repeat.key_new == kbd->repeat.key_repeated) {
+				usb_log_debug2("Repeating key: %u.\n", 
+				    kbd->repeat.key_repeated);
+				usb_kbd_push_ev(kbd, KEY_PRESS, 
+				    kbd->repeat.key_repeated);
+				delay = kbd->repeat.delay_between;
+			} else {
+				usb_log_debug("New key to repeat: %u.\n", 
+				    kbd->repeat.key_new);
+				kbd->repeat.key_repeated = kbd->repeat.key_new;
+				delay = kbd->repeat.delay_before;
+			}
+		} else {
+			if (kbd->repeat.key_repeated > 0) {
+				usb_log_debug("Stopping to repeat key: %u.\n", 
+				    kbd->repeat.key_repeated);
+				kbd->repeat.key_repeated = 0;
+			}
+			delay = CHECK_DELAY;
+		}
+		fibril_mutex_unlock(kbd->repeat_mtx);
+		
+		async_usleep(delay);
+	}
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Main routine to be executed by a fibril for handling auto-repeat.
+ *
+ * Starts the loop for checking changes in auto-repeat.
+ * 
+ * @param arg User-specified argument. Expects pointer to the keyboard device
+ *            structure representing the keyboard.
+ *
+ * @retval EOK if the routine has finished.
+ * @retval EINVAL if no argument is supplied.
+ */
+int usb_kbd_repeat_fibril(void *arg)
+{
+	usb_log_debug("Autorepeat fibril spawned.\n");
+	
+	if (arg == NULL) {
+		usb_log_error("No device!\n");
+		return EINVAL;
+	}
+	
+	usb_kbd_t *kbd = (usb_kbd_t *)arg;
+	
+	usb_kbd_repeat_loop(kbd);
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Start repeating particular key.
+ *
+ * @note Only one key is repeated at any time, so calling this function 
+ *       effectively cancels auto-repeat of the current repeated key (if any)
+ *       and 'schedules' another key for auto-repeat.
+ *
+ * @param kbd Keyboard device structure.
+ * @param key Key to start repeating.
+ */
+void usb_kbd_repeat_start(usb_kbd_t *kbd, unsigned int key)
+{
+	fibril_mutex_lock(kbd->repeat_mtx);
+	kbd->repeat.key_new = key;
+	fibril_mutex_unlock(kbd->repeat_mtx);
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Stop repeating particular key.
+ *
+ * @note Only one key is repeated at any time, but this function may be called
+ *       even with key that is not currently repeated (in that case nothing 
+ *       happens).
+ *
+ * @param kbd Keyboard device structure.
+ * @param key Key to stop repeating.
+ */
+void usb_kbd_repeat_stop(usb_kbd_t *kbd, unsigned int key)
+{
+	fibril_mutex_lock(kbd->repeat_mtx);
+	if (key == kbd->repeat.key_new) {
+		kbd->repeat.key_new = 0;
+	}
+	fibril_mutex_unlock(kbd->repeat_mtx);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/usbkbd/kbdrepeat.h
===================================================================
--- uspace/drv/usbkbd/kbdrepeat.h	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
+++ uspace/drv/usbkbd/kbdrepeat.h	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/** @file
+ * USB HID keyboard autorepeat facilities
+ */
+
+#ifndef USB_KBDREPEAT_H_
+#define USB_KBDREPEAT_H_
+
+struct usb_kbd_t;
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Structure for keeping information needed for auto-repeat of keys.
+ */
+typedef struct {
+	/** Last pressed key. */
+	unsigned int key_new;
+	/** Key to be repeated. */
+	unsigned int key_repeated;
+	/** Delay before first repeat in microseconds. */
+	unsigned int delay_before;
+	/** Delay between repeats in microseconds. */
+	unsigned int delay_between;
+} usb_kbd_repeat_t;
+
+/*----------------------------------------------------------------------------*/
+
+int usb_kbd_repeat_fibril(void *arg);
+
+void usb_kbd_repeat_start(struct usb_kbd_t *kbd, unsigned int key);
+
+void usb_kbd_repeat_stop(struct usb_kbd_t *kbd, unsigned int key);
+
+#endif /* USB_KBDREPEAT_H_ */
+
+/**
+ * @}
+ */
Index: uspace/drv/usbkbd/layout.h
===================================================================
--- uspace/drv/usbkbd/layout.h	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
+++ uspace/drv/usbkbd/layout.h	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2009 Jiri Svoboda
+ * Copyright (c) 2011 Lubos Slovak 
+ * (copied from /uspace/srv/hid/kbd/include/layout.h)
+ * 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 drvusbhid
+ * @{
+ */
+/** @file
+ * Keyboard layout.
+ */
+
+#ifndef USB_KBD_LAYOUT_H_
+#define USB_KBD_LAYOUT_H_
+
+#include <sys/types.h>
+#include <io/console.h>
+
+typedef struct {
+	void (*reset)(void);
+	wchar_t (*parse_ev)(console_event_t *);
+} layout_op_t;
+
+extern layout_op_t us_qwerty_op;
+extern layout_op_t us_dvorak_op;
+extern layout_op_t cz_op;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/drv/usbkbd/main.c
===================================================================
--- uspace/drv/usbkbd/main.c	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
+++ uspace/drv/usbkbd/main.c	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2010 Vojtech Horky
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/**
+ * @file
+ * Main routines of USB HID driver.
+ */
+
+#include <ddf/driver.h>
+#include <usb/debug.h>
+#include <errno.h>
+#include <str_error.h>
+
+#include <usb/devdrv.h>
+
+#include "kbddev.h"
+#include "kbdrepeat.h"
+
+/*----------------------------------------------------------------------------*/
+
+#define NAME "usbkbd"
+
+/**
+ * Function for adding a new device of type USB/HID/keyboard.
+ *
+ * This functions initializes required structures from the device's descriptors
+ * and starts new fibril for polling the keyboard for events and another one for
+ * handling auto-repeat of keys.
+ *
+ * During initialization, the keyboard is switched into boot protocol, the idle
+ * rate is set to 0 (infinity), resulting in the keyboard only reporting event
+ * when a key is pressed or released. Finally, the LED lights are turned on 
+ * according to the default setup of lock keys.
+ *
+ * @note By default, the keyboards is initialized with Num Lock turned on and 
+ *       other locks turned off.
+ * @note Currently supports only boot-protocol keyboards.
+ *
+ * @param dev Device to add.
+ *
+ * @retval EOK if successful.
+ * @retval ENOMEM if there
+ * @return Other error code inherited from one of functions usb_kbd_init(),
+ *         ddf_fun_bind() and ddf_fun_add_to_class().
+ *
+ * @sa usb_kbd_fibril(), usb_kbd_repeat_fibril()
+ */
+static int usbhid_try_add_device(usb_device_t *dev)
+{
+	/* Create the function exposed under /dev/devices. */
+	ddf_fun_t *kbd_fun = ddf_fun_create(dev->ddf_dev, fun_exposed, 
+	    "keyboard");
+	if (kbd_fun == NULL) {
+		usb_log_error("Could not create DDF function node.\n");
+		return ENOMEM;
+	}
+	
+	/* 
+	 * Initialize device (get and process descriptors, get address, etc.)
+	 */
+	usb_log_debug("Initializing USB/HID KBD device...\n");
+	
+	usb_kbd_t *kbd_dev = usb_kbd_new();
+	if (kbd_dev == NULL) {
+		usb_log_error("Error while creating USB/HID KBD device "
+		    "structure.\n");
+		ddf_fun_destroy(kbd_fun);
+		return ENOMEM;  // TODO: some other code??
+	}
+	
+	int rc = usb_kbd_init(kbd_dev, dev);
+	
+	if (rc != EOK) {
+		usb_log_error("Failed to initialize USB/HID KBD device.\n");
+		ddf_fun_destroy(kbd_fun);
+		usb_kbd_free(&kbd_dev);
+		return rc;
+	}	
+	
+	usb_log_debug("USB/HID KBD device structure initialized.\n");
+	
+	/*
+	 * Store the initialized keyboard device and keyboard ops
+	 * to the DDF function.
+	 */
+	kbd_fun->driver_data = kbd_dev;
+	kbd_fun->ops = &keyboard_ops;
+
+	rc = ddf_fun_bind(kbd_fun);
+	if (rc != EOK) {
+		usb_log_error("Could not bind DDF function: %s.\n",
+		    str_error(rc));
+		// TODO: Can / should I destroy the DDF function?
+		ddf_fun_destroy(kbd_fun);
+		usb_kbd_free(&kbd_dev);
+		return rc;
+	}
+	
+	rc = ddf_fun_add_to_class(kbd_fun, "keyboard");
+	if (rc != EOK) {
+		usb_log_error(
+		    "Could not add DDF function to class 'keyboard': %s.\n",
+		    str_error(rc));
+		// TODO: Can / should I destroy the DDF function?
+		ddf_fun_destroy(kbd_fun);
+		usb_kbd_free(&kbd_dev);
+		return rc;
+	}
+	
+	/*
+	 * Create new fibril for handling this keyboard
+	 */
+	//fid_t fid = fibril_create(usb_kbd_fibril, kbd_dev);
+	
+	/* Start automated polling function.
+	 * This will create a separate fibril that will query the device
+	 * for the data continuously 
+	 */
+       rc = usb_device_auto_poll(dev,
+	   /* Index of the polling pipe. */
+	   USB_KBD_POLL_EP_NO,
+	   /* Callback when data arrives. */
+	   usb_kbd_polling_callback,
+	   /* How much data to request. */
+	   dev->pipes[USB_KBD_POLL_EP_NO].pipe->max_packet_size,
+	   /* Callback when the polling ends. */
+	   usb_kbd_polling_ended_callback,
+	   /* Custom argument. */
+	   kbd_dev);
+	
+	
+	if (rc != EOK) {
+		usb_log_error("Failed to start polling fibril for `%s'.\n",
+		    dev->ddf_dev->name);
+		return rc;
+	}
+	//fibril_add_ready(fid);
+	
+	/*
+	 * Create new fibril for auto-repeat
+	 */
+	fid_t fid = fibril_create(usb_kbd_repeat_fibril, kbd_dev);
+	if (fid == 0) {
+		usb_log_error("Failed to start fibril for KBD auto-repeat");
+		return ENOMEM;
+	}
+	fibril_add_ready(fid);
+
+	(void)keyboard_ops;
+
+	/*
+	 * Hurrah, device is initialized.
+	 */
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Callback for passing a new device to the driver.
+ *
+ * @note Currently, only boot-protocol keyboards are supported by this driver.
+ *
+ * @param dev Structure representing the new device.
+ *
+ * @retval EOK if successful. 
+ * @retval EREFUSED if the device is not supported.
+ */
+static int usbhid_add_device(usb_device_t *dev)
+{
+	usb_log_debug("usbhid_add_device()\n");
+	
+	if (dev->interface_no < 0) {
+		usb_log_warning("Device is not a supported keyboard.\n");
+		usb_log_error("Failed to add HID device: endpoint not found."
+		    "\n");
+		return ENOTSUP;
+	}
+	
+	int rc = usbhid_try_add_device(dev);
+	
+	if (rc != EOK) {
+		usb_log_warning("Device is not a supported keyboard.\n");
+		usb_log_error("Failed to add HID device: %s.\n",
+		    str_error(rc));
+		return rc;
+	}
+	
+	usb_log_info("Keyboard `%s' ready to use.\n", dev->ddf_dev->name);
+
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+/* Currently, the framework supports only device adding. Once the framework
+ * supports unplug, more callbacks will be added. */
+static usb_driver_ops_t usbhid_driver_ops = {
+        .add_device = usbhid_add_device,
+};
+
+
+/* The driver itself. */
+static usb_driver_t usbhid_driver = {
+        .name = NAME,
+        .ops = &usbhid_driver_ops,
+        .endpoints = usb_kbd_endpoints
+};
+
+/*----------------------------------------------------------------------------*/
+
+//static driver_ops_t kbd_driver_ops = {
+//	.add_device = usbhid_add_device,
+//};
+
+///*----------------------------------------------------------------------------*/
+
+//static driver_t kbd_driver = {
+//	.name = NAME,
+//	.driver_ops = &kbd_driver_ops
+//};
+
+/*----------------------------------------------------------------------------*/
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS USB HID driver.\n");
+
+	usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
+
+	return usb_driver_main(&usbhid_driver);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/usbkbd/usbkbd.ma
===================================================================
--- uspace/drv/usbkbd/usbkbd.ma	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
+++ uspace/drv/usbkbd/usbkbd.ma	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -0,0 +1,2 @@
+100 usb&interface&class=HID&subclass=0x01&protocol=0x01
+10 usb&interface&class=HID
Index: uspace/drv/usbmid/main.c
===================================================================
--- uspace/drv/usbmid/main.c	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ uspace/drv/usbmid/main.c	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -106,5 +106,5 @@
 	printf(NAME ": USB multi interface device driver.\n");
 
-	usb_log_enable(USB_LOG_LEVEL_INFO, NAME);
+	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
 	return ddf_driver_main(&mid_driver);
 }
Index: uspace/drv/usbmouse/main.c
===================================================================
--- uspace/drv/usbmouse/main.c	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ uspace/drv/usbmouse/main.c	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -90,5 +90,5 @@
 int main(int argc, char *argv[])
 {
-	usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
+	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
 
 	return usb_driver_main(&mouse_driver);
Index: uspace/drv/vhc/hcd.c
===================================================================
--- uspace/drv/vhc/hcd.c	(revision d8421c4c75ad20af382a91d8655ed77628c9488c)
+++ uspace/drv/vhc/hcd.c	(revision da3dafc9675be90ab18a70cd3480c12b7e2a7fab)
@@ -122,5 +122,5 @@
 	//sleep(5);
 
-	usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
+	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
 
 	printf(NAME ": virtual USB host controller driver.\n");
