Index: kernel/Makefile
===================================================================
--- kernel/Makefile	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ kernel/Makefile	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -226,5 +226,4 @@
 	generic/src/proc/task.c \
 	generic/src/proc/the.c \
-	generic/src/proc/tasklet.c \
 	generic/src/syscall/syscall.c \
 	generic/src/syscall/copy.c \
@@ -382,5 +381,4 @@
 		generic/src/main/kinit.c \
 		generic/src/proc/the.c \
-		generic/src/proc/tasklet.c \
 		generic/src/mm/frame.c \
 		generic/src/mm/page.c \
Index: kernel/arch/mips32/include/atomic.h
===================================================================
--- kernel/arch/mips32/include/atomic.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ kernel/arch/mips32/include/atomic.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -91,4 +91,5 @@
 		"	sc %0, %1\n"
 		"	beqz %0, 1b\n"
+		"	nop\n"
 		"2:\n"
 		: "=&r" (tmp),
Index: kernel/generic/include/ipc/ipc.h
===================================================================
--- kernel/generic/include/ipc/ipc.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ kernel/generic/include/ipc/ipc.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -115,4 +115,10 @@
  */
 #define IPC_FF_ROUTE_FROM_ME  (1 << 0)
+
+/* Data transfer flags. */
+#define IPC_XF_NONE		0
+
+/** Restrict the transfer size if necessary. */
+#define IPC_XF_RESTRICT		(1 << 0)
 
 /** Kernel IPC interfaces
Index: rnel/generic/include/proc/tasklet.h
===================================================================
--- kernel/generic/include/proc/tasklet.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ 	(revision )
@@ -1,73 +1,0 @@
-/*
- * Copyright (c) 2007 Jan Hudecek
- * Copyright (c) 2008 Martin Decky
- * 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 genericproc
- * @{
- */
-/** @file tasklet.h
- * @brief Tasklets declarations
- */
-
-#ifndef KERN_TASKLET_H_
-#define KERN_TASKLET_H_
-
-#include <adt/list.h>
-
-/** Tasklet callback type */
-typedef void (* tasklet_callback_t)(void *arg);
-
-/** Tasklet state */
-typedef enum {
-	NotActive,
-	Scheduled,
-	InProgress,
-	Disabled
-} tasklet_state_t;
-
-/** Structure describing a tasklet */
-typedef struct tasklet_descriptor {
-	link_t link;
-	
-	/** Callback to call */
-	tasklet_callback_t callback;
-	
-	/** Argument passed to the callback */
-	void *arg;
-	
-	/** State of the tasklet */
-	tasklet_state_t state;
-} tasklet_descriptor_t;
-
-
-extern void tasklet_init(void);
-
-#endif
-
-/** @}
- */
Index: kernel/generic/src/ipc/sysipc.c
===================================================================
--- kernel/generic/src/ipc/sysipc.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ kernel/generic/src/ipc/sysipc.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -426,7 +426,13 @@
 	case IPC_M_DATA_READ: {
 		size_t size = IPC_GET_ARG2(call->data);
-		if ((size <= 0 || (size > DATA_XFER_LIMIT)))
+		if (size <= 0)
 			return ELIMIT;
-		
+		if (size > DATA_XFER_LIMIT) {
+			int flags = IPC_GET_ARG3(call->data);
+			if (flags & IPC_XF_RESTRICT)
+				IPC_SET_ARG2(call->data, DATA_XFER_LIMIT);
+			else
+				return ELIMIT;
+		}
 		break;
 	}
@@ -435,6 +441,12 @@
 		size_t size = IPC_GET_ARG2(call->data);
 		
-		if (size > DATA_XFER_LIMIT)
-			return ELIMIT;
+		if (size > DATA_XFER_LIMIT) {
+			int flags = IPC_GET_ARG3(call->data);
+			if (flags & IPC_XF_RESTRICT) {
+				size = DATA_XFER_LIMIT;
+				IPC_SET_ARG2(call->data, size);
+			} else
+				return ELIMIT;
+		}
 		
 		call->buffer = (uint8_t *) malloc(size, 0);
Index: kernel/generic/src/main/main.c
===================================================================
--- kernel/generic/src/main/main.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ kernel/generic/src/main/main.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -58,5 +58,4 @@
 #include <proc/thread.h>
 #include <proc/task.h>
-#include <proc/tasklet.h>
 #include <main/kinit.h>
 #include <main/version.h>
@@ -217,5 +216,4 @@
 	tlb_init();
 	ddi_init();
-	tasklet_init();
 	arch_post_mm_init();
 	arch_pre_smp_init();
Index: rnel/generic/src/proc/tasklet.c
===================================================================
--- kernel/generic/src/proc/tasklet.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ 	(revision )
@@ -1,64 +1,0 @@
-/*
- * Copyright (c) 2007 Jan Hudecek
- * Copyright (c) 2008 Martin Decky
- * 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 genericproc
- * @{
- */
-/** @file tasklet.c
- *  @brief Tasklet implementation
- */
-
-#include <proc/tasklet.h>
-#include <synch/spinlock.h>
-#include <mm/slab.h>
-#include <config.h>
-
-/** Spinlock protecting list of tasklets */
-SPINLOCK_INITIALIZE(tasklet_lock);
-
-/** Array of tasklet lists for every CPU */
-tasklet_descriptor_t **tasklet_list;
-
-void tasklet_init(void)
-{
-	unsigned int i;
-	
-	tasklet_list = malloc(sizeof(tasklet_descriptor_t *) * config.cpu_count, 0);
-	if (!tasklet_list)
-		panic("Error initializing tasklets.");
-	
-	for (i = 0; i < config.cpu_count; i++)
-		tasklet_list[i] = NULL;
-	
-	spinlock_initialize(&tasklet_lock, "tasklet_lock");
-}
-
-
-/** @}
- */
Index: uspace/app/bdsh/cmds/modules/cat/cat.c
===================================================================
--- uspace/app/bdsh/cmds/modules/cat/cat.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/app/bdsh/cmds/modules/cat/cat.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -195,5 +195,5 @@
 					wchar_t c = str_decode(buff, &offset, bytes);
 					if (c == 0) {
-						// reached end of string
+						/* Reached end of string */
 						break;
 					}
@@ -228,6 +228,8 @@
 	int rc;
 	
-	// reset global state
-	// TODO: move to structure?
+	/*
+	 * reset global state
+	 * TODO: move to structure?
+	 */
 	paging_enabled = false;
 	chars_remaining = 0;
Index: uspace/app/trace/trace.c
===================================================================
--- uspace/app/trace/trace.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/app/trace/trace.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -53,5 +53,5 @@
 #include <libc.h>
 
-// Temporary: service and method names
+/* Temporary: service and method names */
 #include "proto.h"
 #include <ipc/services.h>
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: pace/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: pace/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>
Index: uspace/lib/c/arch/mips32/include/atomic.h
===================================================================
--- uspace/lib/c/arch/mips32/include/atomic.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/lib/c/arch/mips32/include/atomic.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -70,5 +70,4 @@
 		"	sc %0, %1\n"
 		"	beq %0, %4, 1b\n"	/* if the atomic operation failed, try again */
-		/*	nop	*/		/* nop is inserted automatically by compiler */
 		"	nop\n"
 		: "=&r" (tmp),
Index: uspace/lib/c/generic/adt/measured_strings.c
===================================================================
--- uspace/lib/c/generic/adt/measured_strings.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/lib/c/generic/adt/measured_strings.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -74,5 +74,5 @@
 	new->length = length;
 	new->value = ((uint8_t *) new) + sizeof(measured_string_t);
-	// append terminating zero explicitly - to be safe
+	/* Append terminating zero explicitly - to be safe */
 	memcpy(new->value, string, new->length);
 	new->value[new->length] = '\0';
Index: uspace/lib/c/generic/async.c
===================================================================
--- uspace/lib/c/generic/async.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/lib/c/generic/async.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -1586,12 +1586,14 @@
  * @param dst     Address of the beginning of the destination buffer.
  * @param size    Size of the destination buffer.
+ * @param flags   Flags to control the data transfer.
  *
  * @return Zero on success or a negative error code from errno.h.
  *
  */
-int async_data_read_start(int phoneid, void *dst, size_t size)
-{
-	return async_req_2_0(phoneid, IPC_M_DATA_READ, (sysarg_t) dst,
-	    (sysarg_t) size);
+int
+async_data_read_start_generic(int phoneid, void *dst, size_t size, int flags)
+{
+	return async_req_3_0(phoneid, IPC_M_DATA_READ, (sysarg_t) dst,
+	    (sysarg_t) size, (sysarg_t) flags);
 }
 
@@ -1683,12 +1685,15 @@
  * @param src     Address of the beginning of the source buffer.
  * @param size    Size of the source buffer.
+ * @param flags   Flags to control the data transfer.
  *
  * @return Zero on success or a negative error code from errno.h.
  *
  */
-int async_data_write_start(int phoneid, const void *src, size_t size)
-{
-	return async_req_2_0(phoneid, IPC_M_DATA_WRITE, (sysarg_t) src,
-	    (sysarg_t) size);
+int
+async_data_write_start_generic(int phoneid, const void *src, size_t size,
+    int flags)
+{
+	return async_req_3_0(phoneid, IPC_M_DATA_WRITE, (sysarg_t) src,
+	    (sysarg_t) size, (sysarg_t) flags);
 }
 
Index: uspace/lib/c/generic/vfs/vfs.c
===================================================================
--- uspace/lib/c/generic/vfs/vfs.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/lib/c/generic/vfs/vfs.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -378,5 +378,6 @@
 	
 	req = async_send_1(vfs_phone, VFS_IN_READ, fildes, &answer);
-	rc = async_data_read_start(vfs_phone, (void *)buf, nbyte);
+	rc = async_data_read_start_generic(vfs_phone, (void *) buf, nbyte,
+	    IPC_XF_RESTRICT);
 	if (rc != EOK) {
 		vfs_exchange_end(vfs_phone);
@@ -407,5 +408,6 @@
 	
 	req = async_send_1(vfs_phone, VFS_IN_WRITE, fildes, &answer);
-	rc = async_data_write_start(vfs_phone, (void *)buf, nbyte);
+	rc = async_data_write_start_generic(vfs_phone, (void *) buf, nbyte,
+	    IPC_XF_RESTRICT);
 	if (rc != EOK) {
 		vfs_exchange_end(vfs_phone);
Index: uspace/lib/c/include/async.h
===================================================================
--- uspace/lib/c/include/async.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/lib/c/include/async.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -341,5 +341,8 @@
 
 extern aid_t async_data_read(int, void *, size_t, ipc_call_t *);
-extern int async_data_read_start(int, void *, size_t);
+#define async_data_read_start(p, buf, len) \
+	async_data_read_start_generic((p), (buf), (len), IPC_XF_NONE)
+
+extern int async_data_read_start_generic(int, void *, size_t, int);
 extern bool async_data_read_receive(ipc_callid_t *, size_t *);
 extern int async_data_read_finalize(ipc_callid_t, const void *, size_t);
@@ -380,5 +383,8 @@
 	    (arg4), (answer))
 
-extern int async_data_write_start(int, const void *, size_t);
+#define async_data_write_start(p, buf, len) \
+	async_data_write_start_generic((p), (buf), (len), IPC_XF_NONE)
+
+extern int async_data_write_start_generic(int, const void *, size_t, int);
 extern bool async_data_write_receive(ipc_callid_t *, size_t *);
 extern int async_data_write_finalize(ipc_callid_t, void *, size_t);
Index: uspace/lib/drv/generic/driver.c
===================================================================
--- uspace/lib/drv/generic/driver.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/lib/drv/generic/driver.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -47,4 +47,5 @@
 #include <stdlib.h>
 #include <str.h>
+#include <str_error.h>
 #include <ctype.h>
 #include <errno.h>
@@ -402,5 +403,5 @@
 			    get_remote_method(rem_iface, iface_method_idx);
 			if (iface_method_ptr == NULL) {
-				// the interface has not such method
+				/* The interface has not such method */
 				printf("%s: driver_connection_gen error - "
 				    "invalid interface method.", driver->name);
@@ -655,4 +656,6 @@
 int ddf_driver_main(driver_t *drv)
 {
+	int rc;
+
 	/*
 	 * Remember the driver structure - driver_ops will be called by generic
@@ -668,9 +671,21 @@
 	
 	/*
-	 * Register driver by device manager with generic handler for incoming
-	 * connections.
+	 * Register driver with device manager using generic handler for
+	 * incoming connections.
 	 */
-	devman_driver_register(driver->name, driver_connection);
-	
+	rc = devman_driver_register(driver->name, driver_connection);
+	if (rc != EOK) {
+		printf("Error: Failed to register driver with device manager "
+		    "(%s).\n", (rc == EEXISTS) ? "driver already started" :
+		    str_error(rc));
+		
+		return 1;
+	}
+	
+	/* Return success from the task since server has started. */
+	rc = task_retval(0);
+	if (rc != EOK)
+		return 1;
+
 	async_manager();
 	
Index: uspace/lib/net/generic/generic.c
===================================================================
--- uspace/lib/net/generic/generic.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/lib/net/generic/generic.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -106,5 +106,5 @@
 		return EBADMEM;
 
-	// request the address
+	/* Request the address */
 	message_id = async_send_1(phone, (sysarg_t) message,
 	    (sysarg_t) device_id, NULL);
@@ -112,7 +112,7 @@
 	async_wait_for(message_id, &result);
 
-	// if not successful
+	/* If not successful */
 	if ((string == EOK) && (result != EOK)) {
-		// clear the data
+		/* Clear the data */
 		free(*address);
 		free(*data);
@@ -242,5 +242,5 @@
 		return EBADMEM;
 
-	// request the translation
+	/* Request the translation */
 	message_id = async_send_3(phone, (sysarg_t) message,
 	    (sysarg_t) device_id, (sysarg_t) count, (sysarg_t) service, NULL);
@@ -249,7 +249,7 @@
 	async_wait_for(message_id, &result);
 
-	// if not successful
+	/* If not successful */
 	if ((string == EOK) && (result != EOK)) {
-		// clear the data
+		/* Clear the data */
 		free(*translation);
 		free(*data);
Index: uspace/lib/net/generic/net_checksum.c
===================================================================
--- uspace/lib/net/generic/net_checksum.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/lib/net/generic/net_checksum.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -52,5 +52,5 @@
 uint16_t compact_checksum(uint32_t sum)
 {
-	// shorten to the 16 bits
+	/* Shorten to the 16 bits */
 	while (sum >> 16)
 		sum = (sum & 0xffff) + (sum >> 16);
@@ -72,9 +72,9 @@
 	size_t index;
 
-	// sum all the 16 bit fields
+	/* Sum all the 16 bit fields */
 	for (index = 0; index + 1 < length; index += 2)
 		seed += (data[index] << 8) + data[index + 1];
 
-	// last odd byte with zero padding
+	/* Last odd byte with zero padding */
 	if (index + 1 == length)
 		seed += data[index] << 8;
@@ -94,39 +94,39 @@
 	size_t index;
 
-	// process full bytes
+	/* Process full bytes */
 	while (length >= 8) {
-		// add the data
+		/* Add the data */
 		seed ^= (*data) << 24;
 		
-		// for each added bit
+		/* For each added bit */
 		for (index = 0; index < 8; ++index) {
-			// if the first bit is set
+			/* If the first bit is set */
 			if (seed & 0x80000000) {
-				// shift and divide the checksum
+				/* Shift and divide the checksum */
 				seed = (seed << 1) ^ ((uint32_t) CRC_DIVIDER_BE);
 			} else {
-				// shift otherwise
+				/* Shift otherwise */
 				seed <<= 1;
 			}
 		}
 		
-		// move to the next byte
+		/* Move to the next byte */
 		++data;
 		length -= 8;
 	}
 
-	// process the odd bits
+	/* Process the odd bits */
 	if (length > 0) {
-		// add the data with zero padding
+		/* Add the data with zero padding */
 		seed ^= ((*data) & (0xff << (8 - length))) << 24;
 		
-		// for each added bit
+		/* For each added bit */
 		for (index = 0; index < length; ++index) {
-			// if the first bit is set
+			/* If the first bit is set */
 			if (seed & 0x80000000) {
-				// shift and divide the checksum
+				/* Shift and divide the checksum */
 				seed = (seed << 1) ^ ((uint32_t) CRC_DIVIDER_BE);
 			} else {
-				// shift otherwise
+				/* Shift otherwise */
 				seed <<= 1;
 			}
@@ -148,38 +148,38 @@
 	size_t index;
 
-	// process full bytes
+	/* Process full bytes */
 	while (length >= 8) {
-		// add the data
+		/* Add the data */
 		seed ^= (*data);
 		
-		// for each added bit
+		/* For each added bit */
 		for (index = 0; index < 8; ++index) {
-			// if the last bit is set
+			/* If the last bit is set */
 			if (seed & 1) {
-				// shift and divide the checksum
+				/* Shift and divide the checksum */
 				seed = (seed >> 1) ^ ((uint32_t) CRC_DIVIDER_LE);
 			} else {
-				// shift otherwise
+				/* Shift otherwise */
 				seed >>= 1;
 			}
 		}
 		
-		// move to the next byte
+		/* Move to the next byte */
 		++data;
 		length -= 8;
 	}
 
-	// process the odd bits
+	/* Process the odd bits */
 	if (length > 0) {
-		// add the data with zero padding
+		/* Add the data with zero padding */
 		seed ^= (*data) >> (8 - length);
 		
 		for (index = 0; index < length; ++index) {
-			// if the last bit is set
+			/* If the last bit is set */
 			if (seed & 1) {
-				// shift and divide the checksum
+				/* Shift and divide the checksum */
 				seed = (seed >> 1) ^ ((uint32_t) CRC_DIVIDER_LE);
 			} else {
-				// shift otherwise
+				/* Shift otherwise */
 				seed >>= 1;
 			}
@@ -198,5 +198,5 @@
 uint16_t flip_checksum(uint16_t checksum)
 {
-	// flip, zero is returned as 0xFFFF (not flipped)
+	/* Flip, zero is returned as 0xFFFF (not flipped) */
 	checksum = ~checksum;
 	return checksum ? checksum : IP_CHECKSUM_ZERO;
@@ -216,5 +216,5 @@
 uint16_t ip_checksum(uint8_t *data, size_t length)
 {
-	// compute, compact and flip the data checksum
+	/* Compute, compact and flip the data checksum */
 	return flip_checksum(compact_checksum(compute_checksum(0, data,
 	    length)));
Index: uspace/lib/net/generic/packet_client.c
===================================================================
--- uspace/lib/net/generic/packet_client.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/lib/net/generic/packet_client.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -267,5 +267,5 @@
 		return NULL;
 
-	// get a new packet
+	/* Get a new packet */
 	copy = packet_get_4_remote(phone, PACKET_DATA_LENGTH(packet),
 	    PACKET_MAX_ADDRESS_LENGTH(packet), packet->max_prefix,
@@ -274,10 +274,10 @@
 		return NULL;
 
-	// get addresses
+	/* Get addresses */
 	addrlen = packet_get_addr(packet, &src, &dest);
-	// copy data
+	/* Copy data */
 	if ((packet_copy_data(copy, packet_get_data(packet),
 	    PACKET_DATA_LENGTH(packet)) == EOK) &&
-	    // copy addresses if present
+	    /* Copy addresses if present */
 	    ((addrlen <= 0) ||
 	    (packet_set_addr(copy, src, dest, addrlen) == EOK))) {
Index: uspace/lib/net/il/ip_client.c
===================================================================
--- uspace/lib/net/il/ip_client.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/lib/net/il/ip_client.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -124,5 +124,6 @@
 
 	// TODO IPv6
-/*	case AF_INET6:
+#if 0
+	case AF_INET6:
 		if (addrlen != sizeof(struct sockaddr_in6))
 			return EINVAL;
@@ -130,5 +131,5 @@
 		address_in6 = (struct sockaddr_in6 *) addr;
 		return EOK;
-*/
+#endif
 
 	default:
@@ -159,6 +160,8 @@
 	size_t padding;
 
-	// compute the padding if IP options are set
-	// multiple of 4 bytes
+	/*
+	 * Compute the padding if IP options are set
+	 * multiple of 4 bytes
+	 */
 	padding =  ipopt_length % 4;
 	if (padding) {
@@ -167,14 +170,14 @@
 	}
 
-	// prefix the header
+	/* Prefix the header */
 	data = (uint8_t *) packet_prefix(packet, sizeof(ip_header_t) + padding);
 	if (!data)
 		return ENOMEM;
 
-	// add the padding
+	/* Add the padding */
 	while (padding--)
 		data[sizeof(ip_header_t) + padding] = IPOPT_NOOP;
 
-	// set the header
+	/* Set the header */
 	header = (ip_header_t *) data;
 	header->header_length = IP_COMPUTE_HEADER_LENGTH(sizeof(ip_header_t) +
Index: uspace/lib/net/tl/icmp_client.c
===================================================================
--- uspace/lib/net/tl/icmp_client.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/lib/net/tl/icmp_client.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -81,5 +81,5 @@
 		*mtu = header->un.frag.mtu;
 
-	// remove debug dump
+	/* Remove debug dump */
 #ifdef CONFIG_DEBUG
 	printf("ICMP error %d (%d) in packet %d\n", header->type, header->code,
Index: uspace/lib/net/tl/socket_core.c
===================================================================
--- uspace/lib/net/tl/socket_core.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/lib/net/tl/socket_core.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -91,11 +91,11 @@
 	int packet_id;
 
-	// if bound
+	/* If bound */
 	if (socket->port) {
-		// release the port
+		/* Release the port */
 		socket_port_release(global_sockets, socket);
 	}
 	
-	// release all received packets
+	/* Release all received packets */
 	while ((packet_id = dyn_fifo_pop(&socket->received)) >= 0)
 		pq_release_remote(packet_phone, packet_id);
@@ -166,5 +166,5 @@
 	int rc;
 
-	// create a wrapper
+	/* Create a wrapper */
 	socket_ref = malloc(sizeof(*socket_ref));
 	if (!socket_ref)
@@ -172,5 +172,5 @@
 
 	*socket_ref = socket;
-	// add the wrapper
+	/* Add the wrapper */
 	rc = socket_port_map_add(&socket_port->map, key, key_length,
 	    socket_ref);
@@ -206,5 +206,5 @@
 	int rc;
 
-	// create a wrapper
+	/* Create a wrapper */
 	socket_port = malloc(sizeof(*socket_port));
 	if (!socket_port)
@@ -221,5 +221,5 @@
 		goto fail;
 	
-	// register the incomming port
+	/* Register the incoming port */
 	rc = socket_ports_add(global_sockets, port, socket_port);
 	if (rc < 0)
@@ -277,25 +277,25 @@
 		
 		address_in = (struct sockaddr_in *) addr;
-		// find the socket
+		/* Find the socket */
 		socket = socket_cores_find(local_sockets, socket_id);
 		if (!socket)
 			return ENOTSOCK;
 		
-		// bind a free port?
+		/* Bind a free port? */
 		if (address_in->sin_port <= 0)
 			return socket_bind_free_port(global_sockets, socket,
 			     free_ports_start, free_ports_end, last_used_port);
 		
-		// try to find the port
+		/* Try to find the port */
 		socket_port = socket_ports_find(global_sockets,
 		    ntohs(address_in->sin_port));
 		if (socket_port) {
-			// already used
+			/* Already used */
 			return EADDRINUSE;
 		}
 		
-		// if bound
+		/* If bound */
 		if (socket->port) {
-			// release the port
+			/* Release the port */
 			socket_port_release(global_sockets, socket);
 		}
@@ -333,5 +333,5 @@
 	int index;
 
-	// from the last used one
+	/* From the last used one */
 	index = last_used_port;
 	
@@ -339,18 +339,18 @@
 		++index;
 		
-		// til the range end
+		/* Till the range end */
 		if (index >= free_ports_end) {
-			// start from the range beginning
+			/* Start from the range beginning */
 			index = free_ports_start - 1;
 			do {
 				++index;
-				// til the last used one
+				/* Till the last used one */
 				if (index >= last_used_port) {
-					// none found
+					/* None found */
 					return ENOTCONN;
 				}
 			} while (socket_ports_find(global_sockets, index));
 			
-			// found, break immediately
+			/* Found, break immediately */
 			break;
 		}
@@ -376,5 +376,7 @@
 
 	count = 0;
-//	socket_id = socket_globals.last_id;
+#if 0
+	socket_id = socket_globals.last_id;
+#endif
 	do {
 		if (count < SOCKET_ID_TRIES) {
@@ -384,12 +386,14 @@
 			socket_id = 1;
 			++count;
-		// only this branch for last_id
+		/* Only this branch for last_id */
 		} else {
 			if (socket_id < INT_MAX) {
 				++ socket_id;
-/*			} else if(socket_globals.last_id) {
-*				socket_globals.last_id = 0;
-*				socket_id = 1;
-*/			} else {
+#if 0
+			} else if(socket_globals.last_id) {
+				socket_globals.last_id = 0;
+				socket_id = 1;
+#endif
+			} else {
 				return ELIMIT;
 			}
@@ -425,5 +429,5 @@
 		return EINVAL;
 	
-	// store the socket
+	/* Store the socket */
 	if (*socket_id <= 0) {
 		positive = (*socket_id == 0);
@@ -441,5 +445,5 @@
 		return ENOMEM;
 	
-	// initialize
+	/* Initialize */
 	socket->phone = app_phone;
 	socket->port = -1;
@@ -493,10 +497,10 @@
 	int accepted_id;
 
-	// find the socket
+	/* Find the socket */
 	socket = socket_cores_find(local_sockets, socket_id);
 	if (!socket)
 		return ENOTSOCK;
 	
-	// destroy all accepted sockets
+	/* Destroy all accepted sockets */
 	while ((accepted_id = dyn_fifo_pop(&socket->accepted)) >= 0)
 		socket_destroy(packet_phone, accepted_id, local_sockets,
@@ -535,13 +539,13 @@
 	next_packet = pq_next(packet);
 	if (!next_packet) {
-		// write all if only one fragment
+		/* Write all if only one fragment */
 		rc = data_reply(packet_get_data(packet),
 		    packet_get_data_length(packet));
 		if (rc != EOK)
 			return rc;
-		// store the total length
+		/* Store the total length */
 		*length = packet_get_data_length(packet);
 	} else {
-		// count the packet fragments
+		/* Count the packet fragments */
 		fragments = 1;
 		next_packet = pq_next(packet);
@@ -549,5 +553,5 @@
 			++fragments;
 		
-		// compute and store the fragment lengths
+		/* Compute and store the fragment lengths */
 		lengths = (size_t *) malloc(sizeof(size_t) * fragments +
 		    sizeof(size_t));
@@ -565,5 +569,5 @@
 		}
 		
-		// write the fragment lengths
+		/* Write the fragment lengths */
 		rc = data_reply(lengths, sizeof(int) * (fragments + 1));
 		if (rc != EOK) {
@@ -573,5 +577,5 @@
 		next_packet = packet;
 		
-		// write the fragments
+		/* Write the fragments */
 		for (index = 0; index < fragments; ++index) {
 			rc = data_reply(packet_get_data(next_packet),
@@ -584,5 +588,5 @@
 		}
 		
-		// store the total length
+		/* Store the total length */
 		*length = lengths[fragments];
 		free(lengths);
@@ -636,8 +640,8 @@
 		return;
 	
-	// find ports
+	/* Find ports */
 	socket_port = socket_ports_find(global_sockets, socket->port);
 	if (socket_port) {
-		// find the socket
+		/* Find the socket */
 		socket_ref = socket_port_map_find(&socket_port->map,
 		    socket->key, socket->key_length);
@@ -646,13 +650,13 @@
 			--socket_port->count;
 			
-			// release if empty
+			/* Release if empty */
 			if (socket_port->count <= 0) {
-				// destroy the map
+				/* Destroy the map */
 				socket_port_map_destroy(&socket_port->map, free);
-				// release the port
+				/* Release the port */
 				socket_ports_exclude(global_sockets,
 				    socket->port, free);
 			} else {
-				// remove
+				/* Remove */
 				socket_port_map_exclude(&socket_port->map,
 				    socket->key, socket->key_length, free);
@@ -685,10 +689,10 @@
 	int rc;
 
-	// find ports
+	/* Find ports */
 	socket_port = socket_ports_find(global_sockets, port);
 	if (!socket_port)
 		return ENOENT;
 	
-	// add the socket
+	/* Add the socket */
 	rc = socket_port_add_core(socket_port, socket, key, key_length);
 	if (rc != EOK)
Index: uspace/lib/net/tl/tl_common.c
===================================================================
--- uspace/lib/net/tl/tl_common.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/lib/net/tl/tl_common.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -255,5 +255,5 @@
 	int length;
 
-	// detach the first packet and release the others
+	/* Detach the first packet and release the others */
 	next = pq_detach(packet);
 	if (next)
@@ -262,6 +262,8 @@
 	length = packet_get_addr(packet, &src, NULL);
 	if ((length > 0) && (!error) && (icmp_phone >= 0) &&
-	    // set both addresses to the source one (avoids the source address
-	    // deletion before setting the destination one)
+	    /*
+	     * Set both addresses to the source one (avoids the source address
+	     * deletion before setting the destination one)
+	     */
 	    (packet_set_addr(packet, src, src, (size_t) length) == EOK)) {
 		return EOK;
@@ -299,9 +301,9 @@
 		return EINVAL;
 
-	// get the data length
+	/* Get the data length */
 	if (!async_data_write_receive(&callid, &length))
 		return EINVAL;
 
-	// get a new packet
+	/* Get a new packet */
 	*packet = packet_get_4_remote(packet_phone, length, dimension->addr_len,
 	    prefix + dimension->prefix, dimension->suffix);
@@ -309,5 +311,5 @@
 		return ENOMEM;
 
-	// allocate space in the packet
+	/* Allocate space in the packet */
 	data = packet_suffix(*packet, length);
 	if (!data) {
@@ -316,5 +318,5 @@
 	}
 
-	// read the data into the packet
+	/* Read the data into the packet */
 	rc = async_data_write_finalize(callid, data, length);
 	if (rc != EOK) {
@@ -323,5 +325,5 @@
 	}
 	
-	// set the packet destination address
+	/* Set the packet destination address */
 	rc = packet_set_addr(*packet, NULL, (uint8_t *) addr, addrlen);
 	if (rc != EOK) {
Index: uspace/lib/packet/generic/packet_server.c
===================================================================
--- uspace/lib/packet/generic/packet_server.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/lib/packet/generic/packet_server.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -112,9 +112,9 @@
     size_t max_content, size_t max_suffix)
 {
-	// clear the packet content
+	/* Clear the packet content */
 	bzero(((void *) packet) + sizeof(packet_t),
 	    packet->length - sizeof(packet_t));
 	
-	// clear the packet header
+	/* Clear the packet header */
 	packet->order = 0;
 	packet->metric = 0;
@@ -151,5 +151,5 @@
 	assert(fibril_mutex_is_locked(&ps_globals.lock));
 
-	// already locked
+	/* Already locked */
 	packet = (packet_t *) mmap(NULL, length, PROTO_READ | PROTO_WRITE,
 	    MAP_SHARED | MAP_ANONYMOUS, 0, 0);
Index: uspace/lib/softint/generic/multiplication.c
===================================================================
--- uspace/lib/softint/generic/multiplication.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/lib/softint/generic/multiplication.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -109,5 +109,5 @@
 	 * result does not fit in signed one */
 	if (SOFTINT_CHECK_OF && ((t2 < t1) || (t2 & (1ull << 63)))) {
-		// error, overflow
+		/* Error, overflow */
 		return (neg ? INT64_MIN : INT64_MAX);
 	}
Index: uspace/lib/usb/include/usb/devdrv.h
===================================================================
--- uspace/lib/usb/include/usb/devdrv.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/lib/usb/include/usb/devdrv.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -162,11 +162,4 @@
     usb_endpoint_description_t **);
 
-typedef bool (*usb_polling_callback_t)(usb_device_t *,
-    uint8_t *, size_t, void *);
-typedef void (*usb_polling_terminted_callback_t)(usb_device_t *, bool, void *);
-
-int usb_device_auto_poll(usb_device_t *, size_t,
-    usb_polling_callback_t, size_t, usb_polling_terminted_callback_t, void *);
-
 int usb_device_retrieve_descriptors(usb_pipe_t *, usb_device_descriptors_t *);
 int usb_device_create_pipes(ddf_dev_t *, usb_device_connection_t *,
Index: uspace/lib/usb/include/usb/devpoll.h
===================================================================
--- uspace/lib/usb/include/usb/devpoll.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
+++ uspace/lib/usb/include/usb/devpoll.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libusb
+ * @{
+ */
+/** @file
+ * USB device polling functions.
+ */
+#ifndef LIBUSB_DEVPOLL_H_
+#define LIBUSB_DEVPOLL_H_
+
+#include <usb/devdrv.h>
+#include <time.h>
+
+typedef struct {
+	/** Level of debugging messages from auto polling.
+	 * 0 - nothing
+	 * 1 - inform about errors and polling start/end
+	 * 2 - also dump every retrieved buffer
+	 */
+	int debug;
+	/** Maximum number of consecutive errors before polling termination. */
+	size_t max_failures;
+	/** Delay between poll requests in milliseconds.
+	 * Set to negative value to use value from endpoint descriptor.
+	 */
+	int delay;
+	/** Whether to automatically try to clear the HALT feature after
+	 * the endpoint stalls.
+	 */
+	bool auto_clear_halt;
+	/** Callback when data arrives.
+	 *
+	 * @param dev Device that was polled.
+	 * @param data Data buffer (in USB endianness).
+	 * @param data_size Size of the @p data buffer in bytes.
+	 * @param arg Custom argument.
+	 * @return Whether to continue in polling.
+	 */
+	bool (*on_data)(usb_device_t *dev, uint8_t *data, size_t data_size,
+	    void *arg);
+	/** Callback when polling is terminated.
+	 *
+	 * @param dev Device where the polling was terminated.
+	 * @param due_to_errors Whether polling stopped due to several failures.
+	 * @param arg Custom argument.
+	 */
+	void (*on_polling_end)(usb_device_t *dev, bool due_to_errors,
+	    void *arg);
+	/** Callback when error occurs.
+	 *
+	 * @param dev Device where error occurred.
+	 * @param err_code Error code (as returned from usb_pipe_read).
+	 * @param arg Custom argument.
+	 * @return Whether to continue in polling.
+	 */
+	bool (*on_error)(usb_device_t *dev, int err_code, void *arg);
+} usb_device_auto_polling_t;
+
+int usb_device_auto_polling(usb_device_t *, size_t, usb_device_auto_polling_t *,
+    size_t, void *);
+
+typedef bool (*usb_polling_callback_t)(usb_device_t *,
+    uint8_t *, size_t, void *);
+typedef void (*usb_polling_terminted_callback_t)(usb_device_t *, bool, void *);
+
+int usb_device_auto_poll(usb_device_t *, size_t,
+    usb_polling_callback_t, size_t, usb_polling_terminted_callback_t, void *);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/include/usb/host/batch.h
===================================================================
--- uspace/lib/usb/include/usb/host/batch.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/lib/usb/include/usb/host/batch.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -43,34 +43,27 @@
 typedef struct usb_transfer_batch usb_transfer_batch_t;
 struct usb_transfer_batch {
+	endpoint_t *ep;
 	link_t link;
-	usb_target_t target;
-	usb_transfer_type_t transfer_type;
-	usb_speed_t speed;
-	usb_direction_t direction;
 	usbhc_iface_transfer_in_callback_t callback_in;
 	usbhc_iface_transfer_out_callback_t callback_out;
+	void *arg;
 	char *buffer;
-	char *transport_buffer;
+	char *data_buffer;
 	size_t buffer_size;
 	char *setup_buffer;
 	size_t setup_size;
-	size_t max_packet_size;
 	size_t transfered_size;
 	void (*next_step)(usb_transfer_batch_t *);
 	int error;
 	ddf_fun_t *fun;
-	void *arg;
-	endpoint_t *ep;
 	void *private_data;
+	void (*private_data_dtor)(void *p_data);
 };
 
 void usb_transfer_batch_init(
     usb_transfer_batch_t *instance,
-    usb_target_t target,
-    usb_transfer_type_t transfer_type,
-    usb_speed_t speed,
-    size_t max_packet_size,
+    endpoint_t *ep,
     char *buffer,
-    char *transport_buffer,
+    char *data_buffer,
     size_t buffer_size,
     char *setup_buffer,
@@ -80,17 +73,12 @@
     void *arg,
     ddf_fun_t *fun,
-		endpoint_t *ep,
-    void *private_data
+    void *private_data,
+    void (*private_data_dtor)(void *p_data)
 );
 
-static inline usb_transfer_batch_t *usb_transfer_batch_from_link(link_t *l)
-{
-	assert(l);
-	return list_get_instance(l, usb_transfer_batch_t, link);
-}
-
-void usb_transfer_batch_call_in(usb_transfer_batch_t *instance);
-void usb_transfer_batch_call_out(usb_transfer_batch_t *instance);
+void usb_transfer_batch_call_in_and_dispose(usb_transfer_batch_t *instance);
+void usb_transfer_batch_call_out_and_dispose(usb_transfer_batch_t *instance);
 void usb_transfer_batch_finish(usb_transfer_batch_t *instance);
+void usb_transfer_batch_dispose(usb_transfer_batch_t *instance);
 
 static inline void usb_transfer_batch_finish_error(
@@ -102,4 +90,10 @@
 }
 
+static inline usb_transfer_batch_t *usb_transfer_batch_from_link(link_t *l)
+{
+	assert(l);
+	return list_get_instance(l, usb_transfer_batch_t, link);
+}
+
 #endif
 /**
Index: uspace/lib/usb/include/usb/host/device_keeper.h
===================================================================
--- uspace/lib/usb/include/usb/host/device_keeper.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/lib/usb/include/usb/host/device_keeper.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -54,6 +54,4 @@
 	usb_speed_t speed;
 	bool occupied;
-	link_t endpoints;
-	uint16_t control_used;
 	devman_handle_t handle;
 };
@@ -65,17 +63,8 @@
 	struct usb_device_info devices[USB_ADDRESS_COUNT];
 	fibril_mutex_t guard;
-	fibril_condvar_t change;
 	usb_address_t last_address;
 } usb_device_keeper_t;
 
 void usb_device_keeper_init(usb_device_keeper_t *instance);
-
-void usb_device_keeper_reserve_default_address(
-    usb_device_keeper_t *instance, usb_speed_t speed);
-
-void usb_device_keeper_release_default_address(usb_device_keeper_t *instance);
-
-void usb_device_keeper_reset_if_need(usb_device_keeper_t *instance,
-    usb_target_t target, const uint8_t *setup_data);
 
 usb_address_t device_keeper_get_free_address(usb_device_keeper_t *instance,
Index: uspace/lib/usb/include/usb/host/endpoint.h
===================================================================
--- uspace/lib/usb/include/usb/host/endpoint.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/lib/usb/include/usb/host/endpoint.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -54,4 +54,9 @@
 	fibril_condvar_t avail;
 	volatile bool active;
+	struct {
+		void *data;
+		int (*toggle_get)(void *);
+		void (*toggle_set)(void *, int);
+	} hc_data;
 } endpoint_t;
 
@@ -61,4 +66,9 @@
 
 void endpoint_destroy(endpoint_t *instance);
+
+void endpoint_set_hc_data(endpoint_t *instance,
+    void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int));
+
+void endpoint_clear_hc_data(endpoint_t *instance);
 
 void endpoint_use(endpoint_t *instance);
Index: uspace/lib/usb/include/usb/host/usb_endpoint_manager.h
===================================================================
--- uspace/lib/usb/include/usb/host/usb_endpoint_manager.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/lib/usb/include/usb/host/usb_endpoint_manager.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -66,9 +66,4 @@
     endpoint_t *ep, size_t data_size);
 
-int usb_endpoint_manager_register_ep_wait(usb_endpoint_manager_t *instance,
-    usb_address_t address, usb_endpoint_t ep, usb_direction_t direction,
-    void *data, void (*data_remove_callback)(void* data, void* arg), void *arg,
-    size_t bw);
-
 int usb_endpoint_manager_unregister_ep(usb_endpoint_manager_t *instance,
     usb_address_t address, usb_endpoint_t ep, usb_direction_t direction);
@@ -80,4 +75,28 @@
 void usb_endpoint_manager_reset_if_need(
     usb_endpoint_manager_t *instance, usb_target_t target, const uint8_t *data);
+
+static inline int usb_endpoint_manager_add_ep(usb_endpoint_manager_t *instance,
+    usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction,
+    usb_transfer_type_t type, usb_speed_t speed, size_t max_packet_size,
+    size_t data_size)
+{
+	endpoint_t *ep = malloc(sizeof(endpoint_t));
+	if (ep == NULL)
+		return ENOMEM;
+
+	int ret = endpoint_init(ep, address, endpoint, direction, type, speed,
+	    max_packet_size);
+	if (ret != EOK) {
+		free(ep);
+		return ret;
+	}
+
+	ret = usb_endpoint_manager_register_ep(instance, ep, data_size);
+	if (ret != EOK) {
+		endpoint_destroy(ep);
+		return ret;
+	}
+	return EOK;
+}
 #endif
 /**
Index: uspace/lib/usb/include/usb/pipes.h
===================================================================
--- uspace/lib/usb/include/usb/pipes.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/lib/usb/include/usb/pipes.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -99,4 +99,9 @@
 	/** Number of active transfers over the pipe. */
 	int refcount;
+
+	/** Whether to automatically reset halt on the endpoint.
+	 * Valid only for control endpoint zero.
+	 */
+	bool auto_reset_halt;
 } usb_pipe_t;
 
Index: uspace/lib/usb/src/devpoll.c
===================================================================
--- uspace/lib/usb/src/devpoll.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/lib/usb/src/devpoll.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -33,7 +33,8 @@
  * USB device driver framework - automatic interrupt polling.
  */
-#include <usb/devdrv.h>
+#include <usb/devpoll.h>
 #include <usb/request.h>
 #include <usb/debug.h>
+#include <usb/classes/classes.h>
 #include <errno.h>
 #include <str_error.h>
@@ -45,8 +46,14 @@
 /** Data needed for polling. */
 typedef struct {
+	int debug;
+	size_t max_failures;
+	useconds_t delay;
+	bool auto_clear_halt;
+	bool (*on_data)(usb_device_t *, uint8_t *, size_t, void *);
+	void (*on_polling_end)(usb_device_t *, bool, void *);
+	bool (*on_error)(usb_device_t *, int, void *);
+
 	usb_device_t *dev;
 	size_t pipe_index;
-	usb_polling_callback_t callback;
-	usb_polling_terminted_callback_t terminated_callback;
 	size_t request_size;
 	uint8_t *buffer;
@@ -54,4 +61,5 @@
 } polling_data_t;
 
+
 /** Polling fibril.
  *
@@ -67,12 +75,20 @@
 	    = polling_data->dev->pipes[polling_data->pipe_index].pipe;
 	
-	usb_log_debug("Pipe interface number: %d, protocol: %d, subclass: %d, max packet size: %d\n", 
-	    polling_data->dev->pipes[polling_data->pipe_index].interface_no,
-	    polling_data->dev->pipes[polling_data->pipe_index].description->interface_protocol,
-	    polling_data->dev->pipes[polling_data->pipe_index].description->interface_subclass,
-	    pipe->max_packet_size);
+	if (polling_data->debug > 0) {
+		usb_endpoint_mapping_t *mapping
+		    = &polling_data->dev->pipes[polling_data->pipe_index];
+		usb_log_debug("Poll0x%x: started polling of `%s' - " \
+		    "interface %d (%s,%d,%d), %zuB/%zu.\n",
+		    polling_data,
+		    polling_data->dev->ddf_dev->name,
+		    (int) mapping->interface->interface_number,
+		    usb_str_class(mapping->interface->interface_class),
+		    (int) mapping->interface->interface_subclass,
+		    (int) mapping->interface->interface_protocol,
+		    polling_data->request_size, pipe->max_packet_size);
+	}
 
 	size_t failed_attempts = 0;
-	while (failed_attempts < MAX_FAILED_ATTEMPTS) {
+	while (failed_attempts <= polling_data->max_failures) {
 		int rc;
 
@@ -81,13 +97,40 @@
 		    polling_data->request_size, &actual_size);
 
-		
-//		if (rc == ESTALL) {
-//			usb_log_debug("Seding clear feature...\n");
-//			usb_request_clear_feature(pipe, USB_REQUEST_TYPE_STANDARD,
-//			  USB_REQUEST_RECIPIENT_ENDPOINT, 0, pipe->endpoint_no);
-//			continue;
-//		}
+		if (polling_data->debug > 1) {
+			if (rc == EOK) {
+				usb_log_debug(
+				    "Poll0x%x: received: '%s' (%zuB).\n",
+				    polling_data,
+				    usb_debug_str_buffer(polling_data->buffer,
+				        actual_size, 16),
+				    actual_size);
+			} else {
+				usb_log_debug(
+				    "Poll0x%x: polling failed: %s.\n",
+				    polling_data, str_error(rc));
+			}
+		}
+
+		/* If the pipe stalled, we can try to reset the stall. */
+		if ((rc == ESTALL) && (polling_data->auto_clear_halt)) {
+			/*
+			 * We ignore error here as this is usually a futile
+			 * attempt anyway.
+			 */
+			usb_request_clear_endpoint_halt(
+			    &polling_data->dev->ctrl_pipe,
+			    pipe->endpoint_no);
+		}
 
 		if (rc != EOK) {
+			if (polling_data->on_error != NULL) {
+				bool cont = polling_data->on_error(
+				    polling_data->dev, rc,
+				    polling_data->custom_arg);
+				if (!cont) {
+					failed_attempts
+					    = polling_data->max_failures;
+				}
+			}
 			failed_attempts++;
 			continue;
@@ -95,5 +138,5 @@
 
 		/* We have the data, execute the callback now. */
-		bool carry_on = polling_data->callback(polling_data->dev,
+		bool carry_on = polling_data->on_data(polling_data->dev,
 		    polling_data->buffer, actual_size,
 		    polling_data->custom_arg);
@@ -106,15 +149,26 @@
 		/* Reset as something might be only a temporary problem. */
 		failed_attempts = 0;
-	}
-
-	if (failed_attempts > 0) {
-		usb_log_error(
-		    "Polling of device `%s' terminated: recurring failures.\n",
-		    polling_data->dev->ddf_dev->name);
-	}
-
-	if (polling_data->terminated_callback != NULL) {
-		polling_data->terminated_callback(polling_data->dev,
+
+		/* Take a rest before next request. */
+		async_usleep(polling_data->delay);
+	}
+
+	if (polling_data->on_polling_end != NULL) {
+		polling_data->on_polling_end(polling_data->dev,
 		    failed_attempts > 0, polling_data->custom_arg);
+	}
+
+	if (polling_data->debug > 0) {
+		if (failed_attempts > 0) {
+			usb_log_error(
+			    "Polling of device `%s' terminated: %s.\n",
+			    polling_data->dev->ddf_dev->name,
+			    "recurring failures");
+		} else {
+			usb_log_debug(
+			    "Polling of device `%s' terminated by user.\n",
+			    polling_data->dev->ddf_dev->name
+			);
+		}
 	}
 
@@ -159,4 +213,61 @@
 	}
 
+	usb_device_auto_polling_t *auto_polling
+	    = malloc(sizeof(usb_device_auto_polling_t));
+	if (auto_polling == NULL) {
+		return ENOMEM;
+	}
+
+	auto_polling->debug = 1;
+	auto_polling->auto_clear_halt = true;
+	auto_polling->delay = 0;
+	auto_polling->max_failures = MAX_FAILED_ATTEMPTS;
+	auto_polling->on_data = callback;
+	auto_polling->on_polling_end = terminated_callback;
+	auto_polling->on_error = NULL;
+
+	int rc = usb_device_auto_polling(dev, pipe_index, auto_polling,
+	   request_size, arg);
+
+	free(auto_polling);
+
+	return rc;
+}
+
+/** Start automatic device polling over interrupt in pipe.
+ *
+ * The polling settings is copied thus it is okay to destroy the structure
+ * after this function returns.
+ *
+ * @warning There is no guarantee when the request to the device
+ * will be sent for the first time (it is possible that this
+ * first request would be executed prior to return from this function).
+ *
+ * @param dev Device to be periodically polled.
+ * @param pipe_index Index of the endpoint pipe used for polling.
+ * @param polling Polling settings.
+ * @param request_size How many bytes to ask for in each request.
+ * @param arg Custom argument (passed as is to the callbacks).
+ * @return Error code.
+ * @retval EOK New fibril polling the device was already started.
+ */
+int usb_device_auto_polling(usb_device_t *dev, size_t pipe_index,
+    usb_device_auto_polling_t *polling,
+    size_t request_size, void *arg)
+{
+	if (dev == NULL) {
+		return EBADMEM;
+	}
+	if (pipe_index >= dev->pipes_count) {
+		return EINVAL;
+	}
+	if ((dev->pipes[pipe_index].pipe->transfer_type != USB_TRANSFER_INTERRUPT)
+	    || (dev->pipes[pipe_index].pipe->direction != USB_DIRECTION_IN)) {
+		return EINVAL;
+	}
+	if ((polling == NULL) || (polling->on_data == NULL)) {
+		return EBADMEM;
+	}
+
 	polling_data_t *polling_data = malloc(sizeof(polling_data_t));
 	if (polling_data == NULL) {
@@ -164,16 +275,28 @@
 	}
 
-	/* Allocate now to prevent immediate failure in the polling fibril. */
-	polling_data->buffer = malloc(request_size);
+	/* Fill-in the data. */
+	polling_data->buffer = malloc(sizeof(request_size));
 	if (polling_data->buffer == NULL) {
 		free(polling_data);
 		return ENOMEM;
 	}
+	polling_data->request_size = request_size;
 	polling_data->dev = dev;
 	polling_data->pipe_index = pipe_index;
-	polling_data->callback = callback;
-	polling_data->terminated_callback = terminated_callback;
-	polling_data->request_size = request_size;
 	polling_data->custom_arg = arg;
+
+	polling_data->debug = polling->debug;
+	polling_data->max_failures = polling->max_failures;
+	if (polling->delay >= 0) {
+		polling_data->delay = (useconds_t) polling->delay;
+	} else {
+		polling_data->delay = (useconds_t) dev->pipes[pipe_index]
+		    .descriptor->poll_interval;
+	}
+	polling_data->auto_clear_halt = polling->auto_clear_halt;
+
+	polling_data->on_data = polling->on_data;
+	polling_data->on_polling_end = polling->on_polling_end;
+	polling_data->on_error = polling->on_error;
 
 	fid_t fibril = fibril_create(polling_fibril, polling_data);
@@ -181,10 +304,9 @@
 		free(polling_data->buffer);
 		free(polling_data);
-		/* FIXME: better error code. */
 		return ENOMEM;
 	}
 	fibril_add_ready(fibril);
 
-	/* The allocated buffer etc. will be freed by the fibril. */
+	/* Fibril launched. That fibril will free the allocated data. */
 
 	return EOK;
Index: uspace/lib/usb/src/hidparser.c
===================================================================
--- uspace/lib/usb/src/hidparser.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/lib/usb/src/hidparser.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -900,4 +900,6 @@
 	item->usage_page = usage_page;
 	
+	usb_log_debug("Appending usage %d, usage page %d\n", usage, usage_page);
+	
 	list_append (&usage_path->link, &item->link);
 	usage_path->depth++;
Index: uspace/lib/usb/src/host/batch.c
===================================================================
--- uspace/lib/usb/src/host/batch.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/lib/usb/src/host/batch.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -39,12 +39,12 @@
 #include <usb/host/batch.h>
 
+void usb_transfer_batch_call_in(usb_transfer_batch_t *instance);
+void usb_transfer_batch_call_out(usb_transfer_batch_t *instance);
+
 void usb_transfer_batch_init(
     usb_transfer_batch_t *instance,
-    usb_target_t target,
-    usb_transfer_type_t transfer_type,
-    usb_speed_t speed,
-    size_t max_packet_size,
+    endpoint_t *ep,
     char *buffer,
-    char *transport_buffer,
+    char *data_buffer,
     size_t buffer_size,
     char *setup_buffer,
@@ -54,30 +54,48 @@
     void *arg,
     ddf_fun_t *fun,
-		endpoint_t *ep,
-    void *private_data
+    void *private_data,
+    void (*private_data_dtor)(void *p_data)
     )
 {
 	assert(instance);
 	link_initialize(&instance->link);
-	instance->target = target;
-	instance->transfer_type = transfer_type;
-	instance->speed = speed;
-	instance->direction = ep->direction;
+	instance->ep = ep;
 	instance->callback_in = func_in;
 	instance->callback_out = func_out;
 	instance->arg = arg;
 	instance->buffer = buffer;
-	instance->transport_buffer = transport_buffer;
+	instance->data_buffer = data_buffer;
 	instance->buffer_size = buffer_size;
 	instance->setup_buffer = setup_buffer;
 	instance->setup_size = setup_size;
-	instance->max_packet_size = max_packet_size;
 	instance->fun = fun;
 	instance->private_data = private_data;
+	instance->private_data_dtor = private_data_dtor;
 	instance->transfered_size = 0;
 	instance->next_step = NULL;
 	instance->error = EOK;
-	instance->ep = ep;
 	endpoint_use(instance->ep);
+}
+/*----------------------------------------------------------------------------*/
+/** Helper function, calls callback and correctly destroys batch structure.
+ *
+ * @param[in] instance Batch structure to use.
+ */
+void usb_transfer_batch_call_in_and_dispose(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	usb_transfer_batch_call_in(instance);
+	usb_transfer_batch_dispose(instance);
+}
+/*----------------------------------------------------------------------------*/
+/** Helper function calls callback and correctly destroys batch structure.
+ *
+ * @param[in] instance Batch structure to use.
+ */
+void usb_transfer_batch_call_out_and_dispose(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	usb_transfer_batch_call_out(instance);
+	usb_transfer_batch_dispose(instance);
 }
 /*----------------------------------------------------------------------------*/
@@ -105,16 +123,14 @@
 	assert(instance);
 	assert(instance->callback_in);
+	assert(instance->ep);
 
 	/* We are data in, we need data */
-	memcpy(instance->buffer, instance->transport_buffer,
-	    instance->buffer_size);
+	memcpy(instance->buffer, instance->data_buffer, instance->buffer_size);
 
 	usb_log_debug("Batch %p done (T%d.%d, %s %s in, %zuB): %s (%d).\n",
-	    instance,
-	    instance->target.address, instance->target.endpoint,
-	    usb_str_speed(instance->speed),
-	    usb_str_transfer_type_short(instance->transfer_type),
-	    instance->transfered_size,
-	    str_error(instance->error), instance->error);
+	    instance, instance->ep->address, instance->ep->endpoint,
+	    usb_str_speed(instance->ep->speed),
+	    usb_str_transfer_type_short(instance->ep->transfer_type),
+	    instance->transfered_size, str_error(instance->error), instance->error);
 
 	instance->callback_in(instance->fun, instance->error,
@@ -132,8 +148,7 @@
 
 	usb_log_debug("Batch %p done (T%d.%d, %s %s out): %s (%d).\n",
-	    instance,
-	    instance->target.address, instance->target.endpoint,
-	    usb_str_speed(instance->speed),
-	    usb_str_transfer_type_short(instance->transfer_type),
+	    instance, instance->ep->address, instance->ep->endpoint,
+	    usb_str_speed(instance->ep->speed),
+	    usb_str_transfer_type_short(instance->ep->transfer_type),
 	    str_error(instance->error), instance->error);
 
@@ -141,4 +156,19 @@
 	    instance->error, instance->arg);
 }
+/*----------------------------------------------------------------------------*/
+/** Correctly dispose all used data structures.
+ *
+ * @param[in] instance Batch structure to use.
+ */
+void usb_transfer_batch_dispose(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	usb_log_debug("Batch(%p) disposing.\n", instance);
+	if (instance->private_data) {
+		assert(instance->private_data_dtor);
+		instance->private_data_dtor(instance->private_data);
+	}
+	free(instance);
+}
 /**
  * @}
Index: uspace/lib/usb/src/host/device_keeper.c
===================================================================
--- uspace/lib/usb/src/host/device_keeper.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/lib/usb/src/host/device_keeper.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -48,7 +48,4 @@
 {
 	assert(instance);
-	fibril_mutex_initialize(&instance->guard);
-	fibril_condvar_initialize(&instance->change);
-	instance->last_address = 0;
 	unsigned i = 0;
 	for (; i < USB_ADDRESS_COUNT; ++i) {
@@ -60,38 +57,7 @@
 	// (it is needed to allow smooth registration at default address)
 	instance->devices[0].occupied = true;
+	instance->last_address = 0;
+	fibril_mutex_initialize(&instance->guard);
 }
-/*----------------------------------------------------------------------------*/
-/** Attempt to obtain address 0, blocks.
- *
- * @param[in] instance Device keeper structure to use.
- * @param[in] speed Speed of the device requesting default address.
- */
-void usb_device_keeper_reserve_default_address(
-    usb_device_keeper_t *instance, usb_speed_t speed)
-{
-	assert(instance);
-	fibril_mutex_lock(&instance->guard);
-	while (instance->devices[USB_ADDRESS_DEFAULT].occupied) {
-		fibril_condvar_wait(&instance->change, &instance->guard);
-	}
-	instance->devices[USB_ADDRESS_DEFAULT].occupied = true;
-	instance->devices[USB_ADDRESS_DEFAULT].speed = speed;
-	fibril_mutex_unlock(&instance->guard);
-}
-/*----------------------------------------------------------------------------*/
-/** Attempt to obtain address 0, blocks.
- *
- * @param[in] instance Device keeper structure to use.
- * @param[in] speed Speed of the device requesting default address.
- */
-void usb_device_keeper_release_default_address(usb_device_keeper_t *instance)
-{
-	assert(instance);
-	fibril_mutex_lock(&instance->guard);
-	instance->devices[USB_ADDRESS_DEFAULT].occupied = false;
-	fibril_mutex_unlock(&instance->guard);
-	fibril_condvar_signal(&instance->change);
-}
-/*----------------------------------------------------------------------------*/
 /*----------------------------------------------------------------------------*/
 /** Get a free USB address
@@ -120,7 +86,9 @@
 	assert(new_address != USB_ADDRESS_DEFAULT);
 	assert(instance->devices[new_address].occupied == false);
+
 	instance->devices[new_address].occupied = true;
 	instance->devices[new_address].speed = speed;
 	instance->last_address = new_address;
+
 	fibril_mutex_unlock(&instance->guard);
 	return new_address;
@@ -138,7 +106,9 @@
 	assert(instance);
 	fibril_mutex_lock(&instance->guard);
+
 	assert(address > 0);
 	assert(address <= USB11_ADDRESS_MAX);
 	assert(instance->devices[address].occupied);
+
 	instance->devices[address].handle = handle;
 	fibril_mutex_unlock(&instance->guard);
@@ -159,4 +129,5 @@
 	fibril_mutex_lock(&instance->guard);
 	assert(instance->devices[address].occupied);
+
 	instance->devices[address].occupied = false;
 	fibril_mutex_unlock(&instance->guard);
@@ -177,4 +148,5 @@
 	while (address <= USB11_ADDRESS_MAX) {
 		if (instance->devices[address].handle == handle) {
+			assert(instance->devices[address].occupied);
 			fibril_mutex_unlock(&instance->guard);
 			return address;
@@ -198,4 +170,5 @@
 	assert(address >= 0);
 	assert(address <= USB11_ADDRESS_MAX);
+
 	return instance->devices[address].speed;
 }
Index: uspace/lib/usb/src/host/endpoint.c
===================================================================
--- uspace/lib/usb/src/host/endpoint.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/lib/usb/src/host/endpoint.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -53,4 +53,5 @@
 	fibril_mutex_initialize(&instance->guard);
 	fibril_condvar_initialize(&instance->avail);
+	endpoint_clear_hc_data(instance);
 	return EOK;
 }
@@ -61,4 +62,21 @@
 	assert(!instance->active);
 	free(instance);
+}
+/*----------------------------------------------------------------------------*/
+void endpoint_set_hc_data(endpoint_t *instance,
+    void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int))
+{
+	assert(instance);
+	instance->hc_data.data = data;
+	instance->hc_data.toggle_get = toggle_get;
+	instance->hc_data.toggle_set = toggle_set;
+}
+/*----------------------------------------------------------------------------*/
+void endpoint_clear_hc_data(endpoint_t *instance)
+{
+	assert(instance);
+	instance->hc_data.data = NULL;
+	instance->hc_data.toggle_get = NULL;
+	instance->hc_data.toggle_set = NULL;
 }
 /*----------------------------------------------------------------------------*/
@@ -85,4 +103,7 @@
 {
 	assert(instance);
+	if (instance->hc_data.toggle_get)
+		instance->toggle =
+		    instance->hc_data.toggle_get(instance->hc_data.data);
 	return (int)instance->toggle;
 }
@@ -92,4 +113,6 @@
 	assert(instance);
 	assert(toggle == 0 || toggle == 1);
+	if (instance->hc_data.toggle_set)
+		instance->hc_data.toggle_set(instance->hc_data.data, toggle);
 	instance->toggle = toggle;
 }
@@ -100,5 +123,5 @@
 	if (instance->address == target.address &&
 	    (instance->endpoint == target.endpoint || target.endpoint == 0))
-		instance->toggle = 0;
+		endpoint_toggle_set(instance, 0);
 }
 /**
Index: uspace/lib/usb/src/host/usb_endpoint_manager.c
===================================================================
--- uspace/lib/usb/src/host/usb_endpoint_manager.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/lib/usb/src/host/usb_endpoint_manager.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -211,4 +211,7 @@
 
 	node_t *node = hash_table_get_instance(item, node_t, link);
+	if (node->ep->active)
+		return EBUSY;
+
 	instance->free_bw += node->bw;
 	hash_table_remove(&instance->ep_table, key, MAX_KEYS);
Index: uspace/lib/usb/src/pipesinit.c
===================================================================
--- uspace/lib/usb/src/pipesinit.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/lib/usb/src/pipesinit.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -365,4 +365,5 @@
 	pipe->direction = direction;
 	pipe->refcount = 0;
+	pipe->auto_reset_halt = false;
 
 	return EOK;
@@ -385,4 +386,6 @@
 	    0, USB_TRANSFER_CONTROL, CTRL_PIPE_MIN_PACKET_SIZE,
 	    USB_DIRECTION_BOTH);
+
+	pipe->auto_reset_halt = true;
 
 	return rc;
Index: uspace/lib/usb/src/pipesio.c
===================================================================
--- uspace/lib/usb/src/pipesio.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/lib/usb/src/pipesio.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -49,4 +49,5 @@
 #include <assert.h>
 #include <usbhc_iface.h>
+#include <usb/request.h>
 #include "pipepriv.h"
 
@@ -307,4 +308,23 @@
 }
 
+/** Try to clear endpoint halt of default control pipe.
+ *
+ * @param pipe Pipe for control endpoint zero.
+ */
+static void clear_self_endpoint_halt(usb_pipe_t *pipe)
+{
+	assert(pipe != NULL);
+
+	if (!pipe->auto_reset_halt || (pipe->endpoint_no != 0)) {
+		return;
+	}
+
+
+	/* Prevent indefinite recursion. */
+	pipe->auto_reset_halt = false;
+	usb_request_clear_endpoint_halt(pipe, 0);
+	pipe->auto_reset_halt = true;
+}
+
 
 /** Request a control read transfer, no checking of input parameters.
@@ -436,4 +456,8 @@
 	    setup_buffer, setup_buffer_size,
 	    data_buffer, data_buffer_size, &act_size);
+
+	if (rc == ESTALL) {
+		clear_self_endpoint_halt(pipe);
+	}
 
 	pipe_drop_ref(pipe);
@@ -563,4 +587,8 @@
 	    setup_buffer, setup_buffer_size, data_buffer, data_buffer_size);
 
+	if (rc == ESTALL) {
+		clear_self_endpoint_halt(pipe);
+	}
+
 	pipe_drop_ref(pipe);
 
Index: uspace/srv/bd/ata_bd/ata_bd.c
===================================================================
--- uspace/srv/bd/ata_bd/ata_bd.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/srv/bd/ata_bd/ata_bd.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -372,4 +372,5 @@
 	uint16_t w;
 	uint8_t c;
+	uint16_t bc;
 	size_t pos, len;
 	int rc;
@@ -387,11 +388,24 @@
 	} else if (rc == EIO) {
 		/*
-		 * There is something, but not a register device.
-		 * It could be a packet device.
+		 * There is something, but not a register device. Check to see
+		 * whether the IDENTIFY command left the packet signature in
+		 * the registers in case this is a packet device.
+		 *
+		 * According to the ATA specification, the LBA low and
+		 * interrupt reason registers should be set to 0x01. However,
+		 * there are many devices that do not follow this and only set
+		 * the byte count registers. So, only check these.
 		 */
-		rc = identify_pkt_dev(disk_id, &idata);
-		if (rc == EOK) {
-			/* We have a packet device. */
-			d->dev_type = ata_pkt_dev;
+		bc = ((uint16_t)pio_read_8(&cmd->cylinder_high) << 8) |
+		    pio_read_8(&cmd->cylinder_low);
+
+		if (bc == PDEV_SIGNATURE_BC) {
+			rc = identify_pkt_dev(disk_id, &idata);
+			if (rc == EOK) {
+				/* We have a packet device. */
+				d->dev_type = ata_pkt_dev;
+			} else {
+				return EIO;
+			}
 		} else {
 			/* Nope. Something's there, but not recognized. */
@@ -403,5 +417,4 @@
 	}
 
-	printf("device caps: 0x%04x\n", idata.caps);
 	if (d->dev_type == ata_pkt_dev) {
 		/* Packet device */
@@ -566,8 +579,9 @@
 
 	/*
-	 * This is where we would most likely expect a non-existing device to
-	 * show up by not setting SR_DRDY.
+	 * Do not wait for DRDY to be set in case this is a packet device.
+	 * We determine whether the device is present by waiting for DRQ to be
+	 * set after issuing the command.
 	 */
-	if (wait_status(SR_DRDY, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)
+	if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)
 		return ETIMEOUT;
 
@@ -577,15 +591,20 @@
 		return ETIMEOUT;
 
+	/*
+	 * If ERR is set, this may be a packet device, so return EIO to cause
+	 * the caller to check for one.
+	 */
+	if ((status & SR_ERR) != 0) {
+		return EIO;
+	}
+
+	if (wait_status(SR_DRQ, ~SR_BSY, &status, TIMEOUT_PROBE) != EOK)
+		return ETIMEOUT;
+
 	/* Read data from the disk buffer. */
 
-	if ((status & SR_DRQ) != 0) {
-		for (i = 0; i < identify_data_size / 2; i++) {
-			data = pio_read_16(&cmd->data_port);
-			((uint16_t *) buf)[i] = data;
-		}
-	}
-
-	if ((status & SR_ERR) != 0) {
-		return EIO;
+	for (i = 0; i < identify_data_size / 2; i++) {
+		data = pio_read_16(&cmd->data_port);
+		((uint16_t *) buf)[i] = data;
 	}
 
Index: uspace/srv/bd/ata_bd/ata_hw.h
===================================================================
--- uspace/srv/bd/ata_bd/ata_hw.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/srv/bd/ata_bd/ata_hw.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -293,4 +293,12 @@
 };
 
+enum ata_pdev_signature {
+	/**
+	 * Signature put by a packet device in byte count register
+	 * in response to Identify command.
+	 */
+	PDEV_SIGNATURE_BC	= 0xEB14
+};
+
 #endif
 
Index: uspace/srv/devman/devman.c
===================================================================
--- uspace/srv/devman/devman.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/srv/devman/devman.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -555,17 +555,4 @@
 }
 
-/** Remember the driver's phone.
- *
- * @param driver	The driver.
- * @param phone		The phone to the driver.
- */
-void set_driver_phone(driver_t *driver, sysarg_t phone)
-{
-	fibril_mutex_lock(&driver->driver_mutex);
-	assert(driver->state == DRIVER_STARTING);
-	driver->phone = phone;
-	fibril_mutex_unlock(&driver->driver_mutex);
-}
-
 /** Notify driver about the devices to which it was assigned.
  *
@@ -685,4 +672,5 @@
 	list_initialize(&drv->devices);
 	fibril_mutex_initialize(&drv->driver_mutex);
+	drv->phone = -1;
 }
 
Index: uspace/srv/devman/devman.h
===================================================================
--- uspace/srv/devman/devman.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/srv/devman/devman.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -88,5 +88,5 @@
 	
 	/** Phone asociated with this driver. */
-	sysarg_t phone;
+	int phone;
 	/** Name of the device driver. */
 	char *name;
@@ -316,5 +316,4 @@
 
 extern driver_t *find_driver(driver_list_t *, const char *);
-extern void set_driver_phone(driver_t *, sysarg_t);
 extern void initialize_running_driver(driver_t *, dev_tree_t *);
 
Index: uspace/srv/devman/main.c
===================================================================
--- uspace/srv/devman/main.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/srv/devman/main.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -95,5 +95,4 @@
 	/* Find driver structure. */
 	driver = find_driver(&drivers_list, drv_name);
-	
 	if (driver == NULL) {
 		log_msg(LVL_ERROR, "No driver named `%s' was found.", drv_name);
@@ -107,4 +106,30 @@
 	drv_name = NULL;
 	
+	fibril_mutex_lock(&driver->driver_mutex);
+	
+	if (driver->phone >= 0) {
+		/* We already have a connection to the driver. */
+		log_msg(LVL_ERROR, "Driver '%s' already started.\n",
+		    driver->name);
+		fibril_mutex_unlock(&driver->driver_mutex);
+		async_answer_0(iid, EEXISTS);
+		return NULL;
+	}
+	
+	switch (driver->state) {
+	case DRIVER_NOT_STARTED:
+		/* Somebody started the driver manually. */
+		log_msg(LVL_NOTE, "Driver '%s' started manually.\n",
+		    driver->name);
+		driver->state = DRIVER_STARTING;
+		break;
+	case DRIVER_STARTING:
+		/* The expected case */
+		break;
+	case DRIVER_RUNNING:
+		/* Should not happen since we do not have a connected phone */
+		assert(false);
+	}
+	
 	/* Create connection to the driver. */
 	log_msg(LVL_DEBUG, "Creating connection to the `%s' driver.",
@@ -113,4 +138,5 @@
 	ipc_callid_t callid = async_get_call(&call);
 	if (IPC_GET_IMETHOD(call) != IPC_M_CONNECT_TO_ME) {
+		fibril_mutex_unlock(&driver->driver_mutex);
 		async_answer_0(callid, ENOTSUP);
 		async_answer_0(iid, ENOTSUP);
@@ -119,5 +145,7 @@
 	
 	/* Remember driver's phone. */
-	set_driver_phone(driver, IPC_GET_ARG5(call));
+	driver->phone = IPC_GET_ARG5(call);
+	
+	fibril_mutex_unlock(&driver->driver_mutex);
 	
 	log_msg(LVL_NOTE, 
@@ -579,5 +607,5 @@
 		method = DRIVER_CLIENT;
 	
-	if (driver->phone <= 0) {
+	if (driver->phone < 0) {
 		log_msg(LVL_ERROR, 
 		    "Could not forward to driver `%s' (phone is %d).",
@@ -619,5 +647,5 @@
 	dev = fun->dev;
 	
-	if (dev->state != DEVICE_USABLE || dev->drv->phone <= 0) {
+	if (dev->state != DEVICE_USABLE || dev->drv->phone < 0) {
 		async_answer_0(iid, EINVAL);
 		return;
Index: uspace/srv/fs/fat/fat_ops.c
===================================================================
--- uspace/srv/fs/fat/fat_ops.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/srv/fs/fat/fat_ops.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -722,6 +722,6 @@
 		    (str_cmp((char *) d->name, FAT_NAME_DOT)) == 0) {
 			memset(d, 0, sizeof(fat_dentry_t));
-			str_cpy((char *) d->name, 8, FAT_NAME_DOT);
-			str_cpy((char *) d->ext, 3, FAT_EXT_PAD);
+			memcpy(d->name, FAT_NAME_DOT, FAT_NAME_LEN);
+			memcpy(d->ext, FAT_EXT_PAD, FAT_EXT_LEN);
 			d->attr = FAT_ATTR_SUBDIR;
 			d->firstc = host2uint16_t_le(childp->firstc);
@@ -732,6 +732,6 @@
 		    (str_cmp((char *) d->name, FAT_NAME_DOT_DOT) == 0)) {
 			memset(d, 0, sizeof(fat_dentry_t));
-			str_cpy((char *) d->name, 8, FAT_NAME_DOT_DOT);
-			str_cpy((char *) d->ext, 3, FAT_EXT_PAD);
+			memcpy(d->name, FAT_NAME_DOT_DOT, FAT_NAME_LEN);
+			memcpy(d->ext, FAT_EXT_PAD, FAT_EXT_LEN);
 			d->attr = FAT_ATTR_SUBDIR;
 			d->firstc = (parentp->firstc == FAT_CLST_ROOT) ?
Index: uspace/srv/net/il/ip/ip.c
===================================================================
--- uspace/srv/net/il/ip/ip.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/srv/net/il/ip/ip.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -176,5 +176,5 @@
 	socklen_t addrlen;
 
-	// detach the first packet and release the others
+	/* Detach the first packet and release the others */
 	next = pq_detach(packet);
 	if (next)
@@ -185,5 +185,5 @@
 			return ENOMEM;
 
-		// get header
+		/* Get header */
 		header = (ip_header_t *) packet_get_data(packet);
 		if (!header)
@@ -192,13 +192,13 @@
 	}
 
-	// only for the first fragment
+	/* Only for the first fragment */
 	if (IP_FRAGMENT_OFFSET(header))
 		return EINVAL;
 
-	// not for the ICMP protocol
+	/* Not for the ICMP protocol */
 	if (header->protocol == IPPROTO_ICMP)
 		return EPERM;
 
-	// set the destination address
+	/* Set the destination address */
 	switch (header->version) {
 	case IPVERSION:
@@ -351,5 +351,5 @@
 	configuration = &names[0];
 
-	// get configuration
+	/* Get configuration */
 	rc = net_get_device_conf_req(ip_globals.net_phone, ip_netif->device_id,
 	    &configuration, count, &data);
@@ -419,5 +419,5 @@
 	}
 
-	// binds the netif service which also initializes the device
+	/* Bind netif service which also initializes the device */
 	ip_netif->phone = nil_bind_service(ip_netif->service,
 	    (sysarg_t) ip_netif->device_id, SERVICE_IP,
@@ -429,5 +429,5 @@
 	}
 
-	// has to be after the device netif module initialization
+	/* Has to be after the device netif module initialization */
 	if (ip_netif->arp) {
 		if (route) {
@@ -445,5 +445,5 @@
 	}
 
-	// get packet dimensions
+	/* Get packet dimensions */
 	rc = nil_packet_size_req(ip_netif->phone, ip_netif->device_id,
 	    &ip_netif->packet_dimension);
@@ -463,5 +463,5 @@
 	
 	if (gateway.s_addr) {
-		// the default gateway
+		/* The default gateway */
 		ip_globals.gateway.address.s_addr = 0;
 		ip_globals.gateway.netmask.s_addr = 0;
@@ -512,5 +512,5 @@
 		ip_netif->arp->usage++;
 
-	// print the settings
+	/* Print the settings */
 	printf("%s: Device registered (id: %d, phone: %d, ipv: %d, conf: %s)\n",
 	    NAME, ip_netif->device_id, ip_netif->phone, ip_netif->ipv,
@@ -587,5 +587,5 @@
 	ip_netif_t *netif;
 
-	// start with the last netif - the newest one
+	/* Start with the last netif - the newest one */
 	index = ip_netifs_count(&ip_globals.netifs) - 1;
 	while (index >= 0) {
@@ -629,18 +629,18 @@
 	size_t length;
 
-	// copy first itself
+	/* Copy first itself */
 	memcpy(last, first, sizeof(ip_header_t));
 	length = sizeof(ip_header_t);
 	next = sizeof(ip_header_t);
 
-	// process all ip options
+	/* Process all IP options */
 	while (next < first->header_length) {
 		option = (ip_option_t *) (((uint8_t *) first) + next);
-		// skip end or noop
+		/* Skip end or noop */
 		if ((option->type == IPOPT_END) ||
 		    (option->type == IPOPT_NOOP)) {
 			next++;
 		} else {
-			// copy if told so or skip
+			/* Copy if told so or skip */
 			if (IPOPT_COPIED(option->type)) {
 				memcpy(((uint8_t *) last) + length,
@@ -648,10 +648,10 @@
 				length += option->length;
 			}
-			// next option
+			/* Next option */
 			next += option->length;
 		}
 	}
 
-	// align 4 byte boundary
+	/* Align 4 byte boundary */
 	if (length % 4) {
 		bzero(((uint8_t *) last) + length, 4 - (length % 4));
@@ -789,5 +789,5 @@
 
 	header->total_length = htons(length);
-	// unnecessary for all protocols
+	/* Unnecessary for all protocols */
 	header->header_checksum = IP_HEADER_CHECKSUM(header);
 
@@ -916,14 +916,14 @@
 		return ENOMEM;
 
-	// get header
+	/* Get header */
 	header = (ip_header_t *) packet_get_data(packet);
 	if (!header)
 		return EINVAL;
 
-	// fragmentation forbidden?
+	/* Fragmentation forbidden? */
 	if(header->flags & IPFLAG_DONT_FRAGMENT)
 		return EPERM;
 
-	// create the last fragment
+	/* Create the last fragment */
 	new_packet = packet_get_4_remote(ip_globals.net_phone, prefix, length,
 	    suffix, ((addrlen > addr_len) ? addrlen : addr_len));
@@ -931,5 +931,5 @@
 		return ENOMEM;
 
-	// allocate as much as originally
+	/* Allocate as much as originally */
 	last_header = (ip_header_t *) packet_suffix(new_packet,
 	    IP_HEADER_LENGTH(header));
@@ -939,5 +939,5 @@
 	ip_create_last_header(last_header, header);
 
-	// trim the unused space
+	/* Trim the unused space */
 	rc = packet_trim(new_packet, 0,
 	    IP_HEADER_LENGTH(header) - IP_HEADER_LENGTH(last_header));
@@ -945,5 +945,5 @@
 		return ip_release_and_return(packet, rc);
 
-	// biggest multiple of 8 lower than content
+	/* Greatest multiple of 8 lower than content */
 	// TODO even fragmentation?
 	length = length & ~0x7;
@@ -957,8 +957,8 @@
 		return ip_release_and_return(packet, rc);
 
-	// mark the first as fragmented
+	/* Mark the first as fragmented */
 	header->flags |= IPFLAG_MORE_FRAGMENTS;
 
-	// create middle framgents
+	/* Create middle fragments */
 	while (IP_TOTAL_LENGTH(header) > length) {
 		new_packet = packet_get_4_remote(ip_globals.net_phone, prefix,
@@ -981,5 +981,5 @@
 	}
 
-	// finish the first fragment
+	/* Finish the first fragment */
 	header->header_checksum = IP_HEADER_CHECKSUM(header);
 
@@ -1012,5 +1012,5 @@
 
 	next = packet;
-	// check all packets
+	/* Check all packets */
 	while (next) {
 		length = packet_get_data_length(next);
@@ -1021,5 +1021,5 @@
 		}
 
-		// too long
+		/* Too long */
 		result = ip_fragment_packet(next, content, prefix,
 		    suffix, addr_len);
@@ -1027,13 +1027,13 @@
 			new_packet = pq_detach(next);
 			if (next == packet) {
-				// the new first packet of the queue
+				/* The new first packet of the queue */
 				packet = new_packet;
 			}
-			// fragmentation needed?
+			/* Fragmentation needed? */
 			if (result == EPERM) {
 				phone = ip_prepare_icmp_and_get_phone(
 				    error, next, NULL);
 				if (phone >= 0) {
-					// fragmentation necessary ICMP
+					/* Fragmentation necessary ICMP */
 					icmp_destination_unreachable_msg(phone,
 					    ICMP_FRAG_NEEDED, content, next);
@@ -1080,5 +1080,5 @@
 	int rc;
 
-	// get destination hardware address
+	/* Get destination hardware address */
 	if (netif->arp && (route->address.s_addr != dest.s_addr)) {
 		destination.value = route->gateway.s_addr ?
@@ -1102,5 +1102,5 @@
 			    NULL);
 			if (phone >= 0) {
-				// unreachable ICMP if no routing
+				/* Unreachable ICMP if no routing */
 				icmp_destination_unreachable_msg(phone,
 				    ICMP_HOST_UNREACH, 0, packet);
@@ -1148,6 +1148,8 @@
 	int rc;
 
-	// addresses in the host byte order
-	// should be the next hop address or the target destination address
+	/*
+	 * Addresses in the host byte order
+	 * Should be the next hop address or the target destination address
+	 */
 	addrlen = packet_get_addr(packet, NULL, (uint8_t **) &addr);
 	if (addrlen < 0)
@@ -1174,5 +1176,5 @@
 	fibril_rwlock_read_lock(&ip_globals.netifs_lock);
 
-	// device specified?
+	/* Device specified? */
 	if (device_id > 0) {
 		netif = ip_netifs_find(&ip_globals.netifs, device_id);
@@ -1190,5 +1192,5 @@
 		phone = ip_prepare_icmp_and_get_phone(error, packet, NULL);
 		if (phone >= 0) {
-			// unreachable ICMP if no routing
+			/* Unreachable ICMP if no routing */
 			icmp_destination_unreachable_msg(phone,
 			    ICMP_NET_UNREACH, 0, packet);
@@ -1198,6 +1200,8 @@
 
 	if (error) {
-		// do not send for broadcast, anycast packets or network
-		// broadcast
+		/*
+		 * Do not send for broadcast, anycast packets or network
+		 * broadcast.
+		 */
 		if (!dest->s_addr || !(~dest->s_addr) ||
 		    !(~((dest->s_addr & ~route->netmask.s_addr) |
@@ -1208,8 +1212,8 @@
 	}
 	
-	// if the local host is the destination
+	/* If the local host is the destination */
 	if ((route->address.s_addr == dest->s_addr) &&
 	    (dest->s_addr != IPV4_LOCALHOST_ADDRESS)) {
-		// find the loopback device to deliver
+		/* Find the loopback device to deliver */
 		dest->s_addr = IPV4_LOCALHOST_ADDRESS;
 		route = ip_find_route(*dest);
@@ -1220,5 +1224,5 @@
 			    NULL);
 			if (phone >= 0) {
-				// unreachable ICMP if no routing
+				/* Unreachable ICMP if no routing */
 				icmp_destination_unreachable_msg(phone,
 				    ICMP_HOST_UNREACH, 0, packet);
@@ -1252,5 +1256,5 @@
 
 	fibril_rwlock_write_lock(&ip_globals.netifs_lock);
-	// find the device
+	/* Find the device */
 	netif = ip_netifs_find(&ip_globals.netifs, device_id);
 	if (!netif) {
@@ -1344,5 +1348,5 @@
 		return ip_release_and_return(packet, rc);
 
-	// trim padding if present
+	/* Trim padding if present */
 	if (!error &&
 	    (IP_TOTAL_LENGTH(header) < packet_get_data_length(packet))) {
@@ -1360,5 +1364,5 @@
 		phone = ip_prepare_icmp_and_get_phone(error, packet, header);
 		if (phone >= 0) {
-			// unreachable ICMP
+			/* Unreachable ICMP */
 			icmp_destination_unreachable_msg(phone,
 			    ICMP_PROT_UNREACH, 0, packet);
@@ -1417,10 +1421,10 @@
 		return ip_release_and_return(packet, ENOMEM);
 
-	// checksum
+	/* Checksum */
 	if ((header->header_checksum) &&
 	    (IP_HEADER_CHECKSUM(header) != IP_CHECKSUM_ZERO)) {
 		phone = ip_prepare_icmp_and_get_phone(0, packet, header);
 		if (phone >= 0) {
-			// checksum error ICMP
+			/* Checksum error ICMP */
 			icmp_parameter_problem_msg(phone, ICMP_PARAM_POINTER,
 			    ((size_t) ((void *) &header->header_checksum)) -
@@ -1433,5 +1437,5 @@
 		phone = ip_prepare_icmp_and_get_phone(0, packet, header);
 		if (phone >= 0) {
-			// ttl exceeded ICMP
+			/* TTL exceeded ICMP */
 			icmp_time_exceeded_msg(phone, ICMP_EXC_TTL, packet);
 		}
@@ -1439,8 +1443,8 @@
 	}
 	
-	// process ipopt and get destination
+	/* Process ipopt and get destination */
 	dest = ip_get_destination(header);
 
-	// set the addrination address
+	/* Set the destination address */
 	switch (header->version) {
 	case IPVERSION:
@@ -1464,5 +1468,5 @@
 		phone = ip_prepare_icmp_and_get_phone(0, packet, header);
 		if (phone >= 0) {
-			// unreachable ICMP
+			/* Unreachable ICMP */
 			icmp_destination_unreachable_msg(phone,
 			    ICMP_HOST_UNREACH, 0, packet);
@@ -1472,5 +1476,5 @@
 
 	if (route->address.s_addr == dest.s_addr) {
-		// local delivery
+		/* Local delivery */
 		return ip_deliver_local(device_id, packet, header, 0);
 	}
@@ -1484,5 +1488,5 @@
 	phone = ip_prepare_icmp_and_get_phone(0, packet, header);
 	if (phone >= 0) {
-		// unreachable ICMP if no routing
+		/* Unreachable ICMP if no routing */
 		icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0,
 		    packet);
@@ -1770,8 +1774,8 @@
 		header = (ip_header_t *)(data + offset);
 
-		// destination host unreachable?
+		/* Destination host unreachable? */
 		if ((type != ICMP_DEST_UNREACH) ||
 		    (code != ICMP_HOST_UNREACH)) {
-		    	// no, something else
+			/* No, something else */
 			break;
 		}
@@ -1787,8 +1791,8 @@
 		route = ip_routes_get_index(&netif->routes, 0);
 
-		// from the same network?
+		/* From the same network? */
 		if (route && ((route->address.s_addr & route->netmask.s_addr) ==
 		    (header->destination_address & route->netmask.s_addr))) {
-			// clear the ARP mapping if any
+			/* Clear the ARP mapping if any */
 			address.value = (uint8_t *) &header->destination_address;
 			address.length = sizeof(header->destination_address);
@@ -1844,8 +1848,8 @@
 	fibril_rwlock_read_lock(&ip_globals.lock);
 	route = ip_find_route(*dest);
-	// if the local host is the destination
+	/* If the local host is the destination */
 	if (route && (route->address.s_addr == dest->s_addr) &&
 	    (dest->s_addr != IPV4_LOCALHOST_ADDRESS)) {
-		// find the loopback device to deliver
+		/* Find the loopback device to deliver */
 		dest->s_addr = IPV4_LOCALHOST_ADDRESS;
 		route = ip_find_route(*dest);
Index: uspace/srv/net/nil/eth/eth.c
===================================================================
--- uspace/srv/net/nil/eth/eth.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/srv/net/nil/eth/eth.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -531,5 +531,5 @@
 			    proto->service);
 		} else {
-			// drop invalid/unknown
+			/* Drop invalid/unknown */
 			pq_release_remote(eth_globals.net_phone,
 			    packet_get_id(packet));
Index: uspace/srv/net/tl/tcp/tcp.c
===================================================================
--- uspace/srv/net/tl/tcp/tcp.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/srv/net/tl/tcp/tcp.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -299,7 +299,8 @@
 		return tcp_release_and_return(packet, NO_DATA);
 
-//      printf("header len %d, port %d \n", TCP_HEADER_LENGTH(header),
-//	    ntohs(header->destination_port));
-
+#if 0
+	printf("header len %d, port %d \n", TCP_HEADER_LENGTH(header),
+	    ntohs(header->destination_port));
+#endif
 	result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest);
 	if (result <= 0)
@@ -1062,5 +1063,5 @@
 	tcp_process_acknowledgement(socket, socket_data, header);
 
-	socket_data->next_incoming = ntohl(header->sequence_number);	// + 1;
+	socket_data->next_incoming = ntohl(header->sequence_number); /* + 1; */
 	pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
 	socket_data->state = TCP_SOCKET_ESTABLISHED;
Index: uspace/srv/net/tl/tcp/tcp.h
===================================================================
--- uspace/srv/net/tl/tcp/tcp.h	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/srv/net/tl/tcp/tcp.h	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -190,7 +190,4 @@
 	int backlog;
 	
-//	/** Segment size. */
-//	size_t segment_size;
-
 	/**
 	 * Parent listening socket identifier.
Index: uspace/srv/net/tl/udp/udp.c
===================================================================
--- uspace/srv/net/tl/udp/udp.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/srv/net/tl/udp/udp.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -499,5 +499,9 @@
 	device_id_t device_id;
 	packet_dimension_t *packet_dimension;
+	size_t size;
 	int rc;
+
+	/* In case of error, do not update the data fragment size. */
+	*data_fragment_size = 0;
 	
 	rc = tl_get_address_port(addr, addrlen, &dest_port);
@@ -539,4 +543,14 @@
 		packet_dimension = &udp_globals.packet_dimension;
 //	}
+
+	/*
+	 * Update the data fragment size based on what the lower layers can
+	 * handle without fragmentation, but not more than the maximum allowed
+	 * for UDP.
+	 */
+	size = MAX_UDP_FRAGMENT_SIZE;
+	if (packet_dimension->content < size)
+	    size = packet_dimension->content;
+	*data_fragment_size = size;
 
 	/* Read the first packet fragment */
@@ -740,5 +754,5 @@
 	int socket_id;
 	size_t addrlen;
-	size_t size = 0;
+	size_t size;
 	ipc_call_t answer;
 	size_t answer_count;
@@ -786,13 +800,12 @@
 				break;
 			
+			size = MAX_UDP_FRAGMENT_SIZE;
 			if (tl_get_ip_packet_dimension(udp_globals.ip_phone,
 			    &udp_globals.dimensions, DEVICE_INVALID_ID,
 			    &packet_dimension) == EOK) {
-				SOCKET_SET_DATA_FRAGMENT_SIZE(answer,
-				    packet_dimension->content);
+				if (packet_dimension->content < size)
+					size = packet_dimension->content;
 			}
-
-//			SOCKET_SET_DATA_FRAGMENT_SIZE(answer,
-//			    MAX_UDP_FRAGMENT_SIZE);
+			SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size);
 			SOCKET_SET_HEADER_SIZE(answer, UDP_HEADER_SIZE);
 			answer_count = 3;
Index: uspace/srv/vfs/vfs_file.c
===================================================================
--- uspace/srv/vfs/vfs_file.c	(revision 380e0364390275dc6f268aca523c2557a5b65469)
+++ uspace/srv/vfs/vfs_file.c	(revision d7f08b0d09bf493daacb7481ca175313fec7cb30)
@@ -258,7 +258,9 @@
 	if ((fd >= 0) && (fd < MAX_OPEN_FILES)) {
 		vfs_file_t *file = FILES[fd];
-		vfs_file_addref(file);
-		fibril_mutex_unlock(&VFS_DATA->lock);
-		return file;
+		if (file != NULL) {
+			vfs_file_addref(file);
+			fibril_mutex_unlock(&VFS_DATA->lock);
+			return file;
+		}
 	}
 	fibril_mutex_unlock(&VFS_DATA->lock);
