Index: uspace/drv/uhci-hcd/Makefile
===================================================================
--- uspace/drv/uhci-hcd/Makefile	(revision 1e64b25007a3434f4217cb4a5f05c0ad5cfb253a)
+++ uspace/drv/uhci-hcd/Makefile	(revision 4e38d69166c8e00631d9c20bd9ba6c668aeabe6d)
@@ -33,5 +33,4 @@
 
 SOURCES = \
-	callback.c \
 	iface.c \
 	main.c \
@@ -40,5 +39,6 @@
 	uhci.c \
 	uhci_struct/transfer_descriptor.c \
-	pci.c 
+	pci.c \
+	tracker.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: pace/drv/uhci-hcd/callback.c
===================================================================
--- uspace/drv/uhci-hcd/callback.c	(revision 1e64b25007a3434f4217cb4a5f05c0ad5cfb253a)
+++ 	(revision )
@@ -1,98 +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 <mem.h>
-
-#include <usb/debug.h>
-
-#include "callback.h"
-int callback_init(callback_t *instance, device_t *dev,
-  void *buffer, size_t size, usbhc_iface_transfer_in_callback_t func_in,
-  usbhc_iface_transfer_out_callback_t func_out, void *arg)
-{
-	assert(instance);
-	assert(func_in == NULL || func_out == NULL);
-	if (size > 0) {
-		instance->new_buffer = malloc32(size);
-		if (!instance->new_buffer) {
-			usb_log_error("Failed to allocate device acessible buffer.\n");
-			return ENOMEM;
-		}
-		if (func_out)
-			memcpy(instance->new_buffer, buffer, size);
-	} else {
-		instance->new_buffer = NULL;
-	}
-
-
-	instance->callback_out = func_out;
-	instance->callback_in = func_in;
-	instance->old_buffer = buffer;
-	instance->buffer_size = size;
-	instance->dev = dev;
-	instance->arg = arg;
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-void callback_run(
-callback_t *instance, usb_transaction_outcome_t outcome, size_t act_size)
-{
-	assert(instance);
-
-	/* update the old buffer */
-	if (instance->new_buffer &&
-	  (instance->new_buffer != instance->old_buffer)) {
-		memcpy(instance->old_buffer, instance->new_buffer, instance->buffer_size);
-		free32(instance->new_buffer);
-		instance->new_buffer = NULL;
-	}
-
-	if (instance->callback_in) {
-		assert(instance->callback_out == NULL);
-		usb_log_debug("Callback in: %p %x %d.\n",
-		  instance->callback_in, outcome, act_size);
-		instance->callback_in(
-		  instance->dev, outcome, act_size, instance->arg);
-	} else {
-		assert(instance->callback_out);
-		assert(instance->callback_in == NULL);
-		usb_log_debug("Callback out: %p %p %x %p .\n",
-		 instance->callback_out, instance->dev, outcome, instance->arg);
-		instance->callback_out(
-		  instance->dev, outcome, instance->arg);
-	}
-}
-/**
- * @}
- */
Index: pace/drv/uhci-hcd/callback.h
===================================================================
--- uspace/drv/uhci-hcd/callback.h	(revision 1e64b25007a3434f4217cb4a5f05c0ad5cfb253a)
+++ 	(revision )
@@ -1,95 +1,0 @@
-/*
- * Copyright (c) 2010 Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/** @addtogroup usb
- * @{
- */
-/** @file
- * @brief UHCI driver
- */
-#ifndef DRV_UHCI_CALLBACK_H
-#define DRV_UHCI_CALLBACK_H
-
-#include <usbhc_iface.h>
-#include <usb/usb.h>
-
-#include "utils/malloc32.h"
-
-typedef struct callback
-{
-	usbhc_iface_transfer_in_callback_t callback_in;
-	usbhc_iface_transfer_out_callback_t callback_out;
-	void *old_buffer;
-	void *new_buffer;
-	void *arg;
-	size_t buffer_size;
-	size_t actual_size;
-	device_t *dev;
-} callback_t;
-
-
-int callback_init(callback_t *instance, device_t *dev,
-  void *buffer, size_t size, usbhc_iface_transfer_in_callback_t func_in,
-  usbhc_iface_transfer_out_callback_t func_out, void *arg);
-
-#define callback_in_init(instance, dev, buffer, size, func, arg) \
-	callback_init(instance, dev, buffer, size, func, NULL, arg)
-
-#define callback_out_init(instance, dev, buffer, size, func, arg) \
-	callback_init(instance, dev, buffer, size, func, NULL, arg)
-
-static inline callback_t *callback_get(device_t *dev,
-  void *buffer, size_t size, usbhc_iface_transfer_in_callback_t func_in,
-  usbhc_iface_transfer_out_callback_t func_out, void *arg)
-{
-	callback_t *instance = malloc(sizeof(callback_t));
-	if (callback_init(instance, dev, buffer, size, func_in, func_out, arg)) {
-		free(instance);
-		instance = NULL;
-	}
-	return instance;
-}
-
-static inline void callback_fini(callback_t *instance)
-{
-	assert(instance);
-	if (instance->new_buffer)
-		free32(instance->new_buffer);
-}
-
-static inline void callback_dispose(callback_t *instance)
-{
-	callback_fini(instance);
-	free(instance);
-}
-
-void callback_run(
-  callback_t *instance, usb_transaction_outcome_t outcome, size_t act_size);
-#endif
-/**
- * @}
- */
Index: uspace/drv/uhci-hcd/iface.c
===================================================================
--- uspace/drv/uhci-hcd/iface.c	(revision 1e64b25007a3434f4217cb4a5f05c0ad5cfb253a)
+++ uspace/drv/uhci-hcd/iface.c	(revision 4e38d69166c8e00631d9c20bd9ba6c668aeabe6d)
@@ -106,9 +106,13 @@
     usbhc_iface_transfer_out_callback_t callback, void *arg)
 {
-	assert(dev);
-	uhci_t *hc = dev_to_uhci(dev);
-	assert(hc);
-	return uhci_transfer(hc, dev, target, USB_TRANSFER_INTERRUPT, 0, USB_PID_OUT,
-		false, data, size, callback, NULL, 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;
 }
 /*----------------------------------------------------------------------------*/
@@ -117,9 +121,43 @@
     usbhc_iface_transfer_in_callback_t callback, void *arg)
 {
-	assert(dev);
-	uhci_t *hc = dev_to_uhci(dev);
-	assert(hc);
-	return uhci_transfer(hc, dev, target, USB_TRANSFER_INTERRUPT, 0, USB_PID_IN,
-		false, data, size, NULL, callback, 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,
+    usbhc_iface_transfer_out_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, 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;
 }
 /*----------------------------------------------------------------------------*/
@@ -128,9 +166,11 @@
     usbhc_iface_transfer_out_callback_t callback, void *arg)
 {
-	assert(dev);
-	uhci_t *hc = dev_to_uhci(dev);
-	assert(hc);
-	return uhci_transfer(hc, dev, target, USB_TRANSFER_CONTROL, 0, USB_PID_SETUP,
-		false, data, size, callback, NULL, 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;
 }
 /*----------------------------------------------------------------------------*/
@@ -139,9 +179,10 @@
     usbhc_iface_transfer_out_callback_t callback, void *arg)
 {
-	assert(dev);
-	uhci_t *hc = dev_to_uhci(dev);
-	assert(hc);
-	return uhci_transfer(hc, dev, target, USB_TRANSFER_CONTROL, 1, USB_PID_OUT,
-		false, data, size, callback, NULL, 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;
 }
 /*----------------------------------------------------------------------------*/
@@ -149,9 +190,10 @@
     usbhc_iface_transfer_in_callback_t callback, void *arg)
 {
-	assert(dev);
-	uhci_t *hc = dev_to_uhci(dev);
-	assert(hc);
-	return uhci_transfer(hc, dev, target, USB_TRANSFER_CONTROL, 0, USB_PID_IN,
-		false, NULL, 0, NULL, callback, 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;
 }
 /*----------------------------------------------------------------------------*/
@@ -160,9 +202,11 @@
     usbhc_iface_transfer_out_callback_t callback, void *arg)
 {
-	assert(dev);
-	uhci_t *hc = dev_to_uhci(dev);
-	assert(hc);
-	return uhci_transfer(hc, dev, target, USB_TRANSFER_CONTROL, 0, USB_PID_SETUP,
-		false, data, size, callback, NULL, 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;
 }
 /*----------------------------------------------------------------------------*/
@@ -171,9 +215,10 @@
     usbhc_iface_transfer_in_callback_t callback, void *arg)
 {
-	assert(dev);
-	uhci_t *hc = dev_to_uhci(dev);
-	assert(hc);
-	return uhci_transfer(hc, dev, target, USB_TRANSFER_CONTROL, 1, USB_PID_IN,
-		false, data, size, NULL, callback, 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;
 }
 /*----------------------------------------------------------------------------*/
@@ -181,12 +226,12 @@
     usbhc_iface_transfer_out_callback_t callback, void *arg)
 {
-	assert(dev);
-	uhci_t *hc = dev_to_uhci(dev);
-	assert(hc);
-	return uhci_transfer(hc, dev, target, USB_TRANSFER_CONTROL, 0, USB_PID_OUT,
-		false, NULL, 0, callback, NULL, 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);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
 usbhc_iface_t uhci_iface = {
 	.tell_address = get_address,
@@ -200,4 +245,7 @@
 	.interrupt_out = interrupt_out,
 	.interrupt_in = interrupt_in,
+
+	.control_read = control_read,
+	.control_write = control_write,
 
 	.control_write_setup = control_write_setup,
Index: uspace/drv/uhci-hcd/tracker.c
===================================================================
--- uspace/drv/uhci-hcd/tracker.c	(revision 4e38d69166c8e00631d9c20bd9ba6c668aeabe6d)
+++ uspace/drv/uhci-hcd/tracker.c	(revision 4e38d69166c8e00631d9c20bd9ba6c668aeabe6d)
@@ -0,0 +1,497 @@
+/*
+ * 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: uspace/drv/uhci-hcd/tracker.h
===================================================================
--- uspace/drv/uhci-hcd/tracker.h	(revision 4e38d69166c8e00631d9c20bd9ba6c668aeabe6d)
+++ uspace/drv/uhci-hcd/tracker.h	(revision 4e38d69166c8e00631d9c20bd9ba6c668aeabe6d)
@@ -0,0 +1,102 @@
+/*
+ * 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 1e64b25007a3434f4217cb4a5f05c0ad5cfb253a)
+++ uspace/drv/uhci-hcd/transfer_list.c	(revision 4e38d69166c8e00631d9c20bd9ba6c668aeabe6d)
@@ -41,6 +41,4 @@
 {
 	assert(instance);
-	instance->first = NULL;
-	instance->last = NULL;
 	instance->next = NULL;
 	instance->name = name;
@@ -66,33 +64,39 @@
 }
 /*----------------------------------------------------------------------------*/
-int transfer_list_append(
-  transfer_list_t *instance, transfer_descriptor_t *transfer)
+void transfer_list_add_tracker(transfer_list_t *instance, tracker_t *tracker)
 {
 	assert(instance);
-	assert(transfer);
+	assert(tracker);
 
-	uint32_t pa = (uintptr_t)addr_to_phys(transfer);
+	uint32_t pa = (uintptr_t)addr_to_phys(tracker->td);
 	assert((pa & LINK_POINTER_ADDRESS_MASK) == pa);
 
-	/* empty list */
-	if (instance->first == NULL) {
-		assert(instance->last == NULL);
-		instance->first = instance->last = transfer;
-	} else {
-		assert(instance->last);
-		instance->last->next_va = transfer;
 
-		assert(instance->last->next & LINK_POINTER_TERMINATE_FLAG);
-		instance->last->next = (pa & LINK_POINTER_ADDRESS_MASK);
-		instance->last = transfer;
+	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);
+		/* there is nothing scheduled */
+		instance->last_tracker = tracker;
+		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);
+		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;
 
-	assert(instance->queue_head);
+	usb_log_debug2("Added td(%X:%X) to queue %s last.\n",
+		tracker->td->status, tracker->td->device, instance->name);
+
+	/* check again, may be use atomic compare and swap */
 	if (instance->queue_head->element & LINK_POINTER_TERMINATE_FLAG) {
-		instance->queue_head->element = (pa & LINK_POINTER_ADDRESS_MASK);
+		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);
 	}
-	usb_log_debug("Successfully added transfer to the hc queue %s.\n",
-	  instance->name);
-	return EOK;
 }
 /**
Index: uspace/drv/uhci-hcd/transfer_list.h
===================================================================
--- uspace/drv/uhci-hcd/transfer_list.h	(revision 1e64b25007a3434f4217cb4a5f05c0ad5cfb253a)
+++ uspace/drv/uhci-hcd/transfer_list.h	(revision 4e38d69166c8e00631d9c20bd9ba6c668aeabe6d)
@@ -36,10 +36,10 @@
 
 #include "uhci_struct/queue_head.h"
-#include "uhci_struct/transfer_descriptor.h"
+#include "tracker.h"
 
 typedef struct transfer_list
 {
-	transfer_descriptor_t *first;
-	transfer_descriptor_t *last;
+	tracker_t *last_tracker;
+
 	queue_head_t *queue_head;
 	uint32_t queue_head_pa;
@@ -58,6 +58,6 @@
 }
 
-int transfer_list_append(
-  transfer_list_t *instance, transfer_descriptor_t *transfer);
+
+void transfer_list_add_tracker(transfer_list_t *instance, tracker_t *tracker);
 
 #endif
Index: uspace/drv/uhci-hcd/uhci.c
===================================================================
--- uspace/drv/uhci-hcd/uhci.c	(revision 1e64b25007a3434f4217cb4a5f05c0ad5cfb253a)
+++ uspace/drv/uhci-hcd/uhci.c	(revision 4e38d69166c8e00631d9c20bd9ba6c668aeabe6d)
@@ -33,4 +33,5 @@
  */
 #include <errno.h>
+#include <adt/list.h>
 
 #include <usb/debug.h>
@@ -42,4 +43,6 @@
 static int uhci_clean_finished(void *arg);
 static int uhci_debug_checker(void *arg);
+static bool allowed_usb_packet(
+	bool low_speed, usb_transfer_type_t, size_t size);
 
 int uhci_init(uhci_t *instance, void *regs, size_t reg_size)
@@ -84,6 +87,8 @@
 
 	const uintptr_t pa = (uintptr_t)addr_to_phys(instance->frame_list);
-
 	pio_write_32(&instance->registers->flbaseadd, (uint32_t)pa);
+
+	list_initialize(&instance->tracker_list);
+	fibril_mutex_initialize(&instance->tracker_list_mutex);
 
 	instance->cleaner = fibril_create(uhci_clean_finished, instance);
@@ -93,5 +98,5 @@
 	fibril_add_ready(instance->debug_checker);
 
-	/* Start the hc with large(64b) packet FSBR */
+	/* Start the hc with large(64B) packet FSBR */
 	pio_write_16(&instance->registers->usbcmd,
 	    UHCI_CMD_RUN_STOP | UHCI_CMD_MAX_PACKET);
@@ -147,73 +152,39 @@
 }
 /*----------------------------------------------------------------------------*/
-int uhci_transfer(
-  uhci_t *instance,
-  device_t *dev,
-  usb_target_t target,
-  usb_transfer_type_t transfer_type,
-	bool toggle,
-  usb_packet_id pid,
-	bool low_speed,
-  void *buffer, size_t size,
-  usbhc_iface_transfer_out_callback_t callback_out,
-  usbhc_iface_transfer_in_callback_t callback_in,
-  void *arg)
-{
-	// TODO: Add support for isochronous transfers
-	if (transfer_type == USB_TRANSFER_ISOCHRONOUS) {
-		usb_log_warning("ISO transfer not supported.\n");
+int uhci_schedule(uhci_t *instance, tracker_t *tracker)
+{
+	assert(instance);
+	assert(tracker);
+	const int low_speed = (tracker->speed == LOW_SPEED);
+	if (!allowed_usb_packet(
+	    low_speed, tracker->transfer_type, tracker->packet_size)) {
+		usb_log_warning("Invalid USB packet specified %s SPEED %d %zu.\n",
+			  low_speed ? "LOW" : "FULL" , tracker->transfer_type,
+		    tracker->packet_size);
 		return ENOTSUP;
 	}
-
-	if (transfer_type == USB_TRANSFER_INTERRUPT
-	  && size >= 64) {
-		usb_log_warning("Interrupt transfer too big %zu.\n", size);
-		return ENOTSUP;
-	}
-
-	if (size >= 1024) {
-		usb_log_warning("Transfer too big.\n");
-		return ENOTSUP;
-	}
-	transfer_list_t *list = instance->transfers[low_speed][transfer_type];
-	if (!list) {
-		usb_log_warning("UNSUPPORTED transfer %d-%d.\n", low_speed, transfer_type);
-		return ENOTSUP;
-	}
-
-	transfer_descriptor_t *td = NULL;
-	callback_t *job = NULL;
-	int ret = EOK;
-	assert(dev);
-
-#define CHECK_RET_TRANS_FREE_JOB_TD(message) \
-	if (ret != EOK) { \
-		usb_log_error(message); \
-		if (job) { \
-			callback_dispose(job); \
-		} \
-		if (td) { free32(td); } \
-		return ret; \
-	} else (void) 0
-
-	job = callback_get(dev, buffer, size, callback_in, callback_out, arg);
-	ret = job ? EOK : ENOMEM;
-	CHECK_RET_TRANS_FREE_JOB_TD("Failed to allocate callback structure.\n");
-
-	td = transfer_descriptor_get(3, size, false, target, pid, job->new_buffer);
-	ret = td ? EOK : ENOMEM;
-	CHECK_RET_TRANS_FREE_JOB_TD("Failed to setup transfer descriptor.\n");
-
-	td->callback = job;
-
-
-	usb_log_debug("Appending a new transfer to queue %s.\n", list->name);
-
-	ret = transfer_list_append(list, td);
-	CHECK_RET_TRANS_FREE_JOB_TD("Failed to append transfer descriptor.\n");
+	/* 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];
+	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());
 
 	return EOK;
 }
-/*---------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
 int uhci_clean_finished(void* arg)
 {
@@ -223,34 +194,45 @@
 
 	while(1) {
-		usb_log_debug("Running cleaning fibril on: %p.\n", instance);
-		/* iterate all transfer queues */
-		transfer_list_t *current_list = &instance->transfers_interrupt;
-		while (current_list) {
-			/* Remove inactive transfers from the top of the queue
-			 * TODO: should I reach queue head or is this enough? */
-			volatile transfer_descriptor_t * it =
-				current_list->first;
-			usb_log_debug("Running cleaning fibril on queue: %s (%s).\n",
-				current_list->name, it ? "SOMETHING" : "EMPTY");
-
-			if (it) {
-				usb_log_debug("First in queue: %p (%x) PA:%x.\n",
-					it, it->status, addr_to_phys((void*)it) );
-				usb_log_debug("First to send: %x\n",
-					(current_list->queue_head->element) );
+		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);
 			}
-
-			while (current_list->first &&
-			 !(current_list->first->status & TD_STATUS_ERROR_ACTIVE)) {
-				transfer_descriptor_t *transfer = current_list->first;
-				usb_log_info("Inactive transfer calling callback with status %x.\n",
-				  transfer->status);
-				current_list->first = transfer->next_va;
-				transfer_descriptor_dispose(transfer);
-			}
-			if (!current_list->first)
-				current_list->last = current_list->first;
-
-			current_list = current_list->next;
+			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);
 		}
 		async_usleep(UHCI_CLEANER_TIMEOUT);
@@ -311,4 +293,21 @@
 	return 0;
 }
+/*----------------------------------------------------------------------------*/
+bool allowed_usb_packet(
+	bool low_speed, usb_transfer_type_t transfer, size_t size)
+{
+	/* see USB specification chapter 5.5-5.8 for magic numbers used here */
+	switch(transfer) {
+		case USB_TRANSFER_ISOCHRONOUS:
+			return (!low_speed && size < 1024);
+		case USB_TRANSFER_INTERRUPT:
+			return size <= (low_speed ? 8 : 64);
+		case USB_TRANSFER_CONTROL: /* device specifies its own max size */
+			return (size <= (low_speed ? 8 : 64));
+		case USB_TRANSFER_BULK: /* device specifies its own max size */
+			return (!low_speed && size <= 64);
+	}
+	return false;
+}
 /**
  * @}
Index: uspace/drv/uhci-hcd/uhci.h
===================================================================
--- uspace/drv/uhci-hcd/uhci.h	(revision 1e64b25007a3434f4217cb4a5f05c0ad5cfb253a)
+++ uspace/drv/uhci-hcd/uhci.h	(revision 4e38d69166c8e00631d9c20bd9ba6c668aeabe6d)
@@ -37,4 +37,6 @@
 
 #include <fibril.h>
+#include <fibril_synch.h>
+#include <adt/list.h>
 
 #include <usb/addrkeep.h>
@@ -42,4 +44,5 @@
 
 #include "transfer_list.h"
+#include "tracker.h"
 
 typedef struct uhci_regs {
@@ -68,8 +71,7 @@
 } regs_t;
 
-#define TRANSFER_QUEUES 4
 #define UHCI_FRAME_LIST_COUNT 1024
 #define UHCI_CLEANER_TIMEOUT 10000
-#define UHCI_DEBUGER_TIMEOUT 500000
+#define UHCI_DEBUGER_TIMEOUT 5000000
 
 typedef struct uhci {
@@ -78,4 +80,7 @@
 
 	link_pointer_t *frame_list;
+
+	link_t tracker_list;
+	fibril_mutex_t tracker_list_mutex;
 
 	transfer_list_t transfers_bulk_full;
@@ -108,4 +113,6 @@
   void *arg );
 
+int uhci_schedule(uhci_t *instance, tracker_t *tracker);
+
 static inline uhci_t * dev_to_uhci(device_t *dev)
 	{ return (uhci_t*)dev->driver_data; }
Index: uspace/drv/uhci-hcd/uhci_struct/queue_head.h
===================================================================
--- uspace/drv/uhci-hcd/uhci_struct/queue_head.h	(revision 1e64b25007a3434f4217cb4a5f05c0ad5cfb253a)
+++ uspace/drv/uhci-hcd/uhci_struct/queue_head.h	(revision 4e38d69166c8e00631d9c20bd9ba6c668aeabe6d)
@@ -43,6 +43,6 @@
 
 typedef struct queue_head {
-	link_pointer_t next_queue;
-	link_pointer_t element;
+	volatile link_pointer_t next_queue;
+	volatile link_pointer_t element;
 } __attribute__((packed)) queue_head_t;
 
Index: uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c
===================================================================
--- uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c	(revision 1e64b25007a3434f4217cb4a5f05c0ad5cfb253a)
+++ uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c	(revision 4e38d69166c8e00631d9c20bd9ba6c668aeabe6d)
@@ -32,25 +32,26 @@
  * @brief UHCI driver
  */
+#include <errno.h>
 #include <usb/debug.h>
 
 #include "transfer_descriptor.h"
+#include "utils/malloc32.h"
 
 void transfer_descriptor_init(transfer_descriptor_t *instance,
-  int error_count, size_t size, bool isochronous, usb_target_t target,
-	int pid, void *buffer)
+    int error_count, size_t size, bool toggle, bool isochronous,
+    usb_target_t target, int pid, void *buffer)
 {
 	assert(instance);
 
-	instance->next =
-	  0 | LINK_POINTER_TERMINATE_FLAG;
+	instance->next = 0 | LINK_POINTER_TERMINATE_FLAG;
 
-
-	assert(size < 1024);
 	instance->status = 0
 	  | ((error_count & TD_STATUS_ERROR_COUNT_MASK) << TD_STATUS_ERROR_COUNT_POS)
 	  | TD_STATUS_ERROR_ACTIVE;
 
+	assert(size < 1024);
 	instance->device = 0
 		| (((size - 1) & TD_DEVICE_MAXLEN_MASK) << TD_DEVICE_MAXLEN_POS)
+		| (toggle ? TD_DEVICE_DATA_TOGGLE_ONE_FLAG : 0)
 		| ((target.address & TD_DEVICE_ADDRESS_MASK) << TD_DEVICE_ADDRESS_POS)
 		| ((target.endpoint & TD_DEVICE_ENDPOINT_MASK) << TD_DEVICE_ENDPOINT_POS)
@@ -58,7 +59,4 @@
 
 	instance->buffer_ptr = 0;
-
-	instance->next_va = NULL;
-	instance->callback = NULL;
 
 	if (size) {
@@ -106,16 +104,15 @@
 		return USB_OUTCOME_CRCERROR;
 
-	assert((((status >> TD_STATUS_ERROR_POS) & TD_STATUS_ERROR_MASK)
-	| TD_STATUS_ERROR_RESERVED) == TD_STATUS_ERROR_RESERVED);
+//	assert((((status >> TD_STATUS_ERROR_POS) & TD_STATUS_ERROR_MASK)
+//	| TD_STATUS_ERROR_RESERVED) == TD_STATUS_ERROR_RESERVED);
 	return USB_OUTCOME_OK;
 }
-
-void transfer_descriptor_fini(transfer_descriptor_t *instance)
+/*----------------------------------------------------------------------------*/
+int transfer_descriptor_status(transfer_descriptor_t *instance)
 {
 	assert(instance);
-	callback_run(instance->callback,
-		convert_outcome(instance->status),
-		((instance->status >> TD_STATUS_ACTLEN_POS) + 1) & TD_STATUS_ACTLEN_MASK
-	);
+	if (convert_outcome(instance->status))
+		return EINVAL; //TODO: use sane error value here
+	return EOK;
 }
 /**
Index: uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h
===================================================================
--- uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h	(revision 1e64b25007a3434f4217cb4a5f05c0ad5cfb253a)
+++ uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h	(revision 4e38d69166c8e00631d9c20bd9ba6c668aeabe6d)
@@ -38,6 +38,4 @@
 #include <usb/usb.h>
 
-#include "utils/malloc32.h"
-#include "callback.h"
 #include "link_pointer.h"
 
@@ -86,46 +84,22 @@
 	volatile uint32_t buffer_ptr;
 
-	/* there is 16 bytes of data available here
-	 * those are used to store callback pointer
-	 * and next pointer. Thus, there is some free space
-	 * on 32bits systems.
+	/* there is 16 bytes of data available here, according to UHCI
+	 * Design guide, according to linux kernel the hardware does not care
+	 * we don't use it anyway
 	 */
-	struct transfer_descriptor *next_va;
-	callback_t *callback;
 } __attribute__((packed)) transfer_descriptor_t;
 
 
 void transfer_descriptor_init(transfer_descriptor_t *instance,
-  int error_count, size_t size, bool isochronous, usb_target_t target,
-	int pid, void *buffer);
+    int error_count, size_t size, bool toggle, bool isochronous,
+    usb_target_t target, int pid, void *buffer);
 
-static inline transfer_descriptor_t * transfer_descriptor_get(
-  int error_count, size_t size, bool isochronous, usb_target_t target,
-  int pid, void *buffer)
-{
-	transfer_descriptor_t * instance =
-	  malloc32(sizeof(transfer_descriptor_t));
+int transfer_descriptor_status(transfer_descriptor_t *instance);
 
-	if (instance)
-		transfer_descriptor_init(
-		  instance, error_count, size, isochronous, target, pid, buffer);
-	return instance;
-}
-
-void transfer_descriptor_fini(transfer_descriptor_t *instance);
-
-static inline void transfer_descriptor_dispose(transfer_descriptor_t *instance)
+static inline bool transfer_descriptor_is_active(
+    transfer_descriptor_t *instance)
 {
 	assert(instance);
-	transfer_descriptor_fini(instance);
-	free32(instance);
-}
-
-static inline void transfer_descriptor_append(
-  transfer_descriptor_t *instance, transfer_descriptor_t *item)
-{
-	assert(instance);
-	instance->next_va = item;
-	instance->next = (uintptr_t)addr_to_phys( item ) & LINK_POINTER_ADDRESS_MASK;
+	return (instance->status & TD_STATUS_ERROR_ACTIVE) != 0;
 }
 #endif
Index: uspace/drv/uhci-rhd/main.c
===================================================================
--- uspace/drv/uhci-rhd/main.c	(revision 1e64b25007a3434f4217cb4a5f05c0ad5cfb253a)
+++ uspace/drv/uhci-rhd/main.c	(revision 4e38d69166c8e00631d9c20bd9ba6c668aeabe6d)
@@ -102,5 +102,5 @@
 int main(int argc, char *argv[])
 {
-	usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
+	usb_log_enable(USB_LOG_LEVEL_ERROR, NAME);
 	return driver_main(&uhci_rh_driver);
 }
Index: uspace/drv/usbhid/hid.h
===================================================================
--- uspace/drv/usbhid/hid.h	(revision 1e64b25007a3434f4217cb4a5f05c0ad5cfb253a)
+++ uspace/drv/usbhid/hid.h	(revision 4e38d69166c8e00631d9c20bd9ba6c668aeabe6d)
@@ -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 1e64b25007a3434f4217cb4a5f05c0ad5cfb253a)
+++ uspace/drv/usbhid/main.c	(revision 4e38d69166c8e00631d9c20bd9ba6c668aeabe6d)
@@ -47,5 +47,5 @@
 #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>
@@ -262,5 +262,4 @@
 }
 
-# if 0
 /*
  * Kbd functions
@@ -281,7 +280,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 +303,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 +319,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);
 	
@@ -363,7 +364,9 @@
 	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 +379,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,4 +392,12 @@
 	 * Initialize device pipes.
 	 */
+	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;
+	}
+
 	rc = usb_endpoint_pipe_initialize(&kbd_dev->poll_pipe, &kbd_dev->wire,
 	    GUESSED_POLL_ENDPOINT, USB_TRANSFER_INTERRUPT, USB_DIRECTION_IN);
@@ -433,4 +408,16 @@
 	}
 
+	/*
+	 * 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);
+	usbkbd_process_descriptors(kbd_dev);
+	usb_endpoint_pipe_end_session(&kbd_dev->ctrl_pipe);
 
 	return kbd_dev;
