Index: uspace/drv/ohci/batch.c
===================================================================
--- uspace/drv/ohci/batch.c	(revision e387d0fad920ec084554d359efa79df35684f3ec)
+++ uspace/drv/ohci/batch.c	(revision f8e1a2cf3c4a6688717a5d44ab4b0e3757b50475)
@@ -26,5 +26,5 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-/** @addtogroup drvusbohcihc
+/** @addtogroup drvusbohci
  * @{
  */
@@ -40,287 +40,6 @@
 #include "batch.h"
 
-static void batch_call_in(batch_t *instance);
-static void batch_call_out(batch_t *instance);
-static void batch_call_in_and_dispose(batch_t *instance);
-static void batch_call_out_and_dispose(batch_t *instance);
+#define DEFAULT_ERROR_COUNT 3
 
-/** 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 packets.
- * @param[in] speed Speed of the transaction.
- * @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] arg additional parameter to func_in or func_out
- * @param[in] manager Pointer to toggle management structure.
- * @return Valid pointer if all substructures were successfully created,
- * NULL otherwise.
- *
- * Determines the number of needed packets (TDs). Prepares a transport buffer
- * (that is accessible by the hardware). Initializes parameters needed for the
- * transaction and callback.
- */
-batch_t * batch_get(ddf_fun_t *fun, usb_target_t target,
-    usb_transfer_type_t transfer_type, size_t max_packet_size,
-    usb_speed_t speed, char *buffer, size_t size,
-    char* setup_buffer, size_t setup_size,
-    usbhc_iface_transfer_in_callback_t func_in,
-    usbhc_iface_transfer_out_callback_t func_out, void *arg
-    )
-{
-	assert(func_in == NULL || func_out == NULL);
-	assert(func_in != NULL || func_out != NULL);
-
-#define CHECK_NULL_DISPOSE_RETURN(ptr, message...) \
-	if (ptr == NULL) { \
-		usb_log_error(message); \
-		if (instance) { \
-			batch_dispose(instance); \
-		} \
-		return NULL; \
-	} else (void)0
-
-	batch_t *instance = malloc(sizeof(batch_t));
-	CHECK_NULL_DISPOSE_RETURN(instance,
-	    "Failed to allocate batch instance.\n");
-	bzero(instance, sizeof(batch_t));
-
-	if (size > 0) {
-		/* TODO: use device accessible malloc here */
-		instance->transport_buffer = malloc(size);
-		CHECK_NULL_DISPOSE_RETURN(instance->transport_buffer,
-		    "Failed to allocate device accessible buffer.\n");
-	}
-
-	if (setup_size > 0) {
-		/* TODO: use device accessible malloc here */
-		instance->setup_buffer = malloc(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);
-	}
-
-	link_initialize(&instance->link);
-
-	instance->max_packet_size = max_packet_size;
-	instance->target = target;
-	instance->transfer_type = transfer_type;
-	instance->buffer = buffer;
-	instance->buffer_size = size;
-	instance->setup_size = setup_size;
-	instance->fun = fun;
-	instance->arg = arg;
-	instance->speed = speed;
-	instance->callback_out = func_out;
-	instance->callback_in = func_in;
-
-	usb_log_debug("Batch(%p) %d:%d memory structures ready.\n",
-	    instance, target.address, target.endpoint);
-	return instance;
-}
-/*----------------------------------------------------------------------------*/
-/** Mark batch as finished and continue with next step.
- *
- * @param[in] instance Batch structure to use.
- *
- */
-void batch_finish(batch_t *instance, int error)
-{
-	assert(instance);
-	instance->error = error;
-	instance->next_step(instance);
-}
-/*----------------------------------------------------------------------------*/
-/** Check batch TDs for activity.
- *
- * @param[in] instance Batch structure to use.
- * @return False, if there is an active TD, true otherwise.
- *
- * 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
- * is reached.
- */
-bool batch_is_complete(batch_t *instance)
-{
-	assert(instance);
-	/* TODO: implement */
-	return true;
-}
-/*----------------------------------------------------------------------------*/
-/** Prepares control write transaction.
- *
- * @param[in] instance Batch structure to use.
- *
- * Uses genercir control function with pids OUT and IN.
- */
-void batch_control_write(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;
-	/* TODO: implement */
-	usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
-}
-/*----------------------------------------------------------------------------*/
-/** Prepares control read transaction.
- *
- * @param[in] instance Batch structure to use.
- *
- * Uses generic control with pids IN and OUT.
- */
-void batch_control_read(batch_t *instance)
-{
-	assert(instance);
-	instance->next_step = batch_call_in_and_dispose;
-	/* TODO: implement */
-	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.
- */
-void batch_interrupt_in(batch_t *instance)
-{
-	assert(instance);
-	/* TODO: implement */
-	instance->next_step = 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.
- */
-void batch_interrupt_out(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;
-	/* TODO: implement */
-	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.
- */
-void batch_bulk_in(batch_t *instance)
-{
-	assert(instance);
-	instance->next_step = batch_call_in_and_dispose;
-	/* TODO: implement */
-	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.
- */
-void batch_bulk_out(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;
-	/* TODO: implement */
-	usb_log_debug("Batch(%p) BULK OUT initialized.\n", instance);
-}
-/*----------------------------------------------------------------------------*/
-/** Prepare data, get error status and call callback in.
- *
- * @param[in] instance Batch structure to use.
- * Copies data from transport buffer, and calls callback with appropriate
- * parameters.
- */
-void batch_call_in(batch_t *instance)
-{
-	assert(instance);
-	assert(instance->callback_in);
-
-	/* We are data in, we need data */
-	memcpy(instance->buffer, instance->transport_buffer,
-	    instance->buffer_size);
-
-	int err = instance->error;
-	usb_log_debug("Batch(%p) callback IN(type:%d): %s(%d), %zu.\n",
-	    instance, instance->transfer_type, str_error(err), err,
-	    instance->transfered_size);
-
-	instance->callback_in(
-	    instance->fun, err, instance->transfered_size, instance->arg);
-}
-/*----------------------------------------------------------------------------*/
-/** Get error status and call callback out.
- *
- * @param[in] instance Batch structure to use.
- */
-void batch_call_out(batch_t *instance)
-{
-	assert(instance);
-	assert(instance->callback_out);
-
-	int err = instance->error;
-	usb_log_debug("Batch(%p) callback OUT(type:%d): %s(%d).\n",
-	    instance, instance->transfer_type, str_error(err), err);
-	instance->callback_out(instance->fun,
-	    err, instance->arg);
-}
-/*----------------------------------------------------------------------------*/
-/** Helper function calls callback and correctly disposes of batch structure.
- *
- * @param[in] instance Batch structure to use.
- */
-void batch_call_in_and_dispose(batch_t *instance)
-{
-	assert(instance);
-	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(batch_t *instance)
-{
-	assert(instance);
-	batch_call_out(instance);
-	batch_dispose(instance);
-}
-/*----------------------------------------------------------------------------*/
-/** Correctly dispose all used data structures.
- *
- * @param[in] instance Batch structure to use.
- */
-void batch_dispose(batch_t *instance)
-{
-	assert(instance);
-	usb_log_debug("Batch(%p) disposing.\n", instance);
-	if (instance->setup_buffer)
-		free(instance->setup_buffer);
-	if (instance->transport_buffer)
-		free(instance->transport_buffer);
-	free(instance);
-}
 /**
  * @}
Index: uspace/drv/ohci/batch.h
===================================================================
--- uspace/drv/ohci/batch.h	(revision e387d0fad920ec084554d359efa79df35684f3ec)
+++ uspace/drv/ohci/batch.h	(revision f8e1a2cf3c4a6688717a5d44ab4b0e3757b50475)
@@ -26,39 +26,18 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-/** @addtogroup drvusbuhcihc
+/** @addtogroup drvusbohci
  * @{
  */
 /** @file
- * @brief UHCI driver USB transaction structure
+ * @brief OHCI driver USB transaction structure
  */
-#ifndef DRV_UHCI_BATCH_H
-#define DRV_UHCI_BATCH_H
+#ifndef DRV_OHCI_BATCH_H
+#define DRV_OHCI_BATCH_H
 
-#include <adt/list.h>
 
 #include <usbhc_iface.h>
 #include <usb/usb.h>
-
-typedef struct batch
-{
-	link_t link;
-	usb_speed_t speed;
-	usb_target_t target;
-	usb_transfer_type_t transfer_type;
-	usbhc_iface_transfer_in_callback_t callback_in;
-	usbhc_iface_transfer_out_callback_t callback_out;
-	void *arg;
-	char *transport_buffer;
-	char *setup_buffer;
-	size_t setup_size;
-	char *buffer;
-	size_t buffer_size;
-	size_t max_packet_size;
-	size_t packets;
-	size_t transfered_size;
-	int error;
-	ddf_fun_t *fun;
-	void (*next_step)(struct batch*);
-} batch_t;
+#include <usb/host/device_keeper.h>
+#include <usb/host/batch.h>
 
 batch_t * batch_get(
@@ -74,12 +53,9 @@
     usbhc_iface_transfer_in_callback_t func_in,
     usbhc_iface_transfer_out_callback_t func_out,
-		void *arg
+		void *arg,
+		device_keeper_t *manager
 		);
 
 void batch_dispose(batch_t *instance);
-
-void batch_finish(batch_t *instance, int error);
-
-bool batch_is_complete(batch_t *instance);
 
 void batch_control_write(batch_t *instance);
Index: uspace/drv/ohci/hc_iface.c
===================================================================
--- uspace/drv/ohci/hc_iface.c	(revision e387d0fad920ec084554d359efa79df35684f3ec)
+++ uspace/drv/ohci/hc_iface.c	(revision f8e1a2cf3c4a6688717a5d44ab4b0e3757b50475)
@@ -322,5 +322,5 @@
 }
 
-/** Host controller interface implementation for EHCI. */
+/** Host controller interface implementation for OHCI. */
 usbhc_iface_t ohci_hc_iface = {
 	.reserve_default_address = reserve_default_address,
Index: uspace/drv/ohci/ohci_rh.c
===================================================================
--- uspace/drv/ohci/ohci_rh.c	(revision e387d0fad920ec084554d359efa79df35684f3ec)
+++ uspace/drv/ohci/ohci_rh.c	(revision f8e1a2cf3c4a6688717a5d44ab4b0e3757b50475)
@@ -30,5 +30,5 @@
  */
 /** @file
- * @brief UHCI driver
+ * @brief OHCI driver
  */
 #include <assert.h>
Index: uspace/drv/uhci-hcd/Makefile
===================================================================
--- uspace/drv/uhci-hcd/Makefile	(revision e387d0fad920ec084554d359efa79df35684f3ec)
+++ uspace/drv/uhci-hcd/Makefile	(revision f8e1a2cf3c4a6688717a5d44ab4b0e3757b50475)
@@ -40,5 +40,4 @@
 	uhci_rh.c \
 	uhci_struct/transfer_descriptor.c \
-	utils/device_keeper.c \
 	pci.c \
 	batch.c
Index: uspace/drv/uhci-hcd/batch.c
===================================================================
--- uspace/drv/uhci-hcd/batch.c	(revision e387d0fad920ec084554d359efa79df35684f3ec)
+++ uspace/drv/uhci-hcd/batch.c	(revision f8e1a2cf3c4a6688717a5d44ab4b0e3757b50475)
@@ -42,12 +42,18 @@
 #include "uhci_hc.h"
 #include "utils/malloc32.h"
+#include "uhci_struct/transfer_descriptor.h"
 
 #define DEFAULT_ERROR_COUNT 3
+
+typedef struct uhci_batch {
+	qh_t *qh;
+	td_t *tds;
+	size_t packets;
+	device_keeper_t *manager;
+} uhci_batch_t;
 
 static void batch_control(batch_t *instance,
     usb_packet_id data_stage, usb_packet_id status_stage);
 static void batch_data(batch_t *instance, usb_packet_id pid);
-static void batch_call_in(batch_t *instance);
-static void batch_call_out(batch_t *instance);
 static void batch_call_in_and_dispose(batch_t *instance);
 static void batch_call_out_and_dispose(batch_t *instance);
@@ -78,5 +84,5 @@
 batch_t * batch_get(ddf_fun_t *fun, usb_target_t target,
     usb_transfer_type_t transfer_type, size_t max_packet_size,
-    usb_speed_t speed, char *buffer, size_t size,
+    usb_speed_t speed, char *buffer, size_t buffer_size,
     char* setup_buffer, size_t setup_size,
     usbhc_iface_transfer_in_callback_t func_in,
@@ -100,23 +106,34 @@
 	CHECK_NULL_DISPOSE_RETURN(instance,
 	    "Failed to allocate batch instance.\n");
-	bzero(instance, sizeof(batch_t));
-
-	instance->qh = malloc32(sizeof(qh_t));
-	CHECK_NULL_DISPOSE_RETURN(instance->qh,
+	batch_init(instance, target, transfer_type, speed, max_packet_size,
+	    buffer, NULL, buffer_size, NULL, setup_size, func_in,
+	    func_out, arg, fun, NULL);
+
+
+	uhci_batch_t *data = malloc(sizeof(uhci_batch_t));
+	CHECK_NULL_DISPOSE_RETURN(instance,
+	    "Failed to allocate batch instance.\n");
+	bzero(data, sizeof(uhci_batch_t));
+	data->manager = manager;
+	instance->private_data = data;
+
+	data->packets = (buffer_size + max_packet_size - 1) / max_packet_size;
+	if (transfer_type == USB_TRANSFER_CONTROL) {
+		data->packets += 2;
+	}
+
+	data->tds = malloc32(sizeof(td_t) * data->packets);
+	CHECK_NULL_DISPOSE_RETURN(
+	    data->tds, "Failed to allocate transfer descriptors.\n");
+	bzero(data->tds, sizeof(td_t) * data->packets);
+
+	data->qh = malloc32(sizeof(qh_t));
+	CHECK_NULL_DISPOSE_RETURN(data->qh,
 	    "Failed to allocate batch queue head.\n");
-	qh_init(instance->qh);
-
-	instance->packets = (size + max_packet_size - 1) / max_packet_size;
-	if (transfer_type == USB_TRANSFER_CONTROL) {
-		instance->packets += 2;
-	}
-
-	instance->tds = malloc32(sizeof(td_t) * instance->packets);
-	CHECK_NULL_DISPOSE_RETURN(
-	    instance->tds, "Failed to allocate transfer descriptors.\n");
-	bzero(instance->tds, sizeof(td_t) * instance->packets);
-
-	if (size > 0) {
-		instance->transport_buffer = malloc32(size);
+	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");
@@ -130,22 +147,4 @@
 	}
 
-
-	link_initialize(&instance->link);
-
-	instance->max_packet_size = max_packet_size;
-	instance->target = target;
-	instance->transfer_type = transfer_type;
-	instance->buffer = buffer;
-	instance->buffer_size = size;
-	instance->setup_size = setup_size;
-	instance->fun = fun;
-	instance->arg = arg;
-	instance->speed = speed;
-	instance->manager = manager;
-	instance->callback_out = func_out;
-	instance->callback_in = func_in;
-
-	qh_set_element_td(instance->qh, addr_to_phys(instance->tds));
-
 	usb_log_debug("Batch(%p) %d:%d memory structures ready.\n",
 	    instance, target.address, target.endpoint);
@@ -153,16 +152,4 @@
 }
 /*----------------------------------------------------------------------------*/
-/** Mark batch as failed and continue with next step.
- *
- * @param[in] instance Batch structure to use.
- *
- */
-void batch_abort(batch_t *instance)
-{
-	assert(instance);
-	instance->error = EIO;
-	instance->next_step(instance);
-}
-/*----------------------------------------------------------------------------*/
 /** Check batch TDs for activity.
  *
@@ -177,21 +164,24 @@
 {
 	assert(instance);
+	uhci_batch_t *data = instance->private_data;
+	assert(data);
+
 	usb_log_debug2("Batch(%p) checking %d packet(s) for completion.\n",
-	    instance, instance->packets);
+	    instance, data->packets);
 	instance->transfered_size = 0;
 	size_t i = 0;
-	for (;i < instance->packets; ++i) {
-		if (td_is_active(&instance->tds[i])) {
+	for (;i < data->packets; ++i) {
+		if (td_is_active(&data->tds[i])) {
 			return false;
 		}
 
-		instance->error = td_status(&instance->tds[i]);
+		instance->error = td_status(&data->tds[i]);
 		if (instance->error != EOK) {
 			usb_log_debug("Batch(%p) found error TD(%d):%x.\n",
-			    instance, i, instance->tds[i].status);
-			td_print_status(&instance->tds[i]);
-
-			device_keeper_set_toggle(instance->manager,
-			    instance->target, td_toggle(&instance->tds[i]));
+			    instance, i, data->tds[i].status);
+			td_print_status(&data->tds[i]);
+
+			device_keeper_set_toggle(data->manager,
+			    instance->target, td_toggle(&data->tds[i]));
 			if (i > 0)
 				goto substract_ret;
@@ -199,6 +189,6 @@
 		}
 
-		instance->transfered_size += td_act_size(&instance->tds[i]);
-		if (td_is_short(&instance->tds[i]))
+		instance->transfered_size += td_act_size(&data->tds[i]);
+		if (td_is_short(&data->tds[i]))
 			goto substract_ret;
 	}
@@ -312,7 +302,9 @@
 {
 	assert(instance);
+	uhci_batch_t *data = instance->private_data;
+	assert(data);
+
 	const bool low_speed = instance->speed == USB_SPEED_LOW;
-	int toggle =
-	    device_keeper_get_toggle(instance->manager, instance->target);
+	int toggle = device_keeper_get_toggle(data->manager, instance->target);
 	assert(toggle == 0 || toggle == 1);
 
@@ -320,5 +312,5 @@
 	size_t remain_size = instance->buffer_size;
 	while (remain_size > 0) {
-		char *data =
+		char *trans_data =
 		    instance->transport_buffer + instance->buffer_size
 		    - remain_size;
@@ -328,13 +320,13 @@
 		    remain_size : instance->max_packet_size;
 
-		td_t *next_packet = (packet + 1 < instance->packets)
-		    ? &instance->tds[packet + 1] : NULL;
-
-		assert(packet < instance->packets);
+		td_t *next_packet = (packet + 1 < data->packets)
+		    ? &data->tds[packet + 1] : NULL;
+
+		assert(packet < data->packets);
 		assert(packet_size <= remain_size);
 
 		td_init(
-		    &instance->tds[packet], DEFAULT_ERROR_COUNT, packet_size,
-		    toggle, false, low_speed, instance->target, pid, data,
+		    &data->tds[packet], DEFAULT_ERROR_COUNT, packet_size,
+		    toggle, false, low_speed, instance->target, pid, trans_data,
 		    next_packet);
 
@@ -344,6 +336,6 @@
 		++packet;
 	}
-	td_set_ioc(&instance->tds[packet - 1]);
-	device_keeper_set_toggle(instance->manager, instance->target, toggle);
+	td_set_ioc(&data->tds[packet - 1]);
+	device_keeper_set_toggle(data->manager, instance->target, toggle);
 }
 /*----------------------------------------------------------------------------*/
@@ -363,11 +355,15 @@
 {
 	assert(instance);
+	uhci_batch_t *data = instance->private_data;
+	assert(data);
+	assert(data->packets >= 2);
 
 	const bool low_speed = instance->speed == USB_SPEED_LOW;
 	int toggle = 0;
 	/* setup stage */
-	td_init(instance->tds, DEFAULT_ERROR_COUNT,
-	    instance->setup_size, toggle, false, low_speed, instance->target,
-	    USB_PID_SETUP, instance->setup_buffer, &instance->tds[1]);
+	td_init(
+	    data->tds, DEFAULT_ERROR_COUNT, instance->setup_size, toggle, false,
+	    low_speed, instance->target, USB_PID_SETUP, instance->setup_buffer,
+	    &data->tds[1]);
 
 	/* data stage */
@@ -375,5 +371,5 @@
 	size_t remain_size = instance->buffer_size;
 	while (remain_size > 0) {
-		char *data =
+		char *control_data =
 		    instance->transport_buffer + instance->buffer_size
 		    - remain_size;
@@ -386,10 +382,10 @@
 
 		td_init(
-		    &instance->tds[packet], DEFAULT_ERROR_COUNT, packet_size,
+		    &data->tds[packet], DEFAULT_ERROR_COUNT, packet_size,
 		    toggle, false, low_speed, instance->target, data_stage,
-		    data, &instance->tds[packet + 1]);
+		    control_data, &data->tds[packet + 1]);
 
 		++packet;
-		assert(packet < instance->packets);
+		assert(packet < data->packets);
 		assert(packet_size <= remain_size);
 		remain_size -= packet_size;
@@ -397,51 +393,21 @@
 
 	/* status stage */
-	assert(packet == instance->packets - 1);
-	td_init(&instance->tds[packet], DEFAULT_ERROR_COUNT,
-	    0, 1, false, low_speed, instance->target, status_stage, NULL, NULL);
-
-	td_set_ioc(&instance->tds[packet]);
+	assert(packet == data->packets - 1);
+
+	td_init(
+	    &data->tds[packet], DEFAULT_ERROR_COUNT, 0, 1, false, low_speed,
+	    instance->target, status_stage, NULL, NULL);
+	td_set_ioc(&data->tds[packet]);
+
 	usb_log_debug2("Control last TD status: %x.\n",
-	    instance->tds[packet].status);
-}
-/*----------------------------------------------------------------------------*/
-/** Prepare data, get error status and call callback in.
- *
- * @param[in] instance Batch structure to use.
- * Copies data from transport buffer, and calls callback with appropriate
- * parameters.
- */
-void batch_call_in(batch_t *instance)
-{
-	assert(instance);
-	assert(instance->callback_in);
-
-	/* We are data in, we need data */
-	memcpy(instance->buffer, instance->transport_buffer,
-	    instance->buffer_size);
-
-	int err = instance->error;
-	usb_log_debug("Batch(%p) callback IN(type:%d): %s(%d), %zu.\n",
-	    instance, instance->transfer_type, str_error(err), err,
-	    instance->transfered_size);
-
-	instance->callback_in(
-	    instance->fun, err, instance->transfered_size, instance->arg);
-}
-/*----------------------------------------------------------------------------*/
-/** Get error status and call callback out.
- *
- * @param[in] instance Batch structure to use.
- */
-void batch_call_out(batch_t *instance)
-{
-	assert(instance);
-	assert(instance->callback_out);
-
-	int err = instance->error;
-	usb_log_debug("Batch(%p) callback OUT(type:%d): %s(%d).\n",
-	    instance, instance->transfer_type, str_error(err), err);
-	instance->callback_out(instance->fun,
-	    err, instance->arg);
+	    data->tds[packet].status);
+}
+/*----------------------------------------------------------------------------*/
+qh_t * batch_qh(batch_t *instance)
+{
+	assert(instance);
+	uhci_batch_t *data = instance->private_data;
+	assert(data);
+	return data->qh;
 }
 /*----------------------------------------------------------------------------*/
@@ -475,10 +441,13 @@
 {
 	assert(instance);
+	uhci_batch_t *data = instance->private_data;
+	assert(data);
 	usb_log_debug("Batch(%p) disposing.\n", instance);
 	/* free32 is NULL safe */
-	free32(instance->tds);
-	free32(instance->qh);
+	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 e387d0fad920ec084554d359efa79df35684f3ec)
+++ uspace/drv/uhci-hcd/batch.h	(revision f8e1a2cf3c4a6688717a5d44ab4b0e3757b50475)
@@ -39,33 +39,8 @@
 #include <usbhc_iface.h>
 #include <usb/usb.h>
+#include <usb/host/device_keeper.h>
+#include <usb/host/batch.h>
 
-#include "uhci_struct/transfer_descriptor.h"
 #include "uhci_struct/queue_head.h"
-#include "utils/device_keeper.h"
-
-typedef struct batch
-{
-	link_t link;
-	usb_speed_t speed;
-	usb_target_t target;
-	usb_transfer_type_t transfer_type;
-	usbhc_iface_transfer_in_callback_t callback_in;
-	usbhc_iface_transfer_out_callback_t callback_out;
-	void *arg;
-	char *transport_buffer;
-	char *setup_buffer;
-	size_t setup_size;
-	char *buffer;
-	size_t buffer_size;
-	size_t max_packet_size;
-	size_t packets;
-	size_t transfered_size;
-	int error;
-	ddf_fun_t *fun;
-	qh_t *qh;
-	td_t *tds;
-	void (*next_step)(struct batch*);
-	device_keeper_t *manager;
-} batch_t;
 
 batch_t * batch_get(
@@ -87,6 +62,4 @@
 void batch_dispose(batch_t *instance);
 
-void batch_abort(batch_t *instance);
-
 bool batch_is_complete(batch_t *instance);
 
@@ -102,4 +75,6 @@
 
 void batch_bulk_out(batch_t *instance);
+
+qh_t * batch_qh(batch_t *instance);
 #endif
 /**
Index: uspace/drv/uhci-hcd/iface.c
===================================================================
--- uspace/drv/uhci-hcd/iface.c	(revision e387d0fad920ec084554d359efa79df35684f3ec)
+++ uspace/drv/uhci-hcd/iface.c	(revision f8e1a2cf3c4a6688717a5d44ab4b0e3757b50475)
@@ -41,5 +41,4 @@
 #include "iface.h"
 #include "uhci_hc.h"
-#include "utils/device_keeper.h"
 
 /** Reserve default address interface function
Index: uspace/drv/uhci-hcd/transfer_list.c
===================================================================
--- uspace/drv/uhci-hcd/transfer_list.c	(revision e387d0fad920ec084554d359efa79df35684f3ec)
+++ uspace/drv/uhci-hcd/transfer_list.c	(revision f8e1a2cf3c4a6688717a5d44ab4b0e3757b50475)
@@ -98,10 +98,10 @@
 	usb_log_debug2("Queue %s: Adding batch(%p).\n", instance->name, batch);
 
-	const uint32_t pa = addr_to_phys(batch->qh);
+	const uint32_t pa = addr_to_phys(batch_qh(batch));
 	assert((pa & LINK_POINTER_ADDRESS_MASK) == pa);
 
 	/* New batch will be added to the end of the current list
 	 * so set the link accordingly */
-	qh_set_next_qh(batch->qh, instance->queue_head->next);
+	qh_set_next_qh(batch_qh(batch), instance->queue_head->next);
 
 	fibril_mutex_lock(&instance->guard);
@@ -117,5 +117,5 @@
 		batch_t *last = list_get_instance(
 		    instance->batch_list.prev, batch_t, link);
-		qh_set_next_qh(last->qh, pa);
+		qh_set_next_qh(batch_qh(last), pa);
 	}
 	/* Add to the driver list */
@@ -178,5 +178,5 @@
 		batch_t *batch = list_get_instance(current, batch_t, link);
 		transfer_list_remove_batch(instance, batch);
-		batch_abort(batch);
+		batch_finish(batch, EIO);
 	}
 	fibril_mutex_unlock(&instance->guard);
@@ -194,7 +194,7 @@
 {
 	assert(instance);
+	assert(instance->queue_head);
 	assert(batch);
-	assert(instance->queue_head);
-	assert(batch->qh);
+	assert(batch_qh(batch));
 	usb_log_debug2(
 	    "Queue %s: removing batch(%p).\n", instance->name, batch);
@@ -204,10 +204,10 @@
 	if (batch->link.prev == &instance->batch_list) {
 		/* I'm the first one here */
-		qh_set_element_qh(instance->queue_head, batch->qh->next);
+		qh_set_element_qh(instance->queue_head, batch_qh(batch)->next);
 		pos = "FIRST";
 	} else {
 		batch_t *prev =
 		    list_get_instance(batch->link.prev, batch_t, link);
-		qh_set_next_qh(prev->qh, batch->qh->next);
+		qh_set_next_qh(batch_qh(prev), batch_qh(batch)->next);
 		pos = "NOT FIRST";
 	}
@@ -215,5 +215,5 @@
 	list_remove(&batch->link);
 	usb_log_debug("Batch(%p) removed (%s) from %s, next element %x.\n",
-	    batch, pos, instance->name, batch->qh->next);
+	    batch, pos, instance->name, batch_qh(batch)->next);
 }
 /**
Index: uspace/drv/uhci-hcd/uhci_hc.h
===================================================================
--- uspace/drv/uhci-hcd/uhci_hc.h	(revision e387d0fad920ec084554d359efa79df35684f3ec)
+++ uspace/drv/uhci-hcd/uhci_hc.h	(revision f8e1a2cf3c4a6688717a5d44ab4b0e3757b50475)
@@ -42,8 +42,8 @@
 
 #include <usbhc_iface.h>
+#include <usb/host/device_keeper.h>
 
 #include "batch.h"
 #include "transfer_list.h"
-#include "utils/device_keeper.h"
 
 typedef struct uhci_regs {
Index: uspace/drv/uhci-hcd/utils/device_keeper.c
===================================================================
--- uspace/drv/uhci-hcd/utils/device_keeper.c	(revision e387d0fad920ec084554d359efa79df35684f3ec)
+++ 	(revision )
@@ -1,298 +1,0 @@
-/*
- * Copyright (c) 2011 Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup drvusbuhcihc
- * @{
- */
-/** @file
- * @brief UHCI driver
- */
-#include <assert.h>
-#include <errno.h>
-#include <usb/debug.h>
-
-#include "device_keeper.h"
-
-/*----------------------------------------------------------------------------*/
-/** Initialize device keeper structure.
- *
- * @param[in] instance Memory place to initialize.
- *
- * Set all values to false/0.
- */
-void device_keeper_init(device_keeper_t *instance)
-{
-	assert(instance);
-	fibril_mutex_initialize(&instance->guard);
-	fibril_condvar_initialize(&instance->default_address_occupied);
-	instance->last_address = 0;
-	unsigned i = 0;
-	for (; i < USB_ADDRESS_COUNT; ++i) {
-		instance->devices[i].occupied = false;
-		instance->devices[i].handle = 0;
-		instance->devices[i].toggle_status = 0;
-	}
-}
-/*----------------------------------------------------------------------------*/
-/** 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 device_keeper_reserve_default(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->default_address_occupied,
-		    &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 device_keeper_release_default(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->default_address_occupied);
-}
-/*----------------------------------------------------------------------------*/
-/** Check setup packet data for signs of toggle reset.
- *
- * @param[in] instance Device keeper structure to use.
- * @param[in] target Device to receive setup packet.
- * @param[in] data Setup packet data.
- *
- * Really ugly one.
- */
-void device_keeper_reset_if_need(
-    device_keeper_t *instance, usb_target_t target, const unsigned char *data)
-{
-	assert(instance);
-	fibril_mutex_lock(&instance->guard);
-	if (target.endpoint > 15 || target.endpoint < 0
-	    || target.address >= USB_ADDRESS_COUNT || target.address < 0
-	    || !instance->devices[target.address].occupied) {
-		fibril_mutex_unlock(&instance->guard);
-		usb_log_error("Invalid data when checking for toggle reset.\n");
-		return;
-	}
-
-	switch (data[1])
-	{
-	case 0x01: /*clear feature*/
-		/* recipient is endpoint, value is zero (ENDPOINT_STALL) */
-		if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) {
-			/* endpoint number is < 16, thus first byte is enough */
-			instance->devices[target.address].toggle_status &=
-			    ~(1 << data[4]);
-		}
-	break;
-
-	case 0x9: /* set configuration */
-	case 0x11: /* set interface */
-		/* target must be device */
-		if ((data[0] & 0xf) == 0) {
-			instance->devices[target.address].toggle_status = 0;
-		}
-	break;
-	}
-	fibril_mutex_unlock(&instance->guard);
-}
-/*----------------------------------------------------------------------------*/
-/** Get current value of endpoint toggle.
- *
- * @param[in] instance Device keeper structure to use.
- * @param[in] target Device and endpoint used.
- * @return Error code
- */
-int device_keeper_get_toggle(device_keeper_t *instance, usb_target_t target)
-{
-	assert(instance);
-	int ret;
-	fibril_mutex_lock(&instance->guard);
-	if (target.endpoint > 15 || target.endpoint < 0
-	    || target.address >= USB_ADDRESS_COUNT || target.address < 0
-	    || !instance->devices[target.address].occupied) {
-		usb_log_error("Invalid data when asking for toggle value.\n");
-		ret = EINVAL;
-	} else {
-		ret = (instance->devices[target.address].toggle_status
-		        >> target.endpoint) & 1;
-	}
-	fibril_mutex_unlock(&instance->guard);
-	return ret;
-}
-/*----------------------------------------------------------------------------*/
-/** Set current value of endpoint toggle.
- *
- * @param[in] instance Device keeper structure to use.
- * @param[in] target Device and endpoint used.
- * @param[in] toggle Toggle value.
- * @return Error code.
- */
-int device_keeper_set_toggle(
-    device_keeper_t *instance, usb_target_t target, bool toggle)
-{
-	assert(instance);
-	int ret;
-	fibril_mutex_lock(&instance->guard);
-	if (target.endpoint > 15 || target.endpoint < 0
-	    || target.address >= USB_ADDRESS_COUNT || target.address < 0
-	    || !instance->devices[target.address].occupied) {
-		usb_log_error("Invalid data when setting toggle value.\n");
-		ret = EINVAL;
-	} else {
-		if (toggle) {
-			instance->devices[target.address].toggle_status |= (1 << target.endpoint);
-		} else {
-			instance->devices[target.address].toggle_status &= ~(1 << target.endpoint);
-		}
-		ret = EOK;
-	}
-	fibril_mutex_unlock(&instance->guard);
-	return ret;
-}
-/*----------------------------------------------------------------------------*/
-/** Get a free USB address
- *
- * @param[in] instance Device keeper structure to use.
- * @param[in] speed Speed of the device requiring address.
- * @return Free address, or error code.
- */
-usb_address_t device_keeper_request(
-    device_keeper_t *instance, usb_speed_t speed)
-{
-	assert(instance);
-	fibril_mutex_lock(&instance->guard);
-
-	usb_address_t new_address = instance->last_address + 1;
-	while (instance->devices[new_address].occupied) {
-		if (new_address == instance->last_address) {
-			fibril_mutex_unlock(&instance->guard);
-			return ENOSPC;
-		}
-		if (new_address == USB11_ADDRESS_MAX)
-			new_address = 1;
-		++new_address;
-	}
-
-	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->devices[new_address].toggle_status = 0;
-	instance->last_address = new_address;
-	fibril_mutex_unlock(&instance->guard);
-	return new_address;
-}
-/*----------------------------------------------------------------------------*/
-/** Bind USB address to devman handle.
- *
- * @param[in] instance Device keeper structure to use.
- * @param[in] address Device address
- * @param[in] handle Devman handle of the device.
- */
-void device_keeper_bind(
-    device_keeper_t *instance, usb_address_t address, devman_handle_t handle)
-{
-	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);
-}
-/*----------------------------------------------------------------------------*/
-/** Release used USB address.
- *
- * @param[in] instance Device keeper structure to use.
- * @param[in] address Device address
- */
-void device_keeper_release(device_keeper_t *instance, usb_address_t address)
-{
-	assert(instance);
-	assert(address > 0);
-	assert(address <= USB11_ADDRESS_MAX);
-
-	fibril_mutex_lock(&instance->guard);
-	assert(instance->devices[address].occupied);
-	instance->devices[address].occupied = false;
-	fibril_mutex_unlock(&instance->guard);
-}
-/*----------------------------------------------------------------------------*/
-/** Find USB address associated with the device
- *
- * @param[in] instance Device keeper structure to use.
- * @param[in] handle Devman handle of the device seeking its address.
- * @return USB Address, or error code.
- */
-usb_address_t device_keeper_find(
-    device_keeper_t *instance, devman_handle_t handle)
-{
-	assert(instance);
-	fibril_mutex_lock(&instance->guard);
-	usb_address_t address = 1;
-	while (address <= USB11_ADDRESS_MAX) {
-		if (instance->devices[address].handle == handle) {
-			fibril_mutex_unlock(&instance->guard);
-			return address;
-		}
-		++address;
-	}
-	fibril_mutex_unlock(&instance->guard);
-	return ENOENT;
-}
-/*----------------------------------------------------------------------------*/
-/** Get speed associated with the address
- *
- * @param[in] instance Device keeper structure to use.
- * @param[in] address Address of the device.
- * @return USB speed.
- */
-usb_speed_t device_keeper_speed(
-    device_keeper_t *instance, usb_address_t address)
-{
-	assert(instance);
-	assert(address >= 0);
-	assert(address <= USB11_ADDRESS_MAX);
-	return instance->devices[address].speed;
-}
-/**
- * @}
- */
Index: uspace/drv/uhci-hcd/utils/device_keeper.h
===================================================================
--- uspace/drv/uhci-hcd/utils/device_keeper.h	(revision e387d0fad920ec084554d359efa79df35684f3ec)
+++ 	(revision )
@@ -1,88 +1,0 @@
-/*
- * Copyright (c) 2011 Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup drvusbuhcihc
- * @{
- */
-/** @file
- * @brief UHCI driver
- */
-#ifndef UTILS_DEVICE_KEEPER_H
-#define UTILS_DEVICE_KEEPER_H
-#include <devman.h>
-#include <fibril_synch.h>
-#include <usb/usb.h>
-
-#define USB_ADDRESS_COUNT (USB11_ADDRESS_MAX + 1)
-
-struct usb_device_info {
-	usb_speed_t speed;
-	bool occupied;
-	uint16_t toggle_status;
-	devman_handle_t handle;
-};
-
-typedef struct device_keeper {
-	struct usb_device_info devices[USB_ADDRESS_COUNT];
-	fibril_mutex_t guard;
-	fibril_condvar_t default_address_occupied;
-	usb_address_t last_address;
-} device_keeper_t;
-
-void device_keeper_init(device_keeper_t *instance);
-
-void device_keeper_reserve_default(
-    device_keeper_t *instance, usb_speed_t speed);
-
-void device_keeper_release_default(device_keeper_t *instance);
-
-void device_keeper_reset_if_need(
-    device_keeper_t *instance, usb_target_t target, const unsigned char *setup_data);
-
-int device_keeper_get_toggle(device_keeper_t *instance, usb_target_t target);
-
-int device_keeper_set_toggle(
-    device_keeper_t *instance, usb_target_t target, bool toggle);
-
-usb_address_t device_keeper_request(
-    device_keeper_t *instance, usb_speed_t speed);
-
-void device_keeper_bind(
-    device_keeper_t *instance, usb_address_t address, devman_handle_t handle);
-
-void device_keeper_release(device_keeper_t *instance, usb_address_t address);
-
-usb_address_t device_keeper_find(
-    device_keeper_t *instance, devman_handle_t handle);
-
-usb_speed_t device_keeper_speed(
-    device_keeper_t *instance, usb_address_t address);
-#endif
-/**
- * @}
- */
Index: uspace/lib/usb/Makefile
===================================================================
--- uspace/lib/usb/Makefile	(revision e387d0fad920ec084554d359efa79df35684f3ec)
+++ uspace/lib/usb/Makefile	(revision f8e1a2cf3c4a6688717a5d44ab4b0e3757b50475)
@@ -49,5 +49,7 @@
 	src/request.c \
 	src/usb.c \
-	src/usbdevice.c
+	src/usbdevice.c \
+	src/host/device_keeper.c \
+	src/host/batch.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/usb/include/usb/host/batch.h
===================================================================
--- uspace/lib/usb/include/usb/host/batch.h	(revision f8e1a2cf3c4a6688717a5d44ab4b0e3757b50475)
+++ uspace/lib/usb/include/usb/host/batch.h	(revision f8e1a2cf3c4a6688717a5d44ab4b0e3757b50475)
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup drvusbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI driver USB transaction structure
+ */
+#ifndef LIBUSB_HOST_BATCH_H
+#define LIBUSB_HOST_BATCH_H
+
+#include <adt/list.h>
+
+#include <usbhc_iface.h>
+#include <usb/usb.h>
+
+typedef struct batch
+{
+	link_t link;
+	usb_target_t target;
+	usb_transfer_type_t transfer_type;
+	usb_speed_t speed;
+	usbhc_iface_transfer_in_callback_t callback_in;
+	usbhc_iface_transfer_out_callback_t callback_out;
+	char *buffer;
+	char *transport_buffer;
+	size_t buffer_size;
+	char *setup_buffer;
+	size_t setup_size;
+	size_t max_packet_size;
+	size_t transfered_size;
+	void (*next_step)(struct batch*);
+	int error;
+	ddf_fun_t *fun;
+	void *arg;
+	void *private_data;
+} batch_t;
+
+void batch_init(
+    batch_t *instance,
+    usb_target_t target,
+    usb_transfer_type_t transfer_type,
+    usb_speed_t speed,
+    size_t max_packet_size,
+    char *buffer,
+    char *transport_buffer,
+    size_t buffer_size,
+    char *setup_buffer,
+    size_t setup_size,
+    usbhc_iface_transfer_in_callback_t func_in,
+    usbhc_iface_transfer_out_callback_t func_out,
+    void *arg,
+    ddf_fun_t *fun,
+    void *private_data
+);
+
+static inline batch_t *batch_from_link(link_t *link_ptr)
+{
+	assert(link_ptr);
+	return list_get_instance(link_ptr, batch_t, link);
+}
+
+void batch_call_in(batch_t *instance);
+void batch_call_out(batch_t *instance);
+void batch_finish(batch_t *instance, int error);
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/include/usb/host/device_keeper.h
===================================================================
--- uspace/lib/usb/include/usb/host/device_keeper.h	(revision f8e1a2cf3c4a6688717a5d44ab4b0e3757b50475)
+++ uspace/lib/usb/include/usb/host/device_keeper.h	(revision f8e1a2cf3c4a6688717a5d44ab4b0e3757b50475)
@@ -0,0 +1,88 @@
+/*
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef LIBUSB_HOST_DEVICE_KEEPER_H
+#define LIBUSB_HOST_DEVICE_KEEPER_H
+#include <devman.h>
+#include <fibril_synch.h>
+#include <usb/usb.h>
+
+#define USB_ADDRESS_COUNT (USB11_ADDRESS_MAX + 1)
+
+struct usb_device_info {
+	usb_speed_t speed;
+	bool occupied;
+	uint16_t toggle_status;
+	devman_handle_t handle;
+};
+
+typedef struct device_keeper {
+	struct usb_device_info devices[USB_ADDRESS_COUNT];
+	fibril_mutex_t guard;
+	fibril_condvar_t default_address_occupied;
+	usb_address_t last_address;
+} device_keeper_t;
+
+void device_keeper_init(device_keeper_t *instance);
+
+void device_keeper_reserve_default(
+    device_keeper_t *instance, usb_speed_t speed);
+
+void device_keeper_release_default(device_keeper_t *instance);
+
+void device_keeper_reset_if_need(
+    device_keeper_t *instance, usb_target_t target, const unsigned char *setup_data);
+
+int device_keeper_get_toggle(device_keeper_t *instance, usb_target_t target);
+
+int device_keeper_set_toggle(
+    device_keeper_t *instance, usb_target_t target, bool toggle);
+
+usb_address_t device_keeper_request(
+    device_keeper_t *instance, usb_speed_t speed);
+
+void device_keeper_bind(
+    device_keeper_t *instance, usb_address_t address, devman_handle_t handle);
+
+void device_keeper_release(device_keeper_t *instance, usb_address_t address);
+
+usb_address_t device_keeper_find(
+    device_keeper_t *instance, devman_handle_t handle);
+
+usb_speed_t device_keeper_speed(
+    device_keeper_t *instance, usb_address_t address);
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/host/batch.c
===================================================================
--- uspace/lib/usb/src/host/batch.c	(revision f8e1a2cf3c4a6688717a5d44ab4b0e3757b50475)
+++ uspace/lib/usb/src/host/batch.c	(revision f8e1a2cf3c4a6688717a5d44ab4b0e3757b50475)
@@ -0,0 +1,134 @@
+/*
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * @brief OHCI driver USB transaction structure
+ */
+#include <errno.h>
+#include <str_error.h>
+
+#include <usb/usb.h>
+#include <usb/debug.h>
+#include <usb/host/batch.h>
+
+void batch_init(
+    batch_t *instance,
+    usb_target_t target,
+    usb_transfer_type_t transfer_type,
+    usb_speed_t speed,
+    size_t max_packet_size,
+    char *buffer,
+    char *transport_buffer,
+    size_t buffer_size,
+    char *setup_buffer,
+    size_t setup_size,
+    usbhc_iface_transfer_in_callback_t func_in,
+    usbhc_iface_transfer_out_callback_t func_out,
+    void *arg,
+    ddf_fun_t *fun,
+    void *private_data
+    )
+{
+	assert(instance);
+	link_initialize(&instance->link);
+	instance->target = target;
+	instance->transfer_type = transfer_type;
+	instance->speed = speed;
+	instance->callback_in = func_in;
+	instance->callback_out = func_out;
+	instance->arg = arg;
+	instance->buffer = buffer;
+	instance->transport_buffer = transport_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->transfered_size = 0;
+	instance->next_step = NULL;
+	instance->error = EOK;
+
+}
+/*----------------------------------------------------------------------------*/
+/** Mark batch as finished and continue with next step.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ */
+void batch_finish(batch_t *instance, int error)
+{
+	assert(instance);
+	instance->error = error;
+	instance->next_step(instance);
+}
+/*----------------------------------------------------------------------------*/
+/** Prepare data, get error status and call callback in.
+ *
+ * @param[in] instance Batch structure to use.
+ * Copies data from transport buffer, and calls callback with appropriate
+ * parameters.
+ */
+void batch_call_in(batch_t *instance)
+{
+	assert(instance);
+	assert(instance->callback_in);
+
+	/* We are data in, we need data */
+	memcpy(instance->buffer, instance->transport_buffer,
+	    instance->buffer_size);
+
+	int err = instance->error;
+	usb_log_debug("Batch(%p) callback IN(type:%d): %s(%d), %zu.\n",
+	    instance, instance->transfer_type, str_error(err), err,
+	    instance->transfered_size);
+
+	instance->callback_in(
+	    instance->fun, err, instance->transfered_size, instance->arg);
+}
+/*----------------------------------------------------------------------------*/
+/** Get error status and call callback out.
+ *
+ * @param[in] instance Batch structure to use.
+ */
+void batch_call_out(batch_t *instance)
+{
+	assert(instance);
+	assert(instance->callback_out);
+
+	int err = instance->error;
+	usb_log_debug("Batch(%p) callback OUT(type:%d): %s(%d).\n",
+	    instance, instance->transfer_type, str_error(err), err);
+	instance->callback_out(instance->fun,
+	    err, instance->arg);
+}
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/host/device_keeper.c
===================================================================
--- uspace/lib/usb/src/host/device_keeper.c	(revision f8e1a2cf3c4a6688717a5d44ab4b0e3757b50475)
+++ uspace/lib/usb/src/host/device_keeper.c	(revision f8e1a2cf3c4a6688717a5d44ab4b0e3757b50475)
@@ -0,0 +1,297 @@
+/*
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#include <assert.h>
+#include <errno.h>
+#include <usb/debug.h>
+#include <usb/host/device_keeper.h>
+
+/*----------------------------------------------------------------------------*/
+/** Initialize device keeper structure.
+ *
+ * @param[in] instance Memory place to initialize.
+ *
+ * Set all values to false/0.
+ */
+void device_keeper_init(device_keeper_t *instance)
+{
+	assert(instance);
+	fibril_mutex_initialize(&instance->guard);
+	fibril_condvar_initialize(&instance->default_address_occupied);
+	instance->last_address = 0;
+	unsigned i = 0;
+	for (; i < USB_ADDRESS_COUNT; ++i) {
+		instance->devices[i].occupied = false;
+		instance->devices[i].handle = 0;
+		instance->devices[i].toggle_status = 0;
+	}
+}
+/*----------------------------------------------------------------------------*/
+/** 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 device_keeper_reserve_default(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->default_address_occupied,
+		    &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 device_keeper_release_default(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->default_address_occupied);
+}
+/*----------------------------------------------------------------------------*/
+/** Check setup packet data for signs of toggle reset.
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] target Device to receive setup packet.
+ * @param[in] data Setup packet data.
+ *
+ * Really ugly one.
+ */
+void device_keeper_reset_if_need(
+    device_keeper_t *instance, usb_target_t target, const unsigned char *data)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+	if (target.endpoint > 15 || target.endpoint < 0
+	    || target.address >= USB_ADDRESS_COUNT || target.address < 0
+	    || !instance->devices[target.address].occupied) {
+		fibril_mutex_unlock(&instance->guard);
+		usb_log_error("Invalid data when checking for toggle reset.\n");
+		return;
+	}
+
+	switch (data[1])
+	{
+	case 0x01: /*clear feature*/
+		/* recipient is endpoint, value is zero (ENDPOINT_STALL) */
+		if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) {
+			/* endpoint number is < 16, thus first byte is enough */
+			instance->devices[target.address].toggle_status &=
+			    ~(1 << data[4]);
+		}
+	break;
+
+	case 0x9: /* set configuration */
+	case 0x11: /* set interface */
+		/* target must be device */
+		if ((data[0] & 0xf) == 0) {
+			instance->devices[target.address].toggle_status = 0;
+		}
+	break;
+	}
+	fibril_mutex_unlock(&instance->guard);
+}
+/*----------------------------------------------------------------------------*/
+/** Get current value of endpoint toggle.
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] target Device and endpoint used.
+ * @return Error code
+ */
+int device_keeper_get_toggle(device_keeper_t *instance, usb_target_t target)
+{
+	assert(instance);
+	int ret;
+	fibril_mutex_lock(&instance->guard);
+	if (target.endpoint > 15 || target.endpoint < 0
+	    || target.address >= USB_ADDRESS_COUNT || target.address < 0
+	    || !instance->devices[target.address].occupied) {
+		usb_log_error("Invalid data when asking for toggle value.\n");
+		ret = EINVAL;
+	} else {
+		ret = (instance->devices[target.address].toggle_status
+		        >> target.endpoint) & 1;
+	}
+	fibril_mutex_unlock(&instance->guard);
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+/** Set current value of endpoint toggle.
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] target Device and endpoint used.
+ * @param[in] toggle Toggle value.
+ * @return Error code.
+ */
+int device_keeper_set_toggle(
+    device_keeper_t *instance, usb_target_t target, bool toggle)
+{
+	assert(instance);
+	int ret;
+	fibril_mutex_lock(&instance->guard);
+	if (target.endpoint > 15 || target.endpoint < 0
+	    || target.address >= USB_ADDRESS_COUNT || target.address < 0
+	    || !instance->devices[target.address].occupied) {
+		usb_log_error("Invalid data when setting toggle value.\n");
+		ret = EINVAL;
+	} else {
+		if (toggle) {
+			instance->devices[target.address].toggle_status |= (1 << target.endpoint);
+		} else {
+			instance->devices[target.address].toggle_status &= ~(1 << target.endpoint);
+		}
+		ret = EOK;
+	}
+	fibril_mutex_unlock(&instance->guard);
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+/** Get a free USB address
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] speed Speed of the device requiring address.
+ * @return Free address, or error code.
+ */
+usb_address_t device_keeper_request(
+    device_keeper_t *instance, usb_speed_t speed)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+
+	usb_address_t new_address = instance->last_address + 1;
+	while (instance->devices[new_address].occupied) {
+		if (new_address == instance->last_address) {
+			fibril_mutex_unlock(&instance->guard);
+			return ENOSPC;
+		}
+		if (new_address == USB11_ADDRESS_MAX)
+			new_address = 1;
+		++new_address;
+	}
+
+	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->devices[new_address].toggle_status = 0;
+	instance->last_address = new_address;
+	fibril_mutex_unlock(&instance->guard);
+	return new_address;
+}
+/*----------------------------------------------------------------------------*/
+/** Bind USB address to devman handle.
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] address Device address
+ * @param[in] handle Devman handle of the device.
+ */
+void device_keeper_bind(
+    device_keeper_t *instance, usb_address_t address, devman_handle_t handle)
+{
+	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);
+}
+/*----------------------------------------------------------------------------*/
+/** Release used USB address.
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] address Device address
+ */
+void device_keeper_release(device_keeper_t *instance, usb_address_t address)
+{
+	assert(instance);
+	assert(address > 0);
+	assert(address <= USB11_ADDRESS_MAX);
+
+	fibril_mutex_lock(&instance->guard);
+	assert(instance->devices[address].occupied);
+	instance->devices[address].occupied = false;
+	fibril_mutex_unlock(&instance->guard);
+}
+/*----------------------------------------------------------------------------*/
+/** Find USB address associated with the device
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] handle Devman handle of the device seeking its address.
+ * @return USB Address, or error code.
+ */
+usb_address_t device_keeper_find(
+    device_keeper_t *instance, devman_handle_t handle)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+	usb_address_t address = 1;
+	while (address <= USB11_ADDRESS_MAX) {
+		if (instance->devices[address].handle == handle) {
+			fibril_mutex_unlock(&instance->guard);
+			return address;
+		}
+		++address;
+	}
+	fibril_mutex_unlock(&instance->guard);
+	return ENOENT;
+}
+/*----------------------------------------------------------------------------*/
+/** Get speed associated with the address
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] address Address of the device.
+ * @return USB speed.
+ */
+usb_speed_t device_keeper_speed(
+    device_keeper_t *instance, usb_address_t address)
+{
+	assert(instance);
+	assert(address >= 0);
+	assert(address <= USB11_ADDRESS_MAX);
+	return instance->devices[address].speed;
+}
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/pipes.c
===================================================================
--- uspace/lib/usb/src/pipes.c	(revision e387d0fad920ec084554d359efa79df35684f3ec)
+++ uspace/lib/usb/src/pipes.c	(revision f8e1a2cf3c4a6688717a5d44ab4b0e3757b50475)
@@ -42,4 +42,6 @@
 #include <assert.h>
 
+#define IPC_AGAIN_DELAY (1000 * 2) /* 2ms */
+
 /** Tell USB address assigned to given device.
  *
@@ -150,9 +152,28 @@
 	}
 
-	my_address = get_my_address(parent_phone, dev);
-	if (my_address < 0) {
-		rc = my_address;
-		goto leave;
-	}
+	/*
+	 * Asking for "my" address may require several attempts.
+	 * That is because following scenario may happen:
+	 *  - parent driver (i.e. driver of parent device) announces new device
+	 *    and devman launches current driver
+	 *  - parent driver is preempted and thus does not send address-handle
+	 *    binding to HC driver
+	 *  - this driver gets here and wants the binding
+	 *  - the HC does not know the binding yet and thus it answers ENOENT
+	 *  So, we need to wait for the HC to learn the binding.
+	 */
+	do {
+		my_address = get_my_address(parent_phone, dev);
+
+		if (my_address == ENOENT) {
+			/* Be nice, let other fibrils run and try again. */
+			async_usleep(IPC_AGAIN_DELAY);
+		} else if (my_address < 0) {
+			/* Some other problem, no sense trying again. */
+			rc = my_address;
+			goto leave;
+		}
+
+	} while (my_address < 0);
 
 	rc = usb_device_connection_initialize(connection,
