Index: uspace/drv/uhci-hcd/tracker.c
===================================================================
--- uspace/drv/uhci-hcd/tracker.c	(revision da17cf0f62be93cfcd6ddcf6028b03a49898563d)
+++ uspace/drv/uhci-hcd/tracker.c	(revision 9a818a93338eb8410dcc0917f9c3d49086134801)
@@ -33,9 +33,10 @@
  */
 #include <errno.h>
-#include <mem.h>
 
 #include <usb/debug.h>
 
 #include "tracker.h"
+#include "uhci.h"
+#include "utils/malloc32.h"
 
 #define SETUP_PACKET_DATA_SIZE 8
@@ -44,23 +45,36 @@
 #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);
-
-
-int tracker_init(tracker_t *instance, device_t *dev, usb_target_t target,
-    size_t max_packet_size, dev_speed_t speed, char *buffer, size_t size,
+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(instance);
 	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");
-		return ENOMEM;
+		free(instance);
+		return NULL;
 	}
 
@@ -69,5 +83,6 @@
 		usb_log_error("Failed to allocate device acessible buffer.\n");
 		free32(instance->td);
-		return ENOMEM;
+		free(instance);
+		return NULL;
 	}
 	instance->max_packet_size = max_packet_size;
@@ -77,4 +92,5 @@
 	link_initialize(&instance->link);
 	instance->target = target;
+	instance->transfer_type = transfer_type;
 
 	if (func_out)
@@ -87,5 +103,6 @@
 	instance->arg = arg;
 	instance->toggle = 0;
-	return EOK;
+
+	return instance;
 }
 /*----------------------------------------------------------------------------*/
@@ -94,12 +111,16 @@
 	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, false, instance->target, USB_PID_SETUP,
 	    instance->packet);
+
 	instance->buffer_offset += SETUP_PACKET_DATA_SIZE;
 	instance->next_step = tracker_control_write_data;
-	//TODO: add to scheduler
+
+	tracker_schedule(instance);
 }
 /*----------------------------------------------------------------------------*/
@@ -108,12 +129,16 @@
 	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, false, instance->target, USB_PID_SETUP,
 	    instance->packet);
+
 	instance->buffer_offset += SETUP_PACKET_DATA_SIZE;
 	instance->next_step = tracker_control_read_data;
-	//TODO: add to scheduler
+
+	tracker_schedule(instance);
 }
 /*----------------------------------------------------------------------------*/
@@ -136,9 +161,11 @@
 	/* 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, false, instance->target, USB_PID_IN,
-			instance->packet);
-	// TODO: add to uhci scheduler
+	    instance->buffer_size - instance->buffer_offset);
+
+	transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
+	    instance->packet_size, false, instance->target, USB_PID_IN,
+	    instance->packet);
+
+	tracker_schedule(instance);
 
 	/* set next step */
@@ -166,11 +193,12 @@
 	/* prepare next packet, copy data to packet */
 	instance->packet_size =	MIN(instance->max_packet_size,
-			instance->buffer_size - instance->buffer_offset);
+	    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, false, instance->target, USB_PID_OUT,
-			instance->packet);
-	// TODO: add to uhci scheduler
+	    instance->packet_size, false, instance->target, USB_PID_OUT,
+	    instance->packet);
+
+	tracker_schedule(instance);
 
 	/* set next step */
@@ -202,6 +230,7 @@
 	instance->packet_size =	0;
 	transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
-			0, false, instance->target, USB_PID_OUT, NULL);
-	// TODO: add to uhci scheduler
+	    0, false, instance->target, USB_PID_OUT, NULL);
+
+	tracker_schedule(instance);
 
 	/* set next step, callback and cleanup */
@@ -229,6 +258,7 @@
 	instance->packet_size =	0;
 	transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
-			0, false, instance->target, USB_PID_OUT, NULL);
-	// TODO: add to uhci scheduler
+	    0, false, instance->target, USB_PID_OUT, NULL);
+
+	tracker_schedule(instance);
 
 	/* set next step, callback and cleanup */
@@ -288,4 +318,13 @@
 	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)
@@ -293,12 +332,16 @@
 	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, false, instance->target, USB_PID_SETUP,
 	    instance->packet);
+
 	instance->buffer_offset += SETUP_PACKET_DATA_SIZE;
 	instance->next_step = tracker_call_out_and_dispose;
-	//TODO: add to scheduler
+
+	tracker_schedule(instance);
 }
 
@@ -307,10 +350,14 @@
 	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, false, instance->target, USB_PID_OUT,
-			instance->packet);
+
+	transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
+	    instance->packet_size, false, instance->target, USB_PID_OUT,
+	    instance->packet);
 	instance->next_step = tracker_call_out_and_dispose;
+
+	tracker_schedule(instance);
 }
 
@@ -319,9 +366,14 @@
 	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, false, instance->target, USB_PID_IN,
-			instance->packet);
+
+	transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
+	    instance->packet_size, false, instance->target, USB_PID_IN,
+	    instance->packet);
+
 	instance->next_step = tracker_call_in_and_dispose;
+
+	tracker_schedule(instance);
 }
 
@@ -334,8 +386,11 @@
 
 	instance->packet_size = instance->max_packet_size;
-	transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
-			instance->packet_size, false, instance->target, USB_PID_IN,
-			instance->packet);
 	instance->next_step = tracker_call_in_and_dispose;
+
+	transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
+	    instance->packet_size, false, instance->target, USB_PID_IN,
+	    instance->packet);
+
+	tracker_schedule(instance);
 }
 
@@ -348,8 +403,11 @@
 
 	instance->packet_size = instance->max_packet_size;
-	transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
-			instance->packet_size, false, instance->target, USB_PID_OUT,
-			instance->packet);
 	instance->next_step = tracker_call_out_and_dispose;
+
+	transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
+	    instance->packet_size, 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 da17cf0f62be93cfcd6ddcf6028b03a49898563d)
+++ uspace/drv/uhci-hcd/tracker.h	(revision 9a818a93338eb8410dcc0917f9c3d49086134801)
@@ -51,4 +51,5 @@
 	link_t link;
 	usb_target_t target;
+	usb_transfer_type_t transfer_type;
 	union {
 		usbhc_iface_transfer_in_callback_t callback_in;
@@ -70,6 +71,7 @@
 
 
-int tracker_init(tracker_t *instance, device_t *dev, usb_target_t target,
-    size_t packet_size, dev_speed_t speed, char *buffer, size_t size,
+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);
@@ -82,12 +84,4 @@
 
 void tracker_interrupt_out(tracker_t *instance);
-
-void tracker_call_in(tracker_t *instance);
-
-void tracker_call_out(tracker_t *instance);
-
-void tracker_call_in_and_dispose(tracker_t *instance);
-
-void tracker_call_out_and_dispose(tracker_t *instance);
 
 /* DEPRECATED FUNCTIONS NEEDED BY THE OLD API */
Index: uspace/drv/uhci-hcd/transfer_list.c
===================================================================
--- uspace/drv/uhci-hcd/transfer_list.c	(revision da17cf0f62be93cfcd6ddcf6028b03a49898563d)
+++ uspace/drv/uhci-hcd/transfer_list.c	(revision 9a818a93338eb8410dcc0917f9c3d49086134801)
@@ -96,4 +96,28 @@
 	return EOK;
 }
+/*----------------------------------------------------------------------------*/
+void transfer_list_add_tracker(transfer_list_t *instance, tracker_t *tracker)
+{
+	assert(instance);
+	assert(tracker);
+
+	uint32_t pa = (uintptr_t)addr_to_phys(tracker->td);
+	assert((pa & LINK_POINTER_ADDRESS_MASK) == pa);
+
+	if (instance->queue_head->element & LINK_POINTER_TERMINATE_FLAG) {
+		/* there is nothing scheduled */
+		instance->last_tracker = tracker;
+		instance->queue_head->element = pa;
+		return;
+	}
+	/* now we can be sure that last_tracker is a valid pointer */
+	instance->last_tracker->td->next = pa;
+	instance->last_tracker = tracker;
+
+	/* check again, may be use atomic compare and swap */
+	if (instance->queue_head->element & LINK_POINTER_TERMINATE_FLAG) {
+		instance->queue_head->element = pa;
+	}
+}
 /**
  * @}
Index: uspace/drv/uhci-hcd/transfer_list.h
===================================================================
--- uspace/drv/uhci-hcd/transfer_list.h	(revision da17cf0f62be93cfcd6ddcf6028b03a49898563d)
+++ uspace/drv/uhci-hcd/transfer_list.h	(revision 9a818a93338eb8410dcc0917f9c3d49086134801)
@@ -37,4 +37,5 @@
 #include "uhci_struct/queue_head.h"
 #include "uhci_struct/transfer_descriptor.h"
+#include "tracker.h"
 
 typedef struct transfer_list
@@ -42,4 +43,7 @@
 	transfer_descriptor_t *first;
 	transfer_descriptor_t *last;
+
+	tracker_t *last_tracker;
+
 	queue_head_t *queue_head;
 	uint32_t queue_head_pa;
@@ -61,4 +65,6 @@
   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 da17cf0f62be93cfcd6ddcf6028b03a49898563d)
+++ uspace/drv/uhci-hcd/uhci.c	(revision 9a818a93338eb8410dcc0917f9c3d49086134801)
@@ -86,6 +86,7 @@
 
 	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);
 
 	instance->cleaner = fibril_create(uhci_clean_finished, instance);
@@ -209,5 +210,28 @@
 	return EOK;
 }
-/*---------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
+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;
+	}
+	/* TODO: check available bandwith here */
+
+	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);
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
 int uhci_clean_finished(void* arg)
 {
@@ -217,5 +241,18 @@
 
 	while(1) {
-		usb_log_debug("Running cleaning fibril on: %p.\n", instance);
+		/* tracker iteration */
+		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);
+			if (!transfer_descriptor_is_active(tracker->td)) {
+				usb_log_debug("Found inactive tracker.\n");
+				list_remove(current);
+				tracker->next_step(tracker);
+			}
+			current = next;
+		}
 		/* iterate all transfer queues */
 		transfer_list_t *current_list = &instance->transfers_interrupt;
Index: uspace/drv/uhci-hcd/uhci.h
===================================================================
--- uspace/drv/uhci-hcd/uhci.h	(revision da17cf0f62be93cfcd6ddcf6028b03a49898563d)
+++ uspace/drv/uhci-hcd/uhci.h	(revision 9a818a93338eb8410dcc0917f9c3d49086134801)
@@ -37,4 +37,5 @@
 
 #include <fibril.h>
+#include <adt/list.h>
 
 #include <usb/addrkeep.h>
@@ -42,4 +43,5 @@
 
 #include "transfer_list.h"
+#include "tracker.h"
 
 typedef struct uhci_regs {
@@ -79,4 +81,6 @@
 	link_pointer_t *frame_list;
 
+	link_t tracker_list;
+
 	transfer_list_t transfers_bulk_full;
 	transfer_list_t transfers_control_full;
@@ -108,4 +112,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/transfer_descriptor.h
===================================================================
--- uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h	(revision da17cf0f62be93cfcd6ddcf6028b03a49898563d)
+++ uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h	(revision 9a818a93338eb8410dcc0917f9c3d49086134801)
@@ -124,4 +124,11 @@
 int transfer_descriptor_status(transfer_descriptor_t *instance);
 
+static inline bool transfer_descriptor_is_active(
+    transfer_descriptor_t *instance)
+{
+	assert(instance);
+	return instance->status & TD_STATUS_ERROR_ACTIVE;
+}
+
 static inline void transfer_descriptor_append(
   transfer_descriptor_t *instance, transfer_descriptor_t *item)
