Index: uspace/app/tester/adt/usbaddrkeep.c
===================================================================
--- uspace/app/tester/adt/usbaddrkeep.c	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/app/tester/adt/usbaddrkeep.c	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -29,5 +29,5 @@
 #include <stdio.h>
 #include <stdlib.h>
-#include <usb/hcd.h>
+#include <usb/addrkeep.h>
 #include <errno.h>
 #include "../tester.h"
Index: uspace/app/usbinfo/info.c
===================================================================
--- uspace/app/usbinfo/info.c	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/app/usbinfo/info.c	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -39,4 +39,5 @@
 #include <usb/usbdrv.h>
 #include <usb/pipes.h>
+#include <usb/recognise.h>
 #include <usb/request.h>
 #include "usbinfo.h"
@@ -47,27 +48,4 @@
 	usb_device_connection_t wire;
 	usb_endpoint_pipe_t ctrl_pipe;
-	ctrl_pipe.hc_phone = -1;
-
-	int hc_phone = devman_device_connect(hc_handle, 0);
-	if (hc_phone < 0) {
-		fprintf(stderr,
-		    NAME ": failed to connect to host controller (%zu): %s.\n",
-		        (size_t) hc_handle, str_error(hc_phone));
-		return hc_phone;
-	}
-
-	/*
-	 * Dump information about possible match ids.
-	 */
-	match_id_list_t match_id_list;
-	init_match_ids(&match_id_list);
-	rc = usb_drv_create_device_match_ids(hc_phone, &match_id_list, address);
-	if (rc != EOK) {
-		fprintf(stderr,
-		    NAME ": failed to fetch match ids of the device: %s.\n",
-		    str_error(rc));
-		goto leave;
-	}
-	dump_match_ids(&match_id_list);
 
 	/*
@@ -95,4 +73,18 @@
 		goto leave;
 	}
+
+	/*
+	 * Dump information about possible match ids.
+	 */
+	match_id_list_t match_id_list;
+	init_match_ids(&match_id_list);
+	rc = usb_device_create_match_ids(&ctrl_pipe, &match_id_list);
+	if (rc != EOK) {
+		fprintf(stderr,
+		    NAME ": failed to fetch match ids of the device: %s.\n",
+		    str_error(rc));
+		goto leave;
+	}
+	dump_match_ids(&match_id_list);
 
 	/*
@@ -141,5 +133,4 @@
 leave:
 	/* Ignoring errors here. */
-	async_hangup(hc_phone);
 	usb_endpoint_pipe_end_session(&ctrl_pipe);
 
Index: uspace/app/usbinfo/main.c
===================================================================
--- uspace/app/usbinfo/main.c	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/app/usbinfo/main.c	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -81,4 +81,8 @@
 {
 	int rc;
+
+	if (str_cmp(path, "uhci") == 0) {
+		path = "/hw/pci0/00:01.2";
+	}
 
 	devman_handle_t handle;
Index: uspace/app/virtusbkbd/kbdconfig.c
===================================================================
--- uspace/app/virtusbkbd/kbdconfig.c	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/app/virtusbkbd/kbdconfig.c	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -61,5 +61,5 @@
 	.endpoint_count = 1,
 	.interface_class = USB_CLASS_HID,
-	.interface_subclass = 0,
+	.interface_subclass = USB_HID_SUBCLASS_BOOT,
 	.interface_protocol = USB_HID_PROTOCOL_KEYBOARD,
 	.str_interface = 0
Index: uspace/drv/uhci-hcd/Makefile
===================================================================
--- uspace/drv/uhci-hcd/Makefile	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/drv/uhci-hcd/Makefile	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -40,5 +40,5 @@
 	uhci_struct/transfer_descriptor.c \
 	pci.c \
-	tracker.c
+	batch.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/uhci-hcd/batch.c
===================================================================
--- uspace/drv/uhci-hcd/batch.c	(revision 50ba203e98ce570f05993da83249a116cfffceab)
+++ uspace/drv/uhci-hcd/batch.c	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -0,0 +1,383 @@
+/*
+ * 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 usb
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#include <errno.h>
+
+#include <usb/debug.h>
+
+#include "batch.h"
+#include "transfer_list.h"
+#include "uhci.h"
+#include "utils/malloc32.h"
+
+#define DEFAULT_ERROR_COUNT 3
+
+static int batch_schedule(batch_t *instance);
+
+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);
+
+
+batch_t * batch_get(device_t *dev, usb_target_t target,
+    usb_transfer_type_t transfer_type, size_t max_packet_size,
+    dev_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);
+
+	batch_t *instance = malloc(sizeof(batch_t));
+	if (instance == NULL) {
+		usb_log_error("Failed to allocate batch instance.\n");
+		return NULL;
+	}
+
+	instance->qh = queue_head_get();
+	if (instance->qh == NULL) {
+		usb_log_error("Failed to allocate queue head.\n");
+		free(instance);
+		return NULL;
+	}
+
+	instance->packets = (size + max_packet_size - 1) / max_packet_size;
+	if (transfer_type == USB_TRANSFER_CONTROL) {
+		instance->packets += 2;
+	}
+
+	instance->tds = malloc32(sizeof(transfer_descriptor_t) * instance->packets);
+	if (instance->tds == NULL) {
+		usb_log_error("Failed to allocate transfer descriptors.\n");
+		queue_head_dispose(instance->qh);
+		free(instance);
+		return NULL;
+	}
+	bzero(instance->tds, sizeof(transfer_descriptor_t) * instance->packets);
+
+	const size_t transport_size = max_packet_size * instance->packets;
+
+	instance->transport_buffer =
+	   (size > 0) ? malloc32(transport_size) : NULL;
+	if ((size > 0) && (instance->transport_buffer == NULL)) {
+		usb_log_error("Failed to allocate device accessible buffer.\n");
+		queue_head_dispose(instance->qh);
+		free32(instance->tds);
+		free(instance);
+		return NULL;
+	}
+
+	instance->setup_buffer = setup_buffer ? malloc32(setup_size) : NULL;
+	if ((setup_size > 0) && (instance->setup_buffer == NULL)) {
+		usb_log_error("Failed to allocate device accessible setup buffer.\n");
+		queue_head_dispose(instance->qh);
+		free32(instance->tds);
+		free32(instance->transport_buffer);
+		free(instance);
+		return NULL;
+	}
+	if (instance->setup_buffer) {
+		memcpy(instance->setup_buffer, setup_buffer, setup_size);
+	}
+
+	instance->max_packet_size = max_packet_size;
+
+	link_initialize(&instance->link);
+
+	instance->target = target;
+	instance->transfer_type = transfer_type;
+
+	if (func_out)
+		instance->callback_out = func_out;
+	if (func_in)
+		instance->callback_in = func_in;
+
+	instance->buffer = buffer;
+	instance->buffer_size = size;
+	instance->setup_size = setup_size;
+	instance->dev = dev;
+	instance->arg = arg;
+	instance->speed = speed;
+
+	queue_head_element_td(instance->qh, addr_to_phys(instance->tds));
+	return instance;
+}
+/*----------------------------------------------------------------------------*/
+bool batch_is_complete(batch_t *instance)
+{
+	assert(instance);
+	usb_log_debug("Checking(%p) %d packet for completion.\n",
+	    instance, instance->packets);
+	/* This is just an ugly trick to support the old API */
+	instance->transfered_size = 0;
+	size_t i = 0;
+	for (;i < instance->packets; ++i) {
+		if (transfer_descriptor_is_active(&instance->tds[i])) {
+			return false;
+		}
+		instance->error = transfer_descriptor_status(&instance->tds[i]);
+		if (instance->error != EOK) {
+			if (i > 0)
+				instance->transfered_size -= instance->setup_size;
+			return true;
+		}
+		instance->transfered_size +=
+		    transfer_descriptor_actual_size(&instance->tds[i]);
+	}
+	instance->transfered_size -= instance->setup_size;
+	return true;
+}
+/*----------------------------------------------------------------------------*/
+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);
+
+	int toggle = 0;
+	/* setup stage */
+	transfer_descriptor_init(instance->tds, DEFAULT_ERROR_COUNT,
+	    instance->setup_size, toggle, false, instance->target,
+	    USB_PID_SETUP, instance->setup_buffer, &instance->tds[1]);
+
+	/* data stage */
+	size_t i = 1;
+	for (;i < instance->packets - 1; ++i) {
+		char *data =
+		    instance->transport_buffer + ((i - 1) * instance->max_packet_size);
+		toggle = 1 - toggle;
+
+		transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
+		    instance->max_packet_size, toggle++, false, instance->target,
+		    USB_PID_OUT, data, &instance->tds[i + 1]);
+	}
+
+	/* status stage */
+	i = instance->packets - 1;
+	transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
+	    0, 1, false, instance->target, USB_PID_IN, NULL, NULL);
+
+	instance->next_step = batch_call_out_and_dispose;
+	batch_schedule(instance);
+}
+/*----------------------------------------------------------------------------*/
+void batch_control_read(batch_t *instance)
+{
+	assert(instance);
+
+	int toggle = 0;
+	/* setup stage */
+	transfer_descriptor_init(instance->tds, DEFAULT_ERROR_COUNT,
+	    instance->setup_size, toggle, false, instance->target,
+	    USB_PID_SETUP, instance->setup_buffer, &instance->tds[1]);
+
+	/* data stage */
+	size_t i = 1;
+	for (;i < instance->packets - 1; ++i) {
+		char *data =
+		    instance->transport_buffer + ((i - 1) * instance->max_packet_size);
+		toggle = 1 - toggle;
+
+		transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
+		    instance->max_packet_size, toggle, false, instance->target,
+		    USB_PID_IN, data, &instance->tds[i + 1]);
+	}
+
+	/* status stage */
+	i = instance->packets - 1;
+	transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
+	    0, 1, false, instance->target, USB_PID_OUT, NULL, NULL);
+
+	instance->next_step = batch_call_in_and_dispose;
+	batch_schedule(instance);
+}
+/*----------------------------------------------------------------------------*/
+void batch_interrupt_in(batch_t *instance)
+{
+	assert(instance);
+
+	int toggle = 1;
+	size_t i = 0;
+	for (;i < instance->packets; ++i) {
+		char *data =
+		    instance->transport_buffer + (i  * instance->max_packet_size);
+		transfer_descriptor_t *next = (i + 1) < instance->packets ?
+		    &instance->tds[i + 1] : NULL;
+		toggle = 1 - toggle;
+
+		transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
+		    instance->max_packet_size, toggle, false, instance->target,
+		    USB_PID_IN, data, next);
+	}
+
+	instance->next_step = batch_call_in_and_dispose;
+	batch_schedule(instance);
+}
+/*----------------------------------------------------------------------------*/
+void batch_interrupt_out(batch_t *instance)
+{
+	assert(instance);
+
+	memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
+
+	int toggle = 1;
+	size_t i = 0;
+	for (;i < instance->packets; ++i) {
+		char *data =
+		    instance->transport_buffer + (i  * instance->max_packet_size);
+		transfer_descriptor_t *next = (i + 1) < instance->packets ?
+		    &instance->tds[i + 1] : NULL;
+		toggle = 1 - toggle;
+
+		transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
+		    instance->max_packet_size, toggle++, false, instance->target,
+		    USB_PID_OUT, data, next);
+	}
+
+	instance->next_step = batch_call_out_and_dispose;
+	batch_schedule(instance);
+}
+/*----------------------------------------------------------------------------*/
+void batch_call_in(batch_t *instance)
+{
+	assert(instance);
+	assert(instance->callback_in);
+
+	memcpy(instance->buffer, instance->transport_buffer, instance->buffer_size);
+
+	int err = instance->error;
+	usb_log_info("Callback IN(%d): %d, %zu.\n", instance->transfer_type,
+	    err, instance->transfered_size);
+
+	instance->callback_in(instance->dev,
+	    err, instance->transfered_size,
+	    instance->arg);
+}
+/*----------------------------------------------------------------------------*/
+void batch_call_out(batch_t *instance)
+{
+	assert(instance);
+	assert(instance->callback_out);
+
+	int err = instance->error;
+	usb_log_info("Callback OUT(%d): %d.\n", instance->transfer_type, err);
+	instance->callback_out(instance->dev,
+	    err, instance->arg);
+}
+/*----------------------------------------------------------------------------*/
+void batch_call_in_and_dispose(batch_t *instance)
+{
+	assert(instance);
+	batch_call_in(instance);
+	usb_log_debug("Disposing batch: %p.\n", instance);
+	free32(instance->tds);
+	free32(instance->qh);
+	free32(instance->setup_buffer);
+	free32(instance->transport_buffer);
+	free(instance);
+}
+/*----------------------------------------------------------------------------*/
+void batch_call_out_and_dispose(batch_t *instance)
+{
+	assert(instance);
+	batch_call_out(instance);
+	usb_log_debug("Disposing batch: %p.\n", instance);
+	free32(instance->tds);
+	free32(instance->qh);
+	free32(instance->setup_buffer);
+	free32(instance->transport_buffer);
+	free(instance);
+}
+/*----------------------------------------------------------------------------*/
+int batch_schedule(batch_t *instance)
+{
+	assert(instance);
+	uhci_t *hc = dev_to_uhci(instance->dev);
+	assert(hc);
+	return uhci_schedule(hc, instance);
+}
+/*----------------------------------------------------------------------------*/
+/* DEPRECATED FUNCTIONS NEEDED BY THE OLD API */
+void batch_control_setup_old(batch_t *instance)
+{
+	assert(instance);
+	instance->packets = 1;
+
+	/* setup stage */
+	transfer_descriptor_init(instance->tds, DEFAULT_ERROR_COUNT,
+	    instance->setup_size, 0, false, instance->target,
+	    USB_PID_SETUP, instance->setup_buffer, NULL);
+
+	instance->next_step = batch_call_out_and_dispose;
+	batch_schedule(instance);
+}
+/*----------------------------------------------------------------------------*/
+void batch_control_write_data_old(batch_t *instance)
+{
+	assert(instance);
+	instance->packets -= 2;
+	batch_interrupt_out(instance);
+}
+/*----------------------------------------------------------------------------*/
+void batch_control_read_data_old(batch_t *instance)
+{
+	assert(instance);
+	instance->packets -= 2;
+	batch_interrupt_in(instance);
+}
+/*----------------------------------------------------------------------------*/
+void batch_control_write_status_old(batch_t *instance)
+{
+	assert(instance);
+	instance->packets = 1;
+	transfer_descriptor_init(instance->tds, DEFAULT_ERROR_COUNT,
+	    0, 1, false, instance->target, USB_PID_IN, NULL, NULL);
+	instance->next_step = batch_call_in_and_dispose;
+	batch_schedule(instance);
+}
+/*----------------------------------------------------------------------------*/
+void batch_control_read_status_old(batch_t *instance)
+{
+	assert(instance);
+	instance->packets = 1;
+	transfer_descriptor_init(instance->tds, DEFAULT_ERROR_COUNT,
+	    0, 1, false, instance->target, USB_PID_OUT, NULL, NULL);
+	instance->next_step = batch_call_out_and_dispose;
+	batch_schedule(instance);
+}
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/batch.h
===================================================================
--- uspace/drv/uhci-hcd/batch.h	(revision 50ba203e98ce570f05993da83249a116cfffceab)
+++ uspace/drv/uhci-hcd/batch.h	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -0,0 +1,106 @@
+/*
+ * 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 usb
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef DRV_UHCI_BATCH_H
+#define DRV_UHCI_BATCH_H
+
+#include <adt/list.h>
+
+#include <usbhc_iface.h>
+#include <usb/usb.h>
+
+#include "uhci_struct/transfer_descriptor.h"
+#include "uhci_struct/queue_head.h"
+
+typedef enum {
+	LOW_SPEED,
+	FULL_SPEED,
+} dev_speed_t;
+
+typedef struct batch
+{
+	link_t link;
+	dev_speed_t speed;
+	usb_target_t target;
+	usb_transfer_type_t transfer_type;
+	union {
+		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;
+	device_t *dev;
+	queue_head_t *qh;
+	transfer_descriptor_t *tds;
+	void (*next_step)(struct batch*);
+} batch_t;
+
+batch_t * batch_get(device_t *dev, usb_target_t target,
+    usb_transfer_type_t transfer_type, size_t max_packet_size,
+    dev_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);
+
+bool batch_is_complete(batch_t *instance);
+
+void batch_control_write(batch_t *instance);
+
+void batch_control_read(batch_t *instance);
+
+void batch_interrupt_in(batch_t *instance);
+
+void batch_interrupt_out(batch_t *instance);
+
+/* DEPRECATED FUNCTIONS NEEDED BY THE OLD API */
+void batch_control_setup_old(batch_t *instance);
+
+void batch_control_write_data_old(batch_t *instance);
+
+void batch_control_read_data_old(batch_t *instance);
+
+void batch_control_write_status_old(batch_t *instance);
+
+void batch_control_read_status_old(batch_t *instance);
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/iface.c
===================================================================
--- uspace/drv/uhci-hcd/iface.c	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/drv/uhci-hcd/iface.c	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -54,5 +54,5 @@
 }
 /*----------------------------------------------------------------------------*/
-static int reserve_default_address(device_t *dev)
+static int reserve_default_address(device_t *dev, bool full_speed)
 {
 	assert(dev);
@@ -72,5 +72,6 @@
 }
 /*----------------------------------------------------------------------------*/
-static int request_address(device_t *dev, usb_address_t *address)
+static int request_address(device_t *dev, bool full_speed,
+    usb_address_t *address)
 {
 	assert(dev);
@@ -103,35 +104,145 @@
 /*----------------------------------------------------------------------------*/
 static int interrupt_out(device_t *dev, usb_target_t target,
-    void *data, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
+    size_t max_packet_size,
+    void *data, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	dev_speed_t speed = FULL_SPEED;
+
+	batch_t *batch = batch_get(dev, target, USB_TRANSFER_INTERRUPT,
+	    max_packet_size, speed, data, size, NULL, 0, NULL, callback, arg);
+	if (!batch)
+		return ENOMEM;
+	batch_interrupt_out(batch);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static int interrupt_in(device_t *dev, usb_target_t target,
+    size_t max_packet_size,
+    void *data, size_t size,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	dev_speed_t speed = FULL_SPEED;
+
+	batch_t *batch = batch_get(dev, target, USB_TRANSFER_INTERRUPT,
+	    max_packet_size, speed, data, size, NULL, 0, callback, NULL, arg);
+	if (!batch)
+		return ENOMEM;
+	batch_interrupt_in(batch);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static int control_write(device_t *dev, usb_target_t target,
+    size_t max_packet_size,
+    void *setup_data, size_t setup_size, void *data, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	dev_speed_t speed = FULL_SPEED;
+
+	batch_t *batch = batch_get(dev, target, USB_TRANSFER_CONTROL,
+	    max_packet_size, speed, data, size, setup_data, setup_size,
+	    NULL, callback, arg);
+	if (!batch)
+		return ENOMEM;
+	batch_control_write(batch);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static int control_read(device_t *dev, usb_target_t target,
+    size_t max_packet_size,
+    void *setup_data, size_t setup_size, void *data, size_t size,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	dev_speed_t speed = FULL_SPEED;
+
+	batch_t *batch = batch_get(dev, target, USB_TRANSFER_CONTROL,
+	    max_packet_size, speed, data, size, setup_data, setup_size, callback,
+	    NULL, arg);
+	if (!batch)
+		return ENOMEM;
+	batch_control_read(batch);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static int control_write_setup(device_t *dev, usb_target_t target,
+    size_t max_packet_size,
+    void *data, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	dev_speed_t speed = FULL_SPEED;
+
+	usb_log_warning("Using deprecated API %s.\n", __FUNCTION__);
+	batch_t *batch = batch_get(dev, target, USB_TRANSFER_CONTROL,
+	    max_packet_size, speed, NULL, 0, data, size, NULL, callback, arg);
+	if (!batch)
+		return ENOMEM;
+	batch_control_setup_old(batch);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static int control_write_data(device_t *dev, usb_target_t target,
+    size_t max_packet_size,
+    void *data, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	dev_speed_t speed = FULL_SPEED;
+
+	usb_log_warning("Using deprecated API %s.\n", __FUNCTION__);
+	batch_t *batch = batch_get(dev, target, USB_TRANSFER_CONTROL,
+	    max_packet_size, speed, data, size, NULL, 0, NULL, callback, arg);
+	if (!batch)
+		return ENOMEM;
+	batch_control_write_data_old(batch);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static int control_write_status(device_t *dev, usb_target_t target,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
 {
 	size_t max_packet_size = 8;
 	dev_speed_t speed = FULL_SPEED;
 
-	tracker_t *tracker = tracker_get(dev, target, USB_TRANSFER_INTERRUPT,
-	    max_packet_size, speed, data, size, NULL, callback, arg);
-	if (!tracker)
-		return ENOMEM;
-	tracker_interrupt_out(tracker);
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-static int interrupt_in(device_t *dev, usb_target_t target,
-    void *data, size_t size,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	size_t max_packet_size = 4;
-	dev_speed_t speed = FULL_SPEED;
-
-	tracker_t *tracker = tracker_get(dev, target, USB_TRANSFER_INTERRUPT,
-	    max_packet_size, speed, data, size, callback, NULL, arg);
-	if (!tracker)
-		return ENOMEM;
-	tracker_interrupt_in(tracker);
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-static int control_write(device_t *dev, usb_target_t target,
-    void *setup_data, size_t setup_size, void *data, size_t size,
+	usb_log_warning("Using deprecated API %s.\n", __FUNCTION__);
+	batch_t *batch = batch_get(dev, target, USB_TRANSFER_CONTROL,
+	    max_packet_size, speed, NULL, 0, NULL, 0, callback, NULL, arg);
+	if (!batch)
+		return ENOMEM;
+	batch_control_write_status_old(batch);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static int control_read_setup(device_t *dev, usb_target_t target,
+    size_t max_packet_size,
+    void *data, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	dev_speed_t speed = FULL_SPEED;
+
+	usb_log_warning("Using deprecated API %s.\n", __FUNCTION__);
+	batch_t *batch = batch_get(dev, target, USB_TRANSFER_CONTROL,
+	    max_packet_size, speed, NULL, 0, data, size, NULL, callback, arg);
+	if (!batch)
+		return ENOMEM;
+	batch_control_setup_old(batch);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static int control_read_data(device_t *dev, usb_target_t target,
+    size_t max_packet_size,
+    void *data, size_t size,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	dev_speed_t speed = FULL_SPEED;
+
+	usb_log_warning("Using deprecated API %s.\n", __FUNCTION__);
+	batch_t *batch = batch_get(dev, target, USB_TRANSFER_CONTROL,
+	    max_packet_size, speed, data, size, NULL, 0, callback, NULL, arg);
+	if (!batch)
+		return ENOMEM;
+	batch_control_read_data_old(batch);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static int control_read_status(device_t *dev, usb_target_t target,
     usbhc_iface_transfer_out_callback_t callback, void *arg)
 {
@@ -139,96 +250,10 @@
 	dev_speed_t speed = FULL_SPEED;
 
-	tracker_t *tracker = tracker_get(dev, target, USB_TRANSFER_CONTROL,
-	    max_packet_size, speed, data, size, NULL, callback, arg);
-	if (!tracker)
-		return ENOMEM;
-	tracker_control_write(tracker, setup_data, setup_size);
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-static int control_read(device_t *dev, usb_target_t target,
-    void *setup_data, size_t setup_size, void *data, size_t size,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	size_t max_packet_size = 8;
-	dev_speed_t speed = FULL_SPEED;
-
-	tracker_t *tracker = tracker_get(dev, target, USB_TRANSFER_CONTROL,
-	    max_packet_size, speed, data, size, callback, NULL, arg);
-	if (!tracker)
-		return ENOMEM;
-	tracker_control_read(tracker, setup_data, setup_size);
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-static int control_write_setup(device_t *dev, usb_target_t target,
-    void *data, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	usb_log_warning("Using deprecated API control write setup.\n");
-	tracker_t *tracker = tracker_get(dev, target, USB_TRANSFER_CONTROL,
-	    8, FULL_SPEED, data, size, NULL, callback, arg);
-	if (!tracker)
-		return ENOMEM;
-	tracker_control_setup_old(tracker);
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-static int control_write_data(device_t *dev, usb_target_t target,
-    void *data, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	tracker_t *tracker = tracker_get(dev, target, USB_TRANSFER_CONTROL,
-	    size, FULL_SPEED, data, size, NULL, callback, arg);
-	if (!tracker)
-		return ENOMEM;
-	tracker_control_write_data_old(tracker);
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-static int control_write_status(device_t *dev, usb_target_t target,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	tracker_t *tracker = tracker_get(dev, target, USB_TRANSFER_CONTROL,
-	    0, FULL_SPEED, NULL, 0, callback, NULL, arg);
-	if (!tracker)
-		return ENOMEM;
-	tracker_control_write_status_old(tracker);
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-static int control_read_setup(device_t *dev, usb_target_t target,
-    void *data, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	usb_log_warning("Using deprecated API control read setup.\n");
-	tracker_t *tracker = tracker_get(dev, target, USB_TRANSFER_CONTROL,
-	    8, FULL_SPEED, data, size, NULL, callback, arg);
-	if (!tracker)
-		return ENOMEM;
-	tracker_control_setup_old(tracker);
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-static int control_read_data(device_t *dev, usb_target_t target,
-    void *data, size_t size,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	tracker_t *tracker = tracker_get(dev, target, USB_TRANSFER_CONTROL,
-	    size, FULL_SPEED, data, size, callback, NULL, arg);
-	if (!tracker)
-		return ENOMEM;
-	tracker_control_read_data_old(tracker);
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-static int control_read_status(device_t *dev, usb_target_t target,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	tracker_t *tracker = tracker_get(dev, target, USB_TRANSFER_CONTROL,
-	    0, FULL_SPEED, NULL, 0, NULL, callback, arg);
-	if (!tracker)
-		return ENOMEM;
-	tracker_control_read_status_old(tracker);
+	usb_log_warning("Using deprecated API %s.\n", __FUNCTION__);
+	batch_t *batch = batch_get(dev, target, USB_TRANSFER_CONTROL,
+	    max_packet_size, speed, NULL, 0, NULL, 0, NULL, callback, arg);
+	if (!batch)
+		return ENOMEM;
+	batch_control_read_status_old(batch);
 	return EOK;
 }
Index: uspace/drv/uhci-hcd/root_hub.c
===================================================================
--- uspace/drv/uhci-hcd/root_hub.c	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/drv/uhci-hcd/root_hub.c	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -35,39 +35,11 @@
 #include <errno.h>
 #include <stdio.h>
-
 #include <usb_iface.h>
-
 #include <usb/debug.h>
 
 #include "root_hub.h"
+
+extern device_ops_t child_ops;
 /*----------------------------------------------------------------------------*/
-static int usb_iface_get_hc_handle(device_t *dev, devman_handle_t *handle)
-{
-  assert(dev);
-  assert(dev->parent != NULL);
-
-  device_t *parent = dev->parent;
-
-  if (parent->ops && parent->ops->interfaces[USB_DEV_IFACE]) {
-    usb_iface_t *usb_iface
-        = (usb_iface_t *) parent->ops->interfaces[USB_DEV_IFACE];
-    assert(usb_iface != NULL);
-    if (usb_iface->get_hc_handle) {
-      int rc = usb_iface->get_hc_handle(parent, handle);
-      return rc;
-    }
-  }
-
-  return ENOTSUP;
-}
-/*----------------------------------------------------------------------------*/
-static usb_iface_t usb_iface = {
-  .get_hc_handle = usb_iface_get_hc_handle
-};
-
-static device_ops_t rh_ops = {
-	.interfaces[USB_DEV_IFACE] = &usb_iface
-};
-
 int setup_root_hub(device_t **device, device_t *hc)
 {
@@ -108,5 +80,5 @@
 	hub->name = name;
 	hub->parent = hc;
-	hub->ops = &rh_ops;
+	hub->ops = &child_ops;
 
 	*device = hub;
Index: pace/drv/uhci-hcd/tracker.c
===================================================================
--- uspace/drv/uhci-hcd/tracker.c	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ 	(revision )
@@ -1,497 +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 usb
- * @{
- */
-/** @file
- * @brief UHCI driver
- */
-#include <errno.h>
-
-#include <usb/debug.h>
-
-#include "tracker.h"
-#include "uhci.h"
-#include "utils/malloc32.h"
-
-#define SETUP_PACKET_DATA_SIZE 8
-#define DEFAULT_ERROR_COUNT 3
-#define MAX(a,b) ((a > b) ? a : b)
-#define MIN(a,b) ((a < b) ? a : b)
-
-static int tracker_schedule(tracker_t *instance);
-
-static void tracker_control_read_data(tracker_t *instance);
-static void tracker_control_write_data(tracker_t *instance);
-static void tracker_control_read_status(tracker_t *instance);
-static void tracker_control_write_status(tracker_t *instance);
-
-static void tracker_call_in(tracker_t *instance);
-static void tracker_call_out(tracker_t *instance);
-static void tracker_call_in_and_dispose(tracker_t *instance);
-static void tracker_call_out_and_dispose(tracker_t *instance);
-
-
-tracker_t * tracker_get(device_t *dev, usb_target_t target,
-    usb_transfer_type_t transfer_type, size_t max_packet_size,
-    dev_speed_t speed, char *buffer, size_t 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);
-
-	tracker_t *instance = malloc(sizeof(tracker_t));
-	if (!instance) {
-		usb_log_error("Failed to allocate tracker isntance.\n");
-		return NULL;
-	}
-
-	instance->td = malloc32(sizeof(transfer_descriptor_t));
-	if (!instance->td) {
-		usb_log_error("Failed to allocate transfer descriptor.\n");
-		free(instance);
-		return NULL;
-	}
-	bzero(instance->td, sizeof(transfer_descriptor_t));
-
-	instance->packet = max_packet_size ? malloc32(max_packet_size) : NULL;
-	if (max_packet_size && !instance->packet) {
-		usb_log_error("Failed to allocate device acessible buffer.\n");
-		free32(instance->td);
-		free(instance);
-		return NULL;
-	}
-	instance->max_packet_size = max_packet_size;
-	instance->packet_size = 0;
-	instance->buffer_offset = 0;
-
-	link_initialize(&instance->link);
-	instance->target = target;
-	instance->transfer_type = transfer_type;
-
-	if (func_out)
-		instance->callback_out = func_out;
-	if (func_in)
-		instance->callback_in = func_in;
-	instance->buffer = buffer;
-	instance->buffer_size = size;
-	instance->dev = dev;
-	instance->arg = arg;
-	instance->toggle = 0;
-	instance->speed = speed;
-
-	return instance;
-}
-/*----------------------------------------------------------------------------*/
-void tracker_control_write(
-    tracker_t *instance, char* setup_buffer, size_t setup_size)
-{
-	assert(instance);
-	assert(instance->buffer_offset == 0);
-	assert(setup_size == 8);
-
-	instance->packet_size = 0;
-	memcpy(instance->packet, setup_buffer, setup_size);
-
-	transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
-	    setup_size, instance->toggle++, false, instance->target,
-	    USB_PID_SETUP, instance->packet);
-
-	instance->next_step = tracker_control_write_data;
-
-	tracker_schedule(instance);
-}
-/*----------------------------------------------------------------------------*/
-void tracker_control_read(
-    tracker_t *instance, char* setup_buffer, size_t setup_size)
-{
-	assert(instance);
-	assert(instance->buffer_offset == 0);
-	assert(setup_size == 8);
-
-	memcpy(instance->packet, setup_buffer, setup_size);
-
-	transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
-	    setup_size, instance->toggle++, false, instance->target,
-	    USB_PID_SETUP, instance->packet);
-
-	instance->next_step = tracker_control_read_data;
-
-	tracker_schedule(instance);
-}
-/*----------------------------------------------------------------------------*/
-void tracker_control_read_data(tracker_t *instance)
-{
-	assert(instance);
-
-	/* check for errors */
-	int err = transfer_descriptor_status(instance->td);
-	if (err != EOK) {
-		tracker_call_in_and_dispose(instance);
-		return;
-	}
-
-	/* we are data in, we want data from our device */
-	if (instance->packet_size) {
-		memcpy(instance->buffer + instance->buffer_offset, instance->packet,
-		    instance->packet_size);
-	}
-	instance->buffer_offset += instance->packet_size;
-
-	/* prepare next packet, no copy, we are receiving data */
-	instance->packet_size =	MIN(instance->max_packet_size,
-	    instance->buffer_size - instance->buffer_offset);
-
-	transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
-	    instance->packet_size, instance->toggle++, false, instance->target,
-	    USB_PID_IN, instance->packet);
-
-	tracker_schedule(instance);
-
-	/* set next step */
-	if ((instance->buffer_offset + instance->packet_size)
-	    >= instance->buffer_size) {
-		/* that's all, end coomunication */
-		instance->next_step = tracker_control_read_status;
-	}
-}
-/*----------------------------------------------------------------------------*/
-void tracker_control_write_data(tracker_t *instance)
-{
-	assert(instance);
-
-	/* check for errors */
-	int err = transfer_descriptor_status(instance->td);
-	if (err != EOK) {
-		tracker_call_out_and_dispose(instance);
-		return;
-	}
-
-	/* we are data out, we don't want data from our device */
-	instance->buffer_offset += instance->packet_size;
-
-	/* prepare next packet, copy data to packet */
-	instance->packet_size =	MIN(instance->max_packet_size,
-	    instance->buffer_size - instance->buffer_offset);
-	memcpy(instance->packet, instance->buffer + instance->buffer_offset,
-	    instance->packet_size);
-
-	transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
-	    instance->packet_size, instance->toggle++, false, instance->target,
-	    USB_PID_OUT, instance->packet);
-
-	tracker_schedule(instance);
-
-	/* set next step */
-	if ((instance->buffer_offset + instance->packet_size)
-	    >= instance->buffer_size) {
-		/* that's all, end coomunication */
-		instance->next_step = tracker_control_write_status;
-	}
-}
-/*----------------------------------------------------------------------------*/
-void tracker_control_read_status(tracker_t *instance)
-{
-	assert(instance);
-
-	/* check for errors */
-	int err = transfer_descriptor_status(instance->td);
-	if (err != EOK) {
-		tracker_call_in_and_dispose(instance);
-		return;
-	}
-
-	/* we are data in, we want data from our device */
-	memcpy(instance->buffer + instance->buffer_offset, instance->packet,
-	    instance->packet_size);
-	instance->buffer_offset += instance->packet_size;
-	assert(instance->buffer_offset = instance->buffer_size);
-
-	/* prepare next packet, no nothing, just an empty packet */
-	instance->packet_size =	0;
-	transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
-	    instance->packet_size, 1, false, instance->target, USB_PID_OUT, NULL);
-
-	tracker_schedule(instance);
-
-	/* set next step, callback and cleanup */
-	instance->next_step = tracker_call_in_and_dispose;
-}
-/*----------------------------------------------------------------------------*/
-void tracker_control_write_status(tracker_t *instance)
-{
-	assert(instance);
-
-	/* check for errors */
-	int err = transfer_descriptor_status(instance->td);
-	if (err != EOK) {
-		tracker_call_out_and_dispose(instance);
-		return;
-	}
-
-	/* we are data in, we want data from our device */
-	assert(
-	    instance->buffer_offset + instance->packet_size <= instance->buffer_size);
-	memcpy(instance->buffer + instance->buffer_offset, instance->packet,
-	    instance->packet_size);
-	instance->buffer_offset += instance->packet_size;
-	assert(instance->buffer_offset = instance->buffer_size);
-
-	/* prepare next packet, no nothing, just an empty packet */
-	instance->packet_size =	0;
-	transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
-	    instance->packet_size, 1, false, instance->target, USB_PID_IN, NULL);
-
-	tracker_schedule(instance);
-
-	/* set next step, callback and cleanup */
-	instance->next_step = tracker_call_out_and_dispose;
-}
-/*----------------------------------------------------------------------------*/
-void tracker_interrupt_in(tracker_t *instance)
-{
-	assert(instance);
-
-	/* check for errors */
-	int err = transfer_descriptor_status(instance->td);
-	if (err != EOK) {
-		tracker_call_in_and_dispose(instance);
-		return;
-	}
-
-	assert(instance->packet_size <= instance->max_packet_size);
-	if (instance->packet_size) {
-		/* we are data in, we want data from our device. if there is data */
-		memcpy(instance->buffer + instance->buffer_offset, instance->packet,
-				instance->packet_size);
-		instance->buffer_offset += instance->packet_size;
-	}
-
-	/* prepare next packet, no copy, we are receiving data */
-	instance->packet_size =	MIN(instance->max_packet_size,
-			instance->buffer_size - instance->buffer_offset);
-	assert(instance->packet_size <= instance->max_packet_size);
-
-	transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
-	    instance->packet_size, instance->toggle++, false, instance->target,
-	    USB_PID_IN, instance->packet);
-
-	tracker_schedule(instance);
-
-	/* set next step */
-	if ((instance->buffer_offset + instance->packet_size)
-	    >= instance->buffer_size) {
-		/* that's all, end coomunication */
-		instance->next_step = tracker_call_in_and_dispose;
-	} else {
-		instance->next_step = tracker_interrupt_in;
-	}
-}
-/*----------------------------------------------------------------------------*/
-void tracker_interrupt_out(tracker_t *instance)
-{
-	assert(instance);
-
-	/* check for errors */
-	int err = transfer_descriptor_status(instance->td);
-	if (err != EOK) {
-		tracker_call_out_and_dispose(instance);
-		return;
-	}
-
-	/* we are data out, we don't want data from our device */
-	instance->buffer_offset += instance->packet_size;
-
-	/* prepare next packet, copy data to packet */
-	instance->packet_size =	MIN(instance->max_packet_size,
-	    instance->buffer_size - instance->buffer_offset);
-	memcpy(instance->packet, instance->buffer + instance->buffer_offset,
-	    instance->packet_size);
-
-	transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
-	    instance->packet_size, instance->toggle++, false, instance->target,
-	    USB_PID_OUT, instance->packet);
-
-	tracker_schedule(instance);
-
-	/* set next step */
-	if ((instance->buffer_offset + instance->packet_size)
-	    >= instance->buffer_size) {
-		/* that's all, end coomunication */
-		instance->next_step = tracker_call_out_and_dispose;
-	} else {
-		instance->next_step = tracker_interrupt_out;
-	}
-}
-/*----------------------------------------------------------------------------*/
-void tracker_call_in(tracker_t *instance)
-{
-	assert(instance);
-	assert(instance->callback_in);
-
-	/* check for errors */
-	int err = transfer_descriptor_status(instance->td);
-	if (err == EOK && instance->packet_size) {
-		memcpy(instance->buffer + instance->buffer_offset, instance->packet,
-		    instance->packet_size);
-		instance->buffer_offset += instance->packet_size;
-	}
-	usb_log_debug("Callback IN(%d): %d, %zu.\n", instance->transfer_type,
-	    err, instance->buffer_offset);
-	instance->callback_in(instance->dev,
-	    err ? USB_OUTCOME_CRCERROR : USB_OUTCOME_OK, instance->buffer_offset,
-	    instance->arg);
-}
-/*----------------------------------------------------------------------------*/
-void tracker_call_out(tracker_t *instance)
-{
-	assert(instance);
-	assert(instance->callback_out);
-
-	/* check for errors */
-	int err = transfer_descriptor_status(instance->td);
-	usb_log_debug("Callback OUT(%d): %d, %zu.\n", instance->transfer_type,
-	    err, instance->buffer_offset);
-	instance->callback_out(instance->dev,
-	    err ? USB_OUTCOME_CRCERROR : USB_OUTCOME_OK, instance->arg);
-}
-/*----------------------------------------------------------------------------*/
-void tracker_call_in_and_dispose(tracker_t *instance)
-{
-	assert(instance);
-	tracker_call_in(instance);
-	free32(instance->td);
-	free32(instance->packet);
-	free(instance);
-}
-/*----------------------------------------------------------------------------*/
-void tracker_call_out_and_dispose(tracker_t *instance)
-{
-	assert(instance);
-	tracker_call_out(instance);
-	free32(instance->td);
-	free32(instance->packet);
-	free(instance);
-}
-/*----------------------------------------------------------------------------*/
-int tracker_schedule(tracker_t *instance)
-{
-	assert(instance);
-	uhci_t *hc = dev_to_uhci(instance->dev);
-	assert(hc);
-	return uhci_schedule(hc, instance);
-}
-/*----------------------------------------------------------------------------*/
-/* DEPRECATED FUNCTIONS NEEDED BY THE OLD API */
-void tracker_control_setup_old(tracker_t *instance)
-{
-	assert(instance);
-	assert(instance->buffer_offset == 0);
-
-	instance->packet_size = SETUP_PACKET_DATA_SIZE;
-	memcpy(instance->packet, instance->buffer, SETUP_PACKET_DATA_SIZE);
-
-	transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
-	    SETUP_PACKET_DATA_SIZE, 0, false, instance->target, USB_PID_SETUP,
-	    instance->packet);
-
-	instance->buffer_offset += SETUP_PACKET_DATA_SIZE;
-	instance->next_step = tracker_call_out_and_dispose;
-
-	tracker_schedule(instance);
-}
-
-void tracker_control_write_data_old(tracker_t *instance)
-{
-	assert(instance);
-	assert(instance->max_packet_size == instance->buffer_size);
-
-	memcpy(instance->packet, instance->buffer, instance->max_packet_size);
-	instance->packet_size = instance->max_packet_size;
-
-	transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
-	    instance->packet_size, 1, false, instance->target, USB_PID_OUT,
-	    instance->packet);
-	instance->next_step = tracker_call_out_and_dispose;
-
-	tracker_schedule(instance);
-}
-
-void tracker_control_read_data_old(tracker_t *instance)
-{
-	assert(instance);
-	assert(instance->max_packet_size == instance->buffer_size);
-
-	instance->packet_size = instance->max_packet_size;
-
-	transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
-	    instance->packet_size, 1, false, instance->target, USB_PID_IN,
-	    instance->packet);
-
-	instance->next_step = tracker_call_in_and_dispose;
-
-	tracker_schedule(instance);
-}
-
-void tracker_control_write_status_old(tracker_t *instance)
-{
-	assert(instance);
-	assert(instance->max_packet_size == 0);
-	assert(instance->buffer_size == 0);
-	assert(instance->packet == NULL);
-
-	instance->packet_size = instance->max_packet_size;
-	instance->next_step = tracker_call_in_and_dispose;
-
-	transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
-	    instance->packet_size, 1, false, instance->target, USB_PID_IN,
-	    instance->packet);
-
-	tracker_schedule(instance);
-}
-
-void tracker_control_read_status_old(tracker_t *instance)
-{
-	assert(instance);
-	assert(instance->max_packet_size == 0);
-	assert(instance->buffer_size == 0);
-	assert(instance->packet == NULL);
-
-	instance->packet_size = instance->max_packet_size;
-	instance->next_step = tracker_call_out_and_dispose;
-
-	transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
-	    instance->packet_size, 1, false, instance->target, USB_PID_OUT,
-	    instance->packet);
-
-	tracker_schedule(instance);
-}
-/**
- * @}
- */
Index: pace/drv/uhci-hcd/tracker.h
===================================================================
--- uspace/drv/uhci-hcd/tracker.h	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ 	(revision )
@@ -1,102 +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 usb
- * @{
- */
-/** @file
- * @brief UHCI driver
- */
-#ifndef DRV_UHCI_TRACKER_H
-#define DRV_UHCI_TRACKER_H
-
-#include <adt/list.h>
-
-#include <usbhc_iface.h>
-#include <usb/usb.h>
-
-#include "uhci_struct/transfer_descriptor.h"
-
-typedef enum {
-	LOW_SPEED,
-	FULL_SPEED,
-} dev_speed_t;
-
-typedef struct tracker
-{
-	link_t link;
-	usb_target_t target;
-	usb_transfer_type_t transfer_type;
-	union {
-		usbhc_iface_transfer_in_callback_t callback_in;
-		usbhc_iface_transfer_out_callback_t callback_out;
-	};
-	void *arg;
-	char *buffer;
-	char *packet;
-	size_t buffer_size;
-	size_t max_packet_size;
-	size_t packet_size;
-	size_t buffer_offset;
-	dev_speed_t speed;
-	device_t *dev;
-	transfer_descriptor_t *td;
-	void (*next_step)(struct tracker*);
-	unsigned toggle:1;
-} tracker_t;
-
-
-tracker_t * tracker_get(device_t *dev, usb_target_t target,
-    usb_transfer_type_t transfer_type, size_t max_packet_size,
-    dev_speed_t speed, char *buffer, size_t size,
-    usbhc_iface_transfer_in_callback_t func_in,
-    usbhc_iface_transfer_out_callback_t func_out, void *arg);
-
-void tracker_control_write(
-    tracker_t *instance, char* setup_buffer, size_t setup_size);
-
-void tracker_control_read(
-    tracker_t *instance, char* setup_buffer, size_t setup_size);
-
-void tracker_interrupt_in(tracker_t *instance);
-
-void tracker_interrupt_out(tracker_t *instance);
-
-/* DEPRECATED FUNCTIONS NEEDED BY THE OLD API */
-void tracker_control_setup_old(tracker_t *instance);
-
-void tracker_control_write_data_old(tracker_t *instance);
-
-void tracker_control_read_data_old(tracker_t *instance);
-
-void tracker_control_write_status_old(tracker_t *instance);
-
-void tracker_control_read_status_old(tracker_t *instance);
-#endif
-/**
- * @}
- */
Index: uspace/drv/uhci-hcd/transfer_list.c
===================================================================
--- uspace/drv/uhci-hcd/transfer_list.c	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/drv/uhci-hcd/transfer_list.c	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -51,4 +51,6 @@
 
 	queue_head_init(instance->queue_head);
+	list_initialize(&instance->batch_list);
+	fibril_mutex_initialize(&instance->guard);
 	return EOK;
 }
@@ -58,45 +60,83 @@
 	assert(instance);
 	assert(next);
-	instance->next = next;
 	if (!instance->queue_head)
 		return;
-	queue_head_add_next(instance->queue_head, next->queue_head_pa);
+	queue_head_append_qh(instance->queue_head, next->queue_head_pa);
+	instance->queue_head->element = instance->queue_head->next_queue;
 }
 /*----------------------------------------------------------------------------*/
-void transfer_list_add_tracker(transfer_list_t *instance, tracker_t *tracker)
+void transfer_list_add_batch(transfer_list_t *instance, batch_t *batch)
 {
 	assert(instance);
-	assert(tracker);
+	assert(batch);
 
-	uint32_t pa = (uintptr_t)addr_to_phys(tracker->td);
+	uint32_t pa = (uintptr_t)addr_to_phys(batch->qh);
 	assert((pa & LINK_POINTER_ADDRESS_MASK) == pa);
+	pa |= LINK_POINTER_QUEUE_HEAD_FLAG;
 
+	batch->qh->next_queue = instance->queue_head->next_queue;
 
-	if (instance->queue_head->element & LINK_POINTER_TERMINATE_FLAG) {
-		usb_log_debug2("Adding td(%X:%X) to queue %s first.\n",
-			tracker->td->status, tracker->td->device, instance->name);
+	fibril_mutex_lock(&instance->guard);
+
+	if (instance->queue_head->element == instance->queue_head->next_queue) {
 		/* there is nothing scheduled */
-		instance->last_tracker = tracker;
+		list_append(&batch->link, &instance->batch_list);
 		instance->queue_head->element = pa;
-		usb_log_debug2("Added td(%X:%X) to queue %s first.\n",
-			tracker->td->status, tracker->td->device, instance->name);
+		usb_log_debug2("Added batch(%p) to queue %s first.\n",
+			batch, instance->name);
+		fibril_mutex_unlock(&instance->guard);
 		return;
 	}
-	usb_log_debug2("Adding td(%X:%X) to queue %s last.%p\n",
-	    tracker->td->status, tracker->td->device, instance->name,
-	    instance->last_tracker);
-	/* now we can be sure that last_tracker is a valid pointer */
-	instance->last_tracker->td->next = pa;
-	instance->last_tracker = tracker;
+	/* now we can be sure that there is someting scheduled */
+	assert(!list_empty(&instance->batch_list));
+	batch_t *first = list_get_instance(
+	          instance->batch_list.next, batch_t, link);
+	batch_t *last = list_get_instance(
+	    instance->batch_list.prev, batch_t, link);
+	queue_head_append_qh(last->qh, pa);
+	list_append(&batch->link, &instance->batch_list);
+	usb_log_debug2("Added batch(%p) to queue %s last, first is %p.\n",
+		batch, instance->name, first );
+	fibril_mutex_unlock(&instance->guard);
+}
+/*----------------------------------------------------------------------------*/
+static void transfer_list_remove_batch(
+    transfer_list_t *instance, batch_t *batch)
+{
+	assert(instance);
+	assert(batch);
+	assert(instance->queue_head);
+	assert(batch->qh);
 
-	usb_log_debug2("Added td(%X:%X) to queue %s last.\n",
-		tracker->td->status, tracker->td->device, instance->name);
+	/* I'm the first one here */
+	if (batch->link.prev == &instance->batch_list) {
+		usb_log_debug("Removing tracer %p was first, next element %x.\n",
+			batch, batch->qh->next_queue);
+		instance->queue_head->element = batch->qh->next_queue;
+	} else {
+		usb_log_debug("Removing tracer %p was NOT first, next element %x.\n",
+			batch, batch->qh->next_queue);
+		batch_t *prev = list_get_instance(batch->link.prev, batch_t, link);
+		prev->qh->next_queue = batch->qh->next_queue;
+	}
+	list_remove(&batch->link);
+}
+/*----------------------------------------------------------------------------*/
+void transfer_list_check(transfer_list_t *instance)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+	link_t *current = instance->batch_list.next;
+	while (current != &instance->batch_list) {
+		link_t *next = current->next;
+		batch_t *batch = list_get_instance(current, batch_t, link);
 
-	/* check again, may be use atomic compare and swap */
-	if (instance->queue_head->element & LINK_POINTER_TERMINATE_FLAG) {
-		instance->queue_head->element = pa;
-		usb_log_debug2("Added td(%X:%X) to queue first2 %s.\n",
-			tracker->td->status, tracker->td->device, instance->name);
+		if (batch_is_complete(batch)) {
+			transfer_list_remove_batch(instance, batch);
+			batch->next_step(batch);
+		}
+		current = next;
 	}
+	fibril_mutex_unlock(&instance->guard);
 }
 /**
Index: uspace/drv/uhci-hcd/transfer_list.h
===================================================================
--- uspace/drv/uhci-hcd/transfer_list.h	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/drv/uhci-hcd/transfer_list.h	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -35,15 +35,18 @@
 #define DRV_UHCI_TRANSFER_LIST_H
 
+#include <fibril_synch.h>
+
 #include "uhci_struct/queue_head.h"
-#include "tracker.h"
+
+#include "batch.h"
 
 typedef struct transfer_list
 {
-	tracker_t *last_tracker;
-
+	fibril_mutex_t guard;
 	queue_head_t *queue_head;
 	uint32_t queue_head_pa;
 	struct transfer_list *next;
 	const char *name;
+	link_t batch_list;
 } transfer_list_t;
 
@@ -57,8 +60,7 @@
 	queue_head_dispose(instance->queue_head);
 }
+void transfer_list_check(transfer_list_t *instance);
 
-
-void transfer_list_add_tracker(transfer_list_t *instance, tracker_t *tracker);
-
+void transfer_list_add_batch(transfer_list_t *instance, batch_t *batch);
 #endif
 /**
Index: uspace/drv/uhci-hcd/uhci.c
===================================================================
--- uspace/drv/uhci-hcd/uhci.c	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/drv/uhci-hcd/uhci.c	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -89,6 +89,6 @@
 	pio_write_32(&instance->registers->flbaseadd, (uint32_t)pa);
 
-	list_initialize(&instance->tracker_list);
-	fibril_mutex_initialize(&instance->tracker_list_mutex);
+	list_initialize(&instance->batch_list);
+	fibril_mutex_initialize(&instance->batch_list_mutex);
 
 	instance->cleaner = fibril_create(uhci_clean_finished, instance);
@@ -152,35 +152,22 @@
 }
 /*----------------------------------------------------------------------------*/
-int uhci_schedule(uhci_t *instance, tracker_t *tracker)
-{
-	assert(instance);
-	assert(tracker);
-	const int low_speed = (tracker->speed == LOW_SPEED);
+int uhci_schedule(uhci_t *instance, batch_t *batch)
+{
+	assert(instance);
+	assert(batch);
+	const int low_speed = (batch->speed == LOW_SPEED);
 	if (!allowed_usb_packet(
-	    low_speed, tracker->transfer_type, tracker->packet_size)) {
+	    low_speed, batch->transfer_type, batch->max_packet_size)) {
 		usb_log_warning("Invalid USB packet specified %s SPEED %d %zu.\n",
-			  low_speed ? "LOW" : "FULL" , tracker->transfer_type,
-		    tracker->packet_size);
+			  low_speed ? "LOW" : "FULL" , batch->transfer_type,
+		    batch->max_packet_size);
 		return ENOTSUP;
 	}
 	/* TODO: check available bandwith here */
 
-	usb_log_debug2("Scheduler(%d) acquiring tracker list mutex.\n",
-	    fibril_get_id());
-	fibril_mutex_lock(&instance->tracker_list_mutex);
-	usb_log_debug2("Scheduler(%d) acquired tracker list mutex.\n",
-	    fibril_get_id());
-
 	transfer_list_t *list =
-	    instance->transfers[low_speed][tracker->transfer_type];
+	    instance->transfers[low_speed][batch->transfer_type];
 	assert(list);
-	transfer_list_add_tracker(list, tracker);
-	list_append(&tracker->link, &instance->tracker_list);
-
-	usb_log_debug2("Scheduler(%d) releasing tracker list mutex.\n",
-	    fibril_get_id());
-	fibril_mutex_unlock(&instance->tracker_list_mutex);
-	usb_log_debug2("Scheduler(%d) released tracker list mutex.\n",
-	    fibril_get_id());
+	transfer_list_add_batch(list, batch);
 
 	return EOK;
@@ -194,46 +181,8 @@
 
 	while(1) {
-		LIST_INITIALIZE(done_trackers);
-		/* tracker iteration */
-
-		usb_log_debug2("Cleaner(%d) acquiring tracker list mutex.\n",
-		    fibril_get_id());
-		fibril_mutex_lock(&instance->tracker_list_mutex);
-		usb_log_debug2("Cleaner(%d) acquired tracker list mutex.\n",
-		    fibril_get_id());
-
-		link_t *current = instance->tracker_list.next;
-		while (current != &instance->tracker_list)
-		{
-
-			link_t *next = current->next;
-			tracker_t *tracker = list_get_instance(current, tracker_t, link);
-
-			assert(current == &tracker->link);
-			assert(tracker);
-			assert(tracker->next_step);
-			assert(tracker->td);
-
-			if (!transfer_descriptor_is_active(tracker->td)) {
-				usb_log_info("Found inactive tracker with status: %x:%x.\n",
-				    tracker->td->status, tracker->td->device);
-				list_remove(current);
-				list_append(current, &done_trackers);
-			}
-			current = next;
-		}
-
-		usb_log_debug2("Cleaner(%d) releasing tracker list mutex.\n",
-		    fibril_get_id());
-		fibril_mutex_unlock(&instance->tracker_list_mutex);
-		usb_log_debug2("Cleaner(%d) released tracker list mutex.\n",
-		    fibril_get_id());
-
-		while (!list_empty(&done_trackers)) {
-			tracker_t *tracker = list_get_instance(
-			  done_trackers.next, tracker_t, link);
-			list_remove(&tracker->link);
-			tracker->next_step(tracker);
-		}
+		transfer_list_check(&instance->transfers_interrupt);
+		transfer_list_check(&instance->transfers_control_slow);
+		transfer_list_check(&instance->transfers_control_full);
+		transfer_list_check(&instance->transfers_bulk_full);
 		async_usleep(UHCI_CLEANER_TIMEOUT);
 	}
Index: uspace/drv/uhci-hcd/uhci.h
===================================================================
--- uspace/drv/uhci-hcd/uhci.h	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/drv/uhci-hcd/uhci.h	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -44,5 +44,5 @@
 
 #include "transfer_list.h"
-#include "tracker.h"
+#include "batch.h"
 
 typedef struct uhci_regs {
@@ -81,6 +81,6 @@
 	link_pointer_t *frame_list;
 
-	link_t tracker_list;
-	fibril_mutex_t tracker_list_mutex;
+	link_t batch_list;
+	fibril_mutex_t batch_list_mutex;
 
 	transfer_list_t transfers_bulk_full;
@@ -113,5 +113,5 @@
   void *arg );
 
-int uhci_schedule(uhci_t *instance, tracker_t *tracker);
+int uhci_schedule(uhci_t *instance, batch_t *batch);
 
 static inline uhci_t * dev_to_uhci(device_t *dev)
Index: uspace/drv/uhci-hcd/uhci_struct/queue_head.h
===================================================================
--- uspace/drv/uhci-hcd/uhci_struct/queue_head.h	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/drv/uhci-hcd/uhci_struct/queue_head.h	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -55,14 +55,33 @@
 }
 
-static inline void queue_head_add_next(queue_head_t *instance, uint32_t next_queue_pa)
+static inline void queue_head_append_qh(queue_head_t *instance, uint32_t pa)
 {
-	if (next_queue_pa) {
-		instance->next_queue = (next_queue_pa & LINK_POINTER_ADDRESS_MASK)
-		  | LINK_POINTER_QUEUE_HEAD_FLAG;
+	if (pa) {
+		instance->next_queue = (pa & LINK_POINTER_ADDRESS_MASK)
+		    | LINK_POINTER_QUEUE_HEAD_FLAG;
 	}
 }
 
-static inline queue_head_t * queue_head_get()
-	{ return malloc32(sizeof(queue_head_t)); }
+static inline void queue_head_element_qh(queue_head_t *instance, uint32_t pa)
+{
+	if (pa) {
+		instance->next_queue = (pa & LINK_POINTER_ADDRESS_MASK)
+		    | LINK_POINTER_QUEUE_HEAD_FLAG;
+	}
+}
+
+static inline void queue_head_element_td(queue_head_t *instance, uint32_t pa)
+{
+	if (pa) {
+		instance->element = (pa & LINK_POINTER_ADDRESS_MASK);
+	}
+}
+
+static inline queue_head_t * queue_head_get() {
+	queue_head_t *ret = malloc32(sizeof(queue_head_t));
+	if (ret)
+		queue_head_init(ret);
+	return ret;
+}
 
 static inline void queue_head_dispose(queue_head_t *head)
Index: uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c
===================================================================
--- uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -40,9 +40,11 @@
 void transfer_descriptor_init(transfer_descriptor_t *instance,
     int error_count, size_t size, bool toggle, bool isochronous,
-    usb_target_t target, int pid, void *buffer)
+    usb_target_t target, int pid, void *buffer, transfer_descriptor_t *next)
 {
 	assert(instance);
 
-	instance->next = 0 | LINK_POINTER_TERMINATE_FLAG;
+	instance->next = 0
+	    | LINK_POINTER_VERTICAL_FLAG
+	    | ((next != NULL) ? addr_to_phys(next) : LINK_POINTER_TERMINATE_FLAG);
 
 	instance->status = 0
@@ -80,38 +82,27 @@
 #endif
 }
-
-static inline usb_transaction_outcome_t convert_outcome(uint32_t status)
-{
-	/*TODO: refactor into something sane */
-	/*TODO: add additional usb_errors to usb_outcome_t */
-
-	if (status & TD_STATUS_ERROR_STALLED)
-		return USB_OUTCOME_CRCERROR;
-
-	if (status & TD_STATUS_ERROR_BUFFER)
-		return USB_OUTCOME_CRCERROR;
-
-	if (status & TD_STATUS_ERROR_BABBLE)
-		return USB_OUTCOME_BABBLE;
-
-	if (status & TD_STATUS_ERROR_NAK)
-		return USB_OUTCOME_CRCERROR;
-
-  if (status & TD_STATUS_ERROR_CRC)
-		return USB_OUTCOME_CRCERROR;
-
-	if (status & TD_STATUS_ERROR_BIT_STUFF)
-		return USB_OUTCOME_CRCERROR;
-
-//	assert((((status >> TD_STATUS_ERROR_POS) & TD_STATUS_ERROR_MASK)
-//	| TD_STATUS_ERROR_RESERVED) == TD_STATUS_ERROR_RESERVED);
-	return USB_OUTCOME_OK;
-}
 /*----------------------------------------------------------------------------*/
 int transfer_descriptor_status(transfer_descriptor_t *instance)
 {
 	assert(instance);
-	if (convert_outcome(instance->status))
-		return EINVAL; //TODO: use sane error value here
+
+	if ((instance->status & TD_STATUS_ERROR_STALLED) != 0)
+		return EIO;
+
+	if ((instance->status & TD_STATUS_ERROR_CRC) != 0)
+		return EAGAIN;
+
+	if ((instance->status & TD_STATUS_ERROR_BUFFER) != 0)
+		return EAGAIN;
+
+	if ((instance->status & TD_STATUS_ERROR_BABBLE) != 0)
+		return EIO;
+
+	if ((instance->status & TD_STATUS_ERROR_NAK) != 0)
+		return EAGAIN;
+
+	if ((instance->status & TD_STATUS_ERROR_BIT_STUFF) != 0)
+		return EAGAIN;
+
 	return EOK;
 }
Index: uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h
===================================================================
--- uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -93,7 +93,15 @@
 void transfer_descriptor_init(transfer_descriptor_t *instance,
     int error_count, size_t size, bool toggle, bool isochronous,
-    usb_target_t target, int pid, void *buffer);
+    usb_target_t target, int pid, void *buffer, transfer_descriptor_t * next);
 
 int transfer_descriptor_status(transfer_descriptor_t *instance);
+
+static inline size_t transfer_descriptor_actual_size(
+    transfer_descriptor_t *instance)
+{
+	assert(instance);
+	return
+	    ((instance->status >> TD_STATUS_ACTLEN_POS) + 1) & TD_STATUS_ACTLEN_MASK;
+}
 
 static inline bool transfer_descriptor_is_active(
Index: uspace/drv/uhci-hcd/utils/malloc32.h
===================================================================
--- uspace/drv/uhci-hcd/utils/malloc32.h	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/drv/uhci-hcd/utils/malloc32.h	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -45,5 +45,5 @@
 #define UHCI_REQUIRED_PAGE_SIZE 4096
 
-static inline void * addr_to_phys(void *addr)
+static inline uintptr_t addr_to_phys(void *addr)
 {
 	uintptr_t result;
@@ -51,5 +51,5 @@
 
 	assert(ret == 0);
-	return (void*)(result | ((uintptr_t)addr & 0xfff));
+	return (result | ((uintptr_t)addr & 0xfff));
 }
 
Index: uspace/drv/uhci-rhd/port.c
===================================================================
--- uspace/drv/uhci-rhd/port.c	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/drv/uhci-rhd/port.c	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -33,8 +33,12 @@
  */
 #include <errno.h>
+#include <str_error.h>
 
 #include <usb/usb.h>    /* usb_address_t */
-#include <usb/usbdrv.h> /* usb_drv_*     */
+#include <usb/usbdevice.h>
+#include <usb/hub.h>
+#include <usb/request.h>
 #include <usb/debug.h>
+#include <usb/recognise.h>
 
 #include "port.h"
@@ -56,5 +60,10 @@
 	port->attached_device = 0;
 	port->rh = rh;
-	port->hc_phone = parent_phone;
+	int rc = usb_hc_connection_initialize_from_device(
+	    &port->hc_connection, rh);
+	if (rc != EOK) {
+		usb_log_error("Failed to initialize connection to HC.");
+		return rc;
+	}
 
 	port->checker = fibril_create(uhci_port_check, port);
@@ -96,4 +105,11 @@
 
 		if (port_status & STATUS_CONNECTED_CHANGED) {
+			int rc = usb_hc_connection_open(
+			    &port_instance->hc_connection);
+			if (rc != EOK) {
+				usb_log_error("Failed to connect to HC.");
+				goto next;
+			}
+
 			if (port_status & STATUS_CONNECTED) {
 				/* new device */
@@ -102,5 +118,13 @@
 				uhci_port_remove_device(port_instance);
 			}
+
+			rc = usb_hc_connection_close(
+			    &port_instance->hc_connection);
+			if (rc != EOK) {
+				usb_log_error("Failed to disconnect from HC.");
+				goto next;
+			}
 		}
+	next:
 		async_usleep(port_instance->wait_period_usec);
 	}
@@ -111,10 +135,11 @@
 {
 	assert(port);
-	assert(port->hc_phone);
+	assert(usb_hc_connection_is_opened(&port->hc_connection));
 
 	usb_log_info("Adding new device on port %d.\n", port->number);
 
 	/* get address of the future device */
-	const usb_address_t usb_address = usb_drv_request_address(port->hc_phone);
+	const usb_address_t usb_address = usb_hc_request_address(
+	    &port->hc_connection, true);
 
 	if (usb_address <= 0) {
@@ -126,10 +151,10 @@
 
 	/* get default address */
-	int ret = usb_drv_reserve_default_address(port->hc_phone);
+	int ret = usb_hc_reserve_default_address(&port->hc_connection, true);
 	if (ret != EOK) {
 		usb_log_error("Failed to reserve default address on port %d.\n",
 		    port->number);
-		int ret2 =
-		  usb_drv_release_address(port->hc_phone, usb_address);
+		int ret2 = usb_hc_unregister_device(&port->hc_connection,
+		    usb_address);
 		if (ret2 != EOK) {
 			usb_log_fatal("Failed to return requested address on port %d.\n",
@@ -172,11 +197,28 @@
 	}
 
-	/* assign address to device */
-	ret = usb_drv_req_set_address(port->hc_phone, 0, usb_address);
+	/*
+	 * Initialize connection to the device.
+	 */
+	/* FIXME: check for errors. */
+	usb_device_connection_t new_dev_connection;
+	usb_endpoint_pipe_t new_dev_ctrl_pipe;
+	usb_device_connection_initialize_on_default_address(
+	    &new_dev_connection, &port->hc_connection);
+	usb_endpoint_pipe_initialize_default_control(&new_dev_ctrl_pipe,
+	    &new_dev_connection);
+
+	/*
+	 * Assign new address to the device. This function updates
+	 * the backing connection to still point to the same device.
+	 */
+	/* FIXME: check for errors. */
+	usb_endpoint_pipe_start_session(&new_dev_ctrl_pipe);
+	ret = usb_request_set_address(&new_dev_ctrl_pipe, usb_address);
+	usb_endpoint_pipe_end_session(&new_dev_ctrl_pipe);
 
 	if (ret != EOK) { /* address assigning went wrong */
 		usb_log_error("Failed(%d) to assign address to the device.\n", ret);
 		uhci_port_set_enabled(port, false);
-		int release = usb_drv_release_default_address(port->hc_phone);
+		int release = usb_hc_release_default_address(&port->hc_connection);
 		if (release != EOK) {
 			usb_log_error("Failed to release default address on port %d.\n",
@@ -192,5 +234,5 @@
 
 	/* release default address */
-	ret = usb_drv_release_default_address(port->hc_phone);
+	ret = usb_hc_release_default_address(&port->hc_connection);
 	if (ret != EOK) {
 		usb_log_error("Failed to release default address on port %d.\n",
@@ -204,6 +246,6 @@
 	assert(port->attached_device == 0);
 
-	ret = usb_drv_register_child_in_devman(port->hc_phone, port->rh,
-	  usb_address, &port->attached_device);
+	ret = usb_device_register_child_in_devman(new_dev_connection.address,
+	    new_dev_connection.hc_handle, port->rh, &port->attached_device);
 
 	if (ret != EOK) { /* something went wrong */
@@ -215,6 +257,13 @@
 		port->number, usb_address, port->attached_device);
 
-	ret =
-	  usb_drv_bind_address(port->hc_phone, usb_address, port->attached_device);
+	/*
+	 * Register the device in the host controller.
+	 */
+	usb_hc_attached_device_t new_device = {
+		.address = new_dev_connection.address,
+		.handle = port->attached_device
+	};
+
+	ret = usb_hc_register_device(&port->hc_connection, &new_device);
 	// TODO: proper error check here
 	assert(ret == EOK);
Index: uspace/drv/uhci-rhd/port.h
===================================================================
--- uspace/drv/uhci-rhd/port.h	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/drv/uhci-rhd/port.h	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -38,4 +38,5 @@
 #include <driver.h> /* device_t */
 #include <stdint.h>
+#include <usb/usbdevice.h>
 
 #include "port_status.h"
@@ -46,5 +47,5 @@
 	unsigned number;
 	unsigned wait_period_usec;
-	int hc_phone;
+	usb_hc_connection_t hc_connection;
 	device_t *rh;
 	devman_handle_t attached_device;
Index: uspace/drv/usbhid/hid.h
===================================================================
--- uspace/drv/usbhid/hid.h	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/drv/usbhid/hid.h	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -69,8 +69,8 @@
 	device_t *device;
 	usb_hid_configuration_t *conf;
-	usb_address_t address;
 	usb_hid_report_parser_t *parser;
 
 	usb_device_connection_t wire;
+	usb_endpoint_pipe_t ctrl_pipe;
 	usb_endpoint_pipe_t poll_pipe;
 } usb_hid_dev_kbd_t;
Index: uspace/drv/usbhid/main.c
===================================================================
--- uspace/drv/usbhid/main.c	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/drv/usbhid/main.c	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -45,7 +45,9 @@
 #include <str_error.h>
 #include <fibril.h>
+#include <usb/debug.h>
+#include <usb/classes/classes.h>
 #include <usb/classes/hid.h>
 #include <usb/classes/hidparser.h>
-#include <usb/devreq.h>
+#include <usb/request.h>
 #include <usb/descriptor.h>
 #include <io/console.h>
@@ -60,4 +62,14 @@
 
 #define GUESSED_POLL_ENDPOINT 1
+
+/** Keyboard polling endpoint description for boot protocol class. */
+static usb_endpoint_description_t poll_endpoint_description = {
+	.transfer_type = USB_TRANSFER_INTERRUPT,
+	.direction = USB_DIRECTION_IN,
+	.interface_class = USB_CLASS_HID,
+	.interface_subclass = USB_HID_SUBCLASS_BOOT,
+	.interface_protocol = USB_HID_PROTOCOL_KEYBOARD,
+	.flags = 0
+};
 
 static void default_connection_handler(device_t *, ipc_callid_t, ipc_call_t *);
@@ -262,5 +274,4 @@
 }
 
-# if 0
 /*
  * Kbd functions
@@ -281,7 +292,8 @@
 		
 		// get the descriptor from the device
-		int rc = usb_drv_req_get_descriptor(kbd_dev->device->parent_phone,
-		    kbd_dev->address, USB_REQUEST_TYPE_CLASS, USB_DESCTYPE_HID_REPORT, 
-		    0, i, kbd_dev->conf->interfaces[i].report_desc, length, 
+		int rc = usb_request_get_descriptor(&kbd_dev->ctrl_pipe,
+		    USB_REQUEST_TYPE_CLASS, USB_DESCTYPE_HID_REPORT,
+		    i, 0,
+		    kbd_dev->conf->interfaces[i].report_desc, length,
 		    &actual_size);
 
@@ -303,6 +315,7 @@
 	usb_standard_configuration_descriptor_t config_desc;
 	
-	int rc = usb_drv_req_get_bare_configuration_descriptor(
-	    kbd_dev->device->parent_phone, kbd_dev->address, 0, &config_desc);
+	int rc;
+	rc = usb_request_get_bare_configuration_descriptor(&kbd_dev->ctrl_pipe,
+	    0, &config_desc);
 	
 	if (rc != EOK) {
@@ -318,6 +331,6 @@
 	size_t transferred = 0;
 	// get full configuration descriptor
-	rc = usb_drv_req_get_full_configuration_descriptor(
-	    kbd_dev->device->parent_phone, kbd_dev->address, 0, descriptors,
+	rc = usb_request_get_full_configuration_descriptor(&kbd_dev->ctrl_pipe,
+	    0, descriptors,
 	    config_desc.total_length, &transferred);
 	
@@ -329,4 +342,31 @@
 	}
 	
+	/*
+	 * Initialize the interrupt in endpoint.
+	 */
+	usb_endpoint_mapping_t endpoint_mapping[1] = {
+		{
+			.pipe = &kbd_dev->poll_pipe,
+			.description = &poll_endpoint_description
+		}
+	};
+	rc = usb_endpoint_pipe_initialize_from_configuration(
+	    endpoint_mapping, 1,
+	    descriptors, config_desc.total_length,
+	    &kbd_dev->wire);
+	if (rc != EOK) {
+		usb_log_error("Failed to initialize poll pipe: %s.\n",
+		    str_error(rc));
+		return rc;
+	}
+	if (!endpoint_mapping[0].present) {
+		usb_log_warning("Not accepting device, " \
+		    "not boot-protocol keyboard.\n");
+		return EREFUSED;
+	}
+
+
+
+
 	kbd_dev->conf = (usb_hid_configuration_t *)calloc(1, 
 	    sizeof(usb_hid_configuration_t));
@@ -336,5 +376,5 @@
 	}
 	
-	rc = usbkbd_parse_descriptors(descriptors, transferred, kbd_dev->conf);
+	/*rc = usbkbd_parse_descriptors(descriptors, transferred, kbd_dev->conf);
 	free(descriptors);
 	if (rc != EOK) {
@@ -343,5 +383,5 @@
 	}
 
-	// get and report descriptors
+	// get and report descriptors*/
 	rc = usbkbd_get_report_descriptor(kbd_dev);
 	if (rc != EOK) {
@@ -360,10 +400,12 @@
      *    as the endpoint for polling
 	 */
-	
+
 	return EOK;
 }
-#endif
+
 static usb_hid_dev_kbd_t *usbkbd_init_device(device_t *dev)
 {
+	int rc;
+
 	usb_hid_dev_kbd_t *kbd_dev = (usb_hid_dev_kbd_t *)calloc(1, 
 	    sizeof(usb_hid_dev_kbd_t));
@@ -376,40 +418,4 @@
 	kbd_dev->device = dev;
 
-	// get phone to my HC and save it as my parent's phone
-	// TODO: maybe not a good idea if DDF will use parent_phone
-	int rc = kbd_dev->device->parent_phone = usb_drv_hc_connect_auto(dev, 0);
-	if (rc < 0) {
-		printf("Problem setting phone to HC.\n");
-		goto error_leave;
-	}
-
-	rc = kbd_dev->address = usb_drv_get_my_address(dev->parent_phone, dev);
-	if (rc < 0) {
-		printf("Problem getting address of the device.\n");
-		goto error_leave;
-	}
-
-	// doesn't matter now that we have no address
-//	if (kbd_dev->address < 0) {
-//		fprintf(stderr, NAME ": No device address!\n");
-//		free(kbd_dev);
-//		return NULL;
-//	}
-
-	/*
-	 * will need all descriptors:
-	 * 1) choose one configuration from configuration descriptors 
-	 *    (set it to the device)
-	 * 2) set endpoints from endpoint descriptors
-	 */
-
-
-	// TODO: get descriptors, parse descriptors and save endpoints
-	//usbkbd_process_descriptors(kbd_dev);
-	usb_drv_req_set_configuration(
-	  kbd_dev->device->parent_phone, kbd_dev->address, 1);
-
-
-
 	/*
 	 * Initialize the backing connection to the host controller.
@@ -425,12 +431,27 @@
 	 * Initialize device pipes.
 	 */
-	rc = usb_endpoint_pipe_initialize(&kbd_dev->poll_pipe, &kbd_dev->wire,
-	    GUESSED_POLL_ENDPOINT, USB_TRANSFER_INTERRUPT, USB_DIRECTION_IN);
-	if (rc != EOK) {
-		printf("Failed to initialize interrupt in pipe: %s.\n",
+	rc = usb_endpoint_pipe_initialize_default_control(&kbd_dev->ctrl_pipe,
+	    &kbd_dev->wire);
+	if (rc != EOK) {
+		printf("Failed to initialize default control pipe: %s.\n",
 		    str_error(rc));
 		goto error_leave;
 	}
 
+	/*
+	 * will need all descriptors:
+	 * 1) choose one configuration from configuration descriptors
+	 *    (set it to the device)
+	 * 2) set endpoints from endpoint descriptors
+	 */
+
+	// TODO: get descriptors, parse descriptors and save endpoints
+	usb_endpoint_pipe_start_session(&kbd_dev->ctrl_pipe);
+	//usb_request_set_configuration(&kbd_dev->ctrl_pipe, 1);
+	rc = usbkbd_process_descriptors(kbd_dev);
+	usb_endpoint_pipe_end_session(&kbd_dev->ctrl_pipe);
+	if (rc != EOK) {
+		goto error_leave;
+	}
 
 	return kbd_dev;
@@ -590,4 +611,5 @@
 int main(int argc, char *argv[])
 {
+	usb_log_enable(USB_LOG_LEVEL_INFO, "usbhid");
 	return driver_main(&kbd_driver);
 }
Index: uspace/drv/usbhub/usbhub.c
===================================================================
--- uspace/drv/usbhub/usbhub.c	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/drv/usbhub/usbhub.c	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -36,8 +36,10 @@
 #include <bool.h>
 #include <errno.h>
+#include <str_error.h>
 
 #include <usb_iface.h>
 #include <usb/usbdrv.h>
 #include <usb/descriptor.h>
+#include <usb/recognise.h>
 #include <usb/devreq.h>
 #include <usb/request.h>
@@ -76,6 +78,24 @@
 	result->device = device;
 
+<<<<<<< TREE
 	result->usb_device = usb_new(usb_hcd_attached_device_info_t);
 	
+=======
+
+	dprintf(USB_LOG_LEVEL_DEBUG, "phone to hc = %d", hc);
+	if (hc < 0) {
+		return result;
+	}
+	//get some hub info
+	usb_address_t addr = usb_drv_get_my_address(hc, device);
+	dprintf(USB_LOG_LEVEL_DEBUG, "address of newly created hub = %d", addr);
+	/*if(addr<0){
+		//return result;
+
+	}*/
+
+	result->address = addr;
+
+>>>>>>> MERGE-SOURCE
 	// get hub descriptor
 
@@ -148,7 +168,13 @@
 	int port;
 	int opResult;
+<<<<<<< TREE
 	//usb_target_t target;
 	//target.address = hub_info->usb_device->address;
 	//target.endpoint = 0;
+=======
+	usb_target_t target;
+	target.address = hub_info->address;
+	target.endpoint = 0;
+>>>>>>> MERGE-SOURCE
 
 	//get configuration descriptor
@@ -212,5 +238,5 @@
 	dprintf(USB_LOG_LEVEL_INFO, "hub dev added");
 	dprintf(USB_LOG_LEVEL_DEBUG, "\taddress %d, has %d ports ",
-			hub_info->usb_device->address,
+			hub_info->address,
 			hub_info->port_count);
 	dprintf(USB_LOG_LEVEL_DEBUG, "\tused configuration %d",config_descriptor.configuration_number);
@@ -317,7 +343,15 @@
 	}
 
+	devman_handle_t hc_handle;
+	opResult = usb_drv_find_hc(hub->device, &hc_handle);
+	if (opResult != EOK) {
+		usb_log_error("Failed to get handle of host controller: %s.\n",
+		    str_error(opResult));
+		return;
+	}
+
 	devman_handle_t child_handle;
-	opResult = usb_drv_register_child_in_devman(hc, hub->device,
-            new_device_address, &child_handle);
+        opResult = usb_device_register_child_in_devman(new_device_address,
+            hc_handle, hub->device, &child_handle);
 	if (opResult != EOK) {
 		dprintf(USB_LOG_LEVEL_ERROR, "could not start driver for new device");
@@ -472,5 +506,5 @@
 		/*
 		usb_target_t target;
-		target.address = hub_info->usb_device->address;
+		target.address = hub_info->address;
 		target.endpoint = 1;/// \TODO get from endpoint descriptor
 		dprintf(USB_LOG_LEVEL_INFO, "checking changes for hub at addr %d",
@@ -515,5 +549,9 @@
 			if (interrupt) {
 				usb_hub_process_interrupt(
+<<<<<<< TREE
 				        hub_info, port);
+=======
+				        hub_info, hc, port, hub_info->address);
+>>>>>>> MERGE-SOURCE
 			}
 		}
Index: uspace/drv/usbhub/usbhub.h
===================================================================
--- uspace/drv/usbhub/usbhub.h	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/drv/usbhub/usbhub.h	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -36,10 +36,17 @@
 #define DRV_USBHUB_USBHUB_H
 
+#include <ipc/devman.h>
+#include <usb/usb.h>
+#include <driver.h>
+
 #define NAME "usbhub"
 
+<<<<<<< TREE
 #include "usb/hcdhubd.h"
 
 #include <usb/pipes.h>
 
+=======
+>>>>>>> MERGE-SOURCE
 /** basic information about device attached to hub */
 typedef struct{
@@ -62,8 +69,9 @@
 	/** attached device handles, for each port one */
 	usb_hub_attached_device_t * attached_devs;
-	/** General usb device info. */
-	usb_hcd_attached_device_info_t * usb_device;
+	/** USB address of the hub. */
+	usb_address_t address;
 	/** General device info*/
 	device_t * device;
+<<<<<<< TREE
 	/** connection to hcd */
 	usb_device_connection_t connection;
@@ -71,4 +79,6 @@
 	usb_hub_endpoints_t endpoints;
 
+=======
+>>>>>>> MERGE-SOURCE
 } usb_hub_info_t;
 
Index: uspace/drv/vhc/conn.h
===================================================================
--- uspace/drv/vhc/conn.h	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/drv/vhc/conn.h	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -37,5 +37,4 @@
 
 #include <usb/usb.h>
-#include <usb/hcdhubd.h>
 #include <usbhc_iface.h>
 #include "vhcd.h"
@@ -44,5 +43,4 @@
 void connection_handler_host(sysarg_t);
 
-usb_hcd_transfer_ops_t vhc_transfer_ops;
 usbhc_iface_t vhc_iface;
 
Index: uspace/drv/vhc/connhost.c
===================================================================
--- uspace/drv/vhc/connhost.c	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/drv/vhc/connhost.c	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -36,5 +36,5 @@
 #include <errno.h>
 #include <usb/usb.h>
-#include <usb/hcd.h>
+#include <usb/addrkeep.h>
 
 #include "vhcd.h"
@@ -64,5 +64,5 @@
 
 static void universal_callback(void *buffer, size_t size,
-    usb_transaction_outcome_t outcome, void *arg)
+    int outcome, void *arg)
 {
 	transfer_info_t *transfer = (transfer_info_t *) arg;
@@ -107,5 +107,5 @@
 
 static void control_abort_prematurely(control_transfer_info_t *transfer,
-    size_t size, usb_transaction_outcome_t outcome)
+    size_t size, int outcome)
 {
 	switch (transfer->direction) {
@@ -127,9 +127,9 @@
 
 static void control_callback_two(void *buffer, size_t size,
-    usb_transaction_outcome_t outcome, void *arg)
+    int outcome, void *arg)
 {
 	control_transfer_info_t *ctrl_transfer = (control_transfer_info_t *) arg;
 
-	if (outcome != USB_OUTCOME_OK) {
+	if (outcome != EOK) {
 		control_abort_prematurely(ctrl_transfer, outcome, size);
 		free(ctrl_transfer);
@@ -165,9 +165,9 @@
 
 static void control_callback_one(void *buffer, size_t size,
-    usb_transaction_outcome_t outcome, void *arg)
+    int outcome, void *arg)
 {
 	control_transfer_info_t *transfer = (control_transfer_info_t *) arg;
 
-	if (outcome != USB_OUTCOME_OK) {
+	if (outcome != EOK) {
 		control_abort_prematurely(transfer, outcome, size);
 		free(transfer);
@@ -276,4 +276,5 @@
 
 static int interrupt_out(device_t *dev, usb_target_t target,
+    size_t max_packet_size,
     void *data, size_t size,
     usbhc_iface_transfer_out_callback_t callback, void *arg)
@@ -285,4 +286,5 @@
 
 static int interrupt_in(device_t *dev, usb_target_t target,
+    size_t max_packet_size,
     void *data, size_t size,
     usbhc_iface_transfer_in_callback_t callback, void *arg)
@@ -294,4 +296,5 @@
 
 static int control_write_setup(device_t *dev, usb_target_t target,
+    size_t max_packet_size,
     void *data, size_t size,
     usbhc_iface_transfer_out_callback_t callback, void *arg)
@@ -303,4 +306,5 @@
 
 static int control_write_data(device_t *dev, usb_target_t target,
+    size_t max_packet_size,
     void *data, size_t size,
     usbhc_iface_transfer_out_callback_t callback, void *arg)
@@ -320,4 +324,5 @@
 
 static int control_write(device_t *dev, usb_target_t target,
+    size_t max_packet_size,
     void *setup_packet, size_t setup_packet_size,
     void *data, size_t data_size,
@@ -337,4 +342,5 @@
 
 static int control_read_setup(device_t *dev, usb_target_t target,
+    size_t max_packet_size,
     void *data, size_t size,
     usbhc_iface_transfer_out_callback_t callback, void *arg)
@@ -346,4 +352,5 @@
 
 static int control_read_data(device_t *dev, usb_target_t target,
+    size_t max_packet_size,
     void *data, size_t size,
     usbhc_iface_transfer_in_callback_t callback, void *arg)
@@ -363,4 +370,5 @@
 
 static int control_read(device_t *dev, usb_target_t target,
+    size_t max_packet_size,
     void *setup_packet, size_t setup_packet_size,
     void *data, size_t data_size,
@@ -382,5 +390,5 @@
 
 
-static int reserve_default_address(device_t *dev)
+static int reserve_default_address(device_t *dev, bool ignored)
 {
 	usb_address_keeping_reserve_default(&addresses);
@@ -394,5 +402,5 @@
 }
 
-static int request_address(device_t *dev, usb_address_t *address)
+static int request_address(device_t *dev, bool ignored, usb_address_t *address)
 {
 	usb_address_t addr = usb_address_keeping_request(&addresses);
Index: uspace/drv/vhc/devices.c
===================================================================
--- uspace/drv/vhc/devices.c	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/drv/vhc/devices.c	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -112,5 +112,5 @@
  * @param transaction Transaction to be sent over the bus.
  */
-usb_transaction_outcome_t virtdev_send_to_all(transaction_t *transaction)
+int virtdev_send_to_all(transaction_t *transaction)
 {
 	/* For easier debugging. */
@@ -126,5 +126,5 @@
 			assert(false && "unreachable branch in switch()");
 	}
-	usb_transaction_outcome_t outcome = USB_OUTCOME_BABBLE;
+	int outcome = EBADCHECKSUM;
 
 	link_t *pos;
@@ -185,5 +185,5 @@
 		 */
 		if (rc == EOK) {
-			outcome = USB_OUTCOME_OK;
+			outcome = EOK;
 		}
 	}
@@ -221,5 +221,5 @@
 				break;
 		}
-		outcome = USB_OUTCOME_OK;
+		outcome = EOK;
 	}
 	
Index: uspace/drv/vhc/devices.h
===================================================================
--- uspace/drv/vhc/devices.h	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/drv/vhc/devices.h	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -54,5 +54,5 @@
 virtdev_connection_t *virtdev_find(sysarg_t);
 void virtdev_destroy_device(virtdev_connection_t *);
-usb_transaction_outcome_t virtdev_send_to_all(transaction_t *);
+int virtdev_send_to_all(transaction_t *);
 
 #endif
Index: uspace/drv/vhc/hc.c
===================================================================
--- uspace/drv/vhc/hc.c	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/drv/vhc/hc.c	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -89,9 +89,9 @@
  */
 static void process_transaction_with_outcome(transaction_t * transaction,
-    usb_transaction_outcome_t outcome)
+    int outcome)
 {
 	usb_log_debug2("Transaction " TRANSACTION_FORMAT " done: %s.\n",
 	    TRANSACTION_PRINTF(*transaction),
-	    usb_str_transaction_outcome(outcome));
+	    str_error(outcome));
 	
 	transaction->callback(transaction->buffer, transaction->actual_len,
@@ -127,5 +127,5 @@
 		    TRANSACTION_PRINTF(*transaction), ports);
 
-		usb_transaction_outcome_t outcome;
+		int outcome;
 		outcome = virtdev_send_to_all(transaction);
 		
Index: uspace/drv/vhc/hc.h
===================================================================
--- uspace/drv/vhc/hc.h	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/drv/vhc/hc.h	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -47,5 +47,5 @@
  */
 typedef void (*hc_transaction_done_callback_t)(void *buffer, size_t size,
-    usb_transaction_outcome_t outcome, void *arg);
+    int outcome, void *arg);
 
 /** Pending transaction details. */
Index: uspace/drv/vhc/hub.c
===================================================================
--- uspace/drv/vhc/hub.c	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/drv/vhc/hub.c	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -41,4 +41,5 @@
 #include <driver.h>
 #include <usb/usbdrv.h>
+#include <usb/recognise.h>
 
 #include "hub.h"
@@ -93,5 +94,7 @@
 
 	devman_handle_t hub_handle;
-	usb_drv_register_child_in_devman(hc, hc_dev, hub_address, &hub_handle);
+	usb_device_register_child_in_devman(hub_address, hc_dev->handle,
+	    hc_dev, &hub_handle);
+	//usb_drv_register_child_in_devman(hc, hc_dev, hub_address, &hub_handle);
 	usb_drv_bind_address(hc, hub_address, hub_handle);
 
Index: uspace/lib/c/generic/async.c
===================================================================
--- uspace/lib/c/generic/async.c	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/lib/c/generic/async.c	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -1567,4 +1567,18 @@
 }
 
+/** Start IPC_M_DATA_READ using the async framework.
+ *
+ * @param phoneid Phone that will be used to contact the receiving side.
+ * @param dst Address of the beginning of the destination buffer.
+ * @param size Size of the destination buffer (in bytes).
+ * @param dataptr Storage of call data (arg 2 holds actual data size).
+ * @return Hash of the sent message or 0 on error.
+ */
+aid_t async_data_read(int phoneid, void *dst, size_t size, ipc_call_t *dataptr)
+{
+	return async_send_2(phoneid, IPC_M_DATA_READ, (sysarg_t) dst,
+	    (sysarg_t) size, dataptr);
+}
+
 /** Wrapper for IPC_M_DATA_READ calls using the async framework.
  *
Index: uspace/lib/c/generic/str_error.c
===================================================================
--- uspace/lib/c/generic/str_error.c	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/lib/c/generic/str_error.c	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -33,4 +33,5 @@
  */
 
+#include <errno.h>
 #include <str_error.h>
 #include <stdio.h>
@@ -63,10 +64,20 @@
 static fibril_local char noerr[NOERR_LEN];
 
-const char *str_error(const int errno)
+const char *str_error(const int e)
 {
-	if ((errno <= 0) && (errno >= MIN_ERRNO))
-		return err_desc[-errno];
+	if ((e <= 0) && (e >= MIN_ERRNO))
+		return err_desc[-e];
 	
-	snprintf(noerr, NOERR_LEN, "Unkown error code %d", errno);
+	/* Ad hoc descriptions of error codes interesting for USB. */
+	switch (e) {
+		case EBADCHECKSUM:
+			return "Bad checksum";
+		case EAGAIN:
+			return "Resource temporarily unavailable";
+		default:
+			break;
+	}
+
+	snprintf(noerr, NOERR_LEN, "Unkown error code %d", e);
 	return noerr;
 }
Index: uspace/lib/c/include/async.h
===================================================================
--- uspace/lib/c/include/async.h	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/lib/c/include/async.h	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -340,4 +340,5 @@
 	    (arg4), (answer))
 
+extern aid_t async_data_read(int, void *, size_t, ipc_call_t *);
 extern int async_data_read_start(int, void *, size_t);
 extern bool async_data_read_receive(ipc_callid_t *, size_t *);
Index: uspace/lib/c/include/errno.h
===================================================================
--- uspace/lib/c/include/errno.h	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/lib/c/include/errno.h	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -56,4 +56,7 @@
 #define EMLINK        (-266)
 
+/** Bad checksum. */
+#define EBADCHECKSUM  (-300)
+
 /** An API function is called while another blocking function is in progress. */
 #define EINPROGRESS  (-10036)
Index: uspace/lib/drv/generic/remote_usbhc.c
===================================================================
--- uspace/lib/drv/generic/remote_usbhc.c	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/lib/drv/generic/remote_usbhc.c	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -40,7 +40,8 @@
 
 #define USB_MAX_PAYLOAD_SIZE 1020
+#define HACK_MAX_PACKET_SIZE 8
+#define HACK_MAX_PACKET_SIZE_INTERRUPT_IN 4
 
 static void remote_usbhc_get_address(device_t *, void *, ipc_callid_t, ipc_call_t *);
-static void remote_usbhc_get_buffer(device_t *, void *, ipc_callid_t, ipc_call_t *);
 static void remote_usbhc_interrupt_out(device_t *, void *, ipc_callid_t, ipc_call_t *);
 static void remote_usbhc_interrupt_in(device_t *, void *, ipc_callid_t, ipc_call_t *);
@@ -64,6 +65,4 @@
 	remote_usbhc_get_address,
 
-	remote_usbhc_get_buffer,
-
 	remote_usbhc_reserve_default_address,
 	remote_usbhc_release_default_address,
@@ -98,4 +97,5 @@
 typedef struct {
 	ipc_callid_t caller;
+	ipc_callid_t data_caller;
 	void *buffer;
 	void *setup_packet;
@@ -127,4 +127,5 @@
 
 	trans->caller = caller;
+	trans->data_caller = 0;
 	trans->buffer = NULL;
 	trans->setup_packet = NULL;
@@ -155,37 +156,4 @@
 }
 
-void remote_usbhc_get_buffer(device_t *device, void *iface,
-    ipc_callid_t callid, ipc_call_t *call)
-{
-	sysarg_t buffer_hash = DEV_IPC_GET_ARG1(*call);
-	async_transaction_t * trans = (async_transaction_t *)buffer_hash;
-	if (trans == NULL) {
-		async_answer_0(callid, ENOENT);
-		return;
-	}
-	if (trans->buffer == NULL) {
-		async_answer_0(callid, EINVAL);
-		async_transaction_destroy(trans);
-		return;
-	}
-
-	ipc_callid_t cid;
-	size_t accepted_size;
-	if (!async_data_read_receive(&cid, &accepted_size)) {
-		async_answer_0(callid, EINVAL);
-		async_transaction_destroy(trans);
-		return;
-	}
-
-	if (accepted_size > trans->size) {
-		accepted_size = trans->size;
-	}
-	async_data_read_finalize(cid, trans->buffer, accepted_size);
-
-	async_answer_1(callid, EOK, accepted_size);
-
-	async_transaction_destroy(trans);
-}
-
 void remote_usbhc_reserve_default_address(device_t *device, void *iface,
     ipc_callid_t callid, ipc_call_t *call)
@@ -197,6 +165,8 @@
 		return;
 	}
-
-	int rc = usb_iface->reserve_default_address(device);
+	
+	bool full_speed = DEV_IPC_GET_ARG1(*call);
+	
+	int rc = usb_iface->reserve_default_address(device, full_speed);
 
 	async_answer_0(callid, rc);
@@ -227,7 +197,9 @@
 		return;
 	}
+	
+	bool full_speed = DEV_IPC_GET_ARG1(*call);
 
 	usb_address_t address;
-	int rc = usb_iface->request_address(device, &address);
+	int rc = usb_iface->request_address(device, full_speed, &address);
 	if (rc != EOK) {
 		async_answer_0(callid, rc);
@@ -274,5 +246,5 @@
 
 static void callback_out(device_t *device,
-    usb_transaction_outcome_t outcome, void *arg)
+    int outcome, void *arg)
 {
 	async_transaction_t *trans = (async_transaction_t *)arg;
@@ -284,10 +256,13 @@
 
 static void callback_in(device_t *device,
-    usb_transaction_outcome_t outcome, size_t actual_size, void *arg)
+    int outcome, size_t actual_size, void *arg)
 {
 	async_transaction_t *trans = (async_transaction_t *)arg;
 
-	if (outcome != USB_OUTCOME_OK) {
+	if (outcome != EOK) {
 		async_answer_0(trans->caller, outcome);
+		if (trans->data_caller) {
+			async_answer_0(trans->data_caller, EINTR);
+		}
 		async_transaction_destroy(trans);
 		return;
@@ -295,5 +270,13 @@
 
 	trans->size = actual_size;
-	async_answer_1(trans->caller, USB_OUTCOME_OK, (sysarg_t)trans);
+
+	if (trans->data_caller) {
+		async_data_read_finalize(trans->data_caller,
+		    trans->buffer, actual_size);
+	}
+
+	async_answer_0(trans->caller, EOK);
+
+	async_transaction_destroy(trans);
 }
 
@@ -345,5 +328,6 @@
 	trans->size = len;
 
-	int rc = transfer_func(device, target, buffer, len,
+	int rc = transfer_func(device, target, HACK_MAX_PACKET_SIZE,
+	    buffer, len,
 	    callback_out, trans);
 
@@ -376,4 +360,10 @@
 	};
 
+	ipc_callid_t data_callid;
+	if (!async_data_read_receive(&data_callid, &len)) {
+		async_answer_0(callid, EPARTY);
+		return;
+	}
+
 	async_transaction_t *trans = async_transaction_create(callid);
 	if (trans == NULL) {
@@ -381,8 +371,10 @@
 		return;
 	}
+	trans->data_caller = data_callid;
 	trans->buffer = malloc(len);
 	trans->size = len;
 
-	int rc = transfer_func(device, target, trans->buffer, len,
+	int rc = transfer_func(device, target, HACK_MAX_PACKET_SIZE_INTERRUPT_IN,
+	    trans->buffer, len,
 	    callback_in, trans);
 
@@ -556,4 +548,5 @@
 		.endpoint = DEV_IPC_GET_ARG2(*call)
 	};
+	size_t data_buffer_len = DEV_IPC_GET_ARG3(*call);
 
 	int rc;
@@ -562,5 +555,4 @@
 	void *data_buffer = NULL;
 	size_t setup_packet_len = 0;
-	size_t data_buffer_len = 0;
 
 	rc = async_data_write_accept(&setup_packet, false,
@@ -570,10 +562,13 @@
 		return;
 	}
-	rc = async_data_write_accept(&data_buffer, false,
-	    1, USB_MAX_PAYLOAD_SIZE, 0, &data_buffer_len);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		free(setup_packet);
-		return;
+
+	if (data_buffer_len > 0) {
+		rc = async_data_write_accept(&data_buffer, false,
+		    1, USB_MAX_PAYLOAD_SIZE, 0, &data_buffer_len);
+		if (rc != EOK) {
+			async_answer_0(callid, rc);
+			free(setup_packet);
+			return;
+		}
 	}
 
@@ -589,5 +584,5 @@
 	trans->size = data_buffer_len;
 
-	rc = usb_iface->control_write(device, target,
+	rc = usb_iface->control_write(device, target, HACK_MAX_PACKET_SIZE,
 	    setup_packet, setup_packet_len,
 	    data_buffer, data_buffer_len,
@@ -612,5 +607,4 @@
 	}
 
-	size_t data_len = DEV_IPC_GET_ARG3(*call);
 	usb_target_t target = {
 		.address = DEV_IPC_GET_ARG1(*call),
@@ -622,4 +616,5 @@
 	void *setup_packet = NULL;
 	size_t setup_packet_len = 0;
+	size_t data_len = 0;
 
 	rc = async_data_write_accept(&setup_packet, false,
@@ -627,4 +622,11 @@
 	if (rc != EOK) {
 		async_answer_0(callid, rc);
+		return;
+	}
+
+	ipc_callid_t data_callid;
+	if (!async_data_read_receive(&data_callid, &data_len)) {
+		async_answer_0(callid, EPARTY);
+		free(setup_packet);
 		return;
 	}
@@ -636,4 +638,5 @@
 		return;
 	}
+	trans->data_caller = data_callid;
 	trans->setup_packet = setup_packet;
 	trans->size = data_len;
@@ -645,5 +648,5 @@
 	}
 
-	rc = usb_iface->control_read(device, target,
+	rc = usb_iface->control_read(device, target, HACK_MAX_PACKET_SIZE,
 	    setup_packet, setup_packet_len,
 	    trans->buffer, trans->size,
Index: uspace/lib/drv/include/usbhc_iface.h
===================================================================
--- uspace/lib/drv/include/usbhc_iface.h	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/lib/drv/include/usbhc_iface.h	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -40,4 +40,5 @@
 #include "driver.h"
 #include <usb/usb.h>
+#include <bool.h>
 
 
@@ -66,21 +67,12 @@
  *   - argument #2 is target endpoint
  *   - argument #3 is buffer size
+ * - this call is immediately followed by IPC data read (async version)
  * - the call is not answered until the device returns some data (or until
  *   error occurs)
- * - if the call is answered with EOK, first argument of the answer is buffer
- *   hash that could be used to retrieve the actual data
  *
  * Some special methods (NO-DATA transactions) do not send any data. These
  * might behave as both OUT or IN transactions because communication parts
  * where actual buffers are exchanged are omitted.
- *
- * The mentioned data retrieval can be done any time after receiving EOK
- * answer to IN method.
- * This retrieval is done using the IPC_M_USBHC_GET_BUFFER where
- * the first argument is buffer hash from call answer.
- * This call must be immediately followed by data read-in and after the
- * data are transferred, the initial call (IPC_M_USBHC_GET_BUFFER)
- * is answered. Each buffer can be retrieved only once.
- *
+ **
  * For all these methods, wrap functions exists. Important rule: functions
  * for IN transactions have (as parameters) buffers where retrieved data
@@ -104,11 +96,4 @@
 	IPC_M_USBHC_GET_ADDRESS,
 
-	/** Asks for data buffer.
-	 * See explanation at usb_iface_funcs_t.
-	 * This function does not have counter part in functional interface
-	 * as it is handled by the remote part itself.
-	 */
-	IPC_M_USBHC_GET_BUFFER,
-
 
 	/** Reserve usage of default address.
@@ -223,21 +208,21 @@
 /** Callback for outgoing transfer. */
 typedef void (*usbhc_iface_transfer_out_callback_t)(device_t *,
-    usb_transaction_outcome_t, void *);
+    int, void *);
 
 /** Callback for incoming transfer. */
 typedef void (*usbhc_iface_transfer_in_callback_t)(device_t *,
-    usb_transaction_outcome_t, size_t, void *);
+    int, size_t, void *);
 
 
 /** Out transfer processing function prototype. */
-typedef int (*usbhc_iface_transfer_out_t)(device_t *, usb_target_t,
+typedef int (*usbhc_iface_transfer_out_t)(device_t *, usb_target_t, size_t,
     void *, size_t,
     usbhc_iface_transfer_out_callback_t, void *);
 
-/** Setup transfer processing function prototype. */
+/** Setup transfer processing function prototype. @deprecated */
 typedef usbhc_iface_transfer_out_t usbhc_iface_transfer_setup_t;
 
 /** In transfer processing function prototype. */
-typedef int (*usbhc_iface_transfer_in_t)(device_t *, usb_target_t,
+typedef int (*usbhc_iface_transfer_in_t)(device_t *, usb_target_t, size_t,
     void *, size_t,
     usbhc_iface_transfer_in_callback_t, void *);
@@ -247,7 +232,7 @@
 	int (*tell_address)(device_t *, devman_handle_t, usb_address_t *);
 
-	int (*reserve_default_address)(device_t *);
+	int (*reserve_default_address)(device_t *, bool);
 	int (*release_default_address)(device_t *);
-	int (*request_address)(device_t *, usb_address_t *);
+	int (*request_address)(device_t *, bool, usb_address_t *);
 	int (*bind_address)(device_t *, usb_address_t, devman_handle_t);
 	int (*release_address)(device_t *, usb_address_t);
@@ -267,8 +252,10 @@
 
 	int (*control_write)(device_t *, usb_target_t,
+	    size_t,
 	    void *, size_t, void *, size_t,
 	    usbhc_iface_transfer_out_callback_t, void *);
 
 	int (*control_read)(device_t *, usb_target_t,
+	    size_t,
 	    void *, size_t, void *, size_t,
 	    usbhc_iface_transfer_in_callback_t, void *);
Index: uspace/lib/usb/Makefile
===================================================================
--- uspace/lib/usb/Makefile	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/lib/usb/Makefile	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -39,13 +39,13 @@
 	src/drvpsync.c \
 	src/dump.c \
-	src/hcdhubd.c \
-	src/hcdrv.c \
 	src/hidparser.c \
-	src/localdrv.c \
+	src/hub.c \
 	src/pipes.c \
+	src/pipesinit.c \
+	src/pipesio.c \
 	src/recognise.c \
-	src/remotedrv.c \
 	src/request.c \
 	src/usb.c \
+	src/usbdevice.c \
 	src/usbdrvreq.c \
 	src/usbdrv.c \
Index: uspace/lib/usb/include/usb/addrkeep.h
===================================================================
--- uspace/lib/usb/include/usb/addrkeep.h	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/lib/usb/include/usb/addrkeep.h	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -1,1 +1,86 @@
-hcd.h
+/*
+ * Copyright (c) 2010 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 address keeping for host controller drivers.
+ */
+#ifndef LIBUSB_ADDRKEEP_H_
+#define LIBUSB_ADDRKEEP_H_
+
+#include <usb/usb.h>
+#include <fibril_synch.h>
+#include <devman.h>
+
+/** Info about used address. */
+typedef struct {
+	/** Linked list member. */
+	link_t link;
+	/** Address. */
+	usb_address_t address;
+	/** Corresponding devman handle. */
+	devman_handle_t devman_handle;
+} usb_address_keeping_used_t;
+
+/** Structure for keeping track of free and used USB addresses. */
+typedef struct {
+	/** Head of list of used addresses. */
+	link_t used_addresses;
+	/** Upper bound for USB addresses. */
+	usb_address_t max_address;
+	/** Mutex protecting used address. */
+	fibril_mutex_t used_addresses_guard;
+	/** Condition variable for used addresses. */
+	fibril_condvar_t used_addresses_condvar;
+
+	/** Condition variable mutex for default address. */
+	fibril_mutex_t default_condvar_guard;
+	/** Condition variable for default address. */
+	fibril_condvar_t default_condvar;
+	/** Whether is default address available. */
+	bool default_available;
+} usb_address_keeping_t;
+
+void usb_address_keeping_init(usb_address_keeping_t *, usb_address_t);
+
+void usb_address_keeping_reserve_default(usb_address_keeping_t *);
+void usb_address_keeping_release_default(usb_address_keeping_t *);
+
+usb_address_t usb_address_keeping_request(usb_address_keeping_t *);
+int usb_address_keeping_release(usb_address_keeping_t *, usb_address_t);
+void usb_address_keeping_devman_bind(usb_address_keeping_t *, usb_address_t,
+    devman_handle_t);
+usb_address_t usb_address_keeping_find(usb_address_keeping_t *,
+    devman_handle_t);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/include/usb/classes/hid.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hid.h	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/lib/usb/include/usb/classes/hid.h	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -50,4 +50,10 @@
 	USB_HIDREQ_SET_PROTOCOL = 11
 } usb_hid_request_t;
+
+/** USB/HID subclass constants. */
+typedef enum {
+	USB_HID_SUBCLASS_NONE = 0,
+	USB_HID_SUBCLASS_BOOT = 1
+} usb_hid_subclass_t;
 
 /** USB/HID interface protocols. */
Index: uspace/lib/usb/include/usb/classes/hub.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hub.h	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/lib/usb/include/usb/classes/hub.h	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -37,6 +37,4 @@
 
 #include <sys/types.h>
-#include <usb/hcdhubd.h>
-
 
 /** Hub class feature selector.
@@ -80,5 +78,5 @@
     /**
             D1...D0: Logical Power Switching Mode
-            00: Ganged power switching (all ports’ power at
+            00: Ganged power switching (all ports power at
             once)
             01: Individual port power switching
@@ -91,5 +89,5 @@
             00: Global Over-current Protection. The hub
             reports over-current as a summation of all
-            ports’ current draw, without a breakdown of
+            ports current draw, without a breakdown of
             individual port over-current status.
             01: Individual Port Over-current Protection. The
Index: pace/lib/usb/include/usb/hcd.h
===================================================================
--- uspace/lib/usb/include/usb/hcd.h	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ 	(revision )
@@ -1,86 +1,0 @@
-/*
- * Copyright (c) 2010 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
- * @brief HC driver.
- */
-#ifndef LIBUSB_HCD_H_
-#define LIBUSB_HCD_H_
-
-#include <usb/usb.h>
-#include <fibril_synch.h>
-#include <devman.h>
-
-/** Info about used address. */
-typedef struct {
-	/** Linked list member. */
-	link_t link;
-	/** Address. */
-	usb_address_t address;
-	/** Corresponding devman handle. */
-	devman_handle_t devman_handle;
-} usb_address_keeping_used_t;
-
-/** Structure for keeping track of free and used USB addresses. */
-typedef struct {
-	/** Head of list of used addresses. */
-	link_t used_addresses;
-	/** Upper bound for USB addresses. */
-	usb_address_t max_address;
-	/** Mutex protecting used address. */
-	fibril_mutex_t used_addresses_guard;
-	/** Condition variable for used addresses. */
-	fibril_condvar_t used_addresses_condvar;
-
-	/** Condition variable mutex for default address. */
-	fibril_mutex_t default_condvar_guard;
-	/** Condition variable for default address. */
-	fibril_condvar_t default_condvar;
-	/** Whether is default address available. */
-	bool default_available;
-} usb_address_keeping_t;
-
-void usb_address_keeping_init(usb_address_keeping_t *, usb_address_t);
-
-void usb_address_keeping_reserve_default(usb_address_keeping_t *);
-void usb_address_keeping_release_default(usb_address_keeping_t *);
-
-usb_address_t usb_address_keeping_request(usb_address_keeping_t *);
-int usb_address_keeping_release(usb_address_keeping_t *, usb_address_t);
-void usb_address_keeping_devman_bind(usb_address_keeping_t *, usb_address_t,
-    devman_handle_t);
-usb_address_t usb_address_keeping_find(usb_address_keeping_t *,
-    devman_handle_t);
-
-#endif
-/**
- * @}
- */
Index: pace/lib/usb/include/usb/hcdhubd.h
===================================================================
--- uspace/lib/usb/include/usb/hcdhubd.h	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ 	(revision )
@@ -1,214 +1,0 @@
-/*
- * Copyright (c) 2010 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
- * @brief HC driver and hub driver.
- */
-#ifndef LIBUSB_HCDHUBD_H_
-#define LIBUSB_HCDHUBD_H_
-
-#include <adt/list.h>
-#include <bool.h>
-#include <driver.h>
-#include <usb/usb.h>
-
-/** Endpoint properties. */
-typedef struct {
-	/** Endpoint number. */
-	usb_endpoint_t endpoint;
-	/** Transfer type. */
-	usb_transfer_type_t transfer_type;
-	/** Endpoint direction. */
-	usb_direction_t direction;
-	/** Data toggle bit. */
-	int data_toggle;
-} usb_hc_endpoint_info_t;
-
-/** Information about attached USB device. */
-typedef struct {
-	/** Assigned address. */
-	usb_address_t address;
-	/** Number of endpoints. */
-	size_t endpoint_count;
-	/** Endpoint properties. */
-	usb_hc_endpoint_info_t *endpoints;
-	/** Link to other attached devices of the same HC. */
-	link_t link;
-} usb_hcd_attached_device_info_t;
-
-
-/** Host controller device. */
-typedef struct usb_hc_device usb_hc_device_t;
-
-/** Callback for OUT transfers. */
-typedef void (*usb_hcd_transfer_callback_out_t)
-    (usb_hc_device_t *, usb_transaction_outcome_t, void *);
-
-/** Callback for IN transfers. */
-typedef void (*usb_hcd_transfer_callback_in_t)
-    (usb_hc_device_t *, size_t, usb_transaction_outcome_t, void *);
-
-
-/** Transfer functions provided by each USB host controller driver. */
-typedef struct {
-	/** OUT transfer.
-	 * @param hc Host controller that shall enqueue the transfer.
-	 * @param dev Target device.
-	 * @param ep Target endpoint.
-	 * @param buffer Buffer to be sent.
-	 * @param size Buffer size.
-	 * @param callback Callback after transfer was processed by hardware.
-	 * @param arg Callback argument.
-	 */
-	int (*transfer_out)(usb_hc_device_t *hc,
-	    usb_hcd_attached_device_info_t *dev, usb_hc_endpoint_info_t *ep,
-	    void *buffer, size_t size,
-	    usb_hcd_transfer_callback_out_t callback, void *arg);
-
-	/** SETUP transfer. */
-	int (*transfer_setup)(usb_hc_device_t *,
-	    usb_hcd_attached_device_info_t *, usb_hc_endpoint_info_t *,
-	    void *, size_t,
-	    usb_hcd_transfer_callback_out_t, void *);
-
-	/** IN transfer. */
-	int (*transfer_in)(usb_hc_device_t *,
-	    usb_hcd_attached_device_info_t *, usb_hc_endpoint_info_t *,
-	    void *, size_t,
-	    usb_hcd_transfer_callback_in_t, void *);
-} usb_hcd_transfer_ops_t;
-
-/**
- * @brief structure holding information about free and used addresses
- *
- * This structure should not be used outside usb hcd driver.
- * You better consider it to be 'private'.
- */
-typedef struct {
-	/** lower bound included in the interval */
-	usb_address_t lower_bound;
-
-	/** upper bound, excluded from the interval */
-	usb_address_t upper_bound;
-
-	/** */
-	link_t link;
-}usb_address_list_t;
-
-struct usb_hc_device {
-	/** Transfer operations. */
-	usb_hcd_transfer_ops_t *transfer_ops;
-
-	/** Custom HC data. */
-	void *data;
-
-	/** Generic device entry (read-only). */
-	device_t *generic;
-
-	/** List of attached devices. */
-	link_t attached_devices;
-
-	/** List of hubs operating from this HC. */
-	link_t hubs;
-
-	/** Structure with free and used addresses */
-	link_t addresses;
-
-	/** Link to other driven HCs. */
-	link_t link;
-};
-
-/** Host controller driver. */
-typedef struct {
-	/** Driver name. */
-	const char *name;
-	/** Callback when device (host controller) is added. */
-	int (*add_hc)(usb_hc_device_t *device);
-} usb_hc_driver_t;
-
-
-int usb_hcd_main(usb_hc_driver_t *);
-int usb_hcd_add_root_hub(device_t *dev);
-
-/**
- * find first not yet used address on this host controller and use it
- * @param this_hcd
- * @return number in the range of allowed usb addresses or
- *     a negative number if not succesful
- */
-usb_address_t usb_use_free_address(usb_hc_device_t * this_hcd);
-
-/**
- * @brief free the address in the address space of this hcd.
- *
- * if address is not used, nothing happens
- * @param this_hcd
- * @param addr
- */
-void usb_free_used_address(usb_hc_device_t * this_hcd, usb_address_t addr );
-
-
-/*
- * Functions to be used by drivers within same task as the HC driver.
- * This will probably include only hub drivers.
- */
-
-device_t *usb_hc_connect(device_t *);
-
-int usb_hc_async_interrupt_out(usb_hc_device_t *, usb_target_t,
-    void *, size_t, usb_handle_t *);
-int usb_hc_async_interrupt_in(usb_hc_device_t *, usb_target_t,
-    void *, size_t, size_t *, usb_handle_t *);
-
-int usb_hc_async_control_write_setup(usb_hc_device_t *, usb_target_t,
-    void *, size_t, usb_handle_t *);
-int usb_hc_async_control_write_data(usb_hc_device_t *, usb_target_t,
-    void *, size_t, usb_handle_t *);
-int usb_hc_async_control_write_status(usb_hc_device_t *, usb_target_t,
-    usb_handle_t *);
-
-int usb_hc_async_control_read_setup(usb_hc_device_t *, usb_target_t,
-    void *, size_t, usb_handle_t *);
-int usb_hc_async_control_read_data(usb_hc_device_t *, usb_target_t,
-    void *, size_t, size_t *, usb_handle_t *);
-int usb_hc_async_control_read_status(usb_hc_device_t *, usb_target_t,
-    usb_handle_t *);
-
-int usb_hc_async_wait_for(usb_handle_t);
-
-int usb_hc_add_child_device(device_t *, const char *, const char *, bool);
-
-
-/**
- * @}
- */
-
-#endif
Index: uspace/lib/usb/include/usb/hub.h
===================================================================
--- uspace/lib/usb/include/usb/hub.h	(revision 50ba203e98ce570f05993da83249a116cfffceab)
+++ uspace/lib/usb/include/usb/hub.h	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -0,0 +1,65 @@
+/*
+ * 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
+ * Functions needed by hub drivers.
+ */
+#ifndef LIBUSB_HUB_H_
+#define LIBUSB_HUB_H_
+
+#include <sys/types.h>
+#include <usb/usbdevice.h>
+
+/** Info about device attached to host controller.
+ *
+ * This structure exists only to keep the same signature of
+ * usb_hc_register_device() when more properties of the device
+ * would have to be passed to the host controller.
+ */
+typedef struct {
+	/** Device address. */
+	usb_address_t address;
+	/** Devman handle of the device. */
+	devman_handle_t handle;
+} usb_hc_attached_device_t;
+
+int usb_hc_reserve_default_address(usb_hc_connection_t *, bool);
+int usb_hc_release_default_address(usb_hc_connection_t *);
+
+usb_address_t usb_hc_request_address(usb_hc_connection_t *, bool);
+int usb_hc_register_device(usb_hc_connection_t *,
+    const usb_hc_attached_device_t *);
+int usb_hc_unregister_device(usb_hc_connection_t *, usb_address_t);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/include/usb/pipes.h
===================================================================
--- uspace/lib/usb/include/usb/pipes.h	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/lib/usb/include/usb/pipes.h	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -31,5 +31,5 @@
  */
 /** @file
- * Communication between device drivers and host controller driver.
+ * USB pipes representation.
  */
 #ifndef LIBUSB_PIPES_H_
@@ -38,4 +38,6 @@
 #include <sys/types.h>
 #include <usb/usb.h>
+#include <usb/usbdevice.h>
+#include <usb/descriptor.h>
 #include <ipc/devman.h>
 #include <driver.h>
@@ -73,4 +75,7 @@
 	usb_direction_t direction;
 
+	/** Maximum packet size for the endpoint. */
+	size_t max_packet_size;
+
 	/** Phone to the host controller.
 	 * Negative when no session is active.
@@ -80,4 +85,36 @@
 
 
+/** Description of endpoint characteristics. */
+typedef struct {
+	/** Transfer type (e.g. control or interrupt). */
+	usb_transfer_type_t transfer_type;
+	/** Transfer direction (to or from a device). */
+	usb_direction_t direction;
+	/** Interface class this endpoint belongs to (-1 for any). */
+	int interface_class;
+	/** Interface subclass this endpoint belongs to (-1 for any). */
+	int interface_subclass;
+	/** Interface protocol this endpoint belongs to (-1 for any). */
+	int interface_protocol;
+	/** Extra endpoint flags. */
+	unsigned int flags;
+} usb_endpoint_description_t;
+
+/** Mapping of endpoint pipes and endpoint descriptions. */
+typedef struct {
+	/** Endpoint pipe. */
+	usb_endpoint_pipe_t *pipe;
+	/** Endpoint description. */
+	const usb_endpoint_description_t *description;
+	/** Found descriptor fitting the description. */
+	usb_standard_endpoint_descriptor_t *descriptor;
+	/** Interface the endpoint belongs to. */
+	usb_standard_interface_descriptor_t *interface;
+	/** Whether the endpoint was actually found. */
+	bool present;
+} usb_endpoint_mapping_t;
+
+int usb_device_connection_initialize_on_default_address(
+    usb_device_connection_t *, usb_hc_connection_t *);
 int usb_device_connection_initialize_from_device(usb_device_connection_t *,
     device_t *);
@@ -87,7 +124,9 @@
 int usb_endpoint_pipe_initialize(usb_endpoint_pipe_t *,
     usb_device_connection_t *,
-    usb_endpoint_t, usb_transfer_type_t, usb_direction_t);
+    usb_endpoint_t, usb_transfer_type_t, size_t, usb_direction_t);
 int usb_endpoint_pipe_initialize_default_control(usb_endpoint_pipe_t *,
     usb_device_connection_t *);
+int usb_endpoint_pipe_initialize_from_configuration(usb_endpoint_mapping_t *,
+    size_t, uint8_t *, size_t, usb_device_connection_t *);
 
 
@@ -103,18 +142,4 @@
     void *, size_t);
 
-
-
-int usb_endpoint_pipe_async_read(usb_endpoint_pipe_t *, void *, size_t,
-    size_t *, usb_handle_t *);
-int usb_endpoint_pipe_async_write(usb_endpoint_pipe_t *, void *, size_t,
-    usb_handle_t *);
-
-int usb_endpoint_pipe_async_control_read(usb_endpoint_pipe_t *, void *, size_t,
-    void *, size_t, size_t *, usb_handle_t *);
-int usb_endpoint_pipe_async_control_write(usb_endpoint_pipe_t *, void *, size_t,
-    void *, size_t, usb_handle_t *);
-
-int usb_endpoint_pipe_wait_for(usb_endpoint_pipe_t *, usb_handle_t);
-
 #endif
 /**
Index: uspace/lib/usb/include/usb/recognise.h
===================================================================
--- uspace/lib/usb/include/usb/recognise.h	(revision 50ba203e98ce570f05993da83249a116cfffceab)
+++ uspace/lib/usb/include/usb/recognise.h	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -0,0 +1,51 @@
+/*
+ * 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 recognition.
+ */
+#ifndef LIBUSB_RECOGNISE_H_
+#define LIBUSB_RECOGNISE_H_
+
+#include <sys/types.h>
+#include <usb/usb.h>
+#include <usb/pipes.h>
+#include <ipc/devman.h>
+
+int usb_device_create_match_ids(usb_endpoint_pipe_t *, match_id_list_t *);
+
+int usb_device_register_child_in_devman(usb_address_t address, devman_handle_t hc_handle,
+    device_t *parent, devman_handle_t *child_handle);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/include/usb/usb.h
===================================================================
--- uspace/lib/usb/include/usb/usb.h	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/lib/usb/include/usb/usb.h	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -83,13 +83,4 @@
 } usb_request_recipient_t;
 
-/** USB transaction outcome. */
-typedef enum {
-	USB_OUTCOME_OK,
-	USB_OUTCOME_CRCERROR,
-	USB_OUTCOME_BABBLE
-} usb_transaction_outcome_t;
-
-const char * usb_str_transaction_outcome(usb_transaction_outcome_t o);
-
 /** USB address type.
  * Negative values could be used to indicate error.
Index: uspace/lib/usb/include/usb/usbdevice.h
===================================================================
--- uspace/lib/usb/include/usb/usbdevice.h	(revision 50ba203e98ce570f05993da83249a116cfffceab)
+++ uspace/lib/usb/include/usb/usbdevice.h	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -0,0 +1,67 @@
+/*
+ * 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
+ * General communication between device drivers and host controller driver.
+ */
+#ifndef LIBUSB_USBDEVICE_H_
+#define LIBUSB_USBDEVICE_H_
+
+#include <sys/types.h>
+#include <ipc/devman.h>
+#include <driver.h>
+#include <bool.h>
+#include <usb/usb.h>
+
+/** Connection to the host controller driver. */
+typedef struct {
+	/** Devman handle of the host controller. */
+	devman_handle_t hc_handle;
+	/** Phone to the host controller. */
+	int hc_phone;
+} usb_hc_connection_t;
+
+int usb_hc_find(devman_handle_t, devman_handle_t *);
+
+int usb_hc_connection_initialize_from_device(usb_hc_connection_t *,
+    device_t *);
+int usb_hc_connection_initialize(usb_hc_connection_t *, devman_handle_t);
+
+int usb_hc_connection_open(usb_hc_connection_t *);
+bool usb_hc_connection_is_opened(const usb_hc_connection_t *);
+int usb_hc_connection_close(usb_hc_connection_t *);
+
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/include/usb/usbdrv.h
===================================================================
--- uspace/lib/usb/include/usb/usbdrv.h	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/lib/usb/include/usb/usbdrv.h	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -106,8 +106,4 @@
     const void *, size_t);
 
-int usb_drv_create_device_match_ids(int, match_id_list_t *, usb_address_t);
-int usb_drv_register_child_in_devman(int, device_t *, usb_address_t,
-    devman_handle_t *);
-
 
 #endif
Index: uspace/lib/usb/src/addrkeep.c
===================================================================
--- uspace/lib/usb/src/addrkeep.c	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/lib/usb/src/addrkeep.c	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -33,5 +33,5 @@
  * @brief Address keeping.
  */
-#include <usb/hcd.h>
+#include <usb/addrkeep.h>
 #include <errno.h>
 #include <assert.h>
Index: uspace/lib/usb/src/dump.c
===================================================================
--- uspace/lib/usb/src/dump.c	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/lib/usb/src/dump.c	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -147,6 +147,6 @@
 	PRINTLINE("bDeviceProtocol = 0x%02x", d->device_protocol);
 	PRINTLINE("bMaxPacketSize0 = %d", d->max_packet_size);
-	PRINTLINE("idVendor = %d", d->vendor_id);
-	PRINTLINE("idProduct = %d", d->product_id);
+	PRINTLINE("idVendor = 0x%04x", d->vendor_id);
+	PRINTLINE("idProduct = 0x%04x", d->product_id);
 	PRINTLINE("bcdDevice = %d", d->device_version);
 	PRINTLINE("iManufacturer = %d", d->str_manufacturer);
Index: pace/lib/usb/src/hcdhubd.c
===================================================================
--- uspace/lib/usb/src/hcdhubd.c	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ 	(revision )
@@ -1,341 +1,0 @@
-/*
- * Copyright (c) 2010 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
- * @brief Common stuff for both HC driver and hub driver.
- */
-#include <usb/hcdhubd.h>
-#include <usb/devreq.h>
-#include <usbhc_iface.h>
-#include <usb_iface.h>
-#include <usb/descriptor.h>
-#include <driver.h>
-#include <bool.h>
-#include <errno.h>
-#include <str_error.h>
-#include <usb/classes/hub.h>
-
-#include "hcdhubd_private.h"
-
-
-static int usb_iface_get_hc_handle(device_t *dev, devman_handle_t *handle)
-{
-	assert(dev);
-	assert(dev->parent != NULL);
-
-	device_t *parent = dev->parent;
-
-	if (parent->ops && parent->ops->interfaces[USB_DEV_IFACE]) {
-		usb_iface_t *usb_iface
-		    = (usb_iface_t *) parent->ops->interfaces[USB_DEV_IFACE];
-		assert(usb_iface != NULL);
-		if (usb_iface->get_hc_handle) {
-			int rc = usb_iface->get_hc_handle(parent, handle);
-			return rc;
-		}
-	}
-
-	return ENOTSUP;
-}
-
-static usb_iface_t usb_iface = {
-	.get_hc_handle = usb_iface_get_hc_handle
-};
-
-static device_ops_t child_ops = {
-	.interfaces[USB_DEV_IFACE] = &usb_iface
-};
-
-/** Callback when new device is detected and must be handled by this driver.
- *
- * @param dev New device.
- * @return Error code.
- */
-static int add_device(device_t *dev) {
-	return ENOTSUP;
-}
-
-/** Operations for combined HC and HUB driver. */
-static driver_ops_t hc_driver_generic_ops = {
-	.add_device = add_device
-};
-
-/** Combined HC and HUB driver. */
-static driver_t hc_driver_generic = {
-	.driver_ops = &hc_driver_generic_ops
-};
-
-/** Main USB host controller driver routine.
- *
- * @see driver_main
- *
- * @param hc Host controller driver.
- * @return Error code.
- */
-int usb_hcd_main(usb_hc_driver_t *hc) {
-	hc_driver = hc;
-	hc_driver_generic.name = hc->name;
-
-	/*
-	 * Run the device driver framework.
-	 */
-	return driver_main(&hc_driver_generic);
-}
-
-/** Add a root hub for given host controller.
- * This function shall be called only once for each host controller driven
- * by this driver.
- * It takes care of creating child device - hub - that will be driven by
- * this task.
- *
- * @param dev Host controller device.
- * @return Error code.
- */
-int usb_hcd_add_root_hub(device_t *dev)
-{
-	char *id;
-	int rc = asprintf(&id, "usb&hub");
-	if (rc <= 0) {
-		return rc;
-	}
-
-	rc = usb_hc_add_child_device(dev, USB_HUB_DEVICE_NAME, id, true);
-	if (rc != EOK) {
-		free(id);
-	}
-
-	return rc;
-}
-
-/** Info about child device. */
-struct child_device_info {
-	device_t *parent;
-	const char *name;
-	const char *match_id;
-};
-
-/** Adds a child device fibril worker. */
-static int fibril_add_child_device(void *arg) {
-	struct child_device_info *child_info
-			= (struct child_device_info *) arg;
-	int rc;
-
-	async_usleep(1000);
-
-	device_t *child = create_device();
-	match_id_t *match_id = NULL;
-
-	if (child == NULL) {
-		rc = ENOMEM;
-		goto failure;
-	}
-	child->name = child_info->name;
-	child->parent = child_info->parent;
-	child->ops = &child_ops;
-
-	match_id = create_match_id();
-	if (match_id == NULL) {
-		rc = ENOMEM;
-		goto failure;
-	}
-	match_id->id = child_info->match_id;
-	match_id->score = 10;
-	add_match_id(&child->match_ids, match_id);
-
-	printf("%s: adding child device `%s' with match \"%s\"\n",
-			hc_driver->name, child->name, match_id->id);
-	rc = child_device_register(child, child_info->parent);
-	printf("%s: child device `%s' registration: %s\n",
-			hc_driver->name, child->name, str_error(rc));
-
-	if (rc != EOK) {
-		goto failure;
-	}
-
-	goto leave;
-
-failure:
-	if (child != NULL) {
-		child->name = NULL;
-		delete_device(child);
-	}
-
-	if (match_id != NULL) {
-		match_id->id = NULL;
-		delete_match_id(match_id);
-	}
-
-leave:
-	free(arg);
-	return EOK;
-}
-
-/** Adds a child.
- * Due to deadlock in devman when parent registers child that oughts to be
- * driven by the same task, the child adding is done in separate fibril.
- * Not optimal, but it works.
- * Update: not under all circumstances the new fibril is successful either.
- * Thus the last parameter to let the caller choose.
- *
- * @param parent Parent device.
- * @param name Device name.
- * @param match_id Match id.
- * @param create_fibril Whether to run the addition in new fibril.
- * @return Error code.
- */
-int usb_hc_add_child_device(device_t *parent, const char *name,
-		const char *match_id, bool create_fibril) {
-	printf("%s: about to add child device `%s' (%s)\n", hc_driver->name,
-			name, match_id);
-
-	/*
-	 * Seems that creating fibril which postpones the action
-	 * is the best solution.
-	 */
-	create_fibril = true;
-
-	struct child_device_info *child_info
-			= malloc(sizeof (struct child_device_info));
-
-	child_info->parent = parent;
-	child_info->name = name;
-	child_info->match_id = match_id;
-
-	if (create_fibril) {
-		fid_t fibril = fibril_create(fibril_add_child_device, child_info);
-		if (!fibril) {
-			return ENOMEM;
-		}
-		fibril_add_ready(fibril);
-	} else {
-		fibril_add_child_device(child_info);
-	}
-
-	return EOK;
-}
-
-/** Tell USB address of given device.
- *
- * @param handle Devman handle of the device.
- * @return USB device address or error code.
- */
-usb_address_t usb_get_address_by_handle(devman_handle_t handle) {
-	/* TODO: search list of attached devices. */
-	return ENOENT;
-}
-
-usb_address_t usb_use_free_address(usb_hc_device_t * this_hcd) {
-	//is there free address?
-	link_t * addresses = &this_hcd->addresses;
-	if (list_empty(addresses)) return -1;
-	link_t * link_addr = addresses;
-	bool found = false;
-	usb_address_list_t * range = NULL;
-	while (!found) {
-		link_addr = link_addr->next;
-		if (link_addr == addresses) return -2;
-		range = list_get_instance(link_addr,
-				usb_address_list_t, link);
-		if (range->upper_bound - range->lower_bound > 0) {
-			found = true;
-		}
-	}
-	//now we have interval
-	int result = range->lower_bound;
-	++(range->lower_bound);
-	if (range->upper_bound - range->lower_bound == 0) {
-		list_remove(&range->link);
-		free(range);
-	}
-	return result;
-}
-
-void usb_free_used_address(usb_hc_device_t * this_hcd, usb_address_t addr) {
-	//check range
-	if (addr < usb_lowest_address || addr > usb_highest_address)
-		return;
-	link_t * addresses = &this_hcd->addresses;
-	link_t * link_addr = addresses;
-	//find 'good' interval
-	usb_address_list_t * found_range = NULL;
-	bool found = false;
-	while (!found) {
-		link_addr = link_addr->next;
-		if (link_addr == addresses) {
-			found = true;
-		} else {
-			usb_address_list_t * range = list_get_instance(link_addr,
-					usb_address_list_t, link);
-			if (	(range->lower_bound - 1 == addr) ||
-					(range->upper_bound == addr)) {
-				found = true;
-				found_range = range;
-			}
-			if (range->lower_bound - 1 > addr) {
-				found = true;
-			}
-
-		}
-	}
-	if (found_range == NULL) {
-		//no suitable range found
-		usb_address_list_t * result_range =
-				(usb_address_list_t*) malloc(sizeof (usb_address_list_t));
-		result_range->lower_bound = addr;
-		result_range->upper_bound = addr + 1;
-		list_insert_before(&result_range->link, link_addr);
-	} else {
-		//we have good range
-		if (found_range->lower_bound - 1 == addr) {
-			--found_range->lower_bound;
-		} else {
-			//only one possible case
-			++found_range->upper_bound;
-			if (found_range->link.next != addresses) {
-				usb_address_list_t * next_range =
-						list_get_instance( &found_range->link.next,
-						usb_address_list_t, link);
-				//check neighbour range
-				if (next_range->lower_bound == addr + 1) {
-					//join ranges
-					found_range->upper_bound = next_range->upper_bound;
-					list_remove(&next_range->link);
-					free(next_range);
-				}
-			}
-		}
-	}
-
-}
-
-/**
- * @}
- */
Index: pace/lib/usb/src/hcdrv.c
===================================================================
--- uspace/lib/usb/src/hcdrv.c	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ 	(revision )
@@ -1,127 +1,0 @@
-/*
- * Copyright (c) 2010 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
- * @brief HC driver.
- */
-#include <usb/hcdhubd.h>
-#include <usb/devreq.h>
-#include <usbhc_iface.h>
-#include <usb/descriptor.h>
-#include <driver.h>
-#include <bool.h>
-#include <errno.h>
-#include <usb/classes/hub.h>
-
-#include "hcdhubd_private.h"
-
-/** List of handled host controllers. */
-LIST_INITIALIZE(hc_list);
-
-/* Fake driver to have the name item initialized. */
-static usb_hc_driver_t hc_driver_fake = {
-	.name = "HCD",
-};
-
-/** Our HC driver. */
-usb_hc_driver_t *hc_driver = &hc_driver_fake;
-
-int usb_lowest_address = 1;
-
-int usb_highest_address = 255;
-
-static device_ops_t usb_device_ops = {
-	.interfaces[USBHC_DEV_IFACE] = &usbhc_interface
-};
-
-
-void usb_create_address_list(usb_hc_device_t * hcd){
-	list_initialize(&hcd->addresses);
-	usb_address_list_t * range =
-			(usb_address_list_t*)malloc(sizeof(usb_address_list_t));
-	range->lower_bound = usb_lowest_address;
-	range->upper_bound = usb_highest_address + 1;
-	list_append(&range->link, &hcd->addresses);
-}
-
-static usb_hc_device_t *usb_hc_device_create(device_t *dev) {
-	usb_hc_device_t *hc_dev = malloc(sizeof (usb_hc_device_t));
-
-	list_initialize(&hc_dev->link);
-	list_initialize(&hc_dev->hubs);
-	usb_create_address_list(hc_dev);
-	list_initialize(&hc_dev->attached_devices);
-	hc_dev->transfer_ops = NULL;
-
-	hc_dev->generic = dev;
-	dev->ops = &usb_device_ops;
-	hc_dev->generic->driver_data = hc_dev;
-
-	return hc_dev;
-}
-
-int usb_add_hc_device(device_t *dev)
-{
-	return ENOTSUP;
-	usb_hc_device_t *hc_dev = usb_hc_device_create(dev);
-
-	int rc = hc_driver->add_hc(hc_dev);
-	if (rc != EOK) {
-		free(hc_dev);
-		return rc;
-	}
-
-	/*
-	 * FIXME: The following line causes devman to hang.
-	 * Will investigate later why.
-	 */
-	// add_device_to_class(dev, "usbhc");
-
-	list_append(&hc_dev->link, &hc_list);
-
-	/*
-	 * FIXME: the following is a workaround to force loading of USB
-	 * keyboard driver.
-	 * Will be removed as soon as the hub driver is completed and
-	 * can detect connected devices.
-	 */
-	printf("%s: trying to add USB HID child device...\n", hc_driver->name);
-	rc = usb_hc_add_child_device(dev, USB_KBD_DEVICE_NAME, "usb&hid", false);
-	if (rc != EOK) {
-		printf("%s: adding USB HID child failed...\n", hc_driver->name);
-	}
-
-	return EOK;
-}
-
-/**
- * @}
- */
Index: uspace/lib/usb/src/hub.c
===================================================================
--- uspace/lib/usb/src/hub.c	(revision 50ba203e98ce570f05993da83249a116cfffceab)
+++ uspace/lib/usb/src/hub.c	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -0,0 +1,142 @@
+/*
+ * 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
+ * Functions needed by hub drivers.
+ */
+#include <usb/hub.h>
+#include <usbhc_iface.h>
+#include <errno.h>
+
+/** Check that HC connection is alright.
+ *
+ * @param conn Connection to be checked.
+ */
+#define CHECK_CONNECTION(conn) \
+	do { \
+		assert((conn)); \
+		if (!usb_hc_connection_is_opened((conn))) { \
+			return ENOENT; \
+		} \
+	} while (false)
+
+
+/** Tell host controller to reserve default address.
+ *
+ * @param connection Opened connection to host controller.
+ * @return Error code.
+ */
+int usb_hc_reserve_default_address(usb_hc_connection_t *connection,
+    bool full_speed)
+{
+	CHECK_CONNECTION(connection);
+
+	return async_req_2_0(connection->hc_phone,
+	    DEV_IFACE_ID(USBHC_DEV_IFACE),
+	    IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS, full_speed);
+}
+
+/** Tell host controller to release default address.
+ *
+ * @param connection Opened connection to host controller.
+ * @return Error code.
+ */
+int usb_hc_release_default_address(usb_hc_connection_t *connection)
+{
+	CHECK_CONNECTION(connection);
+
+	return async_req_1_0(connection->hc_phone,
+	    DEV_IFACE_ID(USBHC_DEV_IFACE),
+	    IPC_M_USBHC_RELEASE_DEFAULT_ADDRESS);
+}
+
+/** Ask host controller for free address assignment.
+ *
+ * @param connection Opened connection to host controller.
+ * @return Assigned USB address or negative error code.
+ */
+usb_address_t usb_hc_request_address(usb_hc_connection_t *connection,
+    bool full_speed)
+{
+	CHECK_CONNECTION(connection);
+
+	sysarg_t address;
+	int rc = async_req_2_1(connection->hc_phone,
+	    DEV_IFACE_ID(USBHC_DEV_IFACE),
+	    IPC_M_USBHC_REQUEST_ADDRESS, full_speed,
+	    &address);
+	if (rc != EOK) {
+		return (usb_address_t) rc;
+	} else {
+		return (usb_address_t) address;
+	}
+}
+
+/** Inform host controller about new device.
+ *
+ * @param connection Opened connection to host controller.
+ * @param attached_device Information about the new device.
+ * @return Error code.
+ */
+int usb_hc_register_device(usb_hc_connection_t * connection,
+    const usb_hc_attached_device_t *attached_device)
+{
+	CHECK_CONNECTION(connection);
+	if (attached_device == NULL) {
+		return EBADMEM;
+	}
+
+	return async_req_3_0(connection->hc_phone,
+	    DEV_IFACE_ID(USBHC_DEV_IFACE),
+	    IPC_M_USBHC_BIND_ADDRESS,
+	    attached_device->address, attached_device->handle);
+}
+
+/** Inform host controller about device removal.
+ *
+ * @param connection Opened connection to host controller.
+ * @param address Address of the device that is being removed.
+ * @return Error code.
+ */
+int usb_hc_unregister_device(usb_hc_connection_t *connection,
+    usb_address_t address)
+{
+	CHECK_CONNECTION(connection);
+
+	return async_req_2_0(connection->hc_phone,
+	    DEV_IFACE_ID(USBHC_DEV_IFACE),
+	    IPC_M_USBHC_RELEASE_ADDRESS, address);
+}
+
+
+/**
+ * @}
+ */
Index: pace/lib/usb/src/localdrv.c
===================================================================
--- uspace/lib/usb/src/localdrv.c	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ 	(revision )
@@ -1,414 +1,0 @@
-/*
- * Copyright (c) 2010 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
- * @brief Driver communication for local drivers (hubs).
- */
-#include <usb/hcdhubd.h>
-#include <usbhc_iface.h>
-#include <driver.h>
-#include <bool.h>
-#include <errno.h>
-
-/** Find host controller when handled by current task.
- *
- * @param dev Device asking for connection.
- * @return Device structure corresponding to parent host controller.
- * @retval NULL Corresponding host controller not found.
- */
-device_t *usb_hc_connect(device_t *dev)
-{
-	/*
-	 * FIXME: this will not work when some hub on the path is
-	 * not driven by the same task.
-	 */
-	device_t *parent = dev;
-	while (parent->parent != NULL) {
-		parent = parent->parent;
-	}
-	
-	if (dev == parent) {
-		printf("FIXME in %s:%d encountered!\n", __FILE__, __LINE__);
-		parent = NULL;
-	}
-
-	return parent;
-}
-
-/** Information about pending transaction on HC. */
-typedef struct {
-	/** Storage for actual number of bytes transferred. */
-	size_t *size_transferred;
-
-	/** Target device. */
-	usb_hcd_attached_device_info_t *device;
-	/** Target endpoint. */
-	usb_hc_endpoint_info_t *endpoint;
-
-	/** Guard for the condition variable. */
-	fibril_mutex_t condvar_guard;
-	/** Condition variable for waiting for done. */
-	fibril_condvar_t condvar;
-
-	/** Flag whether the transfer is done. */
-	bool done;
-} transfer_info_t;
-
-/** Create new transfer info.
- *
- * @param device Attached device.
- * @param endpoint Endpoint.
- * @return Transfer info with pre-filled values.
- */
-static transfer_info_t *transfer_info_create(
-    usb_hcd_attached_device_info_t *device, usb_hc_endpoint_info_t *endpoint)
-{
-	transfer_info_t *transfer = malloc(sizeof(transfer_info_t));
-
-	transfer->size_transferred = NULL;
-	fibril_condvar_initialize(&transfer->condvar);
-	fibril_mutex_initialize(&transfer->condvar_guard);
-	transfer->done = false;
-
-	transfer->device = device;
-	transfer->endpoint = endpoint;
-
-	return transfer;
-}
-
-/** Destroy transfer info.
- *
- * @param transfer Transfer to be destroyed.
- */
-static void transfer_info_destroy(transfer_info_t *transfer)
-{
-	free(transfer->device);
-	free(transfer->endpoint);
-	free(transfer);
-}
-
-/** Create info about attached device.
- *
- * @param address Device address.
- * @return Device info structure.
- */
-static usb_hcd_attached_device_info_t *create_attached_device_info(
-    usb_address_t address)
-{
-	usb_hcd_attached_device_info_t *dev
-	    = malloc(sizeof(usb_hcd_attached_device_info_t));
-
-	dev->address = address;
-	dev->endpoint_count = 0;
-	dev->endpoints = NULL;
-	list_initialize(&dev->link);
-
-	return dev;
-}
-
-/** Create info about device endpoint.
- *
- * @param endpoint Endpoint number.
- * @param direction Endpoint data direction.
- * @param transfer_type Transfer type of the endpoint.
- * @return Endpoint info structure.
- */
-static usb_hc_endpoint_info_t *create_endpoint_info(usb_endpoint_t endpoint,
-    usb_direction_t direction, usb_transfer_type_t transfer_type)
-{
-	usb_hc_endpoint_info_t *ep = malloc(sizeof(usb_hc_endpoint_info_t));
-	ep->data_toggle = 0;
-	ep->direction = direction;
-	ep->transfer_type = transfer_type;
-	ep->endpoint = endpoint;
-
-	return ep;
-}
-
-/** Marks given transfer as done.
- *
- * @param transfer Transfer to be completed.
- */
-static void transfer_mark_complete(transfer_info_t *transfer)
-{
-	fibril_mutex_lock(&transfer->condvar_guard);
-	transfer->done = true;
-	fibril_condvar_signal(&transfer->condvar);
-	fibril_mutex_unlock(&transfer->condvar_guard);
-}
-
-/** Callback for OUT transfers.
- *
- * @param hc Host controller that processed the transfer.
- * @param outcome Transfer outcome.
- * @param arg Custom argument.
- */
-static void callback_out(usb_hc_device_t *hc,
-    usb_transaction_outcome_t outcome, void *arg)
-{
-	transfer_info_t *transfer = (transfer_info_t *) arg;
-
-	/*
-	 * For out transfers, marking them complete is enough.
-	 * No other processing is necessary.
-	 */
-	transfer_mark_complete(transfer);
-}
-
-/** Callback for IN transfers.
- *
- * @param hc Host controller that processed the transfer.
- * @param actual_size Number of actually transferred bytes.
- * @param outcome Transfer outcome.
- * @param arg Custom argument.
- */
-static void callback_in(usb_hc_device_t *hc,
-    size_t actual_size, usb_transaction_outcome_t outcome, void *arg)
-{
-	transfer_info_t *transfer = (transfer_info_t *) arg;
-
-	/*
-	 * Set the number of actually transferred bytes and
-	 * mark the transfer as complete.
-	 */
-	if (transfer->size_transferred != NULL) {
-		*transfer->size_transferred = actual_size;
-	}
-
-	transfer_mark_complete(transfer);
-}
-
-static int async_transfer_out(usb_hc_device_t *hc,
-    usb_target_t target, usb_transfer_type_t transfer_type,
-    void *data, size_t size,
-    usb_handle_t *handle)
-{
-	if ((hc->transfer_ops == NULL)
-	    || (hc->transfer_ops->transfer_out == NULL)) {
-		return ENOTSUP;
-	}
-
-	/* This creation of the device on the fly is just a workaround. */
-
-	transfer_info_t *transfer = transfer_info_create(
-	    create_attached_device_info(target.address),
-	    create_endpoint_info(target.endpoint,
-		USB_DIRECTION_OUT, transfer_type));
-
-	int rc = hc->transfer_ops->transfer_out(hc,
-	    transfer->device, transfer->endpoint,
-	    data, size,
-	    callback_out, transfer);
-
-	if (rc != EOK) {
-		transfer_info_destroy(transfer);
-		return rc;
-	}
-
-	*handle = (usb_handle_t)transfer;
-
-	return EOK;
-}
-
-static int async_transfer_setup(usb_hc_device_t *hc,
-    usb_target_t target, usb_transfer_type_t transfer_type,
-    void *data, size_t size,
-    usb_handle_t *handle)
-{
-	if ((hc->transfer_ops == NULL)
-	    || (hc->transfer_ops->transfer_setup == NULL)) {
-		return ENOTSUP;
-	}
-
-	/* This creation of the device on the fly is just a workaround. */
-
-	transfer_info_t *transfer = transfer_info_create(
-	    create_attached_device_info(target.address),
-	    create_endpoint_info(target.endpoint,
-		USB_DIRECTION_OUT, transfer_type));
-
-	int rc = hc->transfer_ops->transfer_setup(hc,
-	    transfer->device, transfer->endpoint,
-	    data, size,
-	    callback_out, transfer);
-
-	if (rc != EOK) {
-		transfer_info_destroy(transfer);
-		return rc;
-	}
-
-	*handle = (usb_handle_t)transfer;
-
-	return EOK;
-}
-
-static int async_transfer_in(usb_hc_device_t *hc, usb_target_t target,
-    usb_transfer_type_t transfer_type,
-    void *buffer, size_t size, size_t *actual_size,
-    usb_handle_t *handle)
-{
-	if ((hc->transfer_ops == NULL)
-	    || (hc->transfer_ops->transfer_in == NULL)) {
-		return ENOTSUP;
-	}
-
-	/* This creation of the device on the fly is just a workaround. */
-
-	transfer_info_t *transfer = transfer_info_create(
-	    create_attached_device_info(target.address),
-	    create_endpoint_info(target.endpoint,
-		USB_DIRECTION_IN, transfer_type));
-	transfer->size_transferred = actual_size;
-
-	int rc = hc->transfer_ops->transfer_in(hc,
-	    transfer->device, transfer->endpoint,
-	    buffer, size,
-	    callback_in, transfer);
-
-	if (rc != EOK) {
-		transfer_info_destroy(transfer);
-		return rc;
-	}
-
-	*handle = (usb_handle_t)transfer;
-
-	return EOK;
-}
-
-
-/** Issue interrupt OUT transfer to HC driven by current task.
- *
- * @param hc Host controller to handle the transfer.
- * @param target Target device address.
- * @param buffer Data buffer.
- * @param size Buffer size.
- * @param handle Transfer handle.
- * @return Error code.
- */
-int usb_hc_async_interrupt_out(usb_hc_device_t *hc, usb_target_t target,
-    void *buffer, size_t size,
-    usb_handle_t *handle)
-{
-	return async_transfer_out(hc, target,
-	    USB_TRANSFER_INTERRUPT, buffer, size, handle);
-}
-
-
-/** Issue interrupt IN transfer to HC driven by current task.
- *
- * @warning The @p buffer and @p actual_size parameters shall not be
- * touched until this transfer is waited for by usb_hc_async_wait_for().
- *
- * @param hc Host controller to handle the transfer.
- * @param target Target device address.
- * @param buffer Data buffer.
- * @param size Buffer size.
- * @param actual_size Size of actually transferred data.
- * @param handle Transfer handle.
- * @return Error code.
- */
-int usb_hc_async_interrupt_in(usb_hc_device_t *hc, usb_target_t target,
-    void *buffer, size_t size, size_t *actual_size,
-    usb_handle_t *handle)
-{
-	return async_transfer_in(hc, target,
-	    USB_TRANSFER_INTERRUPT, buffer, size, actual_size, handle);
-}
-
-int usb_hc_async_control_write_setup(usb_hc_device_t *hc, usb_target_t target,
-    void *data, size_t size, usb_handle_t *handle)
-{
-	return async_transfer_setup(hc, target,
-	    USB_TRANSFER_CONTROL, data, size, handle);
-}
-
-int usb_hc_async_control_write_data(usb_hc_device_t *hc, usb_target_t target,
-    void *data, size_t size, usb_handle_t *handle)
-{
-	return async_transfer_out(hc, target,
-	    USB_TRANSFER_CONTROL, data, size, handle);
-}
-
-int usb_hc_async_control_write_status(usb_hc_device_t *hc, usb_target_t target,
-    usb_handle_t *handle)
-{
-	return async_transfer_in(hc, target,
-	    USB_TRANSFER_CONTROL, NULL, 0, NULL, handle);
-}
-
-int usb_hc_async_control_read_setup(usb_hc_device_t *hc, usb_target_t target,
-    void *data, size_t size, usb_handle_t *handle)
-{
-	return async_transfer_setup(hc, target,
-	    USB_TRANSFER_CONTROL, data, size, handle);
-}
-
-int usb_hc_async_control_read_data(usb_hc_device_t *hc, usb_target_t target,
-    void *buffer, size_t size, size_t *actual_size,
-    usb_handle_t *handle)
-{
-	return async_transfer_in(hc, target,
-	    USB_TRANSFER_CONTROL, buffer, size, actual_size, handle);
-}
-
-int usb_hc_async_control_read_status(usb_hc_device_t *hc, usb_target_t target,
-    usb_handle_t *handle)
-{
-	return async_transfer_out(hc, target,
-	    USB_TRANSFER_CONTROL, NULL, 0, handle);
-}
-
-/** Wait for transfer to complete.
- *
- * @param handle Transfer handle.
- * @return Error code.
- */
-int usb_hc_async_wait_for(usb_handle_t handle)
-{
-	transfer_info_t *transfer = (transfer_info_t *) handle;
-	if (transfer == NULL) {
-		return ENOENT;
-	}
-
-	fibril_mutex_lock(&transfer->condvar_guard);
-	while (!transfer->done) {
-		fibril_condvar_wait(&transfer->condvar, &transfer->condvar_guard);
-	}
-	fibril_mutex_unlock(&transfer->condvar_guard);
-
-	transfer_info_destroy(transfer);
-
-	return EOK;
-}
-
-/**
- * @}
- */
Index: uspace/lib/usb/src/pipes.c
===================================================================
--- uspace/lib/usb/src/pipes.c	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/lib/usb/src/pipes.c	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -31,14 +31,5 @@
  */
 /** @file
- * Communication between device drivers and host controller driver.
- *
- * Note on synchronousness of the operations: there is ABSOLUTELY NO
- * guarantee that a call to particular function will not trigger a fibril
- * switch.
- * The initialization functions may actually involve contacting some other
- * task, starting/ending a session might involve asynchronous IPC and since
- * the transfer functions uses IPC, asynchronous nature of them is obvious.
- * The pseudo synchronous versions for the transfers internally call the
- * asynchronous ones and so fibril switch is possible in them as well.
+ * USB endpoint pipes miscellaneous functions.
  */
 #include <usb/usb.h>
@@ -47,10 +38,4 @@
 #include <assert.h>
 #include <usb/usbdrv.h>
-
-#define _PREPARE_TARGET(varname, pipe) \
-	usb_target_t varname = { \
-		.address = (pipe)->wire->address, \
-		.endpoint = (pipe)->endpoint_no \
-	}
 
 /** Initialize connection to USB device.
@@ -117,46 +102,22 @@
 }
 
-/** Initialize USB endpoint pipe.
+/** Initialize connection to USB device on default address.
  *
- * @param pipe Endpoint pipe to be initialized.
- * @param connection Connection to the USB device backing this pipe (the wire).
- * @param endpoint_no Endpoint number (in USB 1.1 in range 0 to 15).
- * @param transfer_type Transfer type (e.g. interrupt or bulk).
- * @param direction Endpoint direction (in/out).
+ * @param dev_connection Device connection structure to be initialized.
+ * @param hc_connection Initialized connection to host controller.
  * @return Error code.
  */
-int usb_endpoint_pipe_initialize(usb_endpoint_pipe_t *pipe,
-    usb_device_connection_t *connection, usb_endpoint_t endpoint_no,
-    usb_transfer_type_t transfer_type, usb_direction_t direction)
+int usb_device_connection_initialize_on_default_address(
+    usb_device_connection_t *dev_connection,
+    usb_hc_connection_t *hc_connection)
 {
-	assert(pipe);
-	assert(connection);
+	assert(dev_connection);
 
-	pipe->wire = connection;
-	pipe->hc_phone = -1;
-	pipe->endpoint_no = endpoint_no;
-	pipe->transfer_type = transfer_type;
-	pipe->direction = direction;
+	if (hc_connection == NULL) {
+		return EBADMEM;
+	}
 
-	return EOK;
-}
-
-
-/** Initialize USB endpoint pipe as the default zero control pipe.
- *
- * @param pipe Endpoint pipe to be initialized.
- * @param connection Connection to the USB device backing this pipe (the wire).
- * @return Error code.
- */
-int usb_endpoint_pipe_initialize_default_control(usb_endpoint_pipe_t *pipe,
-    usb_device_connection_t *connection)
-{
-	assert(pipe);
-	assert(connection);
-
-	int rc = usb_endpoint_pipe_initialize(pipe, connection,
-	    0, USB_TRANSFER_CONTROL, USB_DIRECTION_BOTH);
-
-	return rc;
+	return usb_device_connection_initialize(dev_connection,
+	    hc_connection->hc_handle, (usb_address_t) 0);
 }
 
@@ -221,305 +182,4 @@
 }
 
-
-/** Request a read (in) transfer on an endpoint pipe.
- *
- * @param[in] pipe Pipe used for the transfer.
- * @param[out] buffer Buffer where to store the data.
- * @param[in] size Size of the buffer (in bytes).
- * @param[out] size_transfered Number of bytes that were actually transfered.
- * @return Error code.
- */
-int usb_endpoint_pipe_read(usb_endpoint_pipe_t *pipe,
-    void *buffer, size_t size, size_t *size_transfered)
-{
-	assert(pipe);
-
-	int rc;
-	usb_handle_t handle;
-
-	rc = usb_endpoint_pipe_async_read(pipe, buffer, size, size_transfered,
-	    &handle);
-	if (rc != EOK) {
-		return rc;
-	}
-
-	rc = usb_endpoint_pipe_wait_for(pipe, handle);
-	return rc;
-}
-
-/** Request a write (out) transfer on an endpoint pipe.
- *
- * @param[in] pipe Pipe used for the transfer.
- * @param[in] buffer Buffer with data to transfer.
- * @param[in] size Size of the buffer (in bytes).
- * @return Error code.
- */
-int usb_endpoint_pipe_write(usb_endpoint_pipe_t *pipe,
-    void *buffer, size_t size)
-{
-	assert(pipe);
-
-	int rc;
-	usb_handle_t handle;
-
-	rc = usb_endpoint_pipe_async_write(pipe, buffer, size, &handle);
-	if (rc != EOK) {
-		return rc;
-	}
-
-	rc = usb_endpoint_pipe_wait_for(pipe, handle);
-	return rc;
-}
-
-
-/** Request a control read transfer on an endpoint pipe.
- *
- * This function encapsulates all three stages of a control transfer.
- *
- * @param[in] pipe Pipe used for the transfer.
- * @param[in] setup_buffer Buffer with the setup packet.
- * @param[in] setup_buffer_size Size of the setup packet (in bytes).
- * @param[out] data_buffer Buffer for incoming data.
- * @param[in] data_buffer_size Size of the buffer for incoming data (in bytes).
- * @param[out] data_transfered_size Number of bytes that were actually
- *                                  transfered during the DATA stage.
- * @return Error code.
- */
-int usb_endpoint_pipe_control_read(usb_endpoint_pipe_t *pipe,
-    void *setup_buffer, size_t setup_buffer_size,
-    void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size)
-{
-	assert(pipe);
-
-	int rc;
-	usb_handle_t handle;
-
-	rc = usb_endpoint_pipe_async_control_read(pipe,
-	    setup_buffer, setup_buffer_size,
-	    data_buffer, data_buffer_size, data_transfered_size,
-	    &handle);
-	if (rc != EOK) {
-		return rc;
-	}
-
-	rc = usb_endpoint_pipe_wait_for(pipe, handle);
-	return rc;
-}
-
-
-/** Request a control write transfer on an endpoint pipe.
- *
- * This function encapsulates all three stages of a control transfer.
- *
- * @param[in] pipe Pipe used for the transfer.
- * @param[in] setup_buffer Buffer with the setup packet.
- * @param[in] setup_buffer_size Size of the setup packet (in bytes).
- * @param[in] data_buffer Buffer with data to be sent.
- * @param[in] data_buffer_size Size of the buffer with outgoing data (in bytes).
- * @return Error code.
- */
-int usb_endpoint_pipe_control_write(usb_endpoint_pipe_t *pipe,
-    void *setup_buffer, size_t setup_buffer_size,
-    void *data_buffer, size_t data_buffer_size)
-{
-	assert(pipe);
-
-	int rc;
-	usb_handle_t handle;
-
-	rc = usb_endpoint_pipe_async_control_write(pipe,
-	    setup_buffer, setup_buffer_size,
-	    data_buffer, data_buffer_size,
-	    &handle);
-	if (rc != EOK) {
-		return rc;
-	}
-
-	rc = usb_endpoint_pipe_wait_for(pipe, handle);
-	return rc;
-}
-
-
-/** Request a read (in) transfer on an endpoint pipe (asynchronous version).
- *
- * @param[in] pipe Pipe used for the transfer.
- * @param[out] buffer Buffer where to store the data.
- * @param[in] size Size of the buffer (in bytes).
- * @param[out] size_transfered Number of bytes that were actually transfered.
- * @param[out] handle Handle of the transfer.
- * @return Error code.
- */
-int usb_endpoint_pipe_async_read(usb_endpoint_pipe_t *pipe,
-    void *buffer, size_t size, size_t *size_transfered,
-    usb_handle_t *handle)
-{
-	assert(pipe);
-
-	if (pipe->hc_phone < 0) {
-		return EBADF;
-	}
-
-	if (pipe->direction != USB_DIRECTION_IN) {
-		return EBADF;
-	}
-
-	int rc;
-	_PREPARE_TARGET(target, pipe);
-
-	switch (pipe->transfer_type) {
-		case USB_TRANSFER_INTERRUPT:
-			rc = usb_drv_async_interrupt_in(pipe->hc_phone, target,
-			    buffer, size, size_transfered, handle);
-			break;
-		case USB_TRANSFER_CONTROL:
-			rc = EBADF;
-			break;
-		default:
-			rc = ENOTSUP;
-			break;
-	}
-
-	return rc;
-}
-
-
-/** Request a write (out) transfer on an endpoint pipe (asynchronous version).
- *
- * @param[in] pipe Pipe used for the transfer.
- * @param[in] buffer Buffer with data to transfer.
- * @param[in] size Size of the buffer (in bytes).
- * @param[out] handle Handle of the transfer.
- * @return Error code.
- */
-int usb_endpoint_pipe_async_write(usb_endpoint_pipe_t *pipe,
-    void *buffer, size_t size,
-    usb_handle_t *handle)
-{
-	assert(pipe);
-
-	if (pipe->hc_phone < 0) {
-		return EBADF;
-	}
-
-	if (pipe->direction != USB_DIRECTION_OUT) {
-		return EBADF;
-	}
-
-	int rc;
-	_PREPARE_TARGET(target, pipe);
-
-	switch (pipe->transfer_type) {
-		case USB_TRANSFER_INTERRUPT:
-			rc = usb_drv_async_interrupt_out(pipe->hc_phone, target,
-			    buffer, size, handle);
-			break;
-		case USB_TRANSFER_CONTROL:
-			rc = EBADF;
-			break;
-		default:
-			rc = ENOTSUP;
-			break;
-	}
-
-	return rc;
-}
-
-
-/** Request a control read transfer on an endpoint pipe (asynchronous version).
- *
- * This function encapsulates all three stages of a control transfer.
- *
- * @param[in] pipe Pipe used for the transfer.
- * @param[in] setup_buffer Buffer with the setup packet.
- * @param[in] setup_buffer_size Size of the setup packet (in bytes).
- * @param[out] data_buffer Buffer for incoming data.
- * @param[in] data_buffer_size Size of the buffer for incoming data (in bytes).
- * @param[out] data_transfered_size Number of bytes that were actually
- *                                  transfered during the DATA stage.
- * @param[out] handle Handle of the transfer.
- * @return Error code.
- */
-int usb_endpoint_pipe_async_control_read(usb_endpoint_pipe_t *pipe,
-    void *setup_buffer, size_t setup_buffer_size,
-    void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size,
-    usb_handle_t *handle)
-{
-	assert(pipe);
-
-	if (pipe->hc_phone < 0) {
-		return EBADF;
-	}
-
-	if ((pipe->direction != USB_DIRECTION_BOTH)
-	    || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
-		return EBADF;
-	}
-
-	int rc;
-	_PREPARE_TARGET(target, pipe);
-
-	rc = usb_drv_async_control_read(pipe->hc_phone, target,
-	    setup_buffer, setup_buffer_size,
-	    data_buffer, data_buffer_size, data_transfered_size,
-	    handle);
-
-	return rc;
-}
-
-
-/** Request a control write transfer on an endpoint pipe (asynchronous version).
- *
- * This function encapsulates all three stages of a control transfer.
- *
- * @param[in] pipe Pipe used for the transfer.
- * @param[in] setup_buffer Buffer with the setup packet.
- * @param[in] setup_buffer_size Size of the setup packet (in bytes).
- * @param[in] data_buffer Buffer with data to be sent.
- * @param[in] data_buffer_size Size of the buffer with outgoing data (in bytes).
- * @param[out] handle Handle of the transfer.
- * @return Error code.
- */
-int usb_endpoint_pipe_async_control_write(usb_endpoint_pipe_t *pipe,
-    void *setup_buffer, size_t setup_buffer_size,
-    void *data_buffer, size_t data_buffer_size,
-    usb_handle_t *handle)
-{
-	assert(pipe);
-
-	if (pipe->hc_phone < 0) {
-		return EBADF;
-	}
-
-	if ((pipe->direction != USB_DIRECTION_BOTH)
-	    || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
-		return EBADF;
-	}
-
-	int rc;
-	_PREPARE_TARGET(target, pipe);
-
-	rc = usb_drv_async_control_write(pipe->hc_phone, target,
-	    setup_buffer, setup_buffer_size,
-	    data_buffer, data_buffer_size,
-	    handle);
-
-	return rc;
-}
-
-/** Wait for transfer completion.
- *
- * The function blocks the caller fibril until the transfer associated
- * with given @p handle is completed.
- *
- * @param[in] pipe Pipe the transfer executed on.
- * @param[in] handle Transfer handle.
- * @return Error code.
- */
-int usb_endpoint_pipe_wait_for(usb_endpoint_pipe_t *pipe, usb_handle_t handle)
-{
-	return usb_drv_async_wait_for(handle);
-}
-
-
 /**
  * @}
Index: uspace/lib/usb/src/pipesinit.c
===================================================================
--- uspace/lib/usb/src/pipesinit.c	(revision 50ba203e98ce570f05993da83249a116cfffceab)
+++ uspace/lib/usb/src/pipesinit.c	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -0,0 +1,371 @@
+/*
+ * 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
+ * Initialization of endpoint pipes.
+ *
+ */
+#include <usb/usb.h>
+#include <usb/pipes.h>
+#include <usb/dp.h>
+#include <errno.h>
+#include <assert.h>
+
+
+#define NESTING(parentname, childname) \
+	{ \
+		.child = USB_DESCTYPE_##childname, \
+		.parent = USB_DESCTYPE_##parentname, \
+	}
+#define LAST_NESTING { -1, -1 }
+
+/** Nesting pairs of standard descriptors. */
+static usb_dp_descriptor_nesting_t descriptor_nesting[] = {
+	NESTING(CONFIGURATION, INTERFACE),
+	NESTING(INTERFACE, ENDPOINT),
+	NESTING(INTERFACE, HUB),
+	NESTING(INTERFACE, HID),
+	NESTING(HID, HID_REPORT),
+	LAST_NESTING
+};
+
+/** Tells whether given descriptor is of endpoint type.
+ *
+ * @param descriptor Descriptor in question.
+ * @return Whether the given descriptor is endpoint descriptor.
+ */
+static inline bool is_endpoint_descriptor(uint8_t *descriptor)
+{
+	return descriptor[1] == USB_DESCTYPE_ENDPOINT;
+}
+
+/** Tells whether found endpoint corresponds to endpoint described by user.
+ *
+ * @param wanted Endpoint description as entered by driver author.
+ * @param found Endpoint description obtained from endpoint descriptor.
+ * @return Whether the @p found descriptor fits the @p wanted descriptor.
+ */
+static bool endpoint_fits_description(const usb_endpoint_description_t *wanted,
+    usb_endpoint_description_t *found)
+{
+#define _SAME(fieldname) ((wanted->fieldname) == (found->fieldname))
+
+	if (!_SAME(direction)) {
+		return false;
+	}
+
+	if (!_SAME(transfer_type)) {
+		return false;
+	}
+
+	if ((wanted->interface_class >= 0) && !_SAME(interface_class)) {
+		return false;
+	}
+
+	if ((wanted->interface_subclass >= 0) && !_SAME(interface_subclass)) {
+		return false;
+	}
+
+	if ((wanted->interface_protocol >= 0) && !_SAME(interface_protocol)) {
+		return false;
+	}
+
+#undef _SAME
+
+	return true;
+}
+
+/** Find endpoint mapping for a found endpoint.
+ *
+ * @param mapping Endpoint mapping list.
+ * @param mapping_count Number of endpoint mappings in @p mapping.
+ * @param found_endpoint Description of found endpoint.
+ * @return Endpoint mapping corresponding to @p found_endpoint.
+ * @retval NULL No corresponding endpoint found.
+ */
+static usb_endpoint_mapping_t *find_endpoint_mapping(
+    usb_endpoint_mapping_t *mapping, size_t mapping_count,
+    usb_endpoint_description_t *found_endpoint)
+{
+	while (mapping_count > 0) {
+		if (endpoint_fits_description(mapping->description,
+		    found_endpoint)) {
+			return mapping;
+		}
+
+		mapping++;
+		mapping_count--;
+	}
+	return NULL;
+}
+
+/** Process endpoint descriptor.
+ *
+ * @param mapping Endpoint mapping list.
+ * @param mapping_count Number of endpoint mappings in @p mapping.
+ * @param interface Interface descriptor under which belongs the @p endpoint.
+ * @param endpoint Endpoint descriptor.
+ * @param wire Connection backing the endpoint pipes.
+ * @return Error code.
+ */
+static int process_endpoint(
+    usb_endpoint_mapping_t *mapping, size_t mapping_count,
+    usb_standard_interface_descriptor_t *interface,
+    usb_standard_endpoint_descriptor_t *endpoint,
+    usb_device_connection_t *wire)
+{
+	usb_endpoint_description_t description;
+
+	/*
+	 * Get endpoint characteristics.
+	 */
+
+	/* Actual endpoint number is in bits 0..3 */
+	usb_endpoint_t ep_no = endpoint->endpoint_address & 0x0F;
+
+	/* Endpoint direction is set by bit 7 */
+	description.direction = (endpoint->endpoint_address & 128)
+	    ? USB_DIRECTION_IN : USB_DIRECTION_OUT;
+	/* Transfer type is in bits 0..2 and the enum values corresponds 1:1 */
+	description.transfer_type = endpoint->attributes & 3;
+
+	/*
+	 * Get interface characteristics.
+	 */
+	description.interface_class = interface->interface_class;
+	description.interface_subclass = interface->interface_subclass;
+	description.interface_protocol = interface->interface_protocol;
+
+	/*
+	 * Find the most fitting mapping and initialize the pipe.
+	 */
+	usb_endpoint_mapping_t *ep_mapping = find_endpoint_mapping(mapping,
+	    mapping_count, &description);
+	if (ep_mapping == NULL) {
+		return ENOENT;
+	}
+
+	if (ep_mapping->pipe == NULL) {
+		return EBADMEM;
+	}
+	if (ep_mapping->present) {
+		return EEXISTS;
+	}
+
+	int rc = usb_endpoint_pipe_initialize(ep_mapping->pipe, wire,
+	    ep_no, description.transfer_type, endpoint->max_packet_size,
+	    description.direction);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	ep_mapping->present = true;
+	ep_mapping->descriptor = endpoint;
+	ep_mapping->interface = interface;
+
+	return EOK;
+}
+
+/** Process whole USB interface.
+ *
+ * @param mapping Endpoint mapping list.
+ * @param mapping_count Number of endpoint mappings in @p mapping.
+ * @param parser Descriptor parser.
+ * @param parser_data Descriptor parser data.
+ * @param interface_descriptor Interface descriptor.
+ * @return Error code.
+ */
+static int process_interface(
+    usb_endpoint_mapping_t *mapping, size_t mapping_count,
+    usb_dp_parser_t *parser, usb_dp_parser_data_t *parser_data,
+    uint8_t *interface_descriptor)
+{
+	uint8_t *descriptor = usb_dp_get_nested_descriptor(parser,
+	    parser_data, interface_descriptor);
+
+	if (descriptor == NULL) {
+		return ENOENT;
+	}
+
+	do {
+		if (is_endpoint_descriptor(descriptor)) {
+			(void) process_endpoint(mapping, mapping_count,
+			    (usb_standard_interface_descriptor_t *)
+			        interface_descriptor,
+			    (usb_standard_endpoint_descriptor_t *)
+			        descriptor,
+			    (usb_device_connection_t *) parser_data->arg);
+		}
+
+		descriptor = usb_dp_get_sibling_descriptor(parser, parser_data,
+		    interface_descriptor, descriptor);
+	} while (descriptor != NULL);
+
+	return EOK;
+}
+
+/** Initialize endpoint pipes from configuration descriptor.
+ *
+ * The mapping array is expected to conform to following rules:
+ * - @c pipe must point to already allocated structure with uninitialized pipe
+ * - @c description must point to prepared endpoint description
+ * - @c descriptor does not need to be initialized (will be overwritten)
+ * - @c interface does not need to be initialized (will be overwritten)
+ * - @c present does not need to be initialized (will be overwritten)
+ *
+ * After processing the configuration descriptor, the mapping is updated
+ * in the following fashion:
+ * - @c present will be set to @c true when the endpoint was found in the
+ *   configuration
+ * - @c descriptor will point inside the configuration descriptor to endpoint
+ *   corresponding to given description (or NULL for not found descriptor)
+ * - @c interface will point inside the configuration descriptor to interface
+ *   descriptor the endpoint @c descriptor belongs to (or NULL for not found
+ *   descriptor)
+ * - @c pipe will be initialized when found, otherwise left untouched
+ * - @c description will be untouched under all circumstances
+ *
+ * @param mapping Endpoint mapping list.
+ * @param mapping_count Number of endpoint mappings in @p mapping.
+ * @param configuration_descriptor Full configuration descriptor (is expected
+ *	to be in USB endianness: i.e. as-is after being retrieved from
+ *	the device).
+ * @param configuration_descriptor_size Size of @p configuration_descriptor
+ *	in bytes.
+ * @param connection Connection backing the endpoint pipes.
+ * @return Error code.
+ */
+int usb_endpoint_pipe_initialize_from_configuration(
+    usb_endpoint_mapping_t *mapping, size_t mapping_count,
+    uint8_t *configuration_descriptor, size_t configuration_descriptor_size,
+    usb_device_connection_t *connection)
+{
+	assert(connection);
+
+	if (configuration_descriptor == NULL) {
+		return EBADMEM;
+	}
+	if (configuration_descriptor_size
+	    < sizeof(usb_standard_configuration_descriptor_t)) {
+		return ERANGE;
+	}
+
+	/*
+	 * Go through the mapping and set all endpoints to not present.
+	 */
+	size_t i;
+	for (i = 0; i < mapping_count; i++) {
+		mapping[i].present = false;
+		mapping[i].descriptor = NULL;
+		mapping[i].interface = NULL;
+	}
+
+	/*
+	 * Prepare the descriptor parser.
+	 */
+	usb_dp_parser_t dp_parser = {
+		.nesting = descriptor_nesting
+	};
+	usb_dp_parser_data_t dp_data = {
+		.data = configuration_descriptor,
+		.size = configuration_descriptor_size,
+		.arg = connection
+	};
+
+	/*
+	 * Iterate through all interfaces.
+	 */
+	uint8_t *interface = usb_dp_get_nested_descriptor(&dp_parser,
+	    &dp_data, configuration_descriptor);
+	if (interface == NULL) {
+		return ENOENT;
+	}
+	do {
+		(void) process_interface(mapping, mapping_count,
+		    &dp_parser, &dp_data,
+		    interface);
+		interface = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data,
+		    configuration_descriptor, interface);
+	} while (interface != NULL);
+
+	return EOK;
+}
+
+/** Initialize USB endpoint pipe.
+ *
+ * @param pipe Endpoint pipe to be initialized.
+ * @param connection Connection to the USB device backing this pipe (the wire).
+ * @param endpoint_no Endpoint number (in USB 1.1 in range 0 to 15).
+ * @param transfer_type Transfer type (e.g. interrupt or bulk).
+ * @param max_packet_size Maximum packet size in bytes.
+ * @param direction Endpoint direction (in/out).
+ * @return Error code.
+ */
+int usb_endpoint_pipe_initialize(usb_endpoint_pipe_t *pipe,
+    usb_device_connection_t *connection, usb_endpoint_t endpoint_no,
+    usb_transfer_type_t transfer_type, size_t max_packet_size,
+    usb_direction_t direction)
+{
+	assert(pipe);
+	assert(connection);
+
+	pipe->wire = connection;
+	pipe->hc_phone = -1;
+	pipe->endpoint_no = endpoint_no;
+	pipe->transfer_type = transfer_type;
+	pipe->max_packet_size = max_packet_size;
+	pipe->direction = direction;
+
+	return EOK;
+}
+
+
+/** Initialize USB endpoint pipe as the default zero control pipe.
+ *
+ * @param pipe Endpoint pipe to be initialized.
+ * @param connection Connection to the USB device backing this pipe (the wire).
+ * @return Error code.
+ */
+int usb_endpoint_pipe_initialize_default_control(usb_endpoint_pipe_t *pipe,
+    usb_device_connection_t *connection)
+{
+	assert(pipe);
+	assert(connection);
+
+	int rc = usb_endpoint_pipe_initialize(pipe, connection,
+	    0, USB_TRANSFER_CONTROL, 8, USB_DIRECTION_BOTH);
+
+	return rc;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/pipesio.c
===================================================================
--- uspace/lib/usb/src/pipesio.c	(revision 50ba203e98ce570f05993da83249a116cfffceab)
+++ uspace/lib/usb/src/pipesio.c	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -0,0 +1,491 @@
+/*
+ * 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
+ * Input and output functions (reads and writes) on endpoint pipes.
+ *
+ * Note on synchronousness of the operations: there is ABSOLUTELY NO
+ * guarantee that a call to particular function will not trigger a fibril
+ * switch.
+ *
+ * Note about the implementation: the transfer requests are always divided
+ * into two functions.
+ * The outer one does checking of input parameters (e.g. that session was
+ * already started, buffers are not NULL etc), while the inner one
+ * (with _no_checks suffix) does the actual IPC (it checks for IPC errors,
+ * obviously).
+ */
+#include <usb/usb.h>
+#include <usb/pipes.h>
+#include <errno.h>
+#include <assert.h>
+#include <usbhc_iface.h>
+
+/** Request an in transfer, no checking of input parameters.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[out] buffer Buffer where to store the data.
+ * @param[in] size Size of the buffer (in bytes).
+ * @param[out] size_transfered Number of bytes that were actually transfered.
+ * @return Error code.
+ */
+static int usb_endpoint_pipe_read_no_checks(usb_endpoint_pipe_t *pipe,
+    void *buffer, size_t size, size_t *size_transfered)
+{
+	/*
+	 * Get corresponding IPC method.
+	 * In future, replace with static array of mappings
+	 * transfer type -> method.
+	 */
+	usbhc_iface_funcs_t ipc_method;
+	switch (pipe->transfer_type) {
+		case USB_TRANSFER_INTERRUPT:
+			ipc_method = IPC_M_USBHC_INTERRUPT_IN;
+			break;
+		default:
+			return ENOTSUP;
+	}
+
+	/*
+	 * Make call identifying target USB device and type of transfer.
+	 */
+	aid_t opening_request = async_send_3(pipe->hc_phone,
+	    DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method,
+	    pipe->wire->address, pipe->endpoint_no,
+	    NULL);
+	if (opening_request == 0) {
+		return ENOMEM;
+	}
+
+	/*
+	 * Retrieve the data.
+	 */
+	ipc_call_t data_request_call;
+	aid_t data_request = async_data_read(pipe->hc_phone, buffer, size,
+	    &data_request_call);
+
+	if (data_request == 0) {
+		/*
+		 * FIXME:
+		 * How to let the other side know that we want to abort?
+		 */
+		async_wait_for(opening_request, NULL);
+		return ENOMEM;
+	}
+
+	/*
+	 * Wait for the answer.
+	 */
+	sysarg_t data_request_rc;
+	sysarg_t opening_request_rc;
+	async_wait_for(data_request, &data_request_rc);
+	async_wait_for(opening_request, &opening_request_rc);
+
+	if (data_request_rc != EOK) {
+		return (int) data_request_rc;
+	}
+	if (opening_request_rc != EOK) {
+		return (int) opening_request_rc;
+	}
+
+	*size_transfered = IPC_GET_ARG2(data_request_call);
+
+	return EOK;
+}
+
+
+/** Request a read (in) transfer on an endpoint pipe.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[out] buffer Buffer where to store the data.
+ * @param[in] size Size of the buffer (in bytes).
+ * @param[out] size_transfered Number of bytes that were actually transfered.
+ * @return Error code.
+ */
+int usb_endpoint_pipe_read(usb_endpoint_pipe_t *pipe,
+    void *buffer, size_t size, size_t *size_transfered)
+{
+	assert(pipe);
+
+	if (buffer == NULL) {
+			return EINVAL;
+	}
+
+	if (size == 0) {
+		return EINVAL;
+	}
+
+	if (pipe->hc_phone < 0) {
+		return EBADF;
+	}
+
+	if (pipe->direction != USB_DIRECTION_IN) {
+		return EBADF;
+	}
+
+	if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
+		return EBADF;
+	}
+
+	size_t act_size = 0;
+	int rc;
+
+	rc = usb_endpoint_pipe_read_no_checks(pipe, buffer, size, &act_size);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	if (size_transfered != NULL) {
+		*size_transfered = act_size;
+	}
+
+	return EOK;
+}
+
+
+
+
+/** Request an out transfer, no checking of input parameters.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[in] buffer Buffer with data to transfer.
+ * @param[in] size Size of the buffer (in bytes).
+ * @return Error code.
+ */
+static int usb_endpoint_pipe_write_no_check(usb_endpoint_pipe_t *pipe,
+    void *buffer, size_t size)
+{
+	/*
+	 * Get corresponding IPC method.
+	 * In future, replace with static array of mappings
+	 * transfer type -> method.
+	 */
+	usbhc_iface_funcs_t ipc_method;
+	switch (pipe->transfer_type) {
+		case USB_TRANSFER_INTERRUPT:
+			ipc_method = IPC_M_USBHC_INTERRUPT_OUT;
+			break;
+		default:
+			return ENOTSUP;
+	}
+
+	/*
+	 * Make call identifying target USB device and type of transfer.
+	 */
+	aid_t opening_request = async_send_3(pipe->hc_phone,
+	    DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method,
+	    pipe->wire->address, pipe->endpoint_no,
+	    NULL);
+	if (opening_request == 0) {
+		return ENOMEM;
+	}
+
+	/*
+	 * Send the data.
+	 */
+	int rc = async_data_write_start(pipe->hc_phone, buffer, size);
+	if (rc != EOK) {
+		async_wait_for(opening_request, NULL);
+		return rc;
+	}
+
+	/*
+	 * Wait for the answer.
+	 */
+	sysarg_t opening_request_rc;
+	async_wait_for(opening_request, &opening_request_rc);
+
+	return (int) opening_request_rc;
+}
+
+/** Request a write (out) transfer on an endpoint pipe.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[in] buffer Buffer with data to transfer.
+ * @param[in] size Size of the buffer (in bytes).
+ * @return Error code.
+ */
+int usb_endpoint_pipe_write(usb_endpoint_pipe_t *pipe,
+    void *buffer, size_t size)
+{
+	assert(pipe);
+
+	if (buffer == NULL) {
+		return EINVAL;
+	}
+
+	if (size == 0) {
+		return EINVAL;
+	}
+
+	if (pipe->hc_phone < 0) {
+		return EBADF;
+	}
+
+	if (pipe->direction != USB_DIRECTION_OUT) {
+		return EBADF;
+	}
+
+	if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
+		return EBADF;
+	}
+
+	int rc = usb_endpoint_pipe_write_no_check(pipe, buffer, size);
+
+	return rc;
+}
+
+
+/** Request a control read transfer, no checking of input parameters.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[in] setup_buffer Buffer with the setup packet.
+ * @param[in] setup_buffer_size Size of the setup packet (in bytes).
+ * @param[out] data_buffer Buffer for incoming data.
+ * @param[in] data_buffer_size Size of the buffer for incoming data (in bytes).
+ * @param[out] data_transfered_size Number of bytes that were actually
+ *                                  transfered during the DATA stage.
+ * @return Error code.
+ */
+static int usb_endpoint_pipe_control_read_no_check(usb_endpoint_pipe_t *pipe,
+    void *setup_buffer, size_t setup_buffer_size,
+    void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size)
+{
+	/*
+	 * Make call identifying target USB device and control transfer type.
+	 */
+	aid_t opening_request = async_send_3(pipe->hc_phone,
+	    DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_READ,
+	    pipe->wire->address, pipe->endpoint_no,
+	    NULL);
+	if (opening_request == 0) {
+		return ENOMEM;
+	}
+
+	/*
+	 * Send the setup packet.
+	 */
+	int rc = async_data_write_start(pipe->hc_phone,
+	    setup_buffer, setup_buffer_size);
+	if (rc != EOK) {
+		async_wait_for(opening_request, NULL);
+		return rc;
+	}
+
+	/*
+	 * Retrieve the data.
+	 */
+	ipc_call_t data_request_call;
+	aid_t data_request = async_data_read(pipe->hc_phone,
+	    data_buffer, data_buffer_size,
+	    &data_request_call);
+	if (data_request == 0) {
+		async_wait_for(opening_request, NULL);
+		return ENOMEM;
+	}
+
+	/*
+	 * Wait for the answer.
+	 */
+	sysarg_t data_request_rc;
+	sysarg_t opening_request_rc;
+	async_wait_for(data_request, &data_request_rc);
+	async_wait_for(opening_request, &opening_request_rc);
+
+	if (data_request_rc != EOK) {
+		return (int) data_request_rc;
+	}
+	if (opening_request_rc != EOK) {
+		return (int) opening_request_rc;
+	}
+
+	*data_transfered_size = IPC_GET_ARG2(data_request_call);
+
+	return EOK;
+}
+
+/** Request a control read transfer on an endpoint pipe.
+ *
+ * This function encapsulates all three stages of a control transfer.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[in] setup_buffer Buffer with the setup packet.
+ * @param[in] setup_buffer_size Size of the setup packet (in bytes).
+ * @param[out] data_buffer Buffer for incoming data.
+ * @param[in] data_buffer_size Size of the buffer for incoming data (in bytes).
+ * @param[out] data_transfered_size Number of bytes that were actually
+ *                                  transfered during the DATA stage.
+ * @return Error code.
+ */
+int usb_endpoint_pipe_control_read(usb_endpoint_pipe_t *pipe,
+    void *setup_buffer, size_t setup_buffer_size,
+    void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size)
+{
+	assert(pipe);
+
+	if ((setup_buffer == NULL) || (setup_buffer_size == 0)) {
+		return EINVAL;
+	}
+
+	if ((data_buffer == NULL) || (data_buffer_size == 0)) {
+		return EINVAL;
+	}
+
+	if (pipe->hc_phone < 0) {
+		return EBADF;
+	}
+
+	if ((pipe->direction != USB_DIRECTION_BOTH)
+	    || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
+		return EBADF;
+	}
+
+	size_t act_size = 0;
+	int rc = usb_endpoint_pipe_control_read_no_check(pipe,
+	    setup_buffer, setup_buffer_size,
+	    data_buffer, data_buffer_size, &act_size);
+
+	if (rc != EOK) {
+		return rc;
+	}
+
+	if (data_transfered_size != NULL) {
+		*data_transfered_size = act_size;
+	}
+
+	return EOK;
+}
+
+
+/** Request a control write transfer, no checking of input parameters.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[in] setup_buffer Buffer with the setup packet.
+ * @param[in] setup_buffer_size Size of the setup packet (in bytes).
+ * @param[in] data_buffer Buffer with data to be sent.
+ * @param[in] data_buffer_size Size of the buffer with outgoing data (in bytes).
+ * @return Error code.
+ */
+static int usb_endpoint_pipe_control_write_no_check(usb_endpoint_pipe_t *pipe,
+    void *setup_buffer, size_t setup_buffer_size,
+    void *data_buffer, size_t data_buffer_size)
+{
+	/*
+	 * Make call identifying target USB device and control transfer type.
+	 */
+	aid_t opening_request = async_send_4(pipe->hc_phone,
+	    DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_WRITE,
+	    pipe->wire->address, pipe->endpoint_no,
+	    data_buffer_size,
+	    NULL);
+	if (opening_request == 0) {
+		return ENOMEM;
+	}
+
+	/*
+	 * Send the setup packet.
+	 */
+	int rc = async_data_write_start(pipe->hc_phone,
+	    setup_buffer, setup_buffer_size);
+	if (rc != EOK) {
+		async_wait_for(opening_request, NULL);
+		return rc;
+	}
+
+	/*
+	 * Send the data (if any).
+	 */
+	if (data_buffer_size > 0) {
+		rc = async_data_write_start(pipe->hc_phone,
+		    data_buffer, data_buffer_size);
+		if (rc != EOK) {
+			async_wait_for(opening_request, NULL);
+			return rc;
+		}
+	}
+
+	/*
+	 * Wait for the answer.
+	 */
+	sysarg_t opening_request_rc;
+	async_wait_for(opening_request, &opening_request_rc);
+
+	return (int) opening_request_rc;
+}
+
+/** Request a control write transfer on an endpoint pipe.
+ *
+ * This function encapsulates all three stages of a control transfer.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[in] setup_buffer Buffer with the setup packet.
+ * @param[in] setup_buffer_size Size of the setup packet (in bytes).
+ * @param[in] data_buffer Buffer with data to be sent.
+ * @param[in] data_buffer_size Size of the buffer with outgoing data (in bytes).
+ * @return Error code.
+ */
+int usb_endpoint_pipe_control_write(usb_endpoint_pipe_t *pipe,
+    void *setup_buffer, size_t setup_buffer_size,
+    void *data_buffer, size_t data_buffer_size)
+{
+	assert(pipe);
+
+	if ((setup_buffer == NULL) || (setup_buffer_size == 0)) {
+		return EINVAL;
+	}
+
+	if ((data_buffer == NULL) && (data_buffer_size > 0)) {
+		return EINVAL;
+	}
+
+	if ((data_buffer != NULL) && (data_buffer_size == 0)) {
+		return EINVAL;
+	}
+
+	if (pipe->hc_phone < 0) {
+		return EBADF;
+	}
+
+	if ((pipe->direction != USB_DIRECTION_BOTH)
+	    || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
+		return EBADF;
+	}
+
+	int rc = usb_endpoint_pipe_control_write_no_check(pipe,
+	    setup_buffer, setup_buffer_size, data_buffer, data_buffer_size);
+
+	return rc;
+}
+
+
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/recognise.c
===================================================================
--- uspace/lib/usb/src/recognise.c	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/lib/usb/src/recognise.c	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -36,7 +36,13 @@
 #include <usb_iface.h>
 #include <usb/usbdrv.h>
+#include <usb/pipes.h>
+#include <usb/recognise.h>
+#include <usb/request.h>
 #include <usb/classes/classes.h>
 #include <stdio.h>
 #include <errno.h>
+
+static size_t device_name_index = 0;
+static FIBRIL_MUTEX_INITIALIZE(device_name_index_mutex);
 
 /** Callback for getting host controller handle.
@@ -70,5 +76,5 @@
 };
 
-static device_ops_t child_ops = {
+device_ops_t child_ops = {
 	.interfaces[USB_DEV_IFACE] = &usb_iface
 };
@@ -155,5 +161,5 @@
 		/* First, with release number. */
 		rc = usb_add_match_id(matches, 100,
-		    "usb&vendor=%d&product=%d&release=" BCD_FMT,
+		    "usb&vendor=0x%04x&product=0x%04x&release=" BCD_FMT,
 		    (int) device_descriptor->vendor_id,
 		    (int) device_descriptor->product_id,
@@ -164,5 +170,6 @@
 		
 		/* Next, without release number. */
-		rc = usb_add_match_id(matches, 90, "usb&vendor=%d&product=%d",
+		rc = usb_add_match_id(matches, 90,
+		    "usb&vendor=0x%04x&product=0x%04x",
 		    (int) device_descriptor->vendor_id,
 		    (int) device_descriptor->product_id);
@@ -241,13 +248,11 @@
 /** Add match ids based on configuration descriptor.
  *
- * @param hc Open phone to host controller.
+ * @param pipe Control pipe to the device.
  * @param matches Match ids list to add matches to.
- * @param address USB address of the attached device.
  * @param config_count Number of configurations the device has.
  * @return Error code.
  */
-static int usb_add_config_descriptor_match_ids(int hc,
-    match_id_list_t *matches, usb_address_t address,
-    int config_count)
+static int usb_add_config_descriptor_match_ids(usb_endpoint_pipe_t *pipe,
+    match_id_list_t *matches, int config_count)
 {
 	int final_rc = EOK;
@@ -257,6 +262,6 @@
 		int rc;
 		usb_standard_configuration_descriptor_t config_descriptor;
-		rc = usb_drv_req_get_bare_configuration_descriptor(hc,
-		    address,  config_index, &config_descriptor);
+		rc = usb_request_get_bare_configuration_descriptor(pipe,
+		    config_index, &config_descriptor);
 		if (rc != EOK) {
 			final_rc = rc;
@@ -267,6 +272,6 @@
 		void *full_config_descriptor
 		    = malloc(config_descriptor.total_length);
-		rc = usb_drv_req_get_full_configuration_descriptor(hc,
-		    address, config_index,
+		rc = usb_request_get_full_configuration_descriptor(pipe,
+		    config_index,
 		    full_config_descriptor, config_descriptor.total_length,
 		    &full_config_descriptor_size);
@@ -299,14 +304,13 @@
  * function exits with error.
  *
- * @param hc Open phone to host controller.
+ * @param ctrl_pipe Control pipe to given device (session must be already
+ *	started).
  * @param matches Initialized list of match ids.
- * @param address USB address of the attached device.
- * @return Error code.
- */
-int usb_drv_create_device_match_ids(int hc, match_id_list_t *matches,
-    usb_address_t address)
+ * @return Error code.
+ */
+int usb_device_create_match_ids(usb_endpoint_pipe_t *ctrl_pipe,
+    match_id_list_t *matches)
 {
 	int rc;
-	
 	/*
 	 * Retrieve device descriptor and add matches from it.
@@ -314,10 +318,9 @@
 	usb_standard_device_descriptor_t device_descriptor;
 
-	rc = usb_drv_req_get_device_descriptor(hc, address,
-	    &device_descriptor);
+	rc = usb_request_get_device_descriptor(ctrl_pipe, &device_descriptor);
 	if (rc != EOK) {
 		return rc;
 	}
-	
+
 	rc = usb_drv_create_match_ids_from_device_descriptor(matches,
 	    &device_descriptor);
@@ -325,11 +328,11 @@
 		return rc;
 	}
-	
+
 	/*
 	 * Go through all configurations and add matches
 	 * based on interface class.
 	 */
-	rc = usb_add_config_descriptor_match_ids(hc, matches,
-	    address, device_descriptor.configuration_count);
+	rc = usb_add_config_descriptor_match_ids(ctrl_pipe, matches,
+	    device_descriptor.configuration_count);
 	if (rc != EOK) {
 		return rc;
@@ -347,19 +350,16 @@
 }
 
-
 /** Probe for device kind and register it in devman.
  *
- * @param[in] hc Open phone to the host controller.
+ * @param[in] address Address of the (unknown) attached device.
+ * @param[in] hc_handle Handle of the host controller.
  * @param[in] parent Parent device.
- * @param[in] address Address of the (unknown) attached device.
  * @param[out] child_handle Handle of the child device.
  * @return Error code.
  */
-int usb_drv_register_child_in_devman(int hc, device_t *parent,
-    usb_address_t address, devman_handle_t *child_handle)
-{
-	static size_t device_name_index = 0;
-	static FIBRIL_MUTEX_INITIALIZE(device_name_index_mutex);
-
+int usb_device_register_child_in_devman(usb_address_t address,
+    devman_handle_t hc_handle,
+    device_t *parent, devman_handle_t *child_handle)
+{
 	size_t this_device_name_index;
 
@@ -369,8 +369,20 @@
 	fibril_mutex_unlock(&device_name_index_mutex);
 
-
 	device_t *child = NULL;
 	char *child_name = NULL;
 	int rc;
+	usb_device_connection_t dev_connection;
+	usb_endpoint_pipe_t ctrl_pipe;
+
+	rc = usb_device_connection_initialize(&dev_connection, hc_handle, address);
+	if (rc != EOK) {
+		goto failure;
+	}
+
+	rc = usb_endpoint_pipe_initialize_default_control(&ctrl_pipe,
+	    &dev_connection);
+	if (rc != EOK) {
+		goto failure;
+	}
 
 	child = create_device();
@@ -391,6 +403,16 @@
 	child->name = child_name;
 	child->ops = &child_ops;
-	
-	rc = usb_drv_create_device_match_ids(hc, &child->match_ids, address);
+
+	rc = usb_endpoint_pipe_start_session(&ctrl_pipe);
+	if (rc != EOK) {
+		goto failure;
+	}
+
+	rc = usb_device_create_match_ids(&ctrl_pipe, &child->match_ids);
+	if (rc != EOK) {
+		goto failure;
+	}
+
+	rc = usb_endpoint_pipe_end_session(&ctrl_pipe);
 	if (rc != EOK) {
 		goto failure;
@@ -405,5 +427,5 @@
 		*child_handle = child->handle;
 	}
-	
+
 	return EOK;
 
@@ -419,5 +441,4 @@
 
 	return rc;
-
 }
 
Index: pace/lib/usb/src/remotedrv.c
===================================================================
--- uspace/lib/usb/src/remotedrv.c	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ 	(revision )
@@ -1,437 +1,0 @@
-/*
- * Copyright (c) 2010 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
- * @brief Driver communication for remote drivers (interface implementation).
- */
-#include <usb/hcdhubd.h>
-#include <usbhc_iface.h>
-#include <driver.h>
-#include <bool.h>
-#include <errno.h>
-
-#include "hcdhubd_private.h"
-
-static int remote_get_address(device_t *, devman_handle_t, usb_address_t *);
-
-static int remote_interrupt_out(device_t *, usb_target_t, void *, size_t,
-    usbhc_iface_transfer_out_callback_t, void *);
-static int remote_interrupt_in(device_t *, usb_target_t, void *, size_t,
-    usbhc_iface_transfer_in_callback_t, void *);
-
-static int remote_control_write_setup(device_t *, usb_target_t,
-    void *, size_t,
-    usbhc_iface_transfer_out_callback_t, void *);
-static int remote_control_write_data(device_t *, usb_target_t,
-    void *, size_t,
-    usbhc_iface_transfer_out_callback_t, void *);
-static int remote_control_write_status(device_t *, usb_target_t,
-    usbhc_iface_transfer_in_callback_t, void *);
-
-static int remote_control_read_setup(device_t *, usb_target_t,
-    void *, size_t,
-    usbhc_iface_transfer_out_callback_t, void *);
-static int remote_control_read_data(device_t *, usb_target_t,
-    void *, size_t,
-    usbhc_iface_transfer_in_callback_t, void *);
-static int remote_control_read_status(device_t *, usb_target_t,
-    usbhc_iface_transfer_out_callback_t, void *);
-
-/** Implementation of USB HC interface. */
-usbhc_iface_t usbhc_interface = {
-	.tell_address = remote_get_address,
-	.interrupt_out = remote_interrupt_out,
-	.interrupt_in = remote_interrupt_in,
-	.control_write_setup = remote_control_write_setup,
-	.control_write_data = remote_control_write_data,
-	.control_write_status = remote_control_write_status,
-	.control_read_setup = remote_control_read_setup,
-	.control_read_data = remote_control_read_data,
-	.control_read_status = remote_control_read_status
-};
-
-/** Get USB address for remote USBHC interface.
- *
- * @param dev Device asked for the information.
- * @param handle Devman handle of the USB device.
- * @param address Storage for obtained address.
- * @return Error code.
- */
-int remote_get_address(device_t *dev, devman_handle_t handle,
-    usb_address_t *address)
-{
-	usb_address_t addr = usb_get_address_by_handle(handle);
-	if (addr < 0) {
-		return addr;
-	}
-
-	*address = addr;
-
-	return EOK;
-}
-
-/** Information about pending transaction on HC. */
-typedef struct {
-	/** Target device. */
-	usb_hcd_attached_device_info_t *device;
-	/** Target endpoint. */
-	usb_hc_endpoint_info_t *endpoint;
-
-	/** Callbacks. */
-	union {
-		/** Callback for outgoing transfers. */
-		usbhc_iface_transfer_out_callback_t out_callback;
-		/** Callback for incoming transfers. */
-		usbhc_iface_transfer_in_callback_t in_callback;
-	};
-
-	/** Custom argument for the callback. */
-	void *arg;
-} transfer_info_t;
-
-/** Create new transfer info.
- *
- * @param device Attached device.
- * @param endpoint Endpoint.
- * @param custom_arg Custom argument.
- * @return Transfer info with pre-filled values.
- */
-static transfer_info_t *transfer_info_create(
-    usb_hcd_attached_device_info_t *device, usb_hc_endpoint_info_t *endpoint,
-    void *custom_arg)
-{
-	transfer_info_t *transfer = malloc(sizeof(transfer_info_t));
-
-	transfer->device = device;
-	transfer->endpoint = endpoint;
-	transfer->arg = custom_arg;
-	transfer->out_callback = NULL;
-	transfer->in_callback = NULL;
-
-	return transfer;
-}
-
-/** Destroy transfer info.
- *
- * @param transfer Transfer to be destroyed.
- */
-static void transfer_info_destroy(transfer_info_t *transfer)
-{
-	free(transfer->device);
-	free(transfer->endpoint);
-	free(transfer);
-}
-
-/** Create info about attached device.
- *
- * @param address Device address.
- * @return Device info structure.
- */
-static usb_hcd_attached_device_info_t *create_attached_device_info(
-    usb_address_t address)
-{
-	usb_hcd_attached_device_info_t *dev
-	    = malloc(sizeof(usb_hcd_attached_device_info_t));
-
-	dev->address = address;
-	dev->endpoint_count = 0;
-	dev->endpoints = NULL;
-	list_initialize(&dev->link);
-
-	return dev;
-}
-
-/** Create info about device endpoint.
- *
- * @param endpoint Endpoint number.
- * @param direction Endpoint data direction.
- * @param transfer_type Transfer type of the endpoint.
- * @return Endpoint info structure.
- */
-static usb_hc_endpoint_info_t *create_endpoint_info(usb_endpoint_t endpoint,
-    usb_direction_t direction, usb_transfer_type_t transfer_type)
-{
-	usb_hc_endpoint_info_t *ep = malloc(sizeof(usb_hc_endpoint_info_t));
-	ep->data_toggle = 0;
-	ep->direction = direction;
-	ep->transfer_type = transfer_type;
-	ep->endpoint = endpoint;
-
-	return ep;
-}
-
-
-
-/** Callback for OUT transfers.
- * This callback is called by implementation of HC operations.
- *
- * @param hc Host controller that processed the transfer.
- * @param outcome Transfer outcome.
- * @param arg Custom argument.
- */
-static void remote_out_callback(usb_hc_device_t *hc,
-    usb_transaction_outcome_t outcome, void *arg)
-{
-	transfer_info_t *transfer = (transfer_info_t *) arg;
-	transfer->out_callback(hc->generic, outcome, transfer->arg);
-
-	transfer_info_destroy(transfer);
-}
-
-/** Start an OUT transfer.
- *
- * @param dev Device that shall process the transfer.
- * @param target Target device for the data.
- * @param transfer_type Transfer type.
- * @param data Data buffer.
- * @param size Size of data buffer.
- * @param callback Callback after transfer is complete.
- * @param arg Custom argument to the callback.
- * @return Error code.
- */
-static int remote_out_transfer(device_t *dev, usb_target_t target,
-    usb_transfer_type_t transfer_type, void *data, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	usb_hc_device_t *hc = (usb_hc_device_t *) dev->driver_data;
-
-	if ((hc->transfer_ops == NULL)
-	    || (hc->transfer_ops->transfer_out == NULL)) {
-		return ENOTSUP;
-	}
-
-	transfer_info_t *transfer = transfer_info_create(
-	    create_attached_device_info(target.address),
-	    create_endpoint_info(target.endpoint,
-		USB_DIRECTION_OUT, transfer_type),
-	    arg);
-	transfer->out_callback = callback;
-
-	int rc = hc->transfer_ops->transfer_out(hc,
-	    transfer->device, transfer->endpoint,
-	    data, size,
-	    remote_out_callback, transfer);
-
-	if (rc != EOK) {
-		transfer_info_destroy(transfer);
-		return rc;
-	}
-
-	return EOK;
-}
-
-/** Start a SETUP transfer.
- *
- * @param dev Device that shall process the transfer.
- * @param target Target device for the data.
- * @param transfer_type Transfer type.
- * @param data Data buffer.
- * @param size Size of data buffer.
- * @param callback Callback after transfer is complete.
- * @param arg Custom argument to the callback.
- * @return Error code.
- */
-static int remote_setup_transfer(device_t *dev, usb_target_t target,
-    usb_transfer_type_t transfer_type, void *data, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	usb_hc_device_t *hc = (usb_hc_device_t *) dev->driver_data;
-
-	if ((hc->transfer_ops == NULL)
-	    || (hc->transfer_ops->transfer_setup == NULL)) {
-		return ENOTSUP;
-	}
-
-	transfer_info_t *transfer = transfer_info_create(
-	    create_attached_device_info(target.address),
-	    create_endpoint_info(target.endpoint,
-		USB_DIRECTION_OUT, transfer_type),
-	    arg);
-	transfer->out_callback = callback;
-
-	int rc = hc->transfer_ops->transfer_setup(hc,
-	    transfer->device, transfer->endpoint,
-	    data, size,
-	    remote_out_callback, transfer);
-
-	if (rc != EOK) {
-		transfer_info_destroy(transfer);
-		return rc;
-	}
-
-	return EOK;
-}
-
-/** Callback for IN transfers.
- * This callback is called by implementation of HC operations.
- *
- * @param hc Host controller that processed the transfer.
- * @param outcome Transfer outcome.
- * @param actual_size Size of actually received data.
- * @param arg Custom argument.
- */
-static void remote_in_callback(usb_hc_device_t *hc,
-    size_t actual_size, usb_transaction_outcome_t outcome, void *arg)
-{
-	transfer_info_t *transfer = (transfer_info_t *) arg;
-	transfer->in_callback(hc->generic, outcome, actual_size, transfer->arg);
-
-	transfer_info_destroy(transfer);
-}
-
-/** Start an IN transfer.
- *
- * @param dev Device that shall process the transfer.
- * @param target Target device for the data.
- * @param transfer_type Transfer type.
- * @param data Data buffer.
- * @param size Size of data buffer.
- * @param callback Callback after transfer is complete.
- * @param arg Custom argument to the callback.
- * @return Error code.
- */
-static int remote_in_transfer(device_t *dev, usb_target_t target,
-    usb_transfer_type_t transfer_type, void *data, size_t size,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	usb_hc_device_t *hc = (usb_hc_device_t *) dev->driver_data;
-
-	if ((hc->transfer_ops == NULL)
-	    || (hc->transfer_ops->transfer_in == NULL)) {
-		return ENOTSUP;
-	}
-
-	transfer_info_t *transfer = transfer_info_create(
-	    create_attached_device_info(target.address),
-	    create_endpoint_info(target.endpoint,
-		USB_DIRECTION_OUT, transfer_type),
-	    arg);
-	transfer->in_callback = callback;
-
-	int rc = hc->transfer_ops->transfer_in(hc,
-	    transfer->device, transfer->endpoint,
-	    data, size,
-	    remote_in_callback, transfer);
-
-	if (rc != EOK) {
-		transfer_info_destroy(transfer);
-		return rc;
-	}
-
-	return EOK;
-}
-
-/** Start outgoing interrupt transfer (USBHC remote interface).
- *
- * @param dev Host controller device processing the transfer.
- * @param target Target USB device.
- * @param buffer Data buffer.
- * @param size Data buffer size.
- * @param callback Callback after the transfer is completed.
- * @param arg Custom argument to the callback.
- * @return Error code.
- */
-int remote_interrupt_out(device_t *dev, usb_target_t target,
-    void *buffer, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	return remote_out_transfer(dev, target, USB_TRANSFER_INTERRUPT,
-	    buffer, size, callback, arg);
-}
-
-/** Start incoming interrupt transfer (USBHC remote interface).
- *
- * @param dev Host controller device processing the transfer.
- * @param target Target USB device.
- * @param buffer Data buffer.
- * @param size Data buffer size.
- * @param callback Callback after the transfer is completed.
- * @param arg Custom argument to the callback.
- * @return Error code.
- */
-int remote_interrupt_in(device_t *dev, usb_target_t target,
-    void *buffer, size_t size,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	return remote_in_transfer(dev, target, USB_TRANSFER_INTERRUPT,
-	    buffer, size, callback, arg);
-}
-
-
-int remote_control_write_setup(device_t *device, usb_target_t target,
-    void *buffer, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	return remote_setup_transfer(device, target, USB_TRANSFER_CONTROL,
-	    buffer, size, callback, arg);
-}
-
-int remote_control_write_data(device_t *device, usb_target_t target,
-    void *buffer, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	return remote_out_transfer(device, target, USB_TRANSFER_CONTROL,
-	    buffer, size, callback, arg);
-}
-
-int remote_control_write_status(device_t *device, usb_target_t target,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	return remote_in_transfer(device, target, USB_TRANSFER_CONTROL,
-	    NULL, 0, callback, arg);
-}
-
-int remote_control_read_setup(device_t *device, usb_target_t target,
-    void *buffer, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	return remote_setup_transfer(device, target, USB_TRANSFER_CONTROL,
-	    buffer, size, callback, arg);
-}
-
-int remote_control_read_data(device_t *dev, usb_target_t target,
-    void *buffer, size_t size,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	return remote_in_transfer(dev, target, USB_TRANSFER_CONTROL,
-	    buffer, size, callback, arg);
-}
-
-int remote_control_read_status(device_t *device, usb_target_t target,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	return remote_out_transfer(device, target, USB_TRANSFER_CONTROL,
-	    NULL, 0, callback, arg);
-}
-
-/**
- * @}
- */
Index: uspace/lib/usb/src/usb.c
===================================================================
--- uspace/lib/usb/src/usb.c	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/lib/usb/src/usb.c	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -54,20 +54,4 @@
 }
 
-/** String representation of USB transaction outcome. */
-const char * usb_str_transaction_outcome(usb_transaction_outcome_t o)
-{
-	switch (o) {
-		case USB_OUTCOME_OK:
-			return "ok";
-		case USB_OUTCOME_CRCERROR:
-			return "CRC error";
-		case USB_OUTCOME_BABBLE:
-			return "babble";
-		default:
-			return "unknown";
-	}
-}
-
-
 /**
  * @}
Index: uspace/lib/usb/src/usbdevice.c
===================================================================
--- uspace/lib/usb/src/usbdevice.c	(revision 50ba203e98ce570f05993da83249a116cfffceab)
+++ uspace/lib/usb/src/usbdevice.c	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -0,0 +1,176 @@
+/*
+ * 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
+ * General communication between device drivers and host controller driver.
+ */
+#include <devman.h>
+#include <async.h>
+#include <usb_iface.h>
+#include <usb/usbdevice.h>
+#include <errno.h>
+
+/** Find host controller handle that is ancestor of given device.
+ *
+ * @param[in] device_handle Device devman handle.
+ * @param[out] hc_handle Where to store handle of host controller
+ *	controlling device with @p device_handle handle.
+ * @return Error code.
+ */
+int usb_hc_find(devman_handle_t device_handle, devman_handle_t *hc_handle)
+{
+	int parent_phone = devman_parent_device_connect(device_handle,
+	    IPC_FLAG_BLOCKING);
+	if (parent_phone < 0) {
+		return parent_phone;
+	}
+
+	devman_handle_t h;
+	int rc = async_req_1_1(parent_phone, DEV_IFACE_ID(USB_DEV_IFACE),
+	    IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, &h);
+
+	async_hangup(parent_phone);
+
+	if (rc != EOK) {
+		return rc;
+	}
+
+	if (hc_handle != NULL) {
+		*hc_handle = h;
+	}
+
+	return EOK;
+}
+
+/** Initialize connection to USB host controller.
+ *
+ * @param connection Connection to be initialized.
+ * @param device Device connecting to the host controller.
+ * @return Error code.
+ */
+int usb_hc_connection_initialize_from_device(usb_hc_connection_t *connection,
+    device_t *device)
+{
+	assert(connection);
+
+	if (device == NULL) {
+		return EBADMEM;
+	}
+
+	devman_handle_t hc_handle;
+	int rc = usb_hc_find(device->handle, &hc_handle);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	rc = usb_hc_connection_initialize(connection, hc_handle);
+
+	return rc;
+}
+
+/** Manually initialize connection to USB host controller.
+ *
+ * @param connection Connection to be initialized.
+ * @param hc_handle Devman handle of the host controller.
+ * @return Error code.
+ */
+int usb_hc_connection_initialize(usb_hc_connection_t *connection,
+    devman_handle_t hc_handle)
+{
+	assert(connection);
+
+	connection->hc_handle = hc_handle;
+	connection->hc_phone = -1;
+
+	return EOK;
+}
+
+/** Open connection to host controller.
+ *
+ * @param connection Connection to the host controller.
+ * @return Error code.
+ */
+int usb_hc_connection_open(usb_hc_connection_t *connection)
+{
+	assert(connection);
+
+	if (usb_hc_connection_is_opened(connection)) {
+		return EBUSY;
+	}
+
+	int phone = devman_device_connect(connection->hc_handle, 0);
+	if (phone < 0) {
+		return phone;
+	}
+
+	connection->hc_phone = phone;
+
+	return EOK;
+}
+
+/** Tells whether connection to host controller is opened.
+ *
+ * @param connection Connection to the host controller.
+ * @return Whether connection is opened.
+ */
+bool usb_hc_connection_is_opened(const usb_hc_connection_t *connection)
+{
+	assert(connection);
+
+	return (connection->hc_phone >= 0);
+}
+
+/** Close connection to the host controller.
+ *
+ * @param connection Connection to the host controller.
+ * @return Error code.
+ */
+int usb_hc_connection_close(usb_hc_connection_t *connection)
+{
+	assert(connection);
+
+	if (!usb_hc_connection_is_opened(connection)) {
+		return ENOENT;
+	}
+
+	int rc = async_hangup(connection->hc_phone);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	connection->hc_phone = -1;
+
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/usbdrv.c
===================================================================
--- uspace/lib/usb/src/usbdrv.c	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/lib/usb/src/usbdrv.c	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -49,8 +49,12 @@
 	/** Storage for actual number of bytes transferred. */
 	size_t *size_transferred;
-	/** Initial call replay data. */
+	/** Initial call reply data. */
 	ipc_call_t reply;
 	/** Initial call identifier. */
 	aid_t request;
+	/** Reply data for data read call. */
+	ipc_call_t read_reply;
+	/** Data read call identifier. */
+	aid_t read_request;
 } transfer_info_t;
 
@@ -140,5 +144,4 @@
 
 	if (rc != EOK) {
-		printf("usb_drv_get_my_address over %d failed: %s\n", phone, str_error(rc));
 		return rc;
 	}
@@ -250,4 +253,5 @@
 	}
 
+	transfer->read_request = 0;
 	transfer->size_transferred = NULL;
 	transfer->buffer = NULL;
@@ -315,4 +319,5 @@
 	}
 
+	transfer->read_request = 0;
 	transfer->size_transferred = actual_size;
 	transfer->buffer = buffer;
@@ -327,4 +332,9 @@
 	    &transfer->reply);
 
+	if (buffer != NULL) {
+		transfer->read_request = async_data_read(phone, buffer, size,
+		    &transfer->read_reply);
+	}
+
 	*handle = (usb_handle_t) transfer;
 
@@ -332,45 +342,4 @@
 }
 
-/** Read buffer from HCD.
- *
- * @param phone Opened phone to HCD.
- * @param hash Buffer hash (obtained after completing IN transaction).
- * @param buffer Buffer where to store data data.
- * @param size Buffer size.
- * @param actual_size Storage where actual number of bytes transferred will
- * 	be stored.
- * @return Error status.
- */
-static int read_buffer_in(int phone, sysarg_t hash,
-    void *buffer, size_t size, size_t *actual_size)
-{
-	ipc_call_t answer_data;
-	sysarg_t answer_rc;
-	aid_t req;
-	int rc;
-
-	req = async_send_2(phone,
-	    DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    IPC_M_USBHC_GET_BUFFER,
-	    hash,
-	    &answer_data);
-
-	rc = async_data_read_start(phone, buffer, size);
-	if (rc != EOK) {
-		async_wait_for(req, NULL);
-		return EINVAL;
-	}
-
-	async_wait_for(req, &answer_rc);
-	rc = (int)answer_rc;
-
-	if (rc != EOK) {
-		return rc;
-	}
-
-	*actual_size = IPC_GET_ARG1(answer_data);
-
-	return EOK;
-}
 
 /** Blocks caller until given USB transaction is finished.
@@ -395,10 +364,4 @@
 
 	sysarg_t answer_rc;
-	async_wait_for(transfer->request, &answer_rc);
-
-	if (answer_rc != EOK) {
-		rc = (int) answer_rc;
-		goto leave;
-	}
 
 	/*
@@ -406,26 +369,22 @@
 	 */
 	if ((transfer->buffer != NULL) && (transfer->size > 0)) {
-		/*
-		 * The buffer hash identifies the data on the server
-		 * side.
-		 * We will use it when actually reading-in the data.
-		 */
-		sysarg_t buffer_hash = IPC_GET_ARG1(transfer->reply);
-		if (buffer_hash == 0) {
-			rc = ENOENT;
+		async_wait_for(transfer->read_request, &answer_rc);
+
+		if (answer_rc != EOK) {
+			rc = (int) answer_rc;
 			goto leave;
 		}
 
-		size_t actual_size;
-		rc = read_buffer_in(transfer->phone, buffer_hash,
-		    transfer->buffer, transfer->size, &actual_size);
-
-		if (rc != EOK) {
-			goto leave;
+		if (transfer->size_transferred != NULL) {
+			*(transfer->size_transferred)
+			    = IPC_GET_ARG2(transfer->read_reply);
 		}
-
-		if (transfer->size_transferred) {
-			*(transfer->size_transferred) = actual_size;
-		}
+	}
+
+	async_wait_for(transfer->request, &answer_rc);
+
+	if (answer_rc != EOK) {
+		rc = (int) answer_rc;
+		goto leave;
 	}
 
@@ -499,4 +458,92 @@
     void *setup_packet, size_t setup_packet_size,
     void *buffer, size_t buffer_size,
+    usb_handle_t *handle)
+{
+	// FIXME - check input parameters instead of asserting them
+	assert(phone > 0);
+	assert(setup_packet != NULL);
+	assert(setup_packet_size > 0);
+	assert(((buffer != NULL) && (buffer_size > 0))
+	    || ((buffer == NULL) && (buffer_size == 0)));
+	assert(handle != NULL);
+
+	transfer_info_t *transfer
+	    = (transfer_info_t *) malloc(sizeof(transfer_info_t));
+	if (transfer == NULL) {
+		return ENOMEM;
+	}
+
+	transfer->read_request = 0;
+	transfer->size_transferred = NULL;
+	transfer->buffer = NULL;
+	transfer->size = 0;
+	transfer->phone = phone;
+
+	int rc;
+
+	transfer->request = async_send_3(phone,
+	    DEV_IFACE_ID(USBHC_DEV_IFACE),
+	    IPC_M_USBHC_CONTROL_WRITE,
+	    target.address, target.endpoint,
+	    &transfer->reply);
+
+	rc = async_data_write_start(phone, setup_packet, setup_packet_size);
+	if (rc != EOK) {
+		async_wait_for(transfer->request, NULL);
+		return rc;
+	}
+
+	if (buffer_size > 0) {
+		rc = async_data_write_start(phone, buffer, buffer_size);
+		if (rc != EOK) {
+			async_wait_for(transfer->request, NULL);
+			return rc;
+		}
+	}
+
+	*handle = (usb_handle_t) transfer;
+
+	return EOK;
+}
+
+/** Start control read transfer. */
+int usb_drv_async_control_read_setup(int phone, usb_target_t target,
+    void *buffer, size_t size,
+    usb_handle_t *handle)
+{
+	return async_send_buffer(phone,
+	    IPC_M_USBHC_CONTROL_READ_SETUP,
+	    target,
+	    buffer, size,
+	    handle);
+}
+
+/** Read data during control read transfer. */
+int usb_drv_async_control_read_data(int phone, usb_target_t target,
+    void *buffer, size_t size, size_t *actual_size,
+    usb_handle_t *handle)
+{
+	return async_recv_buffer(phone,
+	    IPC_M_USBHC_CONTROL_READ_DATA,
+	    target,
+	    buffer, size, actual_size,
+	    handle);
+}
+
+/** Finalize control read transfer. */
+int usb_drv_async_control_read_status(int phone, usb_target_t target,
+    usb_handle_t *handle)
+{
+	return async_send_buffer(phone,
+	    IPC_M_USBHC_CONTROL_READ_STATUS,
+	    target,
+	    NULL, 0,
+	    handle);
+}
+
+/** Issue whole control read transfer. */
+int usb_drv_async_control_read(int phone, usb_target_t target,
+    void *setup_packet, size_t setup_packet_size,
+    void *buffer, size_t buffer_size, size_t *actual_size,
     usb_handle_t *handle)
 {
@@ -515,89 +562,4 @@
 	}
 
-	transfer->size_transferred = NULL;
-	transfer->buffer = NULL;
-	transfer->size = 0;
-	transfer->phone = phone;
-
-	int rc;
-
-	transfer->request = async_send_3(phone,
-	    DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    IPC_M_USBHC_CONTROL_WRITE,
-	    target.address, target.endpoint,
-	    &transfer->reply);
-
-	rc = async_data_write_start(phone, setup_packet, setup_packet_size);
-	if (rc != EOK) {
-		async_wait_for(transfer->request, NULL);
-		return rc;
-	}
-
-	rc = async_data_write_start(phone, buffer, buffer_size);
-	if (rc != EOK) {
-		async_wait_for(transfer->request, NULL);
-		return rc;
-	}
-
-	*handle = (usb_handle_t) transfer;
-
-	return EOK;
-}
-
-/** Start control read transfer. */
-int usb_drv_async_control_read_setup(int phone, usb_target_t target,
-    void *buffer, size_t size,
-    usb_handle_t *handle)
-{
-	return async_send_buffer(phone,
-	    IPC_M_USBHC_CONTROL_READ_SETUP,
-	    target,
-	    buffer, size,
-	    handle);
-}
-
-/** Read data during control read transfer. */
-int usb_drv_async_control_read_data(int phone, usb_target_t target,
-    void *buffer, size_t size, size_t *actual_size,
-    usb_handle_t *handle)
-{
-	return async_recv_buffer(phone,
-	    IPC_M_USBHC_CONTROL_READ_DATA,
-	    target,
-	    buffer, size, actual_size,
-	    handle);
-}
-
-/** Finalize control read transfer. */
-int usb_drv_async_control_read_status(int phone, usb_target_t target,
-    usb_handle_t *handle)
-{
-	return async_send_buffer(phone,
-	    IPC_M_USBHC_CONTROL_READ_STATUS,
-	    target,
-	    NULL, 0,
-	    handle);
-}
-
-/** Issue whole control read transfer. */
-int usb_drv_async_control_read(int phone, usb_target_t target,
-    void *setup_packet, size_t setup_packet_size,
-    void *buffer, size_t buffer_size, size_t *actual_size,
-    usb_handle_t *handle)
-{
-	// FIXME - check input parameters instead of asserting them
-	assert(phone > 0);
-	assert(setup_packet != NULL);
-	assert(setup_packet_size > 0);
-	assert(buffer != NULL);
-	assert(buffer_size > 0);
-	assert(handle != NULL);
-
-	transfer_info_t *transfer
-	    = (transfer_info_t *) malloc(sizeof(transfer_info_t));
-	if (transfer == NULL) {
-		return ENOMEM;
-	}
-
 	transfer->size_transferred = actual_size;
 	transfer->buffer = buffer;
@@ -620,4 +582,7 @@
 	}
 
+	transfer->read_request = async_data_read(phone, buffer, buffer_size,
+	    &transfer->read_reply);
+
 	*handle = (usb_handle_t) transfer;
 
Index: uspace/lib/usbvirt/Makefile
===================================================================
--- uspace/lib/usbvirt/Makefile	(revision d81ef61cee954e3114d2e6b6bce5b1033605c7c8)
+++ uspace/lib/usbvirt/Makefile	(revision 50ba203e98ce570f05993da83249a116cfffceab)
@@ -30,5 +30,4 @@
 LIBRARY = libusbvirt
 
-LIBS = $(LIBUSB_PREFIX)/libusb.a
 EXTRA_CFLAGS = -I$(LIBUSB_PREFIX)/include -Iinclude
 
