Index: uspace/drv/isa/isa.c
===================================================================
--- uspace/drv/isa/isa.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/isa/isa.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -83,5 +83,5 @@
 static bool isa_enable_fun_interrupt(ddf_fun_t *fnode)
 {
-	// TODO
+	/* TODO */
 
 	return false;
Index: uspace/drv/ohci/Makefile
===================================================================
--- uspace/drv/ohci/Makefile	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/ohci/Makefile	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -34,5 +34,7 @@
 SOURCES = \
 	batch.c \
+	endpoint_list.c \
 	hc.c \
+	hcd_endpoint.c \
 	iface.c \
 	main.c \
@@ -40,5 +42,4 @@
 	pci.c \
 	root_hub.c \
-	transfer_list.c \
 	hw_struct/endpoint_descriptor.c \
 	hw_struct/transfer_descriptor.c
Index: uspace/drv/ohci/batch.c
===================================================================
--- uspace/drv/ohci/batch.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/ohci/batch.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -39,20 +39,38 @@
 
 #include "batch.h"
+#include "hcd_endpoint.h"
 #include "utils/malloc32.h"
 #include "hw_struct/endpoint_descriptor.h"
 #include "hw_struct/transfer_descriptor.h"
 
-typedef struct ohci_batch {
+typedef struct ohci_transfer_batch {
 	ed_t *ed;
-	td_t *tds;
+	td_t **tds;
 	size_t td_count;
-} ohci_batch_t;
-
+	size_t leave_td;
+	char *device_buffer;
+} ohci_transfer_batch_t;
+
+static void ohci_transfer_batch_dispose(void *ohci_batch)
+{
+	ohci_transfer_batch_t *instance = ohci_batch;
+	if (!instance)
+		return;
+	free32(instance->device_buffer);
+	unsigned i = 0;
+	if (instance->tds) {
+		for (; i< instance->td_count; ++i) {
+			if (i != instance->leave_td)
+				free32(instance->tds[i]);
+		}
+		free(instance->tds);
+	}
+	free(instance);
+}
+/*----------------------------------------------------------------------------*/
 static void batch_control(usb_transfer_batch_t *instance,
     usb_direction_t data_dir, usb_direction_t status_dir);
-static void batch_call_in_and_dispose(usb_transfer_batch_t *instance);
-static void batch_call_out_and_dispose(usb_transfer_batch_t *instance);
-
-#define DEFAULT_ERROR_COUNT 3
+static void batch_data(usb_transfer_batch_t *instance);
+/*----------------------------------------------------------------------------*/
 usb_transfer_batch_t * batch_get(ddf_fun_t *fun, endpoint_t *ep,
     char *buffer, size_t buffer_size, char* setup_buffer, size_t setup_size,
@@ -64,5 +82,5 @@
                 usb_log_error(message); \
                 if (instance) { \
-                        batch_dispose(instance); \
+                        usb_transfer_batch_dispose(instance); \
                 } \
                 return NULL; \
@@ -72,17 +90,16 @@
 	CHECK_NULL_DISPOSE_RETURN(instance,
 	    "Failed to allocate batch instance.\n");
-	usb_target_t target =
-	    { .address = ep->address, .endpoint = ep->endpoint };
-	usb_transfer_batch_init(instance, target, ep->transfer_type, ep->speed,
-	    ep->max_packet_size, buffer, NULL, buffer_size, NULL, setup_size,
-	    func_in, func_out, arg, fun, ep, NULL);
-
-	ohci_batch_t *data = malloc(sizeof(ohci_batch_t));
+	usb_transfer_batch_init(instance, ep, buffer, NULL, buffer_size,
+	    NULL, setup_size, func_in, func_out, arg, fun, NULL,
+	    ohci_transfer_batch_dispose);
+
+	hcd_endpoint_t *hcd_ep = hcd_endpoint_get(ep);
+	assert(hcd_ep);
+
+	ohci_transfer_batch_t *data = calloc(sizeof(ohci_transfer_batch_t), 1);
 	CHECK_NULL_DISPOSE_RETURN(data, "Failed to allocate batch data.\n");
-	bzero(data, sizeof(ohci_batch_t));
 	instance->private_data = data;
 
-	/* we needs + 1 transfer descriptor as the last one won't be executed */
-	data->td_count = 1 +
+	data->td_count =
 	    ((buffer_size + OHCI_TD_MAX_TRANSFER - 1) / OHCI_TD_MAX_TRANSFER);
 	if (ep->transfer_type == USB_TRANSFER_CONTROL) {
@@ -90,23 +107,26 @@
 	}
 
-	data->tds = malloc32(sizeof(td_t) * data->td_count);
+	/* we need one extra place for td that is currently assigned to hcd_ep*/
+	data->tds = calloc(sizeof(td_t*), data->td_count + 1);
 	CHECK_NULL_DISPOSE_RETURN(data->tds,
 	    "Failed to allocate transfer descriptors.\n");
-	bzero(data->tds, sizeof(td_t) * data->td_count);
-
-	data->ed = malloc32(sizeof(ed_t));
-	CHECK_NULL_DISPOSE_RETURN(data->ed,
-	    "Failed to allocate endpoint descriptor.\n");
-
-        if (buffer_size > 0) {
-                instance->transport_buffer = malloc32(buffer_size);
-                CHECK_NULL_DISPOSE_RETURN(instance->transport_buffer,
+
+	data->tds[0] = hcd_ep->td;
+	data->leave_td = 0;
+	unsigned i = 1;
+	for (; i <= data->td_count; ++i) {
+		data->tds[i] = malloc32(sizeof(td_t));
+		CHECK_NULL_DISPOSE_RETURN(data->tds[i],
+		    "Failed to allocate TD %d.\n", i );
+	}
+
+	data->ed = hcd_ep->ed;
+
+        if (setup_size + buffer_size > 0) {
+		data->device_buffer = malloc32(setup_size + buffer_size);
+                CHECK_NULL_DISPOSE_RETURN(data->device_buffer,
                     "Failed to allocate device accessible buffer.\n");
-        }
-
-        if (setup_size > 0) {
-                instance->setup_buffer = malloc32(setup_size);
-                CHECK_NULL_DISPOSE_RETURN(instance->setup_buffer,
-                    "Failed to allocate device accessible setup buffer.\n");
+		instance->setup_buffer = data->device_buffer;
+		instance->data_buffer = data->device_buffer + setup_size;
                 memcpy(instance->setup_buffer, setup_buffer, setup_size);
         }
@@ -115,49 +135,66 @@
 }
 /*----------------------------------------------------------------------------*/
-void batch_dispose(usb_transfer_batch_t *instance)
-{
-	assert(instance);
-	ohci_batch_t *data = instance->private_data;
-	assert(data);
-	free32(data->ed);
-	free32(data->tds);
-	free32(instance->setup_buffer);
-	free32(instance->transport_buffer);
-	free(data);
-	free(instance);
-}
-/*----------------------------------------------------------------------------*/
 bool batch_is_complete(usb_transfer_batch_t *instance)
 {
 	assert(instance);
-	ohci_batch_t *data = instance->private_data;
-	assert(data);
-	size_t tds = data->td_count - 1;
-	usb_log_debug2("Batch(%p) checking %d td(s) for completion.\n",
+	ohci_transfer_batch_t *data = instance->private_data;
+	assert(data);
+	size_t tds = data->td_count;
+	usb_log_debug("Batch(%p) checking %d td(s) for completion.\n",
 	    instance, tds);
+	usb_log_debug("ED: %x:%x:%x:%x.\n",
+	    data->ed->status, data->ed->td_head, data->ed->td_tail,
+	    data->ed->next);
 	size_t i = 0;
 	for (; i < tds; ++i) {
-		if (!td_is_finished(&data->tds[i]))
+		assert(data->tds[i] != NULL);
+		usb_log_debug("TD %d: %x:%x:%x:%x.\n", i,
+		    data->tds[i]->status, data->tds[i]->cbp, data->tds[i]->next,
+		    data->tds[i]->be);
+		if (!td_is_finished(data->tds[i])) {
 			return false;
-		instance->error = td_error(&data->tds[i]);
+		}
+		instance->error = td_error(data->tds[i]);
 		/* FIXME: calculate real transfered size */
 		instance->transfered_size = instance->buffer_size;
 		if (instance->error != EOK) {
 			usb_log_debug("Batch(%p) found error TD(%d):%x.\n",
-			    instance, i, data->tds[i].status);
-			return true;
-//			endpoint_toggle_set(instance->ep,
+			    instance, i, data->tds[i]->status);
+			/* Make sure TD queue is empty (one TD),
+			 * ED should be marked as halted */
+			data->ed->td_tail =
+			    (data->ed->td_head & ED_TDTAIL_PTR_MASK);
+			++i;
+			break;
 		}
 	}
+	data->leave_td = i;
+	assert(data->leave_td <= data->td_count);
+	hcd_endpoint_t *hcd_ep = hcd_endpoint_get(instance->ep);
+	assert(hcd_ep);
+	hcd_ep->td = data->tds[i];
+	/* Clear possible ED HALT */
+	data->ed->td_head &= ~ED_TDHEAD_HALTED_FLAG;
+	uint32_t pa = addr_to_phys(hcd_ep->td);
+	assert(pa == (data->ed->td_head & ED_TDHEAD_PTR_MASK));
+	assert(pa == (data->ed->td_tail & ED_TDTAIL_PTR_MASK));
+
 	return true;
 }
 /*----------------------------------------------------------------------------*/
+void batch_commit(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	ohci_transfer_batch_t *data = instance->private_data;
+	assert(data);
+	ed_set_end_td(data->ed, data->tds[data->td_count]);
+}
+/*----------------------------------------------------------------------------*/
 void batch_control_write(usb_transfer_batch_t *instance)
 {
 	assert(instance);
 	/* We are data out, we are supposed to provide data */
-	memcpy(instance->transport_buffer, instance->buffer,
-	    instance->buffer_size);
-	instance->next_step = batch_call_out_and_dispose;
+	memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
+	instance->next_step = usb_transfer_batch_call_out_and_dispose;
 	batch_control(instance, USB_DIRECTION_OUT, USB_DIRECTION_IN);
 	usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
@@ -167,5 +204,5 @@
 {
 	assert(instance);
-	instance->next_step = batch_call_in_and_dispose;
+	instance->next_step = usb_transfer_batch_call_in_and_dispose;
 	batch_control(instance, USB_DIRECTION_IN, USB_DIRECTION_OUT);
 	usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance);
@@ -175,7 +212,6 @@
 {
 	assert(instance);
-	assert(instance->direction == USB_DIRECTION_IN);
-	instance->next_step = batch_call_in_and_dispose;
-	/* TODO: implement */
+	instance->next_step = usb_transfer_batch_call_in_and_dispose;
+	batch_data(instance);
 	usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance);
 }
@@ -184,10 +220,8 @@
 {
 	assert(instance);
-	assert(instance->direction == USB_DIRECTION_OUT);
 	/* We are data out, we are supposed to provide data */
-	memcpy(instance->transport_buffer, instance->buffer,
-	    instance->buffer_size);
-	instance->next_step = batch_call_out_and_dispose;
-	/* TODO: implement */
+	memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
+	instance->next_step = usb_transfer_batch_call_out_and_dispose;
+	batch_data(instance);
 	usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance);
 }
@@ -196,7 +230,6 @@
 {
 	assert(instance);
-	instance->direction = USB_DIRECTION_IN;
-	instance->next_step = batch_call_in_and_dispose;
-	/* TODO: implement */
+	instance->next_step = usb_transfer_batch_call_in_and_dispose;
+	batch_data(instance);
 	usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
 }
@@ -205,7 +238,6 @@
 {
 	assert(instance);
-	instance->direction = USB_DIRECTION_IN;
-	instance->next_step = batch_call_in_and_dispose;
-	/* TODO: implement */
+	instance->next_step = usb_transfer_batch_call_in_and_dispose;
+	batch_data(instance);
 	usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
 }
@@ -214,5 +246,5 @@
 {
 	assert(instance);
-	ohci_batch_t *data = instance->private_data;
+	ohci_transfer_batch_t *data = instance->private_data;
 	assert(data);
 	return data->ed;
@@ -223,23 +255,21 @@
 {
 	assert(instance);
-	ohci_batch_t *data = instance->private_data;
-	assert(data);
-	ed_init(data->ed, instance->ep);
-	ed_add_tds(data->ed, &data->tds[0], &data->tds[data->td_count - 1]);
-	usb_log_debug("Created ED(%p): %x:%x:%x:%x.\n", data->ed,
+	ohci_transfer_batch_t *data = instance->private_data;
+	assert(data);
+	usb_log_debug("Using ED(%p): %x:%x:%x:%x.\n", data->ed,
 	    data->ed->status, data->ed->td_tail, data->ed->td_head,
 	    data->ed->next);
 	int toggle = 0;
 	/* setup stage */
-	td_init(&data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer,
+	td_init(data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer,
 		instance->setup_size, toggle);
-	td_set_next(&data->tds[0], &data->tds[1]);
-	usb_log_debug("Created SETUP TD: %x:%x:%x:%x.\n", data->tds[0].status,
-	    data->tds[0].cbp, data->tds[0].next, data->tds[0].be);
+	td_set_next(data->tds[0], data->tds[1]);
+	usb_log_debug("Created SETUP TD: %x:%x:%x:%x.\n", data->tds[0]->status,
+	    data->tds[0]->cbp, data->tds[0]->next, data->tds[0]->be);
 
 	/* data stage */
 	size_t td_current = 1;
 	size_t remain_size = instance->buffer_size;
-	char *transfer_buffer = instance->transport_buffer;
+	char *buffer = instance->data_buffer;
 	while (remain_size > 0) {
 		size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER ?
@@ -247,45 +277,54 @@
 		toggle = 1 - toggle;
 
-		td_init(&data->tds[td_current], data_dir, transfer_buffer,
+		td_init(data->tds[td_current], data_dir, buffer,
 		    transfer_size, toggle);
-		td_set_next(&data->tds[td_current], &data->tds[td_current + 1]);
+		td_set_next(data->tds[td_current], data->tds[td_current + 1]);
 		usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n",
-		    data->tds[td_current].status, data->tds[td_current].cbp,
-		    data->tds[td_current].next, data->tds[td_current].be);
-
-		transfer_buffer += transfer_size;
+		    data->tds[td_current]->status, data->tds[td_current]->cbp,
+		    data->tds[td_current]->next, data->tds[td_current]->be);
+
+		buffer += transfer_size;
 		remain_size -= transfer_size;
-		assert(td_current < data->td_count - 2);
+		assert(td_current < data->td_count - 1);
 		++td_current;
 	}
 
 	/* status stage */
-	assert(td_current == data->td_count - 2);
-	td_init(&data->tds[td_current], status_dir, NULL, 0, 1);
+	assert(td_current == data->td_count - 1);
+	td_init(data->tds[td_current], status_dir, NULL, 0, 1);
+	td_set_next(data->tds[td_current], data->tds[td_current + 1]);
 	usb_log_debug("Created STATUS TD: %x:%x:%x:%x.\n",
-	    data->tds[td_current].status, data->tds[td_current].cbp,
-	    data->tds[td_current].next, data->tds[td_current].be);
-}
-/*----------------------------------------------------------------------------*/
-/** Helper function calls callback and correctly disposes of batch structure.
- *
- * @param[in] instance Batch structure to use.
- */
-void batch_call_in_and_dispose(usb_transfer_batch_t *instance)
-{
-	assert(instance);
-	usb_transfer_batch_call_in(instance);
-	batch_dispose(instance);
-}
-/*----------------------------------------------------------------------------*/
-/** Helper function calls callback and correctly disposes of batch structure.
- *
- * @param[in] instance Batch structure to use.
- */
-void batch_call_out_and_dispose(usb_transfer_batch_t *instance)
-{
-	assert(instance);
-	usb_transfer_batch_call_out(instance);
-	batch_dispose(instance);
+	    data->tds[td_current]->status, data->tds[td_current]->cbp,
+	    data->tds[td_current]->next, data->tds[td_current]->be);
+}
+/*----------------------------------------------------------------------------*/
+void batch_data(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	ohci_transfer_batch_t *data = instance->private_data;
+	assert(data);
+	usb_log_debug("Using ED(%p): %x:%x:%x:%x.\n", data->ed,
+	    data->ed->status, data->ed->td_tail, data->ed->td_head,
+	    data->ed->next);
+
+	size_t td_current = 0;
+	size_t remain_size = instance->buffer_size;
+	char *buffer = instance->data_buffer;
+	while (remain_size > 0) {
+		size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER ?
+		    OHCI_TD_MAX_TRANSFER : remain_size;
+
+		td_init(data->tds[td_current], instance->ep->direction,
+		    buffer, transfer_size, -1);
+		td_set_next(data->tds[td_current], data->tds[td_current + 1]);
+		usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n",
+		    data->tds[td_current]->status, data->tds[td_current]->cbp,
+		    data->tds[td_current]->next, data->tds[td_current]->be);
+
+		buffer += transfer_size;
+		remain_size -= transfer_size;
+		assert(td_current < data->td_count);
+		++td_current;
+	}
 }
 /**
Index: uspace/drv/ohci/batch.h
===================================================================
--- uspace/drv/ohci/batch.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/ohci/batch.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -50,7 +50,7 @@
     void *arg);
 
-void batch_dispose(usb_transfer_batch_t *instance);
+bool batch_is_complete(usb_transfer_batch_t *instance);
 
-bool batch_is_complete(usb_transfer_batch_t *instance);
+void batch_commit(usb_transfer_batch_t *instance);
 
 void batch_control_write(usb_transfer_batch_t *instance);
Index: uspace/drv/ohci/endpoint_list.c
===================================================================
--- uspace/drv/ohci/endpoint_list.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
+++ uspace/drv/ohci/endpoint_list.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -0,0 +1,225 @@
+/*
+ * 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 drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver transfer list implementation
+ */
+#include <errno.h>
+#include <usb/debug.h>
+
+#include "endpoint_list.h"
+
+/** Initialize transfer list structures.
+ *
+ * @param[in] instance Memory place to use.
+ * @param[in] name Name of the new list.
+ * @return Error code
+ *
+ * Allocates memory for internal qh_t structure.
+ */
+int endpoint_list_init(endpoint_list_t *instance, const char *name)
+{
+	assert(instance);
+	instance->name = name;
+	instance->list_head = malloc32(sizeof(ed_t));
+	if (!instance->list_head) {
+		usb_log_error("Failed to allocate list head.\n");
+		return ENOMEM;
+	}
+	instance->list_head_pa = addr_to_phys(instance->list_head);
+	usb_log_debug2("Transfer list %s setup with ED: %p(%p).\n",
+	    name, instance->list_head, instance->list_head_pa);
+
+	ed_init(instance->list_head, NULL);
+	list_initialize(&instance->endpoint_list);
+	fibril_mutex_initialize(&instance->guard);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Set the next list in transfer list chain.
+ *
+ * @param[in] instance List to lead.
+ * @param[in] next List to append.
+ * @return Error code
+ *
+ * Does not check whether this replaces an existing list .
+ */
+void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next)
+{
+	assert(instance);
+	assert(next);
+	ed_append_ed(instance->list_head, next->list_head);
+}
+/*----------------------------------------------------------------------------*/
+/** Submit transfer endpoint to the list and queue.
+ *
+ * @param[in] instance List to use.
+ * @param[in] endpoint Transfer endpoint to submit.
+ * @return Error code
+ *
+ * The endpoint is added to the end of the list and queue.
+ */
+void endpoint_list_add_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep)
+{
+	assert(instance);
+	assert(hcd_ep);
+	usb_log_debug2("Queue %s: Adding endpoint(%p).\n",
+	    instance->name, hcd_ep);
+
+	fibril_mutex_lock(&instance->guard);
+
+	ed_t *last_ed = NULL;
+	/* Add to the hardware queue. */
+	if (list_empty(&instance->endpoint_list)) {
+		/* There is nothing scheduled */
+		last_ed = instance->list_head;
+	} else {
+		/* There is something scheduled */
+		hcd_endpoint_t *last = list_get_instance(
+		    instance->endpoint_list.prev, hcd_endpoint_t, link);
+		last_ed = last->ed;
+	}
+	/* keep link */
+	hcd_ep->ed->next = last_ed->next;
+	ed_append_ed(last_ed, hcd_ep->ed);
+
+	asm volatile ("": : :"memory");
+
+	/* Add to the driver list */
+	list_append(&hcd_ep->link, &instance->endpoint_list);
+
+	hcd_endpoint_t *first = list_get_instance(
+	    instance->endpoint_list.next, hcd_endpoint_t, link);
+	usb_log_debug("HCD EP(%p) added to list %s, first is %p(%p).\n",
+		hcd_ep, instance->name, first, first->ed);
+	if (last_ed == instance->list_head) {
+		usb_log_debug2("%s head ED(%p-%p): %x:%x:%x:%x.\n",
+		    instance->name, last_ed, instance->list_head_pa,
+		    last_ed->status, last_ed->td_tail, last_ed->td_head,
+		    last_ed->next);
+	}
+	fibril_mutex_unlock(&instance->guard);
+}
+/*----------------------------------------------------------------------------*/
+#if 0
+/** Create list for finished endpoints.
+ *
+ * @param[in] instance List to use.
+ * @param[in] done list to fill
+ */
+void endpoint_list_remove_finished(endpoint_list_t *instance, link_t *done)
+{
+	assert(instance);
+	assert(done);
+
+	fibril_mutex_lock(&instance->guard);
+	usb_log_debug2("Checking list %s for completed endpointes(%d).\n",
+	    instance->name, list_count(&instance->endpoint_list));
+	link_t *current = instance->endpoint_list.next;
+	while (current != &instance->endpoint_list) {
+		link_t *next = current->next;
+		hcd_endpoint_t *endpoint =
+		    list_get_instance(current, hcd_endpoint_t, link);
+
+		if (endpoint_is_complete(endpoint)) {
+			/* Save for post-processing */
+			endpoint_list_remove_endpoint(instance, endpoint);
+			list_append(current, done);
+		}
+		current = next;
+	}
+	fibril_mutex_unlock(&instance->guard);
+}
+/*----------------------------------------------------------------------------*/
+/** Walk the list and abort all endpointes.
+ *
+ * @param[in] instance List to use.
+ */
+void endpoint_list_abort_all(endpoint_list_t *instance)
+{
+	fibril_mutex_lock(&instance->guard);
+	while (!list_empty(&instance->endpoint_list)) {
+		link_t *current = instance->endpoint_list.next;
+		hcd_endpoint_t *endpoint =
+		    list_get_instance(current, hcd_endpoint_t, link);
+		endpoint_list_remove_endpoint(instance, endpoint);
+		hcd_endpoint_finish_error(endpoint, EIO);
+	}
+	fibril_mutex_unlock(&instance->guard);
+}
+#endif
+/*----------------------------------------------------------------------------*/
+/** Remove a transfer endpoint from the list and queue.
+ *
+ * @param[in] instance List to use.
+ * @param[in] endpoint Transfer endpoint to remove.
+ * @return Error code
+ *
+ * Does not lock the transfer list, caller is responsible for that.
+ */
+void endpoint_list_remove_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep)
+{
+	assert(instance);
+	assert(instance->list_head);
+	assert(hcd_ep);
+	assert(hcd_ep->ed);
+
+	fibril_mutex_lock(&instance->guard);
+
+	usb_log_debug2(
+	    "Queue %s: removing endpoint(%p).\n", instance->name, hcd_ep);
+
+	const char *qpos = NULL;
+	ed_t *prev_ed;
+	/* Remove from the hardware queue */
+	if (instance->endpoint_list.next == &hcd_ep->link) {
+		/* I'm the first one here */
+		prev_ed = instance->list_head;
+		qpos = "FIRST";
+	} else {
+		hcd_endpoint_t *prev =
+		    list_get_instance(hcd_ep->link.prev, hcd_endpoint_t, link);
+		prev_ed = prev->ed;
+		qpos = "NOT FIRST";
+	}
+	assert((prev_ed->next & ED_NEXT_PTR_MASK) == addr_to_phys(hcd_ep->ed));
+	prev_ed->next = hcd_ep->ed->next;
+
+	asm volatile ("": : :"memory");
+	usb_log_debug("HCD EP(%p) removed (%s) from %s, next %x.\n",
+	    hcd_ep, qpos, instance->name, hcd_ep->ed->next);
+
+	/* Remove from the endpoint list */
+	list_remove(&hcd_ep->link);
+	fibril_mutex_unlock(&instance->guard);
+}
+/**
+ * @}
+ */
Index: uspace/drv/ohci/endpoint_list.h
===================================================================
--- uspace/drv/ohci/endpoint_list.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
+++ uspace/drv/ohci/endpoint_list.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -0,0 +1,79 @@
+/*
+ * 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 drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver transfer list structure
+ */
+#ifndef DRV_OHCI_ENDPOINT_LIST_H
+#define DRV_OHCI_ENDPOINT_LIST_H
+
+#include <fibril_synch.h>
+
+#include "hcd_endpoint.h"
+#include "hw_struct/endpoint_descriptor.h"
+#include "utils/malloc32.h"
+
+typedef struct endpoint_list
+{
+	fibril_mutex_t guard;
+	ed_t *list_head;
+	uint32_t list_head_pa;
+	const char *name;
+	link_t endpoint_list;
+} endpoint_list_t;
+
+/** Dispose transfer list structures.
+ *
+ * @param[in] instance Memory place to use.
+ *
+ * Frees memory for internal qh_t structure.
+ */
+static inline void endpoint_list_fini(endpoint_list_t *instance)
+{
+	assert(instance);
+	free32(instance->list_head);
+}
+
+int endpoint_list_init(endpoint_list_t *instance, const char *name);
+
+void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next);
+
+void endpoint_list_add_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep);
+
+void endpoint_list_remove_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep);
+#if 0
+void endpoint_list_remove_finished(endpoint_list_t *instance, link_t *done);
+
+void endpoint_list_abort_all(endpoint_list_t *instance);
+#endif
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/ohci/hc.c
===================================================================
--- uspace/drv/ohci/hc.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/ohci/hc.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -43,4 +43,5 @@
 
 #include "hc.h"
+#include "hcd_endpoint.h"
 
 static int interrupt_emulator(hc_t *instance);
@@ -55,24 +56,31 @@
 	assert(hub_fun);
 
+	int ret;
+
 	usb_address_t hub_address =
 	    device_keeper_get_free_address(&instance->manager, USB_SPEED_FULL);
+	if (hub_address <= 0) {
+		usb_log_error("Failed to get OHCI root hub address.\n");
+		return hub_address;
+	}
 	instance->rh.address = hub_address;
 	usb_device_keeper_bind(
 	    &instance->manager, hub_address, hub_fun->handle);
 
-	endpoint_t *ep = malloc(sizeof(endpoint_t));
-	assert(ep);
-	int ret = endpoint_init(ep, hub_address, 0, USB_DIRECTION_BOTH,
-	    USB_TRANSFER_CONTROL, USB_SPEED_FULL, 64);
-	assert(ret == EOK);
-	ret = usb_endpoint_manager_register_ep(&instance->ep_manager, ep, 0);
-	assert(ret == EOK);
+	ret = hc_add_endpoint(instance, hub_address, 0, USB_SPEED_FULL,
+	    USB_TRANSFER_CONTROL, USB_DIRECTION_BOTH, 64, 0, 0);
+	if (ret != EOK) {
+		usb_log_error("Failed to add OHCI rh endpoint 0.\n");
+		usb_device_keeper_release(&instance->manager, hub_address);
+		return ret;
+	}
 
 	char *match_str = NULL;
+	/* DDF needs heap allocated string */
 	ret = asprintf(&match_str, "usb&class=hub");
-//	ret = (match_str == NULL) ? ret : EOK;
 	if (ret < 0) {
 		usb_log_error(
 		    "Failed(%d) to create root hub match-id string.\n", ret);
+		usb_device_keeper_release(&instance->manager, hub_address);
 		return ret;
 	}
@@ -80,5 +88,5 @@
 	ret = ddf_fun_add_match_id(hub_fun, match_str, 100);
 	if (ret != EOK) {
-		usb_log_error("Failed add create root hub match-id.\n");
+		usb_log_error("Failed add root hub match-id.\n");
 	}
 	return ret;
@@ -101,5 +109,4 @@
 	    ret, str_error(ret));
 
-	instance->ddf_instance = fun;
 	usb_device_keeper_init(&instance->manager);
 	ret = usb_endpoint_manager_init(&instance->ep_manager,
@@ -113,6 +120,7 @@
 	    ret, str_error(ret));
 	hc_init_hw(instance);
-
-	rh_init(&instance->rh, dev, instance->registers);
+	fibril_mutex_initialize(&instance->guard);
+
+	rh_init(&instance->rh, instance->registers);
 
 	if (!interrupts) {
@@ -122,36 +130,153 @@
 	}
 
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch)
-{
-	assert(instance);
-	assert(batch);
-
-	/* check for root hub communication */
-	if (batch->target.address == instance->rh.address) {
-		return rh_request(&instance->rh, batch);
-	}
-
-	transfer_list_add_batch(
-	    instance->transfers[batch->transfer_type], batch);
-
-	switch (batch->transfer_type) {
+	list_initialize(&instance->pending_batches);
+#undef CHECK_RET_RETURN
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+int hc_add_endpoint(
+    hc_t *instance, usb_address_t address, usb_endpoint_t endpoint,
+    usb_speed_t speed, usb_transfer_type_t type, usb_direction_t direction,
+    size_t mps, size_t size, unsigned interval)
+{
+	endpoint_t *ep = malloc(sizeof(endpoint_t));
+	if (ep == NULL)
+		return ENOMEM;
+	int ret =
+	    endpoint_init(ep, address, endpoint, direction, type, speed, mps);
+	if (ret != EOK) {
+		free(ep);
+		return ret;
+	}
+
+	hcd_endpoint_t *hcd_ep = hcd_endpoint_assign(ep);
+	if (hcd_ep == NULL) {
+		endpoint_destroy(ep);
+		return ENOMEM;
+	}
+
+	ret = usb_endpoint_manager_register_ep(&instance->ep_manager, ep, size);
+	if (ret != EOK) {
+		hcd_endpoint_clear(ep);
+		endpoint_destroy(ep);
+		return ret;
+	}
+
+	/* Enqueue hcd_ep */
+	switch (ep->transfer_type) {
 	case USB_TRANSFER_CONTROL:
 		instance->registers->control &= ~C_CLE;
+		endpoint_list_add_ep(
+		    &instance->lists[ep->transfer_type], hcd_ep);
+		instance->registers->control_current = 0;
+		instance->registers->control |= C_CLE;
+		break;
+	case USB_TRANSFER_BULK:
+		instance->registers->control &= ~C_BLE;
+		endpoint_list_add_ep(
+		    &instance->lists[ep->transfer_type], hcd_ep);
+		instance->registers->control |= C_BLE;
+		break;
+	case USB_TRANSFER_ISOCHRONOUS:
+	case USB_TRANSFER_INTERRUPT:
+		instance->registers->control &= (~C_PLE & ~C_IE);
+		endpoint_list_add_ep(
+		    &instance->lists[ep->transfer_type], hcd_ep);
+		instance->registers->control |= C_PLE | C_IE;
+		break;
+	default:
+		break;
+	}
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+int hc_remove_endpoint(hc_t *instance, usb_address_t address,
+    usb_endpoint_t endpoint, usb_direction_t direction)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+	endpoint_t *ep = usb_endpoint_manager_get_ep(&instance->ep_manager,
+	    address, endpoint, direction, NULL);
+	if (ep == NULL) {
+		usb_log_error("Endpoint unregister failed: No such EP.\n");
+		fibril_mutex_unlock(&instance->guard);
+		return ENOENT;
+	}
+
+	hcd_endpoint_t *hcd_ep = hcd_endpoint_get(ep);
+	if (hcd_ep) {
+		/* Dequeue hcd_ep */
+		switch (ep->transfer_type) {
+		case USB_TRANSFER_CONTROL:
+			instance->registers->control &= ~C_CLE;
+			endpoint_list_remove_ep(
+			    &instance->lists[ep->transfer_type], hcd_ep);
+			instance->registers->control_current = 0;
+			instance->registers->control |= C_CLE;
+			break;
+		case USB_TRANSFER_BULK:
+			instance->registers->control &= ~C_BLE;
+			endpoint_list_remove_ep(
+			    &instance->lists[ep->transfer_type], hcd_ep);
+			instance->registers->control |= C_BLE;
+			break;
+		case USB_TRANSFER_ISOCHRONOUS:
+		case USB_TRANSFER_INTERRUPT:
+			instance->registers->control &= (~C_PLE & ~C_IE);
+			endpoint_list_remove_ep(
+			    &instance->lists[ep->transfer_type], hcd_ep);
+			instance->registers->control |= C_PLE | C_IE;
+			break;
+		default:
+			break;
+		}
+		hcd_endpoint_clear(ep);
+	} else {
+		usb_log_warning("Endpoint without hcd equivalent structure.\n");
+	}
+	int ret = usb_endpoint_manager_unregister_ep(&instance->ep_manager,
+	    address, endpoint, direction);
+	fibril_mutex_unlock(&instance->guard);
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+endpoint_t * hc_get_endpoint(hc_t *instance, usb_address_t address,
+    usb_endpoint_t endpoint, usb_direction_t direction, size_t *bw)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+	endpoint_t *ep = usb_endpoint_manager_get_ep(&instance->ep_manager,
+	    address, endpoint, direction, bw);
+	fibril_mutex_unlock(&instance->guard);
+	return ep;
+}
+/*----------------------------------------------------------------------------*/
+int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch)
+{
+	assert(instance);
+	assert(batch);
+	assert(batch->ep);
+
+	/* check for root hub communication */
+	if (batch->ep->address == instance->rh.address) {
+		return rh_request(&instance->rh, batch);
+	}
+
+	fibril_mutex_lock(&instance->guard);
+	list_append(&batch->link, &instance->pending_batches);
+	batch_commit(batch);
+	switch (batch->ep->transfer_type) {
+	case USB_TRANSFER_CONTROL:
 		instance->registers->command_status |= CS_CLF;
-		usb_log_debug2("Set control transfer filled: %x.\n",
-			instance->registers->command_status);
-		instance->registers->control |= C_CLE;
 		break;
 	case USB_TRANSFER_BULK:
 		instance->registers->command_status |= CS_BLF;
-		usb_log_debug2("Set bulk transfer filled: %x.\n",
-			instance->registers->command_status);
 		break;
 	default:
 		break;
 	}
+
+	fibril_mutex_unlock(&instance->guard);
 	return EOK;
 }
@@ -165,19 +290,26 @@
 		rh_interrupt(&instance->rh);
 
-	usb_log_info("OHCI interrupt: %x.\n", status);
-
-
-	LIST_INITIALIZE(done);
-	transfer_list_remove_finished(&instance->transfers_interrupt, &done);
-	transfer_list_remove_finished(&instance->transfers_isochronous, &done);
-	transfer_list_remove_finished(&instance->transfers_control, &done);
-	transfer_list_remove_finished(&instance->transfers_bulk, &done);
-
-	while (!list_empty(&done)) {
-		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_finish(batch);
+	usb_log_debug("OHCI interrupt: %x.\n", status);
+
+	if (status & IS_WDH) {
+		fibril_mutex_lock(&instance->guard);
+		usb_log_debug2("HCCA: %p-%p(%p).\n", instance->hcca,
+		    instance->registers->hcca, addr_to_phys(instance->hcca));
+		usb_log_debug2("Periodic current: %p.\n",
+		    instance->registers->periodic_current);
+
+		link_t *current = instance->pending_batches.next;
+		while (current != &instance->pending_batches) {
+			link_t *next = current->next;
+			usb_transfer_batch_t *batch =
+			    usb_transfer_batch_from_link(current);
+
+			if (batch_is_complete(batch)) {
+				list_remove(current);
+				usb_transfer_batch_finish(batch);
+			}
+			current = next;
+		}
+		fibril_mutex_unlock(&instance->guard);
 	}
 }
@@ -191,5 +323,5 @@
 		instance->registers->interrupt_status = status;
 		hc_interrupt(instance, status);
-		async_usleep(1000);
+		async_usleep(50000);
 	}
 	return EOK;
@@ -267,4 +399,20 @@
 	    instance->registers->control);
 
+	/* Use HCCA */
+	instance->registers->hcca = addr_to_phys(instance->hcca);
+
+	/* Use queues */
+	instance->registers->bulk_head =
+	    instance->lists[USB_TRANSFER_BULK].list_head_pa;
+	usb_log_debug2("Bulk HEAD set to: %p(%p).\n",
+	    instance->lists[USB_TRANSFER_BULK].list_head,
+	    instance->lists[USB_TRANSFER_BULK].list_head_pa);
+
+	instance->registers->control_head =
+	    instance->lists[USB_TRANSFER_CONTROL].list_head_pa;
+	usb_log_debug2("Control HEAD set to: %p(%p).\n",
+	    instance->lists[USB_TRANSFER_CONTROL].list_head,
+	    instance->lists[USB_TRANSFER_CONTROL].list_head_pa);
+
 	/* Enable queues */
 	instance->registers->control |= (C_PLE | C_IE | C_CLE | C_BLE);
@@ -296,37 +444,27 @@
 	assert(instance);
 
-#define SETUP_TRANSFER_LIST(type, name) \
+#define SETUP_ENDPOINT_LIST(type) \
 do { \
-	int ret = transfer_list_init(&instance->type, name); \
+	const char *name = usb_str_transfer_type(type); \
+	int ret = endpoint_list_init(&instance->lists[type], name); \
 	if (ret != EOK) { \
-		usb_log_error("Failed(%d) to setup %s transfer list.\n", \
+		usb_log_error("Failed(%d) to setup %s endpoint list.\n", \
 		    ret, name); \
-		transfer_list_fini(&instance->transfers_isochronous); \
-		transfer_list_fini(&instance->transfers_interrupt); \
-		transfer_list_fini(&instance->transfers_control); \
-		transfer_list_fini(&instance->transfers_bulk); \
+		endpoint_list_fini(&instance->lists[USB_TRANSFER_ISOCHRONOUS]); \
+		endpoint_list_fini(&instance->lists[USB_TRANSFER_INTERRUPT]); \
+		endpoint_list_fini(&instance->lists[USB_TRANSFER_CONTROL]); \
+		endpoint_list_fini(&instance->lists[USB_TRANSFER_BULK]); \
 	} \
 } while (0)
 
-	SETUP_TRANSFER_LIST(transfers_isochronous, "ISOCHRONOUS");
-	SETUP_TRANSFER_LIST(transfers_interrupt, "INTERRUPT");
-	SETUP_TRANSFER_LIST(transfers_control, "CONTROL");
-	SETUP_TRANSFER_LIST(transfers_bulk, "BULK");
-
-	transfer_list_set_next(&instance->transfers_interrupt,
-	    &instance->transfers_isochronous);
-
-	/* Assign pointers to be used during scheduling */
-	instance->transfers[USB_TRANSFER_INTERRUPT] =
-	  &instance->transfers_interrupt;
-	instance->transfers[USB_TRANSFER_ISOCHRONOUS] =
-	  &instance->transfers_interrupt;
-	instance->transfers[USB_TRANSFER_CONTROL] =
-	  &instance->transfers_control;
-	instance->transfers[USB_TRANSFER_BULK] =
-	  &instance->transfers_bulk;
-
-	return EOK;
-#undef CHECK_RET_CLEAR_RETURN
+	SETUP_ENDPOINT_LIST(USB_TRANSFER_ISOCHRONOUS);
+	SETUP_ENDPOINT_LIST(USB_TRANSFER_INTERRUPT);
+	SETUP_ENDPOINT_LIST(USB_TRANSFER_CONTROL);
+	SETUP_ENDPOINT_LIST(USB_TRANSFER_BULK);
+#undef SETUP_ENDPOINT_LIST
+	endpoint_list_set_next(&instance->lists[USB_TRANSFER_INTERRUPT],
+	    &instance->lists[USB_TRANSFER_ISOCHRONOUS]);
+
+	return EOK;
 }
 /*----------------------------------------------------------------------------*/
@@ -342,28 +480,14 @@
 		return ENOMEM;
 	bzero(instance->hcca, sizeof(hcca_t));
-	instance->registers->hcca = addr_to_phys(instance->hcca);
-	usb_log_debug2("OHCI HCCA initialized at %p(%p).\n",
-	    instance->hcca, instance->registers->hcca);
-
-	/* Use queues */
-	instance->registers->bulk_head = instance->transfers_bulk.list_head_pa;
-	usb_log_debug2("Bulk HEAD set to: %p(%p).\n",
-	    instance->transfers_bulk.list_head,
-	    instance->transfers_bulk.list_head_pa);
-
-	instance->registers->control_head =
-	    instance->transfers_control.list_head_pa;
-	usb_log_debug2("Control HEAD set to: %p(%p).\n",
-	    instance->transfers_control.list_head,
-	    instance->transfers_control.list_head_pa);
+	usb_log_debug2("OHCI HCCA initialized at %p.\n", instance->hcca);
 
 	unsigned i = 0;
 	for (; i < 32; ++i) {
 		instance->hcca->int_ep[i] =
-		    instance->transfers_interrupt.list_head_pa;
+		    instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa;
 	}
 	usb_log_debug2("Interrupt HEADs set to: %p(%p).\n",
-	    instance->transfers_interrupt.list_head,
-	    instance->transfers_interrupt.list_head_pa);
+	    instance->lists[USB_TRANSFER_INTERRUPT].list_head,
+	    instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa);
 
 	return EOK;
Index: uspace/drv/ohci/hc.h
===================================================================
--- uspace/drv/ohci/hc.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/ohci/hc.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -48,25 +48,21 @@
 #include "ohci_regs.h"
 #include "root_hub.h"
-#include "transfer_list.h"
+#include "endpoint_list.h"
 #include "hw_struct/hcca.h"
 
 typedef struct hc {
 	ohci_regs_t *registers;
+	hcca_t *hcca;
+
 	usb_address_t rh_address;
 	rh_t rh;
 
-	hcca_t *hcca;
+	endpoint_list_t lists[4];
+	link_t pending_batches;
 
-	transfer_list_t transfers_isochronous;
-	transfer_list_t transfers_interrupt;
-	transfer_list_t transfers_control;
-	transfer_list_t transfers_bulk;
-
-	transfer_list_t *transfers[4];
-
-	ddf_fun_t *ddf_instance;
 	usb_device_keeper_t manager;
 	usb_endpoint_manager_t ep_manager;
 	fid_t interrupt_emulator;
+	fibril_mutex_t guard;
 } hc_t;
 
@@ -76,8 +72,4 @@
      uintptr_t regs, size_t reg_size, bool interrupts);
 
-int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch);
-
-void hc_interrupt(hc_t *instance, uint32_t status);
-
 /** Safely dispose host controller internal structures
  *
@@ -85,4 +77,18 @@
  */
 static inline void hc_fini(hc_t *instance) { /* TODO: implement*/ };
+
+int hc_add_endpoint(hc_t *instance, usb_address_t address, usb_endpoint_t ep,
+    usb_speed_t speed, usb_transfer_type_t type, usb_direction_t direction,
+    size_t max_packet_size, size_t size, unsigned interval);
+
+int hc_remove_endpoint(hc_t *instance, usb_address_t address,
+    usb_endpoint_t endpoint, usb_direction_t direction);
+
+endpoint_t * hc_get_endpoint(hc_t *instance, usb_address_t address,
+    usb_endpoint_t endpoint, usb_direction_t direction, size_t *bw);
+
+int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch);
+
+void hc_interrupt(hc_t *instance, uint32_t status);
 
 /** Get and cast pointer to the driver data
Index: uspace/drv/ohci/hcd_endpoint.c
===================================================================
--- uspace/drv/ohci/hcd_endpoint.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
+++ uspace/drv/ohci/hcd_endpoint.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -0,0 +1,97 @@
+/*
+ * 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 drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver
+ */
+#include "utils/malloc32.h"
+#include "hcd_endpoint.h"
+
+static void hcd_ep_toggle_set(void *hcd_ep, int toggle)
+{
+	hcd_endpoint_t *instance = hcd_ep;
+	assert(instance);
+	assert(instance->ed);
+	ed_toggle_set(instance->ed, toggle);
+}
+static int hcd_ep_toggle_get(void *hcd_ep)
+{
+	hcd_endpoint_t *instance = hcd_ep;
+	assert(instance);
+	assert(instance->ed);
+	return ed_toggle_get(instance->ed);
+}
+
+
+hcd_endpoint_t * hcd_endpoint_assign(endpoint_t *ep)
+{
+	assert(ep);
+	hcd_endpoint_t *hcd_ep = malloc(sizeof(hcd_endpoint_t));
+	if (hcd_ep == NULL)
+		return NULL;
+
+	hcd_ep->ed = malloc32(sizeof(ed_t));
+	if (hcd_ep->ed == NULL) {
+		free(hcd_ep);
+		return NULL;
+	}
+
+	hcd_ep->td = malloc32(sizeof(td_t));
+	if (hcd_ep->td == NULL) {
+		free32(hcd_ep->ed);
+		free(hcd_ep);
+		return NULL;
+	}
+
+	ed_init(hcd_ep->ed, ep);
+	ed_set_td(hcd_ep->ed, hcd_ep->td);
+	endpoint_set_hc_data(ep, hcd_ep, hcd_ep_toggle_get, hcd_ep_toggle_set);
+
+	return hcd_ep;
+}
+/*----------------------------------------------------------------------------*/
+hcd_endpoint_t * hcd_endpoint_get(endpoint_t *ep)
+{
+	assert(ep);
+	return ep->hc_data.data;
+}
+/*----------------------------------------------------------------------------*/
+void hcd_endpoint_clear(endpoint_t *ep)
+{
+	assert(ep);
+	hcd_endpoint_t *hcd_ep = ep->hc_data.data;
+	assert(hcd_ep);
+	free32(hcd_ep->ed);
+	free32(hcd_ep->td);
+	free(hcd_ep);
+}
+/**
+ * @}
+ */
Index: uspace/drv/ohci/hcd_endpoint.h
===================================================================
--- uspace/drv/ohci/hcd_endpoint.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
+++ uspace/drv/ohci/hcd_endpoint.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -0,0 +1,59 @@
+/*
+ * 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 drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver
+ */
+#ifndef DRV_OHCI_HCD_ENDPOINT_H
+#define DRV_OHCI_HCD_ENDPOINT_H
+
+#include <assert.h>
+#include <adt/list.h>
+
+#include <usb/host/endpoint.h>
+
+#include "hw_struct/endpoint_descriptor.h"
+#include "hw_struct/transfer_descriptor.h"
+
+typedef struct hcd_endpoint {
+	ed_t *ed;
+	td_t *td;
+	link_t link;
+} hcd_endpoint_t;
+
+hcd_endpoint_t * hcd_endpoint_assign(endpoint_t *ep);
+
+hcd_endpoint_t * hcd_endpoint_get(endpoint_t *ep);
+
+void hcd_endpoint_clear(endpoint_t *ep);
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/ohci/hw_struct/endpoint_descriptor.c
===================================================================
--- uspace/drv/ohci/hw_struct/endpoint_descriptor.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/ohci/hw_struct/endpoint_descriptor.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -53,8 +53,12 @@
 	        << ED_STATUS_MPS_SHIFT);
 
+
 	if (ep->speed == USB_SPEED_LOW)
 		instance->status |= ED_STATUS_S_FLAG;
 	if (ep->transfer_type == USB_TRANSFER_ISOCHRONOUS)
 		instance->status |= ED_STATUS_F_FLAG;
+
+	if (ep->toggle)
+		instance->td_head |= ED_TDHEAD_TOGGLE_CARRY;
 }
 /**
Index: uspace/drv/ohci/hw_struct/endpoint_descriptor.h
===================================================================
--- uspace/drv/ohci/hw_struct/endpoint_descriptor.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/ohci/hw_struct/endpoint_descriptor.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -53,6 +53,6 @@
 #define ED_STATUS_D_MASK (0x3)     /* direction */
 #define ED_STATUS_D_SHIFT (11)
-#define ED_STATUS_D_IN (0x1)
-#define ED_STATUS_D_OUT (0x2)
+#define ED_STATUS_D_OUT (0x1)
+#define ED_STATUS_D_IN (0x2)
 #define ED_STATUS_D_TRANSFER (0x3)
 
@@ -73,4 +73,5 @@
 #define ED_TDHEAD_ZERO_SHIFT (2)
 #define ED_TDHEAD_TOGGLE_CARRY (0x2)
+#define ED_TDHEAD_HALTED_FLAG (0x1)
 
 	volatile uint32_t next;
@@ -81,9 +82,19 @@
 void ed_init(ed_t *instance, endpoint_t *ep);
 
-static inline void ed_add_tds(ed_t *instance, td_t *head, td_t *tail)
+static inline void ed_set_td(ed_t *instance, td_t *td)
 {
 	assert(instance);
-	instance->td_head = addr_to_phys(head) & ED_TDHEAD_PTR_MASK;
-	instance->td_tail = addr_to_phys(tail) & ED_TDTAIL_PTR_MASK;
+	uintptr_t pa = addr_to_phys(td);
+	instance->td_head =
+	    ((pa & ED_TDHEAD_PTR_MASK)
+	    | (instance->td_head & ~ED_TDHEAD_PTR_MASK));
+	instance->td_tail = pa & ED_TDTAIL_PTR_MASK;
+}
+
+static inline void ed_set_end_td(ed_t *instance, td_t *td)
+{
+	assert(instance);
+	uintptr_t pa = addr_to_phys(td);
+	instance->td_tail = pa & ED_TDTAIL_PTR_MASK;
 }
 
@@ -97,4 +108,22 @@
 }
 
+static inline int ed_toggle_get(ed_t *instance)
+{
+	assert(instance);
+	return (instance->td_head & ED_TDHEAD_TOGGLE_CARRY) ? 1 : 0;
+}
+
+static inline void ed_toggle_set(ed_t *instance, int toggle)
+{
+	assert(instance);
+	assert(toggle == 0 || toggle == 1);
+	if (toggle == 1) {
+		instance->td_head |= ED_TDHEAD_TOGGLE_CARRY;
+	} else {
+		/* clear halted flag when reseting toggle */
+		instance->td_head &= ~ED_TDHEAD_TOGGLE_CARRY;
+		instance->td_head &= ~ED_TDHEAD_HALTED_FLAG;
+	}
+}
 #endif
 /**
Index: uspace/drv/ohci/hw_struct/hcca.h
===================================================================
--- uspace/drv/ohci/hw_struct/hcca.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/ohci/hw_struct/hcca.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -43,5 +43,5 @@
 	uint32_t done_head;
 	uint32_t reserved[29];
-} __attribute__((packed)) hcca_t;
+} __attribute__((packed, aligned)) hcca_t;
 
 #endif
Index: uspace/drv/ohci/hw_struct/transfer_descriptor.c
===================================================================
--- uspace/drv/ohci/hw_struct/transfer_descriptor.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/ohci/hw_struct/transfer_descriptor.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -53,4 +53,5 @@
 	}
 	if (buffer != NULL) {
+		assert(size != 0);
 		instance->cbp = addr_to_phys(buffer);
 		instance->be = addr_to_phys(buffer + size - 1);
Index: uspace/drv/ohci/hw_struct/transfer_descriptor.h
===================================================================
--- uspace/drv/ohci/hw_struct/transfer_descriptor.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/ohci/hw_struct/transfer_descriptor.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -50,6 +50,6 @@
 #define TD_STATUS_DP_SHIFT (19)
 #define TD_STATUS_DP_SETUP (0x0)
-#define TD_STATUS_DP_IN (0x1)
-#define TD_STATUS_DP_OUT (0x2)
+#define TD_STATUS_DP_OUT (0x1)
+#define TD_STATUS_DP_IN (0x2)
 #define TD_STATUS_DI_MASK (0x7) /* delay interrupt, wait DI frames before int */
 #define TD_STATUS_DI_SHIFT (21)
@@ -86,5 +86,5 @@
 	int cc = (instance->status >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK;
 	/* something went wrong, error code is set */
-	if (cc != CC_NOACCESS1 && cc != CC_NOACCESS2 && cc != CC_NOERROR) {
+	if (cc != CC_NOACCESS1 && cc != CC_NOACCESS2) {
 		return true;
 	}
Index: uspace/drv/ohci/iface.c
===================================================================
--- uspace/drv/ohci/iface.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/ohci/iface.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -55,5 +55,5 @@
 
 	size_t res_bw;
-	endpoint_t *ep = usb_endpoint_manager_get_ep(&(*hc)->ep_manager,
+	endpoint_t *ep = hc_get_endpoint(*hc,
 	    target.address, target.endpoint, direction, &res_bw);
 	if (ep == NULL) {
@@ -164,5 +164,4 @@
 	}
 	const size_t size = max_packet_size;
-	int ret;
 
 	usb_log_debug("Register endpoint %d:%d %s %s(%d) %zu(%zu) %u.\n",
@@ -170,19 +169,6 @@
 	    usb_str_speed(speed), direction, size, max_packet_size, interval);
 
-	endpoint_t *ep = malloc(sizeof(endpoint_t));
-	if (ep == NULL)
-		return ENOMEM;
-	ret = endpoint_init(ep, address, endpoint, direction,
-	    transfer_type, speed, max_packet_size);
-	if (ret != EOK) {
-		free(ep);
-		return ret;
-	}
-
-	ret = usb_endpoint_manager_register_ep(&hc->ep_manager, ep, size);
-	if (ret != EOK) {
-		endpoint_destroy(ep);
-	}
-	return ret;
+	return hc_add_endpoint(hc, address, endpoint, speed, transfer_type,
+	    direction, max_packet_size, size, interval);
 }
 /*----------------------------------------------------------------------------*/
@@ -195,6 +181,5 @@
 	usb_log_debug("Unregister endpoint %d:%d %d.\n",
 	    address, endpoint, direction);
-	return usb_endpoint_manager_unregister_ep(&hc->ep_manager, address,
-	    endpoint, direction);
+	return hc_remove_endpoint(hc, address, endpoint, direction);
 }
 /*----------------------------------------------------------------------------*/
@@ -228,5 +213,5 @@
 	ret = hc_schedule(hc, batch);
 	if (ret != EOK) {
-		batch_dispose(batch);
+		usb_transfer_batch_dispose(batch);
 	}
 	return ret;
@@ -262,5 +247,5 @@
 	ret = hc_schedule(hc, batch);
 	if (ret != EOK) {
-		batch_dispose(batch);
+		usb_transfer_batch_dispose(batch);
 	}
 	return ret;
@@ -296,5 +281,5 @@
 	ret = hc_schedule(hc, batch);
 	if (ret != EOK) {
-		batch_dispose(batch);
+		usb_transfer_batch_dispose(batch);
 	}
 	return ret;
@@ -330,5 +315,5 @@
 	ret = hc_schedule(hc, batch);
 	if (ret != EOK) {
-		batch_dispose(batch);
+		usb_transfer_batch_dispose(batch);
 	}
 	return ret;
@@ -346,8 +331,8 @@
  * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
  *	and deallocated by the caller).
- * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes.
+ * @param[in] setup_size Size of @p setup_packet buffer in bytes.
  * @param[in] data_buffer Data buffer (in USB endianess, allocated and
  *	deallocated by the caller).
- * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes.
+ * @param[in] size Size of @p data_buffer buffer in bytes.
  * @param[in] callback Callback to be issued once the transfer is complete.
  * @param[in] arg Pass-through argument to the callback.
@@ -370,5 +355,5 @@
 	ret = hc_schedule(hc, batch);
 	if (ret != EOK) {
-		batch_dispose(batch);
+		usb_transfer_batch_dispose(batch);
 	}
 	return ret;
@@ -386,8 +371,8 @@
  * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
  *	and deallocated by the caller).
- * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes.
+ * @param[in] setup_size Size of @p setup_packet buffer in bytes.
  * @param[in] data_buffer Buffer where to store the data (in USB endianess,
  *	allocated and deallocated by the caller).
- * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes.
+ * @param[in] size Size of @p data_buffer buffer in bytes.
  * @param[in] callback Callback to be issued once the transfer is complete.
  * @param[in] arg Pass-through argument to the callback.
@@ -409,5 +394,5 @@
 	ret = hc_schedule(hc, batch);
 	if (ret != EOK) {
-		batch_dispose(batch);
+		usb_transfer_batch_dispose(batch);
 	}
 	return ret;
Index: uspace/drv/ohci/ohci.ma
===================================================================
--- uspace/drv/ohci/ohci.ma	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/ohci/ohci.ma	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -1,1 +1,3 @@
 10 pci/ven=106b&dev=003f
+10 pci/ven=10de&dev=0aa5
+10 pci/ven=10de&dev=0aa5
Index: uspace/drv/ohci/ohci_regs.h
===================================================================
--- uspace/drv/ohci/ohci_regs.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/ohci/ohci_regs.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -55,6 +55,6 @@
 #define C_HCFS_MASK        (0x3) /* Host controller functional state */
 #define C_HCFS_RESET       (0x0)
-#define C_HCFS_OPERATIONAL (0x1)
-#define C_HCFS_RESUME      (0x2)
+#define C_HCFS_RESUME      (0x1)
+#define C_HCFS_OPERATIONAL (0x2)
 #define C_HCFS_SUSPEND     (0x3)
 #define C_HCFS_SHIFT       (6)
@@ -100,6 +100,6 @@
 #define HCCA_PTR_MASK 0xffffff00 /* HCCA is 256B aligned */
 
-	/** Currently executed period endpoint */
-	const volatile uint32_t period_current;
+	/** Currently executed periodic endpoint */
+	const volatile uint32_t periodic_current;
 
 	/** The first control endpoint */
Index: uspace/drv/ohci/root_hub.c
===================================================================
--- uspace/drv/ohci/root_hub.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/ohci/root_hub.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -205,21 +205,14 @@
  * @return Error code.
  */
-int rh_init(rh_t *instance, ddf_dev_t *dev, ohci_regs_t *regs) {
+int rh_init(rh_t *instance, ohci_regs_t *regs) {
 	assert(instance);
-	//instance->address = -1;
 	instance->registers = regs;
-	instance->device = dev;
 	instance->port_count =
 	    (instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK;
 	rh_init_descriptors(instance);
 	// set port power mode to no-power-switching
-	instance->registers->rh_desc_a =
-		instance->registers->rh_desc_a | (1<<9);
+	instance->registers->rh_desc_a |= RHDA_NPS_FLAG;
 
 	usb_log_info("OHCI root hub with %d ports.\n", instance->port_count);
-
-	//start generic usb hub driver
-
-	/* TODO: implement */
 	return EOK;
 }
@@ -237,13 +230,13 @@
 	assert(request);
 	int opResult;
-	if (request->transfer_type == USB_TRANSFER_CONTROL) {
+	if (request->ep->transfer_type == USB_TRANSFER_CONTROL) {
 		usb_log_info("Root hub got CONTROL packet\n");
 		opResult = process_ctrl_request(instance, request);
-	} else if (request->transfer_type == USB_TRANSFER_INTERRUPT) {
+	} else if (request->ep->transfer_type == USB_TRANSFER_INTERRUPT) {
 		usb_log_info("Root hub got INTERRUPT packet\n");
 		void * buffer;
 		create_interrupt_mask(instance, &buffer,
 			&(request->transfered_size));
-		memcpy(request->transport_buffer, buffer,
+		memcpy(request->data_buffer, buffer,
 			request->transfered_size);
 		opResult = EOK;
@@ -374,5 +367,5 @@
 	if (port < 1 || port > instance->port_count)
 		return EINVAL;
-	uint32_t * uint32_buffer = (uint32_t*) request->transport_buffer;
+	uint32_t * uint32_buffer = (uint32_t*) request->data_buffer;
 	request->transfered_size = 4;
 	uint32_buffer[0] = instance->registers->rh_port_status[port - 1];
@@ -400,5 +393,5 @@
 static int process_get_hub_status_request(rh_t *instance,
 	usb_transfer_batch_t * request) {
-	uint32_t * uint32_buffer = (uint32_t*) request->transport_buffer;
+	uint32_t * uint32_buffer = (uint32_t*) request->data_buffer;
 	request->transfered_size = 4;
 	//bits, 0,1,16,17
@@ -550,5 +543,5 @@
 	}
 	request->transfered_size = size;
-	memcpy(request->transport_buffer, result_descriptor, size);
+	memcpy(request->data_buffer, result_descriptor, size);
 	if (del)
 		free(result_descriptor);
@@ -571,5 +564,5 @@
 	if (request->buffer_size != 1)
 		return EINVAL;
-	request->transport_buffer[0] = 1;
+	request->data_buffer[0] = 1;
 	request->transfered_size = 1;
 	return EOK;
Index: uspace/drv/ohci/root_hub.h
===================================================================
--- uspace/drv/ohci/root_hub.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/ohci/root_hub.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -50,6 +50,4 @@
 	/** usb address of the root hub */
 	usb_address_t address;
-	/** ddf device information */
-	ddf_dev_t *device;
 	/** hub port count */
 	int port_count;
@@ -58,5 +56,5 @@
 } rh_t;
 
-int rh_init(rh_t *instance, ddf_dev_t *dev, ohci_regs_t *regs);
+int rh_init(rh_t *instance, ohci_regs_t *regs);
 
 int rh_request(rh_t *instance, usb_transfer_batch_t *request);
Index: uspace/drv/ohci/transfer_list.c
===================================================================
--- uspace/drv/ohci/transfer_list.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ 	(revision )
@@ -1,224 +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 drvusbohci
- * @{
- */
-/** @file
- * @brief OHCI driver transfer list implementation
- */
-#include <errno.h>
-#include <usb/debug.h>
-
-#include "transfer_list.h"
-
-static void transfer_list_remove_batch(
-    transfer_list_t *instance, usb_transfer_batch_t *batch);
-/*----------------------------------------------------------------------------*/
-/** Initialize transfer list structures.
- *
- * @param[in] instance Memory place to use.
- * @param[in] name Name of the new list.
- * @return Error code
- *
- * Allocates memory for internal qh_t structure.
- */
-int transfer_list_init(transfer_list_t *instance, const char *name)
-{
-	assert(instance);
-	instance->name = name;
-	instance->list_head = malloc32(sizeof(ed_t));
-	if (!instance->list_head) {
-		usb_log_error("Failed to allocate list head.\n");
-		return ENOMEM;
-	}
-	instance->list_head_pa = addr_to_phys(instance->list_head);
-	usb_log_debug2("Transfer list %s setup with ED: %p(%p).\n",
-	    name, instance->list_head, instance->list_head_pa);
-
-	ed_init(instance->list_head, NULL);
-	list_initialize(&instance->batch_list);
-	fibril_mutex_initialize(&instance->guard);
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/** Set the next list in transfer list chain.
- *
- * @param[in] instance List to lead.
- * @param[in] next List to append.
- * @return Error code
- *
- * Does not check whether this replaces an existing list .
- */
-void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next)
-{
-	assert(instance);
-	assert(next);
-	/* Set both queue_head.next to point to the follower */
-	ed_append_ed(instance->list_head, next->list_head);
-}
-/*----------------------------------------------------------------------------*/
-/** Submit transfer batch to the list and queue.
- *
- * @param[in] instance List to use.
- * @param[in] batch Transfer batch to submit.
- * @return Error code
- *
- * 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)
-{
-	assert(instance);
-	assert(batch);
-	usb_log_debug2("Queue %s: Adding batch(%p).\n", instance->name, batch);
-
-	fibril_mutex_lock(&instance->guard);
-
-	ed_t *last_ed = NULL;
-	/* Add to the hardware queue. */
-	if (list_empty(&instance->batch_list)) {
-		/* There is nothing scheduled */
-		last_ed = instance->list_head;
-	} else {
-		/* There is something scheduled */
-		usb_transfer_batch_t *last = list_get_instance(
-		    instance->batch_list.prev, usb_transfer_batch_t, link);
-		last_ed = batch_ed(last);
-	}
-	/* keep link */
-	batch_ed(batch)->next = last_ed->next;
-	ed_append_ed(last_ed, batch_ed(batch));
-
-	asm volatile ("": : :"memory");
-
-	/* Add to the driver list */
-	list_append(&batch->link, &instance->batch_list);
-
-	usb_transfer_batch_t *first = list_get_instance(
-	    instance->batch_list.next, usb_transfer_batch_t, link);
-	usb_log_debug("Batch(%p) added to list %s, first is %p(%p).\n",
-		batch, instance->name, first, batch_ed(first));
-	if (last_ed == instance->list_head) {
-		usb_log_debug2("%s head ED: %x:%x:%x:%x.\n", instance->name,
-			last_ed->status, last_ed->td_tail, last_ed->td_head,
-			last_ed->next);
-	}
-	fibril_mutex_unlock(&instance->guard);
-}
-/*----------------------------------------------------------------------------*/
-/** Create list for finished batches.
- *
- * @param[in] instance List to use.
- * @param[in] done list to fill
- */
-void transfer_list_remove_finished(transfer_list_t *instance, link_t *done)
-{
-	assert(instance);
-	assert(done);
-
-	fibril_mutex_lock(&instance->guard);
-	link_t *current = instance->batch_list.next;
-	while (current != &instance->batch_list) {
-		link_t *next = current->next;
-		usb_transfer_batch_t *batch =
-		    list_get_instance(current, usb_transfer_batch_t, link);
-
-		if (batch_is_complete(batch)) {
-			/* Save for post-processing */
-			transfer_list_remove_batch(instance, batch);
-			list_append(current, done);
-		}
-		current = next;
-	}
-	fibril_mutex_unlock(&instance->guard);
-}
-/*----------------------------------------------------------------------------*/
-/** Walk the list and abort all batches.
- *
- * @param[in] instance List to use.
- */
-void transfer_list_abort_all(transfer_list_t *instance)
-{
-	fibril_mutex_lock(&instance->guard);
-	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);
-		transfer_list_remove_batch(instance, batch);
-		usb_transfer_batch_finish_error(batch, EIO);
-	}
-	fibril_mutex_unlock(&instance->guard);
-}
-/*----------------------------------------------------------------------------*/
-/** Remove a transfer batch from the list and queue.
- *
- * @param[in] instance List to use.
- * @param[in] batch Transfer batch to remove.
- * @return Error code
- *
- * 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)
-{
-	assert(instance);
-	assert(instance->list_head);
-	assert(batch);
-	assert(batch_ed(batch));
-	assert(fibril_mutex_is_locked(&instance->guard));
-
-	usb_log_debug2(
-	    "Queue %s: removing batch(%p).\n", instance->name, batch);
-
-	const char *qpos = NULL;
-	/* Remove from the hardware queue */
-	if (instance->batch_list.next == &batch->link) {
-		/* I'm the first one here */
-		assert((instance->list_head->next & ED_NEXT_PTR_MASK)
-		    == addr_to_phys(batch_ed(batch)));
-		instance->list_head->next = batch_ed(batch)->next;
-		qpos = "FIRST";
-	} else {
-		usb_transfer_batch_t *prev =
-		    list_get_instance(
-		        batch->link.prev, usb_transfer_batch_t, link);
-		assert((batch_ed(prev)->next & ED_NEXT_PTR_MASK)
-		    == addr_to_phys(batch_ed(batch)));
-		batch_ed(prev)->next = batch_ed(batch)->next;
-		qpos = "NOT FIRST";
-	}
-	asm volatile ("": : :"memory");
-	usb_log_debug("Batch(%p) removed (%s) from %s, next %x.\n",
-	    batch, qpos, instance->name, batch_ed(batch)->next);
-
-	/* Remove from the batch list */
-	list_remove(&batch->link);
-}
-/**
- * @}
- */
Index: uspace/drv/ohci/transfer_list.h
===================================================================
--- uspace/drv/ohci/transfer_list.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ 	(revision )
@@ -1,76 +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 drvusbohci
- * @{
- */
-/** @file
- * @brief OHCI driver transfer list structure
- */
-#ifndef DRV_OHCI_TRANSFER_LIST_H
-#define DRV_OHCI_TRANSFER_LIST_H
-
-#include <fibril_synch.h>
-
-#include "batch.h"
-#include "hw_struct/endpoint_descriptor.h"
-#include "utils/malloc32.h"
-
-typedef struct transfer_list
-{
-	fibril_mutex_t guard;
-	ed_t *list_head;
-	uint32_t list_head_pa;
-	const char *name;
-	link_t batch_list;
-} transfer_list_t;
-
-/** Dispose transfer list structures.
- *
- * @param[in] instance Memory place to use.
- *
- * Frees memory for internal qh_t structure.
- */
-static inline void transfer_list_fini(transfer_list_t *instance)
-{
-	assert(instance);
-	free32(instance->list_head);
-}
-
-int transfer_list_init(transfer_list_t *instance, const char *name);
-
-void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next);
-
-void transfer_list_add_batch(transfer_list_t *instance, usb_transfer_batch_t *batch);
-
-void transfer_list_remove_finished(transfer_list_t *instance, link_t *done);
-
-void transfer_list_abort_all(transfer_list_t *instance);
-#endif
-/**
- * @}
- */
Index: uspace/drv/ohci/utils/malloc32.h
===================================================================
--- uspace/drv/ohci/utils/malloc32.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/ohci/utils/malloc32.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -41,5 +41,4 @@
 #include <as.h>
 
-#define UHCI_STRCUTURES_ALIGNMENT 16
 #define UHCI_REQUIRED_PAGE_SIZE 4096
 
@@ -65,5 +64,5 @@
  */
 static inline void * malloc32(size_t size)
-	{ return memalign(UHCI_STRCUTURES_ALIGNMENT, size); }
+	{ return memalign(size, size); }
 /*----------------------------------------------------------------------------*/
 /** Physical mallocator simulator
Index: uspace/drv/uhci-hcd/batch.c
===================================================================
--- uspace/drv/uhci-hcd/batch.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/uhci-hcd/batch.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -30,5 +30,5 @@
  */
 /** @file
- * @brief UHCI driver USB transaction structure
+ * @brief UHCI driver USB transfer structure
  */
 #include <errno.h>
@@ -45,38 +45,41 @@
 #define DEFAULT_ERROR_COUNT 3
 
-typedef struct uhci_batch {
+typedef struct uhci_transfer_batch {
 	qh_t *qh;
 	td_t *tds;
-	size_t transfers;
-} uhci_batch_t;
+	void *device_buffer;
+	size_t td_count;
+} uhci_transfer_batch_t;
+/*----------------------------------------------------------------------------*/
+static void uhci_transfer_batch_dispose(void *uhci_batch)
+{
+	uhci_transfer_batch_t *instance = uhci_batch;
+	assert(instance);
+	free32(instance->device_buffer);
+	free(instance);
+}
+/*----------------------------------------------------------------------------*/
 
 static void batch_control(usb_transfer_batch_t *instance,
     usb_packet_id data_stage, usb_packet_id status_stage);
 static void batch_data(usb_transfer_batch_t *instance, usb_packet_id pid);
-static void batch_call_in_and_dispose(usb_transfer_batch_t *instance);
-static void batch_call_out_and_dispose(usb_transfer_batch_t *instance);
-
 
 /** Allocate memory and initialize internal data structure.
  *
  * @param[in] fun DDF function to pass to callback.
- * @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 transfers.
- * @param[in] speed Speed of the transaction.
+ * @param[in] ep Communication target
  * @param[in] buffer Data source/destination.
  * @param[in] size Size of the buffer.
  * @param[in] setup_buffer Setup data source (if not NULL)
  * @param[in] setup_size Size of setup_buffer (should be always 8)
- * @param[in] func_in function to call on inbound transaction completion
- * @param[in] func_out function to call on outbound transaction completion
+ * @param[in] func_in function to call on inbound transfer completion
+ * @param[in] func_out function to call on outbound transfer completion
  * @param[in] arg additional parameter to func_in or func_out
- * @param[in] ep Pointer to endpoint toggle management structure.
- * @return Valid pointer if all substructures were successfully created,
+ * @return Valid pointer if all structures were successfully created,
  * NULL otherwise.
  *
- * 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.
+ * Determines the number of needed transfer descriptors (TDs).
+ * Prepares a transport buffer (that is accessible by the hardware).
+ * Initializes parameters needed for the transfer and callback.
  */
 usb_transfer_batch_t * batch_get(ddf_fun_t *fun, endpoint_t *ep,
@@ -92,55 +95,51 @@
 	if (ptr == NULL) { \
 		usb_log_error(message); \
-		if (instance) { \
-			batch_dispose(instance); \
+		if (uhci_data) { \
+			uhci_transfer_batch_dispose(uhci_data); \
 		} \
 		return NULL; \
 	} else (void)0
 
+	uhci_transfer_batch_t *uhci_data =
+	    malloc(sizeof(uhci_transfer_batch_t));
+	CHECK_NULL_DISPOSE_RETURN(uhci_data,
+	    "Failed to allocate UHCI batch.\n");
+	bzero(uhci_data, sizeof(uhci_transfer_batch_t));
+
+	uhci_data->td_count =
+	    (buffer_size + ep->max_packet_size - 1) / ep->max_packet_size;
+	if (ep->transfer_type == USB_TRANSFER_CONTROL) {
+		uhci_data->td_count += 2;
+	}
+
+	assert((sizeof(td_t) % 16) == 0);
+	const size_t total_size = (sizeof(td_t) * uhci_data->td_count)
+	    + sizeof(qh_t) + setup_size + buffer_size;
+	uhci_data->device_buffer = malloc32(total_size);
+	CHECK_NULL_DISPOSE_RETURN(uhci_data->device_buffer,
+	    "Failed to allocate UHCI buffer.\n");
+	bzero(uhci_data->device_buffer, total_size);
+
+	uhci_data->tds = uhci_data->device_buffer;
+	uhci_data->qh =
+	    (uhci_data->device_buffer + (sizeof(td_t) * uhci_data->td_count));
+
+	qh_init(uhci_data->qh);
+	qh_set_element_td(uhci_data->qh, uhci_data->tds);
+
 	usb_transfer_batch_t *instance = malloc(sizeof(usb_transfer_batch_t));
 	CHECK_NULL_DISPOSE_RETURN(instance,
 	    "Failed to allocate batch instance.\n");
+	void *setup =
+	    uhci_data->device_buffer + (sizeof(td_t) * uhci_data->td_count)
+	    + sizeof(qh_t);
+	void *data_buffer = setup + setup_size;
 	usb_target_t target =
 	    { .address = ep->address, .endpoint = ep->endpoint };
-	usb_transfer_batch_init(instance, target, ep->transfer_type, ep->speed,
-	    ep->max_packet_size, buffer, NULL, buffer_size, NULL, setup_size,
-	    func_in, func_out, arg, fun, ep, NULL);
-
-
-	uhci_batch_t *data = malloc(sizeof(uhci_batch_t));
-	CHECK_NULL_DISPOSE_RETURN(data, "Failed to allocate batch data.\n");
-	bzero(data, sizeof(uhci_batch_t));
-	instance->private_data = data;
-
-	data->transfers =
-	    (buffer_size + ep->max_packet_size - 1) / ep->max_packet_size;
-	if (ep->transfer_type == USB_TRANSFER_CONTROL) {
-		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->transfers);
-
-	data->qh = malloc32(sizeof(qh_t));
-	CHECK_NULL_DISPOSE_RETURN(data->qh,
-	    "Failed to allocate batch queue head.\n");
-	qh_init(data->qh);
-	qh_set_element_td(data->qh, addr_to_phys(data->tds));
-
-	if (buffer_size > 0) {
-		instance->transport_buffer = malloc32(buffer_size);
-		CHECK_NULL_DISPOSE_RETURN(instance->transport_buffer,
-		    "Failed to allocate device accessible buffer.\n");
-	}
-
-	if (setup_size > 0) {
-		instance->setup_buffer = malloc32(setup_size);
-		CHECK_NULL_DISPOSE_RETURN(instance->setup_buffer,
-		    "Failed to allocate device accessible setup buffer.\n");
-		memcpy(instance->setup_buffer, setup_buffer, setup_size);
-	}
-
+	usb_transfer_batch_init(instance, ep, buffer, data_buffer, buffer_size,
+	    setup, setup_size, func_in, func_out, arg, fun,
+	    uhci_data, uhci_transfer_batch_dispose);
+
+	memcpy(instance->setup_buffer, setup_buffer, setup_size);
 	usb_log_debug("Batch(%p) %d:%d memory structures ready.\n",
 	    instance, target.address, target.endpoint);
@@ -154,5 +153,5 @@
  *
  * Walk all TDs. Stop with false if there is an active one (it is to be
- * processed). Stop with true if an error is found. Return true if the last TS
+ * processed). Stop with true if an error is found. Return true if the last TD
  * is reached.
  */
@@ -160,12 +159,12 @@
 {
 	assert(instance);
-	uhci_batch_t *data = instance->private_data;
+	uhci_transfer_batch_t *data = instance->private_data;
 	assert(data);
 
 	usb_log_debug2("Batch(%p) checking %d transfer(s) for completion.\n",
-	    instance, data->transfers);
+	    instance, data->td_count);
 	instance->transfered_size = 0;
 	size_t i = 0;
-	for (;i < data->transfers; ++i) {
+	for (;i < data->td_count; ++i) {
 		if (td_is_active(&data->tds[i])) {
 			return false;
@@ -177,6 +176,6 @@
 			    instance, i, data->tds[i].status);
 			td_print_status(&data->tds[i]);
+
 			assert(instance->ep != NULL);
-
 			endpoint_toggle_set(instance->ep,
 			    td_toggle(&data->tds[i]));
@@ -195,9 +194,9 @@
 }
 /*----------------------------------------------------------------------------*/
-/** Prepares control write transaction.
- *
- * @param[in] instance Batch structure to use.
- *
- * Uses genercir control function with pids OUT and IN.
+/** Prepares control write transfer.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Uses generic control function with pids OUT and IN.
  */
 void batch_control_write(usb_transfer_batch_t *instance)
@@ -205,12 +204,11 @@
 	assert(instance);
 	/* We are data out, we are supposed to provide data */
-	memcpy(instance->transport_buffer, instance->buffer,
-	    instance->buffer_size);
+	memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
 	batch_control(instance, USB_PID_OUT, USB_PID_IN);
-	instance->next_step = batch_call_out_and_dispose;
+	instance->next_step = usb_transfer_batch_call_out_and_dispose;
 	usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
 }
 /*----------------------------------------------------------------------------*/
-/** Prepares control read transaction.
+/** Prepares control read transfer.
  *
  * @param[in] instance Batch structure to use.
@@ -222,46 +220,43 @@
 	assert(instance);
 	batch_control(instance, USB_PID_IN, USB_PID_OUT);
-	instance->next_step = batch_call_in_and_dispose;
+	instance->next_step = usb_transfer_batch_call_in_and_dispose;
 	usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance);
 }
 /*----------------------------------------------------------------------------*/
-/** Prepare interrupt in transaction.
- *
- * @param[in] instance Batch structure to use.
- *
- * Data transaction with PID_IN.
+/** Prepare interrupt in transfer.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Data transfer with PID_IN.
  */
 void batch_interrupt_in(usb_transfer_batch_t *instance)
 {
 	assert(instance);
-	instance->direction = USB_DIRECTION_IN;
 	batch_data(instance, USB_PID_IN);
-	instance->next_step = batch_call_in_and_dispose;
+	instance->next_step = usb_transfer_batch_call_in_and_dispose;
 	usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance);
 }
 /*----------------------------------------------------------------------------*/
-/** Prepare interrupt out transaction.
- *
- * @param[in] instance Batch structure to use.
- *
- * Data transaction with PID_OUT.
+/** Prepare interrupt out transfer.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Data transfer with PID_OUT.
  */
 void batch_interrupt_out(usb_transfer_batch_t *instance)
 {
 	assert(instance);
-	instance->direction = USB_DIRECTION_OUT;
 	/* We are data out, we are supposed to provide data */
-	memcpy(instance->transport_buffer, instance->buffer,
-	    instance->buffer_size);
+	memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
 	batch_data(instance, USB_PID_OUT);
-	instance->next_step = batch_call_out_and_dispose;
+	instance->next_step = usb_transfer_batch_call_out_and_dispose;
 	usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance);
 }
 /*----------------------------------------------------------------------------*/
-/** Prepare bulk in transaction.
- *
- * @param[in] instance Batch structure to use.
- *
- * Data transaction with PID_IN.
+/** Prepare bulk in transfer.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Data transfer with PID_IN.
  */
 void batch_bulk_in(usb_transfer_batch_t *instance)
@@ -269,33 +264,30 @@
 	assert(instance);
 	batch_data(instance, USB_PID_IN);
-	instance->direction = USB_DIRECTION_IN;
-	instance->next_step = batch_call_in_and_dispose;
+	instance->next_step = usb_transfer_batch_call_in_and_dispose;
 	usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
 }
 /*----------------------------------------------------------------------------*/
-/** Prepare bulk out transaction.
- *
- * @param[in] instance Batch structure to use.
- *
- * Data transaction with PID_OUT.
+/** Prepare bulk out transfer.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Data transfer with PID_OUT.
  */
 void batch_bulk_out(usb_transfer_batch_t *instance)
 {
 	assert(instance);
-	instance->direction = USB_DIRECTION_OUT;
 	/* We are data out, we are supposed to provide data */
-	memcpy(instance->transport_buffer, instance->buffer,
-	    instance->buffer_size);
+	memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
 	batch_data(instance, USB_PID_OUT);
-	instance->next_step = batch_call_out_and_dispose;
+	instance->next_step = usb_transfer_batch_call_out_and_dispose;
 	usb_log_debug("Batch(%p) BULK OUT initialized.\n", instance);
 }
 /*----------------------------------------------------------------------------*/
-/** Prepare generic data transaction
- *
- * @param[in] instance Batch structure to use.
- * @param[in] pid Pid to use for data transfers.
- *
- * Packets with alternating toggle bit and supplied pid value.
+/** Prepare generic data transfer
+ *
+ * @param[in] instance Batch structure to use.
+ * @param[in] pid Pid to use for data transactions.
+ *
+ * Transactions with alternating toggle bit and supplied pid value.
  * The last transfer is marked with IOC flag.
  */
@@ -303,47 +295,46 @@
 {
 	assert(instance);
-	uhci_batch_t *data = instance->private_data;
+	uhci_transfer_batch_t *data = instance->private_data;
 	assert(data);
 
-	const bool low_speed = instance->speed == USB_SPEED_LOW;
+	const bool low_speed = instance->ep->speed == USB_SPEED_LOW;
 	int toggle = endpoint_toggle_get(instance->ep);
 	assert(toggle == 0 || toggle == 1);
 
-	size_t transfer = 0;
+	size_t td = 0;
 	size_t remain_size = instance->buffer_size;
+	char *buffer = instance->data_buffer;
 	while (remain_size > 0) {
-		char *trans_data =
-		    instance->transport_buffer + instance->buffer_size
-		    - remain_size;
-
 		const size_t packet_size =
-		    (instance->max_packet_size > remain_size) ?
-		    remain_size : instance->max_packet_size;
-
-		td_t *next_transfer = (transfer + 1 < data->transfers)
-		    ? &data->tds[transfer + 1] : NULL;
-
-		assert(transfer < data->transfers);
+		    (instance->ep->max_packet_size > remain_size) ?
+		    remain_size : instance->ep->max_packet_size;
+
+		td_t *next_td = (td + 1 < data->td_count)
+		    ? &data->tds[td + 1] : NULL;
+
+
+		usb_target_t target =
+		    { instance->ep->address, instance->ep->endpoint };
+
+		assert(td < data->td_count);
+		td_init(
+		    &data->tds[td], DEFAULT_ERROR_COUNT, packet_size,
+		    toggle, false, low_speed, target, pid, buffer, next_td);
+
+		++td;
+		toggle = 1 - toggle;
+		buffer += packet_size;
 		assert(packet_size <= remain_size);
-
-		td_init(
-		    &data->tds[transfer], DEFAULT_ERROR_COUNT, packet_size,
-		    toggle, false, low_speed, instance->target, pid, trans_data,
-		    next_transfer);
-
-
-		toggle = 1 - toggle;
 		remain_size -= packet_size;
-		++transfer;
 	}
-	td_set_ioc(&data->tds[transfer - 1]);
+	td_set_ioc(&data->tds[td - 1]);
 	endpoint_toggle_set(instance->ep, toggle);
 }
 /*----------------------------------------------------------------------------*/
-/** Prepare generic control transaction
- *
- * @param[in] instance Batch structure to use.
- * @param[in] data_stage Pid to use for data transfers.
- * @param[in] status_stage Pid to use for data transfers.
+/** Prepare generic control transfer
+ *
+ * @param[in] instance Batch structure to use.
+ * @param[in] data_stage Pid to use for data tds.
+ * @param[in] status_stage Pid to use for data tds.
  *
  * Setup stage with toggle 0 and USB_PID_SETUP.
@@ -356,37 +347,37 @@
 {
 	assert(instance);
-	uhci_batch_t *data = instance->private_data;
+	uhci_transfer_batch_t *data = instance->private_data;
 	assert(data);
-	assert(data->transfers >= 2);
-
-	const bool low_speed = instance->speed == USB_SPEED_LOW;
-	int toggle = 0;
+	assert(data->td_count >= 2);
+
+	const bool low_speed = instance->ep->speed == USB_SPEED_LOW;
+	const usb_target_t target =
+	    { instance->ep->address, instance->ep->endpoint };
+
 	/* setup stage */
 	td_init(
-	    data->tds, DEFAULT_ERROR_COUNT, instance->setup_size, toggle, false,
-	    low_speed, instance->target, USB_PID_SETUP, instance->setup_buffer,
+	    data->tds, DEFAULT_ERROR_COUNT, instance->setup_size, 0, false,
+	    low_speed, target, USB_PID_SETUP, instance->setup_buffer,
 	    &data->tds[1]);
 
 	/* data stage */
-	size_t transfer = 1;
+	size_t td = 1;
+	unsigned toggle = 1;
 	size_t remain_size = instance->buffer_size;
+	char *buffer = instance->data_buffer;
 	while (remain_size > 0) {
-		char *control_data =
-		    instance->transport_buffer + instance->buffer_size
-		    - remain_size;
-
+		const size_t packet_size =
+		    (instance->ep->max_packet_size > remain_size) ?
+		    remain_size : instance->ep->max_packet_size;
+
+		td_init(
+		    &data->tds[td], DEFAULT_ERROR_COUNT, packet_size,
+		    toggle, false, low_speed, target, data_stage,
+		    buffer, &data->tds[td + 1]);
+
+		++td;
 		toggle = 1 - toggle;
-
-		const size_t packet_size =
-		    (instance->max_packet_size > remain_size) ?
-		    remain_size : instance->max_packet_size;
-
-		td_init(
-		    &data->tds[transfer], DEFAULT_ERROR_COUNT, packet_size,
-		    toggle, false, low_speed, instance->target, data_stage,
-		    control_data, &data->tds[transfer + 1]);
-
-		++transfer;
-		assert(transfer < data->transfers);
+		buffer += packet_size;
+		assert(td < data->td_count);
 		assert(packet_size <= remain_size);
 		remain_size -= packet_size;
@@ -394,63 +385,26 @@
 
 	/* status stage */
-	assert(transfer == data->transfers - 1);
+	assert(td == data->td_count - 1);
 
 	td_init(
-	    &data->tds[transfer], DEFAULT_ERROR_COUNT, 0, 1, false, low_speed,
-	    instance->target, status_stage, NULL, NULL);
-	td_set_ioc(&data->tds[transfer]);
+	    &data->tds[td], DEFAULT_ERROR_COUNT, 0, 1, false, low_speed,
+	    target, status_stage, NULL, NULL);
+	td_set_ioc(&data->tds[td]);
 
 	usb_log_debug2("Control last TD status: %x.\n",
-	    data->tds[transfer].status);
-}
-/*----------------------------------------------------------------------------*/
+	    data->tds[td].status);
+}
+/*----------------------------------------------------------------------------*/
+/** Provides access to QH data structure.
+ * @param[in] instance Batch pointer to use.
+ * @return Pointer to the QH used by the batch.
+ */
 qh_t * batch_qh(usb_transfer_batch_t *instance)
 {
 	assert(instance);
-	uhci_batch_t *data = instance->private_data;
+	uhci_transfer_batch_t *data = instance->private_data;
 	assert(data);
 	return data->qh;
 }
-/*----------------------------------------------------------------------------*/
-/** Helper function calls callback and correctly disposes of batch structure.
- *
- * @param[in] instance Batch structure to use.
- */
-void batch_call_in_and_dispose(usb_transfer_batch_t *instance)
-{
-	assert(instance);
-	usb_transfer_batch_call_in(instance);
-	batch_dispose(instance);
-}
-/*----------------------------------------------------------------------------*/
-/** Helper function calls callback and correctly disposes of batch structure.
- *
- * @param[in] instance Batch structure to use.
- */
-void batch_call_out_and_dispose(usb_transfer_batch_t *instance)
-{
-	assert(instance);
-	usb_transfer_batch_call_out(instance);
-	batch_dispose(instance);
-}
-/*----------------------------------------------------------------------------*/
-/** Correctly dispose all used data structures.
- *
- * @param[in] instance Batch structure to use.
- */
-void batch_dispose(usb_transfer_batch_t *instance)
-{
-	assert(instance);
-	uhci_batch_t *data = instance->private_data;
-	assert(data);
-	usb_log_debug("Batch(%p) disposing.\n", instance);
-	/* free32 is NULL safe */
-	free32(data->tds);
-	free32(data->qh);
-	free32(instance->setup_buffer);
-	free32(instance->transport_buffer);
-	free(data);
-	free(instance);
-}
 /**
  * @}
Index: uspace/drv/uhci-hcd/batch.h
===================================================================
--- uspace/drv/uhci-hcd/batch.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/uhci-hcd/batch.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -30,5 +30,5 @@
  */
 /** @file
- * @brief UHCI driver USB transaction structure
+ * @brief UHCI driver USB tranfer helper functions
  */
 #ifndef DRV_UHCI_BATCH_H
Index: uspace/drv/uhci-hcd/hc.c
===================================================================
--- uspace/drv/uhci-hcd/hc.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/uhci-hcd/hc.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -66,8 +66,4 @@
 static int hc_interrupt_emulator(void *arg);
 static int hc_debug_checker(void *arg);
-#if 0
-static bool usb_is_allowed(
-    bool low_speed, usb_transfer_type_t transfer, size_t size);
-#endif
 /*----------------------------------------------------------------------------*/
 /** Initialize UHCI hcd driver structure
@@ -89,9 +85,7 @@
 	int ret;
 
-#define CHECK_RET_DEST_FUN_RETURN(ret, message...) \
+#define CHECK_RET_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
@@ -99,14 +93,11 @@
 	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,
+	CHECK_RET_RETURN(ret,
 	    "Failed(%d) to gain access to registers at %p: %s.\n",
-	    ret, str_error(ret), io);
+	    ret, io, str_error(ret));
 	instance->registers = io;
 	usb_log_debug("Device registers at %p(%u) accessible.\n",
@@ -114,19 +105,15 @@
 
 	ret = hc_init_mem_structures(instance);
-	CHECK_RET_DEST_FUN_RETURN(ret,
-	    "Failed to initialize UHCI memory structures.\n");
+	CHECK_RET_RETURN(ret,
+	    "Failed(%d) to initialize UHCI memory structures: %s.\n",
+	    ret, str_error(ret));
 
 	hc_init_hw(instance);
 	if (!interrupts) {
-		instance->cleaner =
+		instance->interrupt_emulator =
 		    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);
+		fibril_add_ready(instance->interrupt_emulator);
+	}
+	(void)hc_debug_checker;
 
 	return EOK;
@@ -228,6 +215,6 @@
 	/* 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;
+	    LINK_POINTER_QH(addr_to_phys(
+	        instance->transfers_interrupt.queue_head));
 
 	unsigned i = 0;
@@ -236,5 +223,5 @@
 	}
 
-	/* Init device keeper*/
+	/* Init device keeper */
 	usb_device_keeper_init(&instance->manager);
 	usb_log_debug("Initialized device manager.\n");
@@ -260,7 +247,10 @@
 {
 	assert(instance);
-#define CHECK_RET_CLEAR_RETURN(ret, message...) \
+#define SETUP_TRANSFER_LIST(type, name) \
+do { \
+	int ret = transfer_list_init(&instance->transfers_##type, name); \
 	if (ret != EOK) { \
-		usb_log_error(message); \
+		usb_log_error("Failed(%d) to setup %s transfer list: %s.\n", \
+		    ret, name, str_error(ret)); \
 		transfer_list_fini(&instance->transfers_bulk_full); \
 		transfer_list_fini(&instance->transfers_control_full); \
@@ -268,22 +258,13 @@
 		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.");
-
+	} \
+} while (0)
+
+	SETUP_TRANSFER_LIST(bulk_full, "BULK FULL");
+	SETUP_TRANSFER_LIST(control_full, "CONTROL FULL");
+	SETUP_TRANSFER_LIST(control_slow, "CONTROL LOW");
+	SETUP_TRANSFER_LIST(interrupt, "INTERRUPT");
+#undef SETUP_TRANSFER_LIST
+	/* Connect lists into one schedule */
 	transfer_list_set_next(&instance->transfers_control_full,
 		&instance->transfers_bulk_full);
@@ -329,5 +310,5 @@
 
 	transfer_list_t *list =
-	    instance->transfers[batch->speed][batch->transfer_type];
+	    instance->transfers[batch->ep->speed][batch->ep->transfer_type];
 	assert(list);
 	transfer_list_add_batch(list, batch);
@@ -350,7 +331,6 @@
 	assert(instance);
 //	status |= 1; //Uncomment to work around qemu hang
-	/* TODO: Resume interrupts are not supported */
 	/* Lower 2 bits are transaction error and transaction complete */
-	if (status & 0x3) {
+	if (status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) {
 		LIST_INITIALIZE(done);
 		transfer_list_remove_finished(
@@ -371,6 +351,8 @@
 		}
 	}
-	/* bits 4 and 5 indicate hc error */
-	if (status & 0x18) {
+	/* Resume interrupts are not supported */
+
+	/* Bits 4 and 5 indicate hc error */
+	if (status & (UHCI_STATUS_PROCESS_ERROR | UHCI_STATUS_SYSTEM_ERROR)) {
 		usb_log_error("UHCI hardware failure!.\n");
 		++instance->hw_failures;
@@ -402,11 +384,11 @@
 
 	while (1) {
-		/* read and ack interrupts */
+		/* Readd and clear status register */
 		uint16_t status = pio_read_16(&instance->registers->usbsts);
-		pio_write_16(&instance->registers->usbsts, 0x1f);
+		pio_write_16(&instance->registers->usbsts, status);
 		if (status != 0)
 			usb_log_debug2("UHCI status: %x.\n", status);
 		hc_interrupt(instance, status);
-		async_usleep(UHCI_CLEANER_TIMEOUT);
+		async_usleep(UHCI_INT_EMULATOR_TIMEOUT);
 	}
 	return EOK;
@@ -479,31 +461,4 @@
 #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
- */
-#if 0
-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;
-}
-#endif
 /**
  * @}
Index: uspace/drv/uhci-hcd/hc.h
===================================================================
--- uspace/drv/uhci-hcd/hc.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/uhci-hcd/hc.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -48,5 +48,7 @@
 #include "transfer_list.h"
 
+/** UHCI I/O registers layout */
 typedef struct uhci_regs {
+	/** Command register, controls HC behaviour */
 	uint16_t usbcmd;
 #define UHCI_CMD_MAX_PACKET (1 << 7)
@@ -59,4 +61,5 @@
 #define UHCI_CMD_RUN_STOP  (1 << 0)
 
+	/** Status register, 1 means interrupt is asserted (if enabled) */
 	uint16_t usbsts;
 #define UHCI_STATUS_HALTED (1 << 5)
@@ -67,4 +70,5 @@
 #define UHCI_STATUS_INTERRUPT (1 << 0)
 
+	/** Interrupt enabled registers */
 	uint16_t usbintr;
 #define UHCI_INTR_SHORT_PACKET (1 << 3)
@@ -73,37 +77,55 @@
 #define UHCI_INTR_CRC (1 << 0)
 
+	/** Register stores frame number used in SOF packet */
 	uint16_t frnum;
+
+	/** Pointer(physical) to the Frame List */
 	uint32_t flbaseadd;
+
+	/** SOF modification to match external timers */
 	uint8_t sofmod;
 } regs_t;
 
 #define UHCI_FRAME_LIST_COUNT 1024
-#define UHCI_CLEANER_TIMEOUT 10000
+#define UHCI_INT_EMULATOR_TIMEOUT 10000
 #define UHCI_DEBUGER_TIMEOUT 5000000
 #define UHCI_ALLOWED_HW_FAIL 5
 
+/* Main HC driver structure */
 typedef struct hc {
+	/** USB bus driver, devices and addresses */
 	usb_device_keeper_t manager;
+	/** USB bus driver, endpoints */
 	usb_endpoint_manager_t ep_manager;
 
+	/** Addresses of I/O registers */
 	regs_t *registers;
 
+	/** Frame List contains 1024 link pointers */
 	link_pointer_t *frame_list;
 
+	/** List and queue of interrupt transfers */
+	transfer_list_t transfers_interrupt;
+	/** List and queue of low speed control transfers */
+	transfer_list_t transfers_control_slow;
+	/** List and queue of full speed bulk transfers */
 	transfer_list_t transfers_bulk_full;
+	/** List and queue of full speed control transfers */
 	transfer_list_t transfers_control_full;
-	transfer_list_t transfers_control_slow;
-	transfer_list_t transfers_interrupt;
 
+	/** Pointer table to the above lists, helps during scheduling */
 	transfer_list_t *transfers[2][4];
 
+	/** Code to be executed in kernel interrupt handler */
 	irq_code_t interrupt_code;
 
-	fid_t cleaner;
-	fid_t debug_checker;
+	/** Fibril periodically checking status register*/
+	fid_t interrupt_emulator;
+
+	/** Indicator of hw interrupts availability */
 	bool hw_interrupts;
+
+	/** Number of hw failures detected. */
 	unsigned hw_failures;
-
-	ddf_fun_t *ddf_instance;
 } hc_t;
 
Index: uspace/drv/uhci-hcd/hw_struct/queue_head.h
===================================================================
--- uspace/drv/uhci-hcd/hw_struct/queue_head.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/uhci-hcd/hw_struct/queue_head.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -34,12 +34,15 @@
 #ifndef DRV_UHCI_QH_H
 #define DRV_UHCI_QH_H
-
-/* libc */
 #include <assert.h>
 
 #include "link_pointer.h"
+#include "transfer_descriptor.h"
+#include "utils/malloc32.h"
 
+/** This structure is defined in UHCI design guide p. 31 */
 typedef struct queue_head {
+	/** Pointer to the next entity (another QH or TD */
 	volatile link_pointer_t next;
+	/** Pointer to the contained entities (execution controlled by vertical flag*/
 	volatile link_pointer_t element;
 } __attribute__((packed)) qh_t;
@@ -64,11 +67,10 @@
  * @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.
+ * Adds proper flag. If the pointer is NULL, sets next to terminal NULL.
  */
-static inline void qh_set_next_qh(qh_t *instance, uint32_t pa)
+static inline void qh_set_next_qh(qh_t *instance, qh_t *next)
 {
-	/* Address is valid and not terminal */
-	if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) {
+	uint32_t pa = addr_to_phys(next);
+	if (pa) {
 		instance->next = LINK_POINTER_QH(pa);
 	} else {
@@ -80,30 +82,12 @@
  *
  * @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.
+ * Adds proper flag. If the pointer is NULL, sets element to terminal NULL.
  */
-static inline void qh_set_element_td(qh_t *instance, uint32_t pa)
+static inline void qh_set_element_td(qh_t *instance, td_t *td)
 {
-	if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) {
+	uint32_t pa = addr_to_phys(td);
+	if (pa) {
 		instance->element = LINK_POINTER_TD(pa);
 	} else {
@@ -111,5 +95,4 @@
 	}
 }
-
 #endif
 /**
Index: uspace/drv/uhci-hcd/hw_struct/transfer_descriptor.c
===================================================================
--- uspace/drv/uhci-hcd/hw_struct/transfer_descriptor.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/uhci-hcd/hw_struct/transfer_descriptor.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -77,5 +77,6 @@
 
 	instance->status = 0
-	    | ((err_count & TD_STATUS_ERROR_COUNT_MASK) << TD_STATUS_ERROR_COUNT_POS)
+	    | ((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)
@@ -89,6 +90,8 @@
 	    | (((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)
+	    | ((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);
 
@@ -114,5 +117,5 @@
 	assert(instance);
 
-	/* this is hc internal error it should never be reported */
+	/* This is hc internal error it should never be reported. */
 	if ((instance->status & TD_STATUS_ERROR_BIT_STUFF) != 0)
 		return EAGAIN;
@@ -123,18 +126,18 @@
 		return EBADCHECKSUM;
 
-	/* hc does not end transaction on these, it should never be reported */
+	/* HC does not end transactions on these, it should never be reported */
 	if ((instance->status & TD_STATUS_ERROR_NAK) != 0)
 		return EAGAIN;
 
-	/* buffer overrun or underrun */
+	/* Buffer overrun or underrun */
 	if ((instance->status & TD_STATUS_ERROR_BUFFER) != 0)
 		return ERANGE;
 
-	/* device babble is something serious */
+	/* 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*/
+	/* Stall might represent err count reaching zero or stall response from
+	 * the device. If err count reached zero, one of the above is reported*/
 	if ((instance->status & TD_STATUS_ERROR_STALLED) != 0)
 		return ESTALL;
Index: uspace/drv/uhci-hcd/hw_struct/transfer_descriptor.h
===================================================================
--- uspace/drv/uhci-hcd/hw_struct/transfer_descriptor.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/uhci-hcd/hw_struct/transfer_descriptor.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -40,48 +40,53 @@
 #include "link_pointer.h"
 
-/** UHCI Transfer Descriptor */
+/** Transfer Descriptor, defined in UHCI design guide p. 26 */
 typedef struct transfer_descriptor {
+	/** Pointer to the next entity (TD or QH) */
 	link_pointer_t next;
 
+	/** Status doubleword */
 	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_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_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_ERROR_MASK 0xff
 
 #define TD_STATUS_ACTLEN_POS 0
 #define TD_STATUS_ACTLEN_MASK 0x7ff
 
+	/* double word with USB device specific info */
 	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_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_ENDPOINT_MASK 0xf
 #define TD_DEVICE_ADDRESS_POS 8
-#define TD_DEVICE_ADDRESS_MASK ( 0x7f )
+#define TD_DEVICE_ADDRESS_MASK 0x7f
 #define TD_DEVICE_PID_POS 0
-#define TD_DEVICE_PID_MASK ( 0xff )
+#define TD_DEVICE_PID_MASK 0xff
 
+	/** Pointer(physical) to the beginning of the transaction's buffer */
 	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
+	/* According to UHCI design guide, there is 16 bytes of
+	 * data available here.
+	 * 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;
Index: uspace/drv/uhci-hcd/iface.c
===================================================================
--- uspace/drv/uhci-hcd/iface.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/uhci-hcd/iface.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -148,5 +148,4 @@
 	assert(hc);
 	const size_t size = max_packet_size;
-	int ret;
 	usb_speed_t speed = usb_device_keeper_get_speed(&hc->manager, address);
 	if (speed >= USB_SPEED_MAX) {
@@ -157,20 +156,6 @@
 	    usb_str_speed(speed), direction, size, max_packet_size, interval);
 
-
-	endpoint_t *ep = malloc(sizeof(endpoint_t));
-	if (ep == NULL)
-		return ENOMEM;
-	ret = endpoint_init(ep, address, endpoint, direction,
-	    transfer_type, speed, max_packet_size);
-	if (ret != EOK) {
-		free(ep);
-		return ret;
-	}
-
-	ret = usb_endpoint_manager_register_ep(&hc->ep_manager, ep, size);
-	if (ret != EOK) {
-		endpoint_destroy(ep);
-	}
-	return ret;
+	return usb_endpoint_manager_add_ep(&hc->ep_manager, address, endpoint,
+	    direction, transfer_type, speed, max_packet_size, size);
 }
 /*----------------------------------------------------------------------------*/
@@ -210,5 +195,5 @@
 	ret = hc_schedule(hc, batch);
 	if (ret != EOK) {
-		batch_dispose(batch);
+		usb_transfer_batch_dispose(batch);
 	}
 	return ret;
@@ -238,5 +223,5 @@
 	ret = hc_schedule(hc, batch);
 	if (ret != EOK) {
-		batch_dispose(batch);
+		usb_transfer_batch_dispose(batch);
 	}
 	return ret;
@@ -266,5 +251,5 @@
 	ret = hc_schedule(hc, batch);
 	if (ret != EOK) {
-		batch_dispose(batch);
+		usb_transfer_batch_dispose(batch);
 	}
 	return ret;
@@ -294,5 +279,5 @@
 	ret = hc_schedule(hc, batch);
 	if (ret != EOK) {
-		batch_dispose(batch);
+		usb_transfer_batch_dispose(batch);
 	}
 	return ret;
@@ -327,5 +312,5 @@
 	ret = hc_schedule(hc, batch);
 	if (ret != EOK) {
-		batch_dispose(batch);
+		usb_transfer_batch_dispose(batch);
 	}
 	return ret;
@@ -359,5 +344,5 @@
 	ret = hc_schedule(hc, batch);
 	if (ret != EOK) {
-		batch_dispose(batch);
+		usb_transfer_batch_dispose(batch);
 	}
 	return ret;
Index: uspace/drv/uhci-hcd/main.c
===================================================================
--- uspace/drv/uhci-hcd/main.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/uhci-hcd/main.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -39,5 +39,4 @@
 #include <usb/debug.h>
 
-#include "iface.h"
 #include "uhci.h"
 
@@ -62,6 +61,7 @@
 int uhci_add_device(ddf_dev_t *device)
 {
-	usb_log_debug("uhci_add_device() called\n");
+	usb_log_debug2("uhci_add_device() called\n");
 	assert(device);
+
 	uhci_t *uhci = malloc(sizeof(uhci_t));
 	if (uhci == NULL) {
@@ -72,11 +72,11 @@
 	int ret = uhci_init(uhci, device);
 	if (ret != EOK) {
-		usb_log_error("Failed to initialize UHCI driver: %s.\n",
-		    str_error(ret));
+		usb_log_error("Failed(%d) to initialize UHCI driver: %s.\n",
+		    ret, str_error(ret));
 		return ret;
 	}
 	device->driver_data = uhci;
 
-	usb_log_info("Controlling new UHCI device `%s'.\n", device->name);
+	usb_log_info("Controlling new UHCI device '%s'.\n", device->name);
 
 	return EOK;
@@ -85,5 +85,5 @@
 /** Initialize global driver structures (NONE).
  *
- * @param[in] argc Nmber of arguments in argv vector (ignored).
+ * @param[in] argc Number of arguments in argv vector (ignored).
  * @param[in] argv Cmdline argument vector (ignored).
  * @return Error code.
@@ -94,6 +94,4 @@
 {
 	printf(NAME ": HelenOS UHCI driver.\n");
-
-	sleep(3); /* TODO: remove in final version */
 	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
 
Index: uspace/drv/uhci-hcd/pci.c
===================================================================
--- uspace/drv/uhci-hcd/pci.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/uhci-hcd/pci.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -44,5 +44,5 @@
 #include "pci.h"
 
-/** Get address of registers and IRQ for given device.
+/** Get I/O address of registers and IRQ for given device.
  *
  * @param[in] dev Device asking for the addresses.
@@ -53,18 +53,16 @@
  */
 int pci_get_my_registers(ddf_dev_t *dev,
-    uintptr_t *io_reg_address, size_t *io_reg_size,
-    int *irq_no)
+    uintptr_t *io_reg_address, size_t *io_reg_size, int *irq_no)
 {
 	assert(dev != NULL);
 
-	int parent_phone = devman_parent_device_connect(dev->handle,
-	    IPC_FLAG_BLOCKING);
+	int parent_phone =
+	    devman_parent_device_connect(dev->handle, IPC_FLAG_BLOCKING);
 	if (parent_phone < 0) {
 		return parent_phone;
 	}
 
-	int rc;
 	hw_resource_list_t hw_resources;
-	rc = hw_res_get_resource_list(parent_phone, &hw_resources);
+	int rc = hw_res_get_resource_list(parent_phone, &hw_resources);
 	if (rc != EOK) {
 		goto leave;
@@ -95,4 +93,5 @@
 			    res->res.io_range.address, res->res.io_range.size);
 			io_found = true;
+			break;
 
 		default:
@@ -113,5 +112,4 @@
 leave:
 	async_hangup(parent_phone);
-
 	return rc;
 }
@@ -145,5 +143,5 @@
 	}
 
-	/* See UHCI design guide for these values,
+	/* See UHCI design guide for these values p.45,
 	 * write all WC bits in USB legacy register */
 	sysarg_t address = 0xc0;
Index: uspace/drv/uhci-hcd/root_hub.c
===================================================================
--- uspace/drv/uhci-hcd/root_hub.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/uhci-hcd/root_hub.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -55,10 +55,13 @@
 	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;
+		usb_log_error(
+		    "Failed(%d) to create root hub match string: %s.\n",
+		    ret, str_error(ret));
+		return ret;
 	}
 
 	ret = ddf_fun_add_match_id(fun, match_str, 100);
 	if (ret != EOK) {
+		free(match_str);
 		usb_log_error("Failed(%d) to add root hub match id: %s\n",
 		    ret, str_error(ret));
@@ -66,8 +69,8 @@
 	}
 
-	hw_resource_list_t *resource_list = &instance->resource_list;
-	resource_list->count = 1;
-	resource_list->resources = &instance->io_regs;
-	assert(resource_list->resources);
+	/* Initialize resource structure */
+	instance->resource_list.count = 1;
+	instance->resource_list.resources = &instance->io_regs;
+
 	instance->io_regs.type = IO_RANGE;
 	instance->io_regs.res.io_range.address = reg_addr;
Index: uspace/drv/uhci-hcd/root_hub.h
===================================================================
--- uspace/drv/uhci-hcd/root_hub.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/uhci-hcd/root_hub.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -39,6 +39,9 @@
 #include <ops/hw_res.h>
 
+/** DDF support structure for uhci-rhd driver, provides I/O resources */
 typedef struct rh {
+	/** List of resources available to the root hub. */
 	hw_resource_list_t resource_list;
+	/** The only resource in the above list */
 	hw_resource_t io_regs;
 } rh_t;
Index: uspace/drv/uhci-hcd/transfer_list.c
===================================================================
--- uspace/drv/uhci-hcd/transfer_list.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/uhci-hcd/transfer_list.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -57,7 +57,7 @@
 		return ENOMEM;
 	}
-	instance->queue_head_pa = addr_to_phys(instance->queue_head);
+	uint32_t queue_head_pa = addr_to_phys(instance->queue_head);
 	usb_log_debug2("Transfer list %s setup with QH: %p(%p).\n",
-	    name, instance->queue_head, instance->queue_head_pa);
+	    name, instance->queue_head, queue_head_pa);
 
 	qh_init(instance->queue_head);
@@ -67,4 +67,15 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Dispose transfer list structures.
+ *
+ * @param[in] instance Memory place to use.
+ *
+ * Frees memory for internal qh_t structure.
+ */
+void transfer_list_fini(transfer_list_t *instance)
+{
+	assert(instance);
+	free32(instance->queue_head);
+}
 /** Set the next list in transfer list chain.
  *
@@ -81,13 +92,12 @@
 	if (!instance->queue_head)
 		return;
-	/* Set both queue_head.next to point to the follower */
-	qh_set_next_qh(instance->queue_head, next->queue_head_pa);
-}
-/*----------------------------------------------------------------------------*/
-/** Submit transfer batch to the list and queue.
+	/* Set queue_head.next to point to the follower */
+	qh_set_next_qh(instance->queue_head, next->queue_head);
+}
+/*----------------------------------------------------------------------------*/
+/** Add transfer batch to the list and queue.
  *
  * @param[in] instance List to use.
  * @param[in] batch Transfer batch to submit.
- * @return Error code
  *
  * The batch is added to the end of the list and queue.
@@ -109,6 +119,6 @@
 	} else {
 		/* There is something scheduled */
-		usb_transfer_batch_t *last = list_get_instance(
-		    instance->batch_list.prev, usb_transfer_batch_t, link);
+		usb_transfer_batch_t *last =
+		    usb_transfer_batch_from_link(instance->batch_list.prev);
 		last_qh = batch_qh(last);
 	}
@@ -118,5 +128,5 @@
 	/* keep link */
 	batch_qh(batch)->next = last_qh->next;
-	qh_set_next_qh(last_qh, pa);
+	qh_set_next_qh(last_qh, batch_qh(batch));
 
 	asm volatile ("": : :"memory");
@@ -132,5 +142,5 @@
 }
 /*----------------------------------------------------------------------------*/
-/** Create list for finished batches.
+/** Add completed bantches to the provided list.
  *
  * @param[in] instance List to use.
@@ -147,8 +157,8 @@
 		link_t *next = current->next;
 		usb_transfer_batch_t *batch =
-		    list_get_instance(current, usb_transfer_batch_t, link);
+		    usb_transfer_batch_from_link(current);
 
 		if (batch_is_complete(batch)) {
-			/* Save for post-processing */
+			/* Save for processing */
 			transfer_list_remove_batch(instance, batch);
 			list_append(current, done);
@@ -159,5 +169,5 @@
 }
 /*----------------------------------------------------------------------------*/
-/** Walk the list and abort all batches.
+/** Walk the list and finish all batches with EINTR.
  *
  * @param[in] instance List to use.
@@ -169,7 +179,7 @@
 		link_t *current = instance->batch_list.next;
 		usb_transfer_batch_t *batch =
-		    list_get_instance(current, usb_transfer_batch_t, link);
+		    usb_transfer_batch_from_link(current);
 		transfer_list_remove_batch(instance, batch);
-		usb_transfer_batch_finish_error(batch, EIO);
+		usb_transfer_batch_finish_error(batch, EINTR);
 	}
 	fibril_mutex_unlock(&instance->guard);
@@ -180,5 +190,4 @@
  * @param[in] instance List to use.
  * @param[in] batch Transfer batch to remove.
- * @return Error code
  *
  * Does not lock the transfer list, caller is responsible for that.
@@ -197,24 +206,24 @@
 
 	const char *qpos = NULL;
+	qh_t *prev_qh = NULL;
 	/* Remove from the hardware queue */
 	if (instance->batch_list.next == &batch->link) {
 		/* I'm the first one here */
-		assert((instance->queue_head->next & LINK_POINTER_ADDRESS_MASK)
-		    == addr_to_phys(batch_qh(batch)));
-		instance->queue_head->next = batch_qh(batch)->next;
+		prev_qh = instance->queue_head;
 		qpos = "FIRST";
 	} else {
+		/* The thing before me is a batch too */
 		usb_transfer_batch_t *prev =
-		    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;
+		    usb_transfer_batch_from_link(batch->link.prev);
+		prev_qh = batch_qh(prev);
 		qpos = "NOT FIRST";
 	}
+	assert((prev_qh->next & LINK_POINTER_ADDRESS_MASK)
+	    == addr_to_phys(batch_qh(batch)));
+	prev_qh->next = batch_qh(batch)->next;
 	asm volatile ("": : :"memory");
 	/* Remove from the batch list */
 	list_remove(&batch->link);
-	usb_log_debug("Batch(%p) removed (%s) from %s, next %x.\n",
+	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 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/uhci-hcd/transfer_list.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -39,35 +39,26 @@
 #include "batch.h"
 #include "hw_struct/queue_head.h"
-#include "utils/malloc32.h"
 
+/** Structure maintaining both hw queue and software list
+ * of currently executed transfers
+ */
 typedef struct transfer_list
 {
+	/** Guard against multiple add/remove races */
 	fibril_mutex_t guard;
+	/** UHCI hw structure represeting this queue */
 	qh_t *queue_head;
-	uint32_t queue_head_pa;
+	/** Assigned name, for nicer debug output */
 	const char *name;
+	/** List of all batches in this list */
 	link_t batch_list;
 } transfer_list_t;
 
-/** Dispose transfer list structures.
- *
- * @param[in] instance Memory place to use.
- *
- * Frees memory for internal qh_t structure.
- */
-static inline void transfer_list_fini(transfer_list_t *instance)
-{
-	assert(instance);
-	free32(instance->queue_head);
-}
-
+void transfer_list_fini(transfer_list_t *instance);
 int transfer_list_init(transfer_list_t *instance, const char *name);
-
 void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next);
-
-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);
 void transfer_list_remove_finished(transfer_list_t *instance, link_t *done);
-
 void transfer_list_abort_all(transfer_list_t *instance);
 #endif
Index: uspace/drv/uhci-hcd/uhci.c
===================================================================
--- uspace/drv/uhci-hcd/uhci.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/uhci-hcd/uhci.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -44,9 +44,9 @@
 #include "pci.h"
 
-/** IRQ handling callback, identifies device
+/** IRQ handling callback, forward status from call to diver structure.
  *
  * @param[in] dev DDF instance of the device to use.
  * @param[in] iid (Unused).
- * @param[in] call Pointer to the call that represents interrupt.
+ * @param[in] call Pointer to the call from kernel.
  */
 static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call)
@@ -61,7 +61,7 @@
 /** Get address of the device identified by handle.
  *
- * @param[in] dev DDF instance of the device to use.
- * @param[in] iid (Unused).
- * @param[in] call Pointer to the call that represents interrupt.
+ * @param[in] fun DDF instance of the function to use.
+ * @param[in] handle DDF handle of the driver seeking its USB address.
+ * @param[out] address Found address.
  */
 static int usb_iface_get_address(
@@ -69,5 +69,6 @@
 {
 	assert(fun);
-	usb_device_keeper_t *manager = &((uhci_t*)fun->dev->driver_data)->hc.manager;
+	usb_device_keeper_t *manager =
+	    &((uhci_t*)fun->dev->driver_data)->hc.manager;
 
 	usb_address_t addr = usb_device_keeper_find(manager, handle);
@@ -83,8 +84,8 @@
 }
 /*----------------------------------------------------------------------------*/
-/** Gets handle of the respective hc (this or parent device).
- *
- * @param[in] root_hub_fun Root hub function seeking hc handle.
- * @param[out] handle Place to write the handle.
+/** Gets handle of the respective hc.
+ *
+ * @param[in] fun DDF function of uhci device.
+ * @param[out] handle Host cotnroller handle.
  * @return Error code.
  */
@@ -100,5 +101,5 @@
 }
 /*----------------------------------------------------------------------------*/
-/** This iface is generic for both RH and HC. */
+/** USB interface implementation used by RH */
 static usb_iface_t usb_iface = {
 	.get_hc_handle = usb_iface_get_hc_handle,
@@ -106,6 +107,6 @@
 };
 /*----------------------------------------------------------------------------*/
+/** Operations supported by the HC driver */
 static ddf_dev_ops_t hc_ops = {
-//	.interfaces[USB_DEV_IFACE] = &usb_iface,
 	.interfaces[USBHC_DEV_IFACE] = &hc_iface, /* see iface.h/c */
 };
@@ -122,4 +123,5 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Interface to provide the root hub driver with hw info */
 static hw_res_ops_t hw_res_iface = {
 	.get_resource_list = get_resource_list,
@@ -127,4 +129,5 @@
 };
 /*----------------------------------------------------------------------------*/
+/** RH function support for uhci-rhd */
 static ddf_dev_ops_t rh_ops = {
 	.interfaces[USB_DEV_IFACE] = &usb_iface,
@@ -132,5 +135,5 @@
 };
 /*----------------------------------------------------------------------------*/
-/** Initialize hc and rh ddf structures and their respective drivers.
+/** Initialize hc and rh DDF structures and their respective drivers.
  *
  * @param[in] instance UHCI structure to use.
@@ -138,6 +141,6 @@
  *
  * This function does all the preparatory work for hc and rh drivers:
- *  - gets device hw resources
- *  - disables UHCI legacy support
+ *  - gets device's hw resources
+ *  - disables UHCI legacy support (PCI config space)
  *  - asks for interrupt
  *  - registers interrupt handler
@@ -193,9 +196,11 @@
 	ret = (instance->hc_fun == NULL) ? ENOMEM : EOK;
 	CHECK_RET_DEST_FUN_RETURN(ret,
-	    "Failed(%d) to create HC function.\n", ret);
+	    "Failed(%d) to create HC function: %s.\n", ret, str_error(ret));
 
 	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);
+	CHECK_RET_DEST_FUN_RETURN(ret,
+	    "Failed(%d) to init uhci-hcd: %s.\n", ret, str_error(ret));
+
 	instance->hc_fun->ops = &hc_ops;
 	instance->hc_fun->driver_data = &instance->hc;
@@ -221,15 +226,17 @@
 	    &instance->hc.interrupt_code);
 	CHECK_RET_FINI_RETURN(ret,
-	    "Failed(%d) to register interrupt handler.\n", ret);
+	    "Failed(%d) to register interrupt handler: %s.\n",
+	    ret, str_error(ret));
 
 	instance->rh_fun = ddf_fun_create(device, fun_inner, "uhci-rh");
 	ret = (instance->rh_fun == NULL) ? ENOMEM : EOK;
 	CHECK_RET_FINI_RETURN(ret,
-	    "Failed(%d) to create root hub function.\n", ret);
+	    "Failed(%d) to create root hub function: %s.\n",
+	    ret, str_error(ret));
 
 	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);
+	    "Failed(%d) to setup UHCI root hub: %s.\n", ret, str_error(ret));
 
 	instance->rh_fun->ops = &rh_ops;
@@ -237,5 +244,5 @@
 	ret = ddf_fun_bind(instance->rh_fun);
 	CHECK_RET_FINI_RETURN(ret,
-	    "Failed(%d) to register UHCI root hub.\n", ret);
+	    "Failed(%d) to register UHCI root hub: %s.\n", ret, str_error(ret));
 
 	return EOK;
Index: uspace/drv/uhci-hcd/uhci.h
===================================================================
--- uspace/drv/uhci-hcd/uhci.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/uhci-hcd/uhci.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -41,14 +41,19 @@
 #include "root_hub.h"
 
+/** Structure representing both functions of UHCI hc, USB host controller
+ * and USB root hub */
 typedef struct uhci {
+	/** Pointer to DDF represenation of UHCI host controller */
 	ddf_fun_t *hc_fun;
+	/** Pointer to DDF represenation of UHCI root hub */
 	ddf_fun_t *rh_fun;
 
+	/** Internal driver's represenation of UHCI host controller */
 	hc_t hc;
+	/** Internal driver's represenation of UHCI root hub */
 	rh_t rh;
 } uhci_t;
 
 int uhci_init(uhci_t *instance, ddf_dev_t *device);
-
 #endif
 /**
Index: uspace/drv/uhci-rhd/port.c
===================================================================
--- uspace/drv/uhci-rhd/port.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/uhci-rhd/port.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -68,9 +68,8 @@
  * @return Error code. (Always EOK)
  */
-static inline void uhci_port_write_status(
-    uhci_port_t *port, port_status_t value)
-{
-	assert(port);
-	pio_write_16(port->address, value);
+static inline void uhci_port_write_status(uhci_port_t *port, port_status_t val)
+{
+	assert(port);
+	pio_write_16(port->address, val);
 }
 /*----------------------------------------------------------------------------*/
@@ -101,9 +100,9 @@
 	port->rh = rh;
 
-	int rc = usb_hc_connection_initialize_from_device(
-	    &port->hc_connection, rh);
-	if (rc != EOK) {
+	int ret =
+	    usb_hc_connection_initialize_from_device(&port->hc_connection, rh);
+	if (ret != EOK) {
 		usb_log_error("Failed to initialize connection to HC.");
-		return rc;
+		return ret;
 	}
 
@@ -238,5 +237,4 @@
 	/* Enable the port. */
 	uhci_port_set_enabled(port, true);
-
 	return EOK;
 }
@@ -271,5 +269,4 @@
 	usb_log_info("New device at port %u, address %d (handle %llu).\n",
 	    port->number, dev_addr, port->attached_device);
-
 	return EOK;
 }
@@ -313,4 +310,11 @@
 	/* Write new value. */
 	uhci_port_write_status(port, port_status);
+
+	/* Wait for port to become enabled */
+	do {
+		async_usleep(1000);
+		port_status = uhci_port_read_status(port);
+	} while ((port_status & STATUS_CONNECTED) &&
+	    !(port_status & STATUS_ENABLED));
 
 	usb_log_debug("%s: %sabled port.\n",
Index: uspace/drv/uhci-rhd/port.h
===================================================================
--- uspace/drv/uhci-rhd/port.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/uhci-rhd/port.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -54,4 +54,5 @@
 #define STATUS_SUSPEND   (1 << 12)
 
+/** UHCI port structure */
 typedef struct uhci_port
 {
Index: uspace/drv/uhci-rhd/root_hub.c
===================================================================
--- uspace/drv/uhci-rhd/root_hub.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/uhci-rhd/root_hub.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -33,4 +33,5 @@
  */
 #include <errno.h>
+#include <str_error.h>
 #include <ddi.h>
 #include <usb/debug.h>
@@ -43,5 +44,5 @@
  * @param[in] addr Address of I/O registers.
  * @param[in] size Size of available I/O space.
- * @param[in] rh Pointer to ddf instance of the root hub driver.
+ * @param[in] rh Pointer to DDF instance of the root hub driver.
  * @return Error code.
  */
@@ -58,6 +59,6 @@
 	if (ret < 0) {
 		usb_log_error(
-		    "Failed(%d) to gain access to port registers at %p\n",
-		    ret, regs);
+		    "Failed(%d) to gain access to port registers at %p: %s.\n",
+		    ret, regs, str_error(ret));
 		return ret;
 	}
@@ -66,7 +67,6 @@
 	unsigned i = 0;
 	for (; i < UHCI_ROOT_HUB_PORT_COUNT; ++i) {
-		/* NOTE: mind pointer arithmetics here */
 		ret = uhci_port_init(
-		    &instance->ports[i], regs + i, i, ROOT_HUB_WAIT_USEC, rh);
+		    &instance->ports[i], &regs[i], i, ROOT_HUB_WAIT_USEC, rh);
 		if (ret != EOK) {
 			unsigned j = 0;
Index: uspace/drv/uhci-rhd/root_hub.h
===================================================================
--- uspace/drv/uhci-rhd/root_hub.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/uhci-rhd/root_hub.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -42,11 +42,12 @@
 #define ROOT_HUB_WAIT_USEC 250000 /* 250 miliseconds */
 
+/** UHCI root hub drvier structure */
 typedef struct root_hub {
+	/** Ports provided by the hub */
 	uhci_port_t ports[UHCI_ROOT_HUB_PORT_COUNT];
-	devman_handle_t hc_handle;
 } uhci_root_hub_t;
 
 int uhci_root_hub_init(
-  uhci_root_hub_t *instance, void *addr, size_t size, ddf_dev_t *rh);
+    uhci_root_hub_t *instance, void *addr, size_t size, ddf_dev_t *rh);
 
 void uhci_root_hub_fini(uhci_root_hub_t *instance);
Index: uspace/drv/usbhid/Makefile
===================================================================
--- uspace/drv/usbhid/Makefile	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/usbhid/Makefile	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -40,8 +40,10 @@
 	main.c \
 	usbhid.c \
+	subdrivers.c \
 	kbd/conv.c \
 	kbd/kbddev.c \
 	kbd/kbdrepeat.c \
 	generic/hiddev.c \
+	mouse/mousedev.c \
 	$(STOLEN_LAYOUT_SOURCES)
 
Index: uspace/drv/usbhid/generic/hiddev.c
===================================================================
--- uspace/drv/usbhid/generic/hiddev.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/usbhid/generic/hiddev.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -39,4 +39,5 @@
 
 #include "hiddev.h"
+#include "usbhid.h"
 
 /*----------------------------------------------------------------------------*/
@@ -54,8 +55,9 @@
 /*----------------------------------------------------------------------------*/
 
-bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer,
-     size_t buffer_size, void *arg)
+bool usb_generic_hid_polling_callback(usb_hid_dev_t *hid_dev, 
+    uint8_t *buffer, size_t buffer_size)
 {
-	usb_log_debug("usb_hid_polling_callback()\n");
+	usb_log_debug("usb_hid_polling_callback(%p, %p, %zu)\n",
+	    hid_dev, buffer, buffer_size);
 	usb_debug_str_buffer(buffer, buffer_size, 0);
 	return true;
Index: uspace/drv/usbhid/generic/hiddev.h
===================================================================
--- uspace/drv/usbhid/generic/hiddev.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/usbhid/generic/hiddev.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -34,8 +34,10 @@
  */
 
-#ifndef USB_HIDD_H_
-#define USB_HIDD_H_
+#ifndef USB_HID_HIDDDEV_H_
+#define USB_HID_HIDDDEV_H_
 
 #include <usb/devdrv.h>
+
+struct usb_hid_dev;
 
 usb_endpoint_description_t usb_hid_generic_poll_endpoint_description;
@@ -44,8 +46,8 @@
 const char *HID_GENERIC_CLASS_NAME;
 
-bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer,
-     size_t buffer_size, void *arg);
+bool usb_generic_hid_polling_callback(struct usb_hid_dev *hid_dev,
+    uint8_t *buffer, size_t buffer_size);
 
-#endif // USB_HIDD_H_
+#endif // USB_HID_HIDDDEV_H_
 
 /**
Index: uspace/drv/usbhid/kbd/conv.h
===================================================================
--- uspace/drv/usbhid/kbd/conv.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/usbhid/kbd/conv.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -34,10 +34,10 @@
  */
 
-#ifndef USB_KBD_CONV_H_
-#define USB_KBD_CONV_H_
+#ifndef USB_HID_CONV_H_
+#define USB_HID_CONV_H_
 
 unsigned int usbhid_parse_scancode(int scancode);
 
-#endif /* USB_KBD_CONV_H_ */
+#endif /* USB_HID_CONV_H_ */
 
 /**
Index: uspace/drv/usbhid/kbd/kbddev.c
===================================================================
--- uspace/drv/usbhid/kbd/kbddev.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/usbhid/kbd/kbddev.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -238,5 +238,5 @@
  * @param icall Call data.
  */
-void default_connection_handler(ddf_fun_t *fun,
+static void default_connection_handler(ddf_fun_t *fun,
     ipc_callid_t icallid, ipc_call_t *icall)
 {
@@ -856,13 +856,11 @@
 /*----------------------------------------------------------------------------*/
 
-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) {
+bool usb_kbd_polling_callback(usb_hid_dev_t *hid_dev, uint8_t *buffer,
+     size_t buffer_size)
+{
+	if (hid_dev == NULL || buffer == NULL) {
 		// do not continue polling (???)
 		return false;
 	}
-	
-	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
 	
 	// TODO: add return value from this function
@@ -916,5 +914,5 @@
 /*----------------------------------------------------------------------------*/
 
-void usb_kbd_deinit(struct usb_hid_dev_t *hid_dev)
+void usb_kbd_deinit(usb_hid_dev_t *hid_dev)
 {
 	if (hid_dev == NULL) {
Index: uspace/drv/usbhid/kbd/kbddev.h
===================================================================
--- uspace/drv/usbhid/kbd/kbddev.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/usbhid/kbd/kbddev.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -34,6 +34,6 @@
  */
 
-#ifndef USB_KBDDEV_H_
-#define USB_KBDDEV_H_
+#ifndef USB_HID_KBDDEV_H_
+#define USB_HID_KBDDEV_H_
 
 #include <stdint.h>
@@ -49,5 +49,5 @@
 #include "kbdrepeat.h"
 
-struct usb_hid_dev_t;
+struct usb_hid_dev;
 
 /*----------------------------------------------------------------------------*/
@@ -65,8 +65,4 @@
  */
 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;
@@ -91,10 +87,4 @@
 	fibril_mutex_t *repeat_mtx;
 	
-	/** Report descriptor. */
-	//uint8_t *report_desc;
-
-	/** Report descriptor size. */
-	//size_t report_desc_size;
-	
 	uint8_t *output_buffer;
 	
@@ -106,7 +96,4 @@
 	
 	int32_t *led_data;
-
-	/** HID Report parser. */
-	//usb_hid_report_parser_t *parser;
 	
 	/** State of the structure (for checking before use). 
@@ -121,14 +108,4 @@
 /*----------------------------------------------------------------------------*/
 
-//enum {
-//	USB_KBD_POLL_EP_NO = 0,
-//	USB_HID_POLL_EP_NO = 1,
-//	USB_KBD_POLL_EP_COUNT = 2
-//};
-
-//usb_endpoint_description_t *usb_kbd_endpoints[USB_KBD_POLL_EP_COUNT + 1];
-
-//ddf_dev_ops_t keyboard_ops;
-
 usb_endpoint_description_t usb_hid_kbd_poll_endpoint_description;
 
@@ -138,13 +115,8 @@
 /*----------------------------------------------------------------------------*/
 
-//usb_kbd_t *usb_kbd_new(void);
+int usb_kbd_init(struct usb_hid_dev *hid_dev);
 
-int usb_kbd_init(struct usb_hid_dev_t *hid_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);
+bool usb_kbd_polling_callback(struct usb_hid_dev *hid_dev, uint8_t *buffer,
+    size_t buffer_size);
 
 int usb_kbd_is_initialized(const usb_kbd_t *kbd_dev);
@@ -154,13 +126,12 @@
 void usb_kbd_free(usb_kbd_t **kbd_dev);
 
-void usb_kbd_push_ev(struct usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev,
+void usb_kbd_push_ev(struct usb_hid_dev *hid_dev, usb_kbd_t *kbd_dev,
     int type, unsigned int key);
 
+void usb_kbd_deinit(struct usb_hid_dev *hid_dev);
 
-void usb_kbd_deinit(struct usb_hid_dev_t *hid_dev);
+int usb_kbd_set_boot_protocol(struct usb_hid_dev *hid_dev);
 
-int usb_kbd_set_boot_protocol(struct usb_hid_dev_t *hid_dev);
-
-#endif /* USB_KBDDEV_H_ */
+#endif /* USB_HID_KBDDEV_H_ */
 
 /**
Index: uspace/drv/usbhid/kbd/kbdrepeat.h
===================================================================
--- uspace/drv/usbhid/kbd/kbdrepeat.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/usbhid/kbd/kbdrepeat.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -34,6 +34,6 @@
  */
 
-#ifndef USB_KBDREPEAT_H_
-#define USB_KBDREPEAT_H_
+#ifndef USB_HID_KBDREPEAT_H_
+#define USB_HID_KBDREPEAT_H_
 
 struct usb_kbd_t;
@@ -62,5 +62,5 @@
 void usb_kbd_repeat_stop(struct usb_kbd_t *kbd, unsigned int key);
 
-#endif /* USB_KBDREPEAT_H_ */
+#endif /* USB_HID_KBDREPEAT_H_ */
 
 /**
Index: uspace/drv/usbhid/layout.h
===================================================================
--- uspace/drv/usbhid/layout.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/usbhid/layout.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -36,6 +36,6 @@
  */
 
-#ifndef USB_KBD_LAYOUT_H_
-#define USB_KBD_LAYOUT_H_
+#ifndef USB_HID_LAYOUT_H_
+#define USB_HID_LAYOUT_H_
 
 #include <sys/types.h>
Index: uspace/drv/usbhid/main.c
===================================================================
--- uspace/drv/usbhid/main.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/usbhid/main.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -42,4 +42,5 @@
 
 #include <usb/devdrv.h>
+#include <usb/devpoll.h>
 
 #include "usbhid.h"
@@ -98,5 +99,5 @@
 	/* Create the function exposed under /dev/devices. */
 	ddf_fun_t *hid_fun = ddf_fun_create(dev->ddf_dev, fun_exposed, 
-	    usb_hid_get_function_name(hid_dev->device_type));
+	    usb_hid_get_function_name(hid_dev));
 	if (hid_fun == NULL) {
 		usb_log_error("Could not create DDF function node.\n");
@@ -122,6 +123,5 @@
 	}
 	
-	rc = ddf_fun_add_to_class(hid_fun, 
-	    usb_hid_get_class_name(hid_dev->device_type));
+	rc = ddf_fun_add_to_class(hid_fun, usb_hid_get_class_name(hid_dev));
 	if (rc != EOK) {
 		usb_log_error(
@@ -142,5 +142,5 @@
 	   hid_dev->poll_pipe_index,
 	   /* Callback when data arrives. */
-	   hid_dev->poll_callback,
+	   usb_hid_polling_callback,
 	   /* How much data to request. */
 	   dev->pipes[hid_dev->poll_pipe_index].pipe->max_packet_size,
Index: uspace/drv/usbhid/mouse/mousedev.c
===================================================================
--- uspace/drv/usbhid/mouse/mousedev.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
+++ uspace/drv/usbhid/mouse/mousedev.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -0,0 +1,322 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak, 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.
+ */
+
+/** @addtogroup drvusbhid
+ * @{
+ */
+/**
+ * @file
+ * USB Mouse driver API.
+ */
+
+#include <usb/debug.h>
+#include <usb/classes/classes.h>
+#include <usb/classes/hid.h>
+#include <usb/classes/hidreq.h>
+#include <errno.h>
+#include <str_error.h>
+#include <ipc/mouse.h>
+
+#include "mousedev.h"
+#include "../usbhid.h"
+
+/*----------------------------------------------------------------------------*/
+
+usb_endpoint_description_t usb_hid_mouse_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_MOUSE,
+	.flags = 0
+};
+
+const char *HID_MOUSE_FUN_NAME = "mouse";
+const char *HID_MOUSE_CLASS_NAME = "mouse";
+
+/** Default idle rate for mouses. */
+static const uint8_t IDLE_RATE = 0;
+
+/*----------------------------------------------------------------------------*/
+
+enum {
+	USB_MOUSE_BOOT_REPORT_DESCRIPTOR_SIZE = 63
+};
+
+static const uint8_t USB_MOUSE_BOOT_REPORT_DESCRIPTOR[
+    USB_MOUSE_BOOT_REPORT_DESCRIPTOR_SIZE] = {
+	0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
+	0x09, 0x02,                    // USAGE (Mouse)
+	0xa1, 0x01,                    // COLLECTION (Application)
+	0x09, 0x01,                    //   USAGE (Pointer)
+	0xa1, 0x00,                    //   COLLECTION (Physical)
+	0x95, 0x03,                    //     REPORT_COUNT (3)
+	0x75, 0x01,                    //     REPORT_SIZE (1)
+	0x05, 0x09,                    //     USAGE_PAGE (Button)
+	0x19, 0x01,                    //     USAGE_MINIMUM (Button 1)
+	0x29, 0x03,                    //     USAGE_MAXIMUM (Button 3)
+	0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
+	0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
+	0x81, 0x02,                    //     INPUT (Data,Var,Abs)
+	0x95, 0x01,                    //     REPORT_COUNT (1)
+	0x75, 0x05,                    //     REPORT_SIZE (5)
+	0x81, 0x01,                    //     INPUT (Cnst)
+	0x75, 0x08,                    //     REPORT_SIZE (8)
+	0x95, 0x02,                    //     REPORT_COUNT (2)
+	0x05, 0x01,                    //     USAGE_PAGE (Generic Desktop)
+	0x09, 0x30,                    //     USAGE (X)
+	0x09, 0x31,                    //     USAGE (Y)
+	0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)
+	0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)
+	0x81, 0x06,                    //     INPUT (Data,Var,Rel)
+	0xc0,                          //   END_COLLECTION
+	0xc0                           // END_COLLECTION
+};
+
+/*----------------------------------------------------------------------------*/
+
+/** Default handler for IPC methods not handled by DDF.
+ *
+ * @param fun Device function handling the call.
+ * @param icallid Call id.
+ * @param icall Call data.
+ */
+static void default_connection_handler(ddf_fun_t *fun,
+    ipc_callid_t icallid, ipc_call_t *icall)
+{
+	sysarg_t method = IPC_GET_IMETHOD(*icall);
+	
+	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
+	
+	if (hid_dev == NULL || hid_dev->data == NULL) {
+		async_answer_0(icallid, EINVAL);
+		return;
+	}
+	
+	assert(hid_dev != NULL);
+	assert(hid_dev->data != NULL);
+	usb_mouse_t *mouse_dev = (usb_mouse_t *)hid_dev->data;
+	
+	if (method == IPC_M_CONNECT_TO_ME) {
+		int callback = IPC_GET_ARG5(*icall);
+
+		if (mouse_dev->console_phone != -1) {
+			async_answer_0(icallid, ELIMIT);
+			return;
+		}
+
+		mouse_dev->console_phone = callback;
+		usb_log_debug("Console phone to mouse set ok (%d).\n", callback);
+		async_answer_0(icallid, EOK);
+		return;
+	}
+
+	async_answer_0(icallid, EINVAL);
+}
+
+/*----------------------------------------------------------------------------*/
+
+static usb_mouse_t *usb_mouse_new(void)
+{
+	usb_mouse_t *mouse = calloc(1, sizeof(usb_mouse_t));
+	if (mouse == NULL) {
+		return NULL;
+	}
+	mouse->console_phone = -1;
+	
+	return mouse;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static void usb_mouse_free(usb_mouse_t **mouse_dev)
+{
+	if (mouse_dev == NULL || *mouse_dev == NULL) {
+		return;
+	}
+	
+	// hangup phone to the console
+	async_hangup((*mouse_dev)->console_phone);
+	
+	free(*mouse_dev);
+	*mouse_dev = NULL;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static bool usb_mouse_process_boot_report(usb_mouse_t *mouse_dev,
+    uint8_t *buffer, size_t buffer_size)
+{
+	usb_log_debug2("got buffer: %s.\n",
+	    usb_debug_str_buffer(buffer, buffer_size, 0));
+
+	uint8_t butt = buffer[0];
+	char str_buttons[4] = {
+		butt & 1 ? '#' : '.',
+		butt & 2 ? '#' : '.',
+		butt & 4 ? '#' : '.',
+		0
+	};
+
+	int shift_x = ((int) buffer[1]) - 127;
+	int shift_y = ((int) buffer[2]) - 127;
+	int wheel = ((int) buffer[3]) - 127;
+
+	if (buffer[1] == 0) {
+		shift_x = 0;
+	}
+	if (buffer[2] == 0) {
+		shift_y = 0;
+	}
+	if (buffer[3] == 0) {
+		wheel = 0;
+	}
+	
+	if (mouse_dev->console_phone >= 0) {
+		usb_log_debug("Console phone: %d\n", mouse_dev->console_phone);
+		if ((shift_x != 0) || (shift_y != 0)) {
+			/* FIXME: guessed for QEMU */
+			async_req_2_0(mouse_dev->console_phone,
+			    MEVENT_MOVE,
+			    - shift_x / 10,  - shift_y / 10);
+		} else {
+			usb_log_error("No move reported\n");
+		}
+		if (butt) {
+			/* FIXME: proper button clicking. */
+			async_req_2_0(mouse_dev->console_phone,
+			    MEVENT_BUTTON, 1, 1);
+			async_req_2_0(mouse_dev->console_phone,
+			    MEVENT_BUTTON, 1, 0);
+		}
+	} else {
+		usb_log_error("No console phone in mouse!!\n");
+	}
+
+	usb_log_debug("buttons=%s  dX=%+3d  dY=%+3d  wheel=%+3d\n",
+	    str_buttons, shift_x, shift_y, wheel);
+
+	/* Guess. */
+	//async_usleep(1000);
+	// no sleep right now
+
+	return true;
+}
+
+/*----------------------------------------------------------------------------*/
+
+int usb_mouse_init(usb_hid_dev_t *hid_dev)
+{
+	usb_log_debug("Initializing HID/Mouse structure...\n");
+	
+	if (hid_dev == NULL) {
+		usb_log_error("Failed to init keyboard structure: no structure"
+		    " given.\n");
+		return EINVAL;
+	}
+	
+	usb_mouse_t *mouse_dev = usb_mouse_new();
+	if (mouse_dev == NULL) {
+		usb_log_error("Error while creating USB/HID Mouse device "
+		    "structure.\n");
+		return ENOMEM;
+	}
+	
+	// save the Mouse device structure into the HID device structure
+	hid_dev->data = mouse_dev;
+	
+	// set handler for incoming calls
+	hid_dev->ops.default_handler = default_connection_handler;
+	
+	// TODO: how to know if the device supports the request???
+	usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe, 
+	    hid_dev->usb_dev->interface_no, IDLE_RATE);
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+bool usb_mouse_polling_callback(usb_hid_dev_t *hid_dev, uint8_t *buffer,
+     size_t buffer_size)
+{
+	usb_log_debug("usb_mouse_polling_callback()\n");
+	usb_debug_str_buffer(buffer, buffer_size, 0);
+	
+	if (hid_dev == NULL) {
+		usb_log_error("Missing argument to the mouse polling callback."
+		    "\n");
+		return false;
+	}
+	
+	if (hid_dev->data == NULL) {
+		usb_log_error("Wrong argument to the mouse polling callback."
+		    "\n");
+		return false;
+	}
+	usb_mouse_t *mouse_dev = (usb_mouse_t *)hid_dev->data;
+	
+	return usb_mouse_process_boot_report(mouse_dev, buffer, buffer_size);
+}
+
+/*----------------------------------------------------------------------------*/
+
+void usb_mouse_deinit(usb_hid_dev_t *hid_dev)
+{
+	usb_mouse_free((usb_mouse_t **)&hid_dev->data);
+}
+
+/*----------------------------------------------------------------------------*/
+
+int usb_mouse_set_boot_protocol(usb_hid_dev_t *hid_dev)
+{
+	int rc = usb_hid_parse_report_descriptor(hid_dev->parser, 
+	    USB_MOUSE_BOOT_REPORT_DESCRIPTOR, 
+	    USB_MOUSE_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(&hid_dev->usb_dev->ctrl_pipe, 
+	    hid_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;
+	}
+	
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/usbhid/mouse/mousedev.h
===================================================================
--- uspace/drv/usbhid/mouse/mousedev.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
+++ uspace/drv/usbhid/mouse/mousedev.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -0,0 +1,77 @@
+/*
+ * 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 Mouse driver API.
+ */
+
+#ifndef USB_HID_MOUSEDEV_H_
+#define USB_HID_MOUSEDEV_H_
+
+#include <usb/devdrv.h>
+
+struct usb_hid_dev;
+
+/*----------------------------------------------------------------------------*/
+
+/** Container for USB mouse device. */
+typedef struct {
+	///** Polling interval in microseconds. */
+	//suseconds_t poll_interval_us;
+	/** IPC phone to console (consumer). */
+	int console_phone;
+} usb_mouse_t;
+
+/*----------------------------------------------------------------------------*/
+
+usb_endpoint_description_t usb_hid_mouse_poll_endpoint_description;
+
+const char *HID_MOUSE_FUN_NAME;
+const char *HID_MOUSE_CLASS_NAME;
+
+/*----------------------------------------------------------------------------*/
+
+int usb_mouse_init(struct usb_hid_dev *hid_dev);
+
+bool usb_mouse_polling_callback(struct usb_hid_dev *hid_dev, uint8_t *buffer,
+    size_t buffer_size);
+
+void usb_mouse_deinit(struct usb_hid_dev *hid_dev);
+
+int usb_mouse_set_boot_protocol(struct usb_hid_dev *hid_dev);
+
+/*----------------------------------------------------------------------------*/
+
+#endif // USB_HID_MOUSEDEV_H_
+
+/**
+ * @}
+ */
Index: uspace/drv/usbhid/subdrivers.c
===================================================================
--- uspace/drv/usbhid/subdrivers.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
+++ uspace/drv/usbhid/subdrivers.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -0,0 +1,62 @@
+/*
+ * 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 subdriver mappings.
+ */
+
+#include "subdrivers.h"
+#include "usb/classes/hidut.h"
+
+static usb_hid_subdriver_usage_t path_kbd[] = {{USB_HIDUT_PAGE_KEYBOARD, 0}};
+
+const usb_hid_subdriver_mapping_t usb_hid_subdrivers[] = {
+	{
+		path_kbd,
+		1,
+		USB_HID_PATH_COMPARE_END 
+		| USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
+		NULL,
+		NULL,
+		{
+			usb_kbd_init,
+			usb_kbd_deinit,
+			usb_kbd_polling_callback,
+			NULL
+		},
+		
+	},
+	{NULL, 0, 0, NULL, NULL, {NULL, NULL, NULL, NULL}}
+};
+
+/**
+ * @}
+ */
Index: uspace/drv/usbhid/subdrivers.h
===================================================================
--- uspace/drv/usbhid/subdrivers.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
+++ uspace/drv/usbhid/subdrivers.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -0,0 +1,73 @@
+/*
+ * 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 subdriver mappings.
+ */
+
+#ifndef USB_HID_SUBDRIVERS_H_
+#define USB_HID_SUBDRIVERS_H_
+
+#include "usbhid.h"
+#include "kbd/kbddev.h"
+
+/*----------------------------------------------------------------------------*/
+
+typedef struct usb_hid_subdriver_usage {
+	int usage_page;
+	int usage;
+} usb_hid_subdriver_usage_t;
+
+/*----------------------------------------------------------------------------*/
+
+/* TODO: This mapping must contain some other information to get the proper
+ *       interface.
+ */
+typedef struct usb_hid_subdriver_mapping {
+	const usb_hid_subdriver_usage_t *usage_path;
+	int path_size;
+	int compare;
+	const char *vendor_id;
+	const char *product_id;
+	usb_hid_subdriver_t subdriver;
+} usb_hid_subdriver_mapping_t;
+
+/*----------------------------------------------------------------------------*/
+
+extern const usb_hid_subdriver_mapping_t usb_hid_subdrivers[];
+
+/*----------------------------------------------------------------------------*/
+
+#endif /* USB_HID_SUBDRIVERS_H_ */
+
+/**
+ * @}
+ */
Index: uspace/drv/usbhid/usbhid.c
===================================================================
--- uspace/drv/usbhid/usbhid.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/usbhid/usbhid.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -42,4 +42,5 @@
 #include <usb/classes/hidreq.h>
 #include <errno.h>
+#include <str_error.h>
 
 #include "usbhid.h"
@@ -47,16 +48,8 @@
 #include "kbd/kbddev.h"
 #include "generic/hiddev.h"
-
-/*----------------------------------------------------------------------------*/
-
-/** Mouse polling endpoint description for boot protocol class. */
-static usb_endpoint_description_t usb_hid_mouse_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_MOUSE,
-	.flags = 0
-};
+#include "mouse/mousedev.h"
+#include "subdrivers.h"
+
+/*----------------------------------------------------------------------------*/
 
 /* Array of endpoints expected on the device, NULL terminated. */
@@ -68,6 +61,252 @@
 };
 
-static const char *HID_MOUSE_FUN_NAME = "mouse";
-static const char *HID_MOUSE_CLASS_NAME = "mouse";
+static const int USB_HID_MAX_SUBDRIVERS = 10;
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_hid_set_boot_kbd_subdriver(usb_hid_dev_t *hid_dev)
+{
+	assert(hid_dev->subdriver_count == 0);
+	
+	hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
+	    sizeof(usb_hid_subdriver_t));
+	if (hid_dev->subdrivers == NULL) {
+		return ENOMEM;
+	}
+	
+	// set the init callback
+	hid_dev->subdrivers[0].init = usb_kbd_init;
+	
+	// set the polling callback
+	hid_dev->subdrivers[0].poll = usb_kbd_polling_callback;
+	
+	// set the polling ended callback
+	hid_dev->subdrivers[0].poll_end = NULL;
+	
+	// set the deinit callback
+	hid_dev->subdrivers[0].deinit = usb_kbd_deinit;
+	
+	// set subdriver count
+	hid_dev->subdriver_count = 1;
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_hid_set_boot_mouse_subdriver(usb_hid_dev_t *hid_dev)
+{
+	assert(hid_dev->subdriver_count == 0);
+	
+	hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
+	    sizeof(usb_hid_subdriver_t));
+	if (hid_dev->subdrivers == NULL) {
+		return ENOMEM;
+	}
+	
+	// set the init callback
+	hid_dev->subdrivers[0].init = usb_mouse_init;
+	
+	// set the polling callback
+	hid_dev->subdrivers[0].poll = usb_mouse_polling_callback;
+	
+	// set the polling ended callback
+	hid_dev->subdrivers[0].poll_end = NULL;
+	
+	// set the deinit callback
+	hid_dev->subdrivers[0].deinit = usb_mouse_deinit;
+	
+	// set subdriver count
+	hid_dev->subdriver_count = 1;
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_hid_set_generic_hid_subdriver(usb_hid_dev_t *hid_dev)
+{
+	assert(hid_dev->subdriver_count == 0);
+	
+	hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
+	    sizeof(usb_hid_subdriver_t));
+	if (hid_dev->subdrivers == NULL) {
+		return ENOMEM;
+	}
+	
+	// set the init callback
+	hid_dev->subdrivers[0].init = NULL;
+	
+	// set the polling callback
+	hid_dev->subdrivers[0].poll = usb_generic_hid_polling_callback;
+	
+	// set the polling ended callback
+	hid_dev->subdrivers[0].poll_end = NULL;
+	
+	// set the deinit callback
+	hid_dev->subdrivers[0].deinit = NULL;
+	
+	// set subdriver count
+	hid_dev->subdriver_count = 1;
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static bool usb_hid_ids_match(usb_hid_dev_t *hid_dev, 
+    const usb_hid_subdriver_mapping_t *mapping)
+{
+	return false;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static bool usb_hid_path_matches(usb_hid_dev_t *hid_dev, 
+    const usb_hid_subdriver_usage_t *path, int path_size, int compare)
+{
+	assert(hid_dev != NULL);
+	assert(path != NULL);
+	
+	usb_hid_report_path_t *usage_path = usb_hid_report_path();
+	if (usage_path == NULL) {
+		usb_log_debug("Failed to create usage path.\n");
+		return false;
+	}
+	int i;
+	for (i = 0; i < path_size; ++i) {
+		if (usb_hid_report_path_append_item(usage_path, 
+		    path[i].usage_page, path[i].usage) != EOK) {
+			usb_log_debug("Failed to append to usage path.\n");
+			usb_hid_report_path_free(usage_path);
+			return false;
+		}
+	}
+	
+	assert(hid_dev->parser != NULL);
+	
+	usb_log_debug("Compare flags: %d\n", compare);
+	size_t size = usb_hid_report_input_length(hid_dev->parser, usage_path, 
+	    compare);
+	usb_log_debug("Size of the input report: %d\n", size);
+	
+	usb_hid_report_path_free(usage_path);
+	
+	return (size > 0);
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_hid_save_subdrivers(usb_hid_dev_t *hid_dev, 
+    const usb_hid_subdriver_t **subdrivers, int count)
+{
+	int i;
+	
+	if (count <= 0) {
+		hid_dev->subdriver_count = 0;
+		hid_dev->subdrivers = NULL;
+		return EOK;
+	}
+	
+	hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(count * 
+	    sizeof(usb_hid_subdriver_t));
+	if (hid_dev->subdrivers == NULL) {
+		return ENOMEM;
+	}
+	
+	for (i = 0; i < count; ++i) {
+		hid_dev->subdrivers[i].init = subdrivers[i]->init;
+		hid_dev->subdrivers[i].deinit = subdrivers[i]->deinit;
+		hid_dev->subdrivers[i].poll = subdrivers[i]->poll;
+		hid_dev->subdrivers[i].poll_end = subdrivers[i]->poll_end;
+	}
+	
+	hid_dev->subdriver_count = count;
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_hid_find_subdrivers(usb_hid_dev_t *hid_dev)
+{
+	const usb_hid_subdriver_t *subdrivers[USB_HID_MAX_SUBDRIVERS];
+	
+	int i = 0, count = 0;
+	const usb_hid_subdriver_mapping_t *mapping = &usb_hid_subdrivers[i];
+	
+	while (count < USB_HID_MAX_SUBDRIVERS &&
+	    (mapping->usage_path != NULL
+	    || mapping->vendor_id != NULL
+	    || mapping->product_id != NULL)) {
+		// check the vendor & product ID
+		if (mapping->vendor_id != NULL && mapping->product_id == NULL) {
+			usb_log_warning("Missing Product ID for Vendor ID %s\n",
+			    mapping->vendor_id);
+			return EINVAL;
+		}
+		if (mapping->product_id != NULL && mapping->vendor_id == NULL) {
+			usb_log_warning("Missing Vendor ID for Product ID %s\n",
+			    mapping->product_id);
+			return EINVAL;
+		}
+		
+		if (mapping->vendor_id != NULL) {
+			assert(mapping->product_id != NULL);
+			usb_log_debug("Comparing device against vendor ID %s"
+			    " and product ID %s.\n", mapping->vendor_id,
+			    mapping->product_id);
+			if (usb_hid_ids_match(hid_dev, mapping)) {
+				usb_log_debug("Matched.\n");
+				subdrivers[count++] = &mapping->subdriver;
+				// skip the checking of usage path
+				goto next;
+			}
+		}
+		
+		if (mapping->usage_path != NULL) {
+			usb_log_debug("Comparing device against usage path.\n");
+			if (usb_hid_path_matches(hid_dev, 
+			    mapping->usage_path, mapping->path_size,
+			    mapping->compare)) {
+				subdrivers[count++] = &mapping->subdriver;
+			} else {
+				usb_log_debug("Not matched.\n");
+			}
+		}
+	next:
+		mapping = &usb_hid_subdrivers[++i];
+	}
+	
+	// we have all subdrivers determined, save them into the hid device
+	return usb_hid_save_subdrivers(hid_dev, subdrivers, count);
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, usb_device_t *dev)
+{
+	int rc = EOK;
+	
+	if (dev->pipes[USB_HID_KBD_POLL_EP_NO].present) {
+		usb_log_debug("Found keyboard endpoint.\n");
+		// save the pipe index
+		hid_dev->poll_pipe_index = USB_HID_KBD_POLL_EP_NO;
+	} else if (dev->pipes[USB_HID_MOUSE_POLL_EP_NO].present) {
+		usb_log_debug("Found mouse endpoint.\n");
+		// save the pipe index
+		hid_dev->poll_pipe_index = USB_HID_MOUSE_POLL_EP_NO;
+	} else if (dev->pipes[USB_HID_GENERIC_POLL_EP_NO].present) {
+		usb_log_debug("Found generic HID endpoint.\n");
+		// save the pipe index
+		hid_dev->poll_pipe_index = USB_HID_GENERIC_POLL_EP_NO;
+	} else {
+		usb_log_error("None of supported endpoints found - probably"
+		    " not a supported device.\n");
+		rc = ENOTSUP;
+	}
+	
+	return rc;
+}
 
 /*----------------------------------------------------------------------------*/
@@ -91,4 +330,6 @@
 	}
 	
+	hid_dev->poll_pipe_index = -1;
+	
 	return hid_dev;
 }
@@ -96,91 +337,7 @@
 /*----------------------------------------------------------------------------*/
 
-static bool usb_dummy_polling_callback(usb_device_t *dev, uint8_t *buffer,
-     size_t buffer_size, void *arg)
-{
-	usb_log_debug("Dummy polling callback.\n");
-	return false;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, usb_device_t *dev)
-{
-	if (dev->pipes[USB_HID_KBD_POLL_EP_NO].present) {
-		usb_log_debug("Found keyboard endpoint.\n");
-		
-		// save the pipe index and device type
-		hid_dev->poll_pipe_index = USB_HID_KBD_POLL_EP_NO;
-		hid_dev->device_type = USB_HID_PROTOCOL_KEYBOARD;
-		
-		// set the polling callback
-		hid_dev->poll_callback = usb_kbd_polling_callback;
-
-	} else if (dev->pipes[USB_HID_MOUSE_POLL_EP_NO].present) {
-		usb_log_debug("Found mouse endpoint.\n");
-		
-		// save the pipe index and device type
-		hid_dev->poll_pipe_index = USB_HID_MOUSE_POLL_EP_NO;
-		hid_dev->device_type = USB_HID_PROTOCOL_MOUSE;
-		
-		// set the polling callback
-		hid_dev->poll_callback = usb_dummy_polling_callback;
-		
-	} else if (dev->pipes[USB_HID_GENERIC_POLL_EP_NO].present) {
-		usb_log_debug("Found generic HID endpoint.\n");
-		
-		// save the pipe index and device type
-		hid_dev->poll_pipe_index = USB_HID_GENERIC_POLL_EP_NO;
-		hid_dev->device_type = USB_HID_PROTOCOL_NONE;
-		
-		// set the polling callback
-		hid_dev->poll_callback = usb_hid_polling_callback;
-		
-	} else {
-		usb_log_warning("None of supported endpoints found - probably"
-		    " not a supported device.\n");
-		return ENOTSUP;
-	}
-	
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int usb_hid_init_parser(usb_hid_dev_t *hid_dev)
-{
-	/* Initialize the report parser. */
-	int rc = usb_hid_parser_init(hid_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(hid_dev->usb_dev, 
-	    hid_dev->parser);
-	
-	if (rc != EOK) {
-		usb_log_warning("Could not process report descriptor.\n");
-		
-		if (hid_dev->device_type == USB_HID_PROTOCOL_KEYBOARD) {
-			usb_log_warning("Falling back to boot protocol.\n");
-			
-			rc = usb_kbd_set_boot_protocol(hid_dev);
-			
-		} else if (hid_dev->device_type == USB_HID_PROTOCOL_MOUSE) {
-			usb_log_warning("No boot protocol for mouse yet.\n");
-			rc = ENOTSUP;
-		}
-	}
-	
-	return rc;
-}
-
-/*----------------------------------------------------------------------------*/
-
 int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev)
 {
-	int rc;
+	int rc, i;
 	
 	usb_log_debug("Initializing HID structure...\n");
@@ -203,31 +360,125 @@
 	rc = usb_hid_check_pipes(hid_dev, dev);
 	if (rc != EOK) {
+		usb_hid_free(&hid_dev);
 		return rc;
 	}
 	
-	rc = usb_hid_init_parser(hid_dev);
+	/* Initialize the report parser. */
+	rc = usb_hid_parser_init(hid_dev->parser);
 	if (rc != EOK) {
-		usb_log_error("Failed to initialize HID parser.\n");
+		usb_log_error("Failed to initialize report parser.\n");
+		usb_hid_free(&hid_dev);
 		return rc;
 	}
 	
-	switch (hid_dev->device_type) {
-	case USB_HID_PROTOCOL_KEYBOARD:
-		// initialize the keyboard structure
-		rc = usb_kbd_init(hid_dev);
-		if (rc != EOK) {
-			usb_log_warning("Failed to initialize KBD structure."
-			    "\n");
-		}
-		break;
-	case USB_HID_PROTOCOL_MOUSE:
-		break;
-	default:
-//		usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe, 
-//		    hid_dev->usb_dev->interface_no, 0);
-		break;
+	/* Get the report descriptor and parse it. */
+	rc = usb_hid_process_report_descriptor(hid_dev->usb_dev, 
+	    hid_dev->parser);
+	
+	bool fallback = false;
+	
+	if (rc == EOK) {
+		// try to find subdrivers that may want to handle this device
+		rc = usb_hid_find_subdrivers(hid_dev);
+		if (rc != EOK || hid_dev->subdriver_count == 0) {
+			// try to fall back to the boot protocol if available
+			usb_log_info("No subdrivers found to handle this"
+			    " device.\n");
+			fallback = true;
+		}
+	} else {
+		usb_log_error("Failed to parse Report descriptor.\n");
+		// try to fall back to the boot protocol if available
+		fallback = true;
+	}
+	
+	// TODO: remove the mouse hack
+	if (hid_dev->poll_pipe_index == USB_HID_MOUSE_POLL_EP_NO ||
+	    fallback) {
+		// fall back to boot protocol
+		switch (hid_dev->poll_pipe_index) {
+		case USB_HID_KBD_POLL_EP_NO:
+			usb_log_info("Falling back to kbd boot protocol.\n");
+			rc = usb_kbd_set_boot_protocol(hid_dev);
+			if (rc == EOK) {
+				rc = usb_hid_set_boot_kbd_subdriver(hid_dev);
+			}
+			break;
+		case USB_HID_MOUSE_POLL_EP_NO:
+			usb_log_info("Falling back to mouse boot protocol.\n");
+			rc = usb_mouse_set_boot_protocol(hid_dev);
+			if (rc == EOK) {
+				rc = usb_hid_set_boot_mouse_subdriver(hid_dev);
+			}
+			break;
+		default:
+			assert(hid_dev->poll_pipe_index 
+			    == USB_HID_GENERIC_POLL_EP_NO);
+			
+			/* TODO: this has no meaning if the report descriptor
+			         is not parsed */
+			usb_log_info("Falling back to generic HID driver.\n");
+			rc = usb_hid_set_generic_hid_subdriver(hid_dev);
+		}
+	}
+	
+	if (rc != EOK) {
+		usb_log_error("No subdriver for handling this device could be"
+		    " initialized: %s.\n", str_error(rc));
+		usb_hid_free(&hid_dev);
+	} else {
+		bool ok = false;
+		
+		usb_log_debug("Subdriver count: %d\n", 
+		    hid_dev->subdriver_count);
+		
+		for (i = 0; i < hid_dev->subdriver_count; ++i) {
+			if (hid_dev->subdrivers[i].init != NULL) {
+				usb_log_debug("Initializing subdriver %d.\n",i);
+				rc = hid_dev->subdrivers[i].init(hid_dev);
+				if (rc != EOK) {
+					usb_log_warning("Failed to initialize"
+					    " HID subdriver structure.\n");
+				} else {
+					// at least one subdriver initialized
+					ok = true;
+				}
+			} else {
+				ok = true;
+			}
+		}
+		
+		rc = (ok) ? EOK : -1;	// what error to report
 	}
 	
 	return rc;
+}
+
+/*----------------------------------------------------------------------------*/
+
+bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer, 
+    size_t buffer_size, void *arg)
+{
+	int i;
+	
+	if (dev == NULL || arg == NULL || buffer == NULL) {
+		usb_log_error("Missing arguments to polling callback.\n");
+		return false;
+	}
+	
+	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
+	
+	bool cont = false;
+	
+	// continue if at least one of the subdrivers want to continue
+	for (i = 0; i < hid_dev->subdriver_count; ++i) {
+		if (hid_dev->subdrivers[i].poll != NULL
+		    && hid_dev->subdrivers[i].poll(hid_dev, buffer, 
+		    buffer_size)) {
+			cont = true;
+		}
+	}
+	
+	return cont;
 }
 
@@ -237,4 +488,6 @@
      void *arg)
 {
+	int i; 
+	
 	if (dev == NULL || arg == NULL) {
 		return;
@@ -243,4 +496,10 @@
 	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
 	
+	for (i = 0; i < hid_dev->subdriver_count; ++i) {
+		if (hid_dev->subdrivers[i].poll_end != NULL) {
+			hid_dev->subdrivers[i].poll_end(hid_dev, reason);
+		}
+	}
+	
 	usb_hid_free(&hid_dev);
 }
@@ -248,11 +507,11 @@
 /*----------------------------------------------------------------------------*/
 
-const char *usb_hid_get_function_name(usb_hid_iface_protocol_t device_type)
-{
-	switch (device_type) {
-	case USB_HID_PROTOCOL_KEYBOARD:
+const char *usb_hid_get_function_name(const usb_hid_dev_t *hid_dev)
+{
+	switch (hid_dev->poll_pipe_index) {
+	case USB_HID_KBD_POLL_EP_NO:
 		return HID_KBD_FUN_NAME;
 		break;
-	case USB_HID_PROTOCOL_MOUSE:
+	case USB_HID_MOUSE_POLL_EP_NO:
 		return HID_MOUSE_FUN_NAME;
 		break;
@@ -264,11 +523,14 @@
 /*----------------------------------------------------------------------------*/
 
-const char *usb_hid_get_class_name(usb_hid_iface_protocol_t device_type)
-{
-	switch (device_type) {
-	case USB_HID_PROTOCOL_KEYBOARD:
+const char *usb_hid_get_class_name(const usb_hid_dev_t *hid_dev)
+{
+	// this means that only boot protocol keyboards will be connected
+	// to the console; there is probably no better way to do this
+	
+	switch (hid_dev->poll_pipe_index) {
+	case USB_HID_KBD_POLL_EP_NO:
 		return HID_KBD_CLASS_NAME;
 		break;
-	case USB_HID_PROTOCOL_MOUSE:
+	case USB_HID_MOUSE_POLL_EP_NO:
 		return HID_MOUSE_CLASS_NAME;
 		break;
@@ -282,16 +544,22 @@
 void usb_hid_free(usb_hid_dev_t **hid_dev)
 {
+	int i;
+	
 	if (hid_dev == NULL || *hid_dev == NULL) {
 		return;
 	}
 	
-	switch ((*hid_dev)->device_type) {
-	case USB_HID_PROTOCOL_KEYBOARD:
-		usb_kbd_deinit(*hid_dev);
-		break;
-	case USB_HID_PROTOCOL_MOUSE:
-		break;
-	default:
-		break;
+	assert((*hid_dev)->subdrivers != NULL 
+	    || (*hid_dev)->subdriver_count == 0);
+	
+	for (i = 0; i < (*hid_dev)->subdriver_count; ++i) {
+		if ((*hid_dev)->subdrivers[i].deinit != NULL) {
+			(*hid_dev)->subdrivers[i].deinit(*hid_dev);
+		}
+	}
+	
+	// free the subdrivers info
+	if ((*hid_dev)->subdrivers != NULL) {
+		free((*hid_dev)->subdrivers);
 	}
 
Index: uspace/drv/usbhid/usbhid.h
===================================================================
--- uspace/drv/usbhid/usbhid.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/usbhid/usbhid.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -34,6 +34,6 @@
  */
 
-#ifndef USB_USBHID_H_
-#define USB_USBHID_H_
+#ifndef USB_HID_USBHID_H_
+#define USB_HID_USBHID_H_
 
 #include <stdint.h>
@@ -45,9 +45,28 @@
 #include <usb/classes/hid.h>
 
+struct usb_hid_dev;
+
+typedef int (*usb_hid_driver_init_t)(struct usb_hid_dev *);
+typedef void (*usb_hid_driver_deinit_t)(struct usb_hid_dev *);
+typedef bool (*usb_hid_driver_poll)(struct usb_hid_dev *, uint8_t *, size_t);
+typedef int (*usb_hid_driver_poll_ended)(struct usb_hid_dev *, bool reason);
+
+// TODO: add function and class name??
+typedef struct usb_hid_subdriver {	
+	/** Function to be called when initializing HID device. */
+	usb_hid_driver_init_t init;
+	/** Function to be called when destroying the HID device structure. */
+	usb_hid_driver_deinit_t deinit;
+	/** Function to be called when data arrives from the device. */
+	usb_hid_driver_poll poll;
+	/** Function to be called when polling ends. */
+	usb_hid_driver_poll_ended poll_end;
+} usb_hid_subdriver_t;
+
 /*----------------------------------------------------------------------------*/
 /**
  * Structure for holding general HID device data.
  */
-typedef struct usb_hid_dev_t {
+typedef struct usb_hid_dev {
 	/** Structure holding generic USB device information. */
 	usb_device_t *usb_dev;
@@ -59,6 +78,9 @@
 	int poll_pipe_index;
 	
-	/** Function to be called when data arrives from the device. */
-	usb_polling_callback_t poll_callback;
+	/** Subdrivers. */
+	usb_hid_subdriver_t *subdrivers;
+	
+	/** Number of subdrivers. */
+	int subdriver_count;
 	
 	/** Report descriptor. */
@@ -73,7 +95,4 @@
 	/** Arbitrary data (e.g. a special structure for handling keyboard). */
 	void *data;
-	
-	/** Type of the device (keyboard, mouse, generic HID device). */
-	usb_hid_iface_protocol_t device_type;
 } usb_hid_dev_t;
 
@@ -95,14 +114,17 @@
 int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev);
 
+bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer, 
+    size_t buffer_size, void *arg);
+
 void usb_hid_polling_ended_callback(usb_device_t *dev, bool reason, 
      void *arg);
 
-const char *usb_hid_get_function_name(usb_hid_iface_protocol_t device_type);
+const char *usb_hid_get_function_name(const usb_hid_dev_t *hid_dev);
 
-const char *usb_hid_get_class_name(usb_hid_iface_protocol_t device_type);
+const char *usb_hid_get_class_name(const usb_hid_dev_t *hid_dev);
 
 void usb_hid_free(usb_hid_dev_t **hid_dev);
 
-#endif /* USB_USBHID_H_ */
+#endif /* USB_HID_USBHID_H_ */
 
 /**
Index: uspace/drv/usbhid/usbhid.ma
===================================================================
--- uspace/drv/usbhid/usbhid.ma	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/usbhid/usbhid.ma	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -1,3 +1,3 @@
 100 usb&interface&class=HID&subclass=0x01&protocol=0x01
-100 usb&interface&class=HID&subclass=0x01&protocol=0x02
+1000 usb&interface&class=HID&subclass=0x01&protocol=0x02
 100 usb&interface&class=HID
Index: uspace/drv/usbhub/usbhub.c
===================================================================
--- uspace/drv/usbhub/usbhub.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/usbhub/usbhub.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -45,4 +45,5 @@
 #include <usb/request.h>
 #include <usb/classes/hub.h>
+#include <usb/devpoll.h>
 #include <stdio.h>
 
@@ -247,4 +248,12 @@
 	for (port = 0; port < hub_info->port_count + 1; port++) {
 		usb_hub_port_init(&hub_info->ports[port]);
+	}
+	for (port = 0; port < hub_info->port_count; port++) {
+		opResult = usb_hub_set_port_feature(hub_info->control_pipe,
+		    port+1, USB_HUB_FEATURE_PORT_POWER);
+		if (opResult != EOK) {
+			usb_log_error("cannot power on port %d;  %d\n",
+			    port+1, opResult);
+		}
 	}
 	usb_log_debug2("freeing data\n");
Index: uspace/drv/usbkbd/main.c
===================================================================
--- uspace/drv/usbkbd/main.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/usbkbd/main.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -42,4 +42,5 @@
 
 #include <usb/devdrv.h>
+#include <usb/devpoll.h>
 
 #include "kbddev.h"
Index: uspace/drv/usbmouse/main.c
===================================================================
--- uspace/drv/usbmouse/main.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/drv/usbmouse/main.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -36,4 +36,5 @@
 #include "mouse.h"
 #include <usb/debug.h>
+#include <usb/devpoll.h>
 #include <errno.h>
 #include <str_error.h>
